hmgr 0.0.25 → 0.0.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/main.js CHANGED
@@ -990,7 +990,8 @@ export async function ausfuehren(argv, umgebung, optionen = {}) {
990
990
  // Säubern-Angebot nur, wenn eigene Konfiguration liegt, mit derselben Bedingung wie die GUI
991
991
  // (E38, GRILL.md Entwurfskritik 4): eigene Links oder eine liegen gebliebene Registrierung
992
992
  // ohne Link (E38 R7), sonst machten CLI und GUI verschiedene Angebote.
993
- const ziele = (await anwendungsfaelle.istZustand()).filter((z) => z.ziel.harness === name &&
993
+ // Ohne Plugin-Abfrage (E94): gelesen werden nur Harness, Einträge und Registrierung.
994
+ const ziele = (await anwendungsfaelle.istZustand({ plugins: false })).filter((z) => z.ziel.harness === name &&
994
995
  (z.eintraege.some((eintrag) => eintrag.art !== 'fremd') || z.istRegistriert));
995
996
  if (ziele.length === 0)
996
997
  return 0;
package/dist/gui/main.js CHANGED
@@ -886,6 +886,35 @@ function fensterOeffnen() {
886
886
  } catch (fehler) {
887
887
  bundleZerbrichtText = String(fehler);
888
888
  }
889
+ // Sammelstreifen unter „Alle" (E95): das Bundle „vorhaben" liegt an kunde-x in Claude Code
890
+ // und Hermes — ein Streifen mit beiden Harness-Zeichen, Entfernen nennt beide Harnesses
891
+ // (nur der Dialogtext, kein Klick auf „Ja"). Unter dem Harness-Chip steht weiter die
892
+ // volle Gruppe mit Zeilen; danach zurück auf „Alle".
893
+ var streifenKarte = Array.from(document.querySelectorAll('#zielliste .ziel.verzeichnis'))
894
+ .find((k) => (k.querySelector('.zielkopf')?.textContent || '').indexOf('kunde-x') > -1);
895
+ var streifenZahl = null, streifenHarnesse = null, streifenText = null;
896
+ var streifenDialogTitel = null, streifenDialogText = null;
897
+ var chipGruppeZahl = null, chipGruppeZeilenZahl = null, chipStreifenZahl = null;
898
+ try {
899
+ var streifen = Array.from(streifenKarte?.querySelectorAll('.bundlegruppe') ?? []);
900
+ streifenZahl = streifen.length;
901
+ streifenHarnesse = streifen[0]?.querySelector('.zeilenzeichen')?.getAttribute('aria-label') ?? null;
902
+ streifenText = streifen[0]?.textContent?.replace(/\\s+/g, ' ').trim() ?? null;
903
+ streifen[0]?.querySelector('button')?.click();
904
+ streifenDialogTitel = document.getElementById('dx-titel')?.textContent ?? null;
905
+ streifenDialogText = document.getElementById('dx-text')?.textContent ?? null;
906
+ document.querySelector('#d-entfernen button[value="nein"]')?.click();
907
+ var chipClaude = streifenKarte?.querySelector('.kartenchips [data-chipwahl="claude-code"]');
908
+ chipClaude?.click();
909
+ var kundeXNachChip = Array.from(document.querySelectorAll('#zielliste .ziel.verzeichnis'))
910
+ .find((k) => (k.querySelector('.zielkopf')?.textContent || '').indexOf('kunde-x') > -1);
911
+ chipGruppeZahl = kundeXNachChip?.querySelectorAll('.bundlegruppe').length ?? null;
912
+ chipGruppeZeilenZahl = kundeXNachChip?.querySelectorAll('.bundlegruppe .linkliste li').length ?? null;
913
+ chipStreifenZahl = kundeXNachChip?.querySelectorAll('.bundlegruppe .zeilenzeichen').length ?? null;
914
+ kundeXNachChip?.querySelector('.kartenchips [data-chipwahl="alle"]')?.click();
915
+ } catch (fehler) {
916
+ streifenDialogText = String(fehler);
917
+ }
889
918
  // MCP-Ansicht (E61-Folgerunde, F46: abgespeckt zum reinen Katalog): Navigationsreihenfolge
890
919
  // Ziele, MCP, Plugins, Skills, Karten mit Name/Beschreibung/Homepage-Link, F39-Warnzeile,
891
920
  // Einhängen-Dialog öffnen/abbrechen ohne IPC-Schreibaktion. Orte-Liste und Fremdkasten
@@ -1172,6 +1201,14 @@ function fensterOeffnen() {
1172
1201
  bundleGruppeText,
1173
1202
  bundleGruppeZeilen,
1174
1203
  bundleZerbrichtText,
1204
+ streifenZahl,
1205
+ streifenHarnesse,
1206
+ streifenText,
1207
+ streifenDialogTitel,
1208
+ streifenDialogText,
1209
+ chipGruppeZahl,
1210
+ chipGruppeZeilenZahl,
1211
+ chipStreifenZahl,
1175
1212
  interGeladen: document.fonts.check('400 16px Inter'),
1176
1213
  monoGeladen: document.fonts.check('500 16px "JetBrains Mono"'),
1177
1214
  quelleneuVorhanden,
@@ -826,21 +826,35 @@
826
826
  return gruppe;
827
827
  }
828
828
 
829
- /** Ein Bundle als einzelner Streifen (Chip „Alle" einer Verzeichnis-Karte, E69/E53): Harness-
830
- Zeichen, Name, seine Mitglieder als Text, Entfernen. Ohne eigene Tabelle. */
831
- function bundleStreifen(b, z) {
829
+ /** Ein Bundle als einzelner Streifen (Chip „Alle" einer Verzeichnis-Karte, E69/E53/E95): die
830
+ Harness-Zeichen aller Harnesses, in denen es liegt (wie in den Skill-Zeilen), Name, Mitglieder,
831
+ Entfernen für alle diese Harnesses. `treffer`: [{b, z}], je Harness einer, gleicher Name und
832
+ gleiche Quelle. Mitglieder: die des ersten Treffers, abweichende anderer Harnesses folgen. */
833
+ function bundleStreifen(treffer) {
834
+ var b = treffer[0].b;
832
835
  var streifen = e('div', 'bundlegruppe');
833
836
  var kopf = e('div', 'bundlekopf');
834
837
  var titel = e('span', 'bundletitel');
835
- titel.appendChild(harnessZeichen(z.ziel.harness));
838
+ var harnesse = [];
839
+ treffer.forEach(function (t) { if (harnesse.indexOf(t.z.ziel.harness) === -1) harnesse.push(t.z.ziel.harness); });
840
+ harnesse.sort(function (x, y) { return harnessName(x).localeCompare(harnessName(y), 'de'); });
841
+ titel.appendChild(harnesseZeichenSammel(harnesse));
836
842
  titel.appendChild(e('span', 'etikett', 'Bundle'));
837
843
  titel.appendChild(e('b', 'bundlename', b.name));
838
844
  kopf.appendChild(titel);
839
- kopf.appendChild(e('span', 'bundlemitglieder', b.skills.join(', ')));
845
+ var mitglieder = [];
846
+ treffer.forEach(function (t) {
847
+ t.b.skills.forEach(function (n) { if (mitglieder.indexOf(n) === -1) mitglieder.push(n); });
848
+ });
849
+ kopf.appendChild(e('span', 'bundlemitglieder', mitglieder.join(', ')));
840
850
  var weg = e('button', 'knopf leise klein', 'Entfernen');
841
851
  weg.type = 'button';
842
- weg.setAttribute('aria-label', 'Bundle ' + b.name + ' aus ' + zielTitel(z) + ' entfernen');
843
- weg.addEventListener('click', function () { frageBundleEntfernen(b, z.ziel); });
852
+ weg.setAttribute('aria-label', 'Bundle ' + b.name + ' aus '
853
+ + treffer.map(function (t) { return zielTitel(t.z); }).join(', ') + ' entfernen');
854
+ weg.addEventListener('click', function () {
855
+ if (treffer.length === 1) frageBundleEntfernen(b, treffer[0].z.ziel);
856
+ else frageBundleEntfernenAlle(b.name, mitglieder, treffer);
857
+ });
844
858
  kopf.appendChild(weg);
845
859
  streifen.appendChild(kopf);
846
860
  return streifen;
@@ -1209,13 +1223,22 @@
1209
1223
  // Bundle gehört aber zu genau einem Harness — deshalb hier ein Streifen je Bundle mit seinem
1210
1224
  // Harness-Zeichen statt einer Umgruppierung der Tabelle. Unter dem Harness-Chip zeigt linkTeil
1211
1225
  // die volle Gruppe über den Zeilen.
1226
+ // Ein Bundle, das in mehreren Harnesses am selben Ort liegt, ist hier ein Streifen (E95), wie
1227
+ // die Skill-Zeilen: Schlüssel ist Name plus Quelle, gleichnamige Bundles aus zwei Quellen
1228
+ // bleiben getrennt.
1229
+ var bundleGruppen = {}, bundleReihenfolge = [];
1212
1230
  teile.forEach(function (z) {
1213
1231
  (z.bundles || [])
1214
1232
  .filter(function (b) { return b.skills.length > 0; })
1215
- .slice()
1216
- .sort(function (a, b) { return a.name.localeCompare(b.name, 'de'); })
1217
- .forEach(function (b) { teil.appendChild(bundleStreifen(b, z)); });
1233
+ .forEach(function (b) {
1234
+ var schluessel = b.name + '\u0000' + b.quelleText;
1235
+ if (!bundleGruppen[schluessel]) { bundleGruppen[schluessel] = []; bundleReihenfolge.push(schluessel); }
1236
+ bundleGruppen[schluessel].push({ b: b, z: z });
1237
+ });
1218
1238
  });
1239
+ bundleReihenfolge
1240
+ .sort(function (a, b) { return bundleGruppen[a][0].b.name.localeCompare(bundleGruppen[b][0].b.name, 'de'); })
1241
+ .forEach(function (k) { teil.appendChild(bundleStreifen(bundleGruppen[k])); });
1219
1242
 
1220
1243
  var kopf = e('div', 'linkkopf');
1221
1244
  kopf.appendChild(e('span'));
@@ -1612,12 +1635,24 @@
1612
1635
 
1613
1636
  /** Entfernen des ganzen Bundles an einem Ziel (E69): alle seine Links auf einmal. */
1614
1637
  function frageBundleEntfernen(b, ziel) {
1615
- entfernenKontext = { art: 'bundle', bundle: b.name, ziel: ziel };
1638
+ entfernenKontext = { art: 'bundle', bundle: b.name, ziele: [ziel] };
1616
1639
  $('dx-titel').textContent = 'Bundle ' + b.name + ' entfernen?';
1617
1640
  $('dx-text').textContent = zahlwort(b.skills.length, 'Link', 'Links') + ' aus ' + zielTitel({ ziel: ziel })
1618
1641
  + ' verschwinden: ' + b.skills.join(', ') + '. Die Checkouts bleiben liegen, bis kein Link mehr darauf zeigt.';
1619
1642
  zeige($('d-entfernen'));
1620
1643
  }
1644
+ /** Entfernen eines Bundles in allen Harnesses seines Streifens (E95): `treffer` wie bei
1645
+ bundleStreifen, der Dialog nennt die Harnesses mit ihrer Linkzahl und die Mitglieder. */
1646
+ function frageBundleEntfernenAlle(name, mitglieder, treffer) {
1647
+ entfernenKontext = { art: 'bundle', bundle: name, ziele: treffer.map(function (t) { return t.z.ziel; }) };
1648
+ var proHarness = treffer.map(function (t) {
1649
+ return harnessName(t.z.ziel.harness) + ' ' + zahlwort(t.b.skills.length, 'Link', 'Links');
1650
+ });
1651
+ $('dx-titel').textContent = 'Bundle ' + name + ' entfernen?';
1652
+ $('dx-text').textContent = 'Das Bundle verschwindet in ' + treffer.length + ' Harnesses (' + proHarness.join(', ')
1653
+ + '): ' + mitglieder.join(', ') + '. Die Checkouts bleiben liegen, bis kein Link mehr darauf zeigt.';
1654
+ zeige($('d-entfernen'));
1655
+ }
1621
1656
  /** Entfernen einer „Alle"-Zeile (E53 Pkt. 2): entfernbareZiele sind die Ziele (voller z.ziel), in
1622
1657
  denen der Link weg soll, nichtEntfernbareHarnesse die, in denen er nur über ein Plugin hängt
1623
1658
  und liegen bleibt. Der Dialog nennt beides. */
@@ -1640,17 +1675,29 @@
1640
1675
  nachDialog($('d-entfernen'), async function (wert) {
1641
1676
  if (wert !== 'ja' || entfernenKontext === null) return;
1642
1677
  var kontext = entfernenKontext;
1643
- // Bundle als Ganzes (E69): ein Aufruf, der Kern nimmt alle Links des Bundles weg.
1678
+ // Bundle als Ganzes (E69): je Ziel ein Aufruf, der Kern nimmt alle Links des Bundles weg. Bei
1679
+ // mehreren Zielen (E95) hält ein Fehlschlag die übrigen nicht auf, rufe meldet ihn selbst.
1644
1680
  if (kontext.art === 'bundle') {
1645
- var wegB = await rufe(function () {
1646
- return window.hmgr.bundleEntfernen({
1647
- bundle: kontext.bundle,
1648
- harness: kontext.ziel.harness,
1649
- ort: kontext.ziel.ort,
1650
- });
1651
- });
1681
+ var entferntB = 0;
1682
+ var gescheitertB = [];
1683
+ for (var j = 0; j < kontext.ziele.length; j++) {
1684
+ var zielB = kontext.ziele[j];
1685
+ try {
1686
+ var wegB = await rufe(function () {
1687
+ return window.hmgr.bundleEntfernen({ bundle: kontext.bundle, harness: zielB.harness, ort: zielB.ort });
1688
+ });
1689
+ entferntB += wegB.entfernt.length;
1690
+ } catch (fehler) {
1691
+ gescheitertB.push(harnessName(zielB.harness));
1692
+ }
1693
+ }
1652
1694
  await ladeAlles();
1653
- melde('Bundle ' + kontext.bundle + ' entfernt, ' + zahlwort(wegB.entfernt.length, 'Link', 'Links') + ' weniger.');
1695
+ if (gescheitertB.length === 0) {
1696
+ melde('Bundle ' + kontext.bundle + ' entfernt, ' + zahlwort(entferntB, 'Link', 'Links') + ' weniger.');
1697
+ } else if (kontext.ziele.length > 1) {
1698
+ melde('Bundle ' + kontext.bundle + ' blieb in ' + gescheitertB.join(', ') + ' liegen, '
1699
+ + zahlwort(entferntB, 'Link', 'Links') + ' weniger.');
1700
+ }
1654
1701
  return;
1655
1702
  }
1656
1703
  // Ein Fehlschlag in einem Harness hält die übrigen nicht auf: rufe hat ihn schon gemeldet, die
@@ -1998,10 +1998,11 @@ export class Anwendungsfaelle {
1998
1998
  * Pfade, in die ein Link zeigt. Gelesen wird wie beim Ist-Zustand (E19): die Ziele der
1999
1999
  * vorhandenen Harnesses, die Arbeitsverzeichnisse aus dem Zustand. Ein Link, dessen Quelle nicht
2000
2000
  * im Zustand steht, zeigt trotzdem in einen Checkout und hält ihn.
2001
+ * Gelesen werden nur die Einträge, deshalb ohne Plugin-Abfrage (ein Prozess je Ziel, E94).
2001
2002
  */
2002
2003
  async belegteCheckoutPfade() {
2003
2004
  const pfade = new Set();
2004
- for (const zielZustand of await this.istZustand())
2005
+ for (const zielZustand of await this.istZustand({ plugins: false }))
2005
2006
  for (const eintrag of zielZustand.eintraege) {
2006
2007
  if (eintrag.art === 'link')
2007
2008
  pfade.add(path.resolve(eintrag.link.checkout.pfad));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hmgr",
3
- "version": "0.0.25",
3
+ "version": "0.0.27",
4
4
  "description": "Harness Manager: Skills und Plugins für AI-Harnesses verwalten",
5
5
  "license": "MIT",
6
6
  "author": "Tim Kaufmann",