@dennisrepa/elevate 1.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/LICENSE +21 -0
- package/README.md +214 -0
- package/dist/cli.js +3569 -0
- package/dist/cli.js.map +1 -0
- package/docs/de.md +305 -0
- package/docs/en.md +309 -0
- package/docs/plans/transactional-updates.md +142 -0
- package/package.json +73 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# 🪶 Elevate — Plan: Transaktionale Updates & lokaler MCP-Betrieb
|
|
2
|
+
|
|
3
|
+
> **Status:** geplant · **Stand:** 2026-09-25
|
|
4
|
+
> **Betriebsmodell:** Elevate läuft lokal beim Entwickler. Sein Harness (Continue, Cline, Claude Code, Cursor …) startet `elevate mcp` als stdio-Server im Projektordner. Keine Container, kein Gateway (siehe Parity ADR 0006, gilt für die ganze Tool-Familie).
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 1. Ziele
|
|
9
|
+
|
|
10
|
+
1. **Transaktionale Updates:** Schlägt die Verifikation fehl, bleibt das Repository unverändert.
|
|
11
|
+
2. **Ein zentraler Update-Ablauf** statt drei Kopien in CLI, TUI und MCP.
|
|
12
|
+
3. **Saubere Workspace-Bestimmung** im MCP-Betrieb (MCP Roots).
|
|
13
|
+
4. **`init` für alle gängigen Harnesses**, inklusive Continue und Cline.
|
|
14
|
+
|
|
15
|
+
## 2. Ausgangslage
|
|
16
|
+
|
|
17
|
+
| Thema | Heute |
|
|
18
|
+
|---|---|
|
|
19
|
+
| Update-Ablauf | Manifest schreiben → `npm install` / `mvn dependency:resolve` → Verifikation, alles direkt im Repo ([npm-updater.ts](../../src/adapters/npm/npm-updater.ts), [maven-updater.ts](../../src/adapters/maven/maven-updater.ts), [npm-verifier.ts](../../src/adapters/npm/npm-verifier.ts), [maven-verifier.ts](../../src/adapters/maven/maven-verifier.ts)) |
|
|
20
|
+
| Fehlgeschlagene Verifikation | Repo bleibt im geänderten Zustand, man muss selbst zurückrollen |
|
|
21
|
+
| Duplikation | Ablauf „anwenden → verifizieren“ dreifach: [command-update.ts:173](../../src/cli/command-update.ts#L173), [use-updater.ts:34](../../src/hooks/use-updater.ts#L34), [mcp-server.ts:410](../../src/mcp/mcp-server.ts#L410) |
|
|
22
|
+
| Workspace | `findMonorepoRoot(process.cwd())` ([config.ts:67](../../src/config.ts#L67)), MCP Roots werden nicht genutzt |
|
|
23
|
+
| `init` | erkennt Cursor, Claude Desktop, Claude Code, Antigravity, VS Code, Windsurf ([command-init.ts](../../src/cli/command-init.ts)). **Continue und Cline fehlen.** |
|
|
24
|
+
|
|
25
|
+
## 3. Zentraler Update-Workflow
|
|
26
|
+
|
|
27
|
+
Neuer Application Service `src/application/update-workflow.ts`, den CLI, TUI und MCP gemeinsam nutzen:
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
export class UpdateWorkflow {
|
|
31
|
+
constructor(private strategy: EcosystemStrategy, private sandbox: WorkspaceSandboxPort) {}
|
|
32
|
+
|
|
33
|
+
async run(input: {
|
|
34
|
+
module: ProjectModule;
|
|
35
|
+
rootDir: string;
|
|
36
|
+
updates: UpdateCandidate[];
|
|
37
|
+
verify: boolean;
|
|
38
|
+
onProgress: (msg: string) => void;
|
|
39
|
+
}): Promise<UpdateWorkflowResult>; // updateSummary, verifyResult, committed, changedFiles, followUps
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Dieser Schritt ändert **kein** Verhalten. Er beseitigt nur die Duplikation und schafft die Stelle, an der die Transaktion eingebaut wird.
|
|
44
|
+
|
|
45
|
+
## 4. Transaktion ĂĽber einen austauschbaren Arbeitsort
|
|
46
|
+
|
|
47
|
+
### 4.1 Port
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
// src/domain/ports.ts
|
|
51
|
+
export interface WorkspaceSandbox {
|
|
52
|
+
readonly workDir: string;
|
|
53
|
+
resolve(module: ProjectModule): ProjectModule; // Modulpfade ĂĽber relPath auf workDir abbilden
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface WorkspaceSandboxPort {
|
|
57
|
+
open(rootDir: string): Promise<WorkspaceSandbox>;
|
|
58
|
+
commit(sandbox: WorkspaceSandbox, files: string[]): Promise<void>;
|
|
59
|
+
discard(sandbox: WorkspaceSandbox): Promise<void>;
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 4.2 Adapter
|
|
64
|
+
|
|
65
|
+
| Adapter | Verhalten | Einsatz |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| `SnapshotSandboxAdapter` | Arbeitet **direkt im Repo**, sichert vorher Manifeste + Lockfiles. Bei `discard` werden diese zurĂĽckgespielt und die Installation erneut ausgefĂĽhrt, um `node_modules` wiederherzustellen. | **Standard.** Schnell, nutzt vorhandenes `node_modules` |
|
|
68
|
+
| `CopySandboxAdapter` | Kopiert das Repo (git-getrackte + nicht ignorierte Dateien, ohne `node_modules`/`target`/`dist`) in ein Temp-Verzeichnis, arbeitet dort und schreibt bei Erfolg nur Manifeste + Lockfiles zurück. Danach wird im echten Repo installiert. | `--isolated`: maximale Sicherheit, z. B. für riskante Major-Updates. Das Repo wird während der Prüfung **nie** berührt. |
|
|
69
|
+
| `InPlaceSandboxAdapter` | Heutiges Verhalten ohne Rollback | `--no-rollback`, für Sonderfälle |
|
|
70
|
+
|
|
71
|
+
### 4.3 Ablauf
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
1. open Snapshot anlegen bzw. Kopie erstellen
|
|
75
|
+
2. apply Manifest ändern, installieren
|
|
76
|
+
3. verify Build + Tests
|
|
77
|
+
4a. grĂĽn commit: Snapshot verwerfen bzw. Manifeste + Lockfiles zurĂĽckschreiben
|
|
78
|
+
4b. rot discard: Dateien zurückspielen + Installation wiederherstellen → Repo wie vorher
|
|
79
|
+
5. Ergebnis inkl. changedFiles und ggf. followUps
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 4.4 Updater melden geänderte Dateien
|
|
83
|
+
|
|
84
|
+
`DependencyUpdaterPort.applyUpdates()` liefert zusätzlich die geänderten Dateien (relativ zum Root). Das braucht die Transaktion:
|
|
85
|
+
|
|
86
|
+
| Ă–kosystem | Dateien |
|
|
87
|
+
|---|---|
|
|
88
|
+
| npm | betroffene `package.json` + `package-lock.json` |
|
|
89
|
+
| Maven | betroffene `pom.xml` |
|
|
90
|
+
| kĂĽnftig pnpm / Yarn / Gradle | `pnpm-lock.yaml` / `yarn.lock` / `gradle.lockfile`, `libs.versions.toml` |
|
|
91
|
+
|
|
92
|
+
### 4.5 Schutz vor parallelen Änderungen
|
|
93
|
+
|
|
94
|
+
Beim `open` wird ein Hash der betroffenen Dateien gespeichert. Hat der Entwickler (oder ein anderer Agent) sie während des Laufs geändert, bricht `commit`/`discard` ab, statt fremde Änderungen zu überschreiben, und meldet den Konflikt.
|
|
95
|
+
|
|
96
|
+
## 5. MCP-Betrieb
|
|
97
|
+
|
|
98
|
+
### 5.1 Workspace-Bestimmung
|
|
99
|
+
|
|
100
|
+
In dieser Reihenfolge:
|
|
101
|
+
|
|
102
|
+
1. **MCP Roots** des Clients (bei mehreren Roots: Parameter `workspace` wählt aus, Default der erste; auf `roots/list_changed` reagieren)
|
|
103
|
+
2. `--root <pfad>` bzw. `ELEVATE_ROOT`
|
|
104
|
+
3. `findMonorepoRoot(process.cwd())` (heutiges Verhalten)
|
|
105
|
+
|
|
106
|
+
Pfade außerhalb der Roots werden abgelehnt. Diese Logik wandert später ins gemeinsame Toolkit-Paket der Tool-Familie.
|
|
107
|
+
|
|
108
|
+
### 5.2 Antworten
|
|
109
|
+
|
|
110
|
+
- `elevate_apply_updates` meldet `rolledBack: true` samt Grund, wenn die Verifikation fehlschlug.
|
|
111
|
+
- Parameter `isolated: boolean` (entspricht `--isolated`).
|
|
112
|
+
- Keine verschachtelten Parameter mehr für einfache Fälle: zusätzlich `identifiers: string[]` (Update auf latest) neben dem bestehenden `updates`-Array. Das ist für lokale Modelle deutlich robuster.
|
|
113
|
+
|
|
114
|
+
## 6. `init` fĂĽr alle Harnesses
|
|
115
|
+
|
|
116
|
+
Neu: **Continue** (`.continue/mcpServers/elevate.yaml` bzw. globale `config.yaml`) und **Cline** (`cline_mcp_settings.json`). Vorhandene Detektoren bleiben. Ziel ist eine Liste, die in der ganzen Tool-Familie identisch ist:
|
|
117
|
+
|
|
118
|
+
`continue · cline · claude-code · claude-desktop · cursor · windsurf · vscode · antigravity`
|
|
119
|
+
|
|
120
|
+
## 7. Tests
|
|
121
|
+
|
|
122
|
+
- **Unit:** `UpdateWorkflow` mit Fake-Ports: grün → commit, rot → discard, Konflikt → Abbruch.
|
|
123
|
+
- **Adapter:** Snapshot (RĂĽckspielen, EOL-Erhalt, Wiederherstellung von `node_modules`), Copy (Kopierregeln, `resolve()` fĂĽr verschachtelte Module, RĂĽckschreiben).
|
|
124
|
+
- **Integration:** Beispiel-Repo mit absichtlich brechendem Update. Danach ist das Repo per `git status` sauber und die Tests laufen wieder grĂĽn.
|
|
125
|
+
- **MCP:** Roots-Handling mit Test-Client (ein Root, mehrere Roots, Wechsel).
|
|
126
|
+
- **Regression:** TUI, CLI und MCP liefern bei grĂĽnen Updates dieselben Ergebnisse wie vorher.
|
|
127
|
+
|
|
128
|
+
## 8. Umsetzungsschritte
|
|
129
|
+
|
|
130
|
+
| Schritt | Inhalt | Fertig, wenn |
|
|
131
|
+
|---|---|---|
|
|
132
|
+
| 1 | `UpdateWorkflow`, CLI/TUI/MCP umstellen | Duplikation entfernt, Verhalten unverändert |
|
|
133
|
+
| 2 | Port + `InPlaceSandboxAdapter`, Updater liefern `changedFiles` | Heutiges Verhalten läuft über den Port |
|
|
134
|
+
| 3 | `SnapshotSandboxAdapter` als Standard, Konfliktschutz | Rote Verifikation hinterlässt ein unverändertes Repo |
|
|
135
|
+
| 4 | `CopySandboxAdapter` + `--isolated` | Repo wird während isolierter Prüfung nicht berührt |
|
|
136
|
+
| 5 | MCP Roots, `--root`, `rolledBack`, `identifiers` | Roots-Tests grĂĽn |
|
|
137
|
+
| 6 | `init` fĂĽr Continue und Cline, Doku (de/en) | Beide Harnesses per `elevate init` eingerichtet |
|
|
138
|
+
|
|
139
|
+
## 9. Offene Fragen
|
|
140
|
+
|
|
141
|
+
1. Soll bei einem Rollback die Wiederherstellung von `node_modules` per `npm ci` (exakt, langsamer) oder `npm install` (schneller) erfolgen? *Vorschlag:* `npm ci`, wenn ein Lockfile existiert.
|
|
142
|
+
2. Workspace-Bestimmung und `init` zuerst in Elevate bauen und danach ins Toolkit-Paket verschieben, oder direkt im Toolkit starten? *Vorschlag:* direkt im Toolkit, damit Register und Parity sofort profitieren.
|
package/package.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dennisrepa/elevate",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "🪶 Elevate — Interactive Polyglot Terminal Dashboard & Agentic MCP Server for safe dependency updates across monorepos.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/cli.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"elevate": "dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md",
|
|
13
|
+
"docs"
|
|
14
|
+
],
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"cli",
|
|
20
|
+
"tui",
|
|
21
|
+
"dependencies",
|
|
22
|
+
"updater",
|
|
23
|
+
"monorepo",
|
|
24
|
+
"npm",
|
|
25
|
+
"maven",
|
|
26
|
+
"mcp",
|
|
27
|
+
"agentic"
|
|
28
|
+
],
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/DennisRepa/Elevate.git"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://github.com/DennisRepa/Elevate#readme",
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/DennisRepa/Elevate/issues"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsup",
|
|
40
|
+
"build:bundle": "node scripts/build-bundle.mjs",
|
|
41
|
+
"build:binary": "node scripts/build-binary.mjs",
|
|
42
|
+
"dev": "tsx src/index.tsx",
|
|
43
|
+
"start": "node dist/cli.js",
|
|
44
|
+
"prepublishOnly": "npm run build"
|
|
45
|
+
},
|
|
46
|
+
"author": {
|
|
47
|
+
"name": "Dennis Répa",
|
|
48
|
+
"email": "dennis.maier.1989@gmail.com",
|
|
49
|
+
"url": "https://de.linkedin.com/in/dennismaier1989"
|
|
50
|
+
},
|
|
51
|
+
"funding": {
|
|
52
|
+
"type": "ko-fi",
|
|
53
|
+
"url": "https://ko-fi.com/dennisrepa"
|
|
54
|
+
},
|
|
55
|
+
"engines": {
|
|
56
|
+
"node": ">=20.0.0"
|
|
57
|
+
},
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"@modelcontextprotocol/sdk": "^1.30.1",
|
|
60
|
+
"ink": "^6.3.0",
|
|
61
|
+
"picocolors": "^1.1.1",
|
|
62
|
+
"react": "^19.0.0",
|
|
63
|
+
"semver": "^7.6.3",
|
|
64
|
+
"tsx": "^4.19.3"
|
|
65
|
+
},
|
|
66
|
+
"devDependencies": {
|
|
67
|
+
"@types/node": "^26.6.2",
|
|
68
|
+
"@types/react": "^19.3.0",
|
|
69
|
+
"@types/semver": "^7.8.0",
|
|
70
|
+
"tsup": "^8.5.1",
|
|
71
|
+
"typescript": "^7.0.2"
|
|
72
|
+
}
|
|
73
|
+
}
|