sync: global→pool, pool-guard raus, Session-Watcher-Setup, verbotenes Wort Ehrlich
This commit is contained in:
@@ -0,0 +1 @@
|
||||
.ai-control-running
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"pool": "privateDefault",
|
||||
"terminal": {
|
||||
"theme": "one-dark",
|
||||
"icon": "/Users/marcus.hinz/projects/claude-app-builder-4-mac/icons/08-07.png",
|
||||
"title": "08-07"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
.ai-control-running
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"pool": "privateDefault"
|
||||
}
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# connect-test — prüft, ob claude mit der aktuellen Env authentifizieren und antworten kann.
|
||||
# Exit 0 = Verbindung ok. Für Negativtest mit ungültigem Key:
|
||||
# ANTHROPIC_API_KEY=sk-ant-ungueltig connect-test
|
||||
set -euo pipefail
|
||||
|
||||
"${CLAUDE_BIN:-$HOME/.local/bin/claude}" -p 'Antworte nur mit: OK' --model claude-sonnet-5
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
# kc-backup — sichert das Secret des Claude-Code-Keychain-Eintrags in eine Datei.
|
||||
# Ablage außerhalb des Git-Repos (Default: ~/.ssh), damit das Secret nie committet wird.
|
||||
# Usage: kc-backup [zieldatei]
|
||||
set -euo pipefail
|
||||
|
||||
dest=${1:-$HOME/.ssh/claude-keychain-backup.json}
|
||||
security find-generic-password -s "Claude Code-credentials" -a "$USER" -w > "$dest"
|
||||
chmod 600 "$dest"
|
||||
echo "Keychain-Secret gesichert nach: $dest ($(wc -c < "$dest" | tr -d ' ') Bytes)"
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# kc-delete — löscht den Claude-Code-Keychain-Eintrag.
|
||||
# Vorher kc-backup ausführen; zurückspielen mit kc-restore.
|
||||
set -euo pipefail
|
||||
|
||||
security delete-generic-password -s "Claude Code-credentials" -a "$USER"
|
||||
echo "Keychain-Eintrag 'Claude Code-credentials' gelöscht."
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
# kc-restore — spielt das mit kc-backup gesicherte Secret in den Keychain zurück.
|
||||
# -U aktualisiert einen ggf. vorhandenen Eintrag statt zu scheitern.
|
||||
# Usage: kc-restore [backupdatei]
|
||||
set -euo pipefail
|
||||
|
||||
src=${1:-$HOME/.ssh/claude-keychain-backup.json}
|
||||
security add-generic-password -U -s "Claude Code-credentials" -a "$USER" -w "$(cat "$src")"
|
||||
echo "Keychain-Eintrag aus $src wiederhergestellt."
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
# kc-status — zeigt Zustand des Claude-Code-Keychain-Eintrags und der Auth-Env.
|
||||
# mdat = letzte Änderung des Eintrags; ändert sich, wenn eine Session den Keychain beschreibt.
|
||||
set -euo pipefail
|
||||
|
||||
echo "== Keychain-Eintrag 'Claude Code-credentials' =="
|
||||
security find-generic-password -s "Claude Code-credentials" -a "$USER" 2>&1 | grep -E '"(mdat|cdat)"' || echo "kein Eintrag vorhanden"
|
||||
|
||||
echo "== Auth-Env dieser Shell =="
|
||||
env | grep -E '^(ANTHROPIC_API_KEY|CLAUDE_CODE_OAUTH_TOKEN|CLAUDE_CONFIG_DIR)=' | sed -E 's/=(.).*/=\1…/' || echo "keine Auth-Env gesetzt"
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
# oauth-configdir-test — prüft, ob claude auf macOS die .credentials.json aus
|
||||
# CLAUDE_CONFIG_DIR liest, wenn kein Keychain-Eintrag existiert.
|
||||
# Ablauf: Backup → Keychain löschen → claude mit bereinigter Auth-Env →
|
||||
# Nachkontrollen → Restore. Restore läuft auch bei fehlgeschlagenem Testlauf.
|
||||
# Usage: oauth-configdir-test [pool] (Default: Mx9Privat)
|
||||
set -u
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
pool=${1:-Mx9Privat}
|
||||
pooldir="$HOME/claude-pools/$pool"
|
||||
|
||||
bin/kc-backup || exit 1
|
||||
bin/kc-delete || exit 1
|
||||
|
||||
echo "== Testlauf: Env ohne ANTHROPIC_API_KEY/CLAUDE_CODE_OAUTH_TOKEN, CLAUDE_CONFIG_DIR=$pooldir =="
|
||||
env -u ANTHROPIC_API_KEY -u CLAUDE_CODE_OAUTH_TOKEN \
|
||||
CLAUDE_CONFIG_DIR="$pooldir" \
|
||||
"${CLAUDE_BIN:-$HOME/.local/bin/claude}" -p 'Antworte nur mit: OK' --model claude-sonnet-5
|
||||
echo "EXIT: $?"
|
||||
|
||||
echo "== credentials-Datei nach Lauf (#10039: darf nicht gelöscht sein) =="
|
||||
ls -la "$pooldir/.credentials.json"
|
||||
|
||||
echo "== Keychain nach Lauf (es darf KEIN Eintrag entstanden sein) =="
|
||||
bin/kc-status
|
||||
|
||||
echo "== Restore =="
|
||||
bin/kc-restore
|
||||
rm "$HOME/.ssh/claude-keychain-backup.json"
|
||||
bin/kc-status
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
@@ -1,3 +1,7 @@
|
||||
# Memory Index
|
||||
|
||||
- [Multi-Account & Keychain](multi-account-keychain.md) — Keychain trennt nicht pro CLAUDE_CONFIG_DIR; Tokens pro Instanz via Env
|
||||
- [Go-Pflicht](feedback-go-pflicht.md) — weitreichende Änderungen nie ohne ausdrückliches Go; eine Rückfrage von Marcus ist kein Go (Vorfall 2026-07-04)
|
||||
- [Terminal-Tests mit 08-07](feedback-terminal-test-08-07.md) — ABSOLUTES VERBOT: nie ein Terminal für/aus ai-control starten (killt die eigene Session, 3× Kontext verloren am 2026-07-04). Terminal-Tests nur mit 08-07 und nur auf ausdrückliche Ansage
|
||||
|
||||
- [Multi-Account & Keychain](multi-account-keychain.md) — Stand 2.1.199: suffixierter Keychain-Eintrag pro Config-Dir verifiziert; Pools umbenannt, Keychain-Endstand ein Eintrag 096c4ef9 (privateDefault); Kaltstart über Starter läuft (2026-07-04), Qualität laut Marcus noch nicht zufriedenstellend
|
||||
- [Pool-Setup Stand](ai-control-pool-setup.md) — Layout ~/.config/ai-control/pools, Starter, alle Projekte auf privateDefault; seit 2026-07-04 eingebautes Terminal in der App (xterm.js + portable-pty, startet claude-sync), offene Punkte
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
---
|
||||
name: ai-control-pool-setup
|
||||
description: "Stand des Pool-Setups seit 2026-07-03 — Layout, Starter, was gelöscht wurde, offene Punkte"
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: project
|
||||
originSessionId: e108ad75-f176-43b6-901d-c3ec19ec3961
|
||||
---
|
||||
|
||||
Seit 2026-07-03 produktiv:
|
||||
|
||||
- Pools: `~/.config/ai-control/pools/<pool>/` = CLAUDE_CONFIG_DIR. `pool.json` (name, credentialType), oauth: `.credentials.json`, apikey: `apikey` + `apiKeyHelper` in pool-`settings.json`. Pools (umbenannt 2026-07-03 abends): privateDefault (vorher Mx9Privat; oauth), apiDefault (vorher TestWürth; apikey — 2026-07-03 kurz auf oauth, am selben Tag zurück auf apikey via `apiKeyHelper` in Pool-settings.json; model claude-sonnet-5). Alle 7 Projekte → privateDefault; apiDefault derzeit ohne Projekt. Pool-Wechsel eines Projekts = nur noch `ai-control.json` ändern (einzige Quelle; zieht beim nächsten Start). Pool-Umbenennung ändert den Pfad und damit den Keychain-Suffix — alte Einträge greifen dann nicht mehr.
|
||||
- `CLAUDE.md`, `commands/`, `settings.json` liegen als physische Kopien in jedem Pool — bewusst poolspezifisch, keine Symlinks.
|
||||
- Zuordnung: `~/claude-projects/<projekt>/ai-control.json` `{ "pool": ... }`.
|
||||
- Starter: `~/Applications/Ghostty-<projekt>.app`, `LSEnvironment` setzt nur noch XDG_CONFIG_HOME (stabil, nie poolabhängig). Alle Ghostty-Configs starten `command = ~/.local/bin/claude-sync` (ggf. mit `--add-dir`-Args). `claude-sync` löst seit 2026-07-04 den Pool selbst auf (liest `./ai-control.json` im CWD, exportiert `CLAUDE_CONFIG_DIR`, laut scheiternd ohne Pool), macht git pull davor und commit+push danach. `claude-start` ist gelöscht — in `claude-sync` integriert. Env/plist tragen keinen Pool mehr.
|
||||
- Pool-Guard (seit 2026-07-04): `claude-sync` schreibt Sentinel `.ai-control-running` in den Projekt-Root (Inhalt pool=CLAUDE_CONFIG_DIR, pid; FD offen gehalten, nach claude-Ende gelöscht, in .gitignore). Vorab-Check (Endstand 2026-07-03 spät): Fensterzahl statt Prozesszustand, ohne Apple-Events — `ghostty-wincount <app-pid>` (Swift-Helfer, CGWindowListCopyWindowInfo onScreenOnly + Layer 0; Binary `~/.local/bin/ghostty-wincount`, Quelle `~/claude-projects/robotunits/bin/ghostty-wincount.swift`; App-pid via ps+grep auf den App-Pfad). Das Skript läuft selbst in Fenster 1; ≥2 → Arbeitsfenster existiert → `open -a` (Launch Services, kein Prompt) + 4 s + Exit 0; sonst → Sentinel-pid und FD-Holder kill -9, Sentinel kommentarlos löschen, normal starten. Gescheiterte Vorstufen: tty-Heuristik (Zombie behält totes tty), Schreiber-PID-Check (claude-sync-Bash überlebt Ghosttys X-Close manchmal kopflos), osascript count/activate (Automation-Prompt „App X will App Y steuern" = NOGO). Bekannte Grenze: minimierte/Space-fremde Fenster zählen als unsichtbar. Traps in claude-sync: EXIT löscht Sentinel, HUP/TERM killt claude (claude läuft als Hintergrund-Kind mit `<&0` — sonst stdin=/dev/null! — und `wait`), INT no-op; greifen aber bei Ghostty-X/Quit oft nicht (hartes Kill), Rest-Aufräumen beim nächsten Start ist der Normalfall. Alle 7 Ghostty-Configs (`~/.config-ghostty/<projekt>/ghostty/config`): `wait-after-command = false`; claude-sync zeigt Schlussmeldungen per sleep (2 s aktivieren, 3 s Ende, 5 s Fehler), dann schließt das Fenster selbst. SessionStart-Hook `~/claude-projects/robotunits/bin/pool-guard` in allen 7 Projekt-settings.json: Sentinel fehlt / Pool-Mismatch / Schreiber-PID tot → rot blinkender Banner auf /dev/tty + kill des claude-Elternprozesses. RAW-Nutzung außerhalb der Projekte bleibt frei; RAW-Start IM Projekt wird beendet. Achtung: greift auch bei /clear in Sessions, die noch ohne Sentinel gestartet wurden.
|
||||
- Gelöscht: `~/.claude` (komplett), Keychain-Eintrag `Claude Code-credentials`, `~/claude-pools`. Unterhaltungen (90 MB) + `history.jsonl` nach Mx9Privat umgezogen — `/resume` pro Pool.
|
||||
- App-Code (`~/projects/ai-control`, Tauri): Kernlogik mit injizierbarem Home, 22 Tests (`./build.sh`-Toolchain: CARGO_HOME=~/tools/.cargo; node via fnm, nur in interaktiver zsh). Commands unassign_pool/create_project/delete_project, seit 2026-07-04 restart_project (osascript-Quit → warten → open) + Modal in ProjectList: nach Umhängen eines laufenden Projekts Restart-Angebot inkl. Hinweis, dass der claude-sync-Push beim Abschießen entfällt.
|
||||
- Eingebautes Terminal (2026-07-04, Prototyp, funktioniert laut Marcus): `src-tauri/src/terminal.rs` (portable-pty, Commands open_terminal/term_start/term_write/term_resize) + `terminal.html`/`src/terminal.ts` (xterm.js, Output base64-Events, Capability `term-*`). „Terminal"-Button in ProjectList öffnet pro Klick ein eigenes Fenster; PTY startet `zsh -ic claude-sync` im Projektordner — Pool/Sentinel/git-Sync unverändert bei claude-sync, App setzt kein CLAUDE_CONFIG_DIR. Fenster-X killt Kind + schließt PTY (HUP wie Ghostty-X, Abschluss-Push entfällt). Damit Weg frei, die Ghostty-Starter abzulösen ("wir haben alles in der Hand"). Offen: Scrollback-Restore, Fensterposition merken.
|
||||
- Stand 2026-07-04 abends, alles committed+gepusht (bis inkl. Todo-Feature): UI komplett auf Catppuccin-Mocha-Token + JetBrains Mono (frontend-design-Skill; Plugin `frontend-design` war kaputt — installPaths in installed_plugins.json zeigten nach Pool-Umbenennung noch auf Mx9Privat, gefixt), i18n de/en (vue-i18n, Umschalter im Header). Pools: löschbar mit Zuordnungs-Auflösung, „Neu anmelden" löscht vorher den suffixierten Keychain-Eintrag (nur bei ungenutztem Pool, Warn-Dialog), Renew entfernt (Datei-Refresh-Token tot, Keychain hat Vorrang), hasCredentials (apikey-Dateicheck) mit Start-Blockierung. Verbrauch-Tab: usage_stats parst <pool>/projects/*/*.jsonl (Dedup message.id+requestId, Preistabelle Fable 10/50 Opus 5/25 Sonnet 3/15 Haiku 1/5, Cache 1.25x/0.1x), Pool-Zeilen aggregiert + Projekte aufklappbar; apiDefault hat keinerlei Transcripts (Marcus' apiKey-Abfragen vom 04.07. liefen nachweislich nicht über claude-code auf diesem Rechner — Console zeigt die Wahrheit). Projekt-Wizard (create_project_full: Scaffold nach 08-07-Muster inkl. pool-guard-Hook, Arbeitsordner anlegen/verknüpfen) + Löschen (Guard bei laufender Session, optional Arbeitsordner aus additionalDirectories mit). Todo-Feature nur Projektebene (robotunits-Muster: OFFENE-PUNKTE.md + jq-SessionStart-Hook, zuschaltbar in Wizard+Zahnrad; Pool-Ebene bewusst nicht). App heißt ai-control (Cargo-Paket umbenannt), Hand-Icon (Tray per include_bytes + Template-Icon; Dock-Icon der Terminals via NSApplication nur in RunEvent::Ready). 38 Rust-Tests. Offen/geplant: Baustein-Bibliothek (CLAUDE.md-Marker-Mechanismus, Konzept steht: ~/.config/ai-control/blocks/, verwaltete Abschnitte zwischen ai-control:block-Markern), weitere Wizard-Optionen, Split privates Repo / offizielles GitHub-Repo (Ist-Stand als Initial-Commit ohne History; OAuth-Login-Teil wegen ToS-Grauzone fürs öffentliche Repo rausnehmen — apiKey-Teil unkritisch), Vitest für UI-Tests (Vorschlag steht), Dock-Name macOS/Wayland „später überlegen".
|
||||
- Alter Zwischenstand (Commit f747379 = Terminal + Start/Beenden-Button): (a) ProjectList: ein Button pro Zeile — grün „Starten" (open_terminal) / rot „Beenden" (neues Command stop_project: SIGTERM auf exakte PIDs per `pgrep -f -- "--terminal <projekt>$"`, sonst Ghostty-Quit; NIE Quit über die App-Bundle-ID — träfe die Haupt-App); is_running = Ghostty ODER --terminal-Prozess; Status-Kreis ohne Prozess unsichtbar. (b) Terminal-Config-Dialog (Zahnrad): `terminal: { theme, icon, title }` in projekt-`ai-control.json` (pool-Feld jetzt Option, Datei bleibt bei unassign wenn terminal gesetzt); 5 Themes (mocha/dracula/solarized-dark/gruvbox/one-dark, Paletten in terminal.ts, Fenster-BG gespiegelt in terminal.rs theme_background — muss synchron bleiben); Icon = PNG/ICNS-Pfad via tauri-plugin-dialog-Picker, gesetzt per NSApplication.applicationIconImage (objc2, nur in RunEvent::Ready — in setup() überschreibt macOS es wieder); Titel: Fenstertitel + Header, leer → Projektname. `tauri::generate_context!` darf nur 1× expandieren (_EMBED_INFO_PLIST, fällt nur im Release-Build auf).
|
||||
- Dock-Grenze macOS: Hover-Label im Dock = Bundle-Name, zur Laufzeit nicht öffentlich änderbar; Wrapper-Bundle pro Projekt von Marcus abgelehnt („verlieren zu viel"). Windows/X11: Titel+Icon greifen fensterbasiert; Wayland-Docks bräuchten .desktop pro Projekt (xdg-toplevel-icon nur KDE). → „da müssen wir was überlegen, nicht jetzt".
|
||||
|
||||
**Why:** Getrennte Zugänge pro Pool, [[multi-account-keychain]].
|
||||
|
||||
**Agenda 2026-07-04:** Start/Stopp-Architektur grundsätzlich besprechen — Stand vom 2026-07-03 spät (wincount/kill-9/Sentinel-Reste) funktioniert im Test, ist aber Flickwerk um Ghosttys unzuverlässiges Kill-Verhalten herum; Marcus will eine saubere Lösung statt Workarounds. Außerdem: Pool-Guard + Kaltstart über Starter testen; App: UI aufräumen, Projekte managen, Defaults/Standardverhalten (z. B. Todolist); Linux gesondert; Open-Source-Frage („works for my workflow") entschieden nach Feinschliff; außerdem Ghostty und Zed besprechen. Stand App: beta-0.8 gepusht (Tray statt Dock, Autostart-Schalter, Fenster startet unsichtbar, Restart-Dialog).
|
||||
|
||||
**How to apply — offen (Stand 2026-07-03):** (1) Sync-Konzept für `~/.config/ai-control` inkl. Unterhaltungen, Secrets-Frage (git). (2) UI kennt die drei neuen Commands nicht. (3) Erledigt durch Integration in `claude-sync` (2026-07-04): der „Flicker" betraf das gelöschte `claude-start`; `claude-sync` läuft in den Ghostty-Wrappern nachweislich interaktiv.
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
name: feedback-go-pflicht
|
||||
description: Weitreichende Änderungen NIE ohne ausdrückliches Go; eine Rückfrage von Marcus ist kein Go
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: feedback
|
||||
originSessionId: 6c3fc02d-bc5c-4476-9384-8062394a85ff
|
||||
---
|
||||
|
||||
Weitreichende Änderungen (Verhaltensänderungen im Backend, Löschlogik, alles mit Datenverlust-Potenzial) nie umsetzen, bevor Marcus ausdrücklich Go gegeben hat. Eine Rückfrage oder Diskussionsfrage von Marcus („was machen wir dann mit X?") ist KEIN Go — Frage beantworten, dann stoppen und warten.
|
||||
|
||||
**Why:** 2026-07-04: Nach Marcus' Rückfrage zur Pool-Löschung habe ich direkt implementiert; Marcus hat abgebrochen („ICH HATTE NICHT GESAGT, DASS DU DAS TUN SOLLST"). Sein „ja" galt dem Plan davor, seine Folgefrage hat die Diskussion wieder geöffnet.
|
||||
|
||||
**How to apply:** Bei jedem Plan mit offener Designfrage: erst alle offenen Punkte klären, dann explizites Go für den Gesamtumfang abwarten. Antwort auf eine Frage endet mit der Antwort, nicht mit Tool-Calls.
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: feedback-terminal-test-08-07
|
||||
description: "Terminal-/Restart-Tests der App immer mit Projekt 08-07, nie mit ai-control"
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: feedback
|
||||
originSessionId: dd1d2798-9e9a-4e95-bf63-7793e7801020
|
||||
---
|
||||
|
||||
Für Tests des eingebauten Terminals und von restart_project immer das Projekt **08-07** als Beispiel nehmen, nie **ai-control**.
|
||||
|
||||
**Why:** Die Arbeitssession läuft selbst im Projekt ai-control — ein Terminal-/Restart-Test dort killt die eigene Session und der Kontext ist weg.
|
||||
|
||||
**How to apply:** In Testanweisungen, Beispielaufrufen und UI-Tests (`open_terminal`, `restart_project`) als Projektname `08-07` verwenden. Siehe [[ai-control-pool-setup]].
|
||||
|
||||
**Stand 2026-07-04:** Die Session läuft selbst im eingebauten Terminal der App (xterm.js + portable-pty). Ein Neustart/Beenden der App killt die Session direkt — die 08-07-Regel schützt nur gegen `restart_project ai-control`, nicht gegen Tests auf App-Ebene.
|
||||
|
||||
**Verschärfung (2026-07-04, nach erneutem Vorfall):** Alles, was den App-Prozess oder das eigene Terminal berührt, ist tabu — App-Neustart, App-Build+Relaunch, Kill von Electron-/pty-Prozessen, `pkill`/`kill` auf Prozesse, deren Zugehörigkeit nicht geprüft ist. Vor jedem Kill/Restart erst prüfen, ob der Zielprozess in der eigenen Prozesskette hängt. Solche Tests laufen nur nach Ansage von Marcus und dann in 08-07 bzw. einer separaten App-Instanz.
|
||||
|
||||
**Absolutes Verbot (2026-07-04, dritter Vorfall — Kontext erneut verloren):** NIE ein Terminal für oder aus ai-control starten — kein `open_terminal ai-control`, kein Terminal-Start über die App, keine Ausnahme „nur kurz testen". Jeder Terminal-Start, der ai-control betrifft, killt diese Session. Terminal-Funktionen werden ausschließlich mit 08-07 getestet, und nur wenn Marcus es ausdrücklich anweist.
|
||||
@@ -1,14 +1,20 @@
|
||||
---
|
||||
name: multi-account-keychain
|
||||
description: macOS-Keychain trennt Claude-Code-Credentials NICHT pro CLAUDE_CONFIG_DIR — Multi-Account nur über Env-Tokens
|
||||
description: "Multi-Account auf macOS — Stand 2.1.199: pro CLAUDE_CONFIG_DIR eigener suffixierter Keychain-Eintrag; .credentials.json-Ansatz überholt"
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: project
|
||||
originSessionId: 5c4c75da-b313-4740-9988-49533ba77ed1
|
||||
originSessionId: e108ad75-f176-43b6-901d-c3ec19ec3961
|
||||
---
|
||||
|
||||
Verifiziert 2026-07-03: Claude Code nutzt auf macOS einen einzigen Keychain-Eintrag (Service `Claude Code-credentials`, Account = Unix-User) für alle `CLAUDE_CONFIG_DIR`-Profile. Mehrere OAuth-Logins überschreiben sich gegenseitig (Issue anthropics/claude-code#20553); der Datei-Fallback `.credentials.json` wird auf macOS gelöscht (#10039).
|
||||
ÜBERHOLT (galt bis Version vor 2.1.199): claude las die `.credentials.json` direkt aus `CLAUDE_CONFIG_DIR` (verifiziert 2026-07-03 vormittags, Test `bin/oauth-configdir-test`).
|
||||
|
||||
**Why:** ai-control soll 3–4 Claude-Zugänge (Abo + Kunden-API-Keys) strikt getrennt auf einem Rechner betreiben.
|
||||
Stand 2026-07-03 abends, Version 2.1.199 (native Installation): Neu-Login war nötig. Die `.credentials.json` im Pool `Mx9Privat` ist weg; claude speichert jetzt pro Config-Dir einen Keychain-Eintrag `Claude Code-credentials-<suffix>`, Suffix = erste 8 Hex-Zeichen von SHA-256 über den `CLAUDE_CONFIG_DIR`-Pfad (Mx9Privat → `a014e206`, TestWürth → erwartet `4c0ad9a9`, ggf. NFC/NFD-Frage wegen „ü"). Ohne gesetztes `CLAUDE_CONFIG_DIR` entsteht der unsuffixierte Eintrag `Claude Code-credentials` plus `~/.claude`/`~/.claude.json`. Damit ist #20553 (Überschreiben) upstream gelöst — pro Pool ein eigener Eintrag. Verifiziert 2026-07-03 abends: Nach `/login` in ai-control (Mx9Privat) lief wuerth-plato (gleicher Pool) ohne erneutes Login — Eintrag `a014e206` wird poolweit geteilt. Keychain enthielt danach nur diesen einen Claude-Code-Eintrag (kein unsuffixierter). Zweiter Pool ebenfalls verifiziert: 08-07 (TestWürth, oauth) verlangte wie erwartet erneutes Login und erzeugte `Claude Code-credentials-4c0ad9a9` — Suffix stimmt mit der Vorab-Berechnung überein, NFC/NFD-Frage wegen „ü" damit geklärt. Keychain-Stand: genau zwei Einträge, `a014e206` (Mx9Privat) und `4c0ad9a9` (TestWürth). Multi-Account über suffixierte Keychain-Einträge funktioniert damit vollständig. Dritter Beleg: robotunits nach Umzug auf TestWürth ohne Login gestartet (Starter-Pfad hasht identisch auf `4c0ad9a9`). Mit gesetztem `CLAUDE_CONFIG_DIR` entsteht dabei kein neues `~/.claude` im Home — das gelöschte bleibt weg.
|
||||
|
||||
**How to apply:** Pro Instanz Credentials über Env setzen: `CLAUDE_CODE_OAUTH_TOKEN` (via `claude setup-token`, 1 Jahr gültig) für Abo-Zugänge, `ANTHROPIC_API_KEY` für Kunden-Keys. `CLAUDE_CONFIG_DIR` zusätzlich pro Zugang für getrennte settings/History/Projektzustand — nur nicht für Credentials verlassen.
|
||||
Umbenennung 2026-07-03 spätabends: Mx9Privat → privateDefault, TestWürth → apiDefault. Suffixe: privateDefault → `096c4ef9`, apiDefault → `15e10251`. Die alten Einträge `a014e206`/`4c0ad9a9` wurden gelöscht; kurz darauf lag `096c4ef9` im Keychain — eine laufende Session hat die Credentials unter dem neuen Pfad selbst neu geschrieben, ohne Login-Prompt. Weitere Session-Starts erzeugten keinen zusätzlichen Eintrag. Keychain-Endstand 2026-07-03: genau ein Eintrag `096c4ef9`; für apiDefault (`15e10251`) existiert noch keiner, dort ist beim ersten Start Login nötig.
|
||||
|
||||
Kaltstart-Test über die umgestellten Starter (2026-07-04): durchgeführt, funktioniert grundsätzlich (kein Login nötig), aber laut Marcus nicht in der gewünschten Qualität — worin genau der Mangel liegt, ist noch nicht festgehalten.
|
||||
|
||||
**Why:** Mehrere Claude-Zugänge (Abo + Kunden-Keys) strikt getrennt auf einem Rechner.
|
||||
|
||||
**How to apply:** Pro Pool ein Ordner als `CLAUDE_CONFIG_DIR` (siehe [[ai-control-pool-setup]]). OAuth: `.credentials.json` (0600) in den Pool-Ordner. API-Key: `apiKeyHelper` in der Pool-`settings.json` auf die Key-Datei. `CLAUDE_CODE_OAUTH_TOKEN`-Export ist unnötig.
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
{
|
||||
"autoMemoryDirectory": "~/claude-projects/limbach/memory",
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"command": "jq -Rs '{systemMessage: ., hookSpecificOutput:{hookEventName:\"SessionStart\", additionalContext: .}}' /Users/marcus.hinz/claude-projects/limbach/OFFENE-PUNKTE.md",
|
||||
"type": "command"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"permissions": {
|
||||
"additionalDirectories": [
|
||||
"~/projects/limbach"
|
||||
],
|
||||
"allow": [
|
||||
"Edit(~/projects/limbach/**)",
|
||||
"Edit(~/claude-projects/limbach/**)"
|
||||
],
|
||||
"additionalDirectories": [
|
||||
"~/projects/limbach"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
.ai-control-running
|
||||
@@ -0,0 +1,3 @@
|
||||
# Offene Punkte — bei jedem Start prüfen und abhaken
|
||||
|
||||
Keine offenen Punkte.
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"pool": "privateDefault",
|
||||
"terminal": {
|
||||
"icon": "/Users/marcus.hinz/projects/claude-app-builder-4-mac/icons/limbach.png"
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,6 @@ Plan — ein `update_scripts`-Command, der im aktuellen Projektordner die `addit
|
||||
2. **cd-Aliasse** `cd-project-root` / `cd-claude-root`: exakte Bash-Regeln je Pfad statt `cd:*`, z. B. `Bash(cd ~/projects/limbach)` und `Bash(cd ~/claude-projects/limbach)`. cwd persistiert zwischen Bash-Calls, reicht zum Springen.
|
||||
3. **Read/Edit/Write-Globs** je Verzeichnis: `Read(~/projects/limbach/**)`, `Edit(~/projects/limbach/**)`, `Write(~/projects/limbach/**)` und analog für `~/claude-projects/limbach/**`. Damit läuft Coden in genau diesen Dirs prompt-frei, außerhalb wird weiter gefragt.
|
||||
|
||||
Aufräumen: globales `Bash(cd:*)` in `~/claude-projects/global/settings.json` (Symlink-Ziel von `~/.claude/settings.json`) wieder entfernen — vom User als „Mist" bewertet. Globale git-Regeln (`git add/commit/push/…:*`) ebenfalls raus, sobald die Wrapper stehen.
|
||||
Aufräumen: globales `Bash(cd:*)` in `~/claude-projects/pool/settings.json` (Symlink-Ziel von `~/.claude/settings.json`) wieder entfernen — vom User als „Mist" bewertet. Globale git-Regeln (`git add/commit/push/…:*`) ebenfalls raus, sobald die Wrapper stehen.
|
||||
|
||||
Hintergrund: `git-sync` ist davon getrennt (synct alle Repos batch-weise, [[git-sync]]). Ursache früherer Prompts war u. a. das Bündeln von Git mit Nicht-Git-Befehlen (`cd … && ls`, `printf > datei`) in einer Zeile — Permission-Matching prüft jedes `&&`-Segment einzeln; die Wrapper umgehen das.
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"autoMemoryDirectory": "~/claude-projects/misc/memory",
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"command": "jq -Rs '{systemMessage: ., hookSpecificOutput:{hookEventName:\"SessionStart\", additionalContext: .}}' /Users/marcus.hinz/claude-projects/misc/OFFENE-PUNKTE.md",
|
||||
"type": "command"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"permissions": {
|
||||
"additionalDirectories": [
|
||||
"~/projects/misc"
|
||||
],
|
||||
"allow": [
|
||||
"Edit(~/projects/misc/**)"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
.ai-control-running
|
||||
@@ -0,0 +1,3 @@
|
||||
# Offene Punkte — bei jedem Start prüfen und abhaken
|
||||
|
||||
Keine offenen Punkte.
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"pool": "privateDefault"
|
||||
}
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
# Anker
|
||||
|
||||
- Diese Datei ist die Quelle für `~/.claude/CLAUDE.md` (Symlink). Änderungen direkt hier in `~/claude-projects/global/CLAUDE.md` vornehmen, nicht über den Symlink-Pfad.
|
||||
- Diese Datei ist die Quelle für `~/.claude/CLAUDE.md` (Symlink). Änderungen direkt hier in `~/claude-projects/pool/CLAUDE.md` vornehmen, nicht über den Symlink-Pfad.
|
||||
- Anker für projektübergreifend Gemeinsames (Checklisten, Notizen, Memory, geteilte Dateien) ist `~/claude-projects/robotunits`. Solche Dateien gehören dorthin, nicht unter `~/projects/...`.
|
||||
- Projektspezifisches (z. B. SessionStart-Hooks) bleibt im jeweiligen Projekt unter dessen `.claude/settings.json` — nicht global.
|
||||
|
||||
@@ -54,3 +54,4 @@ Nie verwenden, weder in Texten noch in Antworten:
|
||||
- „Der Clou" / „Der Witz" / „Der Hit" / „Die Pointe"
|
||||
- Sinngleiche Effekthascherei: „der Knaller", „das Highlight", „der Wow-Effekt", „die Sensation"
|
||||
- Englische Technikbegriffe nicht holprig eindeutschen (z. B. nicht „spritzen" für *inject*).
|
||||
- „Ehrlich" als Einleitung oder Anrede (z. B. „Ehrlich gesagt", „Ehrlich zum …") — stattdessen direkt die Aussage.
|
||||
@@ -5,7 +5,7 @@ description: Commit + Push aller persistent konfigurierten Projekt-Repos
|
||||
Führe genau dieses eine Kommando aus, sonst nichts:
|
||||
|
||||
```bash
|
||||
~/claude-projects/global/bin/git-sync
|
||||
~/claude-projects/pool/bin/git-sync
|
||||
```
|
||||
|
||||
Das Skript liest selbst die `permissions.additionalDirectories` aus den Settings und
|
||||
@@ -11,9 +11,10 @@
|
||||
"Bash(git mv:*)",
|
||||
"Bash(git check-ignore:*)",
|
||||
"Bash(cd:*)",
|
||||
"Bash(~/claude-projects/global/bin/git-sync:*)"
|
||||
"Bash(~/claude-projects/pool/bin/git-sync:*)"
|
||||
]
|
||||
},
|
||||
"model": "claude-fable-5[1m]",
|
||||
"enabledPlugins": {
|
||||
"frontend-design@claude-plugins-official": true,
|
||||
"swift-lsp@claude-plugins-official": true
|
||||
@@ -21,6 +22,5 @@
|
||||
"promptSuggestionEnabled": false,
|
||||
"awaySummaryEnabled": false,
|
||||
"tui": "fullscreen",
|
||||
"theme": "dark",
|
||||
"model": "claude-fable-5[1m]"
|
||||
"theme": "dark"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
.ai-control-running
|
||||
@@ -0,0 +1,338 @@
|
||||
<!--
|
||||
RSS generated by JIRA (1001.0.0-SNAPSHOT#100292-rev:f152b838bb945118c071b297741ecc5e36093b62) at Fri Jul 03 09:13:25 UTC 2026
|
||||
|
||||
It is possible to restrict the fields that are returned in this document by specifying the 'field' parameter in your request.
|
||||
For example, to request only the issue key and summary add field=key&field=summary to the URL of your request.
|
||||
-->
|
||||
<rss version="0.92" >
|
||||
<channel>
|
||||
<title>Jira adesso Group extern</title>
|
||||
<link>https://adesso-group-extern.atlassian.net</link>
|
||||
<description>This file is an XML representation of an issue</description>
|
||||
<language>en-us</language> <build-info>
|
||||
<version>1001.0.0-SNAPSHOT</version>
|
||||
<build-number>100292</build-number>
|
||||
<build-date>30-06-2026</build-date>
|
||||
</build-info>
|
||||
|
||||
<item>
|
||||
<title>[GEKO-16] Schutzzaun im Layout schließen/Schutzzaun zwischen zwei Punkten planen</title>
|
||||
<link>https://adesso-group-extern.atlassian.net/browse/GEKO-16</link>
|
||||
<project id="12341" key="GEKO">GEKO</project>
|
||||
<description><p>Dieses Ticket implementiert die interaktive Planung eines Schutzzauns zwischen zwei Punkten im 3D-Layout. Die Funktion ermöglicht das Ziehen einer Strecke, berechnet die Geometrie und generiert den Zaun als kaskadierende Baugruppe. Neu ist die intelligente Vererbungslogik: Werden PMIs als Start- oder Endpunkt genutzt, erbt der Zaun Typ und Füllung automatisch; andernfalls werden diese über ein modales Overlay abgefragt.</p>
|
||||
|
||||
<h3><a name="%F0%9F%9F%A6DefinitionofReady%C2%A0"></a><b>�� Definition of Ready</b> </h3>
|
||||
|
||||
<h4><a name="Wer%3F%C2%A0"></a><b>Wer?</b> </h4>
|
||||
|
||||
<p>Anwender des Schutzzaun-Konfigurators im 3D-Layout.</p>
|
||||
|
||||
<h4><a name="Was%3F%C2%A0"></a><b>Was?</b> </h4>
|
||||
|
||||
<ul>
|
||||
<li>Interaktives Setzen von Start- und Endpunkt (frei oder gesnappt an PMIs).</li>
|
||||
<li>Dynamische Anzeige von 3 Bemaßungen (Länge, Diagonale, Winkel) während der Mausbewegung.</li>
|
||||
<li>Intelligente Eigenschafts-Vererbung (Typ/Füllung) basierend auf Start-/End-PMIs zur Vermeidung unnötiger UI-Abfragen.</li>
|
||||
<li>Filterung von PMIs: Inkompatible End-PMIs werden nach der Auswahl des Start-PMIs ignoriert und nicht gehighlighted.</li>
|
||||
<li>Mathematische Berechnung von 2D-Länge (XZ-Ebene) und Ausrichtungswinkel.</li>
|
||||
<li>Algorithmus-gestützte Aufteilung der Strecke in Standard- und Sonderelemente.</li>
|
||||
<li>Generierung des Zauns als kaskadierender Verbund (Typ 2 Einbaubedingungen).</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h4><a name="Warum%3F%C2%A0"></a><b>Warum?</b> </h4>
|
||||
|
||||
<p>Effiziente Planung von Schutzzäunen über größere Distanzen, ohne dass der Nutzer jedes Element einzeln platzieren muss und unter Vermeidung von fehlerhaften Typen-Mischungen.</p>
|
||||
|
||||
<h4><a name="Wozu%3F%C2%A0"></a><b>Wozu?</b> </h4>
|
||||
|
||||
<p>Ein strukturierter, in den Szenegraphen integrierter Schutzzaun-Zug, mit dem offene Züge geschlossen werden können.</p></description>
|
||||
<environment></environment>
|
||||
<key id="139286">GEKO-16</key>
|
||||
<summary>Schutzzaun im Layout schließen/Schutzzaun zwischen zwei Punkten planen</summary>
|
||||
<type id="12871" iconUrl="https://adesso-group-extern.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10318?size=medium">Task</type>
|
||||
<parent id="119259">GEKO-6</parent>
|
||||
<priority id="10001" iconUrl="https://adesso-group-extern.atlassian.net/images/icons/priorities/major.svg">Major</priority>
|
||||
<status id="14794" iconUrl="https://adesso-group-extern.atlassian.net/" description="">To Do</status>
|
||||
<statusCategory id="2" key="new" colorName="blue-gray"/>
|
||||
<resolution id="-1">Unresolved</resolution>
|
||||
<assignee accountid="712020:1a31ac71-0e6f-49af-83f9-0d630a810204">Marcus Hinz</assignee>
|
||||
<reporter accountid="712020:0a2bb4c7-7da6-48f0-8264-d021465e5f0f">Lukas Hörger</reporter>
|
||||
<labels>
|
||||
</labels>
|
||||
<created>Wed, 8 Apr 2026 11:43:54 +0200</created>
|
||||
<updated>Thu, 2 Jul 2026 14:28:25 +0200</updated>
|
||||
<due></due>
|
||||
<votes>0</votes>
|
||||
<watches>0</watches>
|
||||
<attachments>
|
||||
</attachments>
|
||||
<subtasks>
|
||||
</subtasks>
|
||||
<customfields>
|
||||
<customfield id="customfield_10000" key="com.atlassian.jira.plugins.jira-development-integration-plugin:devsummarycf">
|
||||
<customfieldname>Development</customfieldname>
|
||||
<customfieldvalues>
|
||||
|
||||
</customfieldvalues>
|
||||
</customfield>
|
||||
<customfield id="customfield_10019" key="com.pyxis.greenhopper.jira:gh-lexo-rank">
|
||||
<customfieldname>Rank</customfieldname>
|
||||
<customfieldvalues>
|
||||
<customfieldvalue>0|i5ji9k:</customfieldvalue>
|
||||
|
||||
</customfieldvalues>
|
||||
</customfield>
|
||||
<customfield id="customfield_13432" key="com.atlassian.jira.plugin.system.customfieldtypes:select">
|
||||
<customfieldname>T-Shirt Size - Storypoint</customfieldname>
|
||||
<customfieldvalues>
|
||||
<customfieldvalue key="20365"><![CDATA[L]]></customfieldvalue>
|
||||
|
||||
</customfieldvalues>
|
||||
</customfield>
|
||||
<customfield id="customfield_13430" key="com.atlassian.jira.plugin.system.customfieldtypes:textarea">
|
||||
<customfieldname>�� Definition of Ready - Formale Kriterien</customfieldname>
|
||||
<customfieldvalues>
|
||||
<customfieldvalue><h3><a name="%F0%9F%93%98Funktionsbeschreibung%3A"></a><b>�� Funktionsbeschreibung:</b></h3>
|
||||
|
||||
<p><b>Input:</b> Klick-Events im 3D-Viewport und ggf. Auswahl-Events im modalen Overlay.</p>
|
||||
|
||||
<ul>
|
||||
<li><b>Verhalten / Ablauf:</b>
|
||||
<ol>
|
||||
<li><b>Startpunkt (Klick 1):</b> Nutzer setzt den ersten Punkt (Typ 1 Weltkoordinaten oder Typ 2 PMI).</li>
|
||||
<li><b>Zeichnen &amp; Filtern:</b> Unmittelbar <b>nach dem 1. Klick</b> (sofern dieser an einem PMI erfolgte) filtert die Engine den Szenegraphen. Anhand des Typs des Start-PMIs (z. B. Basic) werden alle inkompatiblen PMIs (z. B. Allround) für den aktuellen Zeichen-Modus als ungültig markiert. Während der Nutzer nun die Gummiband-Linie zum Endpunkt zieht, werden diese inkompatiblen PMIs konsequent nicht gehighlighted und können nicht angeklickt werden.</li>
|
||||
<li><b>Endpunkt (Klick 2):</b> Nutzer setzt den zweiten Punkt.</li>
|
||||
<li><b>Vererbungslogik &amp; Konfiguration:</b> Die Engine entscheidet anhand folgender Logik-Matrix, woher die Parameter (Typ/Füllung) stammen:
|
||||
<ul>
|
||||
<li><b>Start: Frei | Ende: Frei</b> → Keine Vererbung. Das modale Auswahl-Overlay öffnet sich. Standard-Elemente werden nach Bestätigung generiert.</li>
|
||||
<li><b>Start: PMI | Ende: Frei</b> → Vererbung der Properties vom Start-PMI. Das Overlay erscheint <b>nicht</b>.</li>
|
||||
<li><b>Start: Frei | Ende: PMI</b> → Vererbung der Properties vom End-PMI. Das Overlay erscheint <b>nicht</b>.</li>
|
||||
<li><b>Start: PMI | Ende: PMI</b> → Vererbung der Properties vom Start-PMI. (Typengleichheit ist durch das Filtern in Schritt 2 bereits sichergestellt). Das Overlay erscheint <b>nicht</b>.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><b>Geometrie-Berechnung:</b> Y-Offset und Rotationen werden ignoriert. Absolute Strecke über Pythagoras ({{L = √(Δx² + Δz²)}}), Winkel über <tt>atan2(Δz, Δx)</tt> (auf XZ-Ebene projiziert).</li>
|
||||
<li><b>Element-Aufteilung:</b> Die Logik <tt>berechnung_aufteilung_laenge</tt> ermittelt die Rasterelemente <em>(siehe Algorithmus-Abschnitt unten)</em>.</li>
|
||||
<li><b>Generierung:</b> Elemente werden kaskadierend via PMI (Typ 2) eingebaut.</li>
|
||||
<li><b>Validierung:</b> Trigger der lokalen Validierungsengine.</li>
|
||||
</ol>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h4><a name="Algorithmus%3AElementAufteilung%28%7B%7Bberechnungaufteilunglaenge%7D%7D%29"></a>Algorithmus: Element-Aufteilung (<tt>berechnung_aufteilung_laenge</tt>)</h4>
|
||||
|
||||
<ul>
|
||||
<li><b>1. Grundkonfiguration:</b>
|
||||
<ul>
|
||||
<li><b>Typ "Basic":</b> Der Elementabstand wird als Parameter übergeben; es gibt keinen Steherzusatz (0 mm).</li>
|
||||
<li><b>Typ "Allround":</b> Fester Elementabstand von <b>11 mm</b>, Steherzusatz von <b>51 mm</b> pro Element.</li>
|
||||
<li><b>Türen:</b> Ist eine Tür in der Konfiguration enthalten, wird pauschal ein Maß von <b>1124 mm</b> (zzgl. Elementabstand) von der Gesamtbreite abgezogen.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><b>2. Standardelemente (Greedy):</b> Der Raum wird systematisch mit den größten passenden Standardelementen gefüllt (Priorität: 1507, 1034, 776, 518 mm).</li>
|
||||
<li><b>3. Dead Zone Correction (Todeszone):</b> Bleibt eine kritische Restbreite (zwischen 43 mm und Mindestbreite der Füllung) übrig, wird das kleinste bereits verplante Element downgradet (z. B. 776 mm -&gt; 518 mm) oder gelöscht, um Platz für ein produzierbares Sonderelement zu schaffen.</li>
|
||||
<li><b>4. Sonderelement (Rasterung):</b> Aus der Restbreite wird im <b>43-mm-Raster</b> das finale Passstück ermittelt. Restlücken &lt; 43 mm werden als Toleranz ignoriert.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<p><b>Pseudocode der Aufteilungslogik:</b></p>
|
||||
|
||||
<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent panelContent">
|
||||
<pre>FUNCTION calculate_width_distribution(type, has_door, gap_input, total_width, filling_type)
|
||||
INITIALIZE results AS dictionary
|
||||
|
||||
// --- 1. Base Setup &amp; Door Deduction ---
|
||||
IF type == "Basic" THEN
|
||||
gap = gap_input
|
||||
post_addition = 0
|
||||
ELSE IF type == "Allround" THEN
|
||||
gap = 11
|
||||
post_addition = 51
|
||||
END IF
|
||||
|
||||
IF has_door == TRUE THEN
|
||||
deduction = 1124 + gap
|
||||
results["door_count"] = 1
|
||||
ELSE IF type != "0" THEN
|
||||
deduction = 51
|
||||
results["door_count"] = 0
|
||||
ELSE
|
||||
deduction = 0
|
||||
results["door_count"] = 0
|
||||
END IF
|
||||
|
||||
remaining_width = total_width - deduction
|
||||
test_width = remaining_width
|
||||
|
||||
// --- 2. Distribute Standard Elements (Greedy Approach) ---
|
||||
STANDARD_SIZES = [1507, 1034, 776, 518]
|
||||
element_counts = {1507: 0, 1034: 0, 776: 0, 518: 0}
|
||||
|
||||
FOR EACH size IN STANDARD_SIZES DO
|
||||
required_width = size + post_addition
|
||||
WHILE test_width &gt;= required_width DO
|
||||
element_counts[size] = element_counts[size] + 1
|
||||
remaining_width = test_width - required_width
|
||||
test_width = remaining_width - gap
|
||||
END WHILE
|
||||
END FOR
|
||||
|
||||
// --- 3. Dead Zone Correction ---
|
||||
min_special_element = (IF filling_type == 0 THEN 174 ELSE 131) + post_addition
|
||||
|
||||
IF test_width &gt;= 43 AND test_width &lt;= min_special_element THEN
|
||||
smallest_assigned = FIND_SMALLEST_ASSIGNED_ELEMENT(element_counts)
|
||||
next_smaller = FIND_NEXT_SMALLER_SIZE(STANDARD_SIZES, smallest_assigned)
|
||||
|
||||
IF smallest_assigned EXISTS THEN
|
||||
element_counts[smallest_assigned] = element_counts[smallest_assigned] - 1
|
||||
|
||||
IF next_smaller EXISTS THEN
|
||||
// Downgrade to next smaller standard element
|
||||
element_counts[next_smaller] = element_counts[next_smaller] + 1
|
||||
difference = smallest_assigned - next_smaller
|
||||
remaining_width = remaining_width + difference
|
||||
test_width = test_width + difference
|
||||
ELSE
|
||||
// Lowest element was 518, remove it completely
|
||||
freed_space = post_addition + smallest_assigned + gap
|
||||
remaining_width = remaining_width + freed_space
|
||||
test_width = test_width + freed_space
|
||||
END IF
|
||||
END IF
|
||||
END IF
|
||||
|
||||
SAVE element_counts TO results
|
||||
test_width = test_width - post_addition
|
||||
|
||||
// --- 4. Special Element (Sonderelement) Calculation ---
|
||||
special_element_width = 0
|
||||
test_width_int = FLOOR(test_width)
|
||||
|
||||
IF test_width_int &lt; 43 THEN
|
||||
special_element_width = 0
|
||||
ELSE IF test_width_int &gt;= 518 AND test_width_int &lt; 561 THEN
|
||||
results["518_count"] = results["518_count"] + 1
|
||||
remaining_width = remaining_width - 518 - gap - post_addition
|
||||
ELSE IF test_width_int &gt;= 776 AND test_width_int &lt; 819 THEN
|
||||
results["776_count"] = results["776_count"] + 1
|
||||
remaining_width = remaining_width - 776 - gap - post_addition
|
||||
ELSE IF test_width_int &gt;= 131 AND test_width_int &lt; 776 THEN
|
||||
// Calculate based on a grid step of 43
|
||||
calculated_size = ((test_width_int - 131) / 43) * 43 + 131
|
||||
|
||||
IF calculated_size == 131 AND min_special_element != 131 + post_addition THEN
|
||||
special_element_width = 0 // Min size rule prevents a 131 element
|
||||
ELSE
|
||||
special_element_width = calculated_size
|
||||
END IF
|
||||
END IF
|
||||
|
||||
// --- 5. Final Remainder Output ---
|
||||
results["special_element"] = special_element_width
|
||||
|
||||
IF special_element_width &gt; 0 THEN
|
||||
remaining_width = remaining_width - special_element_width - gap - post_addition
|
||||
END IF
|
||||
|
||||
results["final_remainder"] = remaining_width
|
||||
|
||||
RETURN results
|
||||
END FUNCTION
|
||||
|
||||
FUNCTION determine_parameters_and_generate(start_point, end_point)
|
||||
// --- 1. Vererbungs-Weiche (Typ und Füllung ermitteln) ---
|
||||
IF start_point.is_pmi == TRUE THEN
|
||||
// Vererbung vom Start-PMI (gilt für PMI+Frei und PMI+PMI)
|
||||
fence_type = start_point.parent.type
|
||||
fence_filling = start_point.parent.filling
|
||||
|
||||
ELSE IF end_point.is_pmi == TRUE THEN
|
||||
// Rückwärtsvererbung vom End-PMI (gilt für Frei+PMI)
|
||||
fence_type = end_point.parent.type
|
||||
fence_filling = end_point.parent.filling
|
||||
|
||||
ELSE
|
||||
// Beide Punkte frei (Frei+Frei) -&gt; Modales UI-Overlay
|
||||
ui_selection = SHOW_MODAL_OVERLAY()
|
||||
IF ui_selection == CANCELLED THEN RETURN
|
||||
|
||||
fence_type = ui_selection.type
|
||||
fence_filling = ui_selection.filling
|
||||
END IF
|
||||
|
||||
// --- 2. Geometrie berechnen ---
|
||||
total_width = CALCULATE_2D_DISTANCE(start_point, end_point)
|
||||
angle = CALCULATE_2D_ANGLE(start_point, end_point)
|
||||
|
||||
// --- 3. Aufteilung berechnen (Kern-Algorithmus bleibt unverändert) ---
|
||||
distribution = calculate_width_distribution(fence_type, FALSE, 0, total_width, fence_filling)
|
||||
|
||||
// --- 4. Kaskadierende Platzierung triggern ---
|
||||
PLACE_FENCE_ELEMENTS(distribution, start_point, angle)
|
||||
END FUNCTION</pre>
|
||||
</div></div>
|
||||
|
||||
<h4><a name="NichtZiele%28OutofScope%29"></a>Nicht-Ziele (Out of Scope)</h4>
|
||||
|
||||
<ul>
|
||||
<li><b>Live-Vorschau (Ghosting):</b> Das Rendern einer 3D-Vorschau des Zauns während der Mausbewegung.</li>
|
||||
<li><b>Passstücke (Sonderbau):</b> Generierung freier Sonder-Bauteile außerhalb des 43-mm-Rasters.</li>
|
||||
<li><b>Spezifikation des Overlays:</b> Das UI des modalen Overlays wird separat spezifiziert.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
<h3><a name="%F0%9F%93%91Akzeptanzkriterien%3A"></a><b>�� Akzeptanzkriterien:</b></h3>
|
||||
|
||||
<ul>
|
||||
<li>Die Vererbungsmatrix wird strikt eingehalten: Das Konfigurations-Overlay öffnet sich <em>ausschließlich</em>, wenn sowohl Start- als auch Endpunkt frei im Raum (Typ 1) liegen.</li>
|
||||
<li>Ist der Startpunkt ein PMI, werden inkompatible PMIs im Viewer beim Hovern ignoriert und nicht als Snapping-Ziel angeboten.</li>
|
||||
<li>Startet der Zaun frei und endet an einem PMI, übernimmt der Zaun die Parameter des Ziel-Elements fehlerfrei (Rückwärtsvererbung).</li>
|
||||
<li>Geometrie wird flach auf der XZ-Ebene berechnet; Höhenunterschiede zwischen den Punkten führen nicht zu schiefen Zäunen.</li>
|
||||
<li>Kaskadierendes Verhalten: Bei Verschiebung des Eltern-Bauteils bewegt sich der gesamte Zaun-Verbund mit.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
<h3><a name="%F0%9F%A7%AATestCases%3A"></a><b>�� Test Cases:</b></h3>
|
||||
|
||||
<ul>
|
||||
<li><b><span class="error">&#91;Rückwärtsvererbung&#93;</span></b>: Startpunkt ins Freie klicken -&gt; Endpunkt an PMI eines Basic-Zauns mit Polycarbonat-Füllung snappen -&gt; <em>Erwartetes Ergebnis:</em> Kein Overlay öffnet sich. Es wird sofort ein Basic-Zaun mit Polycarbonat generiert, der an das Ziel snappt.</li>
|
||||
<li><b><span class="error">&#91;PMI Typen-Filter&#93;</span></b>: Startpunkt an Allround-PMI klicken -&gt; Maus über ein Basic-PMI bewegen -&gt; <em>Erwartetes Ergebnis:</em> Das Basic-PMI wird nicht gehighlighted und kann nicht als Endpunkt ausgewählt werden.</li>
|
||||
<li><b><span class="error">&#91;Overlay-Trigger&#93;</span></b>: Startpunkt frei klicken -&gt; Endpunkt frei klicken -&gt;<em>Erwartetes Ergebnis:</em> Modales Overlay zur Parameterauswahl öffnet sich.</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
<h3><a name="%E2%9A%A0%EF%B8%8FEdgeCases%3A%C2%A0"></a><b>⚠️ Edge Cases:</b> </h3>
|
||||
|
||||
<ul>
|
||||
<li><b><span class="error">&#91;Abbruch während Zeichnen&#93;</span></b>: <tt>ESC</tt> oder ein Klick außerhalb des Canvas bricht den Modus nach Klick 1 restlos ab.</li>
|
||||
<li><b><span class="error">&#91;Distanz zu kurz&#93;</span></b>: Ist die Gesamtdistanz kleiner als das schmalste verfügbare Rasterelement, führt der Abschluss im Overlay zu einem No-Op (keine Generierung).</li>
|
||||
<li><b><span class="error">&#91;Eltern-Löschung&#93;</span></b>: Wird das Bauteil gelöscht, an dessen PMI der Zaun beginnt, verliert das erste Zaunelement seine Typ 2 Bedingung, fällt auf Typ 1 zurück und der Zaun bleibt stehen.</li>
|
||||
</ul>
|
||||
</customfieldvalue>
|
||||
|
||||
</customfieldvalues>
|
||||
</customfield>
|
||||
<customfield id="customfield_13429" key="com.atlassian.jira.plugin.system.customfieldtypes:multicheckboxes">
|
||||
<customfieldname>�� DoR - Checkliste</customfieldname>
|
||||
<customfieldvalues>
|
||||
<customfieldvalue key="20347"><![CDATA[Ziel eindeutig formuliert (W-Fragen vollständig?)]]></customfieldvalue>
|
||||
<customfieldvalue key="20349"><![CDATA[Akzeptanzkriterien definiert]]></customfieldvalue>
|
||||
<customfieldvalue key="20350"><![CDATA[mind. ein Testfall dokumentiert]]></customfieldvalue>
|
||||
<customfieldvalue key="20351"><![CDATA[Priorität gesetzt]]></customfieldvalue>
|
||||
<customfieldvalue key="20352"><![CDATA[Edge Cases beschrieben]]></customfieldvalue>
|
||||
<customfieldvalue key="20353"><![CDATA[T‑Shirt‑Aufwand geschätzt]]></customfieldvalue>
|
||||
|
||||
</customfieldvalues>
|
||||
</customfield>
|
||||
</customfields>
|
||||
</item>
|
||||
</channel>
|
||||
</rss>
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"pool": "privateDefault"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// ghostty-wincount <pid> — Anzahl sichtbarer Normal-Fenster (Layer 0) des
|
||||
// Prozesses, direkt vom Window-Server. Keine Apple-Events, kein TCC-Prompt.
|
||||
import CoreGraphics
|
||||
import Foundation
|
||||
|
||||
guard CommandLine.arguments.count == 2, let pid = Int32(CommandLine.arguments[1]) else {
|
||||
FileHandle.standardError.write(Data("usage: ghostty-wincount <pid>\n".utf8))
|
||||
exit(2)
|
||||
}
|
||||
let list = CGWindowListCopyWindowInfo([.optionOnScreenOnly], kCGNullWindowID) as? [[String: Any]] ?? []
|
||||
let n = list.filter {
|
||||
($0[kCGWindowOwnerPID as String] as? Int32) == pid &&
|
||||
($0[kCGWindowLayer as String] as? Int) == 0
|
||||
}.count
|
||||
print(n)
|
||||
Executable
+32
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env bash
|
||||
# pool-guard — SessionStart-Hook: prüft direkt nach dem claude-Start, ob die
|
||||
# Session über claude-sync (Pool-Mechanismus) läuft. claude-sync schreibt die
|
||||
# Sentinel-Datei in den Projekt-Root und hält sie offen; ein RAW-Start hat
|
||||
# keine lebende Sentinel dahinter und wird beendet.
|
||||
set -uo pipefail
|
||||
|
||||
sentinel="$CLAUDE_PROJECT_DIR/.ai-control-running"
|
||||
|
||||
fail() {
|
||||
# claude im Elternbaum finden und beenden, dann Banner aufs Terminal.
|
||||
p=$PPID
|
||||
while [ -n "$p" ] && [ "$p" -gt 1 ]; do
|
||||
case "$(ps -o comm= -p "$p")" in
|
||||
*claude*) kill "$p"; break ;;
|
||||
esac
|
||||
p=$(ps -o ppid= -p "$p" | tr -d ' ')
|
||||
done
|
||||
sleep 0.3
|
||||
{
|
||||
printf '\n\033[1;5;97;41m POOL-GUARD: %s \033[0m\n\n' "$1"
|
||||
printf '\033[1;31mDiese Session lief außerhalb des Pool-Mechanismus und wurde beendet.\nStart nur über die Ghostty-App bzw. claude-sync.\033[0m\n'
|
||||
} >/dev/tty
|
||||
exit 2
|
||||
}
|
||||
|
||||
[ -f "$sentinel" ] || fail "keine Sentinel-Datei ($sentinel)"
|
||||
pool=$(sed -n 's/^pool=//p' "$sentinel")
|
||||
pid=$(sed -n 's/^pid=//p' "$sentinel")
|
||||
[ "$pool" = "${CLAUDE_CONFIG_DIR:-}" ] || fail "Pool-Mismatch: Sentinel=$pool, Session=${CLAUDE_CONFIG_DIR:-<leer>}"
|
||||
kill -0 "$pid" 2>/dev/null || fail "claude-sync (PID $pid) lebt nicht mehr"
|
||||
exit 0
|
||||
@@ -8,4 +8,6 @@
|
||||
- [cpq Storybook starten](cpq-storybook-start.md) — pnpm --filter @ad-cpq/common-frontend storybook (Port 6006)
|
||||
- [Git nur Fast-Forward](feedback-git-nur-fast-forward.md) — kein rebase/merge/force; bei Divergenz melden statt auflösen
|
||||
- [fire-visual Placement-Mode](fire-visual-placement-mode.md) — snap-to-point: DragPoints/DropPoints, processInput-Algorithmus, start_placement_mode-Command, PMI-DropPoints
|
||||
- [cpq Verbau 90° am Steher](cpq-verbau-90grad-steher.md) — Engine kann's, cpq-GroupProcessor (translation-only) plättet die Rotation beim Replay; Punktdaten tragen die Orientierung schon
|
||||
- [cpq Verbau 90° am Steher](cpq-verbau-90grad-steher.md) — Rotation ist im GroupProcessor-Replay angekommen (Edge.rot/computeLayout); fachliche 90°-Klärung läuft noch
|
||||
- [cpq Configurator Modul-Registry](cpq-configurator-modul-registry.md) — GEKO-76/16: Registry in configurator/modules, Hook nach replay(), Heilung=Ableitung, Overrides=Events
|
||||
- [Suche nur in Projektordnern](feedback-suche-nur-projektordner.md) — find/grep nie über ~ oder den ganzen Rechner, nur im konkreten erlaubten Verzeichnis
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
---
|
||||
name: cpq-configurator-modul-registry
|
||||
description: "GEKO-76/16-Konzept: Modul-Registry im cpq-Configurator — Injection über DefaultCommandProcessor, Hook nach replay(), Heilung = Ableitung, Overrides = Events"
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: project
|
||||
originSessionId: 8d7f85b8-4927-4426-9e04-a8be7def3b5e
|
||||
---
|
||||
|
||||
Konzept-Entscheidung (2026-07-03) für die cpq/geko-Abgrenzung der Schutzzaun-Tickets GEKO-76 (Steher-Logik) und GEKO-16 (Zaun zwischen zwei Punkten):
|
||||
|
||||
- **Registry-Ort:** `packages/frontend/src/configurator/` (neues Verzeichnis `modules/`), kein neues Package. cpq bleibt domänen-agnostisch; geko liefert Module (Steher, Zaun-Zug) von außen.
|
||||
- **Injection:** Konstruktor des `DefaultCommandProcessor`; `Fire3D.vue` nimmt bereits `props.processor` entgegen — die geko-App baut den Processor mit ihren Modulen und reicht ihn durch.
|
||||
- **Zentraler Hook:** nach `groups.replay(...)` in `DefaultCommandProcessor.replay()` — einziger Engpass für Live, Undo/Redo und Placement; Module können Live/Replay nicht auseinanderlaufen lassen.
|
||||
- **Semantik:** Selbstheilung (Bauform A–G, Höhe) ist reine Ableitung aus der Topologie (`occupiedPmis()`, `Edge.rot`) und landet nie im EventStore; manuelle Detailmenü-Overrides sind echte, undo-bare Events (Modul-eigene Event-Typen).
|
||||
- **Mit aufzuräumen:** hartkodierte `.name-CS_EIN_*`-Selektoren im `DefaultCommandProcessor` → Placement-Konfiguration des Moduls; Löschen ist im Processor noch unbehandelt → Kaskaden-Hook von Anfang an als Modul-Vertrag entwerfen.
|
||||
- Ticket-Quellen lokal: `~/claude-projects/robotunits/GEKO-76.xml`, `GEKO-16.xml`; DrawIO-Abgrenzung: `GEKO-76-steher-cpq-geko.drawio`.
|
||||
|
||||
Siehe [[cpq-verbau-architektur]], [[cpq-verbau-90grad-steher]].
|
||||
@@ -1,28 +1,20 @@
|
||||
---
|
||||
name: cpq-verbau-90grad-steher
|
||||
description: "Ziel 90°-Anbau am Steher wie jetzt Links/Rechts — Engine kann es, cpq-GroupProcessor (translation-only) ist der Blocker"
|
||||
description: "90°-Anbau am Steher: Rotation ist im GroupProcessor-Replay angekommen (Edge.rot, computeLayout) — fachliche 90°-Klärung läuft noch"
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: project
|
||||
originSessionId: e3d54daa-eb88-474f-9e99-62bfe83821b2
|
||||
---
|
||||
|
||||
Ziel: an den Stehern im 90°-Winkel anbauen können, genau wie der jetzige Links/Rechts-Verbau.
|
||||
Ziel: an den Stehern im 90°-Winkel anbauen können, genau wie der Links/Rechts-Verbau.
|
||||
|
||||
**Wer ist der Blocker: wir (cpq), nicht fire-visual.**
|
||||
**Stand 2026-07-03 (verifiziert im Code):** Der frühere Blocker — translation-only-Replay im cpq-`GroupProcessor` — ist behoben. `packages/frontend/src/configurator/model/GroupProcessor.ts`:
|
||||
- `Edge` trägt `rot?: Quat` (relative Rotation pro Dock-Kante).
|
||||
- `computeLayout` komponiert Rotationen über den ungerichteten Kantengraphen (Quaternionen, vorwärts `R_to = R_from ∘ edge.rot`, rückwärts invers); mit Identity-Rotationen reduziert es sich exakt auf den alten translation-only-Solver.
|
||||
- `dockRotation` leitet `Edge.rot` aus den PMI-Frame-Orientierungen ab (`pmiRotation` liest `properties.rotation` als Euler ZYX Grad → Quat).
|
||||
- Placement nutzt die `CS_EIN_VORNE`/`CS_EIN_HINTEN`-Selektoren (hart im `DefaultCommandProcessor` — Kandidat für Modul-Konfiguration).
|
||||
|
||||
- **fire-visual kann es.** Das Live-Snapping im PlacementMode setzt die Subject-Matrix als `bestMatrix · dragPointTransform⁻¹` — die Rotation des Drag-Punkts ist drin, die Engine richtet also den vollen Frame aus und dreht das Teil beim Snap schon korrekt um 90°. (Vorbehalt: aus der Placement-Matrix-Notiz abgeleitet, nicht aus frischem Quell-Read; bei Bedarf `PlacementMode`-Quelle prüfen, ob DropPoints den Rotations-Frame durchreichen.)
|
||||
- **cpq verliert es beim Replay.** Nach dem Snap übernehmen wir das Engine-Ergebnis nicht, sondern merken nur „Punkt A trifft Punkt B" (`group-merge` mit zwei PMI-IDs) und rechnen die Anordnung im `GroupProcessor` selbst neu — rein translatorisch. Beim nächsten `setScene` wird die 90°-Drehung auf achsparallel zurückgeplättet.
|
||||
Die fachliche Klärung der 90°-Frage (GEKO-Seite) läuft laut Marcus noch separat.
|
||||
|
||||
**Warum schwer — das Dock-Modell ist translation-only, einachsig, gemeinsame Orientierung. Links/Rechts geht nur, weil nie rotiert wird.** Zu ändernde Schichten:
|
||||
1. `Edge` = `{from,to,fromPmi,toPmi}` kennt keine Rotation → relative Rotation pro Kante nötig.
|
||||
2. `computePositions` dockt mit `pos(to)=pos(from)+pmi(from)−pmi(to)` (nur Position) → Rotation entlang der Kanten komponieren.
|
||||
3. `pmiLocal` liest nur `position.value`. **Die Orientierung steckt schon in den Daten** (`properties.rotation`), wird aber ignoriert — und Format passt nicht: 3 Euler-Grad (z. B. `CS_EIN_90_0_0` → `[0,-0,180]`), deklariert als „quaternion", während `transformMath` `[w,x,y,z]` erwartet.
|
||||
4. Placement-Mode hartverdrahtet auf `.name-CS_LINKS`↔`.name-CS_RECHTS`; Steher-Anschlüsse leben in der `CS_EIN_*`-Familie → neue Drag-/Drop-Selektoren + Open-End-Logik (`occupiedPmis`).
|
||||
5. `buildDetachEvent`/`areConnected` nehmen einen 1-achsigen Lauf an (dominante Achse, Links→Rechts-Leseordnung) → 90°-Anbau macht den Verbau zum 2D-Baum, Annahmen brechen.
|
||||
|
||||
**Datenlage:** kein plain `CS_VORNE`/`CS_HINTEN` (0 Teile); `CS_LINKS`/`CS_RECHTS` nur auf 12 Teilen; Vorne/Hinten nur in `CS_EIN_*` (rotationscodiert: `CS_EIN_VORNE`, `CS_EIN_HINTEN`, `CS_EIN_STEHER_VORNE/HINTEN`, `CS_EIN_90_0_0` …).
|
||||
|
||||
**Machbar:** Erweiterung unseres Modells (Rotation konsumieren + entlang Kanten propagieren + Format-Fix), keine Nachgenerierung der Teile — die nötige Orientierung liefern die Punktdaten bereits.
|
||||
|
||||
Siehe [[cpq-verbau-architektur]], [[fire-visual-placement-mode]].
|
||||
Siehe [[cpq-verbau-architektur]], [[fire-visual-placement-mode]], [[cpq-configurator-modul-registry]].
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
name: feedback-suche-nur-projektordner
|
||||
description: "Suchen/find/grep nur innerhalb der erlaubten Projektverzeichnisse, nie über ~ oder den ganzen Rechner"
|
||||
metadata:
|
||||
node_type: memory
|
||||
type: feedback
|
||||
originSessionId: 8d7f85b8-4927-4426-9e04-a8be7def3b5e
|
||||
---
|
||||
|
||||
Such-Befehle (find, grep, ls …) nur innerhalb der erlaubten Arbeitsverzeichnisse des jeweiligen Projekts ausführen — nicht über `/Users/marcus.hinz`, nicht über breite Pfad-Listen quer durch `~/projects`, nicht über den ganzen Rechner.
|
||||
|
||||
**Why:** Marcus erlaubt Zugriff gezielt pro Projektordner; breite Sweeps über Home verletzen diese Abgrenzung, auch wenn sie technisch funktionieren.
|
||||
|
||||
**How to apply:** Vor einem Such-Befehl den konkretesten bekannten Pfad wählen (z. B. das genannte Repo oder `~/claude-projects/robotunits`). Liegt das Ziel dort nicht, melden statt den Suchraum eigenmächtig auszuweiten. Gilt zusätzlich zu [[feedback-keine-intent-unterstellung]]s Grundregel „nur suchen, wenn angewiesen".
|
||||
@@ -0,0 +1 @@
|
||||
.ai-control-running
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"pool": "privateDefault"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
.ai-control-running
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"pool": "privateDefault"
|
||||
}
|
||||
Reference in New Issue
Block a user