1.4.1
release-tag / release-image (push) Successful in 9m19s

This commit is contained in:
2026-08-26 21:31:42 +02:00
parent e9ae2eccb5
commit 6513468c12
15 changed files with 1175 additions and 93 deletions
+805 -82
View File
@@ -1,110 +1,833 @@
# -----------------------------
# Mega-project core / security
# -----------------------------
NEUROFORGE_ADMIN_TOKEN=CHANGE_ME_ADMIN
NEUROFORGE_APP_API_KEY=CHANGE_ME_APP
NEUROFORGE_WORKER_TOKEN=CHANGE_ME_WORKER
NEUROFORGE_METRICS_TOKEN=CHANGE_ME_METRICS
KB_INTEGRATION_TOKEN=CHANGE_ME_KB_INTEGRATION
CONTROL_READ_TOKEN=CHANGE_ME_CONTROL_READ
NEUROFORGE_CLUSTER_TOKEN=
OPENAI_API_KEY=
###############################################################################
# GLPI NEUROFORGE MEGA v1.4.x - VOLLSTÄNDIGE .ENV.example
#
# Diese Datei ist die zentrale Konfiguration für docker compose.
# Sie enthält:
# - GLPI AI Agent (vollständige produktive Optionen)
# - NeuroForge / Vector Backend / Controlled Learning
# - Knowledge Editor
# - Control Center
# - optional SearXNG Research
# - optionale Codebase-Memory-UI
#
# SICHERER START:
# DRY_RUN=true
# AUTO_REPLY=false
# AUTO_PRIORITY=false
# AUTO_ESCALATION=false
# NEUROFORGE_RESEARCH_ENABLED=false
# NEUROFORGE_AUTONOMY_ENABLED=false
#
# WICHTIG:
# Interne Container-Adressen/Ports wie HTTP_ADDR, DATA_DIR, KNOWLEDGE_DIR,
# OLLAMA_URL, NEUROFORGE_URL und BRAIN_ACTIVITY_URL werden im Mega-Compose
# fest verdrahtet. Dadurch können alte Standalone-Werte die Container-
# Kommunikation nicht versehentlich beschädigen.
###############################################################################
# Staged vector migration: local | dual | neuroforge
KNOWLEDGE_VECTOR_BACKEND=dual
NEUROFORGE_NAMESPACE=glpi-agent
NEUROFORGE_SEARCH_K=128
# true = keep processing with local/lexical fallback if NeuroForge is unavailable
# false = semantic backend failures are blocking
NEUROFORGE_FAIL_OPEN=true
# -----------------------------
# Shared local AI runtime
# -----------------------------
OLLAMA_MODEL=gemma3
OLLAMA_EMBEDDING_MODEL=embeddinggemma
OLLAMA_TIMEOUT=10m
OLLAMA_KEEP_ALIVE=10m
OLLAMA_NUM_PREDICT=768
OLLAMA_JSON_RETRIES=1
# -----------------------------
# GLPI Agent connection
# -----------------------------
GLPI_URL=https://glpi.example.invalid
GLPI_API_VERSION=v2.3
GLPI_CLIENT_ID=
GLPI_CLIENT_SECRET=
GLPI_USERNAME=
GLPI_PASSWORD=
GLPI_AGENT_USER_ID=0
DRY_RUN=true
AUTO_CATEGORY=false
AUTO_REPLY=false
AUTO_PRIORITY=false
AUTO_ESCALATION=false
RAG_ENABLED=true
KNOWLEDGE_INDEX_MODE=incremental
KNOWLEDGE_MIN_SCORE=0.70
KNOWLEDGE_ALLOWED_SOURCES=internal-kb
# -----------------------------
# Web access
# -----------------------------
WEB_USERNAME=admin
WEB_PASSWORD=CHANGE_ME_AGENT_WEB
WEB_ALLOW_ANONYMOUS=false
BASIC_AUTH_USER=admin
BASIC_AUTH_PASSWORD=CHANGE_ME_KB_WEB
# -----------------------------
# Optional host ports
# -----------------------------
###############################################################################
# 01. MEGA STACK - HOST PORTS / PFADE
###############################################################################
CONTROL_HOST_PORT=8070
AGENT_HOST_PORT=8080
KNOWLEDGE_HOST_PORT=8081
NEUROFORGE_HOST_PORT=8090
OLLAMA_HOST_PORT=11434
SEARXNG_HOST_PORT=8888
# -----------------------------
# Controlled learning / research
# -----------------------------
# Enforces: no automatic learning from raw chat input or assistant output;
# explicit validated outcomes and research evidence keep distinct provenance.
# Gemeinsame produktive Knowledge-Quelle auf dem Docker-Host.
KB_DATA_PATH=./knowledge
KB_DATA_MOUNT_MODE=rw
KB_BACKUP_PATH=./backups
KB_STAGING_PATH=./staging
###############################################################################
# 02. MEGA STACK - SECURITY / SERVICE TOKENS
###############################################################################
# Erzeugen z. B. mit: ./scripts/generate-secrets.sh
NEUROFORGE_ADMIN_TOKEN=CHANGE_ME_ADMIN_TOKEN
NEUROFORGE_APP_API_KEY=CHANGE_ME_APP_API_KEY
NEUROFORGE_WORKER_TOKEN=CHANGE_ME_WORKER_TOKEN
NEUROFORGE_METRICS_TOKEN=CHANGE_ME_METRICS_TOKEN
# Nur bei Clusterbetrieb erforderlich.
NEUROFORGE_CLUSTER_TOKEN=
KB_INTEGRATION_TOKEN=CHANGE_ME_KB_INTEGRATION_TOKEN
CONTROL_READ_TOKEN=CHANGE_ME_CONTROL_READ_TOKEN
# Optionaler externer OpenAI-Fallback. Leer = deaktiviert.
OPENAI_API_KEY=
###############################################################################
# 03. SHARED OLLAMA RUNTIME
###############################################################################
# Dieses Modell wird von Agent, Knowledge und NeuroForge gemeinsam verwendet.
# Wenn du dein bisheriges Verhalten beibehalten willst, kannst du hier z. B.
# qwen3:8b statt gemma3 setzen. Das Modell muss vorher in Ollama vorhanden sein.
OLLAMA_MODEL=gemma3
OLLAMA_EMBEDDING_MODEL=embeddinggemma
OLLAMA_TIMEOUT=10m
OLLAMA_MAX_CONCURRENT=1
OLLAMA_NUM_PREDICT=768
OLLAMA_JSON_RETRIES=1
OLLAMA_KEEP_ALIVE=10m
OLLAMA_THINK=false
###############################################################################
# 04. KNOWLEDGE EDITOR
###############################################################################
KB_APP_MODE=editor
APP_TITLE=Knowledge Base Editor
APP_SUBTITLE=GLPI NeuroForge Mega
AUTO_RELOAD_INTERVAL=60s
# Für Produktion setzen. Leer würde die optionale Basic-Auth deaktivieren.
BASIC_AUTH_USER=admin
BASIC_AUTH_PASSWORD=CHANGE_ME_KB_WEB_PASSWORD_LONG
AI_FALLBACK_ENABLED=true
# Wird im Mega-Compose intern auf http://ollama:11434 gesetzt.
OLLAMA_BASE_URL=http://ollama:11434
OLLAMA_STAGING_AUTO_REPLY=false
OLLAMA_STAGING_MIN_SCORE=0.78
###############################################################################
# 05. NEUROFORGE VECTOR BACKEND / INTEGRATION
###############################################################################
# local | dual | neuroforge
KNOWLEDGE_VECTOR_BACKEND=dual
NEUROFORGE_NAMESPACE=glpi-agent
NEUROFORGE_TIMEOUT=15s
NEUROFORGE_SEARCH_K=128
# true = bei NeuroForge-Ausfall lokale/lexikalische Evidenz weiterverwenden.
NEUROFORGE_FAIL_OPEN=true
###############################################################################
# 06. CONTROLLED LEARNING / VALIDATED OUTCOMES
###############################################################################
# Verhindert automatisches Langzeitlernen aus rohem Chatinput/AI-Ausgaben.
NEUROFORGE_CONTROLLED_LEARNING=true
# Separate gate for semantic goal-cycle memories. Required for manual/autonomous
# Goal cycles to learn while Controlled Learning remains enabled.
NEUROFORGE_GOAL_LEARNING_ENABLED=false
# Ticket -> AI proposal -> technician accept/correct -> NeuroForge learn.
# Ticket -> KI-Vorschlag -> Techniker bestätigt/korrigiert -> Trusted Outcome.
OUTCOME_LEARNING_ENABLED=true
# false = technician sees an error when NeuroForge cannot persist the validated outcome.
# The local outcome audit is still retained with sync_status=failed.
OUTCOME_LEARNING_FAIL_OPEN=false
OUTCOME_LEARNING_MAX_OUTCOMES=2000
# Active accepted/corrected outcomes are secondary reply evidence only.
# They never replace the approved-KB requirement for Auto-Reply.
# Menschlich validierte Erfahrungen als sekundäre Evidenz abrufen.
OUTCOME_RETRIEVAL_ENABLED=true
OUTCOME_RETRIEVAL_SEARCH_K=6
OUTCOME_RETRIEVAL_MIN_SIMILARITY=0.58
# true = continue with official KB/context if experience retrieval is unavailable.
OUTCOME_RETRIEVAL_FAIL_OPEN=true
# Research is opt-in. Starting the SearXNG profile alone does not enable learning.
###############################################################################
# 07. OPTIONAL RESEARCH / SEARXNG / AUTONOMY
###############################################################################
# SearXNG-Container wird nur mit `docker compose --profile research ...` gestartet.
SEARXNG_IMAGE=docker.io/searxng/searxng:latest
SEARXNG_SECRET=CHANGE_ME_SEARXNG_LONG_RANDOM_SECRET
# Research und Autonomy sind absichtlich getrennt.
NEUROFORGE_RESEARCH_ENABLED=false
NEUROFORGE_SEARXNG_ENABLED=false
NEUROFORGE_SEARXNG_URL=http://searxng:8080
NEUROFORGE_RESEARCH_GOAL_ENABLED=true
# Separate switch for scheduled self-directed goal cycles.
NEUROFORGE_AUTONOMY_ENABLED=false
NEUROFORGE_AUTONOMY_INTERVAL_MINUTES=30
NEUROFORGE_RESEARCH_MAX_QUERIES=2
NEUROFORGE_RESEARCH_MAX_PAGES=4
# Required only when the optional `research` compose profile is started.
# Pin this to a version/digest in production if reproducible images are required.
SEARXNG_IMAGE=docker.io/searxng/searxng:latest
SEARXNG_SECRET=CHANGE_ME_SEARXNG_LONG_RANDOM_SECRET
SEARXNG_HOST_PORT=8888
# Optional local developer-only Codebase Memory MCP/UI. It is not required by
# production services. For a host process reachable from Docker on Linux:
###############################################################################
# 08. OPTIONAL CODEBASE MEMORY MCP / ENGINEERING UI
###############################################################################
# Developer-only. Für den Produktivbetrieb nicht erforderlich.
CODEBASE_MEMORY_URL=
PUBLIC_CODEBASE_MEMORY_URL=http://localhost:9749
###############################################################################
# 09. AGENT - VOLLSTÄNDIGE KONFIGURATION
###############################################################################
# 09A. GLPI AI AGENT - ALLGEMEINER BETRIEB
###############################################################################
# true:
# Der Agent analysiert vollständig, schreibt aber keine Änderungen nach GLPI.
#
# false:
# Durch die Policy freigegebene Aktionen werden tatsächlich ausgeführt.
#
# Für Tests / Einführung:
# true
DRY_RUN=true
# Mögliche Werte:
# debug
# info
# warn
# error
LOG_LEVEL=info
# HTTP-Listener INNERHALB des Agent-Containers.
# Im Mega-Compose wird dieser Wert zusätzlich fest auf :8080 überschrieben.
# Der veröffentlichte Host-Port wird ausschließlich über AGENT_HOST_PORT gesteuert.
HTTP_ADDR=:8080
# Persistentes Verzeichnis IM Container.
#
# Compose mountet:
# agent-data:/app/data
#
# Enthält unter anderem:
# - Knowledge-Index
# - Audit/Run-Daten
# - Category Learning
# - Managed Knowledge
# - GLPI-KB-Cache
DATA_DIR=/app/data
###############################################################################
# 06. AGENT WEBUI / API / DIAGNOSE
###############################################################################
# Benutzer für Agent-Dashboard, Knowledge-Verwaltung und Diagnose-Cockpit.
WEB_USERNAME=admin
WEB_PASSWORD=CHANGE_ME_AGENT_WEB_PASSWORD_LONG
# false:
# Anmeldung erforderlich.
#
# true:
# Weboberfläche ohne Authentifizierung erreichbar.
#
# In Produktion normalerweise false.
WEB_ALLOW_ANONYMOUS=false
# TrustedNet-Kennzeichnung vor automatisch ausgewählten Antworten.
#
# true:
# TrustedNet-KI-Badge wird vor Anrede und Antwort eingefügt.
#
# false:
# keine KI-Kennzeichnung.
AI_CONTENT_LABEL_ENABLED=true
###############################################################################
# 07. OPTIONALER GLPI-WEBHOOK
###############################################################################
# Optionales Shared Secret für eingehende GLPI-Webhooks.
#
# Der Absender muss dasselbe Secret z. B. über:
# X-Webhook-Secret
# übertragen.
#
# Leer lassen, falls kein Webhook verwendet wird.
WEBHOOK_SECRET=
###############################################################################
# 08. GLPI 11 / HIGH-LEVEL API / OAUTH2
###############################################################################
GLPI_URL=https://glpi.example.invalid
# Verwendete GLPI High-Level API.
GLPI_API_VERSION=v2.3
# OAuth2 Service Account.
GLPI_CLIENT_ID=
GLPI_CLIENT_SECRET=
GLPI_USERNAME=
GLPI_PASSWORD=
# Numerische GLPI-Benutzer-ID des Service-Accounts.
#
# Wird unter anderem benötigt, um Agent-Followups von menschlichen
# Followups unterscheiden zu können.
GLPI_AGENT_USER_ID=0
# Nur für lokale Testsysteme ohne TLS.
#
# Produktion:
# false
GLPI_ALLOW_INSECURE_HTTP=false
###############################################################################
# 09. GLPI TICKET-POLLING
###############################################################################
# Fail-closed Whitelist erlaubter GLPI-Ticketstatus.
#
# Beispiel:
# 1
# 1,2
#
# Status 1 entspricht typischerweise "Neu".
GLPI_ALLOWED_STATUS_IDS=1
# Polling-Intervall.
GLPI_POLL_INTERVAL=30s
# Maximale Anzahl Tickets pro Poll.
GLPI_POLL_LIMIT=50
# Optionale serverseitige Vorfilterung.
#
# Die Agent-Policy prüft GLPI_ALLOWED_STATUS_IDS anschließend trotzdem selbst.
#
# Änderungen der Syntax immer gegen /api.php/doc der eigenen GLPI-Instanz
# prüfen.
GLPI_TICKET_FILTER=status.id==1
# HTTP-Timeout für GLPI-Aufrufe.
GLPI_TIMEOUT=20s
###############################################################################
# 10. GLPI AI AGENT - OLLAMA-POOL
###############################################################################
# Einzelnode-Kompatibilität. Wird nur verwendet, wenn OLLAMA_URLS leer ist.
OLLAMA_URL=http://ollama:11434
# Mehrere Ollama-Instanzen, durch Komma getrennt. Alle Nodes sollten dieselbe
# Ollama-Version, dasselbe Chat-Modell und dasselbe Embedding-Modell besitzen.
# Beispiel für vorhandene Lenovo-Nodes:
# OLLAMA_URLS=http://10.20.30.21:11434,http://10.20.30.22:11434,http://10.20.30.23:11434
OLLAMA_URLS=
# Optionale lesbare Namen; Anzahl muss exakt zu OLLAMA_URLS passen.
# OLLAMA_NODE_NAMES=lenovo-01,lenovo-02,lenovo-03
OLLAMA_NODE_NAMES=
# Optionale Gewichte 1..100; nur für OLLAMA_ROUTING_MODE=weighted relevant.
# OLLAMA_NODE_WEIGHTS=1,1,1
OLLAMA_NODE_WEIGHTS=
# Routing-Modi:
# least_inflight = Node mit den wenigsten laufenden Requests (empfohlen)
# round_robin = zyklische Verteilung
# weighted = Verteilung anhand OLLAMA_NODE_WEIGHTS und Auslastung
# fastest_recent = bevorzugt die zuletzt schnellsten Nodes
OLLAMA_ROUTING_MODE=least_inflight
# Maximale parallele Requests JE Node. Für integrierte GPUs/RAM-Sharing 1.
OLLAMA_NODE_MAX_INFLIGHT=1
# Regelmäßige Prüfung von /api/tags.
OLLAMA_NODE_HEALTH_INTERVAL=15s
# Nach einem retryfähigen Netzwerk-/HTTP-Fehler wird der Node so lange nicht
# für neue Requests verwendet.
OLLAMA_NODE_FAILURE_COOLDOWN=30s
# Maximalzeit für einen einzelnen Request an genau einen Node. Der übergeordnete
# Analyse-Timeout kann kürzer sein und hat dann Vorrang.
OLLAMA_NODE_REQUEST_TIMEOUT=10m
# Bei Netzwerkfehlern, HTTP 408/429/5xx oder ungültigem Response-JSON auf einen
# anderen kompatiblen Node wechseln.
OLLAMA_FAILOVER_ENABLED=true
# Maximale Anzahl verschiedener Nodes je logischem Request. 0 bedeutet:
# automatisch alle konfigurierten Nodes. Ein positiver Wert darf höchstens der
# Zahl der OLLAMA_URLS-Einträge entsprechen.
OLLAMA_FAILOVER_ATTEMPTS=0
# Bei abweichenden Chat-/Embedding-Modelldigests wird der Pool vollständig
# fail-closed. Für reproduzierbare Entscheidungen unbedingt true lassen.
OLLAMA_REQUIRE_SAME_MODEL_DIGEST=true
# true: Jeder Node muss auch OLLAMA_EMBEDDING_MODEL installiert haben.
# Bei RAG empfohlen. false erlaubt Chat-only-Nodes; Embedding-Requests werden
# trotzdem nur an Nodes mit erkanntem Embedding-Modell gesendet.
OLLAMA_REQUIRE_EMBEDDING_MODEL=true
# OLLAMA_MODEL ist bereits oben im gemeinsamen Compose-/Ollama-Bereich gesetzt:
# OLLAMA_MODEL=qwen3:8b
# Embedding-Modell für RAG.
# OLLAMA_EMBEDDING_MODEL=embeddinggemma # already configured in SHARED OLLAMA RUNTIME above
# Modellspezifisches Retrieval-Prompting.
# auto = Modell automatisch erkennen; für embeddinggemma empfohlen.
# plain = keine modellspezifischen Retrieval-Prompts.
KNOWLEDGE_EMBEDDING_PROFILE=auto
# Gesamtbudget für Ollama-Aufrufe und Fallback für Node-Request-Timeouts.
# OLLAMA_TIMEOUT ist bereits oben gesetzt.
# OLLAMA_MAX_CONCURRENT bleibt als Legacy-Alias für
# OLLAMA_NODE_MAX_INFLIGHT erhalten, falls der neue Wert nicht gesetzt ist.
# Maximale Anzahl generierter Tokens für strukturierte Antworten.
# OLLAMA_NUM_PREDICT=768 # already configured in SHARED OLLAMA RUNTIME above
# Wiederholungen bei semantisch/strukturell fehlerhaftem Modell-JSON.
# Diese Wiederholungen sind von Netzwerk-Failover getrennt.
# OLLAMA_JSON_RETRIES=1 # already configured in SHARED OLLAMA RUNTIME above
# Ollama-Modell nach Benutzung im Speicher halten.
# OLLAMA_KEEP_ALIVE=10m # already configured in SHARED OLLAMA RUNTIME above
# Thinking bei unterstützten Modellen deaktivieren.
# OLLAMA_THINK=false # already configured in SHARED OLLAMA RUNTIME above
###############################################################################
# 11. KNOWLEDGE BASE / RAG - BASIS
###############################################################################
# Knowledge-Verzeichnis IM Agent-Container.
#
# Compose sollte hierhin KB_DATA_PATH mounten:
# ${KB_DATA_PATH:-./knowledge}:/app/knowledge:ro
KNOWLEDGE_DIR=/app/knowledge
# Gesamtes Retrieval-System aktivieren.
RAG_ENABLED=true
###############################################################################
# 12. EXTERNE KNOWLEDGE-KATEGORIEN
###############################################################################
# Verhalten bei String-/Fremdkategorien, z. B.:
#
# "AI-Staging"
# "Outlook"
# "E-Mail"
# "Signatur"
#
# Mögliche Werte:
#
# unscoped
# Artikel bleibt nutzbar.
# Fremdkategorien können als Retrieval-Metadaten dienen.
#
# skip
# Artikel mit unbekannten Kategorien überspringen.
#
# strict
# unbekannte Kategorie als Fehler behandeln.
#
# Für eine gemeinsam mit anderen Anwendungen verwendete KB:
# unscoped
KNOWLEDGE_CATEGORY_MODE=unscoped
# Optionales Mapping von Fremdkategorien auf GLPI-ITIL-Kategorie-IDs.
#
# Beispiel knowledge-category-map.json:
#
# {
# "Outlook": 12,
# "E-Mail": 12,
# "Active Directory": 2,
# "Security": [20,21]
# }
KNOWLEDGE_CATEGORY_MAP_FILE=/app/data/knowledge-category-map.json
# Optional bestimmte KB-Dateien ignorieren.
#
# Beispiele:
# KB-SEC-ATTCK-*.json
# legacy-*.json,external-only-*.json
#
# Leer:
# keine zusätzlichen Ignore-Regeln.
KNOWLEDGE_IGNORE_GLOBS=
###############################################################################
# 13. PERSISTENTER KNOWLEDGE-INDEX
###############################################################################
# Mögliche Werte:
#
# incremental
# Persistent gespeicherten Index sofort verwenden.
# Neue/geänderte Dateien anschließend inkrementell nachziehen.
# Für Produktion empfohlen.
#
# rebuild
# vollständigen Index neu erzeugen.
#
# readonly
# nur bestehenden Index verwenden, keine Änderungen übernehmen.
KNOWLEDGE_INDEX_MODE=incremental
# Anzahl Texte pro Embedding-Batch.
KNOWLEDGE_EMBED_BATCH_SIZE=64
# Intervall für neue/geänderte/gelöschte Dateien.
#
# Beispiele:
# 30s
# 1m
# 5m
#
# 0:
# keinen automatischen Hintergrundscan durchführen.
KNOWLEDGE_INDEX_SCAN_INTERVAL=5m
###############################################################################
# 14. RETRIEVAL / DYNAMISCHE KANDIDATENAUSWAHL
###############################################################################
# Unterhalb dieses Retrieval-Scores wird eine KB nicht als geeigneter
# Kandidat betrachtet.
#
# Der Wert ist KEINE Wahrscheinlichkeit.
KNOWLEDGE_RETRIEVAL_FLOOR=0.30
# Maximale Differenz zum besten Treffer.
#
# Beispiel:
#
# bester Treffer 0.82
# MAX_GAP 0.20
# dynamischer Cutoff 0.62
#
# Ein Kandidat mit 0.55 würde dann nicht an die KI gesendet.
KNOWLEDGE_CANDIDATE_MAX_GAP=0.20
# Maximale Anzahl Knowledge-Kandidaten, die tatsächlich an Ollama gehen.
KNOWLEDGE_TOP_K=6
# Anzahl Kandidaten für Audit / Diagnose.
#
# Kann größer als KNOWLEDGE_TOP_K sein.
KNOWLEDGE_AUDIT_TOP_K=10
###############################################################################
# 15. HYBRID-RETRIEVAL - RANKING-GEWICHTE
###############################################################################
# Die Werte beschreiben die Gewichtung beim KB-Ranking.
#
# Summe aktuell:
# 1.0
#
# Fehlende Metadaten sollen nicht automatisch negativ bewertet werden.
# Embedding-/Chunk-Semantik.
KNOWLEDGE_WEIGHT_SEMANTIC=0.45
# Ticket-Betreff gegenüber KB-Titel.
KNOWLEDGE_WEIGHT_TITLE=0.20
# Lexikalische / sprachliche Übereinstimmung.
KNOWLEDGE_WEIGHT_LEXICAL=0.20
# KB-Keywords.
KNOWLEDGE_WEIGHT_KEYWORDS=0.075
# Kategorie-/Lernsignal.
KNOWLEDGE_WEIGHT_CATEGORY=0.075
###############################################################################
# 16. FINALE EVIDENZ FÜR AUTO-REPLY
###############################################################################
# Mindestwert der FINALEN Evidenz.
#
# WICHTIG:
# Das ist nicht der reine Retrieval-Score.
#
# Die finale Evidenz kombiniert:
# - Retrieval
# - AI Confidence
# - Kategorieübereinstimmung
KNOWLEDGE_MIN_SCORE=0.70
# Gewicht Retrieval.
KNOWLEDGE_EVIDENCE_WEIGHT_RETRIEVAL=0.45
# Gewicht KI-Auswahl / KI-Confidence.
KNOWLEDGE_EVIDENCE_WEIGHT_AI=0.35
# Gewicht Kategorieübereinstimmung.
KNOWLEDGE_EVIDENCE_WEIGHT_CATEGORY=0.20
###############################################################################
# 17. KNOWLEDGE-CHUNKING
###############################################################################
# Ungefähre Anzahl Wörter pro Dokument-Chunk.
KNOWLEDGE_CHUNK_WORDS=160
# Überlappung benachbarter Chunks.
KNOWLEDGE_CHUNK_OVERLAP_WORDS=30
# Maximale Anzahl Chunks pro KB-Dokument.
KNOWLEDGE_MAX_CHUNKS_PER_DOC=24
# Maximale Anzahl Query-Chunks bei sehr langen Tickets.
KNOWLEDGE_MAX_QUERY_CHUNKS=64
# Maximale Anzahl Kategorien im Kategorie-Prompt.
CATEGORY_PROMPT_LIMIT=80
###############################################################################
# 18. KNOWLEDGE-QUELLEN / TRUST POLICY
###############################################################################
# Quellen für normale Knowledge-Suche und mögliche Antwortkandidaten.
# Indexiert wird die Vereinigung mit KNOWLEDGE_CATEGORY_SOURCES.
#
# Beispiele:
# internal-kb
# glpi-kb
# runbook
# vendor-docs
KNOWLEDGE_ALLOWED_SOURCES=internal-kb,glpi-kb,vendor-docs,vendor-docs-ms,vendor-docs-linux,vendor-docs-sec
# Quellen, die ausschließlich die Kategorieentscheidung unterstützen.
# Ohne explizite Angabe wird aus Kompatibilitätsgründen KNOWLEDGE_ALLOWED_SOURCES verwendet.
# Mit "none" wird Knowledge-Einfluss auf die Kategorisierung deaktiviert.
KNOWLEDGE_CATEGORY_SOURCES=internal-category
# Nur diese Quellen dürfen grundsätzlich automatische Antworten liefern.
#
# Muss eine Teilmenge von KNOWLEDGE_ALLOWED_SOURCES sein.
#
# Beispiel zum kompletten Abschalten:
# KNOWLEDGE_AUTO_REPLY_SOURCES=none
KNOWLEDGE_AUTO_REPLY_SOURCES=internal-kb,glpi-kb,vendor-docs,vendor-docs-ms,vendor-docs-linux,vendor-docs-sec
# Webbasierte Bearbeitung von Agent-eigenen Knowledge-Artikeln.
#
# Diese werden unter:
# DATA_DIR/knowledge-managed
# gespeichert.
#
# Das statische KNOWLEDGE_DIR bleibt read-only.
KNOWLEDGE_WEB_EDIT_ENABLED=true
###############################################################################
# 19. GLPI KNOWLEDGE BASE CONNECTOR
###############################################################################
# GLPI-interne Knowledge Base synchronisieren.
GLPI_KB_ENABLED=true
# auto:
# Agent ermittelt die KnowbaseItem-Route aus /api.php/doc.json.
GLPI_KB_PATH=auto
# Optionaler serverseitiger GLPI-Filter.
#
# Leer:
# alle für den Service Account sichtbaren Artikel, begrenzt durch LIMIT.
GLPI_KB_FILTER=
# Maximale Anzahl GLPI-KB-Artikel.
GLPI_KB_LIMIT=500
# Synchronisationsintervall.
GLPI_KB_SYNC_INTERVAL=10m
# source-Wert importierter GLPI-KB-Artikel.
GLPI_KB_SOURCE=glpi-kb
# true:
# GLPI-KB-Artikel können grundsätzlich Auto-Replies auslösen.
#
# Zusätzlich gelten weiterhin alle anderen Policy-Gates wie Retrieval,
# KI-Auswahl, Evidenz, Sprache, Stil und vorhandene Antworten.
GLPI_KB_AUTO_REPLY=false
# Whitelist der GLPI KNOWLEDGE-BASE-Kategorie-IDs.
#
# WICHTIG:
# Dies sind NICHT die ITIL-/Ticketkategorie-IDs. Ein kategorisierter Artikel
# ist genau dann grundsätzlich für Auto-Reply freigegeben, wenn mindestens
# eine seiner GLPI-KB-Kategorien hier enthalten ist.
#
# Mehrere Werte:
# 1,2,7
GLPI_KB_AUTO_REPLY_CATEGORY_IDS=1
# VERALTET / WIRD IGNORIERT:
# Ticket-/ITIL-Kategorien geben einen GLPI-Wissensartikel nicht mehr für
# Auto-Reply frei. Die Variable bleibt nur erhalten, damit alte .env-Dateien
# verständlich migriert werden können. Wert bitte leeren oder entfernen.
GLPI_KB_AUTO_REPLY_ITIL_CATEGORY_IDS=
# GLPI-KB-Artikel ohne Knowledge-Base-Kategorie bleiben standardmäßig gesperrt.
#
# true:
# Solche Artikel dürfen ausschließlich dann Auto-Reply verwenden, wenn ihre
# konkrete GLPI-KnowbaseItem-ID zusätzlich in
# GLPI_KB_AUTO_REPLY_UNCATEGORIZED_ARTICLE_IDS steht.
GLPI_KB_AUTO_REPLY_ALLOW_UNCATEGORIZED=false
# Explizite GLPI-KnowbaseItem-IDs für unkategorisierte Artikel.
# Beispiel: Das synchronisierte Dokument GLPI-KB-1 entspricht Artikel-ID 1.
# Diese Liste ist bei ALLOW_UNCATEGORIZED=true verpflichtend.
GLPI_KB_AUTO_REPLY_UNCATEGORIZED_ARTICLE_IDS=
###############################################################################
# 20. HUMAN-IN-THE-LOOP / KATEGORIE-LERNEN
###############################################################################
# Menschlich bestätigte/korrigierte Entscheidungen als Lernbeispiele verwenden.
#
# Der Agent lernt NICHT automatisch aus seinen eigenen unbestätigten
# Entscheidungen.
LEARNING_ENABLED=true
# Maximale Anzahl gespeicherter Beispiele.
LEARNING_MAX_EXAMPLES=500
# Maximale Beispiele pro Kategorie im Prompt.
LEARNING_EXAMPLES_PER_CATEGORY=5
###############################################################################
# 21. KOMMUNIKATIONSPOLICY
###############################################################################
# Erwartete Sprache von Auto-Reply-KBs.
COMMUNICATION_LANGUAGE=de-DE
# Erwarteter Kommunikationsstil.
COMMUNICATION_STYLE=formal
# Wird vor die Knowledge-Antwort gesetzt.
COMMUNICATION_SALUTATION=Guten Tag,
# Abschluss.
COMMUNICATION_CLOSING=Mit freundlichen Grüßen
COMMUNICATION_SIGNATURE=IT-Service
###############################################################################
# 22. OPERATIONAL CONTEXT - GLOBAL
###############################################################################
# Globaler Schalter für zusätzliche Betriebsinformationen:
# - Changes
# - Major Incidents
# - Requester-Geräte
# - Uptime Kuma
CONTEXT_ENABLED=true
# Timeout für Kontextabfragen.
CONTEXT_TIMEOUT=12s
# Mindestscore, ab dem Incident/Outage als für das Ticket relevant gilt.
CONTEXT_RELEVANCE_MIN_SCORE=0.20
# true:
# Fehler einer aktivierten Kontextquelle blockieren Auto-Reply.
#
# Fail-closed und für Produktion empfohlen.
CONTEXT_BLOCK_AUTO_REPLY_ON_ERRORS=true
# true:
# relevante zentrale Störung blockiert individuelle Standardantwort.
CONTEXT_BLOCK_AUTO_REPLY_ON_INCIDENT=true
###############################################################################
# 23. GLPI CHANGE CALENDAR
###############################################################################
CHANGE_CALENDAR_ENABLED=true
# API-Route.
GLPI_CHANGE_PATH=/Assistance/Change
# Optionaler serverseitiger GLPI-Filter.
GLPI_CHANGE_FILTER=
# Maximale Anzahl geladener Changes.
GLPI_CHANGE_LIMIT=100
# Betrachteter Zeitraum in der Vergangenheit.
CHANGE_LOOKBACK=72h
# Betrachteter Zeitraum in der Zukunft.
CHANGE_LOOKAHEAD=24h
###############################################################################
# 24. MAJOR INCIDENTS
###############################################################################
# Major Incidents über GLPI-Tickets ermitteln.
#
# Erst aktivieren, wenn GLPI_MAJOR_INCIDENT_FILTER getestet wurde.
MAJOR_INCIDENTS_ENABLED=false
# Expliziter Filter für Tickets, die als Major Incident gelten.
GLPI_MAJOR_INCIDENT_FILTER=
GLPI_MAJOR_INCIDENT_LIMIT=20
###############################################################################
# 25. REQUESTER -> GERÄT / ASSET CONTEXT
###############################################################################
# Zusätzlich zu direkt verknüpften Ticket-Assets Geräte des Requesters suchen.
USER_DEVICE_CONTEXT_ENABLED=true
# Asset-Routen.
GLPI_USER_DEVICE_PATHS=/Assets/Computer
# {{user_id}} wird vom Agenten ersetzt.
GLPI_USER_DEVICE_FILTER_TEMPLATE=user.id=={{user_id}}
# Maximale Anzahl Geräte je Suche.
GLPI_USER_DEVICE_LIMIT=20
###############################################################################
# 26. UPTIME KUMA
###############################################################################
# Globaler Schalter für Uptime-Kuma-Kontext.
UPTIME_KUMA_ENABLED=false
UPTIME_KUMA_URL=https://uptime.example.com
# Mögliche Werte:
#
# metrics
# authentifizierte Prometheus-Metrics.
#
# status_page
# öffentliche/publizierte Statusseiten.
UPTIME_KUMA_MODE=metrics
# Nur in metrics erforderlich.
UPTIME_KUMA_API_KEY=
# Nur in status_page erforderlich.
#
# Mehrere Slugs:
# it-services,network,applications
UPTIME_KUMA_STATUS_PAGES=it-services
UPTIME_KUMA_TIMEOUT=10s
# Maximale Anzahl gleichzeitig berücksichtigter Probleme.
UPTIME_KUMA_MAX_ISSUES=20
# Maintenance ebenfalls als Kontext berücksichtigen.
UPTIME_KUMA_INCLUDE_MAINTENANCE=true
# Optional: bei eindeutig passender Uptime-Kuma-Störung oder Wartung einen
# ausschließlich vom Betreiber vorgegebenen Text senden. Die KI erzeugt keinen
# Antworttext; sie wählt nur einen aktiven Kandidaten und liefert eine Confidence.
CONTEXT_STATUS_REPLY_ENABLED=false
CONTEXT_STATUS_REPLY_MIN_RELEVANCE=0.50
CONTEXT_STATUS_REPLY_MIN_AI_CONFIDENCE=0.80
# Finaler Score = Relevanz × KI-Confidence.
CONTEXT_STATUS_REPLY_MIN_FINAL_SCORE=0.45
# Literal \n wird als Zeilenumbruch interpretiert. Verfügbare Platzhalter:
# {{service_name}}, {{status}}, {{status_page}}, {{message}},
# {{incident_title}}, {{incident_content}}, {{last_heartbeat}}
CONTEXT_INCIDENT_REPLY_TEXT=Zu Ihrer Meldung liegt derzeit wahrscheinlich eine zentrale Störung bei {{service_name}} vor. Die Einschränkung kann damit zusammenhängen. Wir beobachten den Status.
CONTEXT_MAINTENANCE_REPLY_TEXT=Für {{service_name}} läuft derzeit eine Wartung. Die von Ihnen beschriebene Einschränkung kann damit zusammenhängen. Bitte testen Sie den Dienst nach Abschluss der Wartung erneut.
###############################################################################
# 27. POLICY-GATES
###############################################################################
# Automatische Kategorisierung zulassen.
AUTO_CATEGORY=true
# Automatische Antworten grundsätzlich zulassen.
#
# DRY_RUN=true verhindert trotzdem das tatsächliche Schreiben nach GLPI.
AUTO_REPLY=false
# Mindestconfidence der KI für Kategorieänderungen.
CATEGORY_CONFIDENCE=0.90
# Mindestconfidence der KI für Antwortauswahl.
#
# Dies allein reicht NICHT für Auto-Reply.
# Zusätzlich gelten unter anderem:
#
# - Knowledge-Evidenz
# - Retrieval-Regeln
# - Source Policy
# - KB auto_reply
# - Kommunikationspolicy
# - Followup-Prüfung
# - Kontext-/Incident-Regeln
# - zweite Followup-Prüfung unmittelbar vor dem Schreiben
REPLY_CONFIDENCE=0.97
###############################################################################
# 28. KI-PRIORISIERUNG
###############################################################################
# Separater KI-Lauf zur Empfehlung der GLPI-Priorität. Der Lauf wird im
# Diagnose-Cockpit unabhängig von Kategorie, Status und Antwort gespeichert.
PRIORITY_ENABLED=true
# Standardmäßig Shadow Mode: Empfehlung und Policy-Gates werden protokolliert,
# GLPI wird nicht verändert. Für Live-Schreibzugriffe zusätzlich DRY_RUN=false.
AUTO_PRIORITY=false
PRIORITY_CONFIDENCE=0.88
# Eigener Fail-open-Timeout für diesen optionalen KI-Lauf. Kategorie und Antwort laufen danach weiter.
PRIORITY_ANALYSIS_TIMEOUT=45s
# Automatische Erhöhung je Ticketlauf; Herabstufungen sind grundsätzlich gesperrt.
PRIORITY_MAX_INCREASE=1
# Nur kontrollierte, kommaseparierte Grundcodes dürfen eine Empfehlung tragen.
PRIORITY_ALLOWED_REASON_CODES=multiple_users_affected,site_affected,organization_affected,core_service_unavailable,security_incident_suspected,data_loss_possible,legal_or_regulatory_risk,business_deadline,no_workaround,safety_relevant,exam_or_event_critical
###############################################################################
# 29. ZEITGESTEUERTE KI-ESKALATION
###############################################################################
# Unabhängiger Scheduler. Er prüft offene Tickets auch ohne Änderung von date_mod.
ESCALATION_ENABLED=false
# Standardmäßig werden nur Diagnose-/Shadow-Läufe erzeugt.
# Live-Ausführung benötigt zusätzlich DRY_RUN=false und GLPI_AGENT_USER_ID.
AUTO_ESCALATION=false
ESCALATION_SCAN_INTERVAL=15m
# Mindestalter des Tickets seit date_creation, bevor es in den Eskalationsscan gelangt.
ESCALATION_MIN_AGE=4h
# Mindestdauer seit der letzten menschlichen Aktivität für den Grund
# no_human_response. SLA-, Security- und Major-Incident-Gründe können unabhängig
# davon greifen. Agent-Followups werden über GLPI_AGENT_USER_ID ausgenommen.
ESCALATION_MIN_INACTIVITY=2h
# Eigenes KI-Zeitbudget; blockiert die normalen Ticketläufe nicht unbegrenzt.
ESCALATION_ANALYSIS_TIMEOUT=45s
ESCALATION_CONFIDENCE=0.88
ESCALATION_MAX_LEVEL=3
# Zeitfenster vor time_to_resolve, in dem sla_at_risk deterministisch wahr wird.
ESCALATION_SLA_RISK_WINDOW=2h
# Aktionsspezifische Mindeststufen.
ESCALATION_SERVICE_OWNER_MIN_LEVEL=2
ESCALATION_MANAGER_REVIEW_MIN_LEVEL=3
# Mindest-Relevanz eines vom Kontextkollektor gelieferten Major Incidents.
ESCALATION_MAJOR_INCIDENT_MIN_RELEVANCE=0.50
ESCALATION_ALLOWED_REASON_CODES=no_human_response,sla_at_risk,sla_breached,business_deadline,no_workaround,security_incident_suspected,unassigned,major_incident_candidate
# Jede Aktion muss einzeln freigegeben werden. Sichere Einführung: zunächst nur
# none,raise_priority; weitere Aktionen erst nach Konfiguration der Ziele aktivieren.
# Verfügbar: none,raise_priority,assign_second_level,assign_security_team,
# notify_service_owner,link_major_incident,request_manager_review
ESCALATION_ALLOWED_ACTIONS=none,raise_priority
# Zielgruppen/-benutzer für Zuweisungs- und Benachrichtigungsaktionen.
# Es handelt sich um numerische GLPI-IDs.
ESCALATION_SECOND_LEVEL_GROUP_ID=0
ESCALATION_SECURITY_GROUP_ID=0
ESCALATION_SERVICE_OWNER_GROUP_ID=0
ESCALATION_SERVICE_OWNER_USER_ID=0
ESCALATION_MANAGER_REVIEW_GROUP_ID=0
ESCALATION_MANAGER_REVIEW_USER_ID=0
# Zu jeder ausgeführten Aktion kann ein privater GLPI-Followup geschrieben werden.
ESCALATION_ADD_PRIVATE_FOLLOWUP=true
# Platzhalter: {{ticket_id}}, {{ticket_name}}, {{level}}, {{action}}, {{reason}},
# {{reason_codes}}, {{major_incident_id}}, {{major_incident_name}},
# {{major_incident_score}}.
# Literal \n wird in Template-Werten als Zeilenumbruch interpretiert.
ESCALATION_SECOND_LEVEL_NOTE=Automatische Eskalation Stufe {{level}}: Übergabe an den Second-Level-Support. Gründe: {{reason_codes}}. KI-Begründung: {{reason}}
ESCALATION_SECURITY_NOTE=Automatische Eskalation Stufe {{level}}: Übergabe an das Security-Team. Gründe: {{reason_codes}}. KI-Begründung: {{reason}}
ESCALATION_SERVICE_OWNER_NOTE=Automatische Eskalation Stufe {{level}}: Service Owner wurde zur Prüfung einbezogen. Gründe: {{reason_codes}}. KI-Begründung: {{reason}}
ESCALATION_MAJOR_INCIDENT_NOTE="Automatische Eskalation Stufe {{level}}: Verknüpfung mit Major Incident #{{major_incident_id}} ({{major_incident_name}}). Relevanz: {{major_incident_score}}. Gründe: {{reason_codes}}."
ESCALATION_MANAGER_REVIEW_NOTE=Automatische Eskalation Stufe {{level}}: Management-Review angefordert. Gründe: {{reason_codes}}. KI-Begründung: {{reason}}
# Optionaler ausgehender Webhook für Service-Owner- und Management-Benachrichtigungen.
# Das Token wird nie über die Status-API ausgegeben.
ESCALATION_WEBHOOK_URL=
ESCALATION_WEBHOOK_BEARER_TOKEN=
ESCALATION_WEBHOOK_TIMEOUT=10s
# Nur für isolierte Testnetze; HTTPS ist der sichere Standard.
ESCALATION_WEBHOOK_ALLOW_INSECURE_HTTP=false
# GLPI-Adapter für Zuweisungen. Die Feldnamen müssen zur OpenAPI-Beschreibung der
# konkreten GLPI-Installation passen. Unterstützte Payload-Formen:
# assigned_groups/assigned_users = Liste von {"id":...};
# group/group_tech/user/user_tech = einzelnes {"id":...}.
GLPI_ESCALATION_GROUP_PATCH_FIELD=assigned_groups
GLPI_ESCALATION_USER_PATCH_FIELD=assigned_users
# Installationsspezifischer Adapter für link_major_incident. Beide Werte sind
# erforderlich. Platzhalter im Pfad/JSON: {{ticket_id}}, {{source_ticket_id}},
# {{major_incident_id}}, {{target_ticket_id}}.
GLPI_ESCALATION_ITIL_LINK_PATH=
GLPI_ESCALATION_ITIL_LINK_BODY=
# Leer = GLPI_TICKET_FILTER verwenden. Für Produktion ausdrücklich auf offene,
# eskalierbare Status und die gewünschte Einheit beschränken.
GLPI_ESCALATION_FILTER=
GLPI_ESCALATION_LIMIT=100
###############################################################################
# 30. WORKER / PRIORITÄTSQUEUE
###############################################################################
# Maximale Anzahl wartender Jobs.
QUEUE_SIZE=256
# Parallele Ticket-Worker. Der Ollama-Pool kann nur so viele unabhängige
# Ticketpipelines gleichzeitig verteilen, wie Worker aktiv sind. Für drei
# gleichartige Nodes ist WORKERS=3 ein sinnvoller Lasttest; jeder Node bleibt
# zusätzlich durch OLLAMA_NODE_MAX_INFLIGHT begrenzt.
WORKERS=2
+13
View File
@@ -47,6 +47,8 @@ Standardmäßig bindet der Stack nur an `127.0.0.1`:
Vor dem ersten produktiven Start bleiben in `.env.example` alle automatischen GLPI-Aktionen deaktiviert und `DRY_RUN=true`.
Die Repository-`.env.example` ist die **vollständige** Mega-Konfiguration und dokumentiert auch die weiterhin unterstützten Agent-Optionen aus älteren Installationen. Hinweise zur Migration und zu Compose-eigenen Containerwerten: [`docs/ENVIRONMENT.md`](docs/ENVIRONMENT.md) und [`docs/ENV-MIGRATION-FROM-LEGACY.md`](docs/ENV-MIGRATION-FROM-LEGACY.md).
## Kontrollierter Vektor-Cutover
`KNOWLEDGE_VECTOR_BACKEND` kennt drei Modi:
@@ -170,3 +172,14 @@ python3 scripts/quality-replay.py docs/QUALITY-REPLAY-example.json --url http://
## Bewusst begrenzte Autonomie
Auch bei aktivierter Research-Autonomie veröffentlicht NeuroForge **nicht selbstständig** in die produktive Knowledgebase. Der technische Draft-Ingress ist vorhanden, aber der Übergang von einem konkreten Research-Run zu einem KB-Draft soll über einen expliziten Workflow/Job erfolgen. Das ist eine Governance-Entscheidung, kein fehlender Schreibweg.
### Goal-Learning separat freigeben
Controlled Learning deaktiviert Goal-Cycle-Lernen standardmäßig. Für bewusst freigegebene manuelle oder autonome Goal-Cycles:
```env
NEUROFORGE_CONTROLLED_LEARNING=true
NEUROFORGE_GOAL_LEARNING_ENABLED=true
```
Damit bleibt rohes Chat-/Assistant-Lernen weiterhin deaktiviert.
+9
View File
@@ -0,0 +1,9 @@
# GLPI NeuroForge Mega v1.4.1
## Fix: Goal learning under Controlled Learning
- Adds `NEUROFORGE_GOAL_LEARNING_ENABLED` as an explicit, independent gate.
- Keeps the safe default `false`.
- Allows goal-cycle learning while `NEUROFORGE_CONTROLLED_LEARNING=true` remains enabled.
- Does not re-enable raw chat input learning, assistant-response learning, or imports.
- Wires the flag through Docker Compose and exposes it read-only in Control Center config.
+10 -4
View File
@@ -48,6 +48,7 @@ services:
NEUROFORGE_OLLAMA_CHAT_MODEL: ${OLLAMA_MODEL:-gemma3}
NEUROFORGE_OLLAMA_EMBEDDING_MODEL: ${OLLAMA_EMBEDDING_MODEL:-embeddinggemma}
NEUROFORGE_CONTROLLED_LEARNING: ${NEUROFORGE_CONTROLLED_LEARNING:-true}
NEUROFORGE_GOAL_LEARNING_ENABLED: ${NEUROFORGE_GOAL_LEARNING_ENABLED:-false}
NEUROFORGE_RESEARCH_ENABLED: ${NEUROFORGE_RESEARCH_ENABLED:-false}
NEUROFORGE_SEARXNG_ENABLED: ${NEUROFORGE_SEARXNG_ENABLED:-false}
NEUROFORGE_SEARXNG_URL: ${NEUROFORGE_SEARXNG_URL:-http://searxng:8080}
@@ -110,6 +111,10 @@ services:
restart: unless-stopped
env_file: .env
environment:
# Internal container values are owned by Compose. This prevents legacy
# standalone .env values (for example HTTP_ADDR=:7080) from breaking
# service-to-service networking in the Mega stack.
HTTP_ADDR: :8080
DATA_DIR: /app/data
KNOWLEDGE_DIR: /app/knowledge
OLLAMA_URL: http://ollama:11434
@@ -133,7 +138,7 @@ services:
- "127.0.0.1:${AGENT_HOST_PORT:-8080}:8080"
volumes:
- agent-data:/app/data
- ./knowledge:/app/knowledge:ro
- ${KB_DATA_PATH:-./knowledge}:/app/knowledge:ro
depends_on:
agent-data-init:
condition: service_completed_successfully
@@ -167,9 +172,9 @@ services:
ports:
- "127.0.0.1:${KNOWLEDGE_HOST_PORT:-8081}:8080"
volumes:
- ./knowledge:/data/knowledge:rw
- ./staging:/data/staging:rw
- ./backups:/data/backups:rw
- ${KB_DATA_PATH:-./knowledge}:/data/knowledge:${KB_DATA_MOUNT_MODE:-rw}
- ${KB_STAGING_PATH:-./staging}:/data/staging:rw
- ${KB_BACKUP_PATH:-./backups}:/data/backups:rw
depends_on:
neuroforge:
condition: service_healthy
@@ -199,6 +204,7 @@ services:
NEUROFORGE_SEARCH_K: ${NEUROFORGE_SEARCH_K:-128}
NEUROFORGE_FAIL_OPEN: ${NEUROFORGE_FAIL_OPEN:-true}
NEUROFORGE_CONTROLLED_LEARNING: ${NEUROFORGE_CONTROLLED_LEARNING:-true}
NEUROFORGE_GOAL_LEARNING_ENABLED: ${NEUROFORGE_GOAL_LEARNING_ENABLED:-false}
OUTCOME_LEARNING_ENABLED: ${OUTCOME_LEARNING_ENABLED:-true}
OUTCOME_RETRIEVAL_ENABLED: ${OUTCOME_RETRIEVAL_ENABLED:-true}
OUTCOME_RETRIEVAL_SEARCH_K: ${OUTCOME_RETRIEVAL_SEARCH_K:-6}
+16
View File
@@ -151,6 +151,7 @@ Research darf außerdem nicht direkt produktive Knowledge-Artikel veröffentlich
```text
NEUROFORGE_CONTROLLED_LEARNING=true
NEUROFORGE_GOAL_LEARNING_ENABLED=false
OUTCOME_LEARNING_ENABLED=true
OUTCOME_LEARNING_FAIL_OPEN=false
NEUROFORGE_RESEARCH_ENABLED=false
@@ -159,3 +160,18 @@ NEUROFORGE_AUTONOMY_ENABLED=false
```
Research anschließend gezielt aktivieren, beobachten und erst danach – falls gewünscht – Autonomy einschalten.
## Goal-Learning als separate Freigabe (v1.4.1)
`NEUROFORGE_CONTROLLED_LEARNING=true` deaktiviert weiterhin rohes Chat-/Assistant-Lernen.
Goal-Cycles besitzen nun einen eigenen Schalter:
```env
NEUROFORGE_CONTROLLED_LEARNING=true
NEUROFORGE_GOAL_LEARNING_ENABLED=true
```
Damit dürfen `RunGoalCycle` und autonome Goals semantische `goal-cycle`-Memories erzeugen,
ohne `LearnChatInputs`, `LearnChatResponses` oder `AllowImports` wieder zu aktivieren.
Für autonome Research-Goals sind zusätzlich die jeweiligen Research-/Autonomy-Schalter nötig.
+80
View File
@@ -0,0 +1,80 @@
# Migration einer bisherigen Agent-.env auf den Mega-Stack
## Ergebnis der Prüfung
Die 110 Variablennamen der bisherigen Agent-Konfiguration werden im aktuellen v1.4.x-Agenten
weiterhin verwendet. Das Problem lag nicht in entfernten Agent-Funktionen, sondern in der zu kurzen
Top-Level-`.env.example` des Mega-Projekts: 86 dieser 110 bisherigen Variablen waren dort nicht
explizit dokumentiert.
Die Repository-`.env.example` ist deshalb jetzt die vollständige kanonische Vorlage.
## Werte, die Compose intern besitzt
Diese Werte sollten im Mega-Stack nicht zur Host-Konfiguration benutzt werden:
| Variable | Mega-Containerwert | Externe Einstellung |
| --- | --- | --- |
| `HTTP_ADDR` | `:8080` | `AGENT_HOST_PORT` |
| `DATA_DIR` | `/app/data` | Docker Volume `agent-data` |
| `KNOWLEDGE_DIR` | `/app/knowledge` | `KB_DATA_PATH` |
| `OLLAMA_URL` | `http://ollama:11434` | Compose-Service `ollama` |
| `NEUROFORGE_URL` | `http://neuroforge:8080` | Compose-Service `neuroforge` |
| `NEUROFORGE_API_KEY` | aus `NEUROFORGE_APP_API_KEY` | `NEUROFORGE_APP_API_KEY` |
| `BRAIN_ACTIVITY_URL` | NeuroForge Event API | intern verdrahtet |
Compose überschreibt `HTTP_ADDR` jetzt explizit. Dadurch kann eine alte Standalone-Konfiguration
mit `HTTP_ADDR=:7080` nicht mehr dazu führen, dass der Container auf einem anderen Port lauscht als
Compose weiterleitet.
## Einstellungen mit relevantem Verhaltensunterschied
Beim bloßen Wechsel von der alten `.env` auf die frühere kurze Mega-`.env.example` hätten sich unter
anderem diese Werte geändert:
| Bereich | bisherige Konfiguration | Verhalten bei fehlender Variable / kurzer Mega-Vorlage |
| --- | --- | --- |
| GLPI KB Connector | aktiv | standardmäßig deaktiviert |
| GLPI-KB Auto-Reply | aktiv | standardmäßig deaktiviert |
| Knowledge Web Edit | aktiv | standardmäßig deaktiviert |
| Allowed Sources | mehrere interne/GLPI/Vendor-Quellen | nur `internal-kb` |
| Auto-Reply Sources | mehrere Quellen | nur `internal-kb` |
| Category Confidence | `0.70` | Code-Default `0.90` |
| Reply Confidence | `0.70` | Code-Default `0.97` |
| Change Lookback | `72h` | Code-Default `48h` |
| Chat-Modell | bisher z. B. `qwen3:8b` | Mega-Vorlage `gemma3` |
Diese Unterschiede sind nicht automatisch falsch, müssen aber bewusst entschieden werden.
## Neue Mega-Einstellungen
Neu gegenüber der bisherigen Agent-Only-Konfiguration sind insbesondere:
- NeuroForge Admin/App/Worker/Metrics Tokens
- `KNOWLEDGE_VECTOR_BACKEND=local|dual|neuroforge`
- NeuroForge Namespace/Search/Failure Policy
- Controlled Learning
- Human-validated Outcome Learning
- Outcome Retrieval
- Research/SearXNG
- getrennte Autonomy-Aktivierung
- Knowledge Integration Token
- scoped `CONTROL_READ_TOKEN`
- Control Center / NeuroForge / Knowledge Host Ports
- optionale Codebase-Memory-UI
## Empfohlene Migration
1. Neue `.env` aus der vollständigen `.env.example` erzeugen.
2. Neue Service-Tokens mit `./scripts/generate-secrets.sh` erzeugen.
3. GLPI-Zugangsdaten neu eintragen.
4. Gewünschte alte Retrieval-/Context-/Communication-Werte bewusst übertragen.
5. Zunächst `DRY_RUN=true` und alle automatischen Schreibaktionen deaktiviert lassen.
6. GLPI KB Sync, Knowledge Retrieval, Outcome Retrieval und NeuroForge im `dual`-Modus prüfen.
7. Erst danach einzelne Schreibfunktionen kontrolliert aktivieren.
## Credential-Hygiene
Zugangsdaten, die in Chat, Tickets, CI-Logs oder Screenshots veröffentlicht wurden, gelten nicht mehr
als geheim und sollten vor Produktionsbetrieb rotiert werden. Das betrifft insbesondere GLPI
Client-Secrets/Passwörter, Web-Passwörter und Webhook-Secrets.
+65
View File
@@ -0,0 +1,65 @@
# Environment configuration (v1.4.x)
The repository-level `.env.example` is the canonical configuration template for the Mega stack.
It intentionally includes the complete GLPI Agent configuration plus NeuroForge, controlled-learning,
Knowledge Editor, Control Center and optional Research/SearXNG settings.
## Important migration rule
Do not copy the old standalone agent `.env` unchanged into the Mega stack without reviewing it.
The old variables are still supported, but container-internal values are now owned by Compose:
- `HTTP_ADDR=:8080`
- `DATA_DIR=/app/data`
- `KNOWLEDGE_DIR=/app/knowledge`
- `OLLAMA_URL=http://ollama:11434`
- `NEUROFORGE_URL=http://neuroforge:8080`
- `NEUROFORGE_API_KEY` is derived from `NEUROFORGE_APP_API_KEY`
- Brain-activity endpoints are wired internally by Compose
The host-facing ports are configured separately with `AGENT_HOST_PORT`, `KNOWLEDGE_HOST_PORT`,
`CONTROL_HOST_PORT`, `NEUROFORGE_HOST_PORT`, `OLLAMA_HOST_PORT` and `SEARXNG_HOST_PORT`.
## First setup
```sh
cp .env.example .env
./scripts/generate-secrets.sh
```
Copy the generated values into `.env`, then configure the required GLPI credentials:
- `GLPI_URL`
- `GLPI_CLIENT_ID`
- `GLPI_CLIENT_SECRET`
- `GLPI_USERNAME`
- `GLPI_PASSWORD`
- `GLPI_AGENT_USER_ID` before enabling Auto Reply / escalation writes
Keep `DRY_RUN=true`, `AUTO_REPLY=false`, `AUTO_PRIORITY=false` and `AUTO_ESCALATION=false`
for the first integration tests.
## Legacy behavior that is no longer represented by defaults
A migration from an older agent `.env` can materially change behavior if only the short Mega template
is used. In particular review:
- `GLPI_KB_ENABLED`
- `GLPI_KB_AUTO_REPLY`
- `GLPI_KB_AUTO_REPLY_CATEGORY_IDS`
- `KNOWLEDGE_ALLOWED_SOURCES`
- `KNOWLEDGE_AUTO_REPLY_SOURCES`
- `KNOWLEDGE_WEB_EDIT_ENABLED`
- `CATEGORY_CONFIDENCE`
- `REPLY_CONFIDENCE`
- Context / Change / Uptime Kuma options
- Priority and escalation policy
- Communication policy
The canonical `.env.example` now contains these settings explicitly.
## Secrets
Never commit `.env`. The tracked file must remain `.env.example` only.
If credentials were pasted into issue trackers, chats, CI logs, shell history or screenshots,
rotate them before production use.
+1 -1
View File
@@ -1,4 +1,4 @@
go 1.26
go 1.23
use (
./platform/neuroforge
+145
View File
@@ -0,0 +1,145 @@
diff -ruN '--exclude=patches' /mnt/data/_inspect140/glpi-neuroforge-mega-v1.4.0-gitea-envfix/.env.example /mnt/data/glpi-neuroforge-mega-v1.4.1-gitea/.env.example
--- /mnt/data/_inspect140/glpi-neuroforge-mega-v1.4.0-gitea-envfix/.env.example 2026-08-26 18:29:23.000000000 +0000
+++ /mnt/data/glpi-neuroforge-mega-v1.4.1-gitea/.env.example 2026-08-26 19:16:45.040061919 +0000
@@ -105,6 +105,9 @@
###############################################################################
# Verhindert automatisches Langzeitlernen aus rohem Chatinput/AI-Ausgaben.
NEUROFORGE_CONTROLLED_LEARNING=true
+# Separate gate for semantic goal-cycle memories. Required for manual/autonomous
+# Goal cycles to learn while Controlled Learning remains enabled.
+NEUROFORGE_GOAL_LEARNING_ENABLED=false
# Ticket -> KI-Vorschlag -> Techniker bestätigt/korrigiert -> Trusted Outcome.
OUTCOME_LEARNING_ENABLED=true
diff -ruN '--exclude=patches' /mnt/data/_inspect140/glpi-neuroforge-mega-v1.4.0-gitea-envfix/README.md /mnt/data/glpi-neuroforge-mega-v1.4.1-gitea/README.md
--- /mnt/data/_inspect140/glpi-neuroforge-mega-v1.4.0-gitea-envfix/README.md 2026-08-26 18:30:20.000000000 +0000
+++ /mnt/data/glpi-neuroforge-mega-v1.4.1-gitea/README.md 2026-08-26 19:16:45.040936022 +0000
@@ -172,3 +172,14 @@
## Bewusst begrenzte Autonomie
Auch bei aktivierter Research-Autonomie veröffentlicht NeuroForge **nicht selbstständig** in die produktive Knowledgebase. Der technische Draft-Ingress ist vorhanden, aber der Übergang von einem konkreten Research-Run zu einem KB-Draft soll über einen expliziten Workflow/Job erfolgen. Das ist eine Governance-Entscheidung, kein fehlender Schreibweg.
+
+### Goal-Learning separat freigeben
+
+Controlled Learning deaktiviert Goal-Cycle-Lernen standardmäßig. Für bewusst freigegebene manuelle oder autonome Goal-Cycles:
+
+```env
+NEUROFORGE_CONTROLLED_LEARNING=true
+NEUROFORGE_GOAL_LEARNING_ENABLED=true
+```
+
+Damit bleibt rohes Chat-/Assistant-Lernen weiterhin deaktiviert.
diff -ruN '--exclude=patches' /mnt/data/_inspect140/glpi-neuroforge-mega-v1.4.0-gitea-envfix/RELEASE-NOTES-v1.4.1.md /mnt/data/glpi-neuroforge-mega-v1.4.1-gitea/RELEASE-NOTES-v1.4.1.md
--- /mnt/data/_inspect140/glpi-neuroforge-mega-v1.4.0-gitea-envfix/RELEASE-NOTES-v1.4.1.md 1970-01-01 00:00:00.000000000 +0000
+++ /mnt/data/glpi-neuroforge-mega-v1.4.1-gitea/RELEASE-NOTES-v1.4.1.md 2026-08-26 19:16:45.041115446 +0000
@@ -0,0 +1,9 @@
+# GLPI NeuroForge Mega v1.4.1
+
+## Fix: Goal learning under Controlled Learning
+
+- Adds `NEUROFORGE_GOAL_LEARNING_ENABLED` as an explicit, independent gate.
+- Keeps the safe default `false`.
+- Allows goal-cycle learning while `NEUROFORGE_CONTROLLED_LEARNING=true` remains enabled.
+- Does not re-enable raw chat input learning, assistant-response learning, or imports.
+- Wires the flag through Docker Compose and exposes it read-only in Control Center config.
diff -ruN '--exclude=patches' /mnt/data/_inspect140/glpi-neuroforge-mega-v1.4.0-gitea-envfix/docker-compose.yml /mnt/data/glpi-neuroforge-mega-v1.4.1-gitea/docker-compose.yml
--- /mnt/data/_inspect140/glpi-neuroforge-mega-v1.4.0-gitea-envfix/docker-compose.yml 2026-08-26 18:27:35.000000000 +0000
+++ /mnt/data/glpi-neuroforge-mega-v1.4.1-gitea/docker-compose.yml 2026-08-26 19:16:45.040327469 +0000
@@ -48,6 +48,7 @@
NEUROFORGE_OLLAMA_CHAT_MODEL: ${OLLAMA_MODEL:-gemma3}
NEUROFORGE_OLLAMA_EMBEDDING_MODEL: ${OLLAMA_EMBEDDING_MODEL:-embeddinggemma}
NEUROFORGE_CONTROLLED_LEARNING: ${NEUROFORGE_CONTROLLED_LEARNING:-true}
+ NEUROFORGE_GOAL_LEARNING_ENABLED: ${NEUROFORGE_GOAL_LEARNING_ENABLED:-false}
NEUROFORGE_RESEARCH_ENABLED: ${NEUROFORGE_RESEARCH_ENABLED:-false}
NEUROFORGE_SEARXNG_ENABLED: ${NEUROFORGE_SEARXNG_ENABLED:-false}
NEUROFORGE_SEARXNG_URL: ${NEUROFORGE_SEARXNG_URL:-http://searxng:8080}
@@ -203,6 +204,7 @@
NEUROFORGE_SEARCH_K: ${NEUROFORGE_SEARCH_K:-128}
NEUROFORGE_FAIL_OPEN: ${NEUROFORGE_FAIL_OPEN:-true}
NEUROFORGE_CONTROLLED_LEARNING: ${NEUROFORGE_CONTROLLED_LEARNING:-true}
+ NEUROFORGE_GOAL_LEARNING_ENABLED: ${NEUROFORGE_GOAL_LEARNING_ENABLED:-false}
OUTCOME_LEARNING_ENABLED: ${OUTCOME_LEARNING_ENABLED:-true}
OUTCOME_RETRIEVAL_ENABLED: ${OUTCOME_RETRIEVAL_ENABLED:-true}
OUTCOME_RETRIEVAL_SEARCH_K: ${OUTCOME_RETRIEVAL_SEARCH_K:-6}
diff -ruN '--exclude=patches' /mnt/data/_inspect140/glpi-neuroforge-mega-v1.4.0-gitea-envfix/docs/CONTROLLED-AUTONOMY.md /mnt/data/glpi-neuroforge-mega-v1.4.1-gitea/docs/CONTROLLED-AUTONOMY.md
--- /mnt/data/_inspect140/glpi-neuroforge-mega-v1.4.0-gitea-envfix/docs/CONTROLLED-AUTONOMY.md 2026-08-26 04:47:34.000000000 +0000
+++ /mnt/data/glpi-neuroforge-mega-v1.4.1-gitea/docs/CONTROLLED-AUTONOMY.md 2026-08-26 19:16:45.040751411 +0000
@@ -151,6 +151,7 @@
```text
NEUROFORGE_CONTROLLED_LEARNING=true
+NEUROFORGE_GOAL_LEARNING_ENABLED=false
OUTCOME_LEARNING_ENABLED=true
OUTCOME_LEARNING_FAIL_OPEN=false
NEUROFORGE_RESEARCH_ENABLED=false
@@ -159,3 +160,18 @@
```
Research anschließend gezielt aktivieren, beobachten und erst danach – falls gewünscht – Autonomy einschalten.
+
+
+## Goal-Learning als separate Freigabe (v1.4.1)
+
+`NEUROFORGE_CONTROLLED_LEARNING=true` deaktiviert weiterhin rohes Chat-/Assistant-Lernen.
+Goal-Cycles besitzen nun einen eigenen Schalter:
+
+```env
+NEUROFORGE_CONTROLLED_LEARNING=true
+NEUROFORGE_GOAL_LEARNING_ENABLED=true
+```
+
+Damit dürfen `RunGoalCycle` und autonome Goals semantische `goal-cycle`-Memories erzeugen,
+ohne `LearnChatInputs`, `LearnChatResponses` oder `AllowImports` wieder zu aktivieren.
+Für autonome Research-Goals sind zusätzlich die jeweiligen Research-/Autonomy-Schalter nötig.
diff -ruN '--exclude=patches' /mnt/data/_inspect140/glpi-neuroforge-mega-v1.4.0-gitea-envfix/platform/neuroforge/cmd/server/main.go /mnt/data/glpi-neuroforge-mega-v1.4.1-gitea/platform/neuroforge/cmd/server/main.go
--- /mnt/data/_inspect140/glpi-neuroforge-mega-v1.4.0-gitea-envfix/platform/neuroforge/cmd/server/main.go 2026-08-25 19:00:18.000000000 +0000
+++ /mnt/data/glpi-neuroforge-mega-v1.4.1-gitea/platform/neuroforge/cmd/server/main.go 2026-08-26 19:16:45.039341672 +0000
@@ -144,6 +144,19 @@
return fmt.Errorf("apply controlled learning bootstrap: %w", err)
}
}
+ // Goal-cycle learning is an independent trust boundary. Controlled learning
+ // keeps it disabled by default, but operators may explicitly enable it
+ // without re-enabling raw chat/input learning or memory imports. Apply this
+ // override after the controlled-learning bootstrap so the explicit setting
+ // wins on every restart.
+ if v, ok := envBool("NEUROFORGE_GOAL_LEARNING_ENABLED"); ok {
+ cfg := s.Config()
+ cfg.Brain.LearningPolicy.LearnGoalCycles = v
+ if err := s.UpdateConfig(cfg); err != nil {
+ return fmt.Errorf("apply goal learning environment bootstrap: %w", err)
+ }
+ }
+
if _, hasResearch := os.LookupEnv("NEUROFORGE_RESEARCH_ENABLED"); hasResearch {
cfg := s.Config()
if v, ok := envBool("NEUROFORGE_RESEARCH_ENABLED"); ok {
diff -ruN '--exclude=patches' /mnt/data/_inspect140/glpi-neuroforge-mega-v1.4.0-gitea-envfix/services/control/main.go /mnt/data/glpi-neuroforge-mega-v1.4.1-gitea/services/control/main.go
--- /mnt/data/_inspect140/glpi-neuroforge-mega-v1.4.0-gitea-envfix/services/control/main.go 2026-08-26 15:17:10.000000000 +0000
+++ /mnt/data/glpi-neuroforge-mega-v1.4.1-gitea/services/control/main.go 2026-08-26 19:16:45.040515305 +0000
@@ -50,6 +50,7 @@
neuroforgeSearchK string
failOpen string
controlledLearning string
+ goalLearning string
outcomeLearning string
outcomeRetrieval string
outcomeSearchK string
@@ -75,7 +76,7 @@
if nfKeyRaw != "" {
nfAuth = "Bearer " + nfKeyRaw
}
- s := &server{http: &http.Client{Timeout: 6 * time.Second}, agentURL: strings.TrimRight(agentURL, "/"), agentReadToken: strings.TrimSpace(os.Getenv("CONTROL_READ_TOKEN")), neuroforgeURL: strings.TrimRight(nfURL, "/"), neuroforgeKey: nfKeyRaw, codebaseMemoryURL: strings.TrimRight(strings.TrimSpace(os.Getenv("CODEBASE_MEMORY_URL")), "/"), codebaseMemoryPublicURL: strings.TrimRight(strings.TrimSpace(os.Getenv("PUBLIC_CODEBASE_MEMORY_URL")), "/"), vectorMode: env("KNOWLEDGE_VECTOR_BACKEND", "dual"), neuroforgeSearchK: env("NEUROFORGE_SEARCH_K", "128"), failOpen: env("NEUROFORGE_FAIL_OPEN", "true"), controlledLearning: env("NEUROFORGE_CONTROLLED_LEARNING", "true"), outcomeLearning: env("OUTCOME_LEARNING_ENABLED", "true"), outcomeRetrieval: env("OUTCOME_RETRIEVAL_ENABLED", "true"), outcomeSearchK: env("OUTCOME_RETRIEVAL_SEARCH_K", "6"), outcomeMinSimilarity: env("OUTCOME_RETRIEVAL_MIN_SIMILARITY", "0.58"), outcomeFailOpen: env("OUTCOME_RETRIEVAL_FAIL_OPEN", "true"), researchEnabled: env("NEUROFORGE_RESEARCH_ENABLED", "false"), searxngEnabled: env("NEUROFORGE_SEARXNG_ENABLED", "false"), autonomyEnabled: env("NEUROFORGE_AUTONOMY_ENABLED", "false")}
+ s := &server{http: &http.Client{Timeout: 6 * time.Second}, agentURL: strings.TrimRight(agentURL, "/"), agentReadToken: strings.TrimSpace(os.Getenv("CONTROL_READ_TOKEN")), neuroforgeURL: strings.TrimRight(nfURL, "/"), neuroforgeKey: nfKeyRaw, codebaseMemoryURL: strings.TrimRight(strings.TrimSpace(os.Getenv("CODEBASE_MEMORY_URL")), "/"), codebaseMemoryPublicURL: strings.TrimRight(strings.TrimSpace(os.Getenv("PUBLIC_CODEBASE_MEMORY_URL")), "/"), vectorMode: env("KNOWLEDGE_VECTOR_BACKEND", "dual"), neuroforgeSearchK: env("NEUROFORGE_SEARCH_K", "128"), failOpen: env("NEUROFORGE_FAIL_OPEN", "true"), controlledLearning: env("NEUROFORGE_CONTROLLED_LEARNING", "true"), goalLearning: env("NEUROFORGE_GOAL_LEARNING_ENABLED", "false"), outcomeLearning: env("OUTCOME_LEARNING_ENABLED", "true"), outcomeRetrieval: env("OUTCOME_RETRIEVAL_ENABLED", "true"), outcomeSearchK: env("OUTCOME_RETRIEVAL_SEARCH_K", "6"), outcomeMinSimilarity: env("OUTCOME_RETRIEVAL_MIN_SIMILARITY", "0.58"), outcomeFailOpen: env("OUTCOME_RETRIEVAL_FAIL_OPEN", "true"), researchEnabled: env("NEUROFORGE_RESEARCH_ENABLED", "false"), searxngEnabled: env("NEUROFORGE_SEARXNG_ENABLED", "false"), autonomyEnabled: env("NEUROFORGE_AUTONOMY_ENABLED", "false")}
s.targets = []target{
{ID: "agent", Name: "GLPI AI Agent", URL: agentURL, PublicURL: env("PUBLIC_AGENT_URL", "http://localhost:8080"), Path: "/readyz"},
{ID: "knowledge", Name: "Knowledgebase", URL: env("KNOWLEDGE_URL", "http://knowledge:8080"), PublicURL: env("PUBLIC_KNOWLEDGE_URL", "http://localhost:8081"), Path: "/api/health"},
@@ -123,7 +124,7 @@
}
func (s *server) handleConfig(w http.ResponseWriter, r *http.Request) {
- writeJSON(w, 200, map[string]any{"vector_backend": s.vectorMode, "neuroforge_search_k": s.neuroforgeSearchK, "neuroforge_fail_open": s.failOpen, "controlled_learning": s.controlledLearning, "outcome_learning": s.outcomeLearning, "outcome_retrieval": s.outcomeRetrieval, "outcome_retrieval_search_k": s.outcomeSearchK, "outcome_retrieval_min_similarity": s.outcomeMinSimilarity, "outcome_retrieval_fail_open": s.outcomeFailOpen, "quality_replay": "available-on-agent", "research_enabled": s.researchEnabled, "searxng_enabled": s.searxngEnabled, "autonomy_enabled": s.autonomyEnabled, "control_plane": "read-only", "policy_owner": "glpi-agent", "unified_graph": true, "engineering_graph": "embedded-ast", "codebase_memory_url": s.codebaseMemoryPublicURL})
+ writeJSON(w, 200, map[string]any{"vector_backend": s.vectorMode, "neuroforge_search_k": s.neuroforgeSearchK, "neuroforge_fail_open": s.failOpen, "controlled_learning": s.controlledLearning, "goal_learning": s.goalLearning, "outcome_learning": s.outcomeLearning, "outcome_retrieval": s.outcomeRetrieval, "outcome_retrieval_search_k": s.outcomeSearchK, "outcome_retrieval_min_similarity": s.outcomeMinSimilarity, "outcome_retrieval_fail_open": s.outcomeFailOpen, "quality_replay": "available-on-agent", "research_enabled": s.researchEnabled, "searxng_enabled": s.searxngEnabled, "autonomy_enabled": s.autonomyEnabled, "control_plane": "read-only", "policy_owner": "glpi-agent", "unified_graph": true, "engineering_graph": "embedded-ast", "codebase_memory_url": s.codebaseMemoryPublicURL})
}
func (s *server) handleStatus(w http.ResponseWriter, r *http.Request) {
+3 -3
View File
@@ -1,4 +1,4 @@
FROM golang:1.26-alpine AS build
FROM golang:1.23-alpine AS build
WORKDIR /src
COPY go.mod ./
COPY cmd ./cmd
@@ -7,7 +7,7 @@ RUN CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /out/neuroforge ./cmd/s
CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /out/neuroforge-worker ./cmd/worker && \
CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /out/neuroforge-bench ./cmd/bench
FROM alpine:3.24 AS server
FROM alpine:3.21 AS server
RUN apk add --no-cache ca-certificates poppler-utils && \
addgroup -S neuroforge && adduser -S -G neuroforge neuroforge && \
mkdir -p /app/data && chown -R neuroforge:neuroforge /app
@@ -19,7 +19,7 @@ EXPOSE 8080
HEALTHCHECK --interval=15s --timeout=3s --start-period=10s --retries=4 CMD wget -q -O - http://127.0.0.1:8080/readyz >/dev/null || exit 1
ENTRYPOINT ["neuroforge", "-data", "/app/data", "-listen", ":8080"]
FROM alpine:3.24 AS worker
FROM alpine:3.21 AS worker
RUN apk add --no-cache ca-certificates && addgroup -S neuroforge && adduser -S -G neuroforge neuroforge
COPY --from=build /out/neuroforge-worker /usr/local/bin/neuroforge-worker
USER neuroforge
+13
View File
@@ -144,6 +144,19 @@ func run() (retErr error) {
return fmt.Errorf("apply controlled learning bootstrap: %w", err)
}
}
// Goal-cycle learning is an independent trust boundary. Controlled learning
// keeps it disabled by default, but operators may explicitly enable it
// without re-enabling raw chat/input learning or memory imports. Apply this
// override after the controlled-learning bootstrap so the explicit setting
// wins on every restart.
if v, ok := envBool("NEUROFORGE_GOAL_LEARNING_ENABLED"); ok {
cfg := s.Config()
cfg.Brain.LearningPolicy.LearnGoalCycles = v
if err := s.UpdateConfig(cfg); err != nil {
return fmt.Errorf("apply goal learning environment bootstrap: %w", err)
}
}
if _, hasResearch := os.LookupEnv("NEUROFORGE_RESEARCH_ENABLED"); hasResearch {
cfg := s.Config()
if v, ok := envBool("NEUROFORGE_RESEARCH_ENABLED"); ok {
+1 -1
View File
@@ -1,3 +1,3 @@
module neuroforge
go 1.26
go 1.23
+8
View File
@@ -1,7 +1,10 @@
#!/bin/sh
set -eu
gen() { openssl rand -hex 32; }
cat <<OUT
# Mega service tokens
NEUROFORGE_ADMIN_TOKEN=$(gen)
NEUROFORGE_APP_API_KEY=$(gen)
NEUROFORGE_WORKER_TOKEN=$(gen)
@@ -9,4 +12,9 @@ NEUROFORGE_METRICS_TOKEN=$(gen)
KB_INTEGRATION_TOKEN=$(gen)
CONTROL_READ_TOKEN=$(gen)
SEARXNG_SECRET=$(gen)
# Web/UI and optional webhook secrets
WEB_PASSWORD=$(gen)
BASIC_AUTH_PASSWORD=$(gen)
WEBHOOK_SECRET=$(gen)
OUT
+3
View File
@@ -1,3 +1,6 @@
# NOTE: For the GLPI NeuroForge Mega stack use the repository-level /.env.example.
# This file is retained for standalone agent compatibility and historical documentation.
#
###############################################################################
# GLPI AI STACK - GEMEINSAME .ENV
#
+3 -2
View File
@@ -50,6 +50,7 @@ type server struct {
neuroforgeSearchK string
failOpen string
controlledLearning string
goalLearning string
outcomeLearning string
outcomeRetrieval string
outcomeSearchK string
@@ -75,7 +76,7 @@ func main() {
if nfKeyRaw != "" {
nfAuth = "Bearer " + nfKeyRaw
}
s := &server{http: &http.Client{Timeout: 6 * time.Second}, agentURL: strings.TrimRight(agentURL, "/"), agentReadToken: strings.TrimSpace(os.Getenv("CONTROL_READ_TOKEN")), neuroforgeURL: strings.TrimRight(nfURL, "/"), neuroforgeKey: nfKeyRaw, codebaseMemoryURL: strings.TrimRight(strings.TrimSpace(os.Getenv("CODEBASE_MEMORY_URL")), "/"), codebaseMemoryPublicURL: strings.TrimRight(strings.TrimSpace(os.Getenv("PUBLIC_CODEBASE_MEMORY_URL")), "/"), vectorMode: env("KNOWLEDGE_VECTOR_BACKEND", "dual"), neuroforgeSearchK: env("NEUROFORGE_SEARCH_K", "128"), failOpen: env("NEUROFORGE_FAIL_OPEN", "true"), controlledLearning: env("NEUROFORGE_CONTROLLED_LEARNING", "true"), outcomeLearning: env("OUTCOME_LEARNING_ENABLED", "true"), outcomeRetrieval: env("OUTCOME_RETRIEVAL_ENABLED", "true"), outcomeSearchK: env("OUTCOME_RETRIEVAL_SEARCH_K", "6"), outcomeMinSimilarity: env("OUTCOME_RETRIEVAL_MIN_SIMILARITY", "0.58"), outcomeFailOpen: env("OUTCOME_RETRIEVAL_FAIL_OPEN", "true"), researchEnabled: env("NEUROFORGE_RESEARCH_ENABLED", "false"), searxngEnabled: env("NEUROFORGE_SEARXNG_ENABLED", "false"), autonomyEnabled: env("NEUROFORGE_AUTONOMY_ENABLED", "false")}
s := &server{http: &http.Client{Timeout: 6 * time.Second}, agentURL: strings.TrimRight(agentURL, "/"), agentReadToken: strings.TrimSpace(os.Getenv("CONTROL_READ_TOKEN")), neuroforgeURL: strings.TrimRight(nfURL, "/"), neuroforgeKey: nfKeyRaw, codebaseMemoryURL: strings.TrimRight(strings.TrimSpace(os.Getenv("CODEBASE_MEMORY_URL")), "/"), codebaseMemoryPublicURL: strings.TrimRight(strings.TrimSpace(os.Getenv("PUBLIC_CODEBASE_MEMORY_URL")), "/"), vectorMode: env("KNOWLEDGE_VECTOR_BACKEND", "dual"), neuroforgeSearchK: env("NEUROFORGE_SEARCH_K", "128"), failOpen: env("NEUROFORGE_FAIL_OPEN", "true"), controlledLearning: env("NEUROFORGE_CONTROLLED_LEARNING", "true"), goalLearning: env("NEUROFORGE_GOAL_LEARNING_ENABLED", "false"), outcomeLearning: env("OUTCOME_LEARNING_ENABLED", "true"), outcomeRetrieval: env("OUTCOME_RETRIEVAL_ENABLED", "true"), outcomeSearchK: env("OUTCOME_RETRIEVAL_SEARCH_K", "6"), outcomeMinSimilarity: env("OUTCOME_RETRIEVAL_MIN_SIMILARITY", "0.58"), outcomeFailOpen: env("OUTCOME_RETRIEVAL_FAIL_OPEN", "true"), researchEnabled: env("NEUROFORGE_RESEARCH_ENABLED", "false"), searxngEnabled: env("NEUROFORGE_SEARXNG_ENABLED", "false"), autonomyEnabled: env("NEUROFORGE_AUTONOMY_ENABLED", "false")}
s.targets = []target{
{ID: "agent", Name: "GLPI AI Agent", URL: agentURL, PublicURL: env("PUBLIC_AGENT_URL", "http://localhost:8080"), Path: "/readyz"},
{ID: "knowledge", Name: "Knowledgebase", URL: env("KNOWLEDGE_URL", "http://knowledge:8080"), PublicURL: env("PUBLIC_KNOWLEDGE_URL", "http://localhost:8081"), Path: "/api/health"},
@@ -123,7 +124,7 @@ func secure(next http.Handler) http.Handler {
}
func (s *server) handleConfig(w http.ResponseWriter, r *http.Request) {
writeJSON(w, 200, map[string]any{"vector_backend": s.vectorMode, "neuroforge_search_k": s.neuroforgeSearchK, "neuroforge_fail_open": s.failOpen, "controlled_learning": s.controlledLearning, "outcome_learning": s.outcomeLearning, "outcome_retrieval": s.outcomeRetrieval, "outcome_retrieval_search_k": s.outcomeSearchK, "outcome_retrieval_min_similarity": s.outcomeMinSimilarity, "outcome_retrieval_fail_open": s.outcomeFailOpen, "quality_replay": "available-on-agent", "research_enabled": s.researchEnabled, "searxng_enabled": s.searxngEnabled, "autonomy_enabled": s.autonomyEnabled, "control_plane": "read-only", "policy_owner": "glpi-agent", "unified_graph": true, "engineering_graph": "embedded-ast", "codebase_memory_url": s.codebaseMemoryPublicURL})
writeJSON(w, 200, map[string]any{"vector_backend": s.vectorMode, "neuroforge_search_k": s.neuroforgeSearchK, "neuroforge_fail_open": s.failOpen, "controlled_learning": s.controlledLearning, "goal_learning": s.goalLearning, "outcome_learning": s.outcomeLearning, "outcome_retrieval": s.outcomeRetrieval, "outcome_retrieval_search_k": s.outcomeSearchK, "outcome_retrieval_min_similarity": s.outcomeMinSimilarity, "outcome_retrieval_fail_open": s.outcomeFailOpen, "quality_replay": "available-on-agent", "research_enabled": s.researchEnabled, "searxng_enabled": s.searxngEnabled, "autonomy_enabled": s.autonomyEnabled, "control_plane": "read-only", "policy_owner": "glpi-agent", "unified_graph": true, "engineering_graph": "embedded-ast", "codebase_memory_url": s.codebaseMemoryPublicURL})
}
func (s *server) handleStatus(w http.ResponseWriter, r *http.Request) {