@ipul-labs/forge 1.18.0 → 1.19.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/README.md +23 -0
- package/lib/bin/cli/improve.d.ts +2 -0
- package/lib/bin/cli/improve.d.ts.map +1 -0
- package/lib/bin/cli/improve.js +153 -0
- package/lib/bin/cli/improve.js.map +1 -0
- package/lib/bin/forge-agent.js +4 -0
- package/lib/bin/forge-agent.js.map +1 -1
- package/lib/server/forge/core/configStore.d.ts +1 -0
- package/lib/server/forge/core/configStore.d.ts.map +1 -1
- package/lib/server/forge/core/selfImprove.d.ts +42 -0
- package/lib/server/forge/core/selfImprove.d.ts.map +1 -0
- package/lib/server/forge/core/selfImprove.js +360 -0
- package/lib/server/forge/core/selfImprove.js.map +1 -0
- package/lib/server/forge/core/telemetry.d.ts.map +1 -1
- package/lib/server/forge/core/telemetry.js +18 -0
- package/lib/server/forge/core/telemetry.js.map +1 -1
- package/lib/server/forge/core/types.d.ts +1 -0
- package/lib/server/forge/core/types.d.ts.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -132,6 +132,8 @@ forge close # Close the issue
|
|
|
132
132
|
forge use group/other-repo # Switch active repo
|
|
133
133
|
forge update # Pull latest + reinstall dependencies
|
|
134
134
|
forge stats # View telemetry — success rates, timing, failure patterns
|
|
135
|
+
forge improve # Evaluate patterns and suggest improvements
|
|
136
|
+
forge improve --create # Create improvement issues in the repo
|
|
135
137
|
```
|
|
136
138
|
|
|
137
139
|
#### Options
|
|
@@ -253,6 +255,27 @@ FORGE_REPOS=gitlab:ipul/web-app,github:my-org/mobile
|
|
|
253
255
|
|
|
254
256
|
---
|
|
255
257
|
|
|
258
|
+
## Self-improvement
|
|
259
|
+
|
|
260
|
+
Forge monitors its own performance and proposes fixes autonomously. The loop:
|
|
261
|
+
|
|
262
|
+
1. **Telemetry** — every operation records success/fail, duration, tokens, and cost to `~/.forge/telemetry/`
|
|
263
|
+
2. **Pattern detection** — recurring failures are grouped and classified (timeout-tuning, provider-bug, prompt-quality, validation-gap, error-handling, ux-improvement)
|
|
264
|
+
3. **Auto-evaluation** — runs automatically after every 25 operations (4-hour cooldown). High-severity patterns trigger issue creation.
|
|
265
|
+
4. **Issue creation** — files issues in the configured repo with diagnosis, evidence, and suggested fixes. Tagged `[self-improve]` with category labels.
|
|
266
|
+
5. **Human review** — Forge never auto-merges its own changes. All improvements go through normal MR review.
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
forge stats # View telemetry data
|
|
270
|
+
forge improve # Run evaluation manually
|
|
271
|
+
forge improve --create # Create issues for actionable patterns
|
|
272
|
+
forge improve --json # Pipe-friendly output
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
UX insights are also derived from telemetry: slow operations (>2 min avg), high token usage (>50k avg), and frequent cancellations surface as improvement suggestions.
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
256
279
|
## Security
|
|
257
280
|
|
|
258
281
|
Forge is designed for self-hosted deployment on trusted infrastructure. Security measures in place:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"improve.d.ts","sourceRoot":"","sources":["../../../bin/cli/improve.ts"],"names":[],"mappings":"AA8IA,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmC9D"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
return path;
|
|
8
|
+
};
|
|
9
|
+
import path from "node:path";
|
|
10
|
+
import { useEffect, useState } from "react";
|
|
11
|
+
import Spinner from "ink-spinner";
|
|
12
|
+
import { h, Box, Text, useApp, runApp } from "./ink.js";
|
|
13
|
+
import { projectRoot, getFlag } from "./utils.js";
|
|
14
|
+
async function resolveSelfRepo(argv) {
|
|
15
|
+
const explicit = getFlag(argv, "--repo");
|
|
16
|
+
if (explicit)
|
|
17
|
+
return explicit;
|
|
18
|
+
if (process.env.FORGE_SELF_REPO)
|
|
19
|
+
return process.env.FORGE_SELF_REPO;
|
|
20
|
+
try {
|
|
21
|
+
const { get } = await import(__rewriteRelativeImportExtension(path.join(projectRoot, "server/forge/core/configStore.ts")));
|
|
22
|
+
const repos = get()?.repos ?? [];
|
|
23
|
+
const forgeRepo = repos.find((r) => r.id.toLowerCase().includes("forge"));
|
|
24
|
+
if (forgeRepo)
|
|
25
|
+
return forgeRepo.id;
|
|
26
|
+
}
|
|
27
|
+
catch { }
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
function ImproveView({ createIssues, repo, onDone }) {
|
|
31
|
+
const { exit } = useApp();
|
|
32
|
+
const [phase, setPhase] = useState("evaluating");
|
|
33
|
+
const [result, setResult] = useState(null);
|
|
34
|
+
const [created, setCreated] = useState(0);
|
|
35
|
+
const [error, setError] = useState(null);
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
if (phase === "done" || phase === "error") {
|
|
38
|
+
onDone(result, created);
|
|
39
|
+
exit();
|
|
40
|
+
}
|
|
41
|
+
}, [phase]);
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
(async () => {
|
|
44
|
+
try {
|
|
45
|
+
const { evaluate, formatIssueBody } = await import(__rewriteRelativeImportExtension(path.join(projectRoot, "server/forge/core/selfImprove.ts")));
|
|
46
|
+
const evalResult = await evaluate();
|
|
47
|
+
setResult(evalResult);
|
|
48
|
+
if (!createIssues || evalResult.diagnoses.length === 0 || !repo) {
|
|
49
|
+
setPhase("done");
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
setPhase("creating");
|
|
53
|
+
const { createProvider } = await import(__rewriteRelativeImportExtension(path.join(projectRoot, "server/forge/core/providers/index.ts")));
|
|
54
|
+
const provider = createProvider(repo);
|
|
55
|
+
let count = 0;
|
|
56
|
+
for (const diagnosis of evalResult.diagnoses.slice(0, 3)) {
|
|
57
|
+
const body = formatIssueBody(diagnosis);
|
|
58
|
+
const labels = `forge-self-improve,${diagnosis.category},${diagnosis.severity}`;
|
|
59
|
+
const title = `[self-improve] ${diagnosis.title}`;
|
|
60
|
+
await provider.createIssue(title, `${body}\n\nLabels: ${labels}`);
|
|
61
|
+
count++;
|
|
62
|
+
}
|
|
63
|
+
setCreated(count);
|
|
64
|
+
setPhase("done");
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
setError(err.message);
|
|
68
|
+
setPhase("error");
|
|
69
|
+
}
|
|
70
|
+
})();
|
|
71
|
+
}, []);
|
|
72
|
+
if (phase === "evaluating") {
|
|
73
|
+
return h `<${Box}>
|
|
74
|
+
<${Text} color="cyan"><${Spinner} type="dots"/></>
|
|
75
|
+
<${Text}> Evaluating telemetry patterns...</>
|
|
76
|
+
</>`;
|
|
77
|
+
}
|
|
78
|
+
if (phase === "creating") {
|
|
79
|
+
return h `<${Box}>
|
|
80
|
+
<${Text} color="cyan"><${Spinner} type="dots"/></>
|
|
81
|
+
<${Text}> Creating improvement issues...</>
|
|
82
|
+
</>`;
|
|
83
|
+
}
|
|
84
|
+
if (phase === "error") {
|
|
85
|
+
return h `<${Text} color="red">Error: ${error}</>`;
|
|
86
|
+
}
|
|
87
|
+
if (!result)
|
|
88
|
+
return null;
|
|
89
|
+
const { diagnoses, summary } = result;
|
|
90
|
+
return h `<${Box} flexDirection="column" paddingLeft=${1}>
|
|
91
|
+
<${Text} bold>Self-improvement evaluation</>
|
|
92
|
+
<${Text} dimColor>${summary.totalEvents} telemetry events, ${result.patterns.length} failure patterns</>
|
|
93
|
+
|
|
94
|
+
${diagnoses.length === 0
|
|
95
|
+
? h `<${Box} marginTop=${1}><${Text} color="green">No actionable patterns found. Forge is operating normally.</></>`
|
|
96
|
+
: h `<${Box} flexDirection="column" marginTop=${1}>
|
|
97
|
+
<${Text} bold>${diagnoses.length} improvement${diagnoses.length === 1 ? "" : "s"} identified:</>
|
|
98
|
+
${diagnoses.map((d, i) => h `<${Box} key=${i} marginLeft=${1} marginTop=${1} flexDirection="column">
|
|
99
|
+
<${Box}>
|
|
100
|
+
<${Text} color=${d.severity === "high" ? "red" : d.severity === "medium" ? "yellow" : "white"}>
|
|
101
|
+
${d.severity === "high" ? "▲" : d.severity === "medium" ? "●" : "○"}
|
|
102
|
+
</>
|
|
103
|
+
<${Text} bold>${d.title}</>
|
|
104
|
+
</>
|
|
105
|
+
<${Text} dimColor> ${d.category} — ${d.evidence.length} evidence items</>
|
|
106
|
+
</>`)}
|
|
107
|
+
</>`}
|
|
108
|
+
|
|
109
|
+
${created > 0
|
|
110
|
+
? h `<${Box} marginTop=${1}>
|
|
111
|
+
<${Text} color="green">✓ Created ${created} issue${created === 1 ? "" : "s"} in ${repo}</>
|
|
112
|
+
</>`
|
|
113
|
+
: null}
|
|
114
|
+
</>`;
|
|
115
|
+
}
|
|
116
|
+
async function isAuthorized() {
|
|
117
|
+
try {
|
|
118
|
+
const { get } = await import(__rewriteRelativeImportExtension(path.join(projectRoot, "server/forge/core/configStore.ts")));
|
|
119
|
+
const config = get();
|
|
120
|
+
return config?.defaults?.selfImproveEnabled === true;
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
export async function cmdImprove(argv) {
|
|
127
|
+
if (!(await isAuthorized()) && !argv.includes("--force")) {
|
|
128
|
+
console.error("forge improve is disabled. Enable in Settings → Defaults → Self-improve.");
|
|
129
|
+
process.exit(1);
|
|
130
|
+
}
|
|
131
|
+
const createIssues = argv.includes("--create");
|
|
132
|
+
const json = argv.includes("--json");
|
|
133
|
+
const repo = await resolveSelfRepo(argv);
|
|
134
|
+
if (json) {
|
|
135
|
+
const { evaluate } = await import(__rewriteRelativeImportExtension(path.join(projectRoot, "server/forge/core/selfImprove.ts")));
|
|
136
|
+
const result = await evaluate();
|
|
137
|
+
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
let evalResult = null;
|
|
141
|
+
let issuesCreated = 0;
|
|
142
|
+
await runApp(h `<${ImproveView}
|
|
143
|
+
createIssues=${createIssues}
|
|
144
|
+
repo=${repo}
|
|
145
|
+
onDone=${(r, c) => { evalResult = r; issuesCreated = c; }} />`);
|
|
146
|
+
if (createIssues && issuesCreated === 0 && evalResult?.diagnoses.length) {
|
|
147
|
+
if (!repo) {
|
|
148
|
+
console.error("No repo configured. Pass --repo or run `forge init` first.");
|
|
149
|
+
process.exit(1);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=improve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"improve.js","sourceRoot":"","sources":["../../../bin/cli/improve.ts"],"names":[],"mappings":"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"}
|
package/lib/bin/forge-agent.js
CHANGED
|
@@ -30,6 +30,7 @@ import { cmdCreateIssue } from "./cli/createIssue.js";
|
|
|
30
30
|
import { startRepl } from "./cli/repl.js";
|
|
31
31
|
import { cmdUpdate } from "./cli/update.js";
|
|
32
32
|
import { cmdStats } from "./cli/stats.js";
|
|
33
|
+
import { cmdImprove } from "./cli/improve.js";
|
|
33
34
|
async function cmdUse(argv) {
|
|
34
35
|
const repoId = argv[1];
|
|
35
36
|
if (!repoId) {
|
|
@@ -72,6 +73,7 @@ Commands
|
|
|
72
73
|
doctor Check prerequisites (node, git, claude CLI, token, config)
|
|
73
74
|
update Pull latest changes + reinstall dependencies
|
|
74
75
|
stats Show telemetry — success rates, timing, failure patterns
|
|
76
|
+
improve Evaluate telemetry and suggest improvements (--create to file issues)
|
|
75
77
|
version Print version
|
|
76
78
|
help Show this help
|
|
77
79
|
|
|
@@ -186,6 +188,8 @@ async function dispatch(argv) {
|
|
|
186
188
|
return cmdUpdate();
|
|
187
189
|
case "stats":
|
|
188
190
|
return cmdStats(argv);
|
|
191
|
+
case "improve":
|
|
192
|
+
return cmdImprove(argv);
|
|
189
193
|
case "version":
|
|
190
194
|
case "--version":
|
|
191
195
|
case "-v":
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forge-agent.js","sourceRoot":"","sources":["../../bin/forge-agent.ts"],"names":[],"mappings":";;;;;;;;;AACA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"forge-agent.js","sourceRoot":"","sources":["../../bin/forge-agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configStore.d.ts","sourceRoot":"","sources":["../../../../server/forge/core/configStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,KAAK,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,aAAa,CAAC;AAqHvD,sDAAsD;AACtD,wBAAgB,GAAG,gBAElB;AAED;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAOnE;AAED,0DAA0D;AAC1D,wBAAgB,MAAM,gBAGrB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,WAKhC;AAQD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,WAAW;;;EAQlD;AAQD;;;GAGG;AACH,wBAAgB,SAAS
|
|
1
|
+
{"version":3,"file":"configStore.d.ts","sourceRoot":"","sources":["../../../../server/forge/core/configStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,KAAK,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,aAAa,CAAC;AAqHvD,sDAAsD;AACtD,wBAAgB,GAAG,gBAElB;AAED;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAOnE;AAED,0DAA0D;AAC1D,wBAAgB,MAAM,gBAGrB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,WAKhC;AAQD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,WAAW;;;EAQlD;AAQD;;;GAGG;AACH,wBAAgB,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyBxB"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* server/forge/core/selfImprove.ts
|
|
3
|
+
*
|
|
4
|
+
* Self-improvement engine. Reads telemetry patterns, generates actionable
|
|
5
|
+
* issues against Forge's own repo, and optionally ships them.
|
|
6
|
+
*
|
|
7
|
+
* The engine never auto-merges — it creates issues and MRs that a human
|
|
8
|
+
* reviews. Rejected MRs feed back into telemetry as learning signals.
|
|
9
|
+
*
|
|
10
|
+
* Flow:
|
|
11
|
+
* 1. evaluate() reads failure patterns from telemetry
|
|
12
|
+
* 2. Each pattern is classified into an improvement category
|
|
13
|
+
* 3. For actionable patterns, an issue is drafted with diagnosis + evidence
|
|
14
|
+
* 4. createSelfIssue() opens the issue on the configured self-repo
|
|
15
|
+
* 5. Optionally, shipSelfIssue() runs `forge ship <iid>` against it
|
|
16
|
+
*/
|
|
17
|
+
import type { FailurePattern, TelemetrySummary } from "./telemetry.ts";
|
|
18
|
+
export type ImprovementCategory = "timeout-tuning" | "prompt-quality" | "provider-bug" | "validation-gap" | "error-handling" | "performance" | "ux-improvement";
|
|
19
|
+
export interface Diagnosis {
|
|
20
|
+
category: ImprovementCategory;
|
|
21
|
+
title: string;
|
|
22
|
+
description: string;
|
|
23
|
+
evidence: string[];
|
|
24
|
+
severity: "low" | "medium" | "high";
|
|
25
|
+
pattern: FailurePattern;
|
|
26
|
+
}
|
|
27
|
+
export interface EvaluationResult {
|
|
28
|
+
summary: TelemetrySummary;
|
|
29
|
+
patterns: FailurePattern[];
|
|
30
|
+
diagnoses: Diagnosis[];
|
|
31
|
+
timestamp: string;
|
|
32
|
+
}
|
|
33
|
+
export declare function evaluate(): Promise<EvaluationResult>;
|
|
34
|
+
export declare function formatIssueBody(diagnosis: Diagnosis): string;
|
|
35
|
+
export interface AutoEvalResult {
|
|
36
|
+
skipped: boolean;
|
|
37
|
+
reason?: string;
|
|
38
|
+
diagnoses?: Diagnosis[];
|
|
39
|
+
issuesCreated?: number;
|
|
40
|
+
}
|
|
41
|
+
export declare function maybeAutoEvaluate(): Promise<AutoEvalResult>;
|
|
42
|
+
//# sourceMappingURL=selfImprove.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selfImprove.d.ts","sourceRoot":"","sources":["../../../../server/forge/core/selfImprove.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAOH,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAkB,MAAM,gBAAgB,CAAC;AAIvF,MAAM,MAAM,mBAAmB,GAC5B,gBAAgB,GAChB,gBAAgB,GAChB,cAAc,GACd,gBAAgB,GAChB,gBAAgB,GAChB,aAAa,GACb,gBAAgB,CAAC;AAEpB,MAAM,WAAW,SAAS;IACzB,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACpC,OAAO,EAAE,cAAc,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,gBAAgB,CAAC;IAC1B,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,SAAS,EAAE,SAAS,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CAClB;AAuMD,wBAAsB,QAAQ,IAAI,OAAO,CAAC,gBAAgB,CAAC,CA2C1D;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,CAe5D;AA0CD,MAAM,WAAW,cAAc;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,SAAS,EAAE,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAcD,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,cAAc,CAAC,CA0DjE"}
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* server/forge/core/selfImprove.ts
|
|
3
|
+
*
|
|
4
|
+
* Self-improvement engine. Reads telemetry patterns, generates actionable
|
|
5
|
+
* issues against Forge's own repo, and optionally ships them.
|
|
6
|
+
*
|
|
7
|
+
* The engine never auto-merges — it creates issues and MRs that a human
|
|
8
|
+
* reviews. Rejected MRs feed back into telemetry as learning signals.
|
|
9
|
+
*
|
|
10
|
+
* Flow:
|
|
11
|
+
* 1. evaluate() reads failure patterns from telemetry
|
|
12
|
+
* 2. Each pattern is classified into an improvement category
|
|
13
|
+
* 3. For actionable patterns, an issue is drafted with diagnosis + evidence
|
|
14
|
+
* 4. createSelfIssue() opens the issue on the configured self-repo
|
|
15
|
+
* 5. Optionally, shipSelfIssue() runs `forge ship <iid>` against it
|
|
16
|
+
*/
|
|
17
|
+
import { existsSync } from "node:fs";
|
|
18
|
+
import fs from "node:fs/promises";
|
|
19
|
+
import os from "node:os";
|
|
20
|
+
import path from "node:path";
|
|
21
|
+
import { getFailurePatterns, getSummary, getRecentEvents } from "./telemetry.js";
|
|
22
|
+
const classifiers = [
|
|
23
|
+
{
|
|
24
|
+
match: (p) => /timed?\s*out/i.test(p.errorPattern),
|
|
25
|
+
classify: (p, summary) => ({
|
|
26
|
+
category: "timeout-tuning",
|
|
27
|
+
title: `fix: ${p.operation} timing out (${p.count} occurrences)`,
|
|
28
|
+
description: [
|
|
29
|
+
`The \`${p.operation}\` operation is timing out repeatedly.`,
|
|
30
|
+
``,
|
|
31
|
+
`**Pattern:** ${p.errorPattern}`,
|
|
32
|
+
`**Occurrences:** ${p.count} times across ${p.repos.length} repo(s)`,
|
|
33
|
+
`**First seen:** ${p.firstSeen}`,
|
|
34
|
+
`**Last seen:** ${p.lastSeen}`,
|
|
35
|
+
``,
|
|
36
|
+
`Consider increasing the timeout, optimizing the prompt to reduce token usage,`,
|
|
37
|
+
`or breaking the operation into smaller steps.`,
|
|
38
|
+
].join("\n"),
|
|
39
|
+
evidence: p.examples.map((e) => `${e.ts} — ${e.repo}#${e.iid}: ${e.error}`),
|
|
40
|
+
severity: p.count >= 5 ? "high" : "medium",
|
|
41
|
+
pattern: p,
|
|
42
|
+
}),
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
match: (p) => /git\s*(fetch|clone|push)\s*failed/i.test(p.errorPattern),
|
|
46
|
+
classify: (p) => ({
|
|
47
|
+
category: "provider-bug",
|
|
48
|
+
title: `fix: git operation failing in ${p.operation} (${p.count}x)`,
|
|
49
|
+
description: [
|
|
50
|
+
`Git operations are failing during \`${p.operation}\`.`,
|
|
51
|
+
``,
|
|
52
|
+
`**Pattern:** ${p.errorPattern}`,
|
|
53
|
+
`**Occurrences:** ${p.count}`,
|
|
54
|
+
``,
|
|
55
|
+
`This may indicate an authentication issue, network problem,`,
|
|
56
|
+
`or a bug in the clone/fetch credential handling.`,
|
|
57
|
+
].join("\n"),
|
|
58
|
+
evidence: p.examples.map((e) => `${e.ts} — ${e.repo}#${e.iid}: ${e.error}`),
|
|
59
|
+
severity: "high",
|
|
60
|
+
pattern: p,
|
|
61
|
+
}),
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
match: (p) => /no json found|parse|unexpected token/i.test(p.errorPattern),
|
|
65
|
+
classify: (p) => ({
|
|
66
|
+
category: "prompt-quality",
|
|
67
|
+
title: `fix: ${p.operation} returning unparseable output (${p.count}x)`,
|
|
68
|
+
description: [
|
|
69
|
+
`Claude is returning output that can't be parsed as JSON during \`${p.operation}\`.`,
|
|
70
|
+
``,
|
|
71
|
+
`**Pattern:** ${p.errorPattern}`,
|
|
72
|
+
`**Occurrences:** ${p.count}`,
|
|
73
|
+
``,
|
|
74
|
+
`The system prompt may need stronger formatting instructions,`,
|
|
75
|
+
`or extractJSON needs more lenient parsing.`,
|
|
76
|
+
].join("\n"),
|
|
77
|
+
evidence: p.examples.map((e) => `${e.ts} — ${e.repo}#${e.iid}: ${e.error}`),
|
|
78
|
+
severity: "medium",
|
|
79
|
+
pattern: p,
|
|
80
|
+
}),
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
match: (p) => /validation|lint|typecheck|test.*fail/i.test(p.errorPattern),
|
|
84
|
+
classify: (p) => ({
|
|
85
|
+
category: "validation-gap",
|
|
86
|
+
title: `fix: proposed changes failing validation in ${p.operation} (${p.count}x)`,
|
|
87
|
+
description: [
|
|
88
|
+
`Proposed changes are failing pre-flight validation during \`${p.operation}\`.`,
|
|
89
|
+
``,
|
|
90
|
+
`**Pattern:** ${p.errorPattern}`,
|
|
91
|
+
`**Occurrences:** ${p.count}`,
|
|
92
|
+
``,
|
|
93
|
+
`The analysis prompts may need stronger instructions about type safety,`,
|
|
94
|
+
`import correctness, or test coverage.`,
|
|
95
|
+
].join("\n"),
|
|
96
|
+
evidence: p.examples.map((e) => `${e.ts} — ${e.repo}#${e.iid}: ${e.error}`),
|
|
97
|
+
severity: "medium",
|
|
98
|
+
pattern: p,
|
|
99
|
+
}),
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
match: (p, summary) => {
|
|
103
|
+
const stats = summary.byOperation[p.operation];
|
|
104
|
+
if (!stats || stats.total < 5)
|
|
105
|
+
return false;
|
|
106
|
+
return stats.failures / stats.total > 0.3;
|
|
107
|
+
},
|
|
108
|
+
classify: (p, summary) => {
|
|
109
|
+
const stats = summary.byOperation[p.operation];
|
|
110
|
+
const failRate = stats ? Math.round((stats.failures / stats.total) * 100) : 0;
|
|
111
|
+
return {
|
|
112
|
+
category: "error-handling",
|
|
113
|
+
title: `fix: ${p.operation} has ${failRate}% failure rate`,
|
|
114
|
+
description: [
|
|
115
|
+
`The \`${p.operation}\` operation has an elevated failure rate.`,
|
|
116
|
+
``,
|
|
117
|
+
`**Success rate:** ${100 - failRate}% (${stats?.successes}/${stats?.total})`,
|
|
118
|
+
`**Most common error:** ${p.errorPattern}`,
|
|
119
|
+
`**Occurrences:** ${p.count}`,
|
|
120
|
+
``,
|
|
121
|
+
`Review error handling and recovery for this operation.`,
|
|
122
|
+
].join("\n"),
|
|
123
|
+
evidence: p.examples.map((e) => `${e.ts} — ${e.repo}#${e.iid}: ${e.error}`),
|
|
124
|
+
severity: failRate > 50 ? "high" : "medium",
|
|
125
|
+
pattern: p,
|
|
126
|
+
};
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
];
|
|
130
|
+
function deriveUxDiagnoses(summary, events) {
|
|
131
|
+
const diagnoses = [];
|
|
132
|
+
// Slow operations suggest UX improvements
|
|
133
|
+
for (const [op, stats] of Object.entries(summary.byOperation)) {
|
|
134
|
+
if (stats.total < 3)
|
|
135
|
+
continue;
|
|
136
|
+
if (stats.avgDurationMs > 120_000) {
|
|
137
|
+
diagnoses.push({
|
|
138
|
+
category: "ux-improvement",
|
|
139
|
+
title: `ux: ${op} takes ${(stats.avgDurationMs / 1000).toFixed(0)}s avg — add progress feedback`,
|
|
140
|
+
description: [
|
|
141
|
+
`The \`${op}\` operation averages ${(stats.avgDurationMs / 1000).toFixed(0)} seconds.`,
|
|
142
|
+
`Users may think it's frozen.`,
|
|
143
|
+
``,
|
|
144
|
+
`**Avg duration:** ${(stats.avgDurationMs / 1000).toFixed(1)}s over ${stats.total} runs`,
|
|
145
|
+
``,
|
|
146
|
+
`Suggestions:`,
|
|
147
|
+
`- Add more granular progress steps so the UI/CLI shows activity`,
|
|
148
|
+
`- Show estimated time remaining based on historical avg`,
|
|
149
|
+
`- Consider streaming partial results earlier`,
|
|
150
|
+
].join("\n"),
|
|
151
|
+
evidence: [`avg ${(stats.avgDurationMs / 1000).toFixed(1)}s across ${stats.total} operations`],
|
|
152
|
+
severity: stats.avgDurationMs > 300_000 ? "high" : "medium",
|
|
153
|
+
pattern: { operation: op, errorPattern: "slow", count: stats.total, repos: new Set(), firstSeen: "", lastSeen: "", examples: [] },
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// High token usage suggests prompt optimization
|
|
158
|
+
for (const [op, stats] of Object.entries(summary.byOperation)) {
|
|
159
|
+
if (stats.total < 3 || stats.totalTokensIn === 0)
|
|
160
|
+
continue;
|
|
161
|
+
const avgTokensPerOp = (stats.totalTokensIn + stats.totalTokensOut) / stats.total;
|
|
162
|
+
if (avgTokensPerOp > 50_000) {
|
|
163
|
+
diagnoses.push({
|
|
164
|
+
category: "ux-improvement",
|
|
165
|
+
title: `ux: ${op} uses ${Math.round(avgTokensPerOp / 1000)}k tokens avg — optimize prompts`,
|
|
166
|
+
description: [
|
|
167
|
+
`The \`${op}\` operation averages ${Math.round(avgTokensPerOp)} tokens per call.`,
|
|
168
|
+
`This affects response time and cost.`,
|
|
169
|
+
``,
|
|
170
|
+
`**Avg tokens:** ${Math.round(avgTokensPerOp)} (in+out) over ${stats.total} runs`,
|
|
171
|
+
`**Total cost:** $${stats.totalCost.toFixed(4)}`,
|
|
172
|
+
``,
|
|
173
|
+
`Suggestions:`,
|
|
174
|
+
`- Reduce file content sent to Claude (tighter truncation)`,
|
|
175
|
+
`- Cache file-tree results across refine turns`,
|
|
176
|
+
`- Consider using a smaller model for the identify-files pass`,
|
|
177
|
+
].join("\n"),
|
|
178
|
+
evidence: [`${Math.round(avgTokensPerOp)} avg tokens, $${stats.totalCost.toFixed(4)} total cost`],
|
|
179
|
+
severity: "medium",
|
|
180
|
+
pattern: { operation: op, errorPattern: "high-tokens", count: stats.total, repos: new Set(), firstSeen: "", lastSeen: "", examples: [] },
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
// Frequent cancel/abort suggests UX friction
|
|
185
|
+
const cancels = events.filter((e) => e.error?.includes("cancelled") || e.error?.includes("abort"));
|
|
186
|
+
if (cancels.length >= 3) {
|
|
187
|
+
diagnoses.push({
|
|
188
|
+
category: "ux-improvement",
|
|
189
|
+
title: `ux: ${cancels.length} operations cancelled — investigate user frustration`,
|
|
190
|
+
description: [
|
|
191
|
+
`${cancels.length} operations were cancelled by the user.`,
|
|
192
|
+
`Frequent cancellations suggest the operation is taking too long`,
|
|
193
|
+
`or producing unexpected results.`,
|
|
194
|
+
``,
|
|
195
|
+
`Suggestions:`,
|
|
196
|
+
`- Show clearer progress indicators`,
|
|
197
|
+
`- Allow partial results before full completion`,
|
|
198
|
+
`- Add a "quick mode" that uses fewer passes`,
|
|
199
|
+
].join("\n"),
|
|
200
|
+
evidence: cancels.slice(0, 3).map((e) => `${e.ts} — ${e.operation} on ${e.repo}#${e.iid}`),
|
|
201
|
+
severity: cancels.length >= 5 ? "high" : "medium",
|
|
202
|
+
pattern: { operation: "mixed", errorPattern: "cancelled", count: cancels.length, repos: new Set(), firstSeen: cancels[0]?.ts ?? "", lastSeen: cancels[cancels.length - 1]?.ts ?? "", examples: [] },
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
return diagnoses;
|
|
206
|
+
}
|
|
207
|
+
// ─── Public API ──────────────────────────────────────────────────────────────
|
|
208
|
+
export async function evaluate() {
|
|
209
|
+
const [summary, patterns, events] = await Promise.all([
|
|
210
|
+
getSummary(),
|
|
211
|
+
getFailurePatterns(),
|
|
212
|
+
getRecentEvents(500),
|
|
213
|
+
]);
|
|
214
|
+
const diagnoses = [];
|
|
215
|
+
const seen = new Set();
|
|
216
|
+
for (const pattern of patterns) {
|
|
217
|
+
for (const classifier of classifiers) {
|
|
218
|
+
if (!classifier.match(pattern, summary))
|
|
219
|
+
continue;
|
|
220
|
+
const diagnosis = classifier.classify(pattern, summary, events);
|
|
221
|
+
const key = `${diagnosis.category}:${diagnosis.title}`;
|
|
222
|
+
if (seen.has(key))
|
|
223
|
+
continue;
|
|
224
|
+
seen.add(key);
|
|
225
|
+
diagnoses.push(diagnosis);
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
// Add UX-derived diagnoses (not based on failure patterns)
|
|
230
|
+
const uxDiagnoses = deriveUxDiagnoses(summary, events);
|
|
231
|
+
for (const d of uxDiagnoses) {
|
|
232
|
+
const key = `${d.category}:${d.title}`;
|
|
233
|
+
if (!seen.has(key)) {
|
|
234
|
+
seen.add(key);
|
|
235
|
+
diagnoses.push(d);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
diagnoses.sort((a, b) => {
|
|
239
|
+
const sev = { high: 3, medium: 2, low: 1 };
|
|
240
|
+
return sev[b.severity] - sev[a.severity];
|
|
241
|
+
});
|
|
242
|
+
return {
|
|
243
|
+
summary,
|
|
244
|
+
patterns,
|
|
245
|
+
diagnoses,
|
|
246
|
+
timestamp: new Date().toISOString(),
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
export function formatIssueBody(diagnosis) {
|
|
250
|
+
return [
|
|
251
|
+
diagnosis.description,
|
|
252
|
+
"",
|
|
253
|
+
"## Evidence",
|
|
254
|
+
"",
|
|
255
|
+
...diagnosis.evidence.map((e) => `- \`${e}\``),
|
|
256
|
+
"",
|
|
257
|
+
"## Category",
|
|
258
|
+
"",
|
|
259
|
+
`\`${diagnosis.category}\` — severity: **${diagnosis.severity}**`,
|
|
260
|
+
"",
|
|
261
|
+
"---",
|
|
262
|
+
"*This issue was created automatically by Forge's self-improvement engine.*",
|
|
263
|
+
].join("\n");
|
|
264
|
+
}
|
|
265
|
+
// ─── Auto-evaluation ─────────────────────────────────────────────────────────
|
|
266
|
+
// Runs automatically after every EVAL_THRESHOLD telemetry events. When
|
|
267
|
+
// high-severity diagnoses are found and a self-repo is configured, creates
|
|
268
|
+
// issues automatically. Results are logged to ~/.forge/telemetry/evaluations/.
|
|
269
|
+
const EVAL_THRESHOLD = 25;
|
|
270
|
+
const EVAL_COOLDOWN_MS = 4 * 60 * 60 * 1000; // 4 hours between auto-evals
|
|
271
|
+
function evalDir() {
|
|
272
|
+
return path.join(process.env.FORGE_TELEMETRY_PATH ?? path.join(os.homedir(), ".forge", "telemetry"), "evaluations");
|
|
273
|
+
}
|
|
274
|
+
function lastEvalFile() {
|
|
275
|
+
return path.join(evalDir(), "last-eval.json");
|
|
276
|
+
}
|
|
277
|
+
async function readLastEval() {
|
|
278
|
+
try {
|
|
279
|
+
if (!existsSync(lastEvalFile()))
|
|
280
|
+
return null;
|
|
281
|
+
return JSON.parse(await fs.readFile(lastEvalFile(), "utf8"));
|
|
282
|
+
}
|
|
283
|
+
catch {
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
async function writeLastEval(state) {
|
|
288
|
+
await fs.mkdir(evalDir(), { recursive: true, mode: 0o700 });
|
|
289
|
+
await fs.writeFile(lastEvalFile(), JSON.stringify(state, null, 2), { encoding: "utf8", mode: 0o600 });
|
|
290
|
+
}
|
|
291
|
+
async function resolveSelfRepo() {
|
|
292
|
+
if (process.env.FORGE_SELF_REPO)
|
|
293
|
+
return process.env.FORGE_SELF_REPO;
|
|
294
|
+
try {
|
|
295
|
+
const { get } = await import("./configStore.js");
|
|
296
|
+
const repos = get()?.repos ?? [];
|
|
297
|
+
const forgeRepo = repos.find((r) => r.id.toLowerCase().includes("forge"));
|
|
298
|
+
return forgeRepo?.id ?? null;
|
|
299
|
+
}
|
|
300
|
+
catch {
|
|
301
|
+
return null;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
export async function maybeAutoEvaluate() {
|
|
305
|
+
try {
|
|
306
|
+
const summary = await getSummary();
|
|
307
|
+
const lastEval = await readLastEval();
|
|
308
|
+
// Check threshold: need EVAL_THRESHOLD new events since last eval
|
|
309
|
+
if (lastEval) {
|
|
310
|
+
const newEvents = summary.totalEvents - lastEval.eventCount;
|
|
311
|
+
if (newEvents < EVAL_THRESHOLD) {
|
|
312
|
+
return { skipped: true, reason: `only ${newEvents}/${EVAL_THRESHOLD} new events` };
|
|
313
|
+
}
|
|
314
|
+
// Check cooldown
|
|
315
|
+
const elapsed = Date.now() - new Date(lastEval.timestamp).getTime();
|
|
316
|
+
if (elapsed < EVAL_COOLDOWN_MS) {
|
|
317
|
+
const hoursLeft = ((EVAL_COOLDOWN_MS - elapsed) / 3_600_000).toFixed(1);
|
|
318
|
+
return { skipped: true, reason: `cooldown: ${hoursLeft}h remaining` };
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
else if (summary.totalEvents < EVAL_THRESHOLD) {
|
|
322
|
+
return { skipped: true, reason: `only ${summary.totalEvents}/${EVAL_THRESHOLD} total events` };
|
|
323
|
+
}
|
|
324
|
+
const result = await evaluate();
|
|
325
|
+
const highSeverity = result.diagnoses.filter((d) => d.severity === "high");
|
|
326
|
+
let issuesCreated = 0;
|
|
327
|
+
const selfRepo = await resolveSelfRepo();
|
|
328
|
+
if (highSeverity.length > 0 && selfRepo) {
|
|
329
|
+
try {
|
|
330
|
+
const { createProvider: cp } = await import("./providers/index.js");
|
|
331
|
+
const provider = cp(selfRepo);
|
|
332
|
+
for (const diagnosis of highSeverity.slice(0, 2)) {
|
|
333
|
+
try {
|
|
334
|
+
const title = `[self-improve] ${diagnosis.title}`;
|
|
335
|
+
const body = formatIssueBody(diagnosis);
|
|
336
|
+
await provider.createIssue(title, body);
|
|
337
|
+
issuesCreated++;
|
|
338
|
+
}
|
|
339
|
+
catch {
|
|
340
|
+
// issue creation is best-effort
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
catch {
|
|
345
|
+
// provider import/creation is best-effort
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
await writeLastEval({
|
|
349
|
+
timestamp: new Date().toISOString(),
|
|
350
|
+
eventCount: summary.totalEvents,
|
|
351
|
+
diagnosesCount: result.diagnoses.length,
|
|
352
|
+
issuesCreated,
|
|
353
|
+
});
|
|
354
|
+
return { skipped: false, diagnoses: result.diagnoses, issuesCreated };
|
|
355
|
+
}
|
|
356
|
+
catch {
|
|
357
|
+
return { skipped: true, reason: "evaluation failed" };
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
//# sourceMappingURL=selfImprove.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selfImprove.js","sourceRoot":"","sources":["../../../../server/forge/core/selfImprove.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../../../server/forge/core/telemetry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AASH,MAAM,WAAW,cAAc;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,kBAAkB,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IACrF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,MAAM,kBAAkB,GAC3B,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,UAAU,GACV,OAAO,GACP,OAAO,GACP,OAAO,GACP,kBAAkB,CAAC;AAEtB,MAAM,WAAW,gBAAgB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC5C,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,cAAc;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,WAAW;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACd;AAmBD,wBAAsB,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../../../server/forge/core/telemetry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AASH,MAAM,WAAW,cAAc;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,kBAAkB,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IACrF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,MAAM,kBAAkB,GAC3B,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,UAAU,GACV,OAAO,GACP,OAAO,GACP,OAAO,GACP,kBAAkB,CAAC;AAEtB,MAAM,WAAW,gBAAgB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC5C,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,cAAc;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,WAAW;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACd;AAmBD,wBAAsB,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAWjE;AAgBD,wBAAgB,UAAU,CACzB,SAAS,EAAE,kBAAkB,EAC7B,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,MAAM,EACjB,IAAI,GAAE;IACL,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC1B,GACJ,cAAc,CAUhB;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAQ5D;AAED,wBAAsB,eAAe,CAAC,KAAK,SAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAe5E;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC,CAoCpE;AAED,MAAM,WAAW,cAAc;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1E"}
|
|
@@ -34,11 +34,29 @@ export async function record(event) {
|
|
|
34
34
|
const line = JSON.stringify(event) + "\n";
|
|
35
35
|
await fs.appendFile(eventsFile(), line, { encoding: "utf8", mode: 0o600 });
|
|
36
36
|
await updateSummary(event);
|
|
37
|
+
// Fire-and-forget auto-evaluation after recording
|
|
38
|
+
triggerAutoEval().catch(() => { });
|
|
37
39
|
}
|
|
38
40
|
catch {
|
|
39
41
|
// telemetry is best-effort — never break the main flow
|
|
40
42
|
}
|
|
41
43
|
}
|
|
44
|
+
let autoEvalPending = false;
|
|
45
|
+
async function triggerAutoEval() {
|
|
46
|
+
if (autoEvalPending)
|
|
47
|
+
return;
|
|
48
|
+
autoEvalPending = true;
|
|
49
|
+
try {
|
|
50
|
+
const { maybeAutoEvaluate } = await import("./selfImprove.js");
|
|
51
|
+
await maybeAutoEvaluate();
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// auto-eval is best-effort
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
autoEvalPending = false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
42
60
|
export function buildEvent(operation, repo, iid, success, startTime, opts = {}) {
|
|
43
61
|
return {
|
|
44
62
|
ts: new Date().toISOString(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../../../server/forge/core/telemetry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAuD7B,gFAAgF;AAEhF,SAAS,YAAY;IACpB,OAAO,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;AAC3F,CAAC;AAED,SAAS,UAAU,KAAa,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;AACpF,SAAS,WAAW,KAAa,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;AAEpF,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAE7B,KAAK,UAAU,SAAS;IACvB,MAAM,EAAE,CAAC,KAAK,CAAC,YAAY,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAClE,CAAC;AAED,gFAAgF;AAEhF,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,KAAqB;IACjD,IAAI,CAAC;QACJ,MAAM,SAAS,EAAE,CAAC;QAClB,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;QAC1C,MAAM,EAAE,CAAC,UAAU,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC3E,MAAM,aAAa,CAAC,KAAK,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../../../server/forge/core/telemetry.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../server/forge/core/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,KAAK,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC3D,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClD;AAED,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAc,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,WAAW,CAAC;IACnD,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC,CAAC;IAC9C,UAAU,EAAE,eAAe,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,WAAW;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,SAAS;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC3B,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,QAAQ,EAAE;QACT,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,sBAAsB,EAAE,OAAO,CAAC;QAChC,gBAAgB,EAAE,OAAO,CAAC;QAC1B,WAAW,EAAE,MAAM,CAAC;QACpB,qBAAqB,CAAC,EAAE,MAAM,CAAC;QAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../server/forge/core/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ipul-labs/forge",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.0",
|
|
4
4
|
"description": "AI-powered code change & deploy control panel — connects Claude, GitLab, and Kubernetes",
|
|
5
5
|
"readmeFilename": "README.md",
|
|
6
6
|
"type": "module",
|
|
@@ -85,5 +85,5 @@
|
|
|
85
85
|
"url": "git+https://gitlab.com/ipul-labs/forge.git"
|
|
86
86
|
},
|
|
87
87
|
"license": "MIT",
|
|
88
|
-
"readme": "# Forge by iPuL\n\nAI-powered code change & deploy control panel. Connect an issue tracker, let Claude propose a fix, review the diff, approve — and Forge creates the branch, commits the changes, opens the MR/PR, and monitors the CI pipeline.\n\nBuilt on: Claude Code CLI · GitLab / GitHub / Azure DevOps · Kubernetes\n\n---\n\n## Why Forge\n\n**The CI refinement loop is the thing.** Every other AI coding tool hands off after the PR is open. Forge keeps going: when your pipeline fails, it grabs the last 150 lines of the failed job log, feeds them back to Claude with the original fix context, generates a targeted patch, and commits it to the branch — automatically. No human has to read the stack trace, translate it into a prompt, and paste it somewhere. The loop closes itself.\n\nEverything else fills in the gaps that matter for real teams:\n\n- **No per-token cost** — Claude runs via the `claude` CLI using your existing Claude subscription, not API credits. Heavy use doesn't trigger a bill.\n- **Multi-provider** — GitLab, GitHub, and Azure DevOps are all first-class. Switch providers with a single env var; all normalized data shapes stay the same.\n- **Self-hosted** — your code never leaves your infrastructure. The backend runs wherever you deploy it; AI calls go to Anthropic (or a local gateway via OpenClaw).\n- **Two-pass analysis keeps context focused** — Claude first identifies the 6 most relevant files, then reads only those when proposing the fix. This produces sharper diffs than dumping the whole repo into one prompt.\n\n---\n\n## How it works\n\n1. **Connect** — enter your Forge token to authenticate\n2. **Pick an issue** — Forge loads open issues from your project\n3. **Analyze** — Claude reads the repo file tree, identifies relevant files, and proposes a targeted fix\n4. **Review** — inspect the diff file-by-file; refine with natural-language feedback if needed\n5. **Apply** — Forge creates a branch, commits all changes, and opens a merge/pull request\n6. **Monitor** — watch the CI pipeline run; if it fails, click \"Fix with AI\" to iterate\n\n---\n\n## Getting started\n\n### Prerequisites\n\n- Node.js 20+\n- `claude` CLI installed and authenticated (`claude auth login`)\n- Credentials for your SCM provider (see [Configuration](#configuration))\n\n### Install\n\n```bash\ngit clone https://gitlab.com/ipul-labs/forge.git\ncd forge\nnpm install\n```\n\n### Configure\n\n```bash\n# Interactive setup — writes .env and ~/.forge/config.json\nnpx forge init\n```\n\nOr copy the example env and fill in the values manually:\n\n```bash\ncp .env.example .env\n# fill in FORGE_TOKEN plus your provider credentials\n```\n\n### Launch the UI\n\n```bash\nnpm run dev\n# opens http://localhost:5000 (frontend) with API on :5001\n```\n\nFor production:\n\n```bash\nnpm run build:app # builds Vite SPA to dist/\nnpm start # NODE_ENV=production node server.js\n```\n\n### CLI usage\n\nThe `forge` CLI drives the same orchestrator from the terminal. Install globally or use `npx`:\n\n```bash\n# Global install (adds `forge` to PATH)\nnpm install -g @ipul-labs/forge\n\n# Or run via npx from the repo\nnpx forge <command>\n```\n\n#### Interactive mode\n\nRun `forge` with no arguments to enter an interactive terminal session:\n\n```bash\nforge\n```\n\n```\n forge v1.15.1\n\n──────────────────────────────────────────────────\n ❯ issues --limit 5\n──────────────────────────────────────────────────\n group/repo | agent:claude | v1.15.1\n```\n\nTab-completes command names. Type `use <repo>` to switch repos. Commands that error stay in the session — only `exit`, `quit`, or Ctrl+D leave.\n\n#### End-to-end: issue to production\n\n```bash\nforge ship 42\n```\n\nRuns: analyze → review → validate → apply → watch CI → merge → watch deploy → close, with a `y/N` gate at every state-changing step.\n\n#### Step-by-step commands\n\n```bash\nforge issues # List open issues (--label X, --mine, --limit N)\nforge issue 42 # Show full description\nforge create-issue --title \"fix: broken widget\" # Create a new issue\nforge analyze 42 # Run two-pass analysis, cache result\nforge show # Re-render cached analysis\nforge refine --feedback \"...\" # Iterate with feedback\nforge validate # Run lint/typecheck/test against proposed changes\nforge apply # Push branch + open MR\nforge watch # Poll the MR pipeline\nforge ci-fix # Re-analyze with failed-pipeline logs\nforge merge # Merge the MR\nforge resolution-check # Verify merged MR closes the issue\nforge close # Close the issue\nforge use group/other-repo # Switch active repo\nforge update # Pull latest + reinstall dependencies\nforge stats # View telemetry — success rates, timing, failure patterns\n```\n\n#### Options\n\n```\n-p, --port <n> Port for start\n--repo <group/repo> Primary repo\n--secondary <repo> Additional repo (repeatable)\n--all-repos Include every configured repo\n--model <id> Claude model override\n--agent <name> Agent backend: claude | openclaw\n--prompt <text> Extra user prompt\n--json JSON output\n--quiet Suppress progress\n--yes Skip confirmation gates\n--validate Run validate before apply\n```\n\n#### Diagnostics\n\n```bash\nforge doctor # Check prerequisites (node, claude CLI, env vars)\nforge session list # List cached sessions\nforge session clean # Remove stale session data\n```\n\nSee [`docs/cli.md`](./docs/cli.md) for the full command reference and [`docs/cli-ship-workflow.md`](./docs/cli-ship-workflow.md) for the workflow design.\n\n---\n\n## Configuration\n\n### Core\n\n| Variable | Required | Description |\n|---|---|---|\n| `FORGE_TOKEN` | Yes | Dashboard password — also auto-fills the UI login form |\n| `FORGE_REPOS` | Yes | Comma-separated repo list; first entry is the primary project |\n| `SCM_PROVIDER` | — | `gitlab` (default) · `github` · `azuredevops` |\n| `ANTHROPIC_API_KEY` | — | Enables live model list from Anthropic; falls back to hardcoded list |\n| `FORGE_MODEL` | — | Override default model (default: `claude-sonnet-4-6`) |\n| `K8S_CLUSTER_TOKEN` | — | K8s service account token for rollout monitoring |\n| `K8S_CLUSTER_SERVER` | — | K8s API server URL |\n| `PORT` | — | HTTP server port (default: `5001`) |\n| `OPENCLAW_GATEWAY_URL` | — | Enables OpenClaw agent backend; point at your local Gateway |\n| `OPENCLAW_TOKEN` | — | Bearer token for OpenClaw Gateway auth |\n\n### Provider credentials\n\nSCM tokens can be set here **or** in the Forge Settings UI (Settings → Connections). The UI value takes precedence over env vars.\n\n#### GitLab (`SCM_PROVIDER=gitlab`, default)\n\n| Variable | Required | Description |\n|---|---|---|\n| `GITLAB_TOKEN` | Yes | Personal access token with `api` + `write_repository` scopes |\n\n#### GitHub (`SCM_PROVIDER=github`)\n\n| Variable | Required | Description |\n|---|---|---|\n| `GITHUB_TOKEN` | Yes | Personal access token with `repo` + `workflow` scopes |\n| `GITHUB_OWNER` | Yes | Organization or user, e.g. `ipul-labs` |\n| `GITHUB_REPO` | Yes | Repository name, e.g. `web-app` |\n| `GITHUB_BASE_BRANCH` | — | Default target branch (default: `main`) |\n\n#### Azure DevOps (`SCM_PROVIDER=azuredevops`)\n\n| Variable | Required | Description |\n|---|---|---|\n| `AZURE_DEVOPS_TOKEN` | Yes | Personal access token (Full access or Code + Work Items) |\n| `AZURE_DEVOPS_ORG` | Yes | Organization name, e.g. `ipul-labs` |\n| `AZURE_DEVOPS_PROJECT` | Yes | Team project name, e.g. `web-app` |\n| `AZURE_DEVOPS_REPO` | — | Git repo name (defaults to project name) |\n| `AZURE_DEVOPS_BASE_BRANCH` | — | Default target branch (default: `main`) |\n\n### Deprecated (still work as fallbacks)\n\n| Variable | Replaced by |\n|---|---|\n| `FORGE_GITLAB_PROJECT` | First entry in `FORGE_REPOS` |\n| `VITE_FORGE_TOKEN` | Auto-derived from `FORGE_TOKEN` |\n| `FORGE_REFINE_REPO_ACCESS` | Settings UI toggle (Settings → Defaults) |\n\nSee `.env.example` for a full annotated list.\n\n---\n\n## Multi-provider support\n\nForge's SCM layer is a clean provider abstraction — all three providers implement the same `ScmProvider` interface and return identical normalized shapes (`NormalIssue`, `NormalMR`, `NormalPipeline`, etc.). The rest of the codebase never knows which provider is active.\n\n### Switching providers\n\n```bash\n# .env\nSCM_PROVIDER=github\nGITHUB_TOKEN=ghp_...\nGITHUB_OWNER=my-org\nGITHUB_REPO=my-repo\n```\n\n### Per-repo prefix (multi-repo mixed-provider setups)\n\n```bash\nFORGE_REPOS=gitlab:ipul/web-app,github:my-org/mobile\n```\n\n### Provider capabilities\n\n| Feature | GitLab | GitHub | Azure DevOps |\n|---|---|---|---|\n| Issues / Work Items | Yes | Yes | Yes (Work Items) |\n| Multi-file commits | Yes | Yes (Git Data API) | Yes (Pushes API) |\n| Merge / Pull Requests | Yes | Yes | Yes |\n| CI pipelines | Yes (GitLab CI) | Yes (GitHub Actions) | Yes (Azure Pipelines) |\n| Job log traces | Yes | Yes | Yes |\n| Server-side rebase | Yes | — | — |\n\n---\n\n## Security\n\nForge is designed for self-hosted deployment on trusted infrastructure. Security measures in place:\n\n- **Timing-safe auth** — token comparison uses `crypto.timingSafeEqual` to prevent timing attacks\n- **Rate limiting** — API endpoints are rate-limited (60 req/min per IP) to prevent brute-force\n- **Security headers** — Helmet middleware sets X-Frame-Options, HSTS, X-Content-Type-Options, and CSP (production)\n- **Request size limits** — JSON body capped at 1MB to prevent memory exhaustion\n- **Secret redaction** — error logs and API responses scrub tokens (`glpat-*`, `ghp_*`, `oauth2:*@`) before output\n- **File permissions** — config files (`~/.forge/config.json`) written with `0600`, session directories with `0700`\n- **Git credential isolation** — SCM tokens passed via `GIT_ASKPASS` helper, never embedded in clone URLs\n- **Path traversal protection** — symlink-aware `realpath` checks prevent file writes outside clone directories\n- **No shell injection** — all subprocess calls use `spawn()` with argument arrays, never shell strings\n- **Atomic config writes** — config updates use temp file + rename to prevent corruption\n\n`FORGE_TOKEN` is a standalone dashboard password — never reuse an SCM token for this value.\n\n---\n\n## Production deployment\n\n```bash\nnpm run build:app # builds Vite SPA to dist/\nNODE_ENV=production tsx server.ts\n```\n\nOr with Docker:\n\n```bash\ndocker build -t forge .\ndocker run -p 5001:5001 --env-file .env forge\n```\n\n---\n\n## Architecture\n\nFull-stack TypeScript. The backend runs via `tsx` (no build step); the frontend compiles through Vite.\n\n```\nbin/\n forge-agent.ts # CLI entry point (forge command)\n cli/\n ship.ts # End-to-end orchestrator (Ink UI)\n analyze.ts # Two-pass issue analysis\n repl.ts # Interactive terminal (Ink-based)\n serverClient.ts # CLI → Server API client (server/local mode)\n sessionStore.ts # ~/.forge/sessions/ persistence\n ...\n\nshared/\n events.ts # FORGE_EVENTS constants (server + client)\n\nserver/\n forge/\n routes.ts # Express router — all /api/forge/* endpoints\n core/\n ForgeAgent.ts # Orchestrates the full pipeline (analyze -> apply -> refine)\n claudeClient.ts # Shells out to the claude CLI for structured output\n openclawClient.ts # OpenClaw Gateway HTTP client\n agentClient.ts # Dispatcher: routes to claudeClient or openclawClient\n k8s.ts # Kubernetes client for rollout monitoring\n jobs.ts # Job store with SSE event buffering + replay\n providers/\n base.ts # Abstract ScmProvider — normalized shapes + interface\n gitlab.ts # GitLab REST API v4\n github.ts # GitHub REST API v3 + Git Data API\n azuredevops.ts # Azure DevOps REST API\n index.ts # createProvider() factory\n\nsrc/\n views/Forge/\n ForgeDashboard.tsx # Root UI component with tabbed issue/MR views\n api.ts # Token management + fetch helper\n types.ts # Shared TypeScript types\n utils.ts # SSE helper + state utilities\n components/ # Analysis progress, pipeline status, diff viewer\n hooks/\n useForgeDashboard.ts # All state, phase transitions, and API calls\n useForgeEvents.ts # SSE event bus subscription\n```\n\n### Two-pass analysis\n\n**Pass 1** — `identifyRelevantFiles`: Claude reads the issue + file tree, returns the max-6 most relevant paths.\n\n**Pass 2** — `proposeFix`: Claude reads the actual file contents and proposes a targeted fix as a JSON diff.\n\nBoth passes use `claude --print --output-format json` so cost and service tier are tracked automatically.\n\n### CI refinement\n\nWhen a pipeline fails, Forge fetches the last 150 lines of each failed job's trace log and feeds them to pass 2 with an explicit \"pipeline failed\" framing — not generic reviewer feedback. This improves fix quality for common failures like lint errors and type errors.\n\n### Provider abstraction\n\nAll three SCM providers implement `ScmProvider` from `providers/base.ts`. The contract is:\n- **Normalized return types** — all methods return `NormalIssue`, `NormalMR`, `NormalPipeline`, etc., regardless of provider\n- **Instance-scoped** — each provider is instantiated with a repo string; no global state\n- **`supportsRebase`** — providers that don't support server-side rebase return `false`; the UI and API layer check this before showing the rebase button\n\n---\n\n## Programmatic usage\n\nThe npm package ships compiled JavaScript with TypeScript declarations — no `tsx` or TypeScript runtime needed by consumers.\n\n```ts\nimport forgeRouter from \"@ipul-labs/forge\"; // Express router\nimport { ForgeAgent } from \"@ipul-labs/forge/agent\"; // Core pipeline class\nimport { createProvider } from \"@ipul-labs/forge/providers\"; // SCM factory\n```\n\n```ts\nconst agent = new ForgeAgent({ project: \"group/repo\" });\nconst result = await agent.analyzeIssue(42, (event) => console.log(event));\nconst { branchName, mr } = await agent.applyFix(result);\n```\n\n### Development\n\nSource is TypeScript (`.ts`). The dev server runs via `tsx` (no build step). For the npm package, `tsc` compiles to `lib/` with declarations during `prepack`.\n\n```bash\nnpm run dev # tsx watch + vite (dev)\nnpm run build:server # compile server/bin/shared → lib/\nnpm run typecheck # check both frontend + server configs\n```\n\n---\n\n## License\n\nMIT\n"
|
|
88
|
+
"readme": "# Forge by iPuL\n\nAI-powered code change & deploy control panel. Connect an issue tracker, let Claude propose a fix, review the diff, approve — and Forge creates the branch, commits the changes, opens the MR/PR, and monitors the CI pipeline.\n\nBuilt on: Claude Code CLI · GitLab / GitHub / Azure DevOps · Kubernetes\n\n---\n\n## Why Forge\n\n**The CI refinement loop is the thing.** Every other AI coding tool hands off after the PR is open. Forge keeps going: when your pipeline fails, it grabs the last 150 lines of the failed job log, feeds them back to Claude with the original fix context, generates a targeted patch, and commits it to the branch — automatically. No human has to read the stack trace, translate it into a prompt, and paste it somewhere. The loop closes itself.\n\nEverything else fills in the gaps that matter for real teams:\n\n- **No per-token cost** — Claude runs via the `claude` CLI using your existing Claude subscription, not API credits. Heavy use doesn't trigger a bill.\n- **Multi-provider** — GitLab, GitHub, and Azure DevOps are all first-class. Switch providers with a single env var; all normalized data shapes stay the same.\n- **Self-hosted** — your code never leaves your infrastructure. The backend runs wherever you deploy it; AI calls go to Anthropic (or a local gateway via OpenClaw).\n- **Two-pass analysis keeps context focused** — Claude first identifies the 6 most relevant files, then reads only those when proposing the fix. This produces sharper diffs than dumping the whole repo into one prompt.\n\n---\n\n## How it works\n\n1. **Connect** — enter your Forge token to authenticate\n2. **Pick an issue** — Forge loads open issues from your project\n3. **Analyze** — Claude reads the repo file tree, identifies relevant files, and proposes a targeted fix\n4. **Review** — inspect the diff file-by-file; refine with natural-language feedback if needed\n5. **Apply** — Forge creates a branch, commits all changes, and opens a merge/pull request\n6. **Monitor** — watch the CI pipeline run; if it fails, click \"Fix with AI\" to iterate\n\n---\n\n## Getting started\n\n### Prerequisites\n\n- Node.js 20+\n- `claude` CLI installed and authenticated (`claude auth login`)\n- Credentials for your SCM provider (see [Configuration](#configuration))\n\n### Install\n\n```bash\ngit clone https://gitlab.com/ipul-labs/forge.git\ncd forge\nnpm install\n```\n\n### Configure\n\n```bash\n# Interactive setup — writes .env and ~/.forge/config.json\nnpx forge init\n```\n\nOr copy the example env and fill in the values manually:\n\n```bash\ncp .env.example .env\n# fill in FORGE_TOKEN plus your provider credentials\n```\n\n### Launch the UI\n\n```bash\nnpm run dev\n# opens http://localhost:5000 (frontend) with API on :5001\n```\n\nFor production:\n\n```bash\nnpm run build:app # builds Vite SPA to dist/\nnpm start # NODE_ENV=production node server.js\n```\n\n### CLI usage\n\nThe `forge` CLI drives the same orchestrator from the terminal. Install globally or use `npx`:\n\n```bash\n# Global install (adds `forge` to PATH)\nnpm install -g @ipul-labs/forge\n\n# Or run via npx from the repo\nnpx forge <command>\n```\n\n#### Interactive mode\n\nRun `forge` with no arguments to enter an interactive terminal session:\n\n```bash\nforge\n```\n\n```\n forge v1.15.1\n\n──────────────────────────────────────────────────\n ❯ issues --limit 5\n──────────────────────────────────────────────────\n group/repo | agent:claude | v1.15.1\n```\n\nTab-completes command names. Type `use <repo>` to switch repos. Commands that error stay in the session — only `exit`, `quit`, or Ctrl+D leave.\n\n#### End-to-end: issue to production\n\n```bash\nforge ship 42\n```\n\nRuns: analyze → review → validate → apply → watch CI → merge → watch deploy → close, with a `y/N` gate at every state-changing step.\n\n#### Step-by-step commands\n\n```bash\nforge issues # List open issues (--label X, --mine, --limit N)\nforge issue 42 # Show full description\nforge create-issue --title \"fix: broken widget\" # Create a new issue\nforge analyze 42 # Run two-pass analysis, cache result\nforge show # Re-render cached analysis\nforge refine --feedback \"...\" # Iterate with feedback\nforge validate # Run lint/typecheck/test against proposed changes\nforge apply # Push branch + open MR\nforge watch # Poll the MR pipeline\nforge ci-fix # Re-analyze with failed-pipeline logs\nforge merge # Merge the MR\nforge resolution-check # Verify merged MR closes the issue\nforge close # Close the issue\nforge use group/other-repo # Switch active repo\nforge update # Pull latest + reinstall dependencies\nforge stats # View telemetry — success rates, timing, failure patterns\nforge improve # Evaluate patterns and suggest improvements\nforge improve --create # Create improvement issues in the repo\n```\n\n#### Options\n\n```\n-p, --port <n> Port for start\n--repo <group/repo> Primary repo\n--secondary <repo> Additional repo (repeatable)\n--all-repos Include every configured repo\n--model <id> Claude model override\n--agent <name> Agent backend: claude | openclaw\n--prompt <text> Extra user prompt\n--json JSON output\n--quiet Suppress progress\n--yes Skip confirmation gates\n--validate Run validate before apply\n```\n\n#### Diagnostics\n\n```bash\nforge doctor # Check prerequisites (node, claude CLI, env vars)\nforge session list # List cached sessions\nforge session clean # Remove stale session data\n```\n\nSee [`docs/cli.md`](./docs/cli.md) for the full command reference and [`docs/cli-ship-workflow.md`](./docs/cli-ship-workflow.md) for the workflow design.\n\n---\n\n## Configuration\n\n### Core\n\n| Variable | Required | Description |\n|---|---|---|\n| `FORGE_TOKEN` | Yes | Dashboard password — also auto-fills the UI login form |\n| `FORGE_REPOS` | Yes | Comma-separated repo list; first entry is the primary project |\n| `SCM_PROVIDER` | — | `gitlab` (default) · `github` · `azuredevops` |\n| `ANTHROPIC_API_KEY` | — | Enables live model list from Anthropic; falls back to hardcoded list |\n| `FORGE_MODEL` | — | Override default model (default: `claude-sonnet-4-6`) |\n| `K8S_CLUSTER_TOKEN` | — | K8s service account token for rollout monitoring |\n| `K8S_CLUSTER_SERVER` | — | K8s API server URL |\n| `PORT` | — | HTTP server port (default: `5001`) |\n| `OPENCLAW_GATEWAY_URL` | — | Enables OpenClaw agent backend; point at your local Gateway |\n| `OPENCLAW_TOKEN` | — | Bearer token for OpenClaw Gateway auth |\n\n### Provider credentials\n\nSCM tokens can be set here **or** in the Forge Settings UI (Settings → Connections). The UI value takes precedence over env vars.\n\n#### GitLab (`SCM_PROVIDER=gitlab`, default)\n\n| Variable | Required | Description |\n|---|---|---|\n| `GITLAB_TOKEN` | Yes | Personal access token with `api` + `write_repository` scopes |\n\n#### GitHub (`SCM_PROVIDER=github`)\n\n| Variable | Required | Description |\n|---|---|---|\n| `GITHUB_TOKEN` | Yes | Personal access token with `repo` + `workflow` scopes |\n| `GITHUB_OWNER` | Yes | Organization or user, e.g. `ipul-labs` |\n| `GITHUB_REPO` | Yes | Repository name, e.g. `web-app` |\n| `GITHUB_BASE_BRANCH` | — | Default target branch (default: `main`) |\n\n#### Azure DevOps (`SCM_PROVIDER=azuredevops`)\n\n| Variable | Required | Description |\n|---|---|---|\n| `AZURE_DEVOPS_TOKEN` | Yes | Personal access token (Full access or Code + Work Items) |\n| `AZURE_DEVOPS_ORG` | Yes | Organization name, e.g. `ipul-labs` |\n| `AZURE_DEVOPS_PROJECT` | Yes | Team project name, e.g. `web-app` |\n| `AZURE_DEVOPS_REPO` | — | Git repo name (defaults to project name) |\n| `AZURE_DEVOPS_BASE_BRANCH` | — | Default target branch (default: `main`) |\n\n### Deprecated (still work as fallbacks)\n\n| Variable | Replaced by |\n|---|---|\n| `FORGE_GITLAB_PROJECT` | First entry in `FORGE_REPOS` |\n| `VITE_FORGE_TOKEN` | Auto-derived from `FORGE_TOKEN` |\n| `FORGE_REFINE_REPO_ACCESS` | Settings UI toggle (Settings → Defaults) |\n\nSee `.env.example` for a full annotated list.\n\n---\n\n## Multi-provider support\n\nForge's SCM layer is a clean provider abstraction — all three providers implement the same `ScmProvider` interface and return identical normalized shapes (`NormalIssue`, `NormalMR`, `NormalPipeline`, etc.). The rest of the codebase never knows which provider is active.\n\n### Switching providers\n\n```bash\n# .env\nSCM_PROVIDER=github\nGITHUB_TOKEN=ghp_...\nGITHUB_OWNER=my-org\nGITHUB_REPO=my-repo\n```\n\n### Per-repo prefix (multi-repo mixed-provider setups)\n\n```bash\nFORGE_REPOS=gitlab:ipul/web-app,github:my-org/mobile\n```\n\n### Provider capabilities\n\n| Feature | GitLab | GitHub | Azure DevOps |\n|---|---|---|---|\n| Issues / Work Items | Yes | Yes | Yes (Work Items) |\n| Multi-file commits | Yes | Yes (Git Data API) | Yes (Pushes API) |\n| Merge / Pull Requests | Yes | Yes | Yes |\n| CI pipelines | Yes (GitLab CI) | Yes (GitHub Actions) | Yes (Azure Pipelines) |\n| Job log traces | Yes | Yes | Yes |\n| Server-side rebase | Yes | — | — |\n\n---\n\n## Self-improvement\n\nForge monitors its own performance and proposes fixes autonomously. The loop:\n\n1. **Telemetry** — every operation records success/fail, duration, tokens, and cost to `~/.forge/telemetry/`\n2. **Pattern detection** — recurring failures are grouped and classified (timeout-tuning, provider-bug, prompt-quality, validation-gap, error-handling, ux-improvement)\n3. **Auto-evaluation** — runs automatically after every 25 operations (4-hour cooldown). High-severity patterns trigger issue creation.\n4. **Issue creation** — files issues in the configured repo with diagnosis, evidence, and suggested fixes. Tagged `[self-improve]` with category labels.\n5. **Human review** — Forge never auto-merges its own changes. All improvements go through normal MR review.\n\n```bash\nforge stats # View telemetry data\nforge improve # Run evaluation manually\nforge improve --create # Create issues for actionable patterns\nforge improve --json # Pipe-friendly output\n```\n\nUX insights are also derived from telemetry: slow operations (>2 min avg), high token usage (>50k avg), and frequent cancellations surface as improvement suggestions.\n\n---\n\n## Security\n\nForge is designed for self-hosted deployment on trusted infrastructure. Security measures in place:\n\n- **Timing-safe auth** — token comparison uses `crypto.timingSafeEqual` to prevent timing attacks\n- **Rate limiting** — API endpoints are rate-limited (60 req/min per IP) to prevent brute-force\n- **Security headers** — Helmet middleware sets X-Frame-Options, HSTS, X-Content-Type-Options, and CSP (production)\n- **Request size limits** — JSON body capped at 1MB to prevent memory exhaustion\n- **Secret redaction** — error logs and API responses scrub tokens (`glpat-*`, `ghp_*`, `oauth2:*@`) before output\n- **File permissions** — config files (`~/.forge/config.json`) written with `0600`, session directories with `0700`\n- **Git credential isolation** — SCM tokens passed via `GIT_ASKPASS` helper, never embedded in clone URLs\n- **Path traversal protection** — symlink-aware `realpath` checks prevent file writes outside clone directories\n- **No shell injection** — all subprocess calls use `spawn()` with argument arrays, never shell strings\n- **Atomic config writes** — config updates use temp file + rename to prevent corruption\n\n`FORGE_TOKEN` is a standalone dashboard password — never reuse an SCM token for this value.\n\n---\n\n## Production deployment\n\n```bash\nnpm run build:app # builds Vite SPA to dist/\nNODE_ENV=production tsx server.ts\n```\n\nOr with Docker:\n\n```bash\ndocker build -t forge .\ndocker run -p 5001:5001 --env-file .env forge\n```\n\n---\n\n## Architecture\n\nFull-stack TypeScript. The backend runs via `tsx` (no build step); the frontend compiles through Vite.\n\n```\nbin/\n forge-agent.ts # CLI entry point (forge command)\n cli/\n ship.ts # End-to-end orchestrator (Ink UI)\n analyze.ts # Two-pass issue analysis\n repl.ts # Interactive terminal (Ink-based)\n serverClient.ts # CLI → Server API client (server/local mode)\n sessionStore.ts # ~/.forge/sessions/ persistence\n ...\n\nshared/\n events.ts # FORGE_EVENTS constants (server + client)\n\nserver/\n forge/\n routes.ts # Express router — all /api/forge/* endpoints\n core/\n ForgeAgent.ts # Orchestrates the full pipeline (analyze -> apply -> refine)\n claudeClient.ts # Shells out to the claude CLI for structured output\n openclawClient.ts # OpenClaw Gateway HTTP client\n agentClient.ts # Dispatcher: routes to claudeClient or openclawClient\n k8s.ts # Kubernetes client for rollout monitoring\n jobs.ts # Job store with SSE event buffering + replay\n providers/\n base.ts # Abstract ScmProvider — normalized shapes + interface\n gitlab.ts # GitLab REST API v4\n github.ts # GitHub REST API v3 + Git Data API\n azuredevops.ts # Azure DevOps REST API\n index.ts # createProvider() factory\n\nsrc/\n views/Forge/\n ForgeDashboard.tsx # Root UI component with tabbed issue/MR views\n api.ts # Token management + fetch helper\n types.ts # Shared TypeScript types\n utils.ts # SSE helper + state utilities\n components/ # Analysis progress, pipeline status, diff viewer\n hooks/\n useForgeDashboard.ts # All state, phase transitions, and API calls\n useForgeEvents.ts # SSE event bus subscription\n```\n\n### Two-pass analysis\n\n**Pass 1** — `identifyRelevantFiles`: Claude reads the issue + file tree, returns the max-6 most relevant paths.\n\n**Pass 2** — `proposeFix`: Claude reads the actual file contents and proposes a targeted fix as a JSON diff.\n\nBoth passes use `claude --print --output-format json` so cost and service tier are tracked automatically.\n\n### CI refinement\n\nWhen a pipeline fails, Forge fetches the last 150 lines of each failed job's trace log and feeds them to pass 2 with an explicit \"pipeline failed\" framing — not generic reviewer feedback. This improves fix quality for common failures like lint errors and type errors.\n\n### Provider abstraction\n\nAll three SCM providers implement `ScmProvider` from `providers/base.ts`. The contract is:\n- **Normalized return types** — all methods return `NormalIssue`, `NormalMR`, `NormalPipeline`, etc., regardless of provider\n- **Instance-scoped** — each provider is instantiated with a repo string; no global state\n- **`supportsRebase`** — providers that don't support server-side rebase return `false`; the UI and API layer check this before showing the rebase button\n\n---\n\n## Programmatic usage\n\nThe npm package ships compiled JavaScript with TypeScript declarations — no `tsx` or TypeScript runtime needed by consumers.\n\n```ts\nimport forgeRouter from \"@ipul-labs/forge\"; // Express router\nimport { ForgeAgent } from \"@ipul-labs/forge/agent\"; // Core pipeline class\nimport { createProvider } from \"@ipul-labs/forge/providers\"; // SCM factory\n```\n\n```ts\nconst agent = new ForgeAgent({ project: \"group/repo\" });\nconst result = await agent.analyzeIssue(42, (event) => console.log(event));\nconst { branchName, mr } = await agent.applyFix(result);\n```\n\n### Development\n\nSource is TypeScript (`.ts`). The dev server runs via `tsx` (no build step). For the npm package, `tsc` compiles to `lib/` with declarations during `prepack`.\n\n```bash\nnpm run dev # tsx watch + vite (dev)\nnpm run build:server # compile server/bin/shared → lib/\nnpm run typecheck # check both frontend + server configs\n```\n\n---\n\n## License\n\nMIT\n"
|
|
89
89
|
}
|