hmgr 0.0.39 → 0.0.41

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.
@@ -0,0 +1,31 @@
1
+ // Die Änderungsliste als mitgelieferte JSON-Datei dist/aenderungen.json (E108). Der Adapter liegt in
2
+ // dist/adapter/, die Datei eine Ebene höher; im Quellbaum (node src/cli/main.ts) gibt es sie nicht,
3
+ // dann ist die Liste leer. Fehlende oder kaputte Datei ist nie ein Fehler.
4
+ import { readFile } from 'node:fs/promises';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { ohneBom } from "./datei-text.js";
7
+ export class AenderungenJson {
8
+ pfad;
9
+ constructor(pfad = fileURLToPath(new URL('../aenderungen.json', import.meta.url))) {
10
+ this.pfad = pfad;
11
+ }
12
+ async lesen() {
13
+ const roh = await readFile(this.pfad, 'utf8').catch(() => undefined);
14
+ if (roh === undefined)
15
+ return {};
16
+ try {
17
+ const daten = JSON.parse(ohneBom(roh));
18
+ if (typeof daten.versionen !== 'object' || daten.versionen === null || Array.isArray(daten.versionen))
19
+ return {};
20
+ const ergebnis = {};
21
+ for (const [version, commits] of Object.entries(daten.versionen)) {
22
+ if (Array.isArray(commits))
23
+ ergebnis[version] = commits.filter((c) => typeof c === 'string');
24
+ }
25
+ return ergebnis;
26
+ }
27
+ catch {
28
+ return {};
29
+ }
30
+ }
31
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "fassung": 1,
3
+ "versionen": {
4
+ "0.0.41": [
5
+ "Im Verlauf steht unter „hmgr … installiert\" jetzt aufklappbar, was sich in der neuen Version geändert hat."
6
+ ]
7
+ }
8
+ }
package/dist/cli/hilfe.js CHANGED
@@ -564,6 +564,10 @@ Fehler zu einer Quelle oder einem Bundle, dazu hmgr-Ereignisse: ein Versionsspru
564
564
  (GUI oder CLI, erkannt beim Start bzw. bei jedem CLI-Aufruf) oder ein gefundenes Update, das noch
565
565
  nicht installiert ist. Plugins stehen nicht im Verlauf (siehe hmgr help update).
566
566
 
567
+ Unter einem „installiert"-Eintrag von hmgr stehen die Änderungen: je Version seit der zuvor
568
+ vermerkten die Nummer und darunter die Änderungen als kurze Sätze (E108). Einträge ohne bekannte Vorversion
569
+ zeigen nur die eigene Version, ohne mitgelieferte Änderungsliste entfällt der Abschnitt.
570
+
567
571
  Der Verlauf ist je Rechner: mehrere Maschinen führen ihre eigene Datei, es gibt kein Zusammenführen.
568
572
 
569
573
  Schalter: keine.
package/dist/cli/main.js CHANGED
@@ -22,6 +22,7 @@ import { TerminalRueckfrage } from "../adapter/terminal.js";
22
22
  import { ProzessUmgebung } from "../adapter/umgebung.js";
23
23
  import { ZustandJson } from "../adapter/zustand-json.js";
24
24
  import { VerlaufJson } from "../adapter/verlauf-json.js";
25
+ import { AenderungenJson } from "../adapter/aenderungen-json.js";
25
26
  import { HILFE, hilfeText } from "./hilfe.js";
26
27
  export function umgebungLesen(env = process.env) {
27
28
  const home = env.HOME ?? homedir();
@@ -104,6 +105,7 @@ export function bauen(umgebung, optionen = {}) {
104
105
  variablen: async (distro) => await new WslBruecke(distro, wslUmgebungAusfuehren).variablen(),
105
106
  },
106
107
  verlauf,
108
+ aenderungen: optionen.aenderungen ?? new AenderungenJson(),
107
109
  };
108
110
  return { anwendungsfaelle: new Anwendungsfaelle(ports), ports };
109
111
  }
@@ -858,8 +860,15 @@ export async function ausfuehren(argv, umgebung, optionen = {}) {
858
860
  console.log('Noch keine Ereignisse.');
859
861
  for (const eintrag of eintraege) {
860
862
  console.log(verlaufZeitpunkt(eintrag.zeit));
861
- for (const ereignis of eintrag.ereignisse)
863
+ for (const ereignis of eintrag.ereignisse) {
862
864
  console.log(` ${verlaufEreignisZeile(ereignis)}`);
865
+ // Unter einem Versionssprung die Commits der neuen Version(en), eingerückt (E108).
866
+ if (ereignis.art === 'hmgr-installiert') {
867
+ const aenderungen = await anwendungsfaelle.hmgrAenderungen(ereignis.vorher, ereignis.version);
868
+ for (const zeile of aenderungsZeilen(aenderungen))
869
+ console.log(zeile);
870
+ }
871
+ }
863
872
  }
864
873
  return 0;
865
874
  }
@@ -1091,6 +1100,10 @@ function verlaufZeitpunkt(iso) {
1091
1100
  return (`${zwei(datum.getDate())}.${zwei(datum.getMonth() + 1)}.${datum.getFullYear()} ` +
1092
1101
  `${zwei(datum.getHours())}:${zwei(datum.getMinutes())}`);
1093
1102
  }
1103
+ /** Je Version die Nummer und darunter ihre Commit-Betreffs, tiefer eingerückt als die Ereigniszeile (E108). */
1104
+ function aenderungsZeilen(aenderungen) {
1105
+ return aenderungen.flatMap((a) => [` ${a.version}`, ...a.commits.map((c) => ` ${c}`)]);
1106
+ }
1094
1107
  /** Eine Ereigniszeile im Verlauf (E80), eingerückt unter der Kopfzeile ihres Laufs. */
1095
1108
  function verlaufEreignisZeile(ereignis) {
1096
1109
  if (ereignis.art === 'checkout') {
package/dist/gui/main.js CHANGED
@@ -11,6 +11,7 @@ import { randomUUID } from 'node:crypto';
11
11
  import { stat } from 'node:fs/promises';
12
12
  import { fileURLToPath } from 'node:url';
13
13
  import { bauen, umgebungLesen } from "../cli/main.js";
14
+ import { AenderungenJson } from "../adapter/aenderungen-json.js";
14
15
  import { quelleAlsText, quelleAusText } from "../adapter/quelle-text.js";
15
16
  import { paketVersion } from "../adapter/paket-version.js";
16
17
  import { infoPlistPfad, MeldungsPuffer, neuereVersionAufPlatte } from "./selbst-update.js";
@@ -129,6 +130,11 @@ const rueckfrage = new GuiRueckfrage();
129
130
  const { anwendungsfaelle, ports } = bauen(umgebung, {
130
131
  rueckfrage,
131
132
  ...(smoketest ? { claudeAusfuehrer: smoketestClaudeAusfuehrer } : {}),
133
+ // Nur der Smoke-Test biegt die Änderungsliste auf eine Fixture-Datei um (E108); sonst die
134
+ // mitgelieferte dist/aenderungen.json.
135
+ ...(smoketest && process.env.HMGR_GUI_SMOKE_AENDERUNGEN !== undefined
136
+ ? { aenderungen: new AenderungenJson(process.env.HMGR_GUI_SMOKE_AENDERUNGEN) }
137
+ : {}),
132
138
  });
133
139
  /**
134
140
  * Wer den laufenden Aktualisieren-Lauf ausgelöst hat (E80): der Renderer reicht es bei jedem Aufruf
@@ -329,6 +335,8 @@ function registriereIpc() {
329
335
  }));
330
336
  // Changelog der letzten Läufe (E80), neueste zuerst.
331
337
  ipcMain.handle('hmgr:verlauf', async () => auffangen(async () => anwendungsfaelle.verlauf()));
338
+ // Änderungen (Commit-Betreffs) der Versionen eines hmgr-Versionssprungs (E108).
339
+ ipcMain.handle('hmgr:hmgrAenderungen', async (_event, vorher, version) => auffangen(async () => anwendungsfaelle.hmgrAenderungen(vorher, version)));
332
340
  // E77: der Prüfen-Knopf stößt zusätzlich zum Quellen-Lauf die Prüfung auf hmgr selbst an. Kein
333
341
  // `handle`, sondern `send`/`on`: der Renderer wartet auf nichts, das Ergebnis kommt später von
334
342
  // sich aus über 'hmgr:selbstUpdate'.
@@ -712,6 +720,23 @@ function fensterOeffnen() {
712
720
  verlaufBloecke = document.querySelectorAll('#verlauf .block').length;
713
721
  if (verlaufBloecke > 0) break;
714
722
  }
723
+ // E108: die Änderungslisten kommen nach dem Verlauf per IPC; warten, bis jeder Platz
724
+ // entweder sein details hat oder (ohne Daten) entfernt ist.
725
+ for (var wartezeit2 = 0; wartezeit2 < 2000; wartezeit2 += 100) {
726
+ if (document.querySelector('#verlauf .aenderungen-platz:empty') === null) break;
727
+ await new Promise((r) => setTimeout(r, 100));
728
+ }
729
+ var aenderungenDetails = document.querySelectorAll('#verlauf details.aenderungen').length;
730
+ var aenderungenElement = document.querySelector('#verlauf details.aenderungen');
731
+ var aenderungenSummary = aenderungenElement?.querySelector('summary')?.textContent?.trim() ?? null;
732
+ var aenderungenOffenVorher = aenderungenElement?.open ?? null;
733
+ aenderungenElement?.querySelector('summary')?.click();
734
+ var aenderungenOffenNachher = aenderungenElement?.open ?? null;
735
+ var aenderungenGruppen = aenderungenElement?.querySelectorAll('.aenderungen-version').length ?? 0;
736
+ var aenderungenText = Array.prototype.map.call(
737
+ aenderungenElement?.querySelectorAll('.aenderungen-version') ?? [],
738
+ (g) => g.textContent.replace(/\\s+/g, ' ').trim(),
739
+ ).join(' ');
715
740
  var verlaufText = document.getElementById('verlauf')?.textContent?.replace(/\\s+/g, ' ').trim() ?? null;
716
741
  // Nachziehen je Quelle (E89): das Fixture hat im skills-repo einen neuen Upstream-Commit
717
742
  // (fixtureAufbauen), den erst ein Lauf für diese Quelle holt. Erst der Knopf der
@@ -1295,6 +1320,12 @@ function fensterOeffnen() {
1295
1320
  verlaufVorhanden,
1296
1321
  verlaufText,
1297
1322
  verlaufBloecke,
1323
+ aenderungenDetails,
1324
+ aenderungenSummary,
1325
+ aenderungenOffenVorher,
1326
+ aenderungenOffenNachher,
1327
+ aenderungenGruppen,
1328
+ aenderungenText,
1298
1329
  nachziehenFehler,
1299
1330
  nachziehenKnopfZahl,
1300
1331
  nachziehenBloeckeStart,
@@ -35,6 +35,8 @@ contextBridge.exposeInMainWorld('hmgr', {
35
35
  aktualisieren: (args) => ipcRenderer.invoke('hmgr:aktualisieren', args),
36
36
  /** Changelog der letzten Läufe (E80), neueste zuerst. */
37
37
  verlauf: () => ipcRenderer.invoke('hmgr:verlauf'),
38
+ /** Commit-Betreffs der Versionen zwischen `vorher` (exklusiv) und `version` (E108), neueste zuerst. */
39
+ hmgrAenderungen: (vorher, version) => ipcRenderer.invoke('hmgr:hmgrAenderungen', vorher, version),
38
40
  /** Installiert das geladene GUI-Update und startet neu (E80), Gegenstück zum Neustart-Knopf. */
39
41
  neuStarten: () => {
40
42
  ipcRenderer.send('hmgr:neuStarten');
@@ -2927,6 +2927,12 @@
2927
2927
  } else if (ereignis.art === 'hmgr-installiert') {
2928
2928
  li.appendChild(e('span', 'marke-ok', 'installiert'));
2929
2929
  li.appendChild(e('span', 'pfad', (ereignis.paket === 'gui' ? 'hmgr-GUI ' : 'hmgr ') + ereignis.version));
2930
+ // E108: die Commits der Versionen seit der zuvor installierten, zum Ausklappen unter der Zeile.
2931
+ // Der Platzhalter hält die Stelle, das details kommt nach dem Aufbau des Verlaufs hinein.
2932
+ var aenderungenPlatz = e('div', 'aenderungen-platz');
2933
+ aenderungenPlatz.dataset.vorher = ereignis.vorher || '';
2934
+ aenderungenPlatz.dataset.version = ereignis.version;
2935
+ li.appendChild(aenderungenPlatz);
2930
2936
  } else if (ereignis.art === 'gui-update-geladen') {
2931
2937
  li.appendChild(e('span', 'marke-ok', 'geladen'));
2932
2938
  li.appendChild(e('span', 'pfad', 'GUI-Update ' + ereignis.version));
@@ -2965,6 +2971,29 @@
2965
2971
  block.appendChild(ul);
2966
2972
  box.appendChild(block);
2967
2973
  });
2974
+ // E108: die Änderungslisten nachladen, nachdem der Verlauf steht. Ein Fehler lässt nur den
2975
+ // jeweiligen Abschnitt weg, nie den Verlauf.
2976
+ var plaetze = Array.prototype.slice.call(box.querySelectorAll('.aenderungen-platz'));
2977
+ await Promise.all(plaetze.map(async function (platz) {
2978
+ var versionen = await window.hmgr.hmgrAenderungen(platz.dataset.vorher || undefined, platz.dataset.version)
2979
+ .then(function (r) { return r && r.ok ? r.daten : []; }, function () { return []; });
2980
+ if (versionen.length === 0) { platz.remove(); return; }
2981
+ var zahl = versionen.reduce(function (summe, v) { return summe + v.commits.length; }, 0);
2982
+ var d = e('details', 'notizen aenderungen');
2983
+ var s = e('summary');
2984
+ s.appendChild(keilIcon());
2985
+ s.appendChild(document.createTextNode('Änderungen (' + zahl + ')'));
2986
+ d.appendChild(s);
2987
+ versionen.forEach(function (v) {
2988
+ var gruppe = e('div', 'aenderungen-version');
2989
+ gruppe.appendChild(e('b', null, v.version));
2990
+ var liste = e('ul');
2991
+ v.commits.forEach(function (commit) { liste.appendChild(e('li', null, commit)); });
2992
+ gruppe.appendChild(liste);
2993
+ d.appendChild(gruppe);
2994
+ });
2995
+ platz.appendChild(d);
2996
+ }));
2968
2997
  }
2969
2998
 
2970
2999
  /* ================= PLUGINS ================= */
@@ -3112,13 +3141,8 @@
3112
3141
  return zeilen;
3113
3142
  }
3114
3143
 
3115
- /** Notizen sind das Langsame am Eintrag (entwurf/gui.html): zugeklappt, öffnen sich nur, wenn
3116
- jemand sie sucht. Der Wortlaut bleibt, wie er in der mcp.yaml steht, Zeilenumbrüche
3117
- eingeschlossen (weiss-raum: pre-line in styles.css). */
3118
- function mcpNotizenBlock(text) {
3119
- var d = document.createElement('details');
3120
- d.className = 'notizen';
3121
- var s = document.createElement('summary');
3144
+ /** Der Aufklapp-Keil in einer summary (dreht sich per CSS beim Öffnen). */
3145
+ function keilIcon() {
3122
3146
  var pfeil = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
3123
3147
  pfeil.setAttribute('viewBox', '0 0 16 16');
3124
3148
  pfeil.setAttribute('class', 'keil');
@@ -3128,7 +3152,17 @@
3128
3152
  pfeil.setAttribute('stroke-linejoin', 'round');
3129
3153
  pfeil.setAttribute('aria-hidden', 'true');
3130
3154
  pfeil.innerHTML = '<path d="M4.3 2.5 7.8 6 4.3 9.5"/>';
3131
- s.appendChild(pfeil);
3155
+ return pfeil;
3156
+ }
3157
+
3158
+ /** Notizen sind das Langsame am Eintrag (entwurf/gui.html): zugeklappt, öffnen sich nur, wenn
3159
+ jemand sie sucht. Der Wortlaut bleibt, wie er in der mcp.yaml steht, Zeilenumbrüche
3160
+ eingeschlossen (weiss-raum: pre-line in styles.css). */
3161
+ function mcpNotizenBlock(text) {
3162
+ var d = document.createElement('details');
3163
+ d.className = 'notizen';
3164
+ var s = document.createElement('summary');
3165
+ s.appendChild(keilIcon());
3132
3166
  s.appendChild(document.createTextNode('Notizen'));
3133
3167
  d.appendChild(s);
3134
3168
  d.appendChild(e('p', null, text));
@@ -490,6 +490,13 @@ img.hsymbol{border-radius:3px}
490
490
  .block .marke-ok{color:var(--emaille-hoch);font-weight:700}
491
491
  .block .marke-aus{color:var(--messing-tief);font-weight:700}
492
492
  .block .pfad{color:var(--tinte-weich)}
493
+ /* E108: Änderungen unter „hmgr X installiert", aufklappbar wie die Notizen der MCP-Karte. */
494
+ .block .aenderungen-platz{grid-column:1 / -1}
495
+ .block .aenderungen-platz:empty{display:none}
496
+ .aenderungen{margin-top:0}
497
+ .aenderungen .aenderungen-version{margin-top:9px;padding-left:13px;border-left:2px solid var(--strich);font-size:16px;color:var(--tinte-weich)}
498
+ .block .aenderungen ul{margin-top:4px;gap:4px;font-size:16px}
499
+ .block .aenderungen li{display:block}
493
500
 
494
501
  .markt{margin-bottom:26px}
495
502
  .marktkopf{display:flex;flex-wrap:wrap;gap:8px 16px;align-items:baseline;margin-bottom:12px;padding-bottom:10px;border-bottom:2px solid var(--tinte)}
@@ -6,6 +6,17 @@ import { passenderRef } from "./version.js";
6
6
  import { kannIstRegistriert, kannMcp, kannPlugins, kannProfile, kannSkillOrdner, kannZurueckbauen, kannZusaetzlicheHeime, } from "../ports/harness.js";
7
7
  /** So viele `plugin list`-Prozesse laufen im Ist-Zustand höchstens gleichzeitig (E93). */
8
8
  const PLUGIN_ABFRAGEN_GLEICHZEITIG = 6;
9
+ /** „0.0.39" → [0, 0, 39]; alles andere (Vorabversion, Text) → undefined. */
10
+ function versionZerlegen(version) {
11
+ const t = /^(\d+)\.(\d+)\.(\d+)$/.exec(version);
12
+ return t === null ? undefined : [Number(t[1]), Number(t[2]), Number(t[3])];
13
+ }
14
+ function versionVergleichen(a, b) {
15
+ for (let i = 0; i < 3; i++)
16
+ if (a[i] !== b[i])
17
+ return a[i] - b[i];
18
+ return 0;
19
+ }
9
20
  /**
10
21
  * Die Welt eines Orts als Text für Bericht und Verlauf (E101), in der Schreibweise von `--ort`:
11
22
  * „home" für die Installation dieses Rechners, „wsl:<distro>" für die einer Distro.
@@ -2042,6 +2053,31 @@ export class Anwendungsfaelle {
2042
2053
  async verlauf() {
2043
2054
  return (await this.p.verlauf.lesen()).eintraege;
2044
2055
  }
2056
+ /**
2057
+ * Die Änderungen (Commit-Betreffs) der Versionen, die ein Sprung von `vorher` auf `version`
2058
+ * mitbrachte (E108): alle Versionen V mit vorher < V ≤ version, neueste zuerst. Ohne `vorher`
2059
+ * nur `version` selbst. Versionen ohne Eintrag in der Liste (oder ohne Commits) fehlen im
2060
+ * Ergebnis; eine nicht als x.y.z lesbare Version ergibt eine leere Liste.
2061
+ */
2062
+ async hmgrAenderungen(vorher, version) {
2063
+ const bis = versionZerlegen(version);
2064
+ if (bis === undefined)
2065
+ return [];
2066
+ const ab = vorher === undefined ? undefined : versionZerlegen(vorher);
2067
+ const liste = await this.p.aenderungen.lesen();
2068
+ const treffer = [];
2069
+ for (const [v, commits] of Object.entries(liste)) {
2070
+ const zahlen = versionZerlegen(v);
2071
+ if (zahlen === undefined || commits.length === 0)
2072
+ continue;
2073
+ const imBereich = vorher === undefined
2074
+ ? versionVergleichen(zahlen, bis) === 0
2075
+ : ab !== undefined && versionVergleichen(zahlen, ab) > 0 && versionVergleichen(zahlen, bis) <= 0;
2076
+ if (imBereich)
2077
+ treffer.push({ zahlen, eintrag: { version: v, commits } });
2078
+ }
2079
+ return treffer.sort((a, b) => versionVergleichen(b.zahlen, a.zahlen)).map((t) => t.eintrag);
2080
+ }
2045
2081
  /**
2046
2082
  * Merkt die installierte Version eines hmgr-Pakets (GUI oder CLI) und schreibt bei einem
2047
2083
  * Versionssprung einen Verlaufseintrag (E80). Der erste Aufruf ohne gemerkte Version merkt nur,
@@ -2060,7 +2096,7 @@ export class Anwendungsfaelle {
2060
2096
  const eintrag = {
2061
2097
  zeit: new Date().toISOString(),
2062
2098
  ausloeser,
2063
- ereignisse: [{ art: 'hmgr-installiert', paket, version }],
2099
+ ereignisse: [{ art: 'hmgr-installiert', paket, version, vorher: bisher }],
2064
2100
  };
2065
2101
  await this.p.verlauf.schreiben({ gemerkt, eintraege: [eintrag, ...daten.eintraege] });
2066
2102
  }
@@ -0,0 +1,3 @@
1
+ // Änderungen: die gepflegten Sätze je hmgr-Version (E108) aus AENDERUNGEN.md, beim Bauen nach
2
+ // dist/aenderungen.json übertragen (scripts/aenderungen-erzeugen.mjs). Der Verlauf zeigt sie unter „hmgr X installiert".
3
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hmgr",
3
- "version": "0.0.39",
3
+ "version": "0.0.41",
4
4
  "description": "Harness Manager: Skills und Plugins für AI-Harnesses verwalten",
5
5
  "license": "MIT",
6
6
  "author": "Tim Kaufmann",
@@ -19,7 +19,7 @@
19
19
  },
20
20
  "scripts": {
21
21
  "dev": "node src/cli/main.ts",
22
- "build": "tsc -p tsconfig.build.json && node scripts/copy-gui-assets.mjs",
22
+ "build": "tsc -p tsconfig.build.json && node scripts/copy-gui-assets.mjs && node scripts/aenderungen-erzeugen.mjs",
23
23
  "gui": "npm run build && electron dist/gui/main.js",
24
24
  "gui:smoke": "npm run build && node scripts/gui-smoke-test.ts",
25
25
  "gui:app": "npm run build && electron-builder --mac --arm64",