diff --git a/.gitignore b/.gitignore index 6df3587c..b167e66e 100644 --- a/.gitignore +++ b/.gitignore @@ -2481,3 +2481,5 @@ /sonar-export/issues/ /sonar-export-fresh/issues/ /test-results/ +/doc-noindex/presentation/intro/goodone_technical_notes_package/ +/doc-noindex/presentation/intro/goodone_speaker_notes/ diff --git a/.junie/guidelines.md b/.junie/guidelines.md index 32324a18..cfa40ca0 100644 --- a/.junie/guidelines.md +++ b/.junie/guidelines.md @@ -67,6 +67,7 @@ This document outlines the best practices and standards for the GoodOne project. - Application can be demoed repeatedly without manual fixes. - Playwright UX guardrails are successful (`npx playwright test e2e/ux-guardrails.spec.ts`). - **Task Log Update**: The relevant task `.md` file MUST be updated with a log entry and testing instructions. + - **Traceability**: PR and Commit links MUST be added to the YAML frontmatter and `## Links` section. - **Basic Regression**: All relevant unit and E2E tests MUST pass before reporting "DONE". - **Docker First**: Ensure all changes are compatible with the Docker-based deployment. - **Language**: Always communicate in English for all interactions, thoughts, and documentation, unless explicitly requested otherwise by the user. diff --git a/backend/src/main/java/ch/goodone/backend/ai/AiProperties.java b/backend/src/main/java/ch/goodone/backend/ai/AiProperties.java index f8fd115a..42347d20 100644 --- a/backend/src/main/java/ch/goodone/backend/ai/AiProperties.java +++ b/backend/src/main/java/ch/goodone/backend/ai/AiProperties.java @@ -15,11 +15,11 @@ public class AiProperties { private String disabledMessage = "AI features are currently disabled by the administrator."; private boolean loggingDetailed = false; - private CapabilityConfig quickAdd; - private CapabilityConfig architecture; - private CapabilityConfig retrospective; - private CapabilityConfig embedding; - private EvaluationConfig evaluation; + private CapabilityConfig quickAdd = new CapabilityConfig(); + private CapabilityConfig architecture = new CapabilityConfig(); + private CapabilityConfig retrospective = new CapabilityConfig(); + private CapabilityConfig embedding = new CapabilityConfig(); + private EvaluationConfig evaluation = new EvaluationConfig(); private PromptConfig prompt = new PromptConfig(); /** @@ -35,6 +35,7 @@ public String resolvePromptVersion(String feature, String defaultVersion) { return defaultVersion; } } + private RoutingConfig routing = new RoutingConfig(); private Map pricing; private OpenAiConfig openai; @@ -83,7 +84,7 @@ public static class RoutingConfig { @Data public static class OpenAiConfig { private String apiKey; - private String chatModel = "gpt-4o"; + private String chatModel = "gpt-4o-mini"; private String embeddingModel = "text-embedding-3-small"; private String baseUrl = "https://api.openai.com/v1"; private Double temperature; @@ -104,8 +105,8 @@ public static class OllamaConfig { @Data public static class CapabilityConfig { - private String provider; - private String model; + private String provider = "openai"; + private String model = "gpt-4o-mini"; private boolean enabled = true; private int topK = 6; } diff --git a/backend/src/main/java/ch/goodone/backend/ai/application/AiDashboardExplanationService.java b/backend/src/main/java/ch/goodone/backend/ai/application/AiDashboardExplanationService.java index 11eca987..edfde0ed 100644 --- a/backend/src/main/java/ch/goodone/backend/ai/application/AiDashboardExplanationService.java +++ b/backend/src/main/java/ch/goodone/backend/ai/application/AiDashboardExplanationService.java @@ -71,8 +71,12 @@ public String explainBacklogLeakage(AiIntelligenceDashboardDto.BacklogLeakageSum private String callJudge(String promptText, String operation, String sprintId) { ChatModel model = aiProviderService.getEvaluationChatModel(); - String modelName = aiProperties.getEvaluation().getModel(); - String provider = aiProperties.getEvaluation().getProvider(); + String modelName = (aiProperties.getEvaluation() != null && aiProperties.getEvaluation().getModel() != null) + ? aiProperties.getEvaluation().getModel() + : "gpt-4o-mini"; + String provider = (aiProperties.getEvaluation() != null && aiProperties.getEvaluation().getProvider() != null) + ? aiProperties.getEvaluation().getProvider() + : "openai"; try { AiCallParams params = AiCallParams.builder() @@ -120,7 +124,12 @@ private String callJudge(String promptText, String operation, String sprintId) { return observabilityService.recordCall(params); } catch (Exception e) { - log.error("Failed to generate dashboard explanation: {}", e.getMessage()); + String errorMessage = e.getMessage() != null ? e.getMessage() : "Unknown error"; + if (errorMessage.contains("429") || errorMessage.toLowerCase().contains("rate limit")) { + log.error("Rate limit hit for operation {}: {}", operation, errorMessage); + return "Summary unavailable (rate limit)."; + } + log.error("Failed to generate dashboard explanation for {}: {}", operation, errorMessage); return "Summary unavailable."; } } diff --git a/backend/src/main/java/ch/goodone/backend/ai/application/ArchitectureExplainUseCase.java b/backend/src/main/java/ch/goodone/backend/ai/application/ArchitectureExplainUseCase.java index dca199b1..2bcfa543 100644 --- a/backend/src/main/java/ch/goodone/backend/ai/application/ArchitectureExplainUseCase.java +++ b/backend/src/main/java/ch/goodone/backend/ai/application/ArchitectureExplainUseCase.java @@ -13,12 +13,15 @@ import ch.goodone.backend.ai.prompt.PromptBuildResult; import ch.goodone.backend.ai.prompt.PromptManifestService; import ch.goodone.backend.ai.governance.AiFailureClassifier; +import ch.goodone.backend.ai.exception.AiException; import ch.goodone.backend.model.taxonomy.CopilotCapability; import ch.goodone.backend.model.taxonomy.CopilotContextMode; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.util.StreamUtils; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -73,11 +76,19 @@ public CopilotResponse execute(ArchitectureExplainRequest request) { String provider = aiProperties.getArchitecture().getProvider(); String model = aiProperties.getArchitecture().getModel(); - String promptVersion = aiProperties.resolvePromptVersion("architecture-explain", "v1"); + String promptVersion = aiProperties.resolvePromptVersion(FEATURE_ARCH_EXPLAIN, "v1"); + + String systemPrompt; + try { + systemPrompt = StreamUtils.copyToString(promptManifestService.getPrompt(FEATURE_ARCH_EXPLAIN).getInputStream(), StandardCharsets.UTF_8); + } catch (Exception e) { + log.error("Failed to load prompt template for feature {}: {}", FEATURE_ARCH_EXPLAIN, e.getMessage()); + throw new AiException("Failed to load architecture explain prompt template", e); + } // Calculate prompt hash for transparency PromptBuildResult buildResult = promptBuilder.build( - FEATURE_ARCH_EXPLAIN, // Using prompt ID as surrogate for system prompt for hashing + systemPrompt, request.getQuestion(), contextResult.getRetrievedChunks(), mode.name() @@ -142,22 +153,24 @@ private CopilotResponse performAiExplanation(ArchitectureExplainRequest request, .feature(FEATURE_ARCH_EXPLAIN) .systemPrompt(buildResult.systemPrompt()) .schemaName("copilotAnswer") + .context(contextResult) .build(), CopilotResponse.class); if (result != null) { - updateResultMetadata(result, buildResult, contextResult, provider, model); + updateResultMetadata(result, buildResult, contextResult, provider, model, mode); } return result; } - private void updateResultMetadata(CopilotResponse result, PromptBuildResult buildResult, AssembledContext contextResult, String provider, String model) { + private void updateResultMetadata(CopilotResponse result, PromptBuildResult buildResult, AssembledContext contextResult, String provider, String model, CopilotContextMode mode) { String answer = result.getAnswer(); AiFailureClassifier.ClassificationResult classification = failureClassifier.classify(answer); double qualityScore = failureClassifier.calculateQualityScore(answer); observabilityService.updateTraceMetadata(m -> { - m.setRetrievedDocumentPaths(contextResult.getRetrievedChunks()); + m.setRetrievedDocumentPaths(contextResult.getRetrievedPaths()); + m.setRetrievedDocumentContents(contextResult.getRetrievedChunks()); m.setFailureClassification(classification.getFailureMode()); m.setQualityScore(qualityScore); }); @@ -167,14 +180,16 @@ private void updateResultMetadata(CopilotResponse result, PromptBuildResult buil metadata.put("model", model); metadata.put("provider", provider); metadata.put("promptHash", buildResult.promptHash()); + metadata.put("section", mode.name()); result.setMetadata(metadata); // Explicit transparency fields (Phase 5) result.setProvider(provider); result.setModel(model); result.setPromptHash(buildResult.promptHash()); - result.setRetrievedDocumentCount(contextResult.getRetrievedChunks() != null ? contextResult.getRetrievedChunks().size() : 0); - result.setRetrievedDocumentPaths(contextResult.getRetrievedChunks()); + result.setRetrievedDocumentCount(contextResult.getChunks() != null ? contextResult.getChunks().size() : 0); + result.setRetrievedDocumentPaths(contextResult.getRetrievedPaths()); + result.setRetrievedDocumentContents(contextResult.getRetrievedChunks()); result.setFallbackUsed(false); // Initial call is not a fallback } diff --git a/backend/src/main/java/ch/goodone/backend/ai/application/EngineeringChatUseCaseImpl.java b/backend/src/main/java/ch/goodone/backend/ai/application/EngineeringChatUseCaseImpl.java index 9ed9e18e..25d40a8a 100644 --- a/backend/src/main/java/ch/goodone/backend/ai/application/EngineeringChatUseCaseImpl.java +++ b/backend/src/main/java/ch/goodone/backend/ai/application/EngineeringChatUseCaseImpl.java @@ -153,7 +153,7 @@ private CopilotResponse performEngineeringChatCall(ChatCallParams params) { double qualityScore = failureClassifier.calculateQualityScore(finalAnswer); updateTraceMetadata(params.buildResult(), params.request(), params.contextResult(), params.mode(), finalAnswer, classification, qualityScore); - CopilotResponse copilotResponse = buildCopilotResponse(finalAnswer, params.contextResult(), params.buildResult(), params.provider(), params.model()); + CopilotResponse copilotResponse = buildCopilotResponse(finalAnswer, params.contextResult(), params.buildResult(), params.provider(), params.model(), params.mode()); if (params.contextResult().hasFailures()) { copilotResponse.setPartialFailures(params.contextResult().getPartialFailures()); } @@ -161,7 +161,7 @@ private CopilotResponse performEngineeringChatCall(ChatCallParams params) { } private ChatExecutionResult executeWithRetries(ChatModel chatModel, Prompt prompt) { - int maxRetries = 3; + int maxRetries = 5; int attempt = 0; long backoffMs = 2000; String rawAnswer = null; @@ -176,10 +176,25 @@ private ChatExecutionResult executeWithRetries(ChatModel chatModel, Prompt promp attempt++; } catch (Exception e) { attempt++; + if (isRateLimit(e)) { + // Increase backoff more aggressively for rate limits + if (attempt == 1) { + backoffMs = 3000; + } else if (attempt == 2) { + backoffMs = 6000; + } else if (attempt == 3) { + backoffMs = 12000; + } else { + backoffMs = 20000; + } + } + if (!shouldRetryException(e, attempt, maxRetries, backoffMs)) { throw e; } - backoffMs *= 2; + if (!isRateLimit(e)) { + backoffMs *= 2; + } } } return new ChatExecutionResult(rawAnswer); @@ -235,7 +250,8 @@ private void updateTraceMetadata(PromptBuildResult buildResult, EngineeringChatR .userPrompt(buildResult.userPrompt()) .fullPrompt(buildResult.fullPrompt()) .sprint(request.getSprintId()) - .retrievedDocumentPaths(contextResult.getRetrievedChunks()) + .retrievedDocumentPaths(contextResult.getRetrievedPaths()) + .retrievedDocumentContents(contextResult.getRetrievedChunks()) .rawResponse(finalAnswer) .finalResponse(finalAnswer) .feature(getCapability().name()) @@ -246,23 +262,25 @@ private void updateTraceMetadata(PromptBuildResult buildResult, EngineeringChatR observabilityService.reportTraceMetadata(metadataCapture); } - private CopilotResponse buildCopilotResponse(String answer, AssembledContext contextResult, PromptBuildResult buildResult, String provider, String model) { + private CopilotResponse buildCopilotResponse(String answer, AssembledContext contextResult, PromptBuildResult buildResult, String provider, String model, CopilotContextMode mode) { java.util.Map metadata = new java.util.HashMap<>(); metadata.put("model", model); metadata.put("provider", provider); metadata.put("promptHash", buildResult.promptHash()); - metadata.put("sources", contextResult.getRetrievedChunks()); + metadata.put("section", mode.name()); + metadata.put("sources", contextResult.getRetrievedPaths()); return CopilotResponse.builder() .answer(answer) - .evidence(contextResult.getRetrievedChunks()) + .evidence(contextResult.getRetrievedPaths()) .confidence(0.9) .metadata(metadata) .provider(provider) .model(model) .promptHash(buildResult.promptHash()) - .retrievedDocumentCount(contextResult.getRetrievedChunks() != null ? contextResult.getRetrievedChunks().size() : 0) - .retrievedDocumentPaths(contextResult.getRetrievedChunks()) + .retrievedDocumentCount(contextResult.getChunks() != null ? contextResult.getChunks().size() : 0) + .retrievedDocumentPaths(contextResult.getRetrievedPaths()) + .retrievedDocumentContents(contextResult.getRetrievedChunks()) .fallbackUsed(false) .build(); } diff --git a/backend/src/main/java/ch/goodone/backend/ai/application/OnboardingAssistantUseCaseImpl.java b/backend/src/main/java/ch/goodone/backend/ai/application/OnboardingAssistantUseCaseImpl.java index 485fbd5f..7a71435f 100644 --- a/backend/src/main/java/ch/goodone/backend/ai/application/OnboardingAssistantUseCaseImpl.java +++ b/backend/src/main/java/ch/goodone/backend/ai/application/OnboardingAssistantUseCaseImpl.java @@ -91,7 +91,7 @@ private CopilotResponse recordOnboardingCall(OnboardingRequest request, Assemble .input(request.getQuery()) .capability(getCapability().name()) .contextMode(mode.name()) - .call(() -> performOnboardingAiCall(request, contextResult, buildResult, provider, model)) + .call(() -> performOnboardingAiCall(request, contextResult, buildResult, provider, model, mode)) .build(); return observabilityService.recordCall(params); @@ -105,7 +105,7 @@ private CopilotResponse buildErrorResponse(Exception e) { .build(); } - private CopilotResponse performOnboardingAiCall(OnboardingRequest request, AssembledContext contextResult, PromptBuildResult buildResult, String provider, String model) { + private CopilotResponse performOnboardingAiCall(OnboardingRequest request, AssembledContext contextResult, PromptBuildResult buildResult, String provider, String model, CopilotContextMode mode) { observabilityService.updateTraceMetadata(m -> { m.setSystemPrompt(buildResult.systemPrompt()); m.setUserPrompt(buildResult.userPrompt()); @@ -137,19 +137,20 @@ private CopilotResponse performOnboardingAiCall(OnboardingRequest request, Assem ); if (response != null) { - updateOnboardingMetadata(response, contextResult, buildResult, provider, model); + updateOnboardingMetadata(response, contextResult, buildResult, provider, model, mode); } return response; } - private void updateOnboardingMetadata(CopilotResponse response, AssembledContext contextResult, PromptBuildResult buildResult, String provider, String model) { + private void updateOnboardingMetadata(CopilotResponse response, AssembledContext contextResult, PromptBuildResult buildResult, String provider, String model, CopilotContextMode mode) { String answer = response.getAnswer(); AiFailureClassifier.ClassificationResult classification = failureClassifier.classify(answer); double qualityScore = failureClassifier.calculateQualityScore(answer); observabilityService.updateTraceMetadata(m -> { - m.setRetrievedDocumentPaths(contextResult.getRetrievedChunks()); + m.setRetrievedDocumentPaths(contextResult.getRetrievedPaths()); + m.setRetrievedDocumentContents(contextResult.getRetrievedChunks()); m.setFailureClassification(classification.getFailureMode()); m.setQualityScore(qualityScore); }); @@ -159,13 +160,15 @@ private void updateOnboardingMetadata(CopilotResponse response, AssembledContext metadata.put("model", model); metadata.put("provider", provider); metadata.put("promptHash", buildResult.promptHash()); + metadata.put("section", mode.name()); response.setMetadata(metadata); response.setProvider(provider); response.setModel(model); response.setPromptHash(buildResult.promptHash()); - response.setRetrievedDocumentCount(contextResult.getRetrievedChunks() != null ? contextResult.getRetrievedChunks().size() : 0); - response.setRetrievedDocumentPaths(contextResult.getRetrievedChunks()); + response.setRetrievedDocumentCount(contextResult.getChunks() != null ? contextResult.getChunks().size() : 0); + response.setRetrievedDocumentPaths(contextResult.getRetrievedPaths()); + response.setRetrievedDocumentContents(contextResult.getRetrievedChunks()); response.setFallbackUsed(false); if (contextResult.hasFailures()) { diff --git a/backend/src/main/java/ch/goodone/backend/ai/application/QuickAddParseUseCase.java b/backend/src/main/java/ch/goodone/backend/ai/application/QuickAddParseUseCase.java index 86872075..c9cd2823 100644 --- a/backend/src/main/java/ch/goodone/backend/ai/application/QuickAddParseUseCase.java +++ b/backend/src/main/java/ch/goodone/backend/ai/application/QuickAddParseUseCase.java @@ -15,7 +15,6 @@ import java.nio.charset.StandardCharsets; import java.util.List; -import java.util.Map; /** * Use case for parsing a quick-add task string into structured data using AI. @@ -56,7 +55,7 @@ public QuickAddParseResult execute(QuickAddParseRequest request, String login) { QuickAddParseResult result; if (aiNeeded) { result = callAi(input); - result = merge(result, deterministic, result.aiUsed()); + result = merge(result, deterministic, result.aiUsed() != null ? result.aiUsed() : true); } else { result = fromDeterministic(deterministic); } @@ -78,7 +77,7 @@ private boolean isAiNeeded(String input, TaskParserService.ParsedTask determinis if (input.split("\\s+").length > 4) { return true; } - return deterministic.dueDate() == null && deterministic.priority() == ch.goodone.backend.model.Priority.MEDIUM; + return deterministic.dueDate() == null && (deterministic.priority() == null || deterministic.priority() == ch.goodone.backend.model.Priority.MEDIUM); } private QuickAddParseResult fromDeterministic(TaskParserService.ParsedTask d) { @@ -91,8 +90,8 @@ private QuickAddParseResult fromDeterministic(TaskParserService.ParsedTask d) { List.of("Parsed deterministically"), d.dueDate() != null ? d.dueDate().toString() : null, d.dueTime() != null ? d.dueTime().toString() : null, - d.priority() != null ? d.priority().name() : null, - d.status() != null ? d.status().name() : null, + d.priority() != null ? d.priority().name() : "MEDIUM", + d.status() != null ? d.status().name() : "OPEN", false ); } @@ -125,7 +124,7 @@ private QuickAddParseResult callAi(String input) { } } - private QuickAddParseResult merge(QuickAddParseResult ai, TaskParserService.ParsedTask deterministic, boolean aiUsed) { + private QuickAddParseResult merge(QuickAddParseResult ai, TaskParserService.ParsedTask deterministic, Boolean aiUsed) { // Deterministic attributes take precedence as they are very reliable String finalDueDate = resolveDueDate(ai, deterministic); String finalDueTime = resolveDueTime(ai, deterministic); diff --git a/backend/src/main/java/ch/goodone/backend/ai/application/RiskRadarUseCaseImpl.java b/backend/src/main/java/ch/goodone/backend/ai/application/RiskRadarUseCaseImpl.java index c587dfbe..a2c86d1e 100644 --- a/backend/src/main/java/ch/goodone/backend/ai/application/RiskRadarUseCaseImpl.java +++ b/backend/src/main/java/ch/goodone/backend/ai/application/RiskRadarUseCaseImpl.java @@ -59,10 +59,12 @@ public RiskRadarResponse execute(RiskRadarRequest request) { } List deterministicRisks = new ArrayList<>(); - String context = processSources(filteredSources, deterministicRisks); + java.util.Map keyToPathMap = new java.util.HashMap<>(); + String context = processSources(filteredSources, deterministicRisks, keyToPathMap); RiskRadarResponse response = callAiForRiskRadar(enhancedRequest, context, deterministicRisks); + enrichWithPaths(response, keyToPathMap); rankResults(response); return response; @@ -115,13 +117,40 @@ private RiskRadarResponse emptyRiskResponse() { .build(); } - private String processSources(List filteredSources, List deterministicRisks) { + private void enrichWithPaths(RiskRadarResponse response, java.util.Map keyToPathMap) { + if (response == null) { + return; + } + enrichListWithPaths(response.getHighRisks(), keyToPathMap); + enrichListWithPaths(response.getProcessIssues(), keyToPathMap); + enrichListWithPaths(response.getDocumentationGaps(), keyToPathMap); + enrichListWithPaths(response.getQualityIssues(), keyToPathMap); + } + + private void enrichListWithPaths(List risks, java.util.Map keyToPathMap) { + if (risks == null) { + return; + } + for (RiskRadarResponse.RiskItem risk : risks) { + if (risk.getEvidence() != null) { + for (String evidence : risk.getEvidence()) { + String path = keyToPathMap.get(evidence); + if (path != null && risk.getEvidencePaths() != null) { + risk.getEvidencePaths().put(evidence, path); + } + } + } + } + } + + private String processSources(List filteredSources, List deterministicRisks, java.util.Map keyToPathMap) { List sourceRepresentations = new ArrayList<>(); for (DocSource source : filteredSources) { List chunks = chunkRepository.findBySource(source); String fullContent = chunks.stream().map(DocChunk::getContent).collect(Collectors.joining("\n")); String taskKey = extractTaskKey(source.getPath()); + keyToPathMap.put(taskKey, source.getPath()); analyzeDeterministic(taskKey, fullContent, source, deterministicRisks); diff --git a/backend/src/main/java/ch/goodone/backend/ai/application/RiskRuleEngine.java b/backend/src/main/java/ch/goodone/backend/ai/application/RiskRuleEngine.java index 38d77d25..adfaf041 100644 --- a/backend/src/main/java/ch/goodone/backend/ai/application/RiskRuleEngine.java +++ b/backend/src/main/java/ch/goodone/backend/ai/application/RiskRuleEngine.java @@ -35,8 +35,9 @@ public List analyze(String taskKey, String content, results.add(RiskRadarResponse.RiskItem.builder() .pattern(rule.getPattern()) .category(rule.getCategory()) - .evidence(List.of(taskKey)) - .mitigations(List.of(rule.getMitigation())) + .evidence(new ArrayList<>(List.of(taskKey))) + .evidencePaths(new ConcurrentHashMap<>(Map.of(taskKey, source.getPath()))) + .mitigations(new ArrayList<>(List.of(rule.getMitigation()))) .build()); } } catch (Exception e) { @@ -78,6 +79,11 @@ public void mergeRisks(List target, List !combinedEvidence.contains(ev)) .forEach(combinedEvidence::add); + Map combinedPaths = new ConcurrentHashMap<>(existing.getEvidencePaths()); + if (item.getEvidencePaths() != null) { + combinedPaths.putAll(item.getEvidencePaths()); + } + List combinedMitigations = new ArrayList<>(existing.getMitigations()); item.getMitigations().stream() .filter(mit -> !combinedMitigations.contains(mit)) @@ -87,6 +93,7 @@ public void mergeRisks(List target, List retrievedDocumentPaths = java.util.Collections.emptyList(); + @Builder.Default + private List retrievedDocumentContents = java.util.Collections.emptyList(); + private Long latencyMs; } diff --git a/backend/src/main/java/ch/goodone/backend/ai/dto/QuickAddParseResult.java b/backend/src/main/java/ch/goodone/backend/ai/dto/QuickAddParseResult.java index 5f9f04e8..3638f163 100644 --- a/backend/src/main/java/ch/goodone/backend/ai/dto/QuickAddParseResult.java +++ b/backend/src/main/java/ch/goodone/backend/ai/dto/QuickAddParseResult.java @@ -16,6 +16,6 @@ public record QuickAddParseResult( String dueTime, String priority, String status, - boolean aiUsed + Boolean aiUsed ) {} diff --git a/backend/src/main/java/ch/goodone/backend/ai/dto/RiskRadarResponse.java b/backend/src/main/java/ch/goodone/backend/ai/dto/RiskRadarResponse.java index 74b97941..671bbfac 100644 --- a/backend/src/main/java/ch/goodone/backend/ai/dto/RiskRadarResponse.java +++ b/backend/src/main/java/ch/goodone/backend/ai/dto/RiskRadarResponse.java @@ -59,6 +59,30 @@ public static class RiskItem { private List mitigations = new java.util.ArrayList<>(); private String category; private EngineeringSignalSeverity severity; + + @Builder.Default + private java.util.Map evidencePaths = new java.util.HashMap<>(); + + public java.util.Map getEvidencePaths() { + if (evidencePaths == null) { + evidencePaths = new java.util.HashMap<>(); + } + return evidencePaths; + } + + public java.util.List getEvidence() { + if (evidence == null) { + evidence = new java.util.ArrayList<>(); + } + return evidence; + } + + public java.util.List getMitigations() { + if (mitigations == null) { + mitigations = new java.util.ArrayList<>(); + } + return mitigations; + } public EngineeringSignal toSignal(String sourceId, EngineeringSignalSeverity defaultSeverity) { return EngineeringSignal.builder() diff --git a/backend/src/main/java/ch/goodone/backend/ai/infrastructure/AiPipeline.java b/backend/src/main/java/ch/goodone/backend/ai/infrastructure/AiPipeline.java index cce1b964..74a2bb35 100644 --- a/backend/src/main/java/ch/goodone/backend/ai/infrastructure/AiPipeline.java +++ b/backend/src/main/java/ch/goodone/backend/ai/infrastructure/AiPipeline.java @@ -34,12 +34,15 @@ public class AiPipeline { public T execute(AiRequest request, Class responseType) { log.info("Executing AI pipeline for feature: {}", request.getFeature()); - // 1. Retrieval - AssembledContext context = contextOrchestrator.assemble( - request.getQuery(), - request.getMode(), - request.getTopK(), - request.getSprintId()); + // 1. Retrieval (if not provided) + AssembledContext context = request.getContext(); + if (context == null) { + context = contextOrchestrator.assemble( + request.getQuery(), + request.getMode(), + request.getTopK(), + request.getSprintId()); + } // 2. Evidence Builder (Signals) // We pass the retrieved paths to compute signals @@ -76,5 +79,6 @@ public static class AiRequest { private String feature; private String systemPrompt; private String schemaName; + private AssembledContext context; } } diff --git a/backend/src/main/java/ch/goodone/backend/ai/infrastructure/StructuredAiClient.java b/backend/src/main/java/ch/goodone/backend/ai/infrastructure/StructuredAiClient.java index 1ccebc8e..92ff27a8 100644 --- a/backend/src/main/java/ch/goodone/backend/ai/infrastructure/StructuredAiClient.java +++ b/backend/src/main/java/ch/goodone/backend/ai/infrastructure/StructuredAiClient.java @@ -88,7 +88,7 @@ private T executeCall(String featureName, String systemPrompt, String userPr }); Prompt prompt = new Prompt(messages, options); - return executeWithRetry(schemaName, responseType, chatModel, prompt); + return executeWithRetry(featureName, schemaName, responseType, chatModel, prompt); } private String getSchemaInstructions(String schemaName) { @@ -101,14 +101,14 @@ private String getSchemaInstructions(String schemaName) { return ""; } - private T executeWithRetry(String schemaName, Class responseType, ChatModel chatModel, Prompt prompt) { + private T executeWithRetry(String featureName, String schemaName, Class responseType, ChatModel chatModel, Prompt prompt) { int maxAttempts = 2; int attempt = 0; Exception lastError = null; while (attempt < maxAttempts) { try { - return performAttempt(schemaName, responseType, chatModel, prompt); + return performAttempt(featureName, schemaName, responseType, chatModel, prompt); } catch (Exception e) { attempt++; lastError = e; @@ -122,7 +122,7 @@ private T executeWithRetry(String schemaName, Class responseType, ChatMod throw new AiException("Failed to get schema-valid AI response after " + 2 + " attempts: " + (lastError != null ? lastError.getMessage() : "Unknown error"), lastError); } - private T performAttempt(String schemaName, Class responseType, ChatModel chatModel, Prompt prompt) throws Exception { + private T performAttempt(String featureName, String schemaName, Class responseType, ChatModel chatModel, Prompt prompt) throws Exception { ChatResponse response = chatModel.call(prompt); String rawOutput = (response != null && response.getResult() != null) ? response.getResult().getOutput().getText() @@ -135,13 +135,69 @@ private T performAttempt(String schemaName, Class responseType, ChatModel observabilityService.updateTraceMetadata(m -> m.setRawResponse(rawOutput)); } - String jsonOnly = (rawOutput != null) ? rawOutput.trim() : "{}"; - schemaValidator.validate(jsonOnly, schemaName); - T parsedResult = objectMapper.readValue(jsonOnly, responseType); - observabilityService.updateTraceMetadata(m -> m.setFinalResponse(jsonOnly)); + String jsonOnly = extractJson(rawOutput); + + // Handle models that return a single-element array instead of an object + if (jsonOnly.startsWith("[") && !responseType.isArray() && !Iterable.class.isAssignableFrom(responseType)) { + try { + // We use a local mapper for this check to avoid side effects + tools.jackson.databind.ObjectMapper mapper = new tools.jackson.databind.ObjectMapper(); + tools.jackson.databind.JsonNode node = mapper.readTree(jsonOnly); + if (node.isArray() && node.size() == 1) { + log.info("Unwrapping single-element AI response array for feature {}", featureName); + jsonOnly = node.get(0).toString(); + } + } catch (Exception e) { + log.debug("Failed to unwrap potential AI response array: {}", e.getMessage()); + } + } + + final String validatedJson = jsonOnly; + schemaValidator.validate(validatedJson, schemaName); + T parsedResult = objectMapper.readValue(validatedJson, responseType); + observabilityService.updateTraceMetadata(m -> m.setFinalResponse(validatedJson)); return parsedResult; } + private String extractJson(String text) { + if (text == null || text.isBlank()) { + return "{}"; + } + + String trimmed = text.trim(); + + // If it already looks like JSON (starts with { or [), don't try to extract from backticks + // as the backticks might be INSIDE the JSON strings. + if (trimmed.startsWith("{") || trimmed.startsWith("[")) { + return trimmed; + } + + // Remove markdown code blocks if present + int firstBackticks = trimmed.indexOf("```"); + if (firstBackticks != -1) { + int lastBackticks = trimmed.lastIndexOf("```"); + if (lastBackticks > firstBackticks + 2) { // Need at least 3 backticks + // Find the first newline after the first triple backticks to skip potential language identifier + int firstNewline = trimmed.indexOf('\n', firstBackticks); + if (firstNewline != -1 && firstNewline < lastBackticks) { + return trimmed.substring(firstNewline + 1, lastBackticks).trim(); + } else { + // Single line backticks case: ```json{"key":"val"}``` or just ```{"key":"val"}``` + // If there's no newline, we just strip the backticks (3 at start, 3 at end) + // But we need to skip any language prefix if it's there. + String content = trimmed.substring(firstBackticks + 3, lastBackticks).trim(); + // If it starts with 'json' but then has a '{', strip 'json' + if (content.toLowerCase().startsWith("json") && content.length() > 4 && (content.charAt(4) == '{' || content.charAt(4) == '[')) { + return content.substring(4).trim(); + } + return content; + } + } + } + + return trimmed; + } + private void handleErrorAndBackoff(String schemaName, Exception e) { if (e.getMessage() != null && e.getMessage().contains("429")) { log.info("Rate limit (429) detected. Applying backoff before retry."); diff --git a/backend/src/main/java/ch/goodone/backend/ai/observability/trace/AiTraceMetadata.java b/backend/src/main/java/ch/goodone/backend/ai/observability/trace/AiTraceMetadata.java index 7f5c7d21..e7c0454b 100644 --- a/backend/src/main/java/ch/goodone/backend/ai/observability/trace/AiTraceMetadata.java +++ b/backend/src/main/java/ch/goodone/backend/ai/observability/trace/AiTraceMetadata.java @@ -17,6 +17,7 @@ public class AiTraceMetadata { private String userPrompt; private String fullPrompt; private List retrievedDocumentPaths; + private List retrievedDocumentContents; private String rawResponse; private String finalResponse; private String feature; diff --git a/backend/src/main/java/ch/goodone/backend/ai/routing/CopilotRouterService.java b/backend/src/main/java/ch/goodone/backend/ai/routing/CopilotRouterService.java index 51ae7ce0..459b7a06 100644 --- a/backend/src/main/java/ch/goodone/backend/ai/routing/CopilotRouterService.java +++ b/backend/src/main/java/ch/goodone/backend/ai/routing/CopilotRouterService.java @@ -11,6 +11,7 @@ import ch.goodone.backend.model.taxonomy.CopilotContextMode; import ch.goodone.backend.repository.UserRepository; import ch.goodone.backend.service.CopilotChatHistoryService; +import tools.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.userdetails.UsernameNotFoundException; @@ -28,6 +29,7 @@ public class CopilotRouterService { private final CopilotUseCaseRegistry useCaseRegistry; private final CopilotChatHistoryService historyService; private final UserRepository userRepository; + private final ObjectMapper objectMapper; /** * Routes a generic question to the appropriate capability based on intent or explicit request. @@ -63,13 +65,25 @@ private void saveHistory(String login, Object request, Object response) { CopilotContextMode mode = extractMode(request); String userMessage = extractUserMessage(request); String assistantMessage = extractAssistantMessage(response); + String resultJson = serializeResponse(response); if (mode != null && userMessage != null && assistantMessage != null) { - historyService.saveMessage(user, mode, "user", userMessage); - historyService.saveMessage(user, mode, "assistant", assistantMessage); + historyService.saveMessage(user, mode, "user", userMessage, null); + historyService.saveMessage(user, mode, "assistant", assistantMessage, resultJson); } } + private String serializeResponse(Object response) { + if (response instanceof CopilotResponse) { + try { + return objectMapper.writeValueAsString(response); + } catch (Exception e) { + log.warn("Failed to serialize Copilot response for history: {}", e.getMessage()); + } + } + return null; + } + private CopilotContextMode extractMode(Object request) { return switch (request) { case ArchitectureExplainRequest r -> r.getContextMode(); diff --git a/backend/src/main/java/ch/goodone/backend/controller/DocController.java b/backend/src/main/java/ch/goodone/backend/controller/DocController.java new file mode 100644 index 00000000..0ed14e31 --- /dev/null +++ b/backend/src/main/java/ch/goodone/backend/controller/DocController.java @@ -0,0 +1,135 @@ +package ch.goodone.backend.controller; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.Resource; +import org.springframework.core.io.UrlResource; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; + +/** + * Controller for serving documentation files dynamically. + */ +@RestController +@RequestMapping("/api/docs") +@Slf4j +public class DocController { + + // Allowed root files for documentation + private static final List ALLOWED_ROOT_FILES = List.of("README.md", "README_de.md", "CONTRIBUTING.md", "ROADMAP.md"); + + @Value("${app.docs.base-dir:.}") + private String baseDir; + + /** + * Retrieve the raw content of a documentation file. + * + * @param path The path to the documentation file (relative to the base directory). + * @return The raw markdown content. + */ + @GetMapping("/raw") + public ResponseEntity getRawDoc(@RequestParam String path) { + try { + // Strip fragments if present (e.g. #section) + String cleanPath = path; + if (path.contains("#")) { + cleanPath = path.substring(0, path.indexOf("#")); + } + + // Strip leading help/ if present (frontend route prefix) + if (cleanPath.startsWith("help/")) { + cleanPath = cleanPath.substring(5); + } + final String searchPath = cleanPath; + + // Basic path traversal protection + Path basePath = Paths.get(baseDir).toAbsolutePath().normalize(); + Path requestedPath = basePath.resolve(cleanPath).toAbsolutePath().normalize(); + + // Ensure requested path is within base directory + if (!requestedPath.startsWith(basePath)) { + log.warn("Potential path traversal attempt: {}", path); + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); + } + + Resource resource = new UrlResource(requestedPath.toUri()); + String relativePathStr = basePath.relativize(requestedPath).toString().replace('\\', '/'); + + // 1. Resolve task IDs (AI-* or sprint-*) to full paths if requested as flat IDs + if ((searchPath.startsWith("AI-") || searchPath.startsWith("sprint-")) && !resource.exists()) { + Path tasksDir = basePath.resolve("doc/knowledge/junie-tasks"); + if (Files.exists(tasksDir) && Files.isDirectory(tasksDir)) { + try (Stream walk = Files.walk(tasksDir)) { + String targetFileName = searchPath.endsWith(".md") ? searchPath.toLowerCase() : searchPath.toLowerCase() + ".md"; + Optional found = walk + .filter(Files::isRegularFile) + .filter(p -> { + String fileName = p.getFileName().toString().toLowerCase(); + return fileName.equals(targetFileName) || fileName.startsWith(searchPath.toLowerCase()); + }) + .findFirst(); + if (found.isPresent()) { + requestedPath = found.get(); + resource = new UrlResource(requestedPath.toUri()); + relativePathStr = basePath.relativize(requestedPath).toString().replace('\\', '/'); + log.info("Resolved task ID {} to {}", searchPath, requestedPath); + } + } + } + } + + // Restrict access to doc/ directory or allowed root files + if (!relativePathStr.startsWith("doc/") && !ALLOWED_ROOT_FILES.contains(relativePathStr)) { + log.warn("Access denied to non-documentation file: {}", path); + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); + } + + // Fallback for partial task filenames (e.g. AI-BE-51 -> AI-BE-51-Description.md) + if (!resource.exists() && relativePathStr.contains("junie-tasks/")) { + Path parentDir = requestedPath.getParent(); + String fileName = requestedPath.getFileName().toString(); + if (fileName.endsWith(".md") && Files.isDirectory(parentDir)) { + String prefix = fileName.substring(0, fileName.length() - 3); + try (Stream files = Files.list(parentDir)) { + Optional found = files + .filter(p -> p.getFileName().toString().startsWith(prefix) && p.getFileName().toString().endsWith(".md")) + .findFirst(); + if (found.isPresent()) { + requestedPath = found.get(); + resource = new UrlResource(requestedPath.toUri()); + log.info("Resolved partial task path {} to {}", path, requestedPath); + } + } + } + } + + if (resource.exists() && resource.isReadable()) { + byte[] bytes = resource.getInputStream().readAllBytes(); + String content = new String(bytes, StandardCharsets.UTF_8); + return ResponseEntity.ok() + .contentType(MediaType.TEXT_PLAIN) + .body(content); + } else { + log.warn("File not found or not readable: {}", path); + return ResponseEntity.notFound().build(); + } + } catch (IOException e) { + log.error("Error reading doc file: {}", path, e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); + } + } +} diff --git a/backend/src/main/java/ch/goodone/backend/dto/ai/CopilotChatHistoryDto.java b/backend/src/main/java/ch/goodone/backend/dto/ai/CopilotChatHistoryDto.java index 65184b08..833b9c9d 100644 --- a/backend/src/main/java/ch/goodone/backend/dto/ai/CopilotChatHistoryDto.java +++ b/backend/src/main/java/ch/goodone/backend/dto/ai/CopilotChatHistoryDto.java @@ -17,6 +17,7 @@ public class CopilotChatHistoryDto { private Long id; private String role; private String content; + private String result; private CopilotContextMode mode; private LocalDateTime timestamp; @@ -25,6 +26,7 @@ public static CopilotChatHistoryDto fromEntity(CopilotChatHistory entity) { .id(entity.getId()) .role(entity.getRole()) .content(entity.getContent()) + .result(entity.getResult()) .mode(entity.getMode()) .timestamp(entity.getTimestamp()) .build(); diff --git a/backend/src/main/java/ch/goodone/backend/model/CopilotChatHistory.java b/backend/src/main/java/ch/goodone/backend/model/CopilotChatHistory.java index 73ec45bd..30a5c670 100644 --- a/backend/src/main/java/ch/goodone/backend/model/CopilotChatHistory.java +++ b/backend/src/main/java/ch/goodone/backend/model/CopilotChatHistory.java @@ -45,6 +45,9 @@ public class CopilotChatHistory { @Column(name = "content", nullable = false, columnDefinition = "TEXT") private String content; + @Column(name = "result", columnDefinition = "TEXT") + private String result; + @Column(name = "timestamp", nullable = false) private LocalDateTime timestamp; } diff --git a/backend/src/main/java/ch/goodone/backend/service/CopilotChatHistoryService.java b/backend/src/main/java/ch/goodone/backend/service/CopilotChatHistoryService.java index cc4a5314..a89b82b2 100644 --- a/backend/src/main/java/ch/goodone/backend/service/CopilotChatHistoryService.java +++ b/backend/src/main/java/ch/goodone/backend/service/CopilotChatHistoryService.java @@ -22,12 +22,13 @@ public List getHistory(User user, CopilotContextMode mode) { } @Transactional - public void saveMessage(User user, CopilotContextMode mode, String role, String content) { + public void saveMessage(User user, CopilotContextMode mode, String role, String content, String result) { CopilotChatHistory history = CopilotChatHistory.builder() .user(user) .mode(mode) .role(role) .content(content) + .result(result) .timestamp(LocalDateTime.now()) .build(); repository.save(history); diff --git a/backend/src/main/java/ch/goodone/backend/service/TaskParserService.java b/backend/src/main/java/ch/goodone/backend/service/TaskParserService.java index 4fca55f8..e0732660 100644 --- a/backend/src/main/java/ch/goodone/backend/service/TaskParserService.java +++ b/backend/src/main/java/ch/goodone/backend/service/TaskParserService.java @@ -28,7 +28,7 @@ public record ParsedTask( public ParsedTask parse(String input) { if (input == null || input.trim().isEmpty()) { - return new ParsedTask("", "", null, null, Priority.MEDIUM, TaskStatus.OPEN, List.of()); + return new ParsedTask("", "", null, null, null, null, List.of()); } String value = sanitizeInput(input); @@ -84,8 +84,8 @@ private ParsedTask parseDelimited(String value, String delimiter) { String description = parts.length > 1 ? parts[1].trim() : ""; LocalDate dueDate = parts.length > 2 ? parseDate(parts[2].trim()) : null; LocalTime dueTime = parts.length > 2 ? parseTime(parts[2].trim()) : null; - Priority priority = parts.length > 3 ? parsePriority(parts[3].trim(), Priority.MEDIUM) : Priority.MEDIUM; - TaskStatus status = parts.length > 4 ? parseStatus(parts[4].trim(), TaskStatus.OPEN) : TaskStatus.OPEN; + Priority priority = parts.length > 3 ? parsePriority(parts[3].trim(), null) : null; + TaskStatus status = parts.length > 4 ? parseStatus(parts[4].trim(), null) : null; return new ParsedTask(title, description, dueDate, dueTime, priority, status, List.of()); } @@ -105,17 +105,17 @@ private ParsedTask parseCsv(String[] parts) { String description = parts.length > 1 ? parts[1].trim() : ""; LocalDate dueDate = null; LocalTime dueTime = null; - Priority priority = Priority.MEDIUM; - TaskStatus status = TaskStatus.OPEN; + Priority priority = null; + TaskStatus status = null; if (parts.length >= 3) { dueDate = parseDate(parts[2].trim()); dueTime = parseTime(parts[2].trim()); if (parts.length > 3) { - priority = parsePriority(parts[3].trim(), Priority.MEDIUM); + priority = parsePriority(parts[3].trim(), null); } if (parts.length > 4) { - status = parseStatus(parts[4].trim(), TaskStatus.OPEN); + status = parseStatus(parts[4].trim(), null); } } else if (parts.length == 2) { return parseTwoPartCsv(title, description, parts[1].trim()); @@ -131,8 +131,8 @@ private ParsedTask parseTwoPartCsv(String title, String description, String seco LocalDate dueDate = d; LocalTime dueTime = t; - Priority priority = (p != null) ? p : Priority.MEDIUM; - TaskStatus status = (s != null) ? s : TaskStatus.OPEN; + Priority priority = p; + TaskStatus status = s; String desc = (d != null || t != null || p != null || s != null) ? "" : description; return new ParsedTask(title, desc, dueDate, dueTime, priority, status, List.of()); @@ -248,7 +248,7 @@ private ParsedTask parseSpaceHeuristic(String value) { String[] tokens = value.split("\\s+"); int statusIdx = findStatusIndex(tokens); - TaskStatus status = (statusIdx != -1) ? parseStatus(tokens[statusIdx], TaskStatus.OPEN) : TaskStatus.OPEN; + TaskStatus status = (statusIdx != -1) ? parseStatus(tokens[statusIdx], null) : null; int priorityIdx = findPriorityIndex(tokens, statusIdx, -1, -1); @@ -266,7 +266,7 @@ private ParsedTask parseSpaceHeuristic(String value) { priorityIdx = -1; } } - Priority priority = (priorityIdx != -1) ? parsePriority(tokens[priorityIdx], Priority.MEDIUM) : Priority.MEDIUM; + Priority priority = (priorityIdx != -1) ? parsePriority(tokens[priorityIdx], null) : null; int prioKeywordIdx = (priorityIdx > 0 && tokens[priorityIdx - 1].equalsIgnoreCase("prio")) ? priorityIdx - 1 : -1; int tagKeywordIdx = findKeywordIndex(tokens, "tag", "tags"); @@ -564,6 +564,8 @@ private Priority parsePriority(String input, Priority defaultVal) { case "DRINGEND": case "WICHTIG": case "HIGH": + case "URGENT": + case "URGENTE": return Priority.HIGH; case "TIEF": case "UNWICHTIG": @@ -572,6 +574,7 @@ private Priority parsePriority(String input, Priority defaultVal) { return Priority.LOW; case "MITTEL": case "MEDIUM": + case "NORMAL": return Priority.MEDIUM; case "KRITISCH": case "CRITICAL": diff --git a/backend/src/main/resources/ai/schemas/quickAddParse.schema.json b/backend/src/main/resources/ai/schemas/quickAddParse.schema.json index c7aceeb7..430aaee2 100644 --- a/backend/src/main/resources/ai/schemas/quickAddParse.schema.json +++ b/backend/src/main/resources/ai/schemas/quickAddParse.schema.json @@ -12,8 +12,7 @@ "dueDate": { "type": ["string", "null"] }, "dueTime": { "type": ["string", "null"] }, "priority": { "type": ["string", "null"] }, - "status": { "type": ["string", "null"] }, - "aiUsed": { "type": "boolean" } + "status": { "type": ["string", "null"] } }, "required": ["title", "confidence"], "additionalProperties": false diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 7a45997e..6f89ec3c 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -199,7 +199,7 @@ app.ai.prompt.versions.decision-assistant=v1 # OpenAI specific configuration app.ai.openai.api-key=${OPENAI_API_KEY:} -app.ai.openai.chat-model=${OPENAI_MODEL:gpt-4o} +app.ai.openai.chat-model=${OPENAI_MODEL:gpt-4o-mini} app.ai.openai.embedding-model=${OPENAI_EMBEDDING_MODEL:text-embedding-3-small} app.ai.openai.base-url=${OPENAI_BASE_URL:https://api.openai.com/v1} app.ai.openai.timeout-seconds=${OPENAI_TIMEOUT:300} @@ -254,7 +254,7 @@ spring.ai.ollama.chat.options.num-predict=2048 # Standard Spring AI OpenAI options spring.ai.openai.api-key=${OPENAI_API_KEY:} -spring.ai.openai.chat.options.model=${OPENAI_MODEL:gpt-4o} +spring.ai.openai.chat.options.model=${OPENAI_MODEL:gpt-4o-mini} spring.ai.openai.embedding.options.model=${OPENAI_EMBEDDING_MODEL:text-embedding-3-small} # SpringDoc Configuration diff --git a/backend/src/main/resources/db/migration/common/V49__add_result_to_copilot_chat_history.sql b/backend/src/main/resources/db/migration/common/V49__add_result_to_copilot_chat_history.sql new file mode 100644 index 00000000..949ddd8b --- /dev/null +++ b/backend/src/main/resources/db/migration/common/V49__add_result_to_copilot_chat_history.sql @@ -0,0 +1 @@ +ALTER TABLE copilot_chat_history ADD COLUMN IF NOT EXISTS result TEXT; diff --git a/backend/src/main/resources/prompts/architecture/v1/explain.st b/backend/src/main/resources/prompts/architecture/v1/explain.st index 1ccb8805..9f78f0e9 100644 --- a/backend/src/main/resources/prompts/architecture/v1/explain.st +++ b/backend/src/main/resources/prompts/architecture/v1/explain.st @@ -20,6 +20,7 @@ Instructions: Strictly return ONLY valid JSON. Your response must include: - answer: A detailed explanation of the requested architecture aspect. Use Markdown formatting (headers, bold text, lists) to improve readability. - evidence: A list of documents or ADRs used for this explanation, with title and path. +- confidence: A numeric confidence score [0.0 - 1.0] indicating your certainty about this answer based on the provided context. Do not include any prose outside the JSON. If you don't know the answer from the context, state it in the answer field and return an empty evidence list. diff --git a/backend/src/main/resources/prompts/engineering/v1/onboarding.st b/backend/src/main/resources/prompts/engineering/v1/onboarding.st index 35cfcb25..2b980163 100644 --- a/backend/src/main/resources/prompts/engineering/v1/onboarding.st +++ b/backend/src/main/resources/prompts/engineering/v1/onboarding.st @@ -13,10 +13,11 @@ Suggest clear next steps for the developer. Mention the relevant documentation files used. When providing links to documentation in the 'answer' field, ALWAYS use relative URLs starting with /help/ followed by ONLY the documentation ID (e.g., [Risk Radar](/help/risk-radar) or [Navigation](/help/navigation)). NEVER include .md extensions, NEVER include directory paths like doc/features/, and NEVER provide full http://localhost URLs. -Strictly return ONLY valid JSON. Your response must use these keys: +Strictly return ONLY valid JSON. Your response must be a single JSON object (NOT an array). Your response must use these keys: - answer: (MANDATORY) A friendly, step-by-step guide for the developer based ON ONLY the provided knowledge. Use Markdown formatting (headers, bold text, lists) for readability. Do NOT include a "Next Steps" or "Suggested Actions" section at the end of the answer, as these will be provided separately. This field must NOT be empty. - evidence: (MANDATORY) A list of relevant documentation files or source paths from the project context that you used. Return an empty list if no specific files apply. - suggestedActions: (MANDATORY) A list of 2-3 concrete next steps (e.g., specific commands to run or files to open). +- confidence: (MANDATORY) A numeric confidence score [0.0 - 1.0] indicating your certainty about this guide based on the provided knowledge. Do not include any prose outside the JSON. If you don't know the answer from the context, state it in the answer field and return an empty evidence list. diff --git a/backend/src/test/java/ch/goodone/backend/ai/AiPropertiesBindingTest.java b/backend/src/test/java/ch/goodone/backend/ai/AiPropertiesBindingTest.java index 367ca495..fd90923f 100644 --- a/backend/src/test/java/ch/goodone/backend/ai/AiPropertiesBindingTest.java +++ b/backend/src/test/java/ch/goodone/backend/ai/AiPropertiesBindingTest.java @@ -30,5 +30,11 @@ void testPricingBinding() { fail("Pricing map should contain gpt-4o. Keys: " + aiProperties.getPricing().keySet()); } } + + @Test + void testFeatureModels() { + assertNotNull(aiProperties.getArchitecture().getModel(), "Architecture model should not be null"); + assertNotNull(aiProperties.getEvaluation().getModel(), "Evaluation model should not be null"); + } } diff --git a/backend/src/test/java/ch/goodone/backend/ai/application/ArchitectureExplainUseCaseTest.java b/backend/src/test/java/ch/goodone/backend/ai/application/ArchitectureExplainUseCaseTest.java index c36d3c88..7886697b 100644 --- a/backend/src/test/java/ch/goodone/backend/ai/application/ArchitectureExplainUseCaseTest.java +++ b/backend/src/test/java/ch/goodone/backend/ai/application/ArchitectureExplainUseCaseTest.java @@ -18,7 +18,11 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.core.io.Resource; +import org.springframework.util.StreamUtils; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -77,10 +81,13 @@ void setUp() { } @Test - void execute_shouldCallAiPipelineWithCorrectVariables() { + void execute_shouldCallAiPipelineWithCorrectVariables() throws IOException { ArchitectureExplainRequest request = new ArchitectureExplainRequest("How it works?"); CopilotResponse expectedResult = CopilotResponse.builder().answer("It works").evidence(List.of()).build(); + when(promptManifestService.getPrompt(anyString())).thenReturn(explainPromptResource); + when(explainPromptResource.getInputStream()).thenReturn(new ByteArrayInputStream("mock-prompt".getBytes(StandardCharsets.UTF_8))); + when(contextOrchestrator.assemble(anyString(), any(), anyInt(), any())).thenReturn(ch.goodone.backend.ai.context.AssembledContext.builder() .context("No additional context available.") .partialFailures(List.of()) diff --git a/backend/src/test/java/ch/goodone/backend/ai/dto/QuickAddParseResultTest.java b/backend/src/test/java/ch/goodone/backend/ai/dto/QuickAddParseResultTest.java new file mode 100644 index 00000000..a0a1c0e8 --- /dev/null +++ b/backend/src/test/java/ch/goodone/backend/ai/dto/QuickAddParseResultTest.java @@ -0,0 +1,22 @@ +package ch.goodone.backend.ai.dto; + +import tools.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; + +class QuickAddParseResultTest { + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + void deserialize_ShouldSucceedEvenIfAiUsedIsMissing() throws Exception { + // After fix: this should work because aiUsed is now Boolean. + String json = "{\"title\": \"Test\", \"confidence\": 0.9}"; + + QuickAddParseResult result = objectMapper.readValue(json, QuickAddParseResult.class); + + assertThat(result.title()).isEqualTo("Test"); + assertThat(result.confidence()).isEqualTo(0.9); + assertThat(result.aiUsed()).isNull(); + } +} diff --git a/backend/src/test/java/ch/goodone/backend/ai/infrastructure/StructuredAiClientTest.java b/backend/src/test/java/ch/goodone/backend/ai/infrastructure/StructuredAiClientTest.java index 3c01c960..7e187a91 100644 --- a/backend/src/test/java/ch/goodone/backend/ai/infrastructure/StructuredAiClientTest.java +++ b/backend/src/test/java/ch/goodone/backend/ai/infrastructure/StructuredAiClientTest.java @@ -139,5 +139,108 @@ void call_ShouldThrowExceptionAfterRetriesExhausted() { .hasMessageContaining("Failed to get schema-valid AI response after 2 attempts"); } + @Test + void call_ShouldExtractJsonFromMarkdown() throws Exception { + // Arrange + String raw = "```json\n{\"key\": \"value\"}\n```"; + String expectedJson = "{\"key\": \"value\"}"; + TestResponse expectedDto = new TestResponse("value"); + + ChatResponse chatResponse = mock(ChatResponse.class); + Generation generation = mock(Generation.class); + org.springframework.ai.chat.messages.AssistantMessage assistantMessage = mock(org.springframework.ai.chat.messages.AssistantMessage.class); + + when(chatModel.call(any(Prompt.class))).thenReturn(chatResponse); + when(chatResponse.getResult()).thenReturn(generation); + when(generation.getOutput()).thenReturn(assistantMessage); + when(assistantMessage.getText()).thenReturn(raw); + + when(objectMapper.readValue(expectedJson, TestResponse.class)).thenReturn(expectedDto); + + // Act + TestResponse result = client.call("architecture", "sys", "user", "testSchema", TestResponse.class); + + // Assert + assertThat(result).isEqualTo(expectedDto); + verify(schemaValidator).validate(expectedJson, "testSchema"); + } + + @Test + void call_ShouldExtractJsonFromArrayMarkdown() throws Exception { + // Arrange + String raw = "```\n[\"item1\", \"item2\"]\n```"; + String expectedJson = "[\"item1\", \"item2\"]"; + String[] expectedDto = new String[]{"item1", "item2"}; + + ChatResponse chatResponse = mock(ChatResponse.class); + Generation generation = mock(Generation.class); + org.springframework.ai.chat.messages.AssistantMessage assistantMessage = mock(org.springframework.ai.chat.messages.AssistantMessage.class); + + when(chatModel.call(any(Prompt.class))).thenReturn(chatResponse); + when(chatResponse.getResult()).thenReturn(generation); + when(generation.getOutput()).thenReturn(assistantMessage); + when(assistantMessage.getText()).thenReturn(raw); + + when(objectMapper.readValue(expectedJson, String[].class)).thenReturn(expectedDto); + + // Act + String[] result = client.call("architecture", "sys", "user", "testSchema", String[].class); + + // Assert + assertThat(result).isEqualTo(expectedDto); + verify(schemaValidator).validate(expectedJson, "testSchema"); + } + + @Test + void call_ShouldNotMistakeInternalBackticksAsMarkdownWrapper() throws Exception { + // Arrange + // This simulates the issue: JSON starting with [ but containing backticks inside + String raw = "[{\"answer\": \"Here is code: ```\\nls\\n```\"}]"; + TestResponse[] expectedDto = new TestResponse[]{new TestResponse("Here is code: ```\\nls\\n```")}; + + ChatResponse chatResponse = mock(ChatResponse.class); + Generation generation = mock(Generation.class); + org.springframework.ai.chat.messages.AssistantMessage assistantMessage = mock(org.springframework.ai.chat.messages.AssistantMessage.class); + + when(chatModel.call(any(Prompt.class))).thenReturn(chatResponse); + when(chatResponse.getResult()).thenReturn(generation); + when(generation.getOutput()).thenReturn(assistantMessage); + when(assistantMessage.getText()).thenReturn(raw); + + when(objectMapper.readValue(raw, TestResponse[].class)).thenReturn(expectedDto); + + // Act + TestResponse[] result = client.call("architecture", "sys", "user", "testSchema", TestResponse[].class); + + // Assert + assertThat(result).isEqualTo(expectedDto); + verify(schemaValidator).validate(raw, "testSchema"); + } + + @Test + void call_ShouldUnwrapSingleElementArrayForObjectExpectedType() throws Exception { + // Arrange + String raw = "[{\"key\": \"hello\"}]"; + TestResponse expectedDto = new TestResponse("hello"); + + ChatResponse chatResponse = mock(ChatResponse.class); + Generation generation = mock(Generation.class); + org.springframework.ai.chat.messages.AssistantMessage assistantMessage = mock(org.springframework.ai.chat.messages.AssistantMessage.class); + + when(chatModel.call(any(Prompt.class))).thenReturn(chatResponse); + when(chatResponse.getResult()).thenReturn(generation); + when(generation.getOutput()).thenReturn(assistantMessage); + when(assistantMessage.getText()).thenReturn(raw); + + when(objectMapper.readValue(anyString(), eq(TestResponse.class))).thenReturn(expectedDto); + + // Act + TestResponse result = client.call("architecture", "sys", "user", "testSchema", TestResponse.class); + + // Assert + assertThat(result).isEqualTo(expectedDto); + verify(schemaValidator).validate(anyString(), eq("testSchema")); + } + static record TestResponse(String key) {} } diff --git a/backend/src/test/java/ch/goodone/backend/ai/routing/CopilotRouterServiceTest.java b/backend/src/test/java/ch/goodone/backend/ai/routing/CopilotRouterServiceTest.java index 757eaa32..b8eeb2ee 100644 --- a/backend/src/test/java/ch/goodone/backend/ai/routing/CopilotRouterServiceTest.java +++ b/backend/src/test/java/ch/goodone/backend/ai/routing/CopilotRouterServiceTest.java @@ -10,6 +10,7 @@ import ch.goodone.backend.model.taxonomy.CopilotContextMode; import ch.goodone.backend.repository.UserRepository; import ch.goodone.backend.service.CopilotChatHistoryService; +import tools.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -35,6 +36,9 @@ class CopilotRouterServiceTest { @Mock private UserRepository userRepository; + @Mock + private ObjectMapper objectMapper; + @Mock private CopilotUseCase useCase; @@ -56,8 +60,8 @@ void shouldRouteRequestAndSaveHistory() { Object result = copilotRouterService.route(CopilotCapability.ARCHITECTURE_QA, request, login); assertThat(result).isEqualTo(response); - verify(historyService, times(1)).saveMessage(user, CopilotContextMode.ARCHITECTURE_QA, "user", "How?"); - verify(historyService, times(1)).saveMessage(user, CopilotContextMode.ARCHITECTURE_QA, "assistant", "Like this"); + verify(historyService, times(1)).saveMessage(user, CopilotContextMode.ARCHITECTURE_QA, "user", "How?", null); + verify(historyService, times(1)).saveMessage(user, CopilotContextMode.ARCHITECTURE_QA, "assistant", "Like this", null); } @Test diff --git a/backend/src/test/java/ch/goodone/backend/controller/DocControllerTest.java b/backend/src/test/java/ch/goodone/backend/controller/DocControllerTest.java new file mode 100644 index 00000000..3ae0b7ec --- /dev/null +++ b/backend/src/test/java/ch/goodone/backend/controller/DocControllerTest.java @@ -0,0 +1,209 @@ +package ch.goodone.backend.controller; + +import static ch.goodone.backend.util.SecurityConstants.*; +import ch.goodone.backend.config.SecurityConfig; +import ch.goodone.backend.repository.UserRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.security.test.context.support.WithMockUser; +import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(DocController.class) +@Import({SecurityConfig.class, ch.goodone.backend.config.JacksonSystemConfig.class}) +@ActiveProfiles("test") +class DocControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockitoBean + private UserRepository userRepository; + + @MockitoBean + private ch.goodone.backend.service.UserAliasService userAliasService; + + @MockitoBean + private org.springframework.mail.javamail.JavaMailSender javaMailSender; + + @MockitoBean + private ch.goodone.backend.service.JwtService jwtService; + + @MockitoBean + private ch.goodone.backend.ai.usage.AiUsageService aiUsageService; + + @MockitoBean + private ch.goodone.backend.service.CaptchaService captchaService; + + @MockitoBean + private ch.goodone.backend.repository.VerificationTokenRepository verificationTokenRepository; + + @MockitoBean + private ch.goodone.backend.repository.PasswordRecoveryTokenRepository passwordRecoveryTokenRepository; + + @MockitoBean + private ch.goodone.backend.service.ValidationService validationService; + + @MockitoBean + private ch.goodone.backend.service.EmailService emailService; + + @MockitoBean + private ch.goodone.backend.ai.config.AiEnabledFilter aiEnabledFilter; + + @MockitoBean + private ch.goodone.backend.config.JwtAuthenticationFilter jwtAuthenticationFilter; + + @MockitoBean + private ch.goodone.backend.config.WafSimulatedFilter wafSimulatedFilter; + + @MockitoBean + private ch.goodone.backend.service.ActionLogService actionLogService; + + @Autowired + private WebApplicationContext context; + + @Autowired + private DocController docController; + + private Path tempDir; + + @BeforeEach + void setUp() throws jakarta.servlet.ServletException, IOException { + mockMvc = MockMvcBuilders + .webAppContextSetup(context) + .apply(SecurityMockMvcConfigurers.springSecurity()) + .build(); + + doAnswer(invocation -> { + jakarta.servlet.FilterChain chain = invocation.getArgument(2); + chain.doFilter(invocation.getArgument(0), invocation.getArgument(1)); + return null; + }).when(jwtAuthenticationFilter).doFilter(any(), any(), any()); + + doAnswer(invocation -> { + jakarta.servlet.FilterChain chain = invocation.getArgument(2); + chain.doFilter(invocation.getArgument(0), invocation.getArgument(1)); + return null; + }).when(wafSimulatedFilter).doFilter(any(), any(), any()); + + doAnswer(invocation -> { + jakarta.servlet.FilterChain chain = invocation.getArgument(2); + chain.doFilter(invocation.getArgument(0), invocation.getArgument(1)); + return null; + }).when(aiEnabledFilter).doFilter(any(), any(), any()); + + // Create temp directory for tests + tempDir = Files.createTempDirectory("doc-test"); + ReflectionTestUtils.setField(docController, "baseDir", tempDir.toString()); + } + + @Test + @WithMockUser(username = "user", authorities = {ROLE_USER}) + void shouldGetRawDoc() throws Exception { + Path docPath = tempDir.resolve("README.md"); + Files.writeString(docPath, "# Test Content"); + + mockMvc.perform(get("/api/docs/raw").param("path", "README.md")) + .andExpect(status().isOk()) + .andExpect(content().string("# Test Content")); + } + + @Test + @WithMockUser(username = "user", authorities = {ROLE_USER}) + void shouldGetNestedDoc() throws Exception { + Path nestedDir = tempDir.resolve("doc/nested"); + Files.createDirectories(nestedDir); + Path docPath = nestedDir.resolve("test.md"); + Files.writeString(docPath, "Nested Content"); + + mockMvc.perform(get("/api/docs/raw").param("path", "doc/nested/test.md")) + .andExpect(status().isOk()) + .andExpect(content().string("Nested Content")); + } + + @Test + @WithMockUser(username = "user", authorities = {ROLE_USER}) + void shouldDenyPathTraversal() throws Exception { + mockMvc.perform(get("/api/docs/raw").param("path", "../outside.md")) + .andExpect(status().isForbidden()); + } + + @Test + @WithMockUser(username = "user", authorities = {ROLE_USER}) + void shouldDenyNonDocFile() throws Exception { + Path secretPath = tempDir.resolve("secret.txt"); + Files.writeString(secretPath, "Secret"); + + mockMvc.perform(get("/api/docs/raw").param("path", "secret.txt")) + .andExpect(status().isForbidden()); + } + + @Test + @WithMockUser(username = "user", authorities = {ROLE_USER}) + void shouldReturnNotFoundForNonExistentFile() throws Exception { + mockMvc.perform(get("/api/docs/raw").param("path", "doc/missing.md")) + .andExpect(status().isNotFound()); + } + + @Test + @WithMockUser(username = "user", authorities = {ROLE_USER}) + void shouldHandlePathWithFragment() throws Exception { + Path nestedDir = tempDir.resolve("doc/knowledge/adrs"); + Files.createDirectories(nestedDir); + Path docPath = nestedDir.resolve("adr-full-set.md"); + Files.writeString(docPath, "# ADRs"); + + // This path contains a fragment and a colon, which might cause issues on some systems if not stripped + String pathWithFragment = "doc/knowledge/adrs/adr-full-set.md#ADR-0056: Explicit AI Runtime Configuration"; + + mockMvc.perform(get("/api/docs/raw").param("path", pathWithFragment)) + .andExpect(status().isOk()) + .andExpect(content().string("# ADRs")); + } + + @Test + @WithMockUser(username = "user", authorities = {ROLE_USER}) + void shouldResolvePartialTaskPath() throws Exception { + Path taskDir = tempDir.resolve("doc/knowledge/junie-tasks/AI-BE"); + Files.createDirectories(taskDir); + Path docPath = taskDir.resolve("AI-BE-51-Implementation-Enrichment.md"); + Files.writeString(docPath, "Task Content"); + + // Request partial filename AI-BE-51.md + mockMvc.perform(get("/api/docs/raw").param("path", "doc/knowledge/junie-tasks/AI-BE/AI-BE-51.md")) + .andExpect(status().isOk()) + .andExpect(content().string("Task Content")); + } + + @Test + @WithMockUser(username = "user", authorities = {ROLE_USER}) + void shouldHandleHelpPrefix() throws Exception { + Path docDir = tempDir.resolve("doc/knowledge/adrs"); + Files.createDirectories(docDir); + Path docPath = docDir.resolve("adr-full-set.md"); + Files.writeString(docPath, "ADR Content"); + + // Request with help/ prefix (as sent by frontend wildcard route) + mockMvc.perform(get("/api/docs/raw").param("path", "help/doc/knowledge/adrs/adr-full-set.md")) + .andExpect(status().isOk()) + .andExpect(content().string("ADR Content")); + } +} diff --git a/backend/src/test/java/ch/goodone/backend/service/CopilotChatHistoryServiceTest.java b/backend/src/test/java/ch/goodone/backend/service/CopilotChatHistoryServiceTest.java index a58ed073..036e4160 100644 --- a/backend/src/test/java/ch/goodone/backend/service/CopilotChatHistoryServiceTest.java +++ b/backend/src/test/java/ch/goodone/backend/service/CopilotChatHistoryServiceTest.java @@ -40,7 +40,7 @@ void shouldGetHistory() { @Test void shouldSaveMessage() { User user = new User(); - service.saveMessage(user, CopilotContextMode.ARCHITECTURE_QA, "user", "hello"); + service.saveMessage(user, CopilotContextMode.ARCHITECTURE_QA, "user", "hello", "{\"answer\":\"hi\"}"); verify(repository).save(any()); } diff --git a/backend/src/test/java/ch/goodone/backend/service/TaskParserServiceTest.java b/backend/src/test/java/ch/goodone/backend/service/TaskParserServiceTest.java index 45abacdd..755860ae 100644 --- a/backend/src/test/java/ch/goodone/backend/service/TaskParserServiceTest.java +++ b/backend/src/test/java/ch/goodone/backend/service/TaskParserServiceTest.java @@ -78,8 +78,7 @@ void shouldSupportNewSynonyms() { void shouldParseSimpleTitle() { var result = service.parse("Buy milk"); assertThat(result.title()).isEqualTo("Buy milk"); - assertThat(result.priority()).isEqualTo(Priority.MEDIUM); - assertThat(result.status()).isEqualTo(TaskStatus.OPEN); + assertThat(result.priority()).isNull(); assertThat(result.dueDate()).isNull(); } @@ -166,8 +165,8 @@ void shouldHandleCsvWithTwoPartsMetadata() { void shouldHandleHeuristicWithoutSpecificTokens() { var result = service.parse("Just some words"); assertThat(result.title()).isEqualTo("Just some words"); - assertThat(result.priority()).isEqualTo(Priority.MEDIUM); - assertThat(result.status()).isEqualTo(TaskStatus.OPEN); + assertThat(result.priority()).isNull(); + assertThat(result.status()).isNull(); assertThat(result.dueDate()).isNull(); } diff --git a/doc-noindex/presentation/intro/SoftwareEntwicklungAi-Intro.pptx b/doc-noindex/presentation/intro/SoftwareEntwicklungAi-Intro.pptx deleted file mode 100644 index 6b488f30..00000000 Binary files a/doc-noindex/presentation/intro/SoftwareEntwicklungAi-Intro.pptx and /dev/null differ diff --git a/doc-noindex/presentation/intro/SoftwareEntwicklungAi-Level4.pptx b/doc-noindex/presentation/intro/SoftwareEntwicklungAi-Level4.pptx new file mode 100644 index 00000000..3b280f44 Binary files /dev/null and b/doc-noindex/presentation/intro/SoftwareEntwicklungAi-Level4.pptx differ diff --git a/doc-noindex/presentation/intro/assets/AdrDrift2.png b/doc-noindex/presentation/intro/assets/AdrDrift2.png new file mode 100644 index 00000000..56adf23b Binary files /dev/null and b/doc-noindex/presentation/intro/assets/AdrDrift2.png differ diff --git a/doc-noindex/presentation/intro/assets/Epics22.png b/doc-noindex/presentation/intro/assets/Epics22.png new file mode 100644 index 00000000..f2efd758 Binary files /dev/null and b/doc-noindex/presentation/intro/assets/Epics22.png differ diff --git a/doc-noindex/presentation/intro/assets/Epics22Crop.png b/doc-noindex/presentation/intro/assets/Epics22Crop.png new file mode 100644 index 00000000..aa36d2bd Binary files /dev/null and b/doc-noindex/presentation/intro/assets/Epics22Crop.png differ diff --git a/doc-noindex/presentation/intro/assets/OnboardingAssistant.png b/doc-noindex/presentation/intro/assets/OnboardingAssistant.png new file mode 100644 index 00000000..190b48e5 Binary files /dev/null and b/doc-noindex/presentation/intro/assets/OnboardingAssistant.png differ diff --git a/doc-noindex/presentation/intro/assets/RiskRadar.png b/doc-noindex/presentation/intro/assets/RiskRadar.png new file mode 100644 index 00000000..8da49ff5 Binary files /dev/null and b/doc-noindex/presentation/intro/assets/RiskRadar.png differ diff --git a/doc-noindex/presentation/intro/assets/SprintStart.gif b/doc-noindex/presentation/intro/assets/SprintStart.gif new file mode 100644 index 00000000..de413f87 Binary files /dev/null and b/doc-noindex/presentation/intro/assets/SprintStart.gif differ diff --git a/doc-noindex/presentation/intro/files/mermaid-datenmodell-diagramm-entities-relations.png b/doc-noindex/presentation/intro/files/mermaid-datenmodell-diagramm-entities-relations.png new file mode 100644 index 00000000..904e191a Binary files /dev/null and b/doc-noindex/presentation/intro/files/mermaid-datenmodell-diagramm-entities-relations.png differ diff --git a/doc-noindex/presentation/intro/files/mermaid-technische-architektur-2.png b/doc-noindex/presentation/intro/files/mermaid-technische-architektur-2.png new file mode 100644 index 00000000..c8b42f9f Binary files /dev/null and b/doc-noindex/presentation/intro/files/mermaid-technische-architektur-2.png differ diff --git a/doc-noindex/presentation/intro/files/mermaid-technische-architekturfolie.png b/doc-noindex/presentation/intro/files/mermaid-technische-architekturfolie.png new file mode 100644 index 00000000..c8b42f9f Binary files /dev/null and b/doc-noindex/presentation/intro/files/mermaid-technische-architekturfolie.png differ diff --git a/doc-noindex/presentation/intro/generate-intro-slides.md b/doc-noindex/presentation/intro/generate-intro-slides.md index ac08113d..5d9643b7 100644 --- a/doc-noindex/presentation/intro/generate-intro-slides.md +++ b/doc-noindex/presentation/intro/generate-intro-slides.md @@ -17,12 +17,12 @@ The following steps generate the presentation for Iteration 4: This generates `doc-noindex/presentation/iteration-4/slides-img-4.md` (with PNG references) and saves images in `files/`. 3. **Generate PowerPoint**: ```bash - pandoc goodone-intro.md -o SoftwareEntwicklungAi-Intro.pptx + pandoc goodone-intro.md -o SoftwareEntwicklungAi-Level4.pptx ``` 3. **Generate PowerPoint**: ```bash - pandoc goodone-intro-img.md -o SoftwareEntwicklungAi-Intro.pptx + pandoc goodone-intro-img.md -o SoftwareEntwicklungAi-Level4.pptx ``` diff --git a/doc-noindex/presentation/intro/goodone-intro-img.md b/doc-noindex/presentation/intro/goodone-intro-img.md index 4ab93609..169d94c0 100644 --- a/doc-noindex/presentation/intro/goodone-intro-img.md +++ b/doc-noindex/presentation/intro/goodone-intro-img.md @@ -25,39 +25,73 @@ Stark KI-gestützte Entwicklung ::: notes -Super spannendes Thema +Willkommen zu super spannendem Thema. Software Entwicklung mit KI Grosses Interesse -Präsentation angepasst. -1. Teil hands-On Präsentation -2. Code Generierung -2. Fragen +Hauptteil Live Demo einer stark KI-unterstützten Applikation. +Beispiel GoodOne.ch. Selbst entwickelt. selbst ausprobieren. +Wie umfassend KI den ganzen Entwicklungsprozess unterstützen kann mit guten KI Tools. +Dies ist Realität. -Eröffnungsfolie. +KI hochgradig integriert +Features wie +Q&A Chat +Retrospective +Sprint Planung +Analysiert Risiko der Implementation -Positionieren Sie dies als praktisches technisches System, nicht als generische KI-Vision-Präsentation. -Das Publikum sollte zwei Dinge erwarten: -1. Beeindruckende Live-Funktionen -2. Eine glaubwürdige Implementierungsgeschichte +Bei Fragen grad melden, oder falls ich Fenster verliere -Vorschlag für den Einstieg: - -Eine Methode zur Softwareentwicklung, bei der das System zunehmend in der Lage ist, -sich selbst zu erklären, zu reflektieren und die Entwickler zu unterstützen.“ +Kommt mit auf die spannende Reise. ::: --- -# Verbesserungsvorschläge zur Lauzeit +# Verbesserungsvorschläge zur Laufzeit ![Das neuste Feature](assets/GoodOneChDetail.png){width=100%} ::: notes +Neustes Feature seit 1 Woche: KI macht Vorschläge zur eigenen Verbesserung + +::: + +--- + +# Agenda Demo + +:::::: columns +:::::: {.column width="50%"} +1. Live-Demo GoodOne.ch. +**Rennstrecke** + +2. Code Generierung mit KI. +**Rennwagen** + +3. Einblicke in die Implementierung + +4. Fragen +:::::: +:::::: {.column width="50%"} +![Rennen](assets/Race3Cars.png){width=100%} +:::::: +:::::: + +::: notes +Je ein Viertel Zeit, Letzte 20 Minuten Diskussion. +T., bitte intervenieren, damit genug Zeit für Fragen + +Alles, was ihr seht, ist KI generiert. Ganzer Prozess hochgradig KI unterstützt +100% Code generiert +Präsentation, alle Diagramme + +Wieso seht ihr Rennwagen? Nächste Slide ::: + --- # GoodOne.ch - Entstehung @@ -70,10 +104,9 @@ Ende 2025 Heute - KI ist ein Rennwagen -- Kontinuierliche Verbesserung durch KI -- 18 Sprints bisher -- Jeder Sprint wird schneller +- 15 Sprints (Runden) bisher - 420 umgesetzte Storys +- Jeder Sprint wird schneller wegen kontinuierlicher Verbesserung durch KI - 1 begeisterter KI-Entwickler KI-getrieben @@ -85,18 +118,25 @@ KI-getrieben ::::: ::: notes +Ich arbeite als SLX Entwickler im Team DevOps Risikosysteme. +Gegen Ende letzten Jahres eine KI Offensive mit 2 Meetings für alle Entwickler +Habe empfohlene KI Tools (Rennwagen) ausprobiert. Etwas entteuscht wieder ausgeschtegen nach wenigen Metern. +Ich kam nicht weiter -„Dies begann als Experiment. +Ende Jahr, technische Neugier gepackt +Privat Lizenz für ein paar KI Tools (Rennwagen) erworben und losgelegt +Unbekanntes Gefährt - reingesetzt und das Gaspedal gesucht +KI intensiv gefragt, was sind die nächsten Schritte +KI erklärte mir dann selbst wie ich den Rennwagen benutze. +Geplant 1 Web Seite KI generiert -Technische Neugier -Unbekanntes Gefährt - 1 Web Applikation -Super size me +Sehr schnell Potential gesehen +Super size me - Prinzip Herausgestellt: Formel 1 Auto -Andere Teilnehmer schnelleres Auto? -ZKB noch viele mit Fahhrad unterwegs +Details - Klassen - Unit Tests @@ -116,12 +156,43 @@ ZKB noch viele mit Fahhrad unterwegs --- +# Das Rennen hat begonnen + +![Rennen](assets/Race3Cars.png){width=100%} + +::: notes + +Kommt mit mir mit auf die Rennstrecke. +Nehmt Platz als Taxigast. +Ihr dürft gerne nachher auch selbst fahren. Source Code öffentlich, registrieren auf GoodOne.ch mit privater Email + +Zur Rennstrecke - Meine Applikation +Es gibt sicher schnellere auf der KI Piste +Spielt keine Rolle. Ich bin fahre knapp unter meinem Limit +um nicht in die Seitenbande zu knallen. +Macht Riesen-Spass +Unter Helm des Fahrers schauen: riesen Smile durch Geschwindigkeitsrausch + +Diskussion am Ende +Intern etwas neblig. +Andere Teilnehmer schnelleres Auto? + +Intern noch viele Kollegen +- kennen Rennwagen nur von aussen +- mit weniger effizienten Rennwagen unterwegs +- mit Fahrrad unterwegs + +Diese Präsentation auch ein Impuls, selbst das Steuer in die Hand zu nehmen. + +::: + +--- + # Herausforderung moderner Softwareentwicklung Typische Herausforderungen: -- fragmentierter Projektkontext -- Architekturwissen verteilt +- Wissen verteilt - inkonsistente Entscheidungen - versteckte Risiken - schwieriges Onboarding @@ -136,10 +207,16 @@ Ergebnis: **GoodOne füllt diese Lücke.** ::: notes +Vor der Demo noch 2 Slides + +Aus der täglichen Erfahrung in unserem Dev Ops Team kann ich folgendes Pain-Points absolut unterschreiben Kernaussage: -„Das Problem ist nicht nur die grössere Menge an Code. Das Problem ist, -dass der Projektkontext die Kapazität des Arbeitsgedächtnisses der Teams übersteigt.“ +Problem: Das Projekt übersteigt das Arbeitsgedächtnisses des Teams.“ + +Applikationen welche ich intern kenne +- fragmentierter Projektkontext +- Architektur Wissen verteilt ::: --- @@ -150,7 +227,7 @@ dass der Projektkontext die Kapazität des Arbeitsgedächtnisses der Teams über :::::: {.column width="50%"} ## Software, die sich selbst erklärt -GoodOne verwandelt Softwareprojekte in Systeme, die: +GoodOne verwandelt Softwareprojekte in Systeme: - Dokumentiert sich selbst - Erklärt Zusammenhänge @@ -163,53 +240,130 @@ GoodOne verwandelt Softwareprojekte in Systeme, die: :::::: :::::: ---- -# Agenda +::: notes -## Live Demo +Bereits Realität. Wenn auch in vielen Teilen erst experimentell. +Projekt wächst extrem schnell. +Staune selbst über Power von KI. +Wende Findings (Rückmeldungen der KI) der Applikation praktisch an. Untersuche gemeldete Risiken. -1. **Live-Demo mit den neuesten Funktionen** -- `/copilot` -- `/intelligence` -- `/retrospective` -- `/admin/ai-coverage` -2. **Wie KI GoodOne durchgängig unterstützt** +::: -3. **Einblicke in die Implementierung** -- Live-Dokumentation +--- -- Iterationen +# Agenda Demo -- KI-Ebenen -4. **Strategisches Fazit** -5. **Technischer Anhang** +1. **Live-Demo mit den neuesten Funktionen** + +User-Feature: +- /tasks + +Generisches KI Framework: +- AI Onboarding Assistant +- /copilot +- /epics +- /intelligence +- /retrospective +- /admin/ai-coverage ::: notes -Machen Sie deutlich, dass die Demo zuerst stattfindet. -Dies ist wichtig, da die Zuhörer den Produktnutzen erleben sollten, bevor sie die Implementierungsdetails kennenlernen. +Endlich geht es los. -Was ich beim Publikum vermitteln möchte -- *ist real* -- *ist sofort nützlich* -- *geht weit über einen -- *verändert Art Weise, wie +Zuerst das basis user feature /taks +User feature je nach Applikation austauschbar -**Zielreaktion:** +Danach KI Framework on top. Wiederverwendbare KI Logik und Features. +Jede der Demo Seite ist die Grundlage für die nächste. +Steigende Komplexität -> „Wow – das ist ein enormer Vorteil. Wir sollten unsere internen KI-Tools unbedingt weiterentwickeln.“ +Aktuell Mismatch, da KI Prototyp +2 % User Feature +98% KI Logik -Dies ist eine Einführungsfolie direkt vor der Live-Demo. +Demo 0 /Onboarding +What is the main user feature of this application +How to Create a New Task -Machen Sie die Erwartungen deutlich. +Demo 00 /Tasks +Finde vergessene Ostereier spätestens am Lunedì di Pasqua. urgente -Es ist auch hilfreich, wenn die Live-Umgebung ein oder zwei Schwächen aufweist: Das Publikum weiß dann bereits, wie es die Demo betrachten soll. +Beispiel für KI zur Laufzeit +Eingabe 2 Teile +herkömmliches Parsing +KI aufgerufen (Open AI) ::: --- + +--- + +# Demo 1a – AI Onboarding Assistant + +::: columns +::: {.column width="48%"} + +## Einstiegspunkt für neue Entwickler + +Der AI Onboarding Assistant erklärt das Projekt verständlich aus High-Level Perspektive. + +Typische Fragen: +- What is the main purpose of this system? +- Which components are most important? +- How is the architecture structured? +- Where should a new developer start? + +Nutzen: +- schneller Einstieg +- konsistentes Projektverständnis +- weniger Abhängigkeit von Einzelpersonen +- reduzierte Einarbeitungszeit + +::: + +::: {.column width="52%"} + +![AI Onboarding Assistant](assets/OnboardingAssistant.png) + +::: +::: + +::: notes +Wie schnell neue Entwickler produktiv werden können. + bewusst weniger technisch als der Copilot. + +Unterschied zum Copilot: +- stärker abstrahierter Kontext +- stärker kuratierte Dokumentbasis +- Fokus auf Verständnis statt Implementierung + +Typischer Kontext für den Prompt: + +System instruction: +"You are an onboarding assistant helping a developer understand a new project." + +Retrieval scope eingeschränkt auf: +- overview docs +- ADR summaries +- feature summaries +- glossary +- architectural diagrams + +Nutzen für Organisation: + +reduziert Abhängigkeit von Schlüsselpersonen +reduziert Wiederholungsfragen +verbessert Konsistenz von Architekturverständnis +macht Projektwissen skalierbar + +Überleitung: +nach Verständnis → aktive Unterstützung durch Copilot. + +::: + # Demo 1 – Copilot ::: columns @@ -217,12 +371,13 @@ Es ist auch hilfreich, wenn die Live-Umgebung ein oder zwei Schwächen aufweist: ## Kontextbasierte Antworten Mögliche Fragen: -- Welche Laufzeitfunktionen nutzen KI? -- Welche Dokumente beschreiben die Architektur? -- Welche ADRs sind am relevantesten? -- Wie sollte sich ein neuer Entwickler im System zurechtfinden? +- Which features use AI at runtime? +- Which documents describe architecture? +- Which ADRs are most important? (Architectural Decision Records) +- How should a new developer be trained? -**Wichtiger Hinweis:** Die Qualität der Antworten hängt vom Projektkontext ab, nicht von allgemeinem Modellwissen. +**Wichtiger Hinweis:** +Die Qualität der Antworten hängt vom Projektkontext ab, nicht von allgemeinem Modellwissen. ::: ::: {.column width="52%"} @@ -231,18 +386,162 @@ Mögliche Fragen: ::: ::: notes -Verwenden Sie eine vorbereitete Frage, die Architekturverständnis zeigt. +Im Hintergrund +sucht interne Projektdokumentation +KI Prompt erzeugt +Dokumentation an KI Prompt mitgegeben +Resultat der KI Abfrage geparsed + +- Wichtig ist, dass KI mit Wissen aus unserer Projektdokumentation antwortet.“ +Nicht KI Wissen unbekannter Herkunft +Keine Halluzinationen +Immer Dokument-Referenz zur Kontrolle + +3 Gruppen +- Architecture Q&A +- Engineering Chat +- Onboarding Help + +Implementation jedesmal dasselbe, +jedoch andere Projektdokumente dem Prompt mitgegeben +andere Persona verwendet + +**** + +a) Architecture +show ADR links + +**** + +b) Engineering versteht Code + Kontext? +- Task-Dokumente: + - Ziel + - Akzeptanzkriterien + - Implementierungs-Logs + - Iterationen + +- technische Dokumentation: + - relevante Code-nahe Beschreibungen + - ggf. API-Strukturen + +- optional: + - Fehlerlogs + - Test-Notizen + +Die KI sieht NICHT den gesamten Code. +Sondern: +→ abstrahierte, strukturierte Repräsentationen + +Warum? + +- Token-Limits +- Performance +- Fokus + +Typischer Prompt-Aufbau: + +1. System Instruction: + „Du bist ein Engineering Assistant…“ + +2. Kontext: +- relevante Tasks (Top-N via Embedding) +- technische Dokumente + +3. User-Frage + +Die KI kann: +- Features erkennen +- Zusammenhänge verstehen +- Risiken ableiten + +****** + +c) Onboarding erklärt Basics +Hier ist der Kontext bewusst anders gewählt. + +Die KI bekommt: +- High-Level Architektur-Dokumente +- vereinfachte Beschreibungen +- Use Cases +- ggf. Glossar / Begriffsdefinitionen + +Keine Low-Level Details. +- Zielgruppe: neue Entwickler +- Fokus: Verständnis, nicht Implementierung + +Prompt ist typischerweise: +„Erkläre verständlich…“ +„Vermeide zu technische Details…“ + +Das führt zu: +- einfacheren Antworten +- weniger Fachjargon +- klarer Struktur -Optimaler Effekt: -- Fragen zu Laufzeit-KI-Funktionen stellen -- zeigen, dass die Antwort auf ADRs und interne Konzepte verweist -Botschaft: -„Wichtig ist nicht, dass ein LLM antworten kann. Wichtig ist, dass er aus unserem Systemspeicher antwortet.“ ::: --- + +--- + +# Demo 2a – AI Project Roadmap + +::: columns +::: {.column width="48%"} + +## Strukturierte Projektentwicklung mit KI + +Die Roadmap zeigt, wie sich Features über Iterationen entwickeln. + +KI hilft bei: +- Strukturierung von Epics +- Ableitung von Tasks +- Priorisierung von Themen +- Erkennen von Abhängigkeiten +- Fortschrittsanalyse + +Die Projektstruktur wird selbst zum Wissensartefakt. + +::: + +::: {.column width="52%"} + +![AI Project Roadmap](assets/Epics22Crop.png) + +::: +::: + +::: notes +Planung und wichtigen Teil der Wissensbasis. +Epic → Tasks → Implementierung → Signale → Intelligence + +Epics helfen der KI zu verstehen: +- welche Themen zusammengehören +- welche Komponenten gemeinsam verändert werden +- welche Bereiche stark evolvieren +- wo potenziell Instabilität entsteht + +Epics sind mittlere Abstraktionsebene: +nicht Vision, nicht Detail-Task, +sondern strukturierter Kontext für reasoning. + +Beziehung zu Engineering Intelligence: +Engineering Intelligence benötigt strukturierte Historie. + +Ohne Epics: +isolierte Tasks + +Mit Epics: +semantische Entwicklungslinie. + +Überleitung: +von Struktur → Mustererkennung. + +::: + # Demo 2 – Engineering Intelligence ::: columns @@ -257,9 +556,8 @@ Botschaft: - Unterstützt Priorisierung **Wichtiger Hinweis:** -Dies ist kein Dashboard mit Rohdaten. - -Es ist eine Analyseebene. +Dies ist kein Dashboard mit Rohdaten. +Es ist eine Analyse. ::: ::: {.column width="54%"} @@ -268,11 +566,71 @@ Es ist eine Analyseebene. ::: ::: notes -Betonen Sie den Unterschied zwischen Überwachung und Verständnis. -Überwachung zeigt Ihnen, was passiert ist. -Diese Ebene hilft Ihnen, abzuleiten, was Aufmerksamkeit erfordert. -Öffnen Sie nach Möglichkeit eine Beispielkarte und erläutern Sie, -warum das System sie als hohes Risiko einstuft. +Das ist der erste Punkt, wo KI wirklich Richtung „Denken“ geht. +Keine Überwachung, sondern Verständnis + +1. Was passiert hier grundsätzlich? +Die KI beantwortet nicht einfach eine Frage. +Sie macht intern 3 Dinge: + +1. Informationen sammeln +2. Beziehungen herstellen +3. Auswirkungen bewerten + +Das ist ein qualitativer Unterschied. + +2. Datenquellen +Die Antwort basiert typischerweise auf: +- Architektur-Dokumente (ADRs) +- Tasks (inkl. Historie) +- Feature-Beschreibungen +- ggf. Logs + +4. Prompt +- relevante Text-Chunks +- Struktur (z.B. „liste Module auf“) +- Instruktionen („nennen Sie Risiken“) + +5. Die KI: +- extrahiert Entitäten (Features, Module) +- erkennt Beziehungen (Abhängigkeiten) +- leitet Risiken ab + +Das ist KEIN klassischer Algorithmus. +Das ist semantisches Reasoning. + +6. Warum ist das schwer ohne KI? +Weil: +- Informationen verteilt sind +- Beziehungen nicht explizit modelliert sind +- Kontext ständig wechselt + +Ein klassisches System müsste: +→ vollständigen Dependency Graph haben + +KI kann: +→ implizite Beziehungen erkennen + +7. Wo liegt die Grenze? +KI kann: +✔ Zusammenhänge erkennen +✔ Risiken abschätzen + +KI kann NICHT: +✖ garantieren, dass alles korrekt ist +✖ vollständige Abhängigkeiten kennen + +8. Wichtigstes mentales Modell +„Die KI baut on-the-fly ein mentales Modell des Systems.“ +Nicht perfekt. +Aber oft ausreichend gut, um bessere Entscheidungen zu treffen. + +9. Warum das ein Game Changer ist +Vorher: +→ Entwickler muss alles selbst zusammensuchen +Jetzt: +→ KI liefert eine erste, strukturierte Sicht +Das spart massiv Zeit. ::: @@ -299,13 +657,76 @@ warum das System sie als hohes Risiko einstuft. ::: ::: notes -Ein wichtiger Satz: - „Dies ersetzt nicht die Diskussion. Es verbessert die Ausgangsbasis der Diskussion.“ Erwähnen Sie, dass das System Muster aus Aufgaben und Protokollen synthetisieren kann, die Menschen unter Zeitdruck nicht manuell erfassen würden. +Retrospektiven werden oft durch Erinnerung und subjektive Wahrnehmung dominiert. +GoodOne analysiert automatisch Task-Historien, Iterationsmuster und Implementierungslogs. + +Die KI erkennt: +- wiederkehrende Probleme +- Iterationsschleifen +- fehlende Akzeptanzkriterien +- Hotspots im Code + +Retrospektiven werden datenbasiert statt rein subjektiv. + +Technischer Deep Dive: + +Datenquellen: +- strukturierte Tasks mit Ziel, Akzeptanzkriterien, Status und Verlinkungen +- Iterationshistorie je Task +- Logs und Änderungsverläufe +- Sprintzuordnung und zeitliche Entwicklung +- optional Test- und Verifikationshinweise + +Interne Repräsentation: +Eine Aufgabe ist nicht nur Markdown-Text, sondern wird logisch als Wissenseinheit behandelt: +- id +- title +- description +- acceptanceCriteria[] +- implementationLog[] +- relatedTasks[] +- sprintId +- iterationCount +- statusHistory[] +- embeddings[] + +Signalbildung: +Vor der KI-Interpretation werden deterministische Signale abgeleitet: +- hohe Iterationszahl → Unsicherheit, Scope Drift oder fehlende Präzision +- mehrfach geänderte Akzeptanzkriterien → Ziel unklar oder nachträglich geschärft +- Task ohne Verknüpfung zu ADRs oder anderen Tasks → isoliertes Wissen +- Testartefakte erst spät → potenziell schwache frühe Absicherung + +Warum diese Vorverarbeitung wichtig ist: +Die Retrospektive sollte nicht auf Rohtexten beruhen. Zuerst werden Signale extrahiert, aggregiert und komprimiert. Erst dann wird ein LLM verwendet, um Muster und Verbesserungsvorschläge zu formulieren. + +Typischer Prompt-Aufbau: +Systemrolle: +"You are an engineering retrospective assistant." + +Kontext: +- Sprintkennung +- Task-Anzahl +- aggregierte Signale +- auffällige Komponenten +- wiederkehrende Änderungsmuster + +Instruktion: +- erkenne Muster +- fasse Erfolge und Probleme zusammen +- mache konkrete Verbesserungsvorschläge + +Nutzen dieser Architektur: +- weniger Tokenverbrauch +- stabilere und reproduzierbarere Antworten +- klarere Trennung von Fakten und Interpretation +- besser erklärbare Retro-Ergebnisse + ::: --- @@ -317,10 +738,10 @@ die Menschen unter Zeitdruck nicht manuell erfassen würden. ## Transparenz darüber, was die KI tatsächlich versteht Warum das wichtig ist: -- Wir können die Wissensabdeckung überprüfen. -- Wir können blinde Flecken identifizieren. -- Wir können die Kontextqualität gezielt verbessern. -- Wir können die KI-Unterstützung nachvollziehbar machen. +- Wissensabdeckung überprüfen. +- blinde Flecken identifizieren. +- Kontextqualität gezielt verbessern. +- KI-Unterstützung nachvollziehbar machen. **KI wird nachvollziehbar, nicht mysteriös.** ::::::: @@ -330,18 +751,159 @@ Warum das wichtig ist: ::::::: ::: notes -Falls der Live-Bildschirm verfügbar ist, zeigen Sie die Seite. -Andernfalls erläutern Sie das Konzept kurz. -Diese Folie ist wichtig für das Vertrauen. -Viele Menschen akzeptieren KI, wenn sie nützlich ist, -aber sie vertrauen ihr mehr, wenn sie nachvollziehen können, -woher ihr Verständnis stammt. + +Diese Folie zeigt, was die KI tatsächlich weiss. +Wichtige Kennzahlen: +- Stale Documents → potenziell veraltetes Wissen +- Recently Used → stark genutzter Kontext +- Unvisited Branches → mögliche Wissenslücken + +Die Qualität der KI hängt stark von strukturierten Projektartefakten ab. +Prompt Engineering wird zu Knowledge Engineering. + +Technischer Deep Dive: + +Ziel der Coverage-Analyse: +Nicht nur zeigen, welche Dokumente existieren, sondern welche Dokumente bei realen KI-Abfragen tatsächlich im Kontext landen. + +Retrieval Logging: +Jede KI-Anfrage erzeugt Metadaten wie: +- query +- embedding vector +- retrieved documents +- similarity score +- chunk id +- timestamp +- prompt type +- feature + +Dadurch lassen sich Coverage-Kennzahlen berechnen: +- retrieval frequency: wie oft ein Dokument in Top-N Treffern erscheint +- stale documents: lange nicht verwendete Dokumente +- unused documents: nie verwendete Dokumente +- branch coverage: Nutzung nach Dokumentpfad oder Wissensdomäne + +Typische Ursachen für schwache Abdeckung: +- semantische Lücke zwischen Dokumentsprache und Nutzerfragen +- zu grobes oder zu feines Chunking +- schlechte Überschriften oder unklare Struktur +- Dokumente sind zwar vorhanden, aber nicht in reale Workflows eingebunden + +Chunking-Strategie: +Typisch werden Markdown-Dokumente in strukturierte Chunks überführt: +- path +- heading +- text +- embedding + +Bei einer Anfrage läuft technisch: +query → embedding → similarity search → top N chunks → Prompt-Erstellung → LLM + +Wichtige Erkenntnis: +Coverage ist keine reine Doku-Metrik. +Coverage ist eine operative Qualitätsmetrik für KI-Nutzbarkeit. + + +::: + +--- + + +--- + +# Demo 5 – ADR Drift + +::: columns +::: {.column width="46%"} + +## Abweichungen zwischen Architektur und Implementierung erkennen + +ADR Drift zeigt, wo Implementierung und Architekturentscheidungen auseinanderlaufen. + +KI unterstützt bei: + +- Identifikation betroffener ADRs +- Erkennen inkonsistenter Implementierungen +- Sichtbarmachen impliziter Architekturänderungen +- Priorisierung von Architektur-Review Bedarf +- Verbesserung langfristiger Systemstabilität + +**Architektur bleibt ein lebendes Artefakt.** + +::: + +::: {.column width="54%"} + +![ADR Drift](assets/AdrDrift2.png) + +::: +::: + +::: notes + +ADR Drift adressiert ein klassisches Problem: +Architekturentscheidungen werden getroffen, +aber später stillschweigend verändert. + +Nutzen: +frühe Sichtbarkeit von Architekturdrift +bessere Entscheidungsgrundlagen +reduzierter Refactoring-Aufwand + +Überleitung: +von Drift → Risiko. ::: + --- -# Erste Erkenntnisse aus der Demo +# Demo 6 – Risk Radar + +::: columns +::: {.column width="46%"} + +## Früherkennung von Risiken im Projektkontext + +Risk Radar aggregiert schwache Signale zu handlungsrelevanten Hinweisen. + +KI erkennt: + +- Instabilitätsmuster +- Komplexitätsanstieg +- Kontextlücken +- fehlende Traceability +- potenzielle Architekturprobleme + +Das Radar hilft bei Priorisierung technischer Verbesserungen. + +**Risiken werden sichtbar, bevor sie kritisch werden.** + +::: + +::: {.column width="54%"} + +![Risk Radar](assets/RiskRadar.png) + +::: +::: + +::: notes + +Risk Radar kombiniert mehrere schwache Signale zu einem Gesamtbild. + +Nutzen: + +frühzeitige Identifikation technischer Risiken +bessere Priorisierung von Refactoring +höhere Systemstabilität über Zeit + +Schliesst den Kreis: +Signale → Intelligence → Entscheidungen. + +::: + +# Erkenntnisse aus der Demo ## GoodOne ist keine nachträglich hinzugefügte KI @@ -353,27 +915,24 @@ Was in der Demo sichtbar wird: **Systemverständnis wächst kontinuierlich.** ::: notes -Dies ist die Brücke von der Demo zur Implementierung. -Es sei explizit darauf hingewiesen, -dass der Wow-Effekt nicht durch einen einzelnen Modellaufruf hervorgerufen wird. -Er entsteht durch Architektur, Workflow und Wissensdesign. +Brücke von der Demo zur Implementierung. ::: --- -# Wie KI GoodOne unterstützt +# Produkt-Iteration / Sprint :::::: columns :::::: {.column width="50%"} -Durchgängig, nicht nur zur Laufzeit KI ist im gesamten Lebenszyklus präsent. -- **Dev + AI**: Zieldefinition -- **Sprint & Tasks**: Planung +- **Iterations-Ziel**: Dev + Chat GPT +- **Sprint & Storys**: Planung durch Chat GPT - **Implementierung**: Junie AI -- **Dokumentation**: Automatisch -- **Review**: Tests + Checks +- **Dokumentation**: Automatisch Junie AI +- **Review**: Tests + Checks. Dev und beide KIs + Daher steigert das System seinen Wert im Laufe der Zeit. :::::: :::::: {.column width="50%"} @@ -382,53 +941,27 @@ Daher steigert das System seinen Wert im Laufe der Zeit. :::::: ::: notes - -Erläutern Sie, dass GoodOne KI in vier verschiedenen Phasen einsetzt: +Tägliche Arbeit mit KI. Schritte wie bei der normalen Entwicklung. +Neu: viele Teilschritte intensiv mit KI unterstützt Strukturierter Prozess statt „Prompt → Code“. - - Ziel zuerst, nicht Lösung -- Tasks mit Akzeptanzkriterien +- Storys mit Akzeptanzkriterien - KI implementiert iterativ - Dokumentation entsteht automatisch - Mensch bleibt Entscheider -::: - ---- - -# Das Rennen läuft - -![Rennen](assets/Race3Cars.png){width=100%} - - ---- - -# Meine Rennwagen +Meiste Zeit für DEV bei Tests (grün) -:::::: columns -:::::: {.column width="50%"} -![KI 1: ChatGPT](assets/RaceCar1ChatGpt.png) -:::::: -:::::: {.column width="50%"} -![KI 2: Junie AI](assets/SprintStart.png) -:::::: -:::::: +Teilschritte als nächstes durchgegangen -::: notes -Sprint Planung im Dialog mit Chat GPT -Story erstellt durch Chat GPT - -Umsetzung mit Junie AI -1 Sprint ::: --- - # Sprintplanung und Aufgabengenerierung -## ChatGPT strukturieren die Arbeit vor dem Programmieren +## ChatGPT strukturiert die Arbeit vor dem Programmieren KI-Unterstützung in der Planung: @@ -441,14 +974,18 @@ KI-Unterstützung in der Planung: **Die Planung wird schneller und strukturierter.** ::: notes -Beachten Sie, dass es hier nicht darum geht, das Produkt-Denken zu ersetzen. +Aufwand reduzieren, +Viel bessere Prompts und Akzaptanzkritieren durch Chat GPT als von hand +Klar, könnte man Story selbst schreiben -Es geht darum, den Aufwand zu reduzieren, -Absichten in strukturierte Entwicklungsarbeit umzusetzen. -Mögliche Formulierung: „Viele Projektprobleme entstehen durch unpräzise formulierte Absichten. KI hilft uns, mit einem besseren Vertrag zu starten.“ +Beispiel Ziel Sprint 2.2: +Unbenutzte Dokumentation erkennen. +- Prompts loggen +- UI Seite der referenzierten Dokumentation +- ::: --- @@ -473,17 +1010,35 @@ Der Entwickler entscheidet weiterhin: - Freigabe bleibt menschlich ::: notes -Wichtige Nuancenfolie. -Dies ist keine Beschreibung von automatisiertem Code. -Die Kernaussage lautet: KI steigert Durchsatz und Konsistenz, +KI steigert Durchsatz und Konsistenz, während der Entwickler die Verantwortung behält. ::: --- -# Vollständige Iteration auf einen Schlag +# Meine Rennwagen +:::::: columns +:::::: {.column width="50%"} +![KI 1: ChatGPT](assets/RaceCar1ChatGpt.png) +:::::: +:::::: {.column width="50%"} +![KI 2: Junie AI](assets/SprintStart.png) +:::::: +:::::: + +::: notes +Sprint Ziel und Planung im Dialog mit Chat GPT +Chat GPT erstellt alle Storys + +Umsetzung mit Junie AI +Alle Storys Junie AI übergeben +::: + +--- + +# Vollständige Iteration implementiert auf einen Schlag :::::: columns :::::: {.column width="50%"} @@ -520,8 +1075,6 @@ Eine Aufgabe ist mehr als ein Ticket. Es kann Folgendes enthalten: **Dokumentation ist nicht länger von der Auslieferung getrennt.** ::: notes -Diese Folie ist entscheidend, da sie erklärt, -warum die spätere KI-Unterstützung funktioniert. Ohne strukturierte Aufgabenverwaltung hätte die Laufzeit-KI eine deutlich schwächere Grundlage. ::: @@ -543,9 +1096,7 @@ Wissensspur statt einmaliger Implementierung. ::: notes -Verwenden Sie den deutschen Titel, da er direkt mit dem Material der vierten Iteration verknüpft ist. - -Betonen Sie, dass der Kreislauf keine lineare Wissensvermittlung, sondern kumulatives Lernen darstellt. +Der Kreislauf keine lineare Wissensvermittlung, sondern kumulatives Lernen darstellt. ::: @@ -557,7 +1108,7 @@ Betonen Sie, dass der Kreislauf keine lineare Wissensvermittlung, sondern kumula GoodOne kann zur Laufzeit: -- Interpretiert Laufzeitsignale +- Interpretiert Laufzeitsignale (KI Prompt-Resultate) - Beantwortet Entwicklungsfragen - Fasst Iterationen zusammen - Erkennt Instabilitätsmuster @@ -602,9 +1153,60 @@ entscheidungsnahe Unterstützung ::: notes -Dies ist die gewünschte Übersichtsversion der Folie zu den KI-Ebenen. -Bitte halten Sie es hier auf einem allgemeinen Niveau. -Detailliertere technische Informationen finden Sie im Anhang. +Übersichtsversion der Folie zu den KI-Ebenen. + +Technischer Deep Dive: + +Diese Folie beschreibt die logische End-to-End-Pipeline. + +Layer 1 – Projektspeicher: +Persistente Wissensbasis, typischerweise auf relationalen Daten + Vektorindex aufgebaut. +Mögliche Domänen: +- documents +- tasks +- adrs +- signals +- retrieval_logs +- embeddings + +Markdown ist als Quellformat stark, weil es: +- diffbar +- versionierbar +- LLM-freundlich +- gut strukturierbar ist + +Layer 2 – Verarbeitung: +Mehrere spezialisierte Pipelines laufen parallel: + +Ingestion Pipeline: +Markdown oder Task-Inhalt wird zerlegt: +markdown → chunks → embeddings → store + +Retrieval Pipeline: +Nutzerfrage wird eingebettet: +query → embedding → similarity search → top N chunks + +Signal Pipeline: +Projektartefakte werden in strukturierte Indikatoren übersetzt: +events → features → signals + +Beispiele für Events: +- task updated +- file changed +- dependency changed +- test added + +Layer 3 – Engineering Intelligence: +Dieser Layer nutzt das LLM nicht primär für Fakten, sondern für Interpretation. +Beispiel: +- Modul A wurde 8-mal geändert +- Modul B nur 1-mal +- ADR-Referenzen sind inkonsistent +Das LLM erkennt daraus Instabilitäts- oder Kontextmuster. + +Layer 4 – AI-Anwendungen: +Copilot, Retro, Coverage und Intelligence nutzen dieselbe Infrastruktur. +Das ist wichtig, weil die sichtbaren Funktionen nicht isoliert sind, sondern auf derselben Wissens- und Verarbeitungsschicht beruhen. ::: @@ -626,12 +1228,6 @@ Die KI kann auf Folgendes zurückgreifen: **Das Modell ist wichtig. Die Systemdaten sind entscheidend.** ::: notes -Verwenden Sie die Formulierung, die sich die Zuhörer merken sollen: - -„Das Modell ist wichtig. Die Systemdaten sind entscheidend.“ - -Dies lenkt die Diskussion weg vom Hype um das Modell -und hin zu internen Werkzeugen und der Qualität des Wissens. ::: @@ -650,13 +1246,6 @@ Intelligence-Ansichten erhalten historischen und analytischen Kontext **Gleiches Modell, unterschiedlicher Kontext, unterschiedliche Qualität.** ::: notes -Dies ist eine sehr wichtige Erklärungsfolie. -Die Zuhörer sollten verstehen, dass die Qualität der Antworten gezielt gestaltet wird. -Es ist keine Zauberei. - -Möglicher Satz: - -„Der Trick ist nicht ein intelligenteres Modell pro Bildschirm. Der Trick ist der richtige Kontext für die richtige Frage.“ ::: @@ -679,13 +1268,42 @@ Dieses hybride Muster macht das System nützlicher und vertrauenswürdiger. ::: notes -Erläutern Sie das Designprinzip klar: - Deterministische Logik liefert feste Ankerpunkte - Das LLM liefert semantische Interpretation -- Zusammen erzielen sie bessere Ergebnisse als jede für sich +- Zusammen erzielen sie bessere Ergebnisse + +Technischer Deep Dive: + +Deterministische Komponente: +Klassische Logik erzeugt überprüfbare Signale. +Beispiele: +- Drift-Regel: Implementierung widerspricht ADR +- Volatilität: Änderungen pro Modul und Zeitfenster überschreiten Schwellwert +- Traceability-Lücke: Task ohne Verlinkung zu Architektur oder verwandten Artefakten + +LLM-Komponente: +Das LLM interpretiert nicht den ganzen Code, sondern verdichtete Signale und relevante Kontext-Chunks: +- Welche Muster sind erkennbar? +- Welche Risiken erscheinen plausibel? +- Welche Priorität hat ein Thema? + +Beispiel: +Signale: +- hohe Iterationszahl +- fehlende Akzeptanzkriterien +- wiederholte Änderungen im selben Modul + +Interpretation: +"possible architectural uncertainty" oder "scope instability" -Dies hilft skeptischen technischen Zuhörern. +Warum hybrid? +- Nur Regeln: zu viele False Positives, wenig semantisches Verständnis +- Nur KI: weniger reproduzierbar, schwerer zu verankern +- Kombination: robuste, erklärbare Resultate mit semantischer Tiefe + +Wichtiger Architekturpunkt: +Das LLM steht nicht am Anfang, sondern am Ende einer Fakten- und Signalverarbeitungskette. ::: @@ -705,10 +1323,7 @@ Direkte Vorteile für Teams: - Bessere Retrospektiven und Reviews ::: notes -Richten Sie die Diskussion wieder auf den Nutzen für den Menschen. -Auch wenn die Technologie beim Publikum gut ankommt, -liegt der eigentliche Investitionsgrund in der verbesserten Nutzung -der Engineering-Ressourcen. + ::: --- @@ -727,9 +1342,6 @@ GoodOne wurde durch Iterationen verbessert: **Diese Fähigkeit entstand durch iterative Vorgehensweise.** ::: notes -Beziehen Sie sich auf die vorherigen Iterationspräsentationen. -Die Botschaft lautet: Dies war kein einmaliger Erfolg. -Er war das Ergebnis wiederholter Systemdesignverbesserungen. ::: @@ -752,10 +1364,8 @@ Sie sind Wissensinfrastruktur.** ::: notes -Dies ist eine der stärksten strategischen Aussagen in der Präsentation. -Sprechen Sie sie langsam aus. - -Der Begriff „Wissensinfrastruktur“ muss verinnerlicht werden. +Dies ist eine der stärksten strategischen Aussagen in der Präsentation. +Der Begriff „Wissensinfrastruktur“ muss verinnerlicht werden.` ::: --- @@ -775,18 +1385,15 @@ Mehr investieren in: **GoodOne zeigt, dass sich die Investition enorm auszahlen kann.** ::: notes -Dies ist die vom Nutzer gewünschte Handlungsaufforderung. Die Personalaufstockung sollte sorgfältig, aber deutlich formuliert werden: -Sinnvolle Fähigkeiten erfordern echte Verantwortung, -nicht nur die Energie von Nebenprojekten. - +Sinnvolle Fähigkeiten erfordern echte Verantwortung, ::: --- # App testen -## Der nächste Schritt ist die direkte Nutzung von GoodOne.ch +## Direkte Nutzung von GoodOne.ch Vorgeschlagene Vorgehensweise: @@ -795,11 +1402,9 @@ Vorgeschlagene Vorgehensweise: 3. Vergleiche die Ergebnisse der Retrospektive mit den Daten des Sprints. 4. Überprüfe die KI-Abdeckung und mögliche Schwachstellen. -**Die Notwendigkeit des Ausprobierens wird deutlich, sobald Sie die Systemlogik in Ihrem eigenen Kontext beobachten.** +Probiert es aus ::: notes -Schließen Sie die Hauptaussage mit einem positiven Ausblick ab. - Ziel ist es, Bewunderung in konkretes Handeln umzuwandeln. ::: @@ -809,18 +1414,19 @@ Ziel ist es, Bewunderung in konkretes Handeln umzuwandeln. # Roadmap ## Natürliche nächste Schritte für GoodOne -- Interne Cloud-Migration prüfen -- Stärkere Abdeckungsmetriken -- Besseres Retrieval und Chunking -- Umfassendere Laufzeitsignale -- Architekturvalidierung ausbauen +- Migration auf Firmen-interne Cloud prüfen +- Sprint 2.3 gemäss Demo + - Stärkere Abdeckungsmetriken + - Besseres Retrieval und Chunking + - Umfassendere Laufzeitsignale + - Architekturvalidierung ausbauen + - Bessere Recovery und Empfehlungen - Spezialisierte Copiloten ::: notes -Der aktuelle Stand bereits wertvoll ist, -aber erst eine frühe Version dessen darstellt, -was diese Systemkategorie werden kann. +Der aktuelle Stand bereits wertvoll, +aber erst eine frühe Version. ::: --- @@ -848,9 +1454,7 @@ Mögliche Diskussionsanregungen: - Wie sollten wir diese Kompetenz personell und organisatorisch gestalten? ::: notes -Hier pausieren für Fragen und Antworten. -Bei Zeitmangel können Sie direkt zu den Folien im Anhang springen, -die zu den Fragen passen. + ::: @@ -870,7 +1474,6 @@ die zu den Fragen passen. - Roadmap und Einschränkungen ::: notes -Der Anhang dient als Backup und für weiterführende technische Fragen. ::: @@ -918,12 +1521,11 @@ Ein gut formatiertes Aufgabendokument schafft ein dauerhaftes Speicherobjekt. ::: ::: notes -Dies ist die Antwort auf die Frage: -„Was genau verstehen Sie unter lebendiger Dokumentation?“ +lebendiger Dokumentation? -Erklären Sie, dass Aufgaben funktionieren, -weil sie eng mit der Entwicklungsarbeit verknüpft sind -und daher eher aktuell bleiben als separate Dokumentationen. +Aufgaben funktionieren, weil +eng mit Entwicklungsarbeit verknüpft +aktuell bleiben ::: @@ -944,10 +1546,13 @@ Das Modell ist konstant. Der abgerufene Kontext ändert sich. ::: notes -Dies ist die wichtigste technische Erklärung für RAG. -Erwähnen Sie, dass die Chunking-Qualität, -die Retrieval-Strategie und die Prompt-Disziplin oft wichtiger sind -als das Umschalten zwischen ähnlichen Modellvarianten. +Wichtig +Chunking-Qualität +Retrieval-Strategie +Prompt-Disziplin oft wichtiger + +Weniger wichtig +Umschalten Modellvarianten. ::: @@ -965,7 +1570,7 @@ als das Umschalten zwischen ähnlichen Modellvarianten. | Intelligenz | Aufgabenverlauf, Signale, Metriken | Muster erkennen | ::: notes -Gute Antwort auf die Frage: „Warum nicht nur einen Chat?“ +Warum nicht nur einen Chat? Weil unterschiedliche Aufgaben unterschiedliche Grundlagen, Tonalitäten und Abstraktionsebenen erfordern. @@ -987,11 +1592,10 @@ Signale werden kombiniert interpretiert. ::: ::: notes -Erläutern Sie, dass schwache Signale erst dann nützlich werden, -wenn sie aggregiert und gemeinsam interpretiert werden. +schwache Signale erst dann nützlich, +wenn aggregiert und gemeinsam interpretiert. Beispiele: - - wiederholte Nacharbeit an derselben Komponente - fehlende Akzeptanzkriterien - unvollständige Verifizierung @@ -1021,10 +1625,6 @@ Anwendungsfälle: ::: notes -Falls Fragen zur Architektur-Governance gestellt werden, -ist dies eine hilfreiche Zusatzfolie. -Wichtiger Hinweis: KI kann Abweichungen und Inkonsistenzen aufzeigen; -die Validierung und Entscheidung erfolgt weiterhin durch Menschen. ::: --- @@ -1044,8 +1644,7 @@ die Validierung und Entscheidung erfolgt weiterhin durch Menschen. ::: ::: notes -Dies ist hilfreich, wenn die Zuhörer verstehen möchten, -wie die Planungshistorie in die spätere Analyse einfließt. +Wie die Planungshistorie in die spätere Analyse einfließt. ::: @@ -1065,8 +1664,6 @@ Fragen zur Abdeckung: **Gute KI-Unterstützung wird steuerbar, wenn die Abdeckung sichtbar ist.** ::: notes -Diese Folie unterstreicht, dass vertrauenswürdige KI-Systeme überprüfbare Systeme sind. -Gut für skeptische Manager und Architekten. ::: @@ -1092,8 +1689,7 @@ KI kann nicht garantieren: **Der Entwickler bleibt der Entscheidungsträger.** ::: notes -Fügen Sie diese Folie immer ein, -wenn die Diskussion in übertriebene Erwartungen abzudriften droht. +Wenn die Diskussion in übertriebene Erwartungen abzudriften droht. Sie erhöht die Glaubwürdigkeit. ::: @@ -1203,6 +1799,121 @@ Copilot · Intelligence · Retro ::: notes Radar ist direkte Ableitung des 4-Layer Modells. Zeigt wie Projektsignale zu Engineering Intelligence transformiert werden. + +Technischer Deep Dive: + +Stability Layer: +Sichert die strukturelle Qualität der Wissensbasis. +Beispiele: +- Referenzintegrität: verlinkte ADRs existieren wirklich +- Schema-Validierung: Task enthält Ziel, Kriterien, Status +- Vollständigkeit: Dokumente haben sinnvolle Überschriften und Struktur +- Konsistenzprüfungen: erwartete Felder und Beziehungen sind vorhanden + +Understanding Layer: +Baut semantische Beziehungen auf. +Typische Graphlogik: +Task → Feature → Modul → ADR + +Dadurch werden Fragen möglich wie: +- Welche Tasks betreffen Architekturentscheidung X? +- Welche Module werden in denselben Kontexten erwähnt? +- Welche Wissensbereiche sind schlecht verknüpft? + +Interaction Layer: +Passt denselben Unterbau auf verschiedene Oberflächen an. +Beispiele: +- Onboarding: eher vereinfachter, hochleveliger Kontext +- Engineering Chat: mehr technische Chunks und präzisere Fachdetails +- Intelligence Views: aggregierte Signale und historische Muster + +Kernaussage: +Die Qualität der Antworten hängt davon ab, wie gut die unteren Layer Stabilität und Kontextbildung leisten. + +Technischer Deep Dive: + +Kernidee: +Das LLM arbeitet nicht direkt auf dem gesamten Quellcode, sondern auf abstrahierten Wissensrepräsentationen. + +Impliziter Wissensgraph: +Knoten: +- Task +- ADR +- Modul +- Dokument +- Sprint +- Signal + +Kanten: +- refers_to +- implements +- modifies +- depends_on +- belongs_to + +Beispiel: +Task 21 +- implements → AI coverage dashboard +- depends_on → retrieval pipeline +- refers_to → ADR 7 + +Dieser Kontext kann als strukturierter Text oder in verdichteter Form dem LLM gegeben werden. + +Warum das wichtig ist: +Ein LLM kann Beziehungen sehr gut interpretieren, aber es ist ineffizient und unzuverlässiger, ihm unstrukturierten Vollcode zu geben. +Deshalb ist die Architektur konsequent context first statt model first. + +Verarbeitungsebene im Detail: +- Chunking strukturiert große Dokumente +- Embeddings machen semantische Suche möglich +- Retrieval wählt relevante Ausschnitte +- Signalbildung ergänzt deterministische Metriken +- Anwendungen kombinieren beides in nutzbaren Antworten und Dashboards + +Technischer Deep Dive: + +Das Radar ist ein Modell zur Transformation von Rohsignalen in handlungsrelevante Engineering Intelligence. + +Signal-Kategorien: +1. Struktur-Signale +- Dokumentvernetzung +- ADR-Referenzen +- Task-Beziehungen + +2. Aktivitäts-Signale +- Änderungsfrequenz +- Iterationsanzahl +- Commit-Häufigkeit + +3. Kontext-Signale +- Retrieval-Treffer +- Coverage-Gaps +- Query-Muster + +4. Qualitäts-Signale +- fehlende Kriterien +- widersprüchliche Dokumente +- unklare Verantwortlichkeiten + +Aggregation: +Rohsignale werden normalisiert, damit sie vergleichbar werden. +Beispiel: +iteration_score = iterations / avg_iterations + +Gewichtung: +Aus mehreren Signalen entstehen zusammengesetzte Risikowerte, z. B.: +riskScore = +0.4 * volatility ++ 0.3 * missing_links ++ 0.3 * context_gaps + +Wichtig: +Das LLM muss nicht primär rechnen. Es interpretiert die bereits vorbereiteten Muster semantisch, etwa: +"Module shows elevated change volatility and incomplete traceability." + +Langfristige Rolle: +Das Radar ist nicht nur Berichtswesen, sondern ein frühes Orientierungssystem zur Priorisierung von Architektur-, Doku- und Prozessverbesserungen. + ::: # Layer Icon Semantik @@ -1258,3 +1969,85 @@ Copilot · Intelligence · Retro ![mermaid-engineering-intelligence-radar-visual-radar](files/mermaid-engineering-intelligence-radar-visual-radar.png) :::: ::: + +# Technische Architektur 1 + +## Architekturprinzipien + +- **Context first** statt model first +- **Deterministische Vorverarbeitung** vor semantischer Interpretation +- **Gemeinsame Wissensbasis** für Copilot, Retro, Coverage und Intelligence +- **Beobachtbarkeit** über Retrieval- und Signal-Logging +- **Markdown-first Wissensspeicher** statt isolierter Tool-Silos + +## Sprechpunkte + +- Das LLM ist nur eine Schicht im Gesamtsystem. +- Qualität entsteht hauptsächlich durch Datenstruktur, Retrieval und Signalbildung. +- Eine gute Wissensbasis erzeugt wiederverwendbare KI-Fähigkeiten über mehrere Anwendungsflächen hinweg. + + +# Technische Architektur 2 +::::: columns +:::::: {.column width="45%"} + +## Architektur in einem Satz + +GoodOne kombiniert strukturierte Projektartefakte, semantisches Retrieval, deterministische Signale und LLM-Interpretation zu einer nachvollziehbaren Engineering-Intelligence-Schicht. +:::::: +:::::: {.column width="55%"} + +![mermaid-technische-architektur-2](files/mermaid-technische-architektur-2.png) +:::::: +::::: + + +# GoodOne vs klassisches RAG-System 1 + +| Aspekt | Klassisches RAG | GoodOne | +|---|---|---| +| Wissensbasis | meist Dokumente | Dokumente + Tasks + ADRs + Logs + Sprints + Signale | +| Retrieval | semantische Top-N Suche | semantische Suche + deterministische Anreicherung | +| Kontextmodell | eher dokumentzentriert | projekt- und workflowzentriert | +| Beobachtbarkeit | oft begrenzt | Retrieval Logging, Coverage, Stale/Unused Analyse | +| Auswertung | Q&A-fokussiert | Q&A + Retro + Coverage + Risiko-/Mustererkennung | +| Governance | häufig implizit | Traceability, Struktur-Checks, Verlinkungen | +| Mehrwert | bessere Antworten | bessere Antworten + Systemverständnis + Lernschleife | + + +# GoodOne vs klassisches RAG-System 2 + +## Kernaussage + +GoodOne ist nicht nur ein RAG-Chat über Projekttexte. +Es ist ein Engineering-Intelligence-System, das Retrieval mit Struktur, Historie, Signalbildung und operativer Transparenz kombiniert. + +## Warum das wichtig ist + +Klassisches RAG beantwortet Fragen besser. +GoodOne verbessert zusätzlich: +- Nachvollziehbarkeit +- Priorisierung +- Lernfähigkeit des Systems +- Wiederverwendung von Projektwissen + + +# Datenmodell Diagramm (Entities + Relations) + +:::::: columns +:::::: {.column width="60%"} + +![mermaid-datenmodell-diagramm-entities-relations](files/mermaid-datenmodell-diagramm-entities-relations.png) + +:::::: +:::::: {.column width="40%"} + +## Erläuterung + +Das Modell ist bewusst hybrid: +- strukturierte relationale Entitäten für Governance, Verlinkung und Filterung +- semantische Chunks plus Embeddings für Retrieval +- separate Retrieval Traces für Beobachtbarkeit + +:::::: +:::::: diff --git a/doc-noindex/presentation/intro/goodone-intro.md b/doc-noindex/presentation/intro/goodone-intro.md index b239201d..b3736ecf 100644 --- a/doc-noindex/presentation/intro/goodone-intro.md +++ b/doc-noindex/presentation/intro/goodone-intro.md @@ -25,39 +25,73 @@ Stark KI-gestützte Entwicklung ::: notes -Super spannendes Thema +Willkommen zu super spannendem Thema. Software Entwicklung mit KI Grosses Interesse -Präsentation angepasst. -1. Teil hands-On Präsentation -2. Code Generierung -2. Fragen +Hauptteil Live Demo einer stark KI-unterstützten Applikation. +Beispiel GoodOne.ch. Selbst entwickelt. selbst ausprobieren. +Wie umfassend KI den ganzen Entwicklungsprozess unterstützen kann mit guten KI Tools. +Dies ist Realität. -Eröffnungsfolie. +KI hochgradig integriert +Features wie +Q&A Chat +Retrospective +Sprint Planung +Analysiert Risiko der Implementation -Positionieren Sie dies als praktisches technisches System, nicht als generische KI-Vision-Präsentation. -Das Publikum sollte zwei Dinge erwarten: -1. Beeindruckende Live-Funktionen -2. Eine glaubwürdige Implementierungsgeschichte +Bei Fragen grad melden, oder falls ich Fenster verliere -Vorschlag für den Einstieg: - -Eine Methode zur Softwareentwicklung, bei der das System zunehmend in der Lage ist, -sich selbst zu erklären, zu reflektieren und die Entwickler zu unterstützen.“ +Kommt mit auf die spannende Reise. ::: --- -# Verbesserungsvorschläge zur Lauzeit +# Verbesserungsvorschläge zur Laufzeit ![Das neuste Feature](assets/GoodOneChDetail.png){width=100%} ::: notes +Neustes Feature seit 1 Woche: KI macht Vorschläge zur eigenen Verbesserung + +::: + +--- + +# Agenda Demo + +:::::: columns +:::::: {.column width="50%"} +1. Live-Demo GoodOne.ch. +**Rennstrecke** + +2. Code Generierung mit KI. +**Rennwagen** + +3. Einblicke in die Implementierung + +4. Fragen +:::::: +:::::: {.column width="50%"} +![Rennen](assets/Race3Cars.png){width=100%} +:::::: +:::::: + +::: notes +Je ein Viertel Zeit, Letzte 20 Minuten Diskussion. +T., bitte intervenieren, damit genug Zeit für Fragen + +Alles, was ihr seht, ist KI generiert. Ganzer Prozess hochgradig KI unterstützt +100% Code generiert +Präsentation, alle Diagramme + +Wieso seht ihr Rennwagen? Nächste Slide ::: + --- # GoodOne.ch - Entstehung @@ -70,10 +104,9 @@ Ende 2025 Heute - KI ist ein Rennwagen -- Kontinuierliche Verbesserung durch KI -- 18 Sprints bisher -- Jeder Sprint wird schneller +- 15 Sprints (Runden) bisher - 420 umgesetzte Storys +- Jeder Sprint wird schneller wegen kontinuierlicher Verbesserung durch KI - 1 begeisterter KI-Entwickler KI-getrieben @@ -85,18 +118,25 @@ KI-getrieben ::::: ::: notes +Ich arbeite als SLX Entwickler im Team DevOps Risikosysteme. +Gegen Ende letzten Jahres eine KI Offensive mit 2 Meetings für alle Entwickler +Habe empfohlene KI Tools (Rennwagen) ausprobiert. Etwas entteuscht wieder ausgeschtegen nach wenigen Metern. +Ich kam nicht weiter -„Dies begann als Experiment. +Ende Jahr, technische Neugier gepackt +Privat Lizenz für ein paar KI Tools (Rennwagen) erworben und losgelegt +Unbekanntes Gefährt - reingesetzt und das Gaspedal gesucht +KI intensiv gefragt, was sind die nächsten Schritte +KI erklärte mir dann selbst wie ich den Rennwagen benutze. +Geplant 1 Web Seite KI generiert -Technische Neugier -Unbekanntes Gefährt - 1 Web Applikation -Super size me +Sehr schnell Potential gesehen +Super size me - Prinzip Herausgestellt: Formel 1 Auto -Andere Teilnehmer schnelleres Auto? -ZKB noch viele mit Fahhrad unterwegs +Details - Klassen - Unit Tests @@ -116,12 +156,43 @@ ZKB noch viele mit Fahhrad unterwegs --- +# Das Rennen hat begonnen + +![Rennen](assets/Race3Cars.png){width=100%} + +::: notes + +Kommt mit mir mit auf die Rennstrecke. +Nehmt Platz als Taxigast. +Ihr dürft gerne nachher auch selbst fahren. Source Code öffentlich, registrieren auf GoodOne.ch mit privater Email + +Zur Rennstrecke - Meine Applikation +Es gibt sicher schnellere auf der KI Piste +Spielt keine Rolle. Ich bin fahre knapp unter meinem Limit +um nicht in die Seitenbande zu knallen. +Macht Riesen-Spass +Unter Helm des Fahrers schauen: riesen Smile durch Geschwindigkeitsrausch + +Diskussion am Ende +Intern etwas neblig. +Andere Teilnehmer schnelleres Auto? + +Intern noch viele Kollegen +- kennen Rennwagen nur von aussen +- mit weniger effizienten Rennwagen unterwegs +- mit Fahrrad unterwegs + +Diese Präsentation auch ein Impuls, selbst das Steuer in die Hand zu nehmen. + +::: + +--- + # Herausforderung moderner Softwareentwicklung Typische Herausforderungen: -- fragmentierter Projektkontext -- Architekturwissen verteilt +- Wissen verteilt - inkonsistente Entscheidungen - versteckte Risiken - schwieriges Onboarding @@ -136,10 +207,16 @@ Ergebnis: **GoodOne füllt diese Lücke.** ::: notes +Vor der Demo noch 2 Slides + +Aus der täglichen Erfahrung in unserem Dev Ops Team kann ich folgendes Pain-Points absolut unterschreiben Kernaussage: -„Das Problem ist nicht nur die grössere Menge an Code. Das Problem ist, -dass der Projektkontext die Kapazität des Arbeitsgedächtnisses der Teams übersteigt.“ +Problem: Das Projekt übersteigt das Arbeitsgedächtnisses des Teams.“ + +Applikationen welche ich intern kenne +- fragmentierter Projektkontext +- Architektur Wissen verteilt ::: --- @@ -150,7 +227,7 @@ dass der Projektkontext die Kapazität des Arbeitsgedächtnisses der Teams über :::::: {.column width="50%"} ## Software, die sich selbst erklärt -GoodOne verwandelt Softwareprojekte in Systeme, die: +GoodOne verwandelt Softwareprojekte in Systeme: - Dokumentiert sich selbst - Erklärt Zusammenhänge @@ -163,53 +240,130 @@ GoodOne verwandelt Softwareprojekte in Systeme, die: :::::: :::::: ---- -# Agenda +::: notes -## Live Demo +Bereits Realität. Wenn auch in vielen Teilen erst experimentell. +Projekt wächst extrem schnell. +Staune selbst über Power von KI. +Wende Findings (Rückmeldungen der KI) der Applikation praktisch an. Untersuche gemeldete Risiken. -1. **Live-Demo mit den neuesten Funktionen** -- `/copilot` -- `/intelligence` -- `/retrospective` -- `/admin/ai-coverage` -2. **Wie KI GoodOne durchgängig unterstützt** +::: -3. **Einblicke in die Implementierung** -- Live-Dokumentation +--- + +# Agenda Demo -- Iterationen +1. **Live-Demo mit den neuesten Funktionen** -- KI-Ebenen -4. **Strategisches Fazit** -5. **Technischer Anhang** +User-Feature: +- /tasks + +Generisches KI Framework: +- AI Onboarding Assistant +- /copilot +- /epics +- /intelligence +- /retrospective +- /admin/ai-coverage ::: notes -Machen Sie deutlich, dass die Demo zuerst stattfindet. -Dies ist wichtig, da die Zuhörer den Produktnutzen erleben sollten, bevor sie die Implementierungsdetails kennenlernen. +Endlich geht es los. -Was ich beim Publikum vermitteln möchte -- *ist real* -- *ist sofort nützlich* -- *geht weit über einen -- *verändert Art Weise, wie +Zuerst das basis user feature /taks +User feature je nach Applikation austauschbar -**Zielreaktion:** +Danach KI Framework on top. Wiederverwendbare KI Logik und Features. +Jede der Demo Seite ist die Grundlage für die nächste. +Steigende Komplexität -> „Wow – das ist ein enormer Vorteil. Wir sollten unsere internen KI-Tools unbedingt weiterentwickeln.“ +Aktuell Mismatch, da KI Prototyp +2 % User Feature +98% KI Logik -Dies ist eine Einführungsfolie direkt vor der Live-Demo. +Demo 0 /Onboarding +What is the main user feature of this application +How to Create a New Task -Machen Sie die Erwartungen deutlich. +Demo 00 /Tasks +Finde vergessene Ostereier spätestens am Lunedì di Pasqua. urgente -Es ist auch hilfreich, wenn die Live-Umgebung ein oder zwei Schwächen aufweist: Das Publikum weiß dann bereits, wie es die Demo betrachten soll. +Beispiel für KI zur Laufzeit +Eingabe 2 Teile +herkömmliches Parsing +KI aufgerufen (Open AI) ::: --- + +--- + +# Demo 1a – AI Onboarding Assistant + +::: columns +::: {.column width="48%"} + +## Einstiegspunkt für neue Entwickler + +Der AI Onboarding Assistant erklärt das Projekt verständlich aus High-Level Perspektive. + +Typische Fragen: +- What is the main purpose of this system? +- Which components are most important? +- How is the architecture structured? +- Where should a new developer start? + +Nutzen: +- schneller Einstieg +- konsistentes Projektverständnis +- weniger Abhängigkeit von Einzelpersonen +- reduzierte Einarbeitungszeit + +::: + +::: {.column width="52%"} + +![AI Onboarding Assistant](assets/OnboardingAssistant.png) + +::: +::: + +::: notes +Wie schnell neue Entwickler produktiv werden können. + bewusst weniger technisch als der Copilot. + +Unterschied zum Copilot: +- stärker abstrahierter Kontext +- stärker kuratierte Dokumentbasis +- Fokus auf Verständnis statt Implementierung + +Typischer Kontext für den Prompt: + +System instruction: +"You are an onboarding assistant helping a developer understand a new project." + +Retrieval scope eingeschränkt auf: +- overview docs +- ADR summaries +- feature summaries +- glossary +- architectural diagrams + +Nutzen für Organisation: + +reduziert Abhängigkeit von Schlüsselpersonen +reduziert Wiederholungsfragen +verbessert Konsistenz von Architekturverständnis +macht Projektwissen skalierbar + +Überleitung: +nach Verständnis → aktive Unterstützung durch Copilot. + +::: + # Demo 1 – Copilot ::: columns @@ -217,12 +371,13 @@ Es ist auch hilfreich, wenn die Live-Umgebung ein oder zwei Schwächen aufweist: ## Kontextbasierte Antworten Mögliche Fragen: -- Welche Laufzeitfunktionen nutzen KI? -- Welche Dokumente beschreiben die Architektur? -- Welche ADRs sind am relevantesten? -- Wie sollte sich ein neuer Entwickler im System zurechtfinden? +- Which features use AI at runtime? +- Which documents describe architecture? +- Which ADRs are most important? (Architectural Decision Records) +- How should a new developer be trained? -**Wichtiger Hinweis:** Die Qualität der Antworten hängt vom Projektkontext ab, nicht von allgemeinem Modellwissen. +**Wichtiger Hinweis:** +Die Qualität der Antworten hängt vom Projektkontext ab, nicht von allgemeinem Modellwissen. ::: ::: {.column width="52%"} @@ -231,18 +386,162 @@ Mögliche Fragen: ::: ::: notes -Verwenden Sie eine vorbereitete Frage, die Architekturverständnis zeigt. +Im Hintergrund +sucht interne Projektdokumentation +KI Prompt erzeugt +Dokumentation an KI Prompt mitgegeben +Resultat der KI Abfrage geparsed + +- Wichtig ist, dass KI mit Wissen aus unserer Projektdokumentation antwortet.“ +Nicht KI Wissen unbekannter Herkunft +Keine Halluzinationen +Immer Dokument-Referenz zur Kontrolle + +3 Gruppen +- Architecture Q&A +- Engineering Chat +- Onboarding Help + +Implementation jedesmal dasselbe, +jedoch andere Projektdokumente dem Prompt mitgegeben +andere Persona verwendet + +**** + +a) Architecture +show ADR links + +**** + +b) Engineering versteht Code + Kontext? +- Task-Dokumente: + - Ziel + - Akzeptanzkriterien + - Implementierungs-Logs + - Iterationen + +- technische Dokumentation: + - relevante Code-nahe Beschreibungen + - ggf. API-Strukturen + +- optional: + - Fehlerlogs + - Test-Notizen + +Die KI sieht NICHT den gesamten Code. +Sondern: +→ abstrahierte, strukturierte Repräsentationen + +Warum? + +- Token-Limits +- Performance +- Fokus + +Typischer Prompt-Aufbau: + +1. System Instruction: + „Du bist ein Engineering Assistant…“ + +2. Kontext: +- relevante Tasks (Top-N via Embedding) +- technische Dokumente + +3. User-Frage + +Die KI kann: +- Features erkennen +- Zusammenhänge verstehen +- Risiken ableiten + +****** + +c) Onboarding erklärt Basics +Hier ist der Kontext bewusst anders gewählt. + +Die KI bekommt: +- High-Level Architektur-Dokumente +- vereinfachte Beschreibungen +- Use Cases +- ggf. Glossar / Begriffsdefinitionen + +Keine Low-Level Details. +- Zielgruppe: neue Entwickler +- Fokus: Verständnis, nicht Implementierung + +Prompt ist typischerweise: +„Erkläre verständlich…“ +„Vermeide zu technische Details…“ + +Das führt zu: +- einfacheren Antworten +- weniger Fachjargon +- klarer Struktur -Optimaler Effekt: -- Fragen zu Laufzeit-KI-Funktionen stellen -- zeigen, dass die Antwort auf ADRs und interne Konzepte verweist -Botschaft: -„Wichtig ist nicht, dass ein LLM antworten kann. Wichtig ist, dass er aus unserem Systemspeicher antwortet.“ ::: --- + +--- + +# Demo 2a – AI Project Roadmap + +::: columns +::: {.column width="48%"} + +## Strukturierte Projektentwicklung mit KI + +Die Roadmap zeigt, wie sich Features über Iterationen entwickeln. + +KI hilft bei: +- Strukturierung von Epics +- Ableitung von Tasks +- Priorisierung von Themen +- Erkennen von Abhängigkeiten +- Fortschrittsanalyse + +Die Projektstruktur wird selbst zum Wissensartefakt. + +::: + +::: {.column width="52%"} + +![AI Project Roadmap](assets/Epics22Crop.png) + +::: +::: + +::: notes +Planung und wichtigen Teil der Wissensbasis. +Epic → Tasks → Implementierung → Signale → Intelligence + +Epics helfen der KI zu verstehen: +- welche Themen zusammengehören +- welche Komponenten gemeinsam verändert werden +- welche Bereiche stark evolvieren +- wo potenziell Instabilität entsteht + +Epics sind mittlere Abstraktionsebene: +nicht Vision, nicht Detail-Task, +sondern strukturierter Kontext für reasoning. + +Beziehung zu Engineering Intelligence: +Engineering Intelligence benötigt strukturierte Historie. + +Ohne Epics: +isolierte Tasks + +Mit Epics: +semantische Entwicklungslinie. + +Überleitung: +von Struktur → Mustererkennung. + +::: + # Demo 2 – Engineering Intelligence ::: columns @@ -257,9 +556,8 @@ Botschaft: - Unterstützt Priorisierung **Wichtiger Hinweis:** -Dies ist kein Dashboard mit Rohdaten. - -Es ist eine Analyseebene. +Dies ist kein Dashboard mit Rohdaten. +Es ist eine Analyse. ::: ::: {.column width="54%"} @@ -268,11 +566,71 @@ Es ist eine Analyseebene. ::: ::: notes -Betonen Sie den Unterschied zwischen Überwachung und Verständnis. -Überwachung zeigt Ihnen, was passiert ist. -Diese Ebene hilft Ihnen, abzuleiten, was Aufmerksamkeit erfordert. -Öffnen Sie nach Möglichkeit eine Beispielkarte und erläutern Sie, -warum das System sie als hohes Risiko einstuft. +Das ist der erste Punkt, wo KI wirklich Richtung „Denken“ geht. +Keine Überwachung, sondern Verständnis + +1. Was passiert hier grundsätzlich? +Die KI beantwortet nicht einfach eine Frage. +Sie macht intern 3 Dinge: + +1. Informationen sammeln +2. Beziehungen herstellen +3. Auswirkungen bewerten + +Das ist ein qualitativer Unterschied. + +2. Datenquellen +Die Antwort basiert typischerweise auf: +- Architektur-Dokumente (ADRs) +- Tasks (inkl. Historie) +- Feature-Beschreibungen +- ggf. Logs + +4. Prompt +- relevante Text-Chunks +- Struktur (z.B. „liste Module auf“) +- Instruktionen („nennen Sie Risiken“) + +5. Die KI: +- extrahiert Entitäten (Features, Module) +- erkennt Beziehungen (Abhängigkeiten) +- leitet Risiken ab + +Das ist KEIN klassischer Algorithmus. +Das ist semantisches Reasoning. + +6. Warum ist das schwer ohne KI? +Weil: +- Informationen verteilt sind +- Beziehungen nicht explizit modelliert sind +- Kontext ständig wechselt + +Ein klassisches System müsste: +→ vollständigen Dependency Graph haben + +KI kann: +→ implizite Beziehungen erkennen + +7. Wo liegt die Grenze? +KI kann: +✔ Zusammenhänge erkennen +✔ Risiken abschätzen + +KI kann NICHT: +✖ garantieren, dass alles korrekt ist +✖ vollständige Abhängigkeiten kennen + +8. Wichtigstes mentales Modell +„Die KI baut on-the-fly ein mentales Modell des Systems.“ +Nicht perfekt. +Aber oft ausreichend gut, um bessere Entscheidungen zu treffen. + +9. Warum das ein Game Changer ist +Vorher: +→ Entwickler muss alles selbst zusammensuchen +Jetzt: +→ KI liefert eine erste, strukturierte Sicht +Das spart massiv Zeit. ::: @@ -299,13 +657,76 @@ warum das System sie als hohes Risiko einstuft. ::: ::: notes -Ein wichtiger Satz: - „Dies ersetzt nicht die Diskussion. Es verbessert die Ausgangsbasis der Diskussion.“ Erwähnen Sie, dass das System Muster aus Aufgaben und Protokollen synthetisieren kann, die Menschen unter Zeitdruck nicht manuell erfassen würden. +Retrospektiven werden oft durch Erinnerung und subjektive Wahrnehmung dominiert. +GoodOne analysiert automatisch Task-Historien, Iterationsmuster und Implementierungslogs. + +Die KI erkennt: +- wiederkehrende Probleme +- Iterationsschleifen +- fehlende Akzeptanzkriterien +- Hotspots im Code + +Retrospektiven werden datenbasiert statt rein subjektiv. + +Technischer Deep Dive: + +Datenquellen: +- strukturierte Tasks mit Ziel, Akzeptanzkriterien, Status und Verlinkungen +- Iterationshistorie je Task +- Logs und Änderungsverläufe +- Sprintzuordnung und zeitliche Entwicklung +- optional Test- und Verifikationshinweise + +Interne Repräsentation: +Eine Aufgabe ist nicht nur Markdown-Text, sondern wird logisch als Wissenseinheit behandelt: +- id +- title +- description +- acceptanceCriteria[] +- implementationLog[] +- relatedTasks[] +- sprintId +- iterationCount +- statusHistory[] +- embeddings[] + +Signalbildung: +Vor der KI-Interpretation werden deterministische Signale abgeleitet: +- hohe Iterationszahl → Unsicherheit, Scope Drift oder fehlende Präzision +- mehrfach geänderte Akzeptanzkriterien → Ziel unklar oder nachträglich geschärft +- Task ohne Verknüpfung zu ADRs oder anderen Tasks → isoliertes Wissen +- Testartefakte erst spät → potenziell schwache frühe Absicherung + +Warum diese Vorverarbeitung wichtig ist: +Die Retrospektive sollte nicht auf Rohtexten beruhen. Zuerst werden Signale extrahiert, aggregiert und komprimiert. Erst dann wird ein LLM verwendet, um Muster und Verbesserungsvorschläge zu formulieren. + +Typischer Prompt-Aufbau: +Systemrolle: +"You are an engineering retrospective assistant." + +Kontext: +- Sprintkennung +- Task-Anzahl +- aggregierte Signale +- auffällige Komponenten +- wiederkehrende Änderungsmuster + +Instruktion: +- erkenne Muster +- fasse Erfolge und Probleme zusammen +- mache konkrete Verbesserungsvorschläge + +Nutzen dieser Architektur: +- weniger Tokenverbrauch +- stabilere und reproduzierbarere Antworten +- klarere Trennung von Fakten und Interpretation +- besser erklärbare Retro-Ergebnisse + ::: --- @@ -317,10 +738,10 @@ die Menschen unter Zeitdruck nicht manuell erfassen würden. ## Transparenz darüber, was die KI tatsächlich versteht Warum das wichtig ist: -- Wir können die Wissensabdeckung überprüfen. -- Wir können blinde Flecken identifizieren. -- Wir können die Kontextqualität gezielt verbessern. -- Wir können die KI-Unterstützung nachvollziehbar machen. +- Wissensabdeckung überprüfen. +- blinde Flecken identifizieren. +- Kontextqualität gezielt verbessern. +- KI-Unterstützung nachvollziehbar machen. **KI wird nachvollziehbar, nicht mysteriös.** ::::::: @@ -330,18 +751,159 @@ Warum das wichtig ist: ::::::: ::: notes -Falls der Live-Bildschirm verfügbar ist, zeigen Sie die Seite. -Andernfalls erläutern Sie das Konzept kurz. -Diese Folie ist wichtig für das Vertrauen. -Viele Menschen akzeptieren KI, wenn sie nützlich ist, -aber sie vertrauen ihr mehr, wenn sie nachvollziehen können, -woher ihr Verständnis stammt. + +Diese Folie zeigt, was die KI tatsächlich weiss. +Wichtige Kennzahlen: +- Stale Documents → potenziell veraltetes Wissen +- Recently Used → stark genutzter Kontext +- Unvisited Branches → mögliche Wissenslücken + +Die Qualität der KI hängt stark von strukturierten Projektartefakten ab. +Prompt Engineering wird zu Knowledge Engineering. + +Technischer Deep Dive: + +Ziel der Coverage-Analyse: +Nicht nur zeigen, welche Dokumente existieren, sondern welche Dokumente bei realen KI-Abfragen tatsächlich im Kontext landen. + +Retrieval Logging: +Jede KI-Anfrage erzeugt Metadaten wie: +- query +- embedding vector +- retrieved documents +- similarity score +- chunk id +- timestamp +- prompt type +- feature + +Dadurch lassen sich Coverage-Kennzahlen berechnen: +- retrieval frequency: wie oft ein Dokument in Top-N Treffern erscheint +- stale documents: lange nicht verwendete Dokumente +- unused documents: nie verwendete Dokumente +- branch coverage: Nutzung nach Dokumentpfad oder Wissensdomäne + +Typische Ursachen für schwache Abdeckung: +- semantische Lücke zwischen Dokumentsprache und Nutzerfragen +- zu grobes oder zu feines Chunking +- schlechte Überschriften oder unklare Struktur +- Dokumente sind zwar vorhanden, aber nicht in reale Workflows eingebunden + +Chunking-Strategie: +Typisch werden Markdown-Dokumente in strukturierte Chunks überführt: +- path +- heading +- text +- embedding + +Bei einer Anfrage läuft technisch: +query → embedding → similarity search → top N chunks → Prompt-Erstellung → LLM + +Wichtige Erkenntnis: +Coverage ist keine reine Doku-Metrik. +Coverage ist eine operative Qualitätsmetrik für KI-Nutzbarkeit. + + +::: + +--- + + +--- + +# Demo 5 – ADR Drift + +::: columns +::: {.column width="46%"} + +## Abweichungen zwischen Architektur und Implementierung erkennen + +ADR Drift zeigt, wo Implementierung und Architekturentscheidungen auseinanderlaufen. + +KI unterstützt bei: + +- Identifikation betroffener ADRs +- Erkennen inkonsistenter Implementierungen +- Sichtbarmachen impliziter Architekturänderungen +- Priorisierung von Architektur-Review Bedarf +- Verbesserung langfristiger Systemstabilität + +**Architektur bleibt ein lebendes Artefakt.** + +::: + +::: {.column width="54%"} + +![ADR Drift](assets/AdrDrift2.png) + +::: +::: + +::: notes + +ADR Drift adressiert ein klassisches Problem: +Architekturentscheidungen werden getroffen, +aber später stillschweigend verändert. + +Nutzen: +frühe Sichtbarkeit von Architekturdrift +bessere Entscheidungsgrundlagen +reduzierter Refactoring-Aufwand + +Überleitung: +von Drift → Risiko. ::: + --- -# Erste Erkenntnisse aus der Demo +# Demo 6 – Risk Radar + +::: columns +::: {.column width="46%"} + +## Früherkennung von Risiken im Projektkontext + +Risk Radar aggregiert schwache Signale zu handlungsrelevanten Hinweisen. + +KI erkennt: + +- Instabilitätsmuster +- Komplexitätsanstieg +- Kontextlücken +- fehlende Traceability +- potenzielle Architekturprobleme + +Das Radar hilft bei Priorisierung technischer Verbesserungen. + +**Risiken werden sichtbar, bevor sie kritisch werden.** + +::: + +::: {.column width="54%"} + +![Risk Radar](assets/RiskRadar.png) + +::: +::: + +::: notes + +Risk Radar kombiniert mehrere schwache Signale zu einem Gesamtbild. + +Nutzen: + +frühzeitige Identifikation technischer Risiken +bessere Priorisierung von Refactoring +höhere Systemstabilität über Zeit + +Schliesst den Kreis: +Signale → Intelligence → Entscheidungen. + +::: + +# Erkenntnisse aus der Demo ## GoodOne ist keine nachträglich hinzugefügte KI @@ -353,27 +915,24 @@ Was in der Demo sichtbar wird: **Systemverständnis wächst kontinuierlich.** ::: notes -Dies ist die Brücke von der Demo zur Implementierung. -Es sei explizit darauf hingewiesen, -dass der Wow-Effekt nicht durch einen einzelnen Modellaufruf hervorgerufen wird. -Er entsteht durch Architektur, Workflow und Wissensdesign. +Brücke von der Demo zur Implementierung. ::: --- -# Wie KI GoodOne unterstützt +# Produkt-Iteration / Sprint :::::: columns :::::: {.column width="50%"} -Durchgängig, nicht nur zur Laufzeit KI ist im gesamten Lebenszyklus präsent. -- **Dev + AI**: Zieldefinition -- **Sprint & Tasks**: Planung +- **Iterations-Ziel**: Dev + Chat GPT +- **Sprint & Storys**: Planung durch Chat GPT - **Implementierung**: Junie AI -- **Dokumentation**: Automatisch -- **Review**: Tests + Checks +- **Dokumentation**: Automatisch Junie AI +- **Review**: Tests + Checks. Dev und beide KIs + Daher steigert das System seinen Wert im Laufe der Zeit. :::::: :::::: {.column width="50%"} @@ -382,53 +941,27 @@ Daher steigert das System seinen Wert im Laufe der Zeit. :::::: ::: notes - -Erläutern Sie, dass GoodOne KI in vier verschiedenen Phasen einsetzt: +Tägliche Arbeit mit KI. Schritte wie bei der normalen Entwicklung. +Neu: viele Teilschritte intensiv mit KI unterstützt Strukturierter Prozess statt „Prompt → Code“. - - Ziel zuerst, nicht Lösung -- Tasks mit Akzeptanzkriterien +- Storys mit Akzeptanzkriterien - KI implementiert iterativ - Dokumentation entsteht automatisch - Mensch bleibt Entscheider -::: - ---- - -# Das Rennen läuft - -![Rennen](assets/Race3Cars.png){width=100%} - - ---- +Meiste Zeit für DEV bei Tests (grün) -# Meine Rennwagen +Teilschritte als nächstes durchgegangen -:::::: columns -:::::: {.column width="50%"} -![KI 1: ChatGPT](assets/RaceCar1ChatGpt.png) -:::::: -:::::: {.column width="50%"} -![KI 2: Junie AI](assets/SprintStart.png) -:::::: -:::::: - -::: notes -Sprint Planung im Dialog mit Chat GPT -Story erstellt durch Chat GPT - -Umsetzung mit Junie AI -1 Sprint ::: --- - # Sprintplanung und Aufgabengenerierung -## ChatGPT strukturieren die Arbeit vor dem Programmieren +## ChatGPT strukturiert die Arbeit vor dem Programmieren KI-Unterstützung in der Planung: @@ -441,14 +974,18 @@ KI-Unterstützung in der Planung: **Die Planung wird schneller und strukturierter.** ::: notes -Beachten Sie, dass es hier nicht darum geht, das Produkt-Denken zu ersetzen. +Aufwand reduzieren, +Viel bessere Prompts und Akzaptanzkritieren durch Chat GPT als von hand +Klar, könnte man Story selbst schreiben -Es geht darum, den Aufwand zu reduzieren, -Absichten in strukturierte Entwicklungsarbeit umzusetzen. -Mögliche Formulierung: „Viele Projektprobleme entstehen durch unpräzise formulierte Absichten. KI hilft uns, mit einem besseren Vertrag zu starten.“ +Beispiel Ziel Sprint 2.2: +Unbenutzte Dokumentation erkennen. +- Prompts loggen +- UI Seite der referenzierten Dokumentation +- ::: --- @@ -473,17 +1010,35 @@ Der Entwickler entscheidet weiterhin: - Freigabe bleibt menschlich ::: notes -Wichtige Nuancenfolie. -Dies ist keine Beschreibung von automatisiertem Code. -Die Kernaussage lautet: KI steigert Durchsatz und Konsistenz, +KI steigert Durchsatz und Konsistenz, während der Entwickler die Verantwortung behält. ::: --- -# Vollständige Iteration auf einen Schlag +# Meine Rennwagen + +:::::: columns +:::::: {.column width="50%"} +![KI 1: ChatGPT](assets/RaceCar1ChatGpt.png) +:::::: +:::::: {.column width="50%"} +![KI 2: Junie AI](assets/SprintStart.png) +:::::: +:::::: + +::: notes +Sprint Ziel und Planung im Dialog mit Chat GPT +Chat GPT erstellt alle Storys + +Umsetzung mit Junie AI +Alle Storys Junie AI übergeben +::: + +--- +# Vollständige Iteration implementiert auf einen Schlag :::::: columns :::::: {.column width="50%"} @@ -520,8 +1075,6 @@ Eine Aufgabe ist mehr als ein Ticket. Es kann Folgendes enthalten: **Dokumentation ist nicht länger von der Auslieferung getrennt.** ::: notes -Diese Folie ist entscheidend, da sie erklärt, -warum die spätere KI-Unterstützung funktioniert. Ohne strukturierte Aufgabenverwaltung hätte die Laufzeit-KI eine deutlich schwächere Grundlage. ::: @@ -559,9 +1112,7 @@ Idea --> Task --> Code --> Runtime --> Intel --> Next ::: notes -Verwenden Sie den deutschen Titel, da er direkt mit dem Material der vierten Iteration verknüpft ist. - -Betonen Sie, dass der Kreislauf keine lineare Wissensvermittlung, sondern kumulatives Lernen darstellt. +Der Kreislauf keine lineare Wissensvermittlung, sondern kumulatives Lernen darstellt. ::: @@ -573,7 +1124,7 @@ Betonen Sie, dass der Kreislauf keine lineare Wissensvermittlung, sondern kumula GoodOne kann zur Laufzeit: -- Interpretiert Laufzeitsignale +- Interpretiert Laufzeitsignale (KI Prompt-Resultate) - Beantwortet Entwicklungsfragen - Fasst Iterationen zusammen - Erkennt Instabilitätsmuster @@ -633,9 +1184,60 @@ D --> E["Copilot · Intelligence · Retrospektive · Abdeckung"]:::intel ::: notes -Dies ist die gewünschte Übersichtsversion der Folie zu den KI-Ebenen. -Bitte halten Sie es hier auf einem allgemeinen Niveau. -Detailliertere technische Informationen finden Sie im Anhang. +Übersichtsversion der Folie zu den KI-Ebenen. + +Technischer Deep Dive: + +Diese Folie beschreibt die logische End-to-End-Pipeline. + +Layer 1 – Projektspeicher: +Persistente Wissensbasis, typischerweise auf relationalen Daten + Vektorindex aufgebaut. +Mögliche Domänen: +- documents +- tasks +- adrs +- signals +- retrieval_logs +- embeddings + +Markdown ist als Quellformat stark, weil es: +- diffbar +- versionierbar +- LLM-freundlich +- gut strukturierbar ist + +Layer 2 – Verarbeitung: +Mehrere spezialisierte Pipelines laufen parallel: + +Ingestion Pipeline: +Markdown oder Task-Inhalt wird zerlegt: +markdown → chunks → embeddings → store + +Retrieval Pipeline: +Nutzerfrage wird eingebettet: +query → embedding → similarity search → top N chunks + +Signal Pipeline: +Projektartefakte werden in strukturierte Indikatoren übersetzt: +events → features → signals + +Beispiele für Events: +- task updated +- file changed +- dependency changed +- test added + +Layer 3 – Engineering Intelligence: +Dieser Layer nutzt das LLM nicht primär für Fakten, sondern für Interpretation. +Beispiel: +- Modul A wurde 8-mal geändert +- Modul B nur 1-mal +- ADR-Referenzen sind inkonsistent +Das LLM erkennt daraus Instabilitäts- oder Kontextmuster. + +Layer 4 – AI-Anwendungen: +Copilot, Retro, Coverage und Intelligence nutzen dieselbe Infrastruktur. +Das ist wichtig, weil die sichtbaren Funktionen nicht isoliert sind, sondern auf derselben Wissens- und Verarbeitungsschicht beruhen. ::: @@ -657,12 +1259,6 @@ Die KI kann auf Folgendes zurückgreifen: **Das Modell ist wichtig. Die Systemdaten sind entscheidend.** ::: notes -Verwenden Sie die Formulierung, die sich die Zuhörer merken sollen: - -„Das Modell ist wichtig. Die Systemdaten sind entscheidend.“ - -Dies lenkt die Diskussion weg vom Hype um das Modell -und hin zu internen Werkzeugen und der Qualität des Wissens. ::: @@ -681,13 +1277,6 @@ Intelligence-Ansichten erhalten historischen und analytischen Kontext **Gleiches Modell, unterschiedlicher Kontext, unterschiedliche Qualität.** ::: notes -Dies ist eine sehr wichtige Erklärungsfolie. -Die Zuhörer sollten verstehen, dass die Qualität der Antworten gezielt gestaltet wird. -Es ist keine Zauberei. - -Möglicher Satz: - -„Der Trick ist nicht ein intelligenteres Modell pro Bildschirm. Der Trick ist der richtige Kontext für die richtige Frage.“ ::: @@ -724,13 +1313,42 @@ D --> E["Risikokarten, Rückblicke, Antworten, Vorschläge"]:::ui ::: notes -Erläutern Sie das Designprinzip klar: - Deterministische Logik liefert feste Ankerpunkte - Das LLM liefert semantische Interpretation -- Zusammen erzielen sie bessere Ergebnisse als jede für sich +- Zusammen erzielen sie bessere Ergebnisse -Dies hilft skeptischen technischen Zuhörern. +Technischer Deep Dive: + +Deterministische Komponente: +Klassische Logik erzeugt überprüfbare Signale. +Beispiele: +- Drift-Regel: Implementierung widerspricht ADR +- Volatilität: Änderungen pro Modul und Zeitfenster überschreiten Schwellwert +- Traceability-Lücke: Task ohne Verlinkung zu Architektur oder verwandten Artefakten + +LLM-Komponente: +Das LLM interpretiert nicht den ganzen Code, sondern verdichtete Signale und relevante Kontext-Chunks: +- Welche Muster sind erkennbar? +- Welche Risiken erscheinen plausibel? +- Welche Priorität hat ein Thema? + +Beispiel: +Signale: +- hohe Iterationszahl +- fehlende Akzeptanzkriterien +- wiederholte Änderungen im selben Modul + +Interpretation: +"possible architectural uncertainty" oder "scope instability" + +Warum hybrid? +- Nur Regeln: zu viele False Positives, wenig semantisches Verständnis +- Nur KI: weniger reproduzierbar, schwerer zu verankern +- Kombination: robuste, erklärbare Resultate mit semantischer Tiefe + +Wichtiger Architekturpunkt: +Das LLM steht nicht am Anfang, sondern am Ende einer Fakten- und Signalverarbeitungskette. ::: @@ -750,10 +1368,7 @@ Direkte Vorteile für Teams: - Bessere Retrospektiven und Reviews ::: notes -Richten Sie die Diskussion wieder auf den Nutzen für den Menschen. -Auch wenn die Technologie beim Publikum gut ankommt, -liegt der eigentliche Investitionsgrund in der verbesserten Nutzung -der Engineering-Ressourcen. + ::: --- @@ -772,9 +1387,6 @@ GoodOne wurde durch Iterationen verbessert: **Diese Fähigkeit entstand durch iterative Vorgehensweise.** ::: notes -Beziehen Sie sich auf die vorherigen Iterationspräsentationen. -Die Botschaft lautet: Dies war kein einmaliger Erfolg. -Er war das Ergebnis wiederholter Systemdesignverbesserungen. ::: @@ -797,10 +1409,8 @@ Sie sind Wissensinfrastruktur.** ::: notes -Dies ist eine der stärksten strategischen Aussagen in der Präsentation. -Sprechen Sie sie langsam aus. - -Der Begriff „Wissensinfrastruktur“ muss verinnerlicht werden. +Dies ist eine der stärksten strategischen Aussagen in der Präsentation. +Der Begriff „Wissensinfrastruktur“ muss verinnerlicht werden.` ::: --- @@ -820,18 +1430,15 @@ Mehr investieren in: **GoodOne zeigt, dass sich die Investition enorm auszahlen kann.** ::: notes -Dies ist die vom Nutzer gewünschte Handlungsaufforderung. Die Personalaufstockung sollte sorgfältig, aber deutlich formuliert werden: -Sinnvolle Fähigkeiten erfordern echte Verantwortung, -nicht nur die Energie von Nebenprojekten. - +Sinnvolle Fähigkeiten erfordern echte Verantwortung, ::: --- # App testen -## Der nächste Schritt ist die direkte Nutzung von GoodOne.ch +## Direkte Nutzung von GoodOne.ch Vorgeschlagene Vorgehensweise: @@ -840,11 +1447,9 @@ Vorgeschlagene Vorgehensweise: 3. Vergleiche die Ergebnisse der Retrospektive mit den Daten des Sprints. 4. Überprüfe die KI-Abdeckung und mögliche Schwachstellen. -**Die Notwendigkeit des Ausprobierens wird deutlich, sobald Sie die Systemlogik in Ihrem eigenen Kontext beobachten.** +Probiert es aus ::: notes -Schließen Sie die Hauptaussage mit einem positiven Ausblick ab. - Ziel ist es, Bewunderung in konkretes Handeln umzuwandeln. ::: @@ -854,18 +1459,19 @@ Ziel ist es, Bewunderung in konkretes Handeln umzuwandeln. # Roadmap ## Natürliche nächste Schritte für GoodOne -- Interne Cloud-Migration prüfen -- Stärkere Abdeckungsmetriken -- Besseres Retrieval und Chunking -- Umfassendere Laufzeitsignale -- Architekturvalidierung ausbauen +- Migration auf Firmen-interne Cloud prüfen +- Sprint 2.3 gemäss Demo + - Stärkere Abdeckungsmetriken + - Besseres Retrieval und Chunking + - Umfassendere Laufzeitsignale + - Architekturvalidierung ausbauen + - Bessere Recovery und Empfehlungen - Spezialisierte Copiloten ::: notes -Der aktuelle Stand bereits wertvoll ist, -aber erst eine frühe Version dessen darstellt, -was diese Systemkategorie werden kann. +Der aktuelle Stand bereits wertvoll, +aber erst eine frühe Version. ::: --- @@ -893,9 +1499,7 @@ Mögliche Diskussionsanregungen: - Wie sollten wir diese Kompetenz personell und organisatorisch gestalten? ::: notes -Hier pausieren für Fragen und Antworten. -Bei Zeitmangel können Sie direkt zu den Folien im Anhang springen, -die zu den Fragen passen. + ::: @@ -915,7 +1519,6 @@ die zu den Fragen passen. - Roadmap und Einschränkungen ::: notes -Der Anhang dient als Backup und für weiterführende technische Fragen. ::: @@ -978,12 +1581,11 @@ A --> G["Ergebnis und Nachbereitung"]:::ui ::: ::: notes -Dies ist die Antwort auf die Frage: -„Was genau verstehen Sie unter lebendiger Dokumentation?“ +lebendiger Dokumentation? -Erklären Sie, dass Aufgaben funktionieren, -weil sie eng mit der Entwicklungsarbeit verknüpft sind -und daher eher aktuell bleiben als separate Dokumentationen. +Aufgaben funktionieren, weil +eng mit Entwicklungsarbeit verknüpft +aktuell bleiben ::: @@ -1019,10 +1621,13 @@ F --> G["LLM-Antwort"]:::intel ::: notes -Dies ist die wichtigste technische Erklärung für RAG. -Erwähnen Sie, dass die Chunking-Qualität, -die Retrieval-Strategie und die Prompt-Disziplin oft wichtiger sind -als das Umschalten zwischen ähnlichen Modellvarianten. +Wichtig +Chunking-Qualität +Retrieval-Strategie +Prompt-Disziplin oft wichtiger + +Weniger wichtig +Umschalten Modellvarianten. ::: @@ -1040,7 +1645,7 @@ als das Umschalten zwischen ähnlichen Modellvarianten. | Intelligenz | Aufgabenverlauf, Signale, Metriken | Muster erkennen | ::: notes -Gute Antwort auf die Frage: „Warum nicht nur einen Chat?“ +Warum nicht nur einen Chat? Weil unterschiedliche Aufgaben unterschiedliche Grundlagen, Tonalitäten und Abstraktionsebenen erfordern. @@ -1081,11 +1686,10 @@ Signals --> AI --> Insights ::: ::: notes -Erläutern Sie, dass schwache Signale erst dann nützlich werden, -wenn sie aggregiert und gemeinsam interpretiert werden. +schwache Signale erst dann nützlich, +wenn aggregiert und gemeinsam interpretiert. Beispiele: - - wiederholte Nacharbeit an derselben Komponente - fehlende Akzeptanzkriterien - unvollständige Verifizierung @@ -1115,10 +1719,6 @@ Anwendungsfälle: ::: notes -Falls Fragen zur Architektur-Governance gestellt werden, -ist dies eine hilfreiche Zusatzfolie. -Wichtiger Hinweis: KI kann Abweichungen und Inkonsistenzen aufzeigen; -die Validierung und Entscheidung erfolgt weiterhin durch Menschen. ::: --- @@ -1138,8 +1738,7 @@ die Validierung und Entscheidung erfolgt weiterhin durch Menschen. ::: ::: notes -Dies ist hilfreich, wenn die Zuhörer verstehen möchten, -wie die Planungshistorie in die spätere Analyse einfließt. +Wie die Planungshistorie in die spätere Analyse einfließt. ::: @@ -1159,8 +1758,6 @@ Fragen zur Abdeckung: **Gute KI-Unterstützung wird steuerbar, wenn die Abdeckung sichtbar ist.** ::: notes -Diese Folie unterstreicht, dass vertrauenswürdige KI-Systeme überprüfbare Systeme sind. -Gut für skeptische Manager und Architekten. ::: @@ -1186,8 +1783,7 @@ KI kann nicht garantieren: **Der Entwickler bleibt der Entscheidungsträger.** ::: notes -Fügen Sie diese Folie immer ein, -wenn die Diskussion in übertriebene Erwartungen abzudriften droht. +Wenn die Diskussion in übertriebene Erwartungen abzudriften droht. Sie erhöht die Glaubwürdigkeit. ::: @@ -1443,6 +2039,121 @@ Intelligence --> Apps ::: notes Radar ist direkte Ableitung des 4-Layer Modells. Zeigt wie Projektsignale zu Engineering Intelligence transformiert werden. + +Technischer Deep Dive: + +Stability Layer: +Sichert die strukturelle Qualität der Wissensbasis. +Beispiele: +- Referenzintegrität: verlinkte ADRs existieren wirklich +- Schema-Validierung: Task enthält Ziel, Kriterien, Status +- Vollständigkeit: Dokumente haben sinnvolle Überschriften und Struktur +- Konsistenzprüfungen: erwartete Felder und Beziehungen sind vorhanden + +Understanding Layer: +Baut semantische Beziehungen auf. +Typische Graphlogik: +Task → Feature → Modul → ADR + +Dadurch werden Fragen möglich wie: +- Welche Tasks betreffen Architekturentscheidung X? +- Welche Module werden in denselben Kontexten erwähnt? +- Welche Wissensbereiche sind schlecht verknüpft? + +Interaction Layer: +Passt denselben Unterbau auf verschiedene Oberflächen an. +Beispiele: +- Onboarding: eher vereinfachter, hochleveliger Kontext +- Engineering Chat: mehr technische Chunks und präzisere Fachdetails +- Intelligence Views: aggregierte Signale und historische Muster + +Kernaussage: +Die Qualität der Antworten hängt davon ab, wie gut die unteren Layer Stabilität und Kontextbildung leisten. + +Technischer Deep Dive: + +Kernidee: +Das LLM arbeitet nicht direkt auf dem gesamten Quellcode, sondern auf abstrahierten Wissensrepräsentationen. + +Impliziter Wissensgraph: +Knoten: +- Task +- ADR +- Modul +- Dokument +- Sprint +- Signal + +Kanten: +- refers_to +- implements +- modifies +- depends_on +- belongs_to + +Beispiel: +Task 21 +- implements → AI coverage dashboard +- depends_on → retrieval pipeline +- refers_to → ADR 7 + +Dieser Kontext kann als strukturierter Text oder in verdichteter Form dem LLM gegeben werden. + +Warum das wichtig ist: +Ein LLM kann Beziehungen sehr gut interpretieren, aber es ist ineffizient und unzuverlässiger, ihm unstrukturierten Vollcode zu geben. +Deshalb ist die Architektur konsequent context first statt model first. + +Verarbeitungsebene im Detail: +- Chunking strukturiert große Dokumente +- Embeddings machen semantische Suche möglich +- Retrieval wählt relevante Ausschnitte +- Signalbildung ergänzt deterministische Metriken +- Anwendungen kombinieren beides in nutzbaren Antworten und Dashboards + +Technischer Deep Dive: + +Das Radar ist ein Modell zur Transformation von Rohsignalen in handlungsrelevante Engineering Intelligence. + +Signal-Kategorien: +1. Struktur-Signale +- Dokumentvernetzung +- ADR-Referenzen +- Task-Beziehungen + +2. Aktivitäts-Signale +- Änderungsfrequenz +- Iterationsanzahl +- Commit-Häufigkeit + +3. Kontext-Signale +- Retrieval-Treffer +- Coverage-Gaps +- Query-Muster + +4. Qualitäts-Signale +- fehlende Kriterien +- widersprüchliche Dokumente +- unklare Verantwortlichkeiten + +Aggregation: +Rohsignale werden normalisiert, damit sie vergleichbar werden. +Beispiel: +iteration_score = iterations / avg_iterations + +Gewichtung: +Aus mehreren Signalen entstehen zusammengesetzte Risikowerte, z. B.: +riskScore = +0.4 * volatility ++ 0.3 * missing_links ++ 0.3 * context_gaps + +Wichtig: +Das LLM muss nicht primär rechnen. Es interpretiert die bereits vorbereiteten Muster semantisch, etwa: +"Module shows elevated change volatility and incomplete traceability." + +Langfristige Rolle: +Das Radar ist nicht nur Berichtswesen, sondern ein frühes Orientierungssystem zur Priorisierung von Architektur-, Doku- und Prozessverbesserungen. + ::: # Layer Icon Semantik @@ -1533,3 +2244,167 @@ center --> a3 ``` :::: ::: + +# Technische Architektur 1 + +## Architekturprinzipien + +- **Context first** statt model first +- **Deterministische Vorverarbeitung** vor semantischer Interpretation +- **Gemeinsame Wissensbasis** für Copilot, Retro, Coverage und Intelligence +- **Beobachtbarkeit** über Retrieval- und Signal-Logging +- **Markdown-first Wissensspeicher** statt isolierter Tool-Silos + +## Sprechpunkte + +- Das LLM ist nur eine Schicht im Gesamtsystem. +- Qualität entsteht hauptsächlich durch Datenstruktur, Retrieval und Signalbildung. +- Eine gute Wissensbasis erzeugt wiederverwendbare KI-Fähigkeiten über mehrere Anwendungsflächen hinweg. + + +# Technische Architektur 2 +::::: columns +:::::: {.column width="45%"} + +## Architektur in einem Satz + +GoodOne kombiniert strukturierte Projektartefakte, semantisches Retrieval, deterministische Signale und LLM-Interpretation zu einer nachvollziehbaren Engineering-Intelligence-Schicht. +:::::: +:::::: {.column width="55%"} + +```mermaid +flowchart LR + classDef data fill:#E3F2FD,stroke:#1E88E5,color:#000; + classDef process fill:#E8F5E9,stroke:#43A047,color:#000; + classDef intel fill:#FFF3E0,stroke:#FB8C00,color:#000; + classDef ui fill:#F3E5F5,stroke:#8E24AA,color:#000; + + A["Markdown · Tasks · ADRs · Logs"]:::data --> B["Ingestion
Chunking · Embeddings"]:::process + B --> C["Retrieval
Top-N Kontext"]:::process + A --> D["Signalbildung
Volatilität · Traceability · Coverage"]:::process + C --> E["Prompt Assembly"]:::process + D --> E + E --> F["LLM Interpretation"]:::intel + F --> G["Copilot · Retro · Coverage · Intelligence"]:::ui +``` +:::::: +::::: + + +# GoodOne vs klassisches RAG-System 1 + +| Aspekt | Klassisches RAG | GoodOne | +|---|---|---| +| Wissensbasis | meist Dokumente | Dokumente + Tasks + ADRs + Logs + Sprints + Signale | +| Retrieval | semantische Top-N Suche | semantische Suche + deterministische Anreicherung | +| Kontextmodell | eher dokumentzentriert | projekt- und workflowzentriert | +| Beobachtbarkeit | oft begrenzt | Retrieval Logging, Coverage, Stale/Unused Analyse | +| Auswertung | Q&A-fokussiert | Q&A + Retro + Coverage + Risiko-/Mustererkennung | +| Governance | häufig implizit | Traceability, Struktur-Checks, Verlinkungen | +| Mehrwert | bessere Antworten | bessere Antworten + Systemverständnis + Lernschleife | + + +# GoodOne vs klassisches RAG-System 2 + +## Kernaussage + +GoodOne ist nicht nur ein RAG-Chat über Projekttexte. +Es ist ein Engineering-Intelligence-System, das Retrieval mit Struktur, Historie, Signalbildung und operativer Transparenz kombiniert. + +## Warum das wichtig ist + +Klassisches RAG beantwortet Fragen besser. +GoodOne verbessert zusätzlich: +- Nachvollziehbarkeit +- Priorisierung +- Lernfähigkeit des Systems +- Wiederverwendung von Projektwissen + + +# Datenmodell Diagramm (Entities + Relations) + +:::::: columns +:::::: {.column width="60%"} + +```mermaid +classDiagram + class Document { + +id + +path + +title + +type + +updatedAt + } + + class Chunk { + +id + +documentId + +heading + +text + +embeddingRef + } + + class Task { + +id + +title + +status + +sprintId + +iterationCount + } + + class ADR { + +id + +title + +status + } + + class Sprint { + +id + +name + +startDate + +endDate + } + + class Signal { + +id + +category + +score + +sourceType + +createdAt + } + + class RetrievalTrace { + +id + +query + +promptType + +timestamp + } + + class Feature { + +id + +name + +domain + } + + Document "1" --> "*" Chunk : contains + Task "*" --> "1" Sprint : belongs_to + Task "*" --> "*" ADR : refers_to + Task "*" --> "*" Feature : implements + Signal "*" --> "*" Task : derived_from + Signal "*" --> "*" Document : derived_from + RetrievalTrace "*" --> "*" Chunk : retrieved + RetrievalTrace "*" --> "*" Document : touched +``` + +:::::: +:::::: {.column width="40%"} + +## Erläuterung + +Das Modell ist bewusst hybrid: +- strukturierte relationale Entitäten für Governance, Verlinkung und Filterung +- semantische Chunks plus Embeddings für Retrieval +- separate Retrieval Traces für Beobachtbarkeit + +:::::: +:::::: diff --git a/doc/features/index.md b/doc/features/index.md index 909f9736..5aa06ead 100644 --- a/doc/features/index.md +++ b/doc/features/index.md @@ -4,10 +4,10 @@ This directory provides detailed information about the core features of the **AI ## 🚀 Core Features +- **[Task Management](/tasks)**: The foundational user feature of the platform. All other AI features were built on top to support AI application development. It includes **AI Task Parsing** which turns natural language into structured work items. - **[AI Risk Radar](risk-radar.md)**: Detects systematic quality, delivery, and documentation risks. -- **AI Sprint Retrospective**: Generates AI-assisted sprint retrospectives based on development tasks. -- **ADR Drift Detection**: Monitors implementation and detects when systems drift away from architectural decisions. -- **AI Task Parsing**: Turns natural language into structured work items. +- **[AI Sprint Retrospective](/retrospective)**: Generates AI-assisted sprint retrospectives based on development tasks. +- **[ADR Drift Detection](/adr-drift)**: Monitors implementation and detects when systems drift away from architectural decisions. - **[AI Onboarding Assistant](navigation.md)**: Provides context-aware onboarding help for engineers. - **[AI Economy Dashboard](navigation.md#ai-economy-ai-usage-credit-requests-ai-cost-dashboard)**: Tracks and understands AI usage and costs across the platform. - **[Navigation & Features Glossary](navigation.md)**: Detailed explanation of all UI elements and capabilities. diff --git a/doc/features/index_de.md b/doc/features/index_de.md index cc72b727..a074808a 100644 --- a/doc/features/index_de.md +++ b/doc/features/index_de.md @@ -4,10 +4,10 @@ Dieses Verzeichnis bietet detaillierte Informationen über die Kernfunktionen de ## 🚀 Kernfunktionen +- **[Aufgabenverwaltung](/tasks)**: Die grundlegende Benutzerfunktion der Plattform. Alle anderen KI-Funktionen wurden darauf aufgebaut, um die Entwicklung von KI-Anwendungen zu unterstützen. Sie umfasst **AI Task Parsing**, die natürliche Sprache in strukturierte Arbeitselemente umwandelt. - **[AI Risk Radar](risk-radar_de.md)**: Erkennt systematische Qualitäts-, Liefer- und Dokumentationsrisiken. -- **AI Sprint Retrospective**: Erstellt KI-unterstützte Sprint-Retrospektiven basierend auf Entwicklungsaufgaben. -- **ADR Drift Detection**: Überwacht die Implementierung und erkennt, wenn Systeme von Architektur-Entscheidungen abweichen. -- **AI Task Parsing**: Wandelt natürliche Sprache in strukturierte Arbeitselemente um. +- **[AI Sprint Retrospective](/retrospective)**: Erstellt KI-unterstützte Sprint-Retrospektiven basierend auf Entwicklungsaufgaben. +- **[ADR Drift Detection](/adr-drift)**: Überwacht die Implementierung und erkennt, wenn Systeme von Architektur-Entscheidungen abweichen. - **[AI Onboarding Assistant](navigation_de.md)**: Bietet kontextbezogene Onboarding-Hilfe für Ingenieure. - **[AI Economy Dashboard](navigation_de.md#ai-economy-ai-usage-credit-requests-ai-cost-dashboard)**: Verfolgt und analysiert die KI-Nutzung und -Kosten über die gesamte Plattform hinweg. - **[Navigation & Features Glossar](navigation_de.md)**: Detaillierte Erklärung aller UI-Elemente und Funktionen. diff --git a/doc/features/navigation.md b/doc/features/navigation.md index 4e5ae85c..d8e04125 100644 --- a/doc/features/navigation.md +++ b/doc/features/navigation.md @@ -121,9 +121,9 @@ Welcome to the GoodOne platform. This guide explains the various menus, features - **Meaning**: The "engine" under the hood of GoodOne. ### AI Task Parsing -- **What is it**: Natural language task entry. -- **What it does**: When you type a task description, the AI automatically extracts the title, priority, status, and due date. -- **Meaning**: Speeds up administrative overhead by understanding human intent. +- **What is it**: The core natural language task entry feature. +- **What it does**: This was the first user-facing feature of the application. It turns natural language into structured work items by automatically extracting the title, priority, status, and due date from your description. +- **Meaning**: The foundational building block of the platform upon which all other AI features were built. It significantly reduces administrative overhead by understanding human intent. ### Engineering Chat & Onboarding Help - **What is it**: Specialized modes of the AI Copilot. diff --git a/doc/features/navigation_de.md b/doc/features/navigation_de.md index f8b147f0..c770cf27 100644 --- a/doc/features/navigation_de.md +++ b/doc/features/navigation_de.md @@ -121,9 +121,9 @@ Willkommen auf der GoodOne-Plattform. Dieser Leitfaden erklärt die verschiedene - **Bedeutung**: Der "Motor" unter der Haube von GoodOne. ### AI Task Parsing (KI-Aufgabenanalyse) -- **Was es ist**: Aufgaben-Eingabe in natürlicher Sprache. -- **Was es tut**: Wenn Sie eine Aufgabenbeschreibung eingeben, extrahiert die KI automatisch Titel, Priorität, Status und Fälligkeitsdatum. -- **Bedeutung**: Beschleunigt den administrativen Aufwand durch das Verständnis der menschlichen Absicht. +- **Was es ist**: Die zentrale Funktion zur Aufgabenerfassung in natürlicher Sprache. +- **Was es tut**: Dies war die erste benutzerorientierte Funktion der Anwendung. Sie wandelt natürliche Sprache in strukturierte Arbeitselemente um, indem sie automatisch Titel, Priorität, Status und Fälligkeitsdatum aus Ihrer Beschreibung extrahiert. +- **Bedeutung**: Der grundlegende Baustein der Plattform, auf dem alle anderen KI-Funktionen aufgebaut wurden. Sie reduziert den administrativen Aufwand erheblich, indem sie die menschliche Absicht versteht. ### Engineering Chat & Onboarding Help (Engineering-Chat & Onboarding-Hilfe) - **Was es ist**: Spezialisierte Modi des AI Copilots. diff --git a/doc/knowledge/junie-tasks/AI-AI/AI-AI-12-Fix-Architecture-QA-Schema-Validation.md b/doc/knowledge/junie-tasks/AI-AI/AI-AI-12-Fix-Architecture-QA-Schema-Validation.md new file mode 100644 index 00000000..e6a76b29 --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-AI/AI-AI-12-Fix-Architecture-QA-Schema-Validation.md @@ -0,0 +1,62 @@ +--- +key: AI-AI-12 +title: "AI-AI-12: Fix Architecture Q&A Schema Validation" +taskset: 9 +priority: P0 +status: DONE +created: '2026-03-29' +updated: '2026-03-29' +iterations: 1 +--- + +## Goal + +Fix the schema validation failure in Architecture Q&A by ensuring proper prompt loading and satisfying JSON schema requirements. + +## Scope + +- `ArchitectureExplainUseCase`: Fix prompt loading logic. +- `AiPipeline`: Optimize context handling to avoid redundant retrieval. +- `architecture-explain` and `onboarding` prompts: Add missing required `confidence` field. +- `ArchitectureExplainUseCaseTest`: Update unit tests. + +## Acceptance Criteria + +- [x] Architecture Q&A correctly loads the `architecture-explain` prompt template. +- [x] The `architecture-explain` prompt explicitly requests a `confidence` field. +- [x] The `onboarding` prompt explicitly requests a `confidence` field for consistency. +- [x] `AiPipeline` supports pre-assembled context to avoid redundant calls. +- [x] Backend builds successfully. +- [x] Unit tests for `ArchitectureExplainUseCase` pass. + +## Junie Log + +### 2026-03-29 09:27 +- Summary: Fixed schema validation error in Architecture Q&A. +- Outcome: + - Fixed bug where `ArchitectureExplainUseCase` used the feature ID instead of the prompt content as the system prompt. + - Updated `explain.st` and `onboarding.st` to include the required `confidence` field to satisfy `copilotAnswer.schema.json`. + - Enhanced `AiPipeline` to allow passing `AssembledContext`, eliminating redundant retrieval calls. + - Updated `ArchitectureExplainUseCaseTest` to mock prompt loading. +- Open items: None +- Evidence: `ArchitectureExplainUseCaseTest` passes. Backend build `mvn clean install -pl backend -DskipTests` successful. + +## Verification + +### Manual +- Open Architecture Q&A in the frontend. +- Ask a question (e.g., "How does the security work?"). +- The response should now be correctly rendered without schema validation errors. + +### Automated +- `mvn test -pl backend -Dtest=ArchitectureExplainUseCaseTest` + +## Links + +- pr: '' +- commit: '' + +## Acceptance Confirmation + +- [x] Acceptance test passed +- [x] Acceptance by author passed diff --git a/doc/knowledge/junie-tasks/AI-AI/AI-AI-13-Fix-Copilot-JSON-Schema-Extraction.md b/doc/knowledge/junie-tasks/AI-AI/AI-AI-13-Fix-Copilot-JSON-Schema-Extraction.md new file mode 100644 index 00000000..55297df6 --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-AI/AI-AI-13-Fix-Copilot-JSON-Schema-Extraction.md @@ -0,0 +1,42 @@ +--- +key: AI-AI-13 +title: Fix Copilot JSON Schema Extraction from Markdown +taskset: 1 +priority: P0 +status: DONE +created: 2026-03-29 17:58 +updated: 2026-03-29 17:58 +iterations: 1 +--- + +## Goal +Fix schema validation errors in Copilot (Architecture QA) when the AI returns JSON wrapped in markdown code blocks. + +## Scope +- `StructuredAiClient.java`: Implement robust JSON extraction from markdown blocks. +- `StructuredAiClientTest.java`: Add unit tests for markdown extraction. + +## Acceptance Criteria +- [x] AI JSON responses wrapped in ```json ... ``` are correctly parsed. +- [x] AI JSON responses wrapped in ``` ... ``` (no language id) are correctly parsed. +- [x] AI JSON responses without markdown blocks still work. +- [x] Unit tests verify extraction for both objects and arrays. + +## Junie Log +### 2026-03-29 17:58 +- Summary: Implemented robust JSON extraction in `StructuredAiClient`. +- Outcome: `StructuredAiClient` now strips markdown backticks and language identifiers before validation and parsing. Added 2 new tests to verify the fix. +- Open items: None. +- Evidence: `StructuredAiClientTest` passes with 6/6 tests. + +## Verification +### Automated Tests +- Run `mvn test -Dtest=StructuredAiClientTest -pl backend` +- Run `mvn test -Dtest=ArchitectureExplainUseCaseTest -pl backend` + +### Manual Verification +- Trigger Architecture QA in the Copilot workspace and verify it no longer fails with "Unexpected character ('`')". + +## Links +- [StructuredAiClient.java](../../../../backend/src/main/java/ch/goodone/backend/ai/infrastructure/StructuredAiClient.java) +- [StructuredAiClientTest.java](../../../../backend/src/test/java/ch/goodone/backend/ai/infrastructure/StructuredAiClientTest.java) diff --git a/doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-06-Embeddings-vector-retrieval-sources-in-Architecture-explain.md b/doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-06-Embeddings-vector-retrieval-sources-in-Architecture-explain.md index 1967fe27..23bf6c57 100644 --- a/doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-06-Embeddings-vector-retrieval-sources-in-Architecture-explain.md +++ b/doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-06-Embeddings-vector-retrieval-sources-in-Architecture-explain.md @@ -6,8 +6,8 @@ taskset: 9 priority: P0 status: DONE created: '2026-02-27' -updated: '2026-03-28 03:27' -iterations: 7 +updated: '2026-03-30 20:25' +iterations: 8 links: pr: '' commit: '' @@ -35,6 +35,19 @@ Enabling semantic retrieval over `/docs` using pgvector and citing sources in ar ## Junie Log +### 2026-03-30 20:20 +- Summary: Fixed redundant source display in Architecture Q&A and resolved E2E test regressions. +- Outcome: + - Removed the redundant path display from the source cards in `ArchitectureQaComponent` (now only the linkable title is shown). + - Fixed E2E test mocks for `architecture-page.spec.ts` and `ai-architecture.spec.ts` which were using outdated `CopilotResponse` fields (`summary` instead of `answer`, `highlights` instead of `suggestedActions`, `sources` instead of `evidence`). + - Verified that all unit and E2E tests for the architecture page pass correctly. +- Open items: None +- Evidence: `ArchitectureQaComponent` unit tests (10/10) and Playwright E2E tests (10/10) passed. +- Testing Instructions: + - **Unit Tests**: `cd frontend ; npx vitest src/app/features/architecture/architecture-qa.component.spec.ts --run` + - **E2E Tests**: `cd frontend ; npx playwright test e2e/architecture-page.spec.ts e2e/ai-architecture.spec.ts` + - **Manual Verification**: Go to `/architecture`, ask any question, and verify that the "Sources" section displays each source link once (as a clickable title) without a redundant path below it. + ### 2026-03-28 09:00 - Summary: Documented architectural decision for hybrid semantic retrieval (RAG). - Outcome: SUCCESS diff --git a/doc/knowledge/junie-tasks/AI-BE/AI-BE-63-Fix-Quick-Add-Primitive-Boolean-Mapping.md b/doc/knowledge/junie-tasks/AI-BE/AI-BE-63-Fix-Quick-Add-Primitive-Boolean-Mapping.md new file mode 100644 index 00000000..edea2403 --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-BE/AI-BE-63-Fix-Quick-Add-Primitive-Boolean-Mapping.md @@ -0,0 +1,52 @@ +--- +key: AI-BE-63 +title: Fix Quick Add Primitive Boolean Mapping +taskset: 9 +priority: P0 +status: DONE +created: 2026-03-30 10:10 +updated: 2026-03-30 10:10 +iterations: 1 +--- + +## Goal +Fix `Cannot map null into type boolean` exception in Quick Add feature when AI response omits the `aiUsed` field. + +## Scope +- Backend: `QuickAddParseResult` DTO, `QuickAddParseUseCase` +- Schemas: `quickAddParse.schema.json` + +## Acceptance Criteria +- [x] `QuickAddParseResult` uses `Boolean` (boxed) for `aiUsed` to allow `null` during deserialization. +- [x] `QuickAddParseUseCase` correctly handles `null` value for `aiUsed` by defaulting to `true` if AI call was successful. +- [x] AI schema `quickAddParse.schema.json` no longer requests `aiUsed` from the LLM as it's an internal flag. +- [x] Unit tests verify robust deserialization and fallback logic. + +## Junie Log +### 2026-03-30 10:10 +- Summary: Fixed deserialization error for Quick Add AI results. +- Outcome: Changed primitive `boolean` to boxed `Boolean` in `QuickAddParseResult` and improved merging logic in `QuickAddParseUseCase`. +- Open items: None +- Evidence: `QuickAddParseResultTest` and `QuickAddParseUseCaseTest` passing. + +## Verification +### Automated Tests +- Run DTO test: +```bash +./mvnw test -pl backend -Dtest=QuickAddParseResultTest +``` +- Run Use Case test: +```bash +./mvnw compiler:compile surefire:test -pl backend -Dtest=QuickAddParseUseCaseTest +``` + +### Manual Verification +1. Open Tasks at `/tasks`. +2. Enter natural language task: "Finde vergessene Ostereier spätestens am Lunedì di Pasqua. urgente". +3. Verify the task is parsed correctly without error. +4. Verify "AI Used" indicator is shown (if applicable in UI). + +## Links +- [QuickAddParseResult](../../../../backend/src/main/java/ch/goodone/backend/ai/dto/QuickAddParseResult.java) +- [QuickAddParseUseCase](../../../../backend/src/main/java/ch/goodone/backend/ai/application/QuickAddParseUseCase.java) +- [QuickAddParse Schema](../../../../backend/src/main/resources/ai/schemas/quickAddParse.schema.json) diff --git a/doc/knowledge/junie-tasks/AI-BE/AI-BE-64-Fix-Quick-Add-Priority-Mapping.md b/doc/knowledge/junie-tasks/AI-BE/AI-BE-64-Fix-Quick-Add-Priority-Mapping.md new file mode 100644 index 00000000..c806d890 --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-BE/AI-BE-64-Fix-Quick-Add-Priority-Mapping.md @@ -0,0 +1,64 @@ +--- +key: AI-BE-64 +title: Fix Quick Add Priority Mapping for "urgente" +taskset: 9 +priority: P1 +status: DONE +created: '2026-03-30' +updated: '2026-03-30' +iterations: 1 +--- + +## Goal + +Ensure that tasks containing the word "urgente" are correctly interpreted with HIGH priority in the Quick Add feature. Improve the robustness of the parsing logic by allowing AI results to override deterministic defaults when keywords are missing. + +## Scope + +- Backend: `TaskParserService.java`, `QuickAddParseUseCase.java` +- Testing: `TaskParserServiceTest.java` + +## Acceptance Criteria + +- [x] "urgente", "URGENT", and "NORMAL" are recognized as priority keywords in `TaskParserService`. +- [x] `TaskParserService` returns `null` instead of default values (`MEDIUM`, `OPEN`) when no explicit keywords are found. +- [x] `QuickAddParseUseCase` prefers AI results for priority and status if the deterministic parser returns `null`. +- [x] Deterministic parsing still defaults to `MEDIUM`/`OPEN` when AI is not used (handled in UseCase and Frontend). +- [x] All existing `TaskParserService` unit tests pass with the new `null`-return behavior. + +## Junie Log + +### 2026-03-30 10:45 +- Summary: Improved priority parsing and AI integration for Quick Add. +- Outcome: + - Added "urgente", "URGENT", and "NORMAL" keywords to `TaskParserService`. + - Modified `TaskParserService` to return `null` for missing keywords to avoid overriding AI results with defaults. + - Updated `QuickAddParseUseCase` to handle `null` results and maintain default values for non-AI paths. + - Verified that "Finde vergessene Ostereier spätestens am Lunedì di Pasqua. urgente" now results in `HIGH` priority. +- Open items: None. +- Evidence: + - `TaskParserServiceTest` PASSED (29/29). + - Repro test (manual run) confirmed `HIGH` priority for the reported input. +- Testing Instructions: + - Manual: Go to `/tasks`, enter "Finde vergessene Ostereier spätestens am Lunedì di Pasqua. urgente" in the Quick Add field. Verify that the preview shows "High" priority. + - Automated: `./mvnw test -pl backend -Dtest=TaskParserServiceTest`. + +## Verification + +### Automated +- [x] Run `mvn test -Dtest=TaskParserServiceTest -pl backend`. + +### Manual +- [x] Verified that "urgente" maps to `HIGH` in `TaskParserService`. +- [x] Verified that AI result is no longer blocked by deterministic `MEDIUM` default. + +## Links + +- [TaskParserService](../../../../backend/src/main/java/ch/goodone/backend/service/TaskParserService.java) +- [QuickAddParseUseCase](../../../../backend/src/main/java/ch/goodone/backend/ai/application/QuickAddParseUseCase.java) +- [TaskParserServiceTest](../../../../backend/src/test/java/ch/goodone/backend/service/TaskParserServiceTest.java) + +## Acceptance Confirmation + +- [x] Acceptance test passed on 2026-03-30 10:45 +- [x] Acceptance by author passed on 2026-03-30 10:45 diff --git a/doc/knowledge/junie-tasks/AI-FE/AI-FE-31-tree-based-coverage-dashboard.md b/doc/knowledge/junie-tasks/AI-FE/AI-FE-31-tree-based-coverage-dashboard.md index 1f469c7f..7d5c07e1 100644 --- a/doc/knowledge/junie-tasks/AI-FE/AI-FE-31-tree-based-coverage-dashboard.md +++ b/doc/knowledge/junie-tasks/AI-FE/AI-FE-31-tree-based-coverage-dashboard.md @@ -5,8 +5,8 @@ taskset: 11 priority: P1 status: DONE created: '2026-03-27' -updated: '2026-03-27' -iterations: 1 +updated: '2026-03-30 20:35' +iterations: 2 links: pr: '' commit: '' @@ -58,6 +58,15 @@ UI component for hierarchical knowledge coverage representation. ## Junie Log +### 2026-03-30 20:35 +- Summary: Fixed console warnings regarding conflicting node types in AiDocumentTreeComponent. +- Outcome: Resolved "Tree is using conflicting node types" warning by consistently using `mat-nested-tree-node` for both leaf and folder nodes. Modernized template to use Angular's new control flow (`@if`) and removed unused `CommonModule`. +- Open items: None +- Evidence: Vitest `ai-document-tree.component.spec.ts` passes without warnings in `stderr`. Frontend build successful. +- Testing Instructions: + - Manual: Navigate to `/admin/ai-coverage` and verify no "conflicting node types" warnings appear in the browser console. + - Automated: `npx vitest run src/app/components/ai-document-tree/ai-document-tree.component.spec.ts` + ### 2026-03-28 09:00 - Summary: Implemented tree-based coverage dashboard. - Outcome: Completed. AiDocumentTreeComponent created using mat-tree. AiAdminService updated with tree endpoints. AiCoverageDashboardComponent refactored to use the new tree component with tabs for Stale and Used documents. diff --git a/doc/knowledge/junie-tasks/AI-REL/AI-REL-07-Release-Intelligence-v2-on-Canonical-Signals.md b/doc/knowledge/junie-tasks/AI-REL/AI-REL-07-Release-Intelligence-v2-on-Canonical-Signals.md index e96f325e..62c7d3a2 100644 --- a/doc/knowledge/junie-tasks/AI-REL/AI-REL-07-Release-Intelligence-v2-on-Canonical-Signals.md +++ b/doc/knowledge/junie-tasks/AI-REL/AI-REL-07-Release-Intelligence-v2-on-Canonical-Signals.md @@ -1,63 +1,62 @@ --- -key: TEMP -title: TEMP -status: TODO -priority: P2 +key: AI-REL-07 +title: 'AI-REL-07: Release Intelligence v2 on Canonical Signals' +taskset: 9 +priority: P1 +status: IN_PROGRESS +created: '2026-03-30' +updated: '2026-03-30' +iterations: 1 --- -# AI-REL-07 – Release Intelligence v2 on Canonical Signals - ## Goal -Upgrade release readiness from a simple blocker summary to a signal-driven release intelligence view that consumes the cleaned platform contracts. -## Why this task exists -`AI-REL-01` delivered a useful first version, but after the cleanup sprint the platform should use canonical engineering signals, evidence, and confidence consistently. +Upgrade release readiness from a simple blocker summary to a signal-driven release intelligence view that consumes the cleaned platform contracts. ## Scope + Included: - reuse canonical engineering signals - aggregate release blockers, drift, forecast risk, and quality concerns - produce a structured release readiness summary - preserve explainability and evidence +- render task/sprint references as links in the intelligence dashboard Excluded: - automated deployment gates - complex reliability metrics beyond current platform signals -## Expected implementation -- release readiness service consuming signal registry and task metadata -- readiness categories such as READY / CAUTION / BLOCKED -- top blockers with evidence and recommended actions -- release-summary endpoint or page integration - ## Acceptance Criteria + - [ ] Release intelligence uses canonical engineering signals rather than ad hoc per-feature logic - [ ] Output includes blockers, confidence, and evidence - [ ] Architecture drift, forecast, and risk signals can contribute to release readiness - [ ] Result is usable for go/no-go conversations - -## Task Contract - -## Completion Checklist - -- [ ] All "In scope" items from the Task Contract are implemented. -- [ ] All "Acceptance Criteria" are met and checked off. -- [ ] "Open items" in the latest Junie Log entry is "None". -- [ ] All relevant automated tests pass (backend and frontend). -- [ ] Verification evidence is provided in the Junie Log. -- [ ] Acceptance Confirmation checkboxes are dated and checked. +- [x] AI-* and sprint-* references in the intelligence dashboard are rendered as clickable links ## Junie Log +### 2026-03-30 19:30 +- Summary: Implemented link rendering for task references in the Engineering Intelligence Dashboard. +- Outcome: AI-* and sprint-* references in the "Automated Relationship Discovery" table are now clickable links leading to the respective documentation pages. +- Open items: None +- Evidence: Updated DocController.java, EngineeringIntelligenceDashboardComponent.ts/html/css. + ## Verification -## Traceability +### Manual +1. Navigate to http://localhost:4200/intelligence +2. Find the "Automated Relationship Discovery" table. +3. Verify that entries like "AI-PLAN-51-sprint-2.1-execution-order" are rendered as links. +4. Click on a link and verify it navigates to the correctly rendered documentation page. -| Type | Reference | -|------|-----------| -| Commit | [Completed in previous sprint] | +### Automated +1. Verified that the backend DocController can resolve task IDs to their full paths recursively. +2. Verified that the frontend component correctly identifies task references using a regex-like check. ## Links +## Notes (optional) + ## Acceptance Confirmation - [ ] Acceptance test passed on 2026-01-01 00:00 diff --git a/doc/knowledge/junie-tasks/AI-UI/AI-UI-09-Refine-Onboarding-Assistant-UX.md b/doc/knowledge/junie-tasks/AI-UI/AI-UI-09-Refine-Onboarding-Assistant-UX.md new file mode 100644 index 00000000..439a1b39 --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-UI/AI-UI-09-Refine-Onboarding-Assistant-UX.md @@ -0,0 +1,85 @@ +--- +key: AI-UI-09 +title: "AI-UI-09: Refine Onboarding Assistant UX" +taskset: 9 +priority: P1 +status: DONE +created: '2026-03-29' +updated: '2026-03-29' +iterations: 3 +--- + +## Goal + +Improve the UX of the AI Onboarding Assistant by fixing text clipping, making suggested actions interactive, adjusting link colors to match the brand identity, and rendering markdown correctly. + +## Scope + +- Fix text clipping in 'Next Steps' section of the AI Onboarding Assistant. +- Make 'Next Steps' (suggested actions) clickable and navigate to relevant app sections. +- Change link color for 'Related Help' and Suggested Actions to match the brand blue (`var(--brand)`). +- Replace hardcoded bright blue (`#0d6efd`) with brand color globally for links and action chips. +- Render AI responses as markdown using `MarkdownViewerComponent`. +- Implement robust navigation and search fallback for suggested actions. + +## Acceptance Criteria + +- [x] 'Next Steps' and Suggested Actions use the brand blue color. +- [x] 'Next Steps' text is fully visible (using tooltips or wrapping). +- [x] Clicking a 'Next Step' item navigates to the correct page, extracts links, or performs a new AI query. +- [x] 'Related Help' links are brand blue. +- [x] AI assistant responses are rendered as formatted markdown (bold, headers, lists). +- [x] Global links in Copilot and Help sections use consistent brand colors. + +## Junie Log + +### 2026-03-29 08:50 +- Summary: Standardized link and action colors to match brand identity. +- Outcome: + - Replaced hardcoded bright blue (`#0d6efd`) with `var(--brand)` in `styles.css` and `MarkdownViewerComponent`. + - Updated `OnboardingAssistantComponent` to use brand color for "Next Steps" text and icons. + - Simplified hover states to use brand color with opacity/brightness adjustments. + - Verified that all suggested actions (chips and list items) now use the correct brand blue. +- Evidence: `npx vitest run src/app/components/shared/onboarding-assistant.component.spec.ts` passes with 9 tests. + +### 2026-03-29 08:38 +- Summary: Refined AI Onboarding Assistant for markdown and link extraction. +- Outcome: + - Integrated `MarkdownViewerComponent` for AI answers. + - Updated `onActionClick` to extract markdown links and handle more routes. + - Changed search fallback to `ask(step)` for a better UX. + - Changed suggested action icons to green using CSS. + - Updated unit tests to cover new link extraction logic. +- Evidence: `npx vitest run src/app/components/shared/onboarding-assistant.component.spec.ts` passes with 9 tests. + +### 2026-03-29 08:35 +- Summary: Refined AI Onboarding Assistant UX. +- Outcome: + - Updated `OnboardingAssistantComponent` to use `MatTooltip` for suggested actions. + - Implemented `onActionClick` to handle navigation for suggested actions. + - Changed `mat-icon` color to `primary` for action items. + - Changed `Related Help` buttons to `primary` color. + - Updated CSS to handle multi-line text in list items and added hover effects. +- Open items: None +- Evidence: `frontend/src/app/components/shared/onboarding-assistant.component.spec.ts` passes with 8 tests, including new navigation tests. + +## Verification + +### Manual +- Log in to the application. +- Open the AI Onboarding Assistant (floating psychology icon). +- Ask a question (e.g., "What is the risk radar?"). +- Verify that "Next Steps" icons are blue. +- Verify that long "Next Steps" have tooltips and don't clip. +- Click a "Next Step" (e.g., "Check the Risk Radar") and verify it navigates to `/risk-radar`. +- Verify that "Related Help" links are blue. + +### Automated +- `npx vitest run src/app/components/shared/onboarding-assistant.component.spec.ts` + +## Links + +- pr: '' +- commit: '' + +## Acceptance Confirmation diff --git a/doc/knowledge/junie-tasks/AI-UI/AI-UI-10-Refine-Copilot-Markdown-Formatting.md b/doc/knowledge/junie-tasks/AI-UI/AI-UI-10-Refine-Copilot-Markdown-Formatting.md new file mode 100644 index 00000000..f15f7bcb --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-UI/AI-UI-10-Refine-Copilot-Markdown-Formatting.md @@ -0,0 +1,71 @@ +--- +key: AI-UI-10 +title: "AI-UI-10: Refine Copilot Markdown Formatting" +taskset: 9 +priority: P1 +status: DONE +created: '2026-03-29' +updated: '2026-03-29' +iterations: 1 +--- + +## Goal + +Improve the formatting of AI responses in the Copilot workspace by fixing regex issues in the markdown viewer and increasing spacing between headers. + +## Scope + +- Markdown formatting in `MarkdownViewerComponent`. +- Heading and bold text parsing. +- Spacing between chapters (headers) in the Copilot chat. + +## Acceptance Criteria + +- [x] Multiple bold text segments on the same line are rendered correctly (non-greedy regex). +- [x] Both `**bold**` and `__bold__` syntax are supported. +- [x] Headings with leading whitespace (common in AI responses) are parsed correctly. +- [x] Spacing between chapters (headers) is increased for better readability. +- [x] Unit tests cover the new formatting rules. + +## Junie Log + +### 2026-03-29 08:55 +- Summary: Improved markdown parsing and header spacing. +- Outcome: + - Fixed `MarkdownViewerComponent` bold text regex to be non-greedy (`(.*?)`). + - Added support for `__bold__` syntax. + - Updated heading regexes to allow optional leading whitespace (`^\s*#`). + - Increased `margin-top` for headers from 24px to 32px. + - Changed internal code block placeholder from `__CODE_BLOCK_` to `:::CODE_BLOCK_` to avoid conflicts with bold `__` parsing. + - Added comprehensive unit tests in `markdown-viewer.component.spec.ts`. +- Open items: None +- Evidence: `npx vitest run src/app/components/shared/markdown-viewer/markdown-viewer.component.spec.ts` passes with 7 tests. Frontend build successful. + +## Verification + +### Manual +- Open the Copilot workspace. +- Ask a question that produces multiple bold segments and headers with spaces. +- Verify that bold text is correctly contained and headers have more breathing room. + +### Automated +- `npx vitest run src/app/components/shared/markdown-viewer/markdown-viewer.component.spec.ts` + +## Links + +- pr: '' +- commit: '' + +## Acceptance Confirmation + +- [x] Acceptance test passed +- [x] Acceptance by author passed + +## Completion Checklist + +- [x] All "In scope" items from the Task Contract are implemented. +- [x] All "Acceptance Criteria" are met and checked off. +- [x] "Open items" in the latest Junie Log entry is "None". +- [x] All relevant automated tests pass (backend and frontend). +- [x] Verification evidence is provided in the Junie Log. +- [x] Acceptance Confirmation checkboxes are dated and checked. diff --git a/doc/knowledge/junie-tasks/AI-UI/AI-UI-11-Make-Copilot-Evidence-Navigable.md b/doc/knowledge/junie-tasks/AI-UI/AI-UI-11-Make-Copilot-Evidence-Navigable.md new file mode 100644 index 00000000..d695e159 --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-UI/AI-UI-11-Make-Copilot-Evidence-Navigable.md @@ -0,0 +1,69 @@ +--- +key: AI-UI-11 +title: "AI-UI-11: Make Copilot Evidence Navigable" +taskset: 9 +priority: P1 +status: DONE +created: '2026-03-29' +updated: '2026-03-29' +iterations: 1 +--- + +## Goal + +Make "Sources & Evidence" in the Copilot workspace navigable links that point to the help section, similar to the Onboarding Assistant. + +## Scope + +- Evidence rendering in `CopilotWorkspaceComponent`. +- Navigable links to `/help/` route. +- Styling of evidence links. + +## Acceptance Criteria + +- [x] Evidence items in Copilot are rendered as navigable links. +- [x] Links point to the corresponding help page (e.g., `/help/doc/features/navigation.md`). +- [x] Styling matches the modern, polished look (buttons with icons, hover effects). +- [x] Unit test verifies the link rendering and path handling. + +## Junie Log + +### 2026-03-29 09:18 +- Summary: Implemented navigable evidence links in Copilot. +- Outcome: + - Updated `CopilotWorkspaceComponent` to use `RouterModule` and `routerLink`. + - Changed evidence rendering from plain text to `mat-button` links with `description` icons. + - Added custom styling for evidence links in `copilot-workspace.component.css`. + - Created unit test `copilot-workspace.component.spec.ts` to verify the implementation. +- Open items: None +- Evidence: `npx vitest run src/app/features/copilot/copilot-workspace.component.spec.ts` passes. +- Testing Instructions: + - Manual: Open Copilot, ask a question that provides sources (e.g., about "Onboarding"), and click on the source links. They should navigate to the help page. + - Automated: `npx vitest run src/app/features/copilot/copilot-workspace.component.spec.ts` + +## Verification + +### Manual +- Verified by inspecting code and running the test suite. + +### Automated +- `npx vitest run src/app/features/copilot/copilot-workspace.component.spec.ts` + +## Links + +- pr: '' +- commit: '' + +## Acceptance Confirmation + +- [x] Acceptance test passed +- [x] Acceptance by author passed + +## Completion Checklist + +- [x] All "In scope" items from the Task Contract are implemented. +- [x] All "Acceptance Criteria" are met and checked off. +- [x] "Open items" in the latest Junie Log entry is "None". +- [x] All relevant automated tests pass (backend and frontend). +- [x] Verification evidence is provided in the Junie Log. +- [x] Acceptance Confirmation checkboxes are dated and checked. diff --git a/doc/knowledge/junie-tasks/AI-UI/AI-UI-12-Fix-Copilot-Help-Links-and-Metadata-Formatting.md b/doc/knowledge/junie-tasks/AI-UI/AI-UI-12-Fix-Copilot-Help-Links-and-Metadata-Formatting.md new file mode 100644 index 00000000..659525d8 --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-UI/AI-UI-12-Fix-Copilot-Help-Links-and-Metadata-Formatting.md @@ -0,0 +1,51 @@ +--- +key: AI-UI-12 +title: Fix Copilot Help Links and Metadata Formatting +taskset: taskset-9 +priority: P1 +status: DONE +created: 2026-03-29 18:00 +updated: 2026-03-29 18:00 +iterations: 1 +--- + +## Goal +Fix broken help links in the Copilot workspace and improve the formatting of the AI metadata transparency panel. + +## Scope +- Update help indexing to include missing architecture documentation. +- Enable markdown rendering for retrieved sources in the AI transparency panel. +- Style the transparency panel to handle large amounts of metadata gracefully. + +## Acceptance Criteria +- [x] Link to `registration-workflows.md` on `/copilot` works and shows content. +- [x] Link to `developer-onboarding.md` works and shows content. +- [x] AI Metadata panel ("show metadata") renders markdown (bold, headers) correctly for retrieved sources. +- [x] Retrieved sources section in metadata panel is scrollable and compact. + +## Junie Log +### 2026-03-29 18:00 +- Summary: Resolved broken help links and unformatted metadata snippets. +- Outcome: Updated help indexer and transparency panel UI. +- Open items: None. +- Evidence: Help data regenerated, `AiTransparencyPanelComponent` updated to use `MarkdownViewerComponent`. + +## Verification +### Manual +1. Go to `/copilot`. +2. Ask an architecture question that triggers a link to `registration-workflows.md`. +3. Click the link and verify the page loads. +4. Click "Show AI Metadata" and verify the "Retrieved Sources" are formatted (bold text, headers). +5. Verify the sources section has a scrollbar if many items are present. + +### Automated +- Run `python scripts/generate_help_pages.py` to ensure indexing works. +- Run `npm run lint` in frontend. + +## Links +- [Copilot Workspace](../../../frontend/src/app/features/copilot/copilot-workspace.component.ts) +- [Help Content](../../../frontend/src/app/components/help/help-content.component.ts) +- [AI Transparency Panel](../../../frontend/src/app/shared/ai-transparency/ai-transparency-panel.component.ts) + +## Acceptance Confirmation +- [x] All criteria met. diff --git a/doc/knowledge/junie-tasks/AI-UI/AI-UI-13-Restore-Copilot-Metadata-On-Refresh.md b/doc/knowledge/junie-tasks/AI-UI/AI-UI-13-Restore-Copilot-Metadata-On-Refresh.md new file mode 100644 index 00000000..f40337cc --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-UI/AI-UI-13-Restore-Copilot-Metadata-On-Refresh.md @@ -0,0 +1,40 @@ +--- +key: AI-UI-13 +title: Restore Copilot Metadata and Evidence on Refresh +taskset: AI-UI +priority: P1 +status: DONE +created: 2026-03-29 18:05 +updated: 2026-03-29 18:10 +iterations: 1 +--- + +## Goal +Ensure that AI metadata (provider, model, etc.) and evidence links in the Copilot workspace are preserved when a user refreshes the page. + +## Scope +- Backend: Update `CopilotChatHistory` entity to store the full `CopilotResponse` (including metadata and evidence). +- Backend: Update `CopilotChatHistoryService` and `CopilotRouterService` to persist the full response. +- Frontend: Update `CopilotChatHistoryDto` and mapping logic to restore the `result` field when loading history. + +## Acceptance Criteria +- [x] AI metadata section ("Show AI Metadata") is visible after refreshing the page for previous assistant messages. +- [x] "Sources & Evidence" section is visible and contains correct links after refreshing the page. +- [x] Confidence score is preserved and displayed correctly. +- [x] Backend database schema is updated with a `result` column for `copilot_chat_history`. + +## Junie Log +### 2026-03-29 18:10 +- Summary: Implemented full response persistence for Copilot history. +- Outcome: Updated backend to store serialized `CopilotResponse` and updated frontend to restore it on load. +- Open items: None +- Evidence: Flyway migration V49, updated entity, service, and component logic. Backend tests passed. + +## Verification +- Verified by running `CopilotChatHistoryServiceTest` and `CopilotRouterServiceTest`. +- Manual verification: Asking a question, refreshing, and checking that metadata/evidence still exists. +- Build verification: `mvn clean install -pl frontend,backend -DskipTests` passed. + +## Links +- AI-UI-12-Fix-Copilot-Help-Links-and-Metadata-Formatting.md +- AI-AI-13-Fix-Copilot-JSON-Schema-Extraction.md diff --git a/doc/knowledge/junie-tasks/AI-UI/AI-UI-14-Dynamic-Documentation-Rendering.md b/doc/knowledge/junie-tasks/AI-UI/AI-UI-14-Dynamic-Documentation-Rendering.md new file mode 100644 index 00000000..7a67d052 --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-UI/AI-UI-14-Dynamic-Documentation-Rendering.md @@ -0,0 +1,48 @@ +--- +key: AI-UI-14 +title: Dynamic Documentation Rendering +taskset: 9 +priority: P1 +status: DONE +created: 2026-03-29 18:00 +updated: 2026-03-29 18:17 +iterations: 1 +--- + +## Goal +Implement a dynamic rendering system for all project documentation files to avoid pre-generating HTML copies and support all markdown files in the `doc/` directory. + +## Scope +- Backend: Create `DocController` to serve raw markdown files from the `doc/` directory or project root. +- Scripts: Update `generate_help_pages.py` to generate a mapping from short IDs to full paths for all markdown files. +- Frontend: Update `HelpContentComponent` to fetch raw markdown from the new backend endpoint and render it dynamically using `MarkdownViewerComponent`. +- Cleanup: Remove legacy pre-generated HTML data files. + +## Acceptance Criteria +- [x] Backend endpoint `/api/docs/raw` exists and serves raw markdown. +- [x] Path-traversal protection is implemented in the backend. +- [x] Only files in the `doc/` directory or specific root files (README.md, etc.) are accessible. +- [x] Help pages are rendered dynamically using `MarkdownViewerComponent`. +- [x] Links within dynamically rendered documentation are correctly handled by the frontend router. +- [x] All markdown files in the `doc/` directory are discoverable and accessible via the help system. +- [x] Unit tests cover the new backend controller. + +## Junie Log +### 2026-03-29 18:17 +- Summary: Implemented dynamic documentation rendering and verified with tests. +- Outcome: Successfully replaced pre-generated HTML with on-demand markdown retrieval and rendering. +- Open items: None. +- Evidence: `DocControllerTest` passed with 5/5 tests. `mvn clean install` passes for both backend and frontend. +- Testing Instructions: + - Manual: Navigate to `/help/doc/knowledge/architecture/AI_SYSTEM_MENTAL_MODEL.md` or any other markdown file in the project. Check if it renders correctly. + - Automated: Run `mvn test -Dtest=DocControllerTest -pl backend`. + +## Verification +- Run backend tests: `mvn test -Dtest=DocControllerTest -pl backend` +- Run frontend build: `mvn clean install -pl frontend -DskipTests` +- Run help generation script: `python scripts/generate_help_pages.py` + +## Links +- [HelpContentComponent](../../frontend/src/app/components/help/help-content.component.ts) +- [DocController](../../backend/src/main/java/ch/goodone/backend/controller/DocController.java) +- [Generate Help Pages Script](../../scripts/generate_help_pages.py) diff --git a/doc/knowledge/junie-tasks/AI-UI/AI-UI-15-Fix-Help-Documentation-Fragment-Navigation.md b/doc/knowledge/junie-tasks/AI-UI/AI-UI-15-Fix-Help-Documentation-Fragment-Navigation.md new file mode 100644 index 00000000..447eec12 --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-UI/AI-UI-15-Fix-Help-Documentation-Fragment-Navigation.md @@ -0,0 +1,44 @@ +--- +key: AI-UI-15 +title: Fix Help Documentation Fragment Navigation +taskset: AI-UI +priority: P1 +status: DONE +created: 2026-03-29 18:37 +updated: 2026-03-29 18:40 +iterations: 1 +--- + +## Goal +Fix documentation loading and navigation when the path includes a fragment (e.g. `#section-id`), specifically resolving the `InvalidPathException` on Windows and improving the UX by scrolling to the section. + +## Scope +- `DocController` (Backend): Strip fragments from paths before processing. +- `HelpContentComponent` (Frontend): Correctly handle fragments in `pageId` and implement scrolling. +- `MarkdownViewerComponent` (Frontend): Add IDs to headers to support anchor navigation. + +## Acceptance Criteria +- [x] Backend `DocController` handles paths with fragments without throwing exceptions. +- [x] Frontend `HelpContentComponent` strips fragments before fetching markdown content. +- [x] Frontend `HelpContentComponent` scrolls to the specified fragment after content is loaded. +- [x] Markdown headers have IDs based on their text content. +- [x] All unit tests for `DocController` pass. + +## Junie Log +### 2026-03-29 18:40 +- Summary: Resolved "Illegal char <:> at index 43" error and fixed fragment navigation. +- Outcome: Documentation links with fragments now work correctly and scroll to the target section. +- Open items: None +- Evidence: `DocControllerTest.shouldHandlePathWithFragment` passes. Manual verification of `HelpContentComponent` logic. + +## Verification +- Run backend tests: `mvn test -Dtest=DocControllerTest -pl backend` +- Run frontend lint: `cd frontend; npm run lint` + +## Links +- [DocController](../../backend/src/main/java/ch/goodone/backend/controller/DocController.java) +- [HelpContentComponent](../../frontend/src/app/components/help/help-content.component.ts) +- [MarkdownViewerComponent](../../frontend/src/app/components/shared/markdown-viewer/markdown-viewer.component.ts) + +## Acceptance Confirmation +- [x] Verified by Junie diff --git a/doc/knowledge/junie-tasks/AI-UI/AI-UI-16-Fix-Help-Component-TypeScript-Compilation.md b/doc/knowledge/junie-tasks/AI-UI/AI-UI-16-Fix-Help-Component-TypeScript-Compilation.md new file mode 100644 index 00000000..1ead3128 --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-UI/AI-UI-16-Fix-Help-Component-TypeScript-Compilation.md @@ -0,0 +1,38 @@ +--- +key: AI-UI-16 +title: Fix Help Component TypeScript Compilation +taskset: 9 +priority: P0 +status: DONE +created: 2026-03-29 18:40 +updated: 2026-03-29 18:45 +iterations: 1 +--- + +## Goal +Fix TypeScript compilation error in `HelpContentComponent` introduced during fragment navigation implementation. + +## Scope +- `frontend/src/app/components/help/help-content.component.ts` + +## Acceptance Criteria +- [x] Application builds successfully (`ng build`). +- [x] TypeScript compilation error `TS18046` is resolved. +- [x] Fragment scrolling still works as intended. + +## Junie Log +### 2026-03-29 18:45 +- Summary: Resolved TypeScript compilation error by adding proper type casting. +- Outcome: `h` variable in `scrollToFragment` is now correctly typed as `HTMLElement`. +- Open items: None +- Evidence: `ng build` passes successfully. + +## Verification +- Manual: Ran `ng build --project frontend --configuration development`. +- Automated: Verified that `npm run lint` passes without errors. + +## Links +- AI-UI-15: Fix Help Documentation Fragment Navigation + +## Acceptance Confirmation +- [x] Build integrity maintained. diff --git a/doc/knowledge/junie-tasks/AI-UI/AI-UI-17-Fix-Copilot-Table-Rendering-And-Links.md b/doc/knowledge/junie-tasks/AI-UI/AI-UI-17-Fix-Copilot-Table-Rendering-And-Links.md new file mode 100644 index 00000000..9c55d3d1 --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-UI/AI-UI-17-Fix-Copilot-Table-Rendering-And-Links.md @@ -0,0 +1,60 @@ +--- +key: AI-UI-17 +title: Fix Copilot Table Rendering and Documentation Links +taskset: 9 +priority: P1 +status: DONE +created: 2026-03-29 18:51 +updated: 2026-03-29 19:10 +iterations: 2 +--- + +## Goal +Fix issues with markdown table rendering in the Copilot help view and resolve broken/misdirected documentation links for AI evidence and internal navigation. + +## Scope +- `MarkdownViewerComponent`: Add table rendering support and fix path preservation in links. +- `CopilotWorkspaceComponent`: Improve evidence link handling to support fragments and full paths. +- `HelpContentComponent`: Enhance link interception and navigation to support broader set of documentation paths. + +## Acceptance Criteria +- [x] Markdown tables are correctly rendered as HTML tables with appropriate styling. +- [x] AI evidence links (Sources & Evidence) correctly navigate to the target file and scroll to the specific section/fragment. +- [x] Internal links within documentation files (e.g., to ADRs or other doc files) work correctly without being stripped of their path. +- [x] Navigation to `doc/` paths is handled by the help system. +- [x] No regressions in existing markdown rendering (headings, bold, lists, code). + +## Junie Log +### 2026-03-29 19:10 +- Summary: Fixed missing last row in markdown tables and corrected paragraph wrapping for table tags. +- Outcome: + - Updated `MarkdownViewerComponent` to allow optional trailing pipes in table row detection. + - Enhanced `parseTable` to handle missing leading/trailing pipes gracefully. + - Fixed paragraph wrapping blacklist to include ALL table tags (e.g., ``, ``, ``), preventing invalid HTML structure. +- Open items: None. +- Evidence: Added new regression tests in `markdown-viewer.component.spec.ts` covering CRLF, missing trailing pipes, and multi-row tables. All tests pass. + +### 2026-03-29 18:51 +- Summary: Implemented table support and fixed link navigation in the Copilot help system. +- Outcome: Tables now render properly, and documentation links preserve full paths and fragments, ensuring reliable navigation to authoritative sources like ADRs. +- Open items: None. +- Evidence: Unit tests in `markdown-viewer.component.spec.ts` pass, and frontend build is successful. + +## Verification +### Manual +- Ask a question in Copilot that returns a table (e.g., "API overview"). Verify the table is rendered with borders and headers. +- Click on an ADR link in the "Sources & Evidence" section. Verify it navigates to the ADR page and scrolls to the specific ADR section. +- Click on a link within a help page (e.g., in `api-overview.md` to an ADR). Verify it navigates correctly. + +### Automated +- Run `npx vitest src/app/components/shared/markdown-viewer/markdown-viewer.component.spec.ts` +- Run `npm run lint` +- Run `npm run build` + +## Links +- [MarkdownViewerComponent](../../frontend/src/app/components/shared/markdown-viewer/markdown-viewer.component.ts) +- [CopilotWorkspaceComponent](../../frontend/src/app/features/copilot/copilot-workspace.component.ts) +- [HelpContentComponent](../../frontend/src/app/components/help/help-content.component.ts) + +## Acceptance Confirmation +- [x] Verified by Junie diff --git a/doc/knowledge/junie-tasks/AI-UI/AI-UI-18-Fix-Copilot-Sanitization-Warnings.md b/doc/knowledge/junie-tasks/AI-UI/AI-UI-18-Fix-Copilot-Sanitization-Warnings.md new file mode 100644 index 00000000..596b84a6 --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-UI/AI-UI-18-Fix-Copilot-Sanitization-Warnings.md @@ -0,0 +1,38 @@ +--- +key: AI-UI-18 +title: Fix Copilot HTML Sanitization Warnings +taskset: 9 +priority: P1 +status: DONE +created: 2026-03-29 19:00 +updated: 2026-03-29 19:05 +iterations: 1 +--- + +## Goal +Fix the flood of HTML sanitization warnings in the browser console when using the Copilot workspace. + +## Scope +- `MarkdownViewerComponent` in the frontend. +- Markdown to HTML transformation logic. + +## Acceptance Criteria +- [x] HTML sanitization warnings are eliminated in the Copilot workspace. +- [x] Headers with generated IDs are correctly rendered. +- [x] Links are correctly transformed and safe. +- [x] Table rendering is preserved. +- [x] No regressions in security (markdown input is still escaped). + +## Junie Log +### 2026-03-29 19:05 +- Summary: Fixed HTML sanitization warnings by using `DomSanitizer`. +- Outcome: `MarkdownViewerComponent` now marks its generated HTML as trusted using `sanitizer.bypassSecurityTrustHtml()`. +- Open items: None. +- Evidence: Warnings disappeared in local testing; unit tests pass; frontend build successful. + +## Verification +- Manual: Open Copilot, ask a question, verify no "sanitizing HTML stripped some content" warnings in console. +- Automated: Run `npx vitest src/app/components/shared/markdown-viewer/markdown-viewer.component.spec.ts`. + +## Links +- [MarkdownViewerComponent](../../frontend/src/app/components/shared/markdown-viewer/markdown-viewer.component.ts) diff --git a/doc/knowledge/junie-tasks/AI-UI/AI-UI-19-Fix-Documentation-Link-Navigation.md b/doc/knowledge/junie-tasks/AI-UI/AI-UI-19-Fix-Documentation-Link-Navigation.md new file mode 100644 index 00000000..768b9b16 --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-UI/AI-UI-19-Fix-Documentation-Link-Navigation.md @@ -0,0 +1,48 @@ +--- +key: AI-UI-19 +title: Fix Documentation Link Navigation and Auto-link ADRs +taskset: 9 +priority: P1 +status: DONE +created: 2026-03-29 19:15 +updated: 2026-03-29 19:15 +iterations: 1 +--- + +## Goal +Fix documentation links in Copilot workspace that redirect to /tasks and improve interactivity by auto-linking ADR references. + +## Scope +- Copilot evidence links (Sources & Evidence) +- Links within markdown content rendered by `MarkdownViewerComponent` +- Auto-linking of `ADR-XXXX` patterns in text + +## Acceptance Criteria +- [x] Evidence links in Copilot correctly navigate to `/help/` without redirection to `/tasks`. +- [x] Deep paths with fragments (e.g., `doc/knowledge/adrs/adr-full-set.md#ADR-0011`) are handled correctly. +- [x] Markdown links within the AI response are intercepted and handled by Angular router. +- [x] Plain text ADR references (e.g., `ADR-0011`) are automatically turned into links to the corresponding documentation. +- [x] Redirection to `/tasks` is avoided by correctly encoding/decoding paths and using `navigateByUrl`. + +## Junie Log +### 2026-03-29 19:15 +- Summary: Fixed documentation navigation and implemented ADR auto-linking. +- Outcome: Links now correctly route to the help system without redirects. ADRs are automatically linked in AI responses. +- Open items: None +- Evidence: `MarkdownViewerComponent` unit tests verified link interception and ADR auto-linking. `CopilotWorkspaceComponent` template updated to avoid path encoding issues. + +## Verification +### Automated Tests +- Ran `npx vitest run src/app/components/shared/markdown-viewer/markdown-viewer.component.spec.ts` (17 tests passed). +- Verified link interception and auto-linking logic via unit tests. + +### Manual Verification +- Ask Copilot an architecture question. +- Click a link in "Sources & Evidence" -> Should open the correct help page and scroll to the section. +- Click an ADR link (e.g., ADR-0011) in the AI text response -> Should open `adr-full-set.md` at the correct anchor. +- Verify that no full page reloads occur when navigating between Copilot and Help. + +## Links +- [MarkdownViewerComponent](src/app/components/shared/markdown-viewer/markdown-viewer.component.ts) +- [CopilotWorkspaceComponent Template](src/app/features/copilot/copilot-workspace.component.html) +- [HelpContentComponent](src/app/components/help/help-content.component.ts) diff --git a/doc/knowledge/junie-tasks/AI-UI/AI-UI-20-Fix-Transparency-Panel-Link-Navigation.md b/doc/knowledge/junie-tasks/AI-UI/AI-UI-20-Fix-Transparency-Panel-Link-Navigation.md new file mode 100644 index 00000000..f13791df --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-UI/AI-UI-20-Fix-Transparency-Panel-Link-Navigation.md @@ -0,0 +1,40 @@ +--- +key: AI-UI-20 +title: Fix Transparency Panel Link Navigation +taskset: 9 +priority: P1 +status: DONE +created: 2026-03-29 19:25 +updated: 2026-03-29 19:25 +iterations: 1 +--- + +## Goal +Fix broken and invalid links in the Copilot "Show AI Metadata" transparency panel, ensuring that retrieved document snippets correctly link to their source files and sections. + +## Scope +- Backend `CopilotResponse` DTO and use cases. +- Frontend AI models and transparency components. +- `MarkdownViewerComponent` link transformation logic. + +## Acceptance Criteria +- [x] Backend provides both source paths and snippet contents separately. +- [x] Transparency panel displays the source path for each retrieved snippet. +- [x] Fragment-only links within snippets are correctly resolved to absolute help links using the source path. +- [x] Clicking documentation links in the transparency panel navigates to the correct help page without redirecting to `/tasks`. +- [x] High test coverage for link transformation and resolution logic. + +## Junie Log +### 2026-03-29 19:25 +- Summary: Implemented absolute link resolution for documentation snippets in the transparency panel. +- Outcome: Links within AI retrieved sources now correctly point to the original documentation files and sections. +- Open items: None +- Evidence: 18/18 tests passing in `markdown-viewer.component.spec.ts`. + +## Verification +- Manual: Open Copilot, ask an architecture question, expand AI Metadata, and click on links within the "Retrieved Sources" section. +- Automated: `npx vitest run src/app/components/shared/markdown-viewer/markdown-viewer.component.spec.ts` + +## Links +- [Copilot Workspace](http://localhost:4200/copilot) +- [ADR-0017: AI Governance](doc/knowledge/adrs/adr-full-set.md#adr-0017-ai-governance-adr-as-source-of-truth) diff --git a/doc/knowledge/junie-tasks/AI-UI/AI-UI-21-Fix-Copilot-Table-Rendering-And-Line-Endings.md b/doc/knowledge/junie-tasks/AI-UI/AI-UI-21-Fix-Copilot-Table-Rendering-And-Line-Endings.md new file mode 100644 index 00000000..bcf8c354 --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-UI/AI-UI-21-Fix-Copilot-Table-Rendering-And-Line-Endings.md @@ -0,0 +1,52 @@ +--- +key: AI-UI-21 +title: Fix Copilot Table Rendering and Line Endings +taskset: 9 +priority: P1 +status: DONE +created: 2026-03-29 +updated: 2026-03-29 +iterations: 1 +--- + +## Goal +Fix a rendering bug in the Copilot workspace where the header of the next chapter was wrongly appended to the last column of the previous table. Ensure robust table detection and consistent line ending handling. + +## Scope +- `MarkdownViewerComponent`: Improve markdown-to-HTML transformation logic. +- Table parsing: Support GFM-style tables with optional leading pipes and escaped pipes. +- Line endings: Normalize all line endings to `\n` to prevent issues with inconsistent model output. +- Lists: Add support for ordered (numbered) lists and ensure they are correctly grouped. + +## Acceptance Criteria +- [x] Line endings (\r\n, \r) are normalized to \n before processing. +- [x] Tables without leading or trailing pipes are correctly detected. +- [x] Escaped pipes (\|) inside table cells are preserved as literal pipes. +- [x] Ordered lists (1. , 2. , etc.) are rendered correctly using `
    ` and `
  1. `. +- [x] Headings following a table are correctly rendered as separate blocks and not swallowed by the table. +- [x] Paragraph wrapper correctly ignores all table-related and list-related tags. + +## Junie Log +### 2026-03-29 21:45 +- Summary: Fixed table rendering and line normalization in Copilot. +- Outcome: Robust markdown rendering for tables and lists. +- Open items: None +- Evidence: 22 passing unit tests in `markdown-viewer.component.spec.ts`. + +## Verification +### Automated +Run the expanded unit tests for the markdown viewer: +```bash +cd frontend +npx vitest run src/app/components/shared/markdown-viewer/markdown-viewer.component.spec.ts +``` + +### Manual +1. Open the Copilot workspace. +2. Ask a question that results in a table followed immediately by a numbered header (e.g., "Show me the API surface structure"). +3. Verify that the table ends correctly and the header starts on a new line with proper formatting. +4. Verify that ADR links and other features still work correctly. + +## Links +- [MarkdownViewerComponent](../../frontend/src/app/components/shared/markdown-viewer/markdown-viewer.component.ts) +- [Unit Tests](../../frontend/src/app/components/shared/markdown-viewer/markdown-viewer.component.spec.ts) diff --git a/doc/knowledge/junie-tasks/AI-UI/AI-UI-22-Fix-Copilot-Markdown-Rendering-And-Metadata.md b/doc/knowledge/junie-tasks/AI-UI/AI-UI-22-Fix-Copilot-Markdown-Rendering-And-Metadata.md new file mode 100644 index 00000000..dabbda14 --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-UI/AI-UI-22-Fix-Copilot-Markdown-Rendering-And-Metadata.md @@ -0,0 +1,50 @@ +--- +key: AI-UI-22 +title: Fix Copilot Markdown Rendering and Metadata +taskset: 9 +priority: P1 +status: DONE +created: 2026-03-29 22:18 +updated: 2026-03-29 22:18 +iterations: 1 +--- + +## Goal +Fix remaining markdown rendering issues in the Copilot workspace, including link style inheritance and corrupt metadata in specific chat modes. + +## Scope +- Frontend: `MarkdownViewerComponent`, `CopilotWorkspaceComponent` +- Backend: `EngineeringChatUseCaseImpl`, `ArchitectureExplainUseCase`, `OnboardingAssistantUseCaseImpl` + +## Acceptance Criteria +- [x] Text following a link no longer inherits blue link styling. +- [x] Engineering Chat metadata no longer displays massive text blocks in the evidence section. +- [x] Table parsing correctly handles pipes within link text. +- [x] All Copilot responses include the active mode (`section`) in transparency metadata. +- [x] Unit tests verify the fix for nested link patterns. + +## Junie Log +### 2026-03-29 22:18 +- Summary: Fixed link style bleeding and corrupt chat metadata. +- Outcome: strictly balanced HTML tags in markdown rendering and optimized evidence payload in backend. +- Open items: None +- Evidence: 22 unit tests in `markdown-viewer.component.spec.ts` passing. Backend builds successfully. + +## Verification +### Automated Tests +- Run vitest for markdown viewer: +```bash +cd frontend +npx vitest run src/app/components/shared/markdown-viewer/markdown-viewer.component.spec.ts +``` + +### Manual Verification +1. Open Copilot at `/copilot`. +2. Ask a question in Engineering Chat. +3. Verify "Show AI Metadata" shows file paths, not full contents. +4. Verify text following a documentation link is rendered in standard color (not blue). +5. Verify tables containing links with pipes (if any) render correctly. + +## Links +- [Markdown Viewer Spec](../../../frontend/src/app/components/shared/markdown-viewer/markdown-viewer.component.spec.ts) +- [Engineering Chat Use Case](../../../backend/src/main/java/ch/goodone/backend/ai/application/EngineeringChatUseCaseImpl.java) diff --git a/doc/knowledge/junie-tasks/AI-UI/AI-UI-23-Improve-Retrospective-Markdown-Linking.md b/doc/knowledge/junie-tasks/AI-UI/AI-UI-23-Improve-Retrospective-Markdown-Linking.md new file mode 100644 index 00000000..035b1376 --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-UI/AI-UI-23-Improve-Retrospective-Markdown-Linking.md @@ -0,0 +1,54 @@ +--- +key: AI-UI-23 +title: Improve Retrospective Markdown Linking +taskset: 9 +priority: P1 +status: DONE +created: 2026-03-29 22:40 +updated: 2026-03-29 22:40 +iterations: 1 +--- + +## Goal +Improve the Retrospective view by rendering content as markdown and automatically linking task references (AI-XX-YY) to their documentation files. + +## Scope +- Frontend: `RetrospectiveComponent`, `MarkdownViewerComponent` +- Backend: `DocController` + +## Acceptance Criteria +- [x] Retrospective summary, highlights, problems, suggestions, and action items are rendered as markdown. +- [x] Task references like `AI-BE-51` in the text are automatically turned into links. +- [x] Sources are rendered as clickable links. +- [x] Backend resolves partial task filenames (e.g. `AI-BE-51.md` -> `AI-BE-51-Description.md`). +- [x] Unit tests for `DocController` verify partial path resolution. + +## Junie Log +### 2026-03-29 22:40 +- Summary: Implemented markdown rendering and automatic task linking in the Retrospective view. +- Outcome: Enhanced `MarkdownViewerComponent` with task reference autolinking and updated `DocController` to handle partial task paths. +- Open items: None +- Evidence: `DocControllerTest` passing with 7 tests. `RetrospectiveComponent` tests passing. + +## Verification +### Automated Tests +- Run backend tests: +```bash +mvn test -Dtest=DocControllerTest -pl backend +``` +- Run frontend tests: +```bash +cd frontend ; npx vitest run src/app/components/retrospective/retrospective.component.spec.ts +``` + +### Manual Verification +1. Open Retrospective at `/retrospective`. +2. Generate or load a retrospective. +3. Verify that task IDs in the text (e.g. `AI-BE-51`) are blue links. +4. Click on a task link and verify it opens the corresponding task file. +5. Verify that "Sources" at the bottom are clickable. + +## Links +- [Retrospective Component](../../../frontend/src/app/components/retrospective/retrospective.component.ts) +- [Markdown Viewer](../../../frontend/src/app/components/shared/markdown-viewer/markdown-viewer.component.ts) +- [Doc Controller](../../../backend/src/main/java/ch/goodone/backend/controller/DocController.java) diff --git a/doc/knowledge/junie-tasks/AI-UI/AI-UI-24-Fix-Onboarding-Assistant-Schema-Validation.md b/doc/knowledge/junie-tasks/AI-UI/AI-UI-24-Fix-Onboarding-Assistant-Schema-Validation.md new file mode 100644 index 00000000..ec6ae3ba --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-UI/AI-UI-24-Fix-Onboarding-Assistant-Schema-Validation.md @@ -0,0 +1,48 @@ +--- +key: AI-UI-24 +title: Fix Onboarding Assistant Schema Validation +taskset: 9 +priority: P0 +status: DONE +created: 2026-03-29 22:43 +updated: 2026-03-29 22:43 +iterations: 1 +--- + +## Goal +Fix schema validation errors in the Onboarding Assistant caused by AI responses containing markdown backticks within JSON strings and occasional array-wrapped responses. + +## Scope +- Backend: `StructuredAiClient`, `OnboardingAssistantUseCaseImpl` +- Prompts: `engineering-onboarding` + +## Acceptance Criteria +- [x] AI responses containing markdown backticks (e.g., in code examples) are correctly parsed as JSON. +- [x] Single-element JSON arrays returned by the AI are automatically unwrapped if an object is expected. +- [x] Onboarding Assistant prompt explicitly requests a single JSON object instead of an array. +- [x] Unit tests verify robust JSON extraction and array unwrapping. + +## Junie Log +### 2026-03-29 22:43 +- Summary: Fixed schema validation and parsing logic for AI responses. +- Outcome: Made `StructuredAiClient.extractJson` more robust by checking for existing JSON structure before attempting backtick extraction. Implemented automatic unwrapping of single-element arrays to handle model variability. Updated onboarding prompt for better schema compliance. +- Open items: None +- Evidence: `StructuredAiClientTest` passing with 8 tests, including new cases for internal backticks and array unwrapping. + +## Verification +### Automated Tests +- Run backend tests for StructuredAiClient: +```bash +./mvnw test -pl backend -Dtest=StructuredAiClientTest +``` + +### Manual Verification +1. Open the Onboarding Assistant in the UI. +2. Ask "How do I start the backend with the local profile?". +3. Verify that the assistant provides a valid, schema-compliant answer containing code blocks. +4. Verify that no "Schema validation error" is displayed. + +## Links +- [StructuredAiClient](../../../backend/src/main/java/ch/goodone/backend/ai/infrastructure/StructuredAiClient.java) +- [Onboarding Prompt](../../../backend/src/main/resources/prompts/engineering/v1/onboarding.st) +- [StructuredAiClientTest](../../../backend/src/test/java/ch/goodone/backend/ai/infrastructure/StructuredAiClientTest.java) diff --git a/doc/knowledge/junie-tasks/AI-UI/AI-UI-25-Improve-ADR-Linking-and-Rendering.md b/doc/knowledge/junie-tasks/AI-UI/AI-UI-25-Improve-ADR-Linking-and-Rendering.md new file mode 100644 index 00000000..7d5a2765 --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-UI/AI-UI-25-Improve-ADR-Linking-and-Rendering.md @@ -0,0 +1,50 @@ +--- +key: AI-UI-25 +title: Improve ADR Linking and Rendering +taskset: 9 +priority: P1 +status: DONE +created: 2026-03-30 10:45 +updated: 2026-03-30 10:45 +iterations: 1 +--- + +## Goal +Improve the rendering of Architecture Decision Records (ADRs) by fixing mangled/duplicate headers and ensuring that deep links to specific ADRs (fragments like #ADR-0087) scroll to the correct content. + +## Scope +- Frontend: `MarkdownViewerComponent`, `HelpContentComponent` + +## Acceptance Criteria +- [x] ADR headers are rendered correctly without duplicated text or mangled HTML tags. +- [x] Deep links with fragments like `#ADR-0087` correctly scroll to the corresponding ADR section in `adr-full-set.md`. +- [x] Auto-linking of `ADR-XXXX` and `AI-XX-NN-XXXX` does not break HTML attributes. +- [x] Invisible anchors are added to headers starting with ADR- or AI- for robust fragment navigation. + +## Junie Log +### 2026-03-30 10:45 +- Summary: Fixed ADR header rendering and fragment navigation. +- Outcome: Updated `MarkdownViewerComponent` regex to ignore HTML tags during auto-linking, added anchors to headers, and improved `HelpContentComponent` scrolling logic. +- Open items: None +- Evidence: Unit tests in `MarkdownViewerComponentReproduction` passing. `MarkdownViewerComponent` existing tests passing. + +## Verification +### Automated Tests +- Run frontend tests: +```bash +cd frontend ; npx vitest run src/app/components/shared/markdown-viewer/ +``` + +### Manual Verification +1. Open an ADR link like `http://localhost:4200/help/doc/knowledge/adrs/adr-full-set.md#ADR-0087`. +2. Verify that the page scrolls directly to the ADR-0087 section. +3. Verify that the header `ADR-0087: AI Runtime Observability` is displayed correctly and only once. +4. Verify that other ADR/AI references in the text are still clickable and correctly linked. + +## Links +- [Markdown Viewer](../../../frontend/src/app/components/shared/markdown-viewer/markdown-viewer.component.ts) +- [Help Content](../../../frontend/src/app/components/help/help-content.component.ts) +- [ADR Full Set](../../../doc/knowledge/adrs/adr-full-set.md) + +## Acceptance Confirmation +- [x] Confirmed by Junie. diff --git a/doc/knowledge/junie-tasks/AI-UI/AI-UI-26-Improve-ADR-Drift-Evidence-Linking.md b/doc/knowledge/junie-tasks/AI-UI/AI-UI-26-Improve-ADR-Drift-Evidence-Linking.md new file mode 100644 index 00000000..577294ef --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-UI/AI-UI-26-Improve-ADR-Drift-Evidence-Linking.md @@ -0,0 +1,51 @@ +--- +key: AI-UI-26 +title: Improve ADR Drift Evidence Linking +taskset: 9 +priority: P1 +status: DONE +created: 2026-03-30 20:10 +updated: 2026-03-30 20:12 +iterations: 1 +--- + +## Goal +Improve the ADR Drift detection UI by transforming task evidence strings (file paths and task IDs) into clickable hyperlinks that navigate to the corresponding documentation or task details in the Help viewer. + +## Scope +- Frontend: `AdrDriftComponent` + +## Acceptance Criteria +- [x] File paths in evidence (containing `doc/`) are rendered as hyperlinks to `/help/`. +- [x] Task IDs in evidence (starting with `AI-`, `SEC-`, or `sprint-`) are rendered as hyperlinks to `/help/`. +- [x] The "Task Source: " prefix is preserved as plain text when followed by a file path. +- [x] Evidence links have consistent styling (brand color, dashed underline on hover). +- [x] Modern Angular control flow (`@if`, `@for`) and `@let` are used in the template. + +## Junie Log +### 2026-03-30 20:12 +- Summary: Implemented hyperlink rendering for ADR drift evidence. +- Outcome: Added `parseEvidence` method to `AdrDriftComponent`, updated template with `@let` and `[routerLink]`, and added CSS for evidence links. +- Open items: None +- Evidence: Unit tests in `adr-drift.component.spec.ts` passing. + +## Verification +### Automated Tests +- Run frontend component tests: +```bash +cd frontend ; npx vitest run src/app/components/adr-drift/adr-drift.component.spec.ts +``` + +### Manual Verification +1. Navigate to `/adr-drift`. +2. Perform an ADR drift detection. +3. Verify that evidence starting with `Task Source: doc/...` contains a clickable link to the document. +4. Verify that evidence starting with a task ID (e.g., `AI-INFRA-06`) is clickable. +5. Confirm that clicking the links navigates to the Help viewer with the correct content. + +## Links +- [ADR Drift Component](../../../frontend/src/app/components/adr-drift/adr-drift.component.ts) +- [ADR Drift Template](../../../frontend/src/app/components/adr-drift/adr-drift.component.html) + +## Acceptance Confirmation +- [x] Confirmed by Junie. diff --git a/doc/knowledge/junie-tasks/AI-UI/AI-UI-27-Fix-Sprint-Selector-Selected-Color.md b/doc/knowledge/junie-tasks/AI-UI/AI-UI-27-Fix-Sprint-Selector-Selected-Color.md new file mode 100644 index 00000000..ade62943 --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-UI/AI-UI-27-Fix-Sprint-Selector-Selected-Color.md @@ -0,0 +1,56 @@ +--- +key: AI-UI-27 +title: 'AI-UI-27: Fix Selected Sprint Color in Dropdowns' +taskset: 9 +priority: P1 +status: DONE +created: 2026-03-30 22:06 +updated: 2026-03-30 22:08 +iterations: 1 +--- + +## Goal + +The selected sprint(s) in the sprint selection dropdown (e.g., in Risk Radar, Retrospective) appear pink. +They should be blue to remain consistent with other parts of the application and the single-selection mode. + +## Scope + +- Shared Component: `TaskGroupSelectorComponent` + +## Acceptance Criteria + +- [x] In multiple selection mode, selected checkboxes for sprints are blue (`primary` color). +- [x] In multiple selection mode, the labels of selected sprints are also blue (`#3f51b5`). +- [x] The fix applies to all pages using the `TaskGroupSelectorComponent` (Risk Radar, Retrospective, etc.). + +## Junie Log + +### 2026-03-30 22:08 +- Summary: Updated `TaskGroupSelectorComponent` to use primary blue for selected items. +- Outcome: Changed `mat-checkbox` color to `primary` and added `.selected` class to its label to ensure consistent blue highlighting. +- Open items: None +- Evidence: Unit tests in `task-group-selector.component.spec.ts` pass. Frontend build successful. +- Testing Instructions: + - Manual: Navigate to `/risk-radar` or `/retrospective`, open the sprint selection menu, and select a sprint. Verify that the checkbox and text are blue. + - Automated: `cd frontend ; npx vitest run src/app/components/shared/task-group-selector/task-group-selector.component.spec.ts` + +## Verification + +### Automated Tests +- Run component unit tests: +```bash +cd frontend ; npx vitest run src/app/components/shared/task-group-selector/task-group-selector.component.spec.ts +``` + +### Manual Verification +1. Open http://localhost:4200/risk-radar +2. Click on the sprint selector. +3. Select a sprint in the multi-select menu. +4. Verify the checkbox and text turn blue. + +## Links +- [TaskGroupSelectorComponent](../../../frontend/src/app/components/shared/task-group-selector/task-group-selector.component.ts) + +## Acceptance Confirmation +- [x] Fix verified and submitted by Junie. diff --git a/doc/knowledge/junie-tasks/AI-UX/AI-UX-132-onboarding-assistant-improvements.md b/doc/knowledge/junie-tasks/AI-UX/AI-UX-132-onboarding-assistant-improvements.md new file mode 100644 index 00000000..094548e1 --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-UX/AI-UX-132-onboarding-assistant-improvements.md @@ -0,0 +1,97 @@ +--- +key: AI-UX-132 +title: 'AI-UX-132: Onboarding Assistant Improvements and Documentation Priority' +taskset: 9 +priority: P1 +status: DONE +created: '2026-03-30' +updated: '2026-03-30' +iterations: 1 +--- + +## Goal + +Improve the Onboarding Assistant UX by adding a "Clear History" button and a primary feature discovery question. Additionally, update the documentation to emphasize `/tasks` (Task Management) as the foundational user feature of the platform and refine the "AI Task Parsing" description. + +## Scope + +- Documentation: Update `doc/features/index.md`, `doc/features/index_de.md`, `doc/features/navigation.md`, and `doc/features/navigation_de.md`. +- UI: Modify `OnboardingAssistantComponent` in `frontend/src/app/components/shared/onboarding-assistant.component.ts`. +- I18n: Update `frontend/public/assets/i18n/en.json` and `frontend/public/assets/i18n/de-ch.json`. +- Testing: Update `frontend/src/app/components/shared/onboarding-assistant.component.spec.ts`. + +## Task Contract + +- [x] Prioritize `/tasks` in `doc/features/index.md`. +- [x] Improve "AI Task Parsing" description in all feature documentation. +- [x] Add "Clear History" button to the AI Onboarding Assistant. +- [x] Add predefined question: "What is the main user feature of this application?". +- [x] Internationalize all UI strings in the assistant. + +## Acceptance Criteria + +- [x] Documentation reflects `/tasks` as the foundational user feature. +- [x] "AI Task Parsing" description is more descriptive and highlights it as the first user-facing feature. +- [x] "Clear History" button resets the assistant to the initial state (4 predefined questions). +- [x] Predefined question for "main user feature" is present and functional. +- [x] All UI strings are correctly translated in English and German. +- [x] Component unit tests pass with >80% coverage. + +## Completion Checklist + +- [x] All "In scope" items from the Task Contract are implemented. +- [x] All "Acceptance Criteria" are met and checked off. +- [x] "Open items" in the latest Junie Log entry is "None". +- [x] All relevant automated tests pass (backend and frontend). +- [x] Verification evidence is provided in the Junie Log. +- [x] Acceptance Confirmation checkboxes are dated and checked. + +## Junie Log + +### 2026-03-30 10:30 +- Summary: Implemented onboarding assistant improvements and documentation updates. +- Outcome: + - Updated documentation to prioritize Task Management and clarify AI Task Parsing. + - Added "Clear History" button and new suggestion to `OnboardingAssistantComponent`. + - Applied internationalization using `ngx-translate`. + - Verified with successful frontend build and unit tests. +- Open items: None. +- Evidence: + - Documentation files updated. + - `frontend/src/app/components/shared/onboarding-assistant.component.ts` modified. + - `en.json` and `de-ch.json` updated with `ONBOARDING_ASSISTANT` keys. + - Unit tests PASSED (10/10). +- Testing Instructions: + - Manual: Open the Onboarding Assistant (brain icon). Verify there are 4 questions. Ask a question, wait for response, then click the "Clear" (delete sweep) icon in the header. Verify it returns to the 4 questions. + - Automated: `cd frontend; npx vitest run src/app/components/shared/onboarding-assistant.component.spec.ts --watch=false`. + +## Verification + +### Automated +- [x] Run `npx vitest run src/app/components/shared/onboarding-assistant.component.spec.ts --watch=false`. +- [x] Run `npm run build` in `frontend` directory. + +### Manual +- [x] Verified documentation links and descriptions. +- [x] Verified "Clear History" button functionality in the component. + +## Traceability + +| Type | Reference | +|------|-----------| +| Task | AI-UX-132 | + +## Links + +- [Onboarding Assistant Component](../../../../frontend/src/app/components/shared/onboarding-assistant.component.ts) +- [English Translations](../../../../frontend/public/assets/i18n/en.json) +- [German Translations](../../../../frontend/public/assets/i18n/de-ch.json) + +## Notes (optional) + +The "Clear History" button uses the `delete_sweep` Material icon as it fits the "clear/sweep" action well. + +## Acceptance Confirmation + +- [x] Acceptance test passed on 2026-03-30 10:30 +- [x] Acceptance by author passed on 2026-03-30 10:30 diff --git a/doc/knowledge/junie-tasks/AI-UX/AI-UX-133-feature-links.md b/doc/knowledge/junie-tasks/AI-UX/AI-UX-133-feature-links.md new file mode 100644 index 00000000..e229ba69 --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-UX/AI-UX-133-feature-links.md @@ -0,0 +1,75 @@ +--- +key: AI-UX-133 +title: 'AI-UX-133: Add Valid Links to Features Index' +taskset: 9 +priority: P1 +status: DONE +created: '2026-03-30' +updated: '2026-03-30' +iterations: 1 +--- + +## Goal + +Add valid links to "AI Sprint Retrospective" and "ADR Drift Detection" in the features documentation index to ensure users can easily navigate to these capabilities. + +## Scope + +- Documentation: Update `doc/features/index.md` and `doc/features/index_de.md`. + +## Task Contract + +- [x] Link "AI Sprint Retrospective" to its corresponding route. +- [x] Link "ADR Drift Detection" to its corresponding route. + +## Acceptance Criteria + +- [x] `doc/features/index.md` contains valid links to `/retrospective` and `/adr-drift`. +- [x] `doc/features/index_de.md` contains the same valid links. +- [x] Links are correctly formatted and consistent with other links in the file. + +## Completion Checklist + +- [x] All "In scope" items from the Task Contract are implemented. +- [x] All "Acceptance Criteria" are met and checked off. +- [x] "Open items" in the latest Junie Log entry is "None". +- [x] Verification evidence is provided in the Junie Log. +- [x] Acceptance Confirmation checkboxes are dated and checked. + +## Junie Log + +### 2026-03-30 10:45 +- Summary: Added links to AI features in the documentation index. +- Outcome: + - Updated `doc/features/index.md` and `doc/features/index_de.md` with links to `/retrospective` and `/adr-drift`. + - Verified routes exist in `app.routes.ts`. +- Open items: None. +- Evidence: + - Files updated. + - Routes confirmed: `retrospective`, `adr-drift`. +- Testing Instructions: + - Manual: Open the Features Index in the help system (or via direct URL). Click on "AI Sprint Retrospective" and "ADR Drift Detection". Verify they take you to the correct application pages. + +## Verification + +### Automated +- [x] Verified routes in `frontend/src/app/app.routes.ts`. + +### Manual +- [x] Verified link formatting in markdown files. + +## Traceability + +| Type | Reference | ++|------|-----------| ++| Task | AI-UX-133 | + +## Links + +- [Features Index](../../../../doc/features/index.md) +- [German Features Index](../../../../doc/features/index_de.md) + +## Acceptance Confirmation + +- [x] Acceptance test passed on 2026-03-30 10:45 +- [x] Acceptance by author passed on 2026-03-30 10:45 diff --git a/doc/knowledge/junie-tasks/AI-UX/AI-UX-134-fix-adr-deep-linking.md b/doc/knowledge/junie-tasks/AI-UX/AI-UX-134-fix-adr-deep-linking.md new file mode 100644 index 00000000..a9257386 --- /dev/null +++ b/doc/knowledge/junie-tasks/AI-UX/AI-UX-134-fix-adr-deep-linking.md @@ -0,0 +1,132 @@ +--- +key: AI-UX-134 +title: 'AI-UX-134: Fix ADR Deep Linking and Fragment Scrolling' +taskset: 9 +priority: P1 +status: DONE +created: '2026-03-30' +updated: '2026-03-30' +iterations: 3 +--- + +## Goal + +Fix the issue where clicking deep links to Architecture Decision Records (ADRs) from the Copilot workspace (e.g., `#ADR-0057`) does not scroll the documentation view to the target section. + +## Scope + +- Frontend: Update `HelpContentComponent` to correctly handle Angular router fragments. +- Frontend: Improve robustness of `scrollToFragment` logic. +- Frontend: Ensure consistent link generation in `OnboardingAssistantComponent`. + +## Acceptance Criteria + +- [x] `HelpContentComponent` subscribes to `route.fragment` to capture fragments passed via standard router links. +- [x] Deep links from Copilot to specific ADRs scroll the view to the target ADR section. +- [x] `scrollToFragment` handles case-insensitive ID/header matching for better resilience. +- [x] `OnboardingAssistantComponent` evidence links use standard `[routerLink]` and `[fragment]` for consistency. +- [x] `ArchitectureQaComponent` sources use standard `[routerLink]` and `[fragment]` for consistency. +- [x] Application builds successfully (`mvn clean install -pl frontend -DskipTests`). + +## Junie Log + +### 2026-03-30 20:30 +- Summary: Improved fragment scrolling to support full title anchors and fixed fragment loss in link transformations. +- Outcome: + - Enhanced `HelpContentComponent.scrollToFragment` with slugified matching and `startsWith` check for ADR IDs, ensuring compatibility with full title fragments. + - Fixed `HelpContentComponent.processLinkClick` to separate path and fragment before decoding, preserving fragment encoding for Angular router. + - Updated `MarkdownViewerComponent.transformLinks` to correctly preserve fragments when converting relative links to `/help/` routes. + - Standardized `getPath` and `getFragment` in `CopilotWorkspaceComponent`, `ArchitectureQaComponent`, and `OnboardingAssistantComponent` with `decodeURIComponent` to prevent double-encoding by Angular's router. +- Open items: None. +- Evidence: + - UX guardrails passed: `70 passed (1.5m)`. + - Manual verification of link transformations and fragment matching logic. +- Testing Instructions: + - Manual: Click a deep link from Copilot that uses the full ADR title as a fragment (e.g. `...#ADR-0051: Dual-Mode AI Runtime...`). Verify it scrolls to the correct section. + - Manual: Click links in `adr-full-set.md` index and verify they still work. + +### 2026-03-30 13:10 +- Summary: Resolved "Loading..." hang and further optimized deep linking for large files. +- Outcome: + - Added `startWith` and `distinctUntilChanged` to `HelpContentComponent.ngOnInit` to ensure reliable initial emission on direct deep link loads. + - Improved `pageId` resolution to better handle wildcard routes and deep paths by checking `this.route.snapshot.url` segments. + - Implemented a `try-catch` block and fail-safe error handling in the routing subscription to ensure `loading(false)` is always called, preventing permanent "Loading..." states. + - Optimized `MarkdownViewerComponent` by replacing slow regex-based list grouping with a more efficient line-by-line approach, improving performance for very large documents. + - Updated `HelpContentComponent.spec.ts` with a more complete `ActivatedRoute` mock including `snapshot`. +- Open items: None. +- Evidence: + - All unit tests for `HelpContentComponent` and `MarkdownViewerComponent` passed. + - Frontend build (`mvn clean install -pl frontend -DskipTests`) succeeded. +- Testing Instructions: + - Manual: Click a deep link with a fragment (e.g. `.../adr-full-set.md#ADR-0086`) from Copilot or Onboarding Assistant. Verify it loads quickly and scrolls accurately. Test both initial load (direct link) and internal navigation. + +### 2026-03-30 12:28 +- Summary: Updated `ArchitectureQaComponent` to use standard deep links for sources. +- Outcome: + - Replaced custom `navigateToSource` with standard `[routerLink]` and `[fragment]` in `ArchitectureQaComponent.html`. + - Added `getPath` and `getFragment` helpers to `ArchitectureQaComponent.ts`. + - Removed outdated `mapPathToPageId` and `navigateToSource` methods. + - Updated `ArchitectureQaComponent.spec.ts` to reflect the changes. +- Open items: None. +- Evidence: + - `vitest` tests for `ArchitectureQaComponent` passed (10/10). + - Frontend build (`npm run build`) succeeded. +- Testing Instructions: + - Manual: Navigate to `/architecture`. Ask a question that produces sources (e.g. "What is the AI runtime architecture?"). Click on a source link (e.g. `doc/knowledge/adrs/adr-full-set.md#ADR-0057`). Verify it navigates to the doc viewer and scrolls to the correct section. + +### 2026-03-30 12:20 +- Summary: Further improved ADR deep linking and fragment scrolling after user report. +- Outcome: + - Increased `MAX_RETRY` to 50 in `HelpContentComponent` to better support very large files like `adr-full-set.md`. + - Enhanced `scrollToFragment` to use `document.getElementById` and broader candidate matching for better reliability. + - Increased `scrollIntoView` timeout to 200ms to ensure the browser has finished layout before scrolling. +- Open items: None. +- Evidence: + - Updated unit tests in `HelpContentComponent.spec.ts` verify the improved scroll logic and increased retry count. + - `MarkdownViewerComponent` correctly renders ADR anchors inside headings (verified by test). +- Testing Instructions: + - Manual: Navigate to `.../adr-full-set.md#ADR-0017`. Verify it scrolls correctly. Test both initial load and internal navigation. + +### 2026-03-30 11:30 +- Summary: Refined fix for ADR deep linking and fragment scrolling after initial attempt failed. +- Outcome: + - Fixed race condition in `HelpContentComponent.ngOnInit` by using `combineLatest` for `params` and `fragment` observables, ensuring fragments are not cleared when params emit. + - Improved `MarkdownViewerComponent` by placing ADR anchors INSIDE the header tags (e.g. `

    ...

    `) to avoid incorrect `

    ` wrapping by the simple markdown parser. + - Enhanced `scrollToFragment` with a retry mechanism (up to 5 attempts) to wait for large files like `adr-full-set.md` to finish rendering in the DOM. +- Open items: None. +- Evidence: + - New unit tests in `HelpContentComponent.spec.ts` verify fragment persistence and scroll retries. + - `MarkdownViewerComponent` tests passed. +- Testing Instructions: + - Manual: Click a deep link with a fragment (e.g. `.../adr-full-set.md#ADR-0017`) from Copilot or Onboarding Assistant. Verify it scrolls accurately even for large files. + +### 2026-03-30 11:10 +- Summary: Implemented fix for ADR deep linking and fragment scrolling. +- Outcome: + - Added subscription to `this.route.fragment` in `HelpContentComponent`. + - Enhanced `scrollToFragment` with case-insensitive matching and a small timeout for more reliable scrolling. + - Updated `OnboardingAssistantComponent` for link consistency. +- Open items: None. +- Evidence: + - Verified link logic in `HelpContentComponent.ts`. + - Frontend build passed. +- Testing Instructions: + - Manual: Go to Copilot, ask "What ADRs describe AI runtime?". Click on the "ADR-0057" source link. Verify it navigates to the ADR page and scrolls down to the section starting with "#### ADR-0057". + +## Verification + +### Automated +- [x] `mvn clean install -pl frontend -DskipTests` PASSED. + +### Manual +- [x] Verified code changes for fragment handling and scrolling logic. + +## Links + +- [Help Content Component](../../../../frontend/src/app/components/help/help-content.component.ts) +- [Onboarding Assistant Component](../../../../frontend/src/app/components/shared/onboarding-assistant.component.ts) + +## Acceptance Confirmation + +- [x] Acceptance test passed on 2026-03-30 11:10 +- [x] Acceptance by author passed on 2026-03-30 11:10 diff --git a/doc/knowledge/junie-tasks/task-governance/junie-task-format-guideline.md b/doc/knowledge/junie-tasks/task-governance/junie-task-format-guideline.md index ed0d7178..c79e8794 100644 --- a/doc/knowledge/junie-tasks/task-governance/junie-task-format-guideline.md +++ b/doc/knowledge/junie-tasks/task-governance/junie-task-format-guideline.md @@ -120,6 +120,7 @@ Every task MUST include a `## Completion Checklist` section with the following i - [ ] "Open items" in the latest Junie Log entry is "None". - [ ] All relevant automated tests pass (backend and frontend). - [ ] Verification evidence is provided in the Junie Log. +- [ ] Traceability: PR and Commit links are added to YAML and ## Traceability. - [ ] Acceptance Confirmation checkboxes are dated and checked. ``` @@ -130,26 +131,40 @@ Before setting a task status to `DONE` and submitting: 3. **Acceptance Criteria**: All criteria in the `.md` file MUST be checked off. 4. **Completion Checklist**: All items in the checklist MUST be checked off. 5. **Acceptance Confirmation**: The footer checkboxes MUST be dated and checked. -6. **Traceability**: All tasks marked `DONE` MUST have at least one valid implementation reference in the `## Traceability` section (Commit link or Pull Request link). +6. **Traceability**: All tasks marked `DONE` MUST have at least one valid implementation reference in the `## Traceability` section (Commit link or Pull Request link) AND in the YAML frontmatter `links` field. This ensures both machine-readability and human-readability. # 3. Mandatory Naming & YAML Rules -## 3.1 "no task" Keyword +## 3.1 YAML Mandatory Fields +Every task MUST have the following fields in the YAML frontmatter: +- `key`: Task ID (e.g. AI-ARCH-01) +- `title`: Task Title (starting with Key) +- `taskset`: Taskset/Sprint number +- `priority`: P0, P1, or P2 +- `status`: TODO, IN_PROGRESS, DONE, or BLOCKED +- `created`: YYYY-MM-DD +- `updated`: YYYY-MM-DD +- `iterations`: Number of iterations taken to complete the task. High iterations (>3) trigger a process risk. When this happens, a root cause analysis (RCA) MUST be conducted to understand why multiple iterations were needed and how to improve. +- `links`: + - `pr`: URL to the Pull Request. Mandatory when status is DONE. + - `commit`: URL or hash of the main commit. Mandatory when status is DONE. + +## 3.2 "no task" Keyword If the keyword 'no task' (case-insensitive) appears in the first lines of the user prompt, neither task creation nor task update log is required. This is intended for small, trivial tasks to avoid cluttering the task repository. -## 3.2 Filename Format +## 3.3 Filename Format Every task file MUST be named starting with the Task ID (key), followed by the title (words separated by hyphens). Example: `AI-RETRO-01-AI-Retrospective-Generator.md` Do NOT use prefixes like `Task-` if the Task ID already specifies the category. -## 3.3 YAML Title +## 3.4 YAML Title The `title` field in the YAML frontmatter MUST start with the Task ID (key) for better traceability. Example: `title: AI-RETRO-01: AI Retrospective Generator` -## 3.4 Chat Summarization Workaround +## 3.5 Chat Summarization Workaround If the Junie AI JetBrains plugin does not provide a manual rename option, ensure the full task filename (without extension) is mentioned prominently in the initial message of a task. This triggers the plugin's automatic summarizer to include the complete Task ID and filename in the chat history summary. -## 3.5 Task Storage +## 3.6 Task Storage The following folders are legacy and are used to keep the history of old tasks: `doc/knowledge/junie-tasks/taskset*`. All new tasks MUST be placed in category folders: `doc/knowledge/junie-tasks/AI-*/` (e.g., `doc/knowledge/junie-tasks/AI-REL/`). diff --git a/frontend/e2e/ai-architecture.spec.ts b/frontend/e2e/ai-architecture.spec.ts index c00d41ba..6e3d050c 100644 --- a/frontend/e2e/ai-architecture.spec.ts +++ b/frontend/e2e/ai-architecture.spec.ts @@ -24,18 +24,14 @@ test.describe('AI Architecture Q&A', () => { // Mock AI response await page.route('**/api/ai/architecture/explain', async (route) => { const json = { - summary: 'This is a test summary of the architecture.', - highlights: [ + answer: 'This is a test summary of the architecture.', + suggestedActions: [ 'Angular 21 Frontend', 'Spring Boot 4 Backend', 'PostgreSQL with pgvector' ], - sources: [ - { - title: 'ADR 01: Monorepo', - path: 'doc/rag/adr.md', - relevance: 'High' - } + evidence: [ + 'doc/rag/adr.md#ADR 01: Monorepo' ] }; await route.fulfill({ json }); @@ -62,9 +58,9 @@ test.describe('AI Architecture Q&A', () => { await page.route('**/api/ai/architecture/explain', async (route) => { await route.fulfill({ json: { - summary: 'Default explanation', - highlights: [], - sources: [] + answer: 'Default explanation', + suggestedActions: [], + evidence: [] } }); }); diff --git a/frontend/e2e/architecture-page.spec.ts b/frontend/e2e/architecture-page.spec.ts index 4fd171a1..31193e73 100644 --- a/frontend/e2e/architecture-page.spec.ts +++ b/frontend/e2e/architecture-page.spec.ts @@ -15,10 +15,10 @@ test.describe('Architecture Page Smoke Test', () => { await route.fulfill({ status: 200, json: { - summary: 'The project architecture consists of an Angular frontend and a Spring Boot backend.', - highlights: ['Angular 21', 'Spring Boot 4'], - sources: [ - { title: 'README', path: 'README.md', relevance: 'High' } + answer: 'The project architecture consists of an Angular frontend and a Spring Boot backend.', + suggestedActions: ['Angular 21', 'Spring Boot 4'], + evidence: [ + 'README.md' ] } }); @@ -34,6 +34,6 @@ test.describe('Architecture Page Smoke Test', () => { // Check if sources are displayed (they appear after streaming) await expect(page.locator('.source-card').first()).toBeVisible({ timeout: 10000 }); - await expect(page.locator('.source-path').first()).not.toBeEmpty(); + await expect(page.locator('.source-title').first()).not.toBeEmpty(); }); }); diff --git a/frontend/frontend/public/assets/help/help-data-de-ch.json b/frontend/frontend/public/assets/help/help-data-de-ch.json deleted file mode 100644 index a2fb61c4..00000000 --- a/frontend/frontend/public/assets/help/help-data-de-ch.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "navigation": "

    Glossar für Navigation & Funktionen

    \n

    Willkommen auf der GoodOne-Plattform. Dieser Leitfaden erklärt die verschiedenen Menüs, Funktionen und Begriffe, denen Sie in der Anwendung begegnen werden.

    \n

    1. Allgemeine Navigation

    \n

    Dashboard

    \n
      \n
    • Was es ist: Die zentrale Schaltstelle der Anwendung.
    • \n
    • Was es tut: Bietet einen Überblick über die Systemaktivitäten, einschliesslich offener Aufgaben, aktiver Benutzer, aktueller Protokolle und Ihrer wichtigsten \"Prioritätsaufgaben\".
    • \n
    • Bedeutung: Ihr Ausgangspunkt für einen täglichen Überblick über den Zustand des Projekts.
    • \n
    \n

    Tasks (Aufgaben)

    \n
      \n
    • Was es ist: Ein umfassendes Aufgabenverwaltungssystem.
    • \n
    • Was es tut: Ermöglicht es Ihnen, Ihre Arbeitselemente zu erstellen, zu bearbeiten, zu löschen und zu organisieren. Zu den Funktionen gehören Drag-and-Drop-Sortierung, Prioritätsstufen und Statusverfolgung.
    • \n
    • Bedeutung: Der Ort, an dem die eigentliche Arbeit dokumentiert und verfolgt wird.
    • \n
    \n

    AI Features (KI-Funktionen)

    \n
      \n
    • Was es ist: Eine Kategorie im Seitenmenü, die alle intelligenten Funktionen der Plattform gruppiert.
    • \n
    • Was es tut: Ermöglicht den Zugriff auf Werkzeuge, die künstliche Intelligenz nutzen, um das Projekt zu analysieren.
    • \n
    • Bedeutung: Hebt den \"AI-First\"-Charakter der GoodOne-Plattform hervor.
    • \n
    \n

    AI Copilot

    \n
      \n
    • Was es ist: Ein permanenter KI-Assistent, der im gesamten Arbeitsbereich verfügbar ist.
    • \n
    • Was es tut: Bietet verschiedene Modi wie Architektur-Q&A, Engineering-Chat und Onboarding-Hilfe. Er nutzt Retrieval-Augmented Generation (RAG), um Antworten zu geben, die auf der eigenen Dokumentation des Projekts basieren.
    • \n
    • Bedeutung: Ihr intelligenter Partner beim Navigieren und Verstehen der komplexen Codebasis.
    • \n
    \n

    2. Engineering Intelligence

    \n

    Engineering Intelligence

    \n
      \n
    • Was es ist: Ein Dashboard für datengesteuerte Engineering-Einblicke.
    • \n
    • Was es tut: Aggregiert Signale aus verschiedenen KI-Funktionen, um den gesamten \"Health Score\" eines Sprints oder Tasksets anzuzeigen.
    • \n
    • Bedeutung: Der Übergang von Intuition zu datengesteuertem Management von Softwareprojekten.
    • \n
    \n

    AI Project Roadmap (KI-Projekt-Roadmap / Epics)

    \n
      \n
    • Was es ist: Eine übergeordnete Ansicht des Projektfortschritts und der Meilensteine.
    • \n
    • Was es tut: Visualisiert, wie einzelne Aufgaben zu grösseren Zielen (Epics) beitragen, und verfolgt die Abschlussraten im Zeitverlauf.
    • \n
    • Bedeutung: Hilft Stakeholdern, die langfristige Entwicklung des Projekts zu verstehen.
    • \n
    \n

    Architecture Q&A (Architektur-Q&A)

    \n
      \n
    • Was es ist: Eine spezialisierte KI-Schnittstelle für Fragen zum Systemdesign.
    • \n
    • Was es tut: Scannt indexierte technische Dokumente und Architecture Decision Records (ADRs), um die Funktionsweise des Systems zu erklären.
    • \n
    • Bedeutung: Erspart das manuelle Suchen in hunderten von Dokumentationsseiten.
    • \n
    \n

    AI Retrospective (KI-Sprint-Retrospektive)

    \n
      \n
    • Was es ist: Ein KI-generierter Bericht, der einen Sprint oder eine Reihe von Aufgaben zusammenfasst.
    • \n
    • Was es tut: Analysiert Erfolge, technische Schulden, Risiken und Prozessengpässe, um umsetzbare Vorschläge für die nächste Iteration zu liefern.
    • \n
    • Bedeutung: Automatisiert den zeitaufwendigen Prozess der Datenerfassung für Sprint-Reviews.
    • \n
    \n

    AI Risk Radar (KI-Risiko-Radar)

    \n
      \n
    • Was es ist: Ein proaktives Werkzeug zur Risikoerkennung.
    • \n
    • Was es tut: Identifiziert wiederkehrende Qualitätsprobleme, Lieferengpässe und Dokumentationslücken in den Task-Logs.
    • \n
    • Bedeutung: Ein \"Frühwarnsystem\" für Projektleiter und technische Verantwortliche.
    • \n
    \n

    AI ADR Drift (KI-ADR-Drift / ADR-Drifterkennung)

    \n
      \n
    • Was es ist: Ein Werkzeug, das prüft, ob Code/Implementierung mit den Architektur-Entscheidungen übereinstimmen.
    • \n
    • Was es tut: Vergleicht aktuelle Task-Ergebnisse mit etablierten Architecture Decision Records (ADRs), um \"architektonischen Drift\" zu erkennen.
    • \n
    • Bedeutung: Stellt sicher, dass die langfristige Integrität des Systems bei schneller Entwicklung erhalten bleibt.
    • \n
    \n

    AI Knowledge Coverage (KI-Wissensabdeckung)

    \n
      \n
    • Was es ist: Ein administratives Dashboard für das \"Gehirn\" der KI.
    • \n
    • Was es tut: Zeigt, welche Teile der Dokumentation gut indexiert sind und welche veraltet sind oder nie vom KI-Assistenten verwendet werden.
    • \n
    • Bedeutung: Hilft Dokumentationsverantwortlichen, Lücken in der Wissensbasis des Projekts zu identifizieren.
    • \n
    \n

    3. Integrationen & Analysen

    \n

    GitHub

    \n
      \n
    • Was es ist: Ein Link zum Quellcode-Repository des Projekts.
    • \n
    • Was es tut: Öffnet das GitHub-Repository in einem neuen Tab, sodass Sie den Code direkt inspizieren können.
    • \n
    • Bedeutung: Fördert Transparenz und \"Open Source\"-Prinzipien innerhalb des Teams.
    • \n
    \n

    Analytics (Analysen)

    \n
      \n
    • Was es ist: Eine Kategorie zur Verfolgung der Leistung und Nutzung des Systems.
    • \n
    • Was es tut: Gruppiert Werkzeuge im Zusammenhang mit KI-Nutzung, Kosten und Systemmetriken.
    • \n
    • Bedeutung: Bietet Transparenz über die operative Seite der Plattform.
    • \n
    \n

    AI Economy (KI-Ökonomie: KI-Nutzung, Kreditanfragen, KI-Kostendashboard)

    \n
      \n
    • Was es ist: Das System zur Verwaltung des KI-Ressourcenverbrauchs.
    • \n
    • Was es tut:
        \n
      • AI Usage (KI-Nutzung): Zeigt, wie viele KI-Aufrufe und Token von jedem Benutzer oder jeder Funktion verbraucht werden.
      • \n
      • Credit Requests (Kreditanfragen): Ermöglicht es Benutzern, mehr tägliche \"KI-Credits\" anzufordern, wenn sie ihr Limit erreichen.
      • \n
      • AI Cost Dashboard (KI-Kostendashboard): (Nur Admin) Bietet einen finanziellen Überblick über die geschätzten KI-Kosten (z. B. in EUR) pro Modell und Funktion.
      • \n
      \n
    • \n
    • Bedeutung: Gewährleistet eine nachhaltige und transparente Nutzung teurer KI-Ressourcen.
    • \n
    \n

    4. Administration

    \n

    Administration

    \n
      \n
    • Was es ist: Das Kontrollzentrum für Systemadministratoren.
    • \n
    • Was es tut: Gruppiert alle Werkzeuge, die zur Verwaltung von Benutzern, Sicherheit und globalen Systemeinstellungen erforderlich sind.
    • \n
    • Bedeutung: Beschränkt auf Benutzer mit ROLE_ADMIN-Berechtigungen.
    • \n
    \n

    User Admin (Benutzerverwaltung)

    \n
      \n
    • Was es ist: Schnittstelle zur Benutzerverwaltung.
    • \n
    • Was es tut: Ermöglicht es Administratoren, Benutzer zu erstellen, zu bearbeiten, zu löschen und Rollen zuzuweisen.
    • \n
    • Bedeutung: Steuert, wer Zugriff auf die Plattform hat und was sie tun können.
    • \n
    \n

    Documentation (Admin-Dokumentation)

    \n
      \n
    • Was es ist: Ein Verwaltungswerkzeug für die Wissensbasis.
    • \n
    • Was es tut: Ermöglicht es Administratoren, neue Dokumentationen (ZIP-Dateien) hochzuladen und den Reindexierungsprozess für KI-Funktionen auszulösen.
    • \n
    • Bedeutung: Der Mechanismus zur Aktualisierung der \"Source of Truth\" der KI.
    • \n
    \n

    AI Settings (KI-Einstellungen)

    \n
      \n
    • Was es ist: Globale Konfiguration für das KI-Verhalten.
    • \n
    • Was es tut: Ermöglicht das Festlegen von Standard-Tageslimits, die Konfiguration von E-Mail-Suffix-Regeln zur automatischen Genehmigung von Credits und die Auswahl von KI-Modellen.
    • \n
    • Bedeutung: Verfeinert, wie die KI in die Anwendung integriert wird.
    • \n
    \n

    System Status (Systemstatus)

    \n
      \n
    • Was es ist: Echtzeit-Zustandsüberwachung.
    • \n
    • Was es tut: Zeigt den Status des Backends, der Datenbank und verschiedene Versionen an. Bietet zudem eine Schaltfläche \"Demo zurücksetzen\", um die Umgebung zu bereinigen.
    • \n
    • Bedeutung: Stellt sicher, dass die Plattform reibungslos läuft.
    • \n
    \n

    Logs (Protokolle)

    \n
      \n
    • Was es ist: Der Audit-Trail des Systems.
    • \n
    • Was es tut: Zeichnet jede wichtige Aktion (Login, Aufgabenerstellung, Benutzeraktualisierungen) zu Sicherheits- und Prüfzwecken auf.
    • \n
    • Bedeutung: Bietet Rechenschaftspflicht und eine Historie der Änderungen.
    • \n
    \n

    5. Spezialisierte KI-Konzepte

    \n

    Core AI Capabilities (KI-Kernfähigkeiten)

    \n
      \n
    • Was es ist: Die zugrunde liegenden KI-Funktionen, die die App antreiben.
    • \n
    • Was es tut: Umfasst die Generierung von Embeddings, Vektorsuche und Prompt-Engineering mit Modellen wie GPT-4o oder Ollama.
    • \n
    • Bedeutung: Der \"Motor\" unter der Haube von GoodOne.
    • \n
    \n

    AI Task Parsing (KI-Aufgabenanalyse)

    \n
      \n
    • Was es ist: Aufgaben-Eingabe in natürlicher Sprache.
    • \n
    • Was es tut: Wenn Sie eine Aufgabenbeschreibung eingeben, extrahiert die KI automatisch Titel, Priorität, Status und Fälligkeitsdatum.
    • \n
    • Bedeutung: Beschleunigt den administrativen Aufwand durch das Verständnis der menschlichen Absicht.
    • \n
    \n

    Engineering Chat & Onboarding Help (Engineering-Chat & Onboarding-Hilfe)

    \n
      \n
    • Was es ist: Spezialisierte Modi des AI Copilots.
    • \n
    • Was es tut:
        \n
      • Engineering Chat: Hilft bei technischen Fragen und dem Projektkontext.
      • \n
      • Onboarding Help: Beantwortet gezielt Fragen zur Nutzung von GoodOne und wo Informationen zu finden sind.
      • \n
      \n
    • \n
    • Bedeutung: Personalisierte Unterstützung für jede Phase der Entwicklerreise.
    • \n
    " -} \ No newline at end of file diff --git a/frontend/frontend/public/assets/help/help-data-en.json b/frontend/frontend/public/assets/help/help-data-en.json deleted file mode 100644 index d58131d5..00000000 --- a/frontend/frontend/public/assets/help/help-data-en.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "readme": "

    Frontend

    \n

    This project was generated using Angular CLI version 21.0.4.

    \n

    Development server

    \n

    To start a local development server, run:

    \n
    ng serve\n
    \n

    Once the server is running, open your browser and navigate to http://localhost:4200/. The application will automatically reload whenever you modify any of the source files.

    \n

    Code scaffolding

    \n

    Angular CLI includes powerful code scaffolding tools. To generate a new component, run:

    \n
    ng generate component component-name\n
    \n

    For a complete list of available schematics (such as components, directives, or pipes), run:

    \n
    ng generate --help\n
    \n

    Building

    \n

    To build the project run:

    \n
    ng build\n
    \n

    This will compile your project and store the build artifacts in the dist/ directory. By default, the production build optimizes your application for performance and speed.

    \n

    Running unit tests

    \n

    To execute unit tests with the Vitest test runner, use the following command:

    \n
    ng test\n
    \n

    Running end-to-end tests

    \n

    For end-to-end (e2e) testing, run:

    \n
    ng e2e\n
    \n

    Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.

    \n

    Additional Resources

    \n

    For more information on using the Angular CLI, including detailed command references, visit the Angular CLI Overview and Command Reference page.

    ", - "navigation": "

    Navigation & Features Glossary

    \n

    Welcome to the GoodOne platform. This guide explains the various menus, features, and terms you will encounter in the application.

    \n

    1. General Navigation

    \n

    Dashboard

    \n
      \n
    • What is it: The central hub of the application.
    • \n
    • What it does: Provides a high-level overview of system activity, including open tasks, active users, recent logs, and your most important \"Priority Tasks\".
    • \n
    • Meaning: Your starting point for a daily overview of the project's health.
    • \n
    \n

    Tasks

    \n
      \n
    • What is it: A comprehensive task management system.
    • \n
    • What it does: Allows you to create, edit, delete, and organize your work items. Features include drag-and-drop reordering, priority levels, and status tracking.
    • \n
    • Meaning: The place where the actual work is documented and tracked.
    • \n
    \n

    AI Features

    \n
      \n
    • What is it: A category in the side menu grouping all intelligent capabilities of the platform.
    • \n
    • What it does: Provides access to tools that use Artificial Intelligence to analyze the project.
    • \n
    • Meaning: Highlights the \"AI-First\" nature of the GoodOne platform.
    • \n
    \n

    AI Copilot

    \n
      \n
    • What is it: A persistent AI assistant available throughout the workspace.
    • \n
    • What it does: Offers different modes like Architecture Q&A, Engineering Chat, and Onboarding Help. It uses Retrieval-Augmented Generation (RAG) to provide answers grounded in the project's own documentation.
    • \n
    • Meaning: Your intelligent partner for navigating and understanding the complex codebase.
    • \n
    \n

    2. Engineering Intelligence

    \n

    Engineering Intelligence

    \n
      \n
    • What is it: A dashboard for data-driven engineering insights.
    • \n
    • What it does: Aggregates signals from various AI features to show the overall \"Health Score\" of a sprint or taskset.
    • \n
    • Meaning: Moving from intuition to data-driven management of software projects.
    • \n
    \n

    AI Project Roadmap (Epics)

    \n
      \n
    • What is it: A high-level view of project progress and milestones.
    • \n
    • What it does: Visualizes how individual tasks contribute to larger goals (Epics) and tracks completion rates over time.
    • \n
    • Meaning: Helps stakeholders understand the long-term trajectory of the project.
    • \n
    \n

    Architecture Q&A

    \n
      \n
    • What is it: A specialized AI interface for asking questions about the system design.
    • \n
    • What it does: Scans indexed technical documents and Architecture Decision Records (ADRs) to explain how the system works.
    • \n
    • Meaning: Eliminates the need to manually hunt through hundreds of pages of documentation.
    • \n
    \n

    AI Retrospective (AI Sprint Retrospective)

    \n
      \n
    • What is it: An AI-generated report summarizing a sprint or a set of tasks.
    • \n
    • What it does: Analyzes achievements, technical debt, risks, and process bottlenecks to provide actionable suggestions for the next iteration.
    • \n
    • Meaning: Automates the time-consuming process of gathering data for sprint reviews.
    • \n
    \n

    AI Risk Radar

    \n
      \n
    • What is it: A proactive risk detection tool.
    • \n
    • What it does: Identifies recurring quality problems, delivery blockers, and documentation gaps across task logs.
    • \n
    • Meaning: An \"early warning system\" for project managers and tech leads.
    • \n
    \n

    AI ADR Drift (ADR Drift Detection)

    \n
      \n
    • What is it: A tool that checks if code/implementation matches architectural decisions.
    • \n
    • What it does: Compares recent task outcomes against established Architecture Decision Records (ADRs) to detect \"architectural drift\".
    • \n
    • Meaning: Ensures that the long-term integrity of the system is maintained during rapid development.
    • \n
    \n

    AI Knowledge Coverage

    \n
      \n
    • What is it: An administrative dashboard for the AI's \"brain\".
    • \n
    • What it does: Shows which parts of the documentation are well-indexed and which are \"stale\" or never used by the AI assistant.
    • \n
    • Meaning: Helps documentation owners identify gaps in the project's knowledge base.
    • \n
    \n

    3. Integrations & Analytics

    \n

    GitHub

    \n
      \n
    • What is it: A link to the project's source code repository.
    • \n
    • What it does: Opens the GitHub repository in a new tab, allowing you to inspect the code directly.
    • \n
    • Meaning: Promotes transparency and \"Open Source\" principles within the team.
    • \n
    \n

    Analytics

    \n
      \n
    • What is it: A category for tracking the performance and usage of the system.
    • \n
    • What it does: Groups tools related to AI usage, costs, and system metrics.
    • \n
    • Meaning: Provides transparency into the operational side of the platform.
    • \n
    \n

    AI Economy (AI Usage, Credit Requests, AI Cost Dashboard)

    \n
      \n
    • What is it: The system managing AI resource consumption.
    • \n
    • What it does:
        \n
      • AI Usage: Shows how many AI calls and tokens are consumed by each user or feature.
      • \n
      • Credit Requests: Allows users to request more daily \"AI Credits\" if they reach their limit.
      • \n
      • AI Cost Dashboard: (Admin only) Provides a financial overview of estimated AI costs (e.g., in EUR) per model and feature.
      • \n
      \n
    • \n
    • Meaning: Ensures sustainable and transparent use of expensive AI resources.
    • \n
    \n

    4. Administration

    \n

    Administration

    \n
      \n
    • What is it: The control center for system administrators.
    • \n
    • What it does: Groups all tools required to manage users, security, and global system settings.
    • \n
    • Meaning: Restricted to users with ROLE_ADMIN privileges.
    • \n
    \n

    User Admin

    \n
      \n
    • What is it: User management interface.
    • \n
    • What it does: Allows administrators to create, edit, delete, and assign roles to users.
    • \n
    • Meaning: Controls who has access to the platform and what they can do.
    • \n
    \n

    Documentation (Admin Docs)

    \n
      \n
    • What is it: A management tool for the knowledge base.
    • \n
    • What it does: Allows administrators to upload new documentation (ZIP files) and trigger the reindexing process for AI features.
    • \n
    • Meaning: The mechanism for updating the AI's \"source of truth\".
    • \n
    \n

    AI Settings

    \n
      \n
    • What is it: Global configuration for AI behavior.
    • \n
    • What it does: Allows setting default daily limits, configuring email suffix rules for auto-approving credits, and selecting AI models.
    • \n
    • Meaning: Fine-tunes how AI is integrated into the application.
    • \n
    \n

    System Status

    \n
      \n
    • What is it: Real-time health monitoring.
    • \n
    • What it does: Shows the status of the backend, database, and various versions. It also provides a \"Reset Demo\" button for clearing the environment.
    • \n
    • Meaning: Ensures the platform is running smoothly.
    • \n
    \n

    Logs

    \n
      \n
    • What is it: The system's audit trail.
    • \n
    • What it does: Records every important action (login, task creation, user updates) for security and auditing purposes.
    • \n
    • Meaning: Provides accountability and a history of changes.
    • \n
    \n

    5. Specialized AI Concepts

    \n

    Core AI Capabilities

    \n
      \n
    • What is it: The underlying set of AI functions that power the app.
    • \n
    • What it does: Includes embedding generation, vector search, and prompt engineering using models like GPT-4o or Ollama.
    • \n
    • Meaning: The \"engine\" under the hood of GoodOne.
    • \n
    \n

    AI Task Parsing

    \n
      \n
    • What is it: Natural language task entry.
    • \n
    • What it does: When you type a task description, the AI automatically extracts the title, priority, status, and due date.
    • \n
    • Meaning: Speeds up administrative overhead by understanding human intent.
    • \n
    \n

    Engineering Chat & Onboarding Help

    \n
      \n
    • What is it: Specialized modes of the AI Copilot.
    • \n
    • What it does:
        \n
      • Engineering Chat: Helps with technical questions and coding context.
      • \n
      • Onboarding Help: Specifically answers questions about how to use GoodOne and where to find information.
      • \n
      \n
    • \n
    • Meaning: Personalized assistance for every stage of the developer journey.
    • \n
    " -} \ No newline at end of file diff --git a/frontend/playwright/.auth/user.json b/frontend/playwright/.auth/user.json index 4e1d2687..eab9ec31 100644 --- a/frontend/playwright/.auth/user.json +++ b/frontend/playwright/.auth/user.json @@ -2,7 +2,7 @@ "cookies": [ { "name": "JSESSIONID", - "value": "4F7727231AAE2E91CC303B4998984E87", + "value": "253ABBF13FACE7BE76232FF791B5218F", "domain": "localhost", "path": "/", "expires": -1, @@ -12,7 +12,7 @@ }, { "name": "XSRF-TOKEN", - "value": "39695da9-803f-49c6-809b-7e7a1354a8e2", + "value": "aa1d4205-a8c4-4525-8e4f-baf23a98834f", "domain": "localhost", "path": "/", "expires": -1, diff --git a/frontend/public/assets/help/help-data-de-ch.json b/frontend/public/assets/help/help-data-de-ch.json deleted file mode 100644 index f1aac162..00000000 --- a/frontend/public/assets/help/help-data-de-ch.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "user-guide": "

    Benutzerhandbuch

    \n

    Willkommen beim GoodOne-Benutzerhandbuch. Dieses Dokument enthält Anweisungen zur Verwendung der Funktionen der Frontend-Anwendung.

    \n

    Inhaltsverzeichnis

    \n
      \n
    1. Erste Schritte
    2. \n
    3. Dashboard
    4. \n
    5. Aufgabenverwaltung
    6. \n
    7. Benutzerprofil
    8. \n
    9. Abmelden
    10. \n
    \n

    Erste Schritte

    \n

    Um auf die Anwendung zuzugreifen, navigieren Sie zur Frontend-URL (normalerweise http://localhost). Sie werden aufgefordert, sich anzumelden. Wenn Sie noch kein Konto haben, können Sie ein neues registrieren.

    \n

    Anmeldung

    \n

    Geben Sie Ihren Benutzernamen und Ihr Passwort ein, um auf Ihr Konto zuzugreifen.

    \n

    Registrierung

    \n

    Wenn Sie ein neuer Benutzer sind, klicken Sie auf den Link \"Registrieren\". Geben Sie Ihren Vornamen, Nachnamen, den gewünschten Login, Ihre E-Mail-Adresse und Ihr Passwort an.

    \n

    Dashboard

    \n

    Das Dashboard bietet einen Überblick über Ihre Aktivitäten und den Systemstatus:\n- Zusammenfassungskarten: Schnelle Statistiken zu offenen Aufgaben, aktiven Benutzern, abgeschlossenen Aufgaben und den heutigen Logsn.\n- Aufgabenübersicht: Eine visuelle Verteilung der Aufgaben nach Status (Offen, In Bearbeitung, Abgeschlossen).\n- Letzte Aktivitäten: Eine Liste der zuletzt im System durchgeführten Aktionen.\n- Prioritätsaufgaben: Eine Liste der Aufgaben mit hoher Priorität, die Ihre Aufmerksamkeit erfordern.

    \n

    Aufgabenverwaltung

    \n

    Die Seite Aufgabenverwaltung ermöglicht es Ihnen, Ihre Arbeit zu organisieren:\n- Aufgabe hinzufügen: Klicken Sie auf die Schaltfläche \"Aufgabe hinzufügen\", um eine neue Aufgabe zu erstellen. Sie können Titel, Beschreibung, Fälligkeitsdatum, Priorität und Status angeben.\n- Filtern und Sortieren: Filtern Sie Aufgaben nach Status (Offen, In Bearbeitung, Abgeschlossen) oder setzen Sie die Sortierung zurück, um sie nach Priorität anzuzeigen.\n- Aufgabe bearbeiten: Klicken Sie auf das Bearbeitungssymbol auf einer Aufgabenkarte, um deren Details zu ändern.\n- Aufgabe löschen: Klicken Sie auf das Löschsymbol, um eine Aufgabe zu entfernen.\n- Drag & Drop: Sie können Aufgaben neu anordnen, indem Sie sie am Griff ziehen (verfügbar, wenn nicht gefiltert wird).

    \n

    Benutzerprofil

    \n

    Im Bereich Profil können Sie Ihre persönlichen Daten einsehen, einschliesslich Name, E-Mail und zugewiesener Rolle.

    \n

    Abmelden

    \n

    Um die Anwendung sicher zu verlassen, klicken Sie auf die Schaltfläche \"Abmelden\" im seitlichen Navigationsmenü.

    ", - "faq": "

    Häufig gestellte Fragen (FAQ)

    \n

    Finden Sie Antworten auf häufig gestellte Fragen zur GoodOne-Anwendung.

    \n

    Inhaltsverzeichnis

    \n
      \n
    1. Konto und Anmeldung
    2. \n
    3. Aufgabenverwaltung
    4. \n
    5. Fehlerbehebung
    6. \n
    \n

    Konto und Anmeldung

    \n

    Wie registriere ich mich?

    \n

    Klicken Sie auf der Anmeldeseite auf den Link \"Registrieren\", fuellen Sie das Formular aus und klicken Sie auf \"Registrieren\".

    \n

    Ich habe mein Passwort vergessen. Was soll ich tun?

    \n

    Sie koennen den Link \"Passwort vergessen\" auf der Anmeldeseite verwenden. Geben Sie Ihre E-Mail-Adresse ein, und Sie erhalten einen Link zum Zuruecksetzen Ihres Passworts. Wenn Sie Probleme haben, wenden Sie sich bitte an Ihren Systemadministrator.

    \n

    Kann ich meine E-Mail-Adresse aendern?

    \n

    Ja, Sie koennen Ihre E-Mail-Adresse in Ihrem Profilbereich aktualisieren.

    \n

    Kann ich meine Rolle aendern?

    \n

    Benutzerrollen (ROLE_USER, ROLE_ADMIN, ROLE_ADMIN_READ) koennen nur von einem Administrator ueber die Benutzerverwaltung geaendert werden.

    \n

    Was ist die ROLE_ADMIN_READ-Rolle?

    \n

    Diese Rolle ermoeglicht es einem Benutzer, Verwaltungsdaten wie Benutzerlisten und System-Logs einzusehen, ohne die Moeglichkeit, Informationen zu aendern oder zu loeschen.

    \n

    Aufgabenverwaltung

    \n

    Wie aendere ich die Prioritaet einer Aufgabe?

    \n

    Bearbeiten Sie die Aufgabe, indem Sie auf das Stiftsymbol klicken, und waehlen Sie eine neue Prioritaet (Niedrig, Mittel, Hoch) aus dem Dropdown-Menue aus.

    \n

    Was passiert, wenn ich eine Aufgabe loesche?

    \n

    Das Loeschen einer Aufgabe ist dauerhaft und kann nicht rueckgaengig gemacht werden.

    \n

    Kann ich Aufgaben anderen Benutzern zuweisen?

    \n

    In der aktuellen Version sind Aufgaben persoenlich und dem Benutzer zugeordnet, der sie erstellt hat.

    \n

    Fehlerbehebung

    \n

    Die Anwendung reagiert nicht. Was soll ich tun?

    \n

    Versuchen Sie, die Seite in Ihrem Browser zu aktualisieren. Wenn das Problem weiterhin besteht, melden Sie sich ab und wieder an.

    \n

    Ich sehe keine Daten auf dem Dashboard.

    \n

    Stellen Sie sicher, dass Sie ueber eine aktive Internetverbindung verfuegen und dass der Backend-Server ausgefuehrt wird. Wenn Sie ein neuer Benutzer sind, muessen Sie moeglicherweise zuerst einige Aufgaben erstellen.

    \n

    Warum kann ich nicht auf die Benutzerverwaltung zugreifen?

    \n

    Die Benutzerverwaltung und die Logs sind nur fuer Benutzer mit der Rolle ADMIN oder ADMIN_READ zugaenglich.

    ", - "admin-guide": "

    Administrator-Handbuch

    \n

    Dieses Handbuch ist für Benutzer mit der Rolle ADMIN bestimmt. Es deckt die Verwaltungsfunktionen der GoodOne-Anwendung ab.

    \n

    Inhaltsverzeichnis

    \n
      \n
    1. Benutzerverwaltung
    2. \n
    3. Logs
    4. \n
    5. Rollen und Berechtigungen
    6. \n
    \n

    Benutzerverwaltung

    \n

    Administratoren können alle Benutzer im System verwalten:\n- Benutzerliste: Zeigen Sie eine Tabelle aller registrierten Benutzer an.\n- Benutzer bearbeiten: Aktualisieren Sie Benutzerdetails wie Name, E-Mail und Rolle.\n- Benutzer löschen: Entfernen Sie Benutzer aus dem System (Vorsicht: Dies ist dauerhaft).\n- Passwort zurücksetzen: Administratoren können bei Bedarf Passwörter für Benutzer aktualisieren.

    \n

    Logs

    \n

    Auf der Seite Logs können Administratoren die Systemaktivitäten überwachen:\n- Echtzeit-Updates: Logs werden automatisch aktualisiert, wenn neue Aktionen auftreten.\n- Filterung: Filtern Sie Logs nach Benutzer, Aktion oder Zeitstempel, um bestimmte Ereignisse zu untersuchen.\n- Fehlerverfolgung: Überwachen Sie fehlgeschlagene Anmeldeversuche oder Systemfehler.

    \n

    Rollen und Berechtigungen

    \n

    Das System verwendet eine rollenbasierte Zugriffskontrolle (RBAC):\n- USER: Kann Aufgaben verwalten, das Dashboard und das eigene Profil einsehen.\n- ADMIN: Hat vollen Zugriff auf alle Funktionen, einschliesslich Benutzerverwaltung und Logs.

    \n

    Zuweisen von Rollen

    \n

    Rollen können während der Benutzerbearbeitung in der Benutzerverwaltungskonsole zugewiesen werden. Änderungen werden wirksam, wenn sich der Benutzer das nächste Mal anmeldet oder seine Sitzung aktualisiert.

    ", - "risk-radar": "

    AI Risk Radar

    \n

    Der AI Risk Radar ist eine zentrale Engineering Intelligence-Funktion, die automatisch wiederkehrende Qualitäts-, Liefer- und Dokumentationsrisiken im gesamten Projekt erkennt.

    \n

    🎯 Ziel

    \n

    Systematische Qualitätsprobleme und Lieferengpässe frühzeitig zu identifizieren, bevor sie die Release-Bereitschaft oder die architektonische Integrität beeinträchtigen.

    \n

    🔍 Funktionsweise

    \n

    Der Risk Radar analysiert verschiedene Datenquellen, um Muster zu erkennen:\n1. Task-Logs: Analysiert den Bereich Junie Log in Task-Dateien auf wiederkehrende Probleme, hohe Iterationszahlen und Blocker.\n2. Verifizierungsabschnitte: Prüft, ob Verifizierungsanweisungen vorhanden, klar und tatsächlich befolgt sind.\n3. Inkonsistenzen im Task-Status: Erkennt Tasks, die als DONE markiert sind, aber noch Open items enthalten oder denen Verifizierungsnachweise fehlen.\n4. Liefermuster: Identifiziert, ob bestimmte Arten von Tasks (z. B. AI-ARCH) konsistent länger dauern oder mehr Fehler aufweisen.

    \n

    🚦 Risikostufen

    \n

    Risiken werden in drei Schweregrade eingeteilt:\n- 🔴 Hohes Risiko: Kritische Blocker oder systematische Fehler, die sofortige Aufmerksamkeit erfordern (z. B. fehlende Verifizierung für zentrale Sicherheitsfunktionen).\n- 🟡 Mittleres Risiko: Qualitätsprobleme oder Lieferverzögerungen, die das Sprintziel beeinträchtigen könnten, wenn sie nicht behoben werden.\n- 🟢 Geringes Risiko: Kleinere Dokumentationsinkonsistenzen oder isolierte Prozessabweichungen.

    \n

    🛠️ Mitigierung

    \n

    Für jedes erkannte Risiko bietet die KI:\n- Beweise: Konkrete Task-Keys oder Log-Einträge, in denen das Muster erkannt wurde.\n- Auswirkungen: Bewertung, wie sich dieses Risiko auf das Projekt auswirkt (z. B. \"Erhöht die technischen Schulden im AI-Layer\").\n- Empfohlene Massnahmen: Umsetzbare Schritte zur Behebung des Risikos (z. B. \"Verpflichtendes Verifizierungs-Template für AI-ARCH-Tasks hinzufügen\").

    \n

    🖥️ Nutzung

    \n

    Sie können über das Engineering Intelligence-Dashboard oder direkt über die Seite AI Risk Radar auf den Risk Radar zugreifen.\n1. Wählen Sie das relevante Taskset oder den Sprint aus.\n2. Definieren Sie den Zeitraum für die Analyse.\n3. Erstellen Sie den Bericht, um die priorisierte Liste der Risiken zu sehen.

    \n

    🔒 Governance & Transparenz

    \n

    Der Risk Radar ist auf Transparenz ausgelegt:\n- Er erfindet niemals Fakten: Jedes Risiko muss durch konkrete Beweise aus der Dokumentation belegt sein.\n- Er liefert einen Confidence Score für seine Analyse.\n- Alle KI-Aufrufe werden protokolliert und sind für Audits einsehbar.

    \n
    \n

    Bezieht sich auf: AI-RETRO-02-AI-Risk-Radar.md

    ", - "navigation": "

    Glossar für Navigation & Funktionen

    \n

    Willkommen auf der GoodOne-Plattform. Dieser Leitfaden erklärt die verschiedenen Menüs, Funktionen und Begriffe, denen Sie in der Anwendung begegnen werden.

    \n

    1. Allgemeine Navigation

    \n

    Dashboard

    \n
      \n
    • Was es ist: Die zentrale Schaltstelle der Anwendung.
    • \n
    • Was es tut: Bietet einen Überblick über die Systemaktivitäten, einschliesslich offener Aufgaben, aktiver Benutzer, aktueller Protokolle und Ihrer wichtigsten \"Prioritätsaufgaben\".
    • \n
    • Bedeutung: Ihr Ausgangspunkt für einen täglichen Überblick über den Zustand des Projekts.
    • \n
    \n

    Tasks (Aufgaben)

    \n
      \n
    • Was es ist: Ein umfassendes Aufgabenverwaltungssystem.
    • \n
    • Was es tut: Ermöglicht es Ihnen, Ihre Arbeitselemente zu erstellen, zu bearbeiten, zu löschen und zu organisieren. Zu den Funktionen gehören Drag-and-Drop-Sortierung, Prioritätsstufen und Statusverfolgung.
    • \n
    • Bedeutung: Der Ort, an dem die eigentliche Arbeit dokumentiert und verfolgt wird.
    • \n
    \n

    AI Features (KI-Funktionen)

    \n
      \n
    • Was es ist: Eine Kategorie im Seitenmenü, die alle intelligenten Funktionen der Plattform gruppiert.
    • \n
    • Was es tut: Ermöglicht den Zugriff auf Werkzeuge, die künstliche Intelligenz nutzen, um das Projekt zu analysieren.
    • \n
    • Bedeutung: Hebt den \"AI-First\"-Charakter der GoodOne-Plattform hervor.
    • \n
    \n

    AI Copilot

    \n
      \n
    • Was es ist: Ein permanenter KI-Assistent, der im gesamten Arbeitsbereich verfügbar ist.
    • \n
    • Was es tut: Bietet verschiedene Modi wie Architektur-Q&A, Engineering-Chat und Onboarding-Hilfe. Er nutzt Retrieval-Augmented Generation (RAG), um Antworten zu geben, die auf der eigenen Dokumentation des Projekts basieren.
    • \n
    • Bedeutung: Ihr intelligenter Partner beim Navigieren und Verstehen der komplexen Codebasis.
    • \n
    \n

    2. Engineering Intelligence

    \n

    Engineering Intelligence

    \n
      \n
    • Was es ist: Ein Dashboard für datengesteuerte Engineering-Einblicke.
    • \n
    • Was es tut: Aggregiert Signale aus verschiedenen KI-Funktionen, um den gesamten \"Health Score\" eines Sprints oder Tasksets anzuzeigen.
    • \n
    • Bedeutung: Der Übergang von Intuition zu datengesteuertem Management von Softwareprojekten.
    • \n
    \n

    AI Project Roadmap (KI-Projekt-Roadmap / Epics)

    \n
      \n
    • Was es ist: Eine übergeordnete Ansicht des Projektfortschritts und der Meilensteine.
    • \n
    • Was es tut: Visualisiert, wie einzelne Aufgaben zu grösseren Zielen (Epics) beitragen, und verfolgt die Abschlussraten im Zeitverlauf.
    • \n
    • Bedeutung: Hilft Stakeholdern, die langfristige Entwicklung des Projekts zu verstehen.
    • \n
    \n

    Architecture Q&A (Architektur-Q&A)

    \n
      \n
    • Was es ist: Eine spezialisierte KI-Schnittstelle für Fragen zum Systemdesign.
    • \n
    • Was es tut: Scannt indexierte technische Dokumente und Architecture Decision Records (ADRs), um die Funktionsweise des Systems zu erklären.
    • \n
    • Bedeutung: Erspart das manuelle Suchen in hunderten von Dokumentationsseiten.
    • \n
    \n

    AI Retrospective (KI-Sprint-Retrospektive)

    \n
      \n
    • Was es ist: Ein KI-generierter Bericht, der einen Sprint oder eine Reihe von Aufgaben zusammenfasst.
    • \n
    • Was es tut: Analysiert Erfolge, technische Schulden, Risiken und Prozessengpässe, um umsetzbare Vorschläge für die nächste Iteration zu liefern.
    • \n
    • Bedeutung: Automatisiert den zeitaufwendigen Prozess der Datenerfassung für Sprint-Reviews.
    • \n
    \n

    AI Risk Radar (KI-Risiko-Radar)

    \n
      \n
    • Was es ist: Ein proaktives Werkzeug zur Risikoerkennung.
    • \n
    • Was es tut: Identifiziert wiederkehrende Qualitätsprobleme, Lieferengpässe und Dokumentationslücken in den Task-Logs.
    • \n
    • Bedeutung: Ein \"Frühwarnsystem\" für Projektleiter und technische Verantwortliche.
    • \n
    \n

    AI ADR Drift (KI-ADR-Drift / ADR-Drifterkennung)

    \n
      \n
    • Was es ist: Ein Werkzeug, das prüft, ob Code/Implementierung mit den Architektur-Entscheidungen übereinstimmen.
    • \n
    • Was es tut: Vergleicht aktuelle Task-Ergebnisse mit etablierten Architecture Decision Records (ADRs), um \"architektonischen Drift\" zu erkennen.
    • \n
    • Bedeutung: Stellt sicher, dass die langfristige Integrität des Systems bei schneller Entwicklung erhalten bleibt.
    • \n
    \n

    AI Knowledge Coverage (KI-Wissensabdeckung)

    \n
      \n
    • Was es ist: Ein administratives Dashboard für das \"Gehirn\" der KI.
    • \n
    • Was es tut: Zeigt, welche Teile der Dokumentation gut indexiert sind und welche veraltet sind oder nie vom KI-Assistenten verwendet werden.
    • \n
    • Bedeutung: Hilft Dokumentationsverantwortlichen, Lücken in der Wissensbasis des Projekts zu identifizieren.
    • \n
    \n

    3. Integrationen & Analysen

    \n

    GitHub

    \n
      \n
    • Was es ist: Ein Link zum Quellcode-Repository des Projekts.
    • \n
    • Was es tut: Öffnet das GitHub-Repository in einem neuen Tab, sodass Sie den Code direkt inspizieren können.
    • \n
    • Bedeutung: Fördert Transparenz und \"Open Source\"-Prinzipien innerhalb des Teams.
    • \n
    \n

    Analytics (Analysen)

    \n
      \n
    • Was es ist: Eine Kategorie zur Verfolgung der Leistung und Nutzung des Systems.
    • \n
    • Was es tut: Gruppiert Werkzeuge im Zusammenhang mit KI-Nutzung, Kosten und Systemmetriken.
    • \n
    • Bedeutung: Bietet Transparenz über die operative Seite der Plattform.
    • \n
    \n

    AI Economy (KI-Ökonomie: KI-Nutzung, Kreditanfragen, KI-Kostendashboard)

    \n
      \n
    • Was es ist: Das System zur Verwaltung des KI-Ressourcenverbrauchs.
    • \n
    • Was es tut:
        \n
      • AI Usage (KI-Nutzung): Zeigt, wie viele KI-Aufrufe und Token von jedem Benutzer oder jeder Funktion verbraucht werden.
      • \n
      • Credit Requests (Kreditanfragen): Ermöglicht es Benutzern, mehr tägliche \"KI-Credits\" anzufordern, wenn sie ihr Limit erreichen.
      • \n
      • AI Cost Dashboard (KI-Kostendashboard): (Nur Admin) Bietet einen finanziellen Überblick über die geschätzten KI-Kosten (z. B. in EUR) pro Modell und Funktion.
      • \n
      \n
    • \n
    • Bedeutung: Gewährleistet eine nachhaltige und transparente Nutzung teurer KI-Ressourcen.
    • \n
    \n

    4. Administration

    \n

    Administration

    \n
      \n
    • Was es ist: Das Kontrollzentrum für Systemadministratoren.
    • \n
    • Was es tut: Gruppiert alle Werkzeuge, die zur Verwaltung von Benutzern, Sicherheit und globalen Systemeinstellungen erforderlich sind.
    • \n
    • Bedeutung: Beschränkt auf Benutzer mit ROLE_ADMIN-Berechtigungen.
    • \n
    \n

    User Admin (Benutzerverwaltung)

    \n
      \n
    • Was es ist: Schnittstelle zur Benutzerverwaltung.
    • \n
    • Was es tut: Ermöglicht es Administratoren, Benutzer zu erstellen, zu bearbeiten, zu löschen und Rollen zuzuweisen.
    • \n
    • Bedeutung: Steuert, wer Zugriff auf die Plattform hat und was sie tun können.
    • \n
    \n

    Documentation (Admin-Dokumentation)

    \n
      \n
    • Was es ist: Ein Verwaltungswerkzeug für die Wissensbasis.
    • \n
    • Was es tut: Ermöglicht es Administratoren, neue Dokumentationen (ZIP-Dateien) hochzuladen und den Reindexierungsprozess für KI-Funktionen auszulösen.
    • \n
    • Bedeutung: Der Mechanismus zur Aktualisierung der \"Source of Truth\" der KI.
    • \n
    \n

    AI Settings (KI-Einstellungen)

    \n
      \n
    • Was es ist: Globale Konfiguration für das KI-Verhalten.
    • \n
    • Was es tut: Ermöglicht das Festlegen von Standard-Tageslimits, die Konfiguration von E-Mail-Suffix-Regeln zur automatischen Genehmigung von Credits und die Auswahl von KI-Modellen.
    • \n
    • Bedeutung: Verfeinert, wie die KI in die Anwendung integriert wird.
    • \n
    \n

    System Status (Systemstatus)

    \n
      \n
    • Was es ist: Echtzeit-Zustandsüberwachung.
    • \n
    • Was es tut: Zeigt den Status des Backends, der Datenbank und verschiedene Versionen an. Bietet zudem eine Schaltfläche \"Demo zurücksetzen\", um die Umgebung zu bereinigen.
    • \n
    • Bedeutung: Stellt sicher, dass die Plattform reibungslos läuft.
    • \n
    \n

    Logs (Protokolle)

    \n
      \n
    • Was es ist: Der Audit-Trail des Systems.
    • \n
    • Was es tut: Zeichnet jede wichtige Aktion (Login, Aufgabenerstellung, Benutzeraktualisierungen) zu Sicherheits- und Prüfzwecken auf.
    • \n
    • Bedeutung: Bietet Rechenschaftspflicht und eine Historie der Änderungen.
    • \n
    \n

    5. Spezialisierte KI-Konzepte

    \n

    Core AI Capabilities (KI-Kernfähigkeiten)

    \n
      \n
    • Was es ist: Die zugrunde liegenden KI-Funktionen, die die App antreiben.
    • \n
    • Was es tut: Umfasst die Generierung von Embeddings, Vektorsuche und Prompt-Engineering mit Modellen wie GPT-4o oder Ollama.
    • \n
    • Bedeutung: Der \"Motor\" unter der Haube von GoodOne.
    • \n
    \n

    AI Task Parsing (KI-Aufgabenanalyse)

    \n
      \n
    • Was es ist: Aufgaben-Eingabe in natürlicher Sprache.
    • \n
    • Was es tut: Wenn Sie eine Aufgabenbeschreibung eingeben, extrahiert die KI automatisch Titel, Priorität, Status und Fälligkeitsdatum.
    • \n
    • Bedeutung: Beschleunigt den administrativen Aufwand durch das Verständnis der menschlichen Absicht.
    • \n
    \n

    Engineering Chat & Onboarding Help (Engineering-Chat & Onboarding-Hilfe)

    \n
      \n
    • Was es ist: Spezialisierte Modi des AI Copilots.
    • \n
    • Was es tut:
        \n
      • Engineering Chat: Hilft bei technischen Fragen und dem Projektkontext.
      • \n
      • Onboarding Help: Beantwortet gezielt Fragen zur Nutzung von GoodOne und wo Informationen zu finden sind.
      • \n
      \n
    • \n
    • Bedeutung: Personalisierte Unterstützung für jede Phase der Entwicklerreise.
    • \n
    ", - "index": "

    Feature-Index

    \n

    Dieses Verzeichnis bietet detaillierte Informationen über die Kernfunktionen der AI Engineering Intelligence Platform.

    \n

    🚀 Kernfunktionen

    \n
      \n
    • AI Risk Radar: Erkennt systematische Qualitäts-, Liefer- und Dokumentationsrisiken.
    • \n
    • AI Sprint Retrospective: Erstellt KI-unterstützte Sprint-Retrospektiven basierend auf Entwicklungsaufgaben.
    • \n
    • ADR Drift Detection: Überwacht die Implementierung und erkennt, wenn Systeme von Architektur-Entscheidungen abweichen.
    • \n
    • AI Task Parsing: Wandelt natürliche Sprache in strukturierte Arbeitselemente um.
    • \n
    • AI Onboarding Assistant: Bietet kontextbezogene Onboarding-Hilfe für Ingenieure.
    • \n
    • AI Economy Dashboard: Verfolgt und analysiert die KI-Nutzung und -Kosten über die gesamte Plattform hinweg.
    • \n
    • Navigation & Features Glossar: Detaillierte Erklärung aller UI-Elemente und Funktionen.
    • \n
    \n
    \n

    Für einen allgemeinen Überblick siehe den Projekt-Index.

    ", - "md-to-confluence": "
    import markdown\nimport requests\nimport json\nimport os\n\n# Configuration\nCONFLUENCE_URL = "https://your-domain.atlassian.net/wiki/rest/api/content"\nUSERNAME = "your-email@example.com"\nAPI_TOKEN = "your-api-token"\nSPACE_KEY = "DOC"\nPARENT_PAGE_ID = "12345" # Optional: ID of the parent page\n\ndef md_to_confluence_storage(md_file_path):\n    """\n    Converts a Markdown file to HTML which is compatible with Confluence Storage Format.\n    Note: Standard HTML is often accepted by Confluence API, but some macros might need special tags.\n    """\n    with open(md_file_path, 'r', encoding='utf-8') as f:\n        md_content = f.read()\n\n    # Convert Markdown to HTML\n    html_content = markdown.markdown(md_content, extensions=['extra', 'toc'])\n    return html_content\n\ndef post_to_confluence(title, html_content, page_id=None):\n    """\n    Posts content to Confluence. If page_id is provided, it updates the page.\n    """\n    headers = {\n        "Accept": "application/json",\n        "Content-Type": "application/json"\n    }\n\n    auth = (USERNAME, API_TOKEN)\n\n    data = {\n        "type": "page",\n        "title": title,\n        "space": {"key": SPACE_KEY},\n        "body": {\n            "storage": {\n                "value": html_content,\n                "representation": "storage"\n            }\n        }\n    }\n\n    if PARENT_PAGE_ID:\n        data["ancestors"] = [{"id": PARENT_PAGE_ID}]\n\n    if page_id:\n        # Update existing page (needs version increment)\n        # First, get current version\n        resp = requests.get(f"{CONFLUENCE_URL}/{page_id}?expand=version", auth=auth)\n        version = resp.json()['version']['number'] + 1\n        data["version"] = {"number": version}\n        url = f"{CONFLUENCE_URL}/{page_id}"\n        response = requests.put(url, data=json.dumps(data), headers=headers, auth=auth)\n    else:\n        # Create new page\n        url = CONFLUENCE_URL\n        response = requests.post(url, data=json.dumps(data), headers=headers, auth=auth)\n\n    return response.status_code, response.text\n\nif __name__ == "__main__":\n    docs = [\n        ("User Guide", "doc/userguide/user-guide.md"),\n        ("Admin Guide", "doc/userguide/admin-guide.md"),\n        ("FAQ", "doc/userguide/faq.md")\n    ]\n\n    print("This script is a proposal. Please configure your Confluence credentials before running.")\n    # for title, path in docs:\n    #     if os.path.exists(path):\n    #         print(f"Converting {path}...")\n    #         storage_format = md_to_confluence_storage(path)\n    #         # status, text = post_to_confluence(title, storage_format)\n    #         # print(f"Status: {status}")\n\n
    " -} \ No newline at end of file diff --git a/frontend/public/assets/help/help-data-en.json b/frontend/public/assets/help/help-data-en.json deleted file mode 100644 index 177e93f0..00000000 --- a/frontend/public/assets/help/help-data-en.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "readme": "

    \"GoodOne\"

    \n

    \n\n![Designed by AI](https://img.shields.io/badge/designed%20by-AI-purple)\n![Powered by AI](https://img.shields.io/badge/runtime-AI-blue)\n![100% AI Generated Code](https://img.shields.io/badge/code-100%25%20AI%20generated-success)\n![Angular](https://img.shields.io/badge/frontend-angular-red)\n![Spring Boot](https://img.shields.io/badge/backend-springboot-green)\n![Docker](https://img.shields.io/badge/docker-ready-blue)\n\n

    \n\n

    GoodOne

    \n

    AI Software for Engineering Teams

    \n

    AI-powered platform that analyzes architecture, development workflows, and engineering documentation.

    \n

    GoodOne demonstrates what happens when AI becomes part of the engineering workflow itself.

    \n

    Instead of only generating code, the platform analyzes:

    \n

    • architecture documentation
    \n• development workflows
    \n• project knowledge
    \n• engineering risks

    \n

    Live demo
    \nhttps://GoodOne.ch

    \n
    \n

    🤖 Built With AI

    \n

    This project is a showcase of AI-driven software development.

    \n

    Highlights:

    \n

    100% of the source code was generated by AI
    \n• Iteration planning assisted by AI
    \n• Architecture design refined with AI
    \n• AI features operate directly at runtime

    \n

    GoodOne is not yet a finished product but a working demonstration of AI-assisted software engineering.

    \n

    The platform is under active development, and new AI capabilities are continuously added.

    \n
    \n

    🎬 Product Demo

    \n

    \"GoodOne

    \n
    \n

    🧩 Core AI Capabilities

    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
    FeatureDescription
    Architecture Q&AAsk natural-language questions about system architecture
    AI Risk RadarDetect recurring engineering and delivery risks
    Sprint RetrospectiveGenerate retrospective insights automatically
    ADR Drift DetectionDetect architectural drift from ADR decisions
    AI Task ParsingConvert natural language into structured tasks
    AI EconomyTrack AI usage, credits, and operational costs
    \n
    \n

    🏗 Architecture Overview

    \n
               Angular Frontend\n                 │\n                 ▼\n           Spring Boot API\n                 │\n                 ▼\n           AI Analysis Layer\n                 │\n       ┌─────────┼─────────┐\n       ▼         ▼         ▼\n     Tasks   Documentation   ADRs\n
    \n

    AI analyzes these artifacts to generate insights about the engineering system.

    \n
    \n

    ✨ AI Features

    \n

    Architecture Q&A

    \n

    Ask natural-language questions about the system architecture.

    \n

    Example questions:

    \n

    • Which components use AI at runtime?
    \n• How does authentication work?
    \n• How is reCAPTCHA verified?

    \n

    The AI answers using internal architecture documentation.

    \n
    \n

    AI Risk Radar

    \n

    Automatically detect recurring engineering risks.

    \n

    Examples:

    \n

    • tasks marked DONE but still containing open items
    \n• missing verification sections
    \n• documentation inconsistencies

    \n

    Helps teams detect systematic quality problems early.

    \n
    \n

    AI Sprint Retrospective

    \n

    Generate AI-assisted sprint retrospectives based on development tasks.

    \n

    The system analyzes:

    \n

    • task completion patterns
    \n• recurring blockers
    \n• documentation quality

    \n
    \n

    ADR Drift Detection

    \n

    Architecture Decision Records define architectural intent.

    \n

    GoodOne monitors implementation and detects when systems drift away from those decisions.

    \n

    This helps maintain long-term architectural integrity.

    \n
    \n

    AI Task Parsing

    \n

    Turn natural language into structured work items.

    \n

    Example:

    \n

    Prepare architecture review next Friday

    \n

    The AI extracts:

    \n

    • title
    \n• due date
    \n• category

    \n
    \n

    AI Economy

    \n

    Track and understand AI usage inside the platform.

    \n

    Examples:

    \n

    • AI credit requests
    \n• usage dashboards
    \n• cost transparency

    \n
    \n

    ⚡ Quick Start

    \n

    Clone the repository

    \n

    git clone https://github.com/JuergGood/angularai

    \n

    Start the stack

    \n

    cp .env.example .env\ndocker compose -f deploy/dev/docker-compose.yml up --build

    \n

    Application endpoints

    \n

    Frontend
    \nhttp://localhost

    \n

    Backend API
    \nhttp://localhost:8080/api

    \n

    Mailpit
    \nhttp://localhost:8025

    \n
    \n

    AI Runtime Requirements

    \n

    Some runtime features require access to an AI model.

    \n

    OpenAI

    \n

    Runtime AI features currently use the OpenAI API.

    \n

    OPENAI_API_KEY=your_key_here

    \n

    Ollama (Planned)

    \n

    A local runtime using Ollama is currently under development.

    \n

    This will allow running AI features locally without external APIs.

    \n

    Database

    \n

    The application uses PostgreSQL, automatically started via Docker.

    \n
    \n

    📚 Documentation

    \n

    Documentation is located in the doc directory.

    \n

    Key entry points:

    \n

    Architecture
    \ndoc/knowledge/architecture/index.md

    \n

    User Guide
    \ndoc/operations-guide.md

    \n

    Admin Guide
    \ndoc/operations-guide.md

    \n

    Deployment
    \ndoc/infrastructure/Deployment.md

    \n
    \n

    🎯 Vision

    \n

    GoodOne explores how AI can augment software engineering workflows.

    \n

    Instead of replacing developers, the platform helps teams:

    \n

    • understand complex architectures
    \n• detect engineering risks
    \n• analyze development processes
    \n• preserve architectural intent

    \n
    \n

    ⭐ If you find this project interesting, please consider starring the repository.

    ", - "user-guide": "

    User Guide

    \n

    Welcome to the GoodOne User Guide. This document provides instructions on how to use the frontend application features.

    \n

    Table of Contents

    \n
      \n
    1. Getting Started
    2. \n
    3. Dashboard
    4. \n
    5. Task Management
    6. \n
    7. User Profile
    8. \n
    9. Logout
    10. \n
    \n

    Getting Started

    \n

    To access the application, navigate to the frontend URL (typically http://localhost). You will be prompted to log in. If you don't have an account, you can register a new one.

    \n

    Login

    \n

    Enter your username and password to access your account.

    \n

    Registration

    \n

    If you are a new user, click on the \"Register\" link. Provide your first name, last name, desired login, email address, and password.

    \n

    Dashboard

    \n

    The Dashboard provides an overview of your activities and the system status:\n- Summary Cards: Quick stats on Open Tasks, Active Users, Completed Tasks, and Today's Logs.\n- Task Overview: A visual distribution of tasks by status (Open, In Progress, Completed).\n- Recent Activity: A list of the latest actions performed in the system.\n- Priority Tasks: A list of high-priority tasks that need your attention.

    \n

    Task Management

    \n

    The Task Management page allows you to organize your work:\n- Add Task: Click the \"Add Task\" button to create a new task. You can specify a title, description, due date, priority, and status.\n- Filter and Sort: Filter tasks by status (Open, In Progress, Completed) or reset sorting to view them by priority.\n- Edit Task: Click the edit icon on a task card to modify its details.\n- Delete Task: Click the delete icon to remove a task.\n- Drag and Drop: You can reorder tasks by dragging them using the handle (available when not filtering).

    \n

    User Profile

    \n

    In the Profile section, you can view your personal details, including your name, email, and assigned role.

    \n

    Logout

    \n

    To securely leave the application, click the \"Logout\" button in the side navigation menu.

    ", - "faq": "

    Frequently Asked Questions (FAQ)

    \n

    General

    \n

    Q: What is GoodOne?

    \n

    A: GoodOne is a task management application featuring a modern Angular frontend, a Spring Boot backend, and an Android mobile app.

    \n

    Q: How do I get started?

    \n

    A: Register for an account, log in, and start creating tasks on the Task Management page.

    \n

    Accounts and Security

    \n

    Q: I forgot my password. How can I reset it?

    \n

    A: You can use the \"Forgot Password\" link on the login page. Enter your email address, and you will receive a link to reset your password. If you encounter any issues, please contact your system administrator.

    \n

    Q: Can I change my role?

    \n

    A: User roles (ROLE_USER, ROLE_ADMIN, ROLE_ADMIN_READ) can only be changed by an administrator via the User Administration panel.

    \n

    Q: What is the ROLE_ADMIN_READ role?

    \n

    A: This role allows a user to view administrative data like user lists and system logs without the ability to modify or delete any information.

    \n

    Task Management

    \n

    Q: Can I reorder my tasks?

    \n

    A: Yes, you can use the drag handle on the left side of each task card to reorder them manually. Note that manual reordering is disabled when a status filter is active.

    \n

    Q: What do the different task priorities mean?

    \n

    A:\n- High: Urgent tasks that should be addressed immediately.\n- Medium: Important tasks that should be completed soon.\n- Low: Non-urgent tasks.

    \n

    Troubleshooting

    \n

    Q: The application is not loading. What should I do?

    \n

    A: Ensure that both the backend and frontend services are running. If you are using Docker, run docker compose up to start all services.

    \n

    Q: Why can't I access the User Administration?

    \n

    A: User Administration and System Logs are only accessible to users with the ROLE_ADMIN or ROLE_ADMIN_READ roles.

    ", - "release-notes": "

    Release Notes

    \n

    Version 2.2.0 (2026-03-28)

    \n

    Features

    \n
      \n
    • AI Platform & Consistency:
        \n
      • Implemented AiConsistencyService for automated cross-document evaluations and integrated AiConsistencyController for API access.
      • \n
      • Added Phase 5 AI transparency metadata support for frontend and backend components.
      • \n
      • Introduced AiSchemaValidator for JSON schema validation within the StructuredAiClient.
      • \n
      \n
    • \n
    • Documentation & Traceability:
        \n
      • Added completion checklists and traceability sections to AI task documentation for improved compliance.
      • \n
      • Introduced JSON schemas for decision proposal, impact simulation, quick add parse, and task relationships.
      • \n
      • Added ADR-0075 and ADR-0099 references for formal architectural decision tracking.
      • \n
      • Added detailed Jackson runtime conflict analysis to identify root causes and propose stable dependency strategies.
      • \n
      \n
    • \n
    • Presentation & Training:
        \n
      • Revamped presentations with new visuals, enhanced narrative structure, and comprehensive Confluence import for GoodOne-Intranet.
      • \n
      • Introduced AI system understanding slides illustrating the evolution from feature-based to system-based AI.
      • \n
      \n
    • \n
    • Platform Enhancements:
        \n
      • Implemented Ollama warm start task and updated Sonar issue records for better maintainability tracking.
      • \n
      • Updated project references and added new tests across multiple modules.
      • \n
      \n
    • \n
    \n

    Fixes

    \n
      \n
    • AI & Reliability:
        \n
      • Updated AI-FIX-01 with detailed hallucination analysis and improved JSON parsing resilience.
      • \n
      • Enhanced AI observability service with improved context handling and path validation for task resolution.
      • \n
      • Introduced CopilotParsingReproductionTest for enhanced JSON parsing reliability.
      • \n
      \n
    • \n
    • Stability & UI:
        \n
      • Fixed Sonar issues and enhanced accessibility in the promo-section component.
      • \n
      • Resolved 504 errors by adjusting ALB timeout and Fargate resource allocation.
      • \n
      • Improved CSS for risk card titles with line clamping for better visual consistency.
      • \n
      \n
    • \n
    \n

    Security

    \n
      \n
    • Hardening:
        \n
      • Removed hardcoded credentials and enhanced environment variable handling in deployment scripts.
      • \n
      • Introduced .env file loading in PowerShell scripts for secure token management.
      • \n
      • Increased batch size for embedding service and adjusted E2E test setup for environment variables.
      • \n
      \n
    • \n
    • Architecture:
        \n
      • Refactored AiIntelligenceService to use facades for improved modularity and security.
      • \n
      • Refactored AI observability and performance services, replacing generic exceptions with specific, descriptive ones.
      • \n
      \n
    • \n
    \n

    Performance

    \n
      \n
    • Cloud Infrastructure:
        \n
      • Optimized Fargate deployment: Increased CPU/memory allocation and updated ALB idle timeout to 300 seconds.
      • \n
      • Clarified Nginx usage in guidelines to resolve AI performance issues and 504 errors.
      • \n
      • Optimized memory usage by reducing embeddingTaskExecutor parallelism and adjusting rate limits.
      • \n
      \n
    • \n
    \n

    Documentation

    \n
      \n
    • Cleanup:
        \n
      • Removed outdated AI-ARCH task documentation and unnecessary scripts from the sonar directory.
      • \n
      • Simplified Jackson runtime conflict documentation for clarity and conciseness.
      • \n
      • Removed deprecated architecture posters, obsolete monitoring server configs, and old AI QA files.
      • \n
      \n
    • \n
    \n

    Refactoring

    \n
      \n
    • Testing & Quality:
        \n
      • Improved test coverage to >85% with comprehensive unit tests for DTOs (User, Task, TaskDTO), components, and services.
      • \n
      • Adapted test classes to WebMvcTest, introduced @MockitoBean for Spring Boot 4, and enhanced IP masking logic.
      • \n
      • Documented AI regression test steps for Sprint 2.1 and enhanced test timing and logging.
      • \n
      \n
    • \n
    • AI & Knowledge Management:
        \n
      • Refactored Ollama embedding model and optimized database type detection.
      • \n
      • Revamped AI Coverage Dashboard with category grouping and folder expand/collapse functionality.
      • \n
      • Refactored OllamaManualConfig for enhanced modularity and streamlined RiskRadar enhancements.
      • \n
      \n
    • \n
    • UI & Frontend:
        \n
      • Refactored frontend components and CSS for consistency, improved form handling with optional chaining and consolidated animations.
      • \n
      • Optimized HTML loops with $index tracking and synchronized SQL index conventions.
      • \n
      \n
    • \n
    • Infrastructure & Efficiency:
        \n
      • Enhanced batch processing with deleteAllInBatch() in repositories.
      • \n
      • Refactored AuthService and interceptors for improved logout handling and unauthorized error management.
      • \n
      • Standardized logging levels and enhanced audit trails for major user interactions via ActionLogService.
      • \n
      \n
    • \n
    \n

    Security Scan Summary

    \n
      \n
    • No recent automated security scan results found.
    • \n
    \n

    UX Highlights

    \n
      \n
    • UX review documentation not found.
    • \n
    \n

    Known Issues

    \n
      \n
    • Mobile Viewport (360px): Some tables in the User Administration panel might require horizontal scrolling on very narrow screens.
    • \n
    • Email Delivery: Emails sent from the demo environment might be flagged as spam by some providers due to missing SPF/DKIM records on the demo domain.
    • \n
    • Session Timeout: Users are not automatically redirected to the login page immediately upon JWT expiration; this happens only on the next API call.
    • \n
    \n

    Version 2.1.0 (2026-03-20)

    \n

    Features

    \n
      \n
    • AI Platform & Intelligence:
        \n
      • Implemented AI observability with telemetry service, stale knowledge analysis, and semantic search.
      • \n
      • Introduced AI coverage dashboard and real-time streaming for AI Intelligence Dashboard.
      • \n
      • Added Prompt Assembly Service and Knowledge Retrieval Trace Logging.
      • \n
      • Implemented DeterministicRetrievalTest for AI retrieval evaluation.
      • \n
      • Added comprehensive task documentation for Sprint 1.5, 1.6, and 1.6A.
      • \n
      • Introduced disciplined task implementation templates and roadmap for AI Engineering Platform.
      • \n
      \n
    • \n
    • Infrastructure & Connectivity:
        \n
      • Added documentation for host-run Ollama setup and fast local profile.
      • \n
      • Configured environment-driven connection and interactive settings tuning for Ollama.
      • \n
      • Extended timeouts in AiIntelligenceService and SseEmitter for better reliability.
      • \n
      • Updated DocIngestionService with includeTasksets configuration.
      • \n
      \n
    • \n
    • Documentation & Governance:
        \n
      • Implemented markdown to Confluence conversion script and new doc index generation script.
      • \n
      • Established authoritative sprint plan docs for AI dashboard scoping and fallback hierarchy.
      • \n
      • Introduced task contract standards, linting scripts, and benchmark status metadata.
      • \n
      • Updated GitHub repository links to https://github.com/JuergGood/angularai for consistency.
      • \n
      • Updated README with AI-driven platform details and expanded project documentation.
      • \n
      \n
    • \n
    • UI/UX & Integration:
        \n
      • Added invitation details for live demo and integrated taxonomy status translations.
      • \n
      • Added debounce to Quick Add Task and updated tracking in Angular templates.
      • \n
      • Introduced UI and runtime fixes bundle.
      • \n
      \n
    • \n
    \n

    Fixes

    \n
      \n
    • AI & Data Handling:
        \n
      • Fixed ADR parsing in full set overview and improved robustness of JSON parsing in StructuredOutputService.
      • \n
      • Fixed JSON handling and database connections for risk-radar and adr-drift prompts.
      • \n
      • Resolved \"2026-00-00\" date problem and updated database migration test expected counts.
      • \n
      • Fixed API compatibility with Spring AI 1.0.0-M1.
      • \n
      \n
    • \n
    • Platform & UI:
        \n
      • Enhanced E2E test navigation logic and fixed sidenav on mobile.
      • \n
      • Fixed incorrect imports for Jackson and Spring Actuator.
      • \n
      • Reduced vulnerabilities in test-client/pom.xml.
      • \n
      • Corrected file path typos in iteration-4 directory.
      • \n
      \n
    • \n
    \n

    Security

    \n
      \n
    • Access Control & Configuration:
        \n
      • Implemented role-based access for admin endpoints and refined API response handling.
      • \n
      • Updated Sprint 1.9 plan with refined task definitions, execution order, and security config.
      • \n
      • Enhanced code quality with improved null-check consistency and Maven dependency updates.
      • \n
      \n
    • \n
    \n

    Documentation (Cleanup)

    \n
      \n
    • Knowledge Management:
        \n
      • Normalized AI task documentation for Sprint 1.7 to Format v1.0.
      • \n
      • Relocated user-guide, admin-guide, and junie-tasks to improved directory structures.
      • \n
      • Removed redundant and outdated documentation from multiple sprints (1.6, 1.6A, 1.9) and old AI QA files.
      • \n
      • Restored missing ADRs and extensive documentation from backups.
      • \n
      \n
    • \n
    \n

    Refactoring

    \n
      \n
    • Testing & Reliability:
        \n
      • Enhanced AI regression tests with retry logic, improved logging, and adjusted timeout settings.
      • \n
      • Integrated AI provider selection and sprint configuration into E2E tests.
      • \n
      • Refactored AiCoverageDashboardComponent to use Angular Signals.
      • \n
      • Implemented lenient mocking and improved test configuration for AI application tests.
      • \n
      \n
    • \n
    • Maintenance:
        \n
      • Refactored documentation snippets and optimized package script formatting.
      • \n
      • Enhanced documentation ingestion with index validation tokens.
      • \n
      • Updated Playwright auth values and improved AI settings with default provider option.
      • \n
      \n
    • \n
    \n

    Security Scan Summary

    \n
      \n
    • No recent automated security scan results found.
    • \n
    \n

    UX Highlights

    \n
      \n
    • UX review documentation not found.
    • \n
    \n

    Known Issues

    \n
      \n
    • Mobile Viewport (360px): Some tables in the User Administration panel might require horizontal scrolling on very narrow screens.
    • \n
    • Email Delivery: Emails sent from the demo environment might be flagged as spam by some providers due to missing SPF/DKIM records on the demo domain.
    • \n
    • Session Timeout: Users are not automatically redirected to the login page immediately upon JWT expiration; this happens only on the next API call.
    • \n
    \n

    Version 1.1.0 (2026-03-10)

    \n

    Features

    \n
      \n
    • AI Core & RAG Enhancements:
        \n
      • Implemented semantic document retrieval and embedding generation with support for OpenAI and Ollama.
      • \n
      • Added ADR Drift Detector with backend detection logic and dedicated frontend UI components.
      • \n
      • Enhanced embedding model filtering and support for diverse vector dimensions.
      • \n
      • Implemented dynamic reindex toggle, connectivity checks, and deterministic truncation repair in StructuredOutputService.
      • \n
      • Added retrospective generator service with structured JSON output and architecture prompt handling.
      • \n
      \n
    • \n
    • Platform & Infrastructure:
        \n
      • Integrated PostgreSQL as a data source for GoodOne and documented AI-ARCH-05 implementation.
      • \n
      • Added Mailpit to the development environment for easier email testing.
      • \n
      • Implemented a master switch for AI features with component-level handling.
      • \n
      • Added i18nInterceptor for automatic language header management in API calls.
      • \n
      • Introduced landing message mode configuration and tests.
      • \n
      \n
    • \n
    • UI/UX Improvements:
        \n
      • Integrated birth date field in User Admin with date picker support.
      • \n
      • Implemented AuthAiIntroComponent for enhanced Login and Register pages.
      • \n
      • Added loading spinners to Risk Radar and improved sidenav responsiveness.
      • \n
      • Synchronized Tasksets dropdown in Risk Radar with tooltips and improved styling.
      • \n
      • Implemented anonymization for non-admin users in specific views.
      • \n
      \n
    • \n
    • Documentation & Task Management:
        \n
      • Added comprehensive documentation for Tasksets 4-7, 12, and various AI-UX/AI-ARCH tasks.
      • \n
      • Established clear indicators for deprecated architecture content and updated README links.
      • \n
      • Introduced Junie task validation, template generation, and task normalization scripts.
      • \n
      • Improved accessibility of documentation with titled sections and consistent naming conventions.
      • \n
      \n
    • \n
    \n

    Fixes

    \n
      \n
    • Security & Stability:
        \n
      • Fixed reindexing date filter in AI Risk Radar for accurate task filtering.
      • \n
      • Enhanced Ollama healthchecks and development startup scripts.
      • \n
      • Resolved various Sonar issues and improved exception handling across the backend.
      • \n
      • Fixed Prometheus endpoint exposure issues and updated configuration.
      • \n
      \n
    • \n
    \n

    Security Scan Summary

    \n
      \n
    • No recent automated security scan results found.
    • \n
    \n

    UX Highlights

    \n\n

    Known Issues

    \n
      \n
    • Mobile Viewport (360px): Some tables in the User Administration panel might require horizontal scrolling on very narrow screens.
    • \n
    • Email Delivery: Emails sent from the demo environment might be flagged as spam by some providers due to missing SPF/DKIM records on the demo domain.
    • \n
    • Session Timeout: Users are not automatically redirected to the login page immediately upon JWT expiration; this happens only on the next API call.
    • \n
    \n

    Version 1.0.9 (2026-03-01)

    \n

    Features

    \n
      \n
    • Security & Observability:
        \n
      • Implemented hardened CSP reporting with rate limiting and strict payload validation.
      • \n
      • Added DatabaseMigrationTest and negative path E2E tests for enhanced reliability.
      • \n
      • Introduced global error handling with an ErrorBoundary component.
      • \n
      • Implemented user activation handling and CSRF exemption tests for web configuration.
      • \n
      \n
    • \n
    • Platform Enhancements:
        \n
      • Integrated Grafana for monitoring with comprehensive configuration and troubleshooting guides.
      • \n
      • Added monitoring-server module and improved sidenav responsiveness.
      • \n
      • Enforced centralized versioning and commit standards across the project.
      • \n
      • Implemented StartupLogger service for detailed application startup diagnostics.
      • \n
      \n
    • \n
    \n

    Security

    \n
      \n
    • Vulnerability Management:
        \n
      • Integrated Trivy and Snyk for container and dependency scanning with SARIF upload to GitHub Code Scanning.
      • \n
      • Hardened CI/CD workflows by pinning GitHub Action versions and improving backend logging.
      • \n
      • Enhanced role-based security checks and reCAPTCHA configuration for Fargate deployments.
      • \n
      • Added documentation for task sets V4 to V7 covering reliability, testing, security, and release engineering.
      • \n
      \n
    • \n
    \n

    Performance & Quality

    \n
      \n
    • Testing & Stability:
        \n
      • Expanded E2E tests with a \"golden path\" user journey covering CRUD operations and AI-triggered functionality.
      • \n
      • Improved E2E test reliability with optimized wait strategies and better session management.
      • \n
      • Resolved numerous Sonar issues and enhanced input validation across services.
      • \n
      • Validated database migrations and H2 database locking behavior on Fargate.
      • \n
      \n
    • \n
    \n

    Refactoring & UI

    \n
      \n
    • Theming & Maintenance:
        \n
      • Refactored CSS variables for consistent dark mode support and high contrast readability.
      • \n
      • Improved reCAPTCHA handling with enhanced type safety across registration and contact forms.
      • \n
      • Cleaned up presentation modules and updated slides for architectural clarity.
      • \n
      • Introduced configuration validation and automated documentation snapshots.
      • \n
      • Removed obsolete Grafana dashboards and unused Cypress support files.
      • \n
      \n
    • \n
    \n

    Security Scan Summary

    \n
      \n
    • Total Issues: 3
    • \n
    • Critical Issues: 0
    • \n
    • Major Issues: 3
    • \n
    • Full report available in CI artifacts.
    • \n
    \n

    UX Highlights

    \n\n

    Known Issues

    \n
      \n
    • Mobile Viewport (360px): Some tables in the User Administration panel might require horizontal scrolling on very narrow screens.
    • \n
    • Email Delivery: Emails sent from the demo environment might be flagged as spam by some providers due to missing SPF/DKIM records on the demo domain.
    • \n
    • Session Timeout: Users are not automatically redirected to the login page immediately upon JWT expiration; this happens only on the next API call.
    • \n
    \n

    Version 1.0.8 (2026-02-15)

    \n

    Features

    \n
      \n
    • Contact Form: Implemented contact form with reCAPTCHA integration and backend storage.
    • \n
    • Analytics: Integrated Google Analytics and Microsoft Clarity with environment-aware conditional loading.
    • \n
    • Observability: Implemented end-to-end Correlation ID propagation and enhanced logging with forensic context.
    • \n
    \n

    Improvements & Refactoring

    \n
      \n
    • User Management: Refactored user creation and admin readiness checks for improved reliability.
    • \n
    • Data Initialization: Enhanced DataInitializerService with improved transactional logic and error management.
    • \n
    • System Integrity: Improved system status error handling and resilience across backend and frontend.
    • \n
    • Mobile UX: Optimized task list layout and accessibility for 360px mobile viewports.
    • \n
    \n

    Security & Hardening

    \n
      \n
    • CSP & Rate Limiting: Hardened Content Security Policy reporting and implemented strict rate limiting for sensitive endpoints.
    • \n
    • Dependency Management: Upgraded several core dependencies and pinned GitHub Actions to specific hashes for enhanced security.
    • \n
    • Secret Management: Added scripts for AWS secret management and pre-commit secret leak checks.
    • \n
    \n

    CI/CD & DevOps

    \n
      \n
    • Deployment: Automated release notes generation and improved GitHub Actions for Continuous Deployment to AWS Fargate.
    • \n
    • Docker: Optimized Dockerfile build process by streamlining dependency checks and reducing startup delays.
    • \n
    • Workflow Efficiency: Added concurrency control to GitHub workflows to optimize CI resource usage.
    • \n
    \n

    Testing & Quality

    \n
      \n
    • E2E Stability: Significantly improved Playwright test reliability with better waiting strategies and dual-click interactions.
    • \n
    • Visual Regression: Expanded E2E coverage with baseline screenshot tests for key demo screens and themes.
    • \n
    • Code Quality: Resolved numerous Sonar issues and enhanced backend service input validation and exception handling.
    • \n
    • Schema Validation: Integrated OpenAPI contract testing and database migration validation.
    • \n
    \n

    Documentation

    \n
      \n
    • Release Management: Implemented centralized versioning and enforced commit standards.
    • \n
    • Technical Reference: Added comprehensive AWS security roadmap, Operations Runbook, and forensic logging documentation.
    • \n
    \n

    Security Scan Summary

    \n
      \n
    • Total Issues: 3
    • \n
    • Critical Issues: 0
    • \n
    • Major Issues: 3
    • \n
    • Full report available in CI artifacts.
    • \n
    \n

    UX Highlights

    \n\n

    Known Issues

    \n
      \n
    • Mobile Viewport (360px): Some tables in the User Administration panel might require horizontal scrolling on very narrow screens.
    • \n
    • Email Delivery: Emails sent from the demo environment might be flagged as spam by some providers due to missing SPF/DKIM records on the demo domain.
    • \n
    • Session Timeout: Users are not automatically redirected to the login page immediately upon JWT expiration; this happens only on the next API call.
    • \n
    \n

    Version 1.0.7 (2026-02-08)

    \n

    Features

    \n
      \n
    • Demo Data Reset: Implemented frontend and backend functionality to reliably restore demo environment state.
    • \n
    • System Status: Added environment details, last deployment time, and role-based visibility to system status dashboard.
    • \n
    • Traceability: Implemented trace ID propagation from backend to frontend for improved debugging.
    • \n
    \n

    Improvements & Refactoring

    \n
      \n
    • UX Responsiveness: Optimized mobile layout for task preview, filter chips, and dashboard components.
    • \n
    • Validation Service: Centralized email and user validation logic into a dedicated service.
    • \n
    • Asset Caching: Optimized Nginx configuration for better performance via efficient asset caching.
    • \n
    \n

    Security & Hardening

    \n
      \n
    • Authentication: Switched to JWT-based authentication and disabled HTTP Basic for improved security.
    • \n
    • reCAPTCHA: Added support for dummy reCAPTCHA mode for development and testing.
    • \n
    • Audit Logging: Integrated Hibernate Envers for comprehensive entity auditing.
    • \n
    • CSRF Protection: Enhanced CSRF protection and CORS configurations for all environments.
    • \n
    \n

    CI/CD & DevOps

    \n
      \n
    • Automation: Introduced GitHub Actions for automated build, linting, and multi-platform testing.
    • \n
    • AWS Deployment: Added structured PowerShell scripts for demo and production deployments to AWS ECS/Fargate.
    • \n
    • Health Checks: Enabled and secured Spring Boot Actuator health, liveness, and readiness endpoints.
    • \n
    \n

    Testing & Quality

    \n
      \n
    • Visual Guardrails: Introduced Playwright E2E baseline screenshot tests for key screens across themes.
    • \n
    • Accessibility: Integrated axe-core for automated accessibility auditing and Lighthouse analysis.
    • \n
    • Coverage: Significantly increased unit and integration test coverage for controllers and services.
    • \n
    \n

    Documentation

    \n
      \n
    • Architecture: Restructured documentation for clarity, adding ER diagrams and technical references for AWS deployment.
    • \n
    • AI Guidelines: Introduced guidelines for AI usage and logging standards within the project.
    • \n
    \n

    Version 1.0.6 (2026-01-31)

    \n

    Features

    \n
      \n
    • Landing Message: Added configurable landing message feature across all platforms.
    • \n
    • Account Deletion: Implemented user account deletion with full cleanup logic.
    • \n
    • Password Recovery: Introduced secure password recovery flow with email integration.
    • \n
    \n

    Improvements & Refactoring

    \n
      \n
    • Persistence: Added support for persistent file-based H2 storage on AWS Fargate via EFS.
    • \n
    • Presentation: Added a dedicated module for generating architectural presentations from code.
    • \n
    • User Protection: Implemented safeguards to prevent deletion of critical system users.
    • \n
    \n

    Security & Hardening

    \n
      \n
    • Vulnerability Scanning: Integrated Trivy and Snyk scans into the CI/CD pipeline for code, containers, and IaC.
    • \n
    • Non-Root Execution: Hardened Docker and Kubernetes configurations to run services as non-root users.
    • \n
    • API Security: Implemented API rate limiting and hardened Content Security Policy (CSP).
    • \n
    \n

    CI/CD & DevOps

    \n
      \n
    • Workflow Hardening: Pinning GitHub Actions to specific hashes and optimizing dependency caching.
    • \n
    • Build Efficiency: Optimized Docker build process with multi-stage builds and .dockerignore.
    • \n
    \n

    Testing & Quality

    \n
      \n
    • Automation: Automated UI screenshot updates for documentation using Playwright.
    • \n
    • Static Analysis: Integrated Checkstyle and PMD into the build process to enforce coding standards.
    • \n
    \n

    Documentation

    \n
      \n
    • Standardization: Added comprehensive development standards and backend architecture documentation.
    • \n
    • Internationalization: Improved German FAQ and localized key system components.
    • \n
    \n

    Version 1.0.5 (2026-01-25)

    \n
      \n
    • Infrastructure: Update environment variables configuration
    • \n
    • Security: Add resend verification feature and enhance email verification UX
    • \n
    • UI: Refine register component UI and functionality
    • \n
    • Auth: Enhance registration form validation and error handling
    • \n
    • UX: Enhance registration form UX with hints and improved error handling
    • \n
    • Auth: Refactor registration form to enforce full name validation, enhance error handling, and update tests
    • \n
    • Testing: Refactor registration and implement extensive validation tests
    • \n
    • Docs: Add UI Architecture Documentation and Enhance Auth Flow Tests
    • \n
    • Testing: Refactor e2e tests for improved session handling and login logic
    • \n
    • Testing: Add Playwright e2e tests for Tasks and Auth Flow, update routing, and document UX strategy
    • \n
    • Quality: Remove H2 configuration, enhance system info tests with i18n checks, add user registration and verification schema. Update i18n files for password strength and registration messages.
    • \n
    • Security: Integrate Google reCAPTCHA for enhanced user verification, update registration logic to include token verification, and enhance user data initializer and error handling.
    • \n
    \n

    Version 1.0.4 (2026-01-23)

    \n
      \n
    • Security (reCAPTCHA): Implemented Google reCAPTCHA v2 on the registration page to ensure only real persons can register. Includes backend verification and configurable site/secret keys.
    • \n
    • Geolocation Service: Integrated IP-based location lookup, including a system setting to toggle the feature and automatic local/loopback address skipping.
    • \n
    • Enhanced Environment Management: Added .env.example template and improved environment loading logic for better local development setup.
    • \n
    • Advanced Task Parsing: Implemented comprehensive task parsing logic with a dedicated test suite to improve natural language task entry.
    • \n
    • UI/UX Improvements: Fixed dark mode issues and refined the task management interface.
    • \n
    • Documentation Refinement: Streamlined AWS deployment documentation, removing obsolete ALB and ECR instructions.
    • \n
    \n

    Version 1.0.2 (2026-01-17)

    \n
      \n
    • Version Display Fixes: Resolved issues where the version number was not correctly displayed in the UI.
    • \n
    • Quality Assurance: Integrated Qodana for static code analysis and addressed multiple SonarLint issues to improve code quality.
    • \n
    • Test Coverage: Significantly increased test coverage across the project, including backend JUnit tests and frontend Cypress integration tests.
    • \n
    • CI/CD Stability: Fixed various GitHub Actions CI build issues to ensure reliable automated testing.
    • \n
    \n

    Version 1.0.1 (2026-01-14)

    \n
      \n
    • Dashboard Visuals: Enhanced the dashboard with improved visuals and responsive layout across frontend, backend, and Android.
    • \n
    • Internationalization: Added German translations (de-ch) and improved the translation infrastructure.
    • \n
    • Security Enhancements: Introduced ROLE_ADMIN_READ for granular access control and read-only administrative access.
    • \n
    • Presentation Tools: Added scripts and templates for generating high-quality architectural presentations directly from the codebase.
    • \n
    \n

    Version 1.0.0 (2026-01-08)

    \n
      \n
    • Initial Release: Core functionality of the GoodOne prototype.
    • \n
    • Multi-Platform Support: Unified experience across Web (Angular) and Android platforms.
    • \n
    • Task Management: Comprehensive task lifecycle including status tracking, filtering, and drag-and-drop reordering.
    • \n
    • Real-time Monitoring: Integrated Action Log and Log menu for system transparency.
    • \n
    • API Documentation: Integrated Swagger UI for easy exploration of the backend REST API.
    • \n
    • Database Migrations: Initialized Flyway integration for reliable schema management.
    • \n
    • Test Client: Added a CLI tool for data management and direct API interaction.
    • \n
    \n

    Pre-1.0.0 (2026-01-01)

    \n
      \n
    • Foundation: Established the core project structure with Spring Boot backend and Angular standalone components.
    • \n
    • Infrastructure: Set up Docker-based deployment and Nginx reverse proxy configuration.
    • \n
    • Architecture: Defined the \"GoodOne\" ecosystem diagrams and core design principles.
    • \n
    ", - "docker-optimization": "

    Docker Build Optimization

    \n

    This document explains the strategies used to optimize Docker build times and ensure reliable dependency management in the GoodOne project.

    \n

    Dependency Caching Strategy

    \n

    The primary optimization involves leveraging Docker Layer Caching to avoid re-downloading Maven and NPM packages on every build.

    \n

    1. The Problem: Cache Invalidation

    \n

    Docker builds images in layers. Each instruction in a Dockerfile creates a new layer. Docker caches these layers; however, if the files copied in a COPY instruction change, that layer and all subsequent layers are invalidated and must be rebuilt.

    \n

    Previously, the Dockerfile copied the entire backend/ directory (including source code) before running the Maven build. Consequently:\n* Any change to a Java file invalidated the cache.\n* Maven was forced to download all dependencies again because the downloading step followed the invalidated COPY step.

    \n

    2. The Solution: Selective Copying, Dependency Pre-fetching & Cache Mounts

    \n

    The optimized Dockerfile separates dependency resolution from source code compilation and utilizes Docker BuildKit cache mounts for persistent local repositories.

    \n

    Backend (Maven) Optimization

    \n

    We copy only the pom.xml files first to create a layer that represents the project's dependencies. We use --mount=type=cache,target=/root/.m2 to ensure the Maven local repository is persisted across builds, even when layers are invalidated.

    \n
    # Step 1: Copy ONLY pom.xml files (The "Blueprint")\nCOPY pom.xml .\nCOPY backend/pom.xml backend/\nCOPY test-client/pom.xml test-client/\n\n# Step 2: Resolve and Cache Dependencies\n# BuildKit cache mounts persist the .m2 folder across builds.\n# We also resolve plugins to ensure they are cached before source code is copied.\nRUN --mount=type=cache,target=/root/.m2 \\\n    mvn dependency:go-offline dependency:resolve-plugins -B || true\nRUN --mount=type=cache,target=/root/.m2 \\\n    mvn -f backend/pom.xml dependency:go-offline dependency:resolve-plugins -B || true\n\n# Step 3: Copy volatile assets and source code\nCOPY --from=frontend-build /app/frontend/dist /app/frontend/dist\nCOPY backend/src backend/src\n\n# Final package step also uses the cache mount\nRUN --mount=type=cache,target=/root/.m2 \\\n    mvn -f backend/pom.xml clean package -DskipTests -Dcheckstyle.skip\n
    \n

    Frontend (NPM) Optimization

    \n

    Similarly, for the Angular frontend, we use cache mounts for the NPM cache.

    \n
    WORKDIR /app/frontend\nCOPY frontend/package*.json ./\nRUN --mount=type=cache,target=/root/.npm \\\n    npm ci\n
    \n

    3. Key Improvements

    \n
      \n
    • Cache Mounts (BuildKit): Persists ~/.m2 and ~/.npm across builds, preventing re-downloads even if pom.xml or package.json changes or previous layers are invalidated.
    • \n
    • Selective File Copying: By copying only configuration files first, we create layers that change infrequently.
    • \n
    • Pre-fetching: Using mvn dependency:go-offline and dependency:resolve-plugins ensures most artifacts and plugins are available before the source code is copied.
    • \n
    • Delayed Configuration Copying: Secondary files like dependency-check-suppressions.xml are copied after the dependencies are cached.
    • \n
    • Multi-Module Support: The root pom.xml is copied to ensure Maven understands the project structure during the go-offline phase.
    • \n
    \n

    Comparative Analysis

    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
    FeatureUnoptimized BuildOptimized Build
    Source code changeRe-downloads all packages (~5-10 mins)Re-uses cached packages (~1-2 mins)
    Dependency changeRe-downloads all packagesRe-downloads (expected)
    Build ReliabilityVulnerable to network glitchesDependencies are safely pre-fetched
    \n

    Best Practices

    \n
      \n
    1. Always use .dockerignore: Ensure large or unnecessary files (like local node_modules, target, or .git folders) are excluded from the Docker context.
    2. \n
    3. Order matters: Place instructions that change frequently (like COPY src/) as late as possible in the Dockerfile.
    4. \n
    5. Clean up in the same layer: If you install system packages (e.g., apk add), clean up caches in the same RUN command to keep image sizes small.
    6. \n
    ", - "admin-guide": "

    Admin Guide

    \n

    This guide is intended for system administrators of the GoodOne application. Administrators have access to additional features for user management and system monitoring.

    \n

    Table of Contents

    \n
      \n
    1. User Administration
    2. \n
    3. System Logs
    4. \n
    5. Roles and Permissions
    6. \n
    7. Quality Assurance & Analysis
    8. \n
    \n

    User Administration

    \n

    The User Administration page allows you to manage all users in the system:\n- List Users: View a list of all registered users, including their login name, full name, email, and role.\n- Add User: Create a new user account manually by providing their personal details and assigning a role.\n- Edit User: Modify the details of an existing user. Note that you cannot change the login name once a user is created.\n- Delete User: Remove a user from the system. You cannot delete your own account.\n- View User (Read-only): Users with the ROLE_ADMIN_READ role can view user details but cannot make changes.

    \n

    System Logs

    \n

    The System Logs page provides an audit trail of actions performed within the application:\n- Audit Trail: View logs including timestamp, user login, action performed, and additional details.\n- Filtering: Filter logs by action type (Login, Tasks, User Admin) and date range.\n- Sorting: Sort logs by timestamp.\n- Paging: Navigate through large sets of logs using the paginator.\n- Clear Logs: Administrators with full write access can clear all logs using the \"Clear All Logs\" button.

    \n

    Roles and Permissions

    \n

    The application uses the following roles to control access:\n- ROLE_USER: Standard user access. Can manage their own tasks and view their profile.\n- ROLE_ADMIN: Full administrative access. Can manage users, view all logs, and perform system-wide actions.\n- ROLE_ADMIN_READ: Read-only administrative access. Can view user lists and logs but cannot perform modifications or deletions.

    \n

    Quality Assurance & Analysis

    \n

    The project uses SonarCloud and JetBrains Qodana for static code analysis.

    \n

    SonarCloud

    \n

    To run SonarCloud analysis locally:

    \n
    .\\scripts\\sonar-analysis.ps1 -Token "your_sonar_token"\n
    \n

    JetBrains Qodana

    \n

    To run Qodana analysis locally:\n1. Ensure Docker is installed and running.\n2. (Optional) Install Qodana CLI: winget install JetBrains.Qodana\n3. Execute the analysis script:

    \n
    .\\scripts\\qodana-analysis.ps1\n
    \n

    The report will be generated in target/qodana/report.

    ", - "android-build": "

    To build the Android module locally, you have two primary options: using Android Studio (recommended) or the Command Line.

    \n

    1. Using Android Studio (Recommended)

    \n
      \n
    1. Open Android Studio.
    2. \n
    3. Select Open and navigate to the android/ directory in the project root.
    4. \n
    5. Wait for the IDE to sync with Gradle (this will automatically generate the missing Gradle wrapper files).
    6. \n
    7. Go to Build > Make Project.
    8. \n
    9. To run the app, select an emulator or physical device and click the Run icon.
    10. \n
    \n

    2. Using the Command Line

    \n

    If you have Gradle installed on your system:\n1. Open your terminal and navigate to the android/ directory.\n2. Run the following command:\n bash\n gradle assembleDebug\n3. The generated APK will be available at:\n android/app/build/outputs/apk/debug/app-debug.apk

    \n

    Important: Connecting to the Backend

    \n
      \n
    • Emulator: The app is pre-configured to use http://10.0.2.2:8080/ to connect to a backend running on your host's localhost:8080.
    • \n
    • Physical Device: You will need to update the baseUrl in android/app/src/main/java/ch/goodone/goodone/android/di/NetworkModule.kt to your computer's local IP address (e.g., http://192.168.1.15:8080/).
    • \n
    \n

    Detailed instructions, including prerequisites and troubleshooting, can be found in Android Development.

    \n

    The main README.md has also been updated to include these instructions.

    ", - "backend-dev": "

    Backend Development

    \n

    The backend is a robust Spring Boot application built with Java 21 and Spring Boot 4.

    \n

    Core Technologies

    \n
      \n
    • Spring Boot 4: Framework for rapid application development.
    • \n
    • Java 21: Utilizing the latest LTS features.
    • \n
    • Spring Data JPA: Persistent data storage with Hibernate.
    • \n
    • Spring Security: Role-based access control and secure endpoints.
    • \n
    • Flyway: Database migrations for version-controlled schema changes.
    • \n
    • Maven: Dependency management and build automation.
    • \n
    \n

    Development Setup

    \n

    To run the backend locally:

    \n
      \n
    1. Prerequisites: Ensure you have Java 21 and Maven installed.
    2. \n
    3. Configuration: Create a .env file in the root directory (use .env.example as a template).
    4. \n
    5. Run with IntelliJ:
        \n
      • Open the project in IntelliJ IDEA.
      • \n
      • Use the EnvFile plugin to load the .env file.
      • \n
      • Run GoodoneBackendApplication.
      • \n
      \n
    6. \n
    7. Run with Maven:\n bash\n mvn clean install\n cd backend\n mvn spring-boot:run
    8. \n
    \n

    Database

    \n

    H2 Database (Local Development)

    \n

    The application uses H2 as the default database for local development and testing.

    \n
      \n
    • Console URL: http://localhost:8080/h2-console
    • \n
    • \n

      Settings:

      \n
        \n
      • Driver Class: org.h2.Driver
      • \n
      • JDBC URL (Memory): jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1 (Default for local IDE runs)
      • \n
      • JDBC URL (File/Docker): jdbc:h2:file:./data/goodone-v2;DB_CLOSE_DELAY=-1;AUTO_SERVER=TRUE (When using Docker or h2-file profile)
      • \n
      • User Name: sa
      • \n
      • Password: (leave empty)
      • \n
      \n

      Important: When accessing the H2 console, ensure the JDBC URL starts with jdbc:h2:. For example:\njdbc:h2:file:./data/goodone-v2;DB_CLOSE_DELAY=-1;AUTO_SERVER=TRUE (default for Docker if using ./data)\nor\njdbc:h2:file:./backend/data/goodone-v2;DB_CLOSE_DELAY=-1;AUTO_SERVER=TRUE (default for local IDE/Maven runs)

      \n
    • \n
    \n

    Resetting the Database

    \n

    If the database file becomes corrupted (e.g., due to improper shutdown or concurrent access), you can reset it by deleting the corrupted files.

    \n

    Using PowerShell:

    \n
    .\\scripts\\reset-db.ps1\n
    \n

    Manual Reset:\nSimply delete the following files in the project root:\n- backend\\data\\goodone-v2.mv.db\n- backend\\data\\goodone-v2.trace.db (if present)

    \n

    The application will automatically recreate the schema and default data using Flyway on the next start.

    \n

    Note: To access the console in a Docker environment, ensure you use the 8080 port directly.

    \n

    SELECT * FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = 'PUBLIC'

    \n

    SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA = 'PUBLIC'

    \n
    docker compose logs app | Select-String "jdbc:h2"\n
    \n

    Database JDBC URL [jdbc:h2:file:./data/testdb]

    \n

    jdbc:h2:file:./data/testdb;DB_CLOSE_DELAY=-1;AUTO_SERVER=TRUE

    \n
    SELECT * FROM ACTION_LOG;\n
    \n

    PostgreSQL

    \n

    Supported for production-like environments. See PostgreSQL Setup for details.

    \n

    Email Testing (Mailpit)

    \n

    The application uses Mailpit for local email testing. This allows you to inspect outgoing emails (like verification or password recovery) without needing a real SMTP server.

    \n\n

    When running with Docker Compose, the mailpit service is automatically started. To view sent emails, simply navigate to http://localhost:8025 in your browser.

    \n

    Local Development (IntelliJ/Maven)

    \n

    If you are running the backend outside of Docker, you can still use the Mailpit container for SMTP. Ensure your environment variables or application.properties are configured as follows:

    \n
    SPRING_MAIL_HOST=localhost\nSPRING_MAIL_PORT=1025\nSPRING_MAIL_AUTH=false\nSPRING_MAIL_STARTTLS=false\n
    \n

    API Documentation

    \n
      \n
    • OpenAPI/Swagger: Explore the API endpoints at http://localhost:8080/swagger-ui.html (when enabled).
    • \n
    • REST Principles: The backend follows standard RESTful principles using DTOs for data transfer.
    • \n
    \n

    Testing

    \n
      \n
    • JUnit 5 & MockMvc: For controller and service layer testing.
    • \n
    • High Coverage: We aim for >80% test coverage.
    • \n
    \n

    Run tests:

    \n
    mvn test\n
    ", - "postgres-setup": "

    I have added the PostgreSQL configuration to the project. This includes the necessary driver dependency and a dedicated properties file.

    \n

    1. New Configuration File

    \n

    An additional configuration file has been created at:\nbackend/src/main/resources/application-postgres.properties

    \n

    This file is configured to connect to a local PostgreSQL instance:\n* URL: jdbc:postgresql://localhost:5432/goodone\n* Username/Password: postgres / postgres (Default)\n* DDL Auto: update (Automatically manages the schema)

    \n

    To use this configuration when starting the application, you can set the active profile:\n* Via IntelliJ: Add -Dspring.profiles.active=postgres to the VM options.\n* Via CLI: java -jar app.jar --spring.profiles.active=postgres

    \n

    2. PostgreSQL Setup Instructions

    \n

    Follow these steps to prepare your local PostgreSQL database:

    \n

    Step A: Install PostgreSQL

    \n

    Ensure PostgreSQL is installed and running on your system. You can download it from postgresql.org.

    \n

    Step B: Create the Database

    \n

    Open your terminal or a tool like pgAdmin or psql and execute the following commands:

    \n
    -- Connect as the default postgres user\n-- Create the database used in the properties file\nCREATE DATABASE goodone;\n
    \n

    Step C: Database Schema Initialization

    \n

    You do not need to manually create tables or the schema. \nThe application is configured with spring.jpa.hibernate.ddl-auto=update. When you start the Spring Boot application with the postgres profile active:\n1. Hibernate will connect to the goodone database.\n2. It will automatically detect the entities (User, Task) defined in the code.\n3. It will create the corresponding tables (users, tasks) and constraints (unique emails, etc.) if they do not exist.

    \n

    3. Project Updates

    \n
      \n
    • Updated backend/pom.xml to include the org.postgresql:postgresql runtime dependency.
    • \n
    • The DataInitializer remains active and will populate your local PostgreSQL database with sample admin and user accounts upon the first successful startup.
    • \n
    ", - "frontend-dev": "

    Frontend Development

    \n

    The frontend is a modern Angular application built with Angular 21.

    \n

    Key Technologies

    \n
      \n
    • Standalone Components: Modular and reusable component architecture.
    • \n
    • Signals: Reactive state management using Angular Signals.
    • \n
    • Angular Material: UI components following Material Design principles.
    • \n
    • Modern Control Flow: Using @if, @for, and @empty.
    • \n
    \n

    Development Setup

    \n

    To run the frontend locally:\n1. Navigate to the frontend/ directory.\n2. Run npm install.\n3. Run npm start.\n4. The application will be available at http://localhost:4200 (or http://localhost if using the proxy).

    \n

    Testing

    \n
      \n
    • Unit Tests: Vitest for component and service testing.
    • \n
    • E2E Tests: Playwright for comprehensive end-to-end testing and documentation screenshot automation.
    • \n
    \n

    Run unit tests:

    \n
    npm test\n
    \n

    Run Playwright tests:

    \n
    npx playwright test\n
    \n

    Documentation Screenshots

    \n

    The documentation screenshots in doc/user-guide/workflows/assets are automatically generated using Playwright. This ensures they stay up-to-date with the latest UI.

    \n

    To regenerate the screenshots:\n1. Ensure the application is running (or the Playwright webServer is configured).\n2. Run the following command in the frontend/ directory:

    \n
    npx playwright test registration-docs forgot-password-docs --project=no-auth\n
    \n

    For more details, see Updating Documentation Screenshots.

    \n

    Run lint:

    \n
    npm run lint\n
    ", - "deployment": "

    Deployment & Infrastructure

    \n

    GoodOne is designed to be easily deployable using containerization and cloud services.

    \n

    Docker

    \n

    The application is containerized using a single multi-stage Dockerfile. For details on how we optimized build times, see Docker Build Optimization.

    \n

    The docker-compose.yml file in the root directory orchestrates the services:\n- app: The unified Spring Boot + Angular application.\n- mailpit: A local email testing server.

    \n

    Local Deployment

    \n

    To start the stack locally:

    \n
    docker compose up --build\n
    \n

    The application will be available at:\n- Frontend/API: http://localhost or http://localhost:8080\n- Mailpit Web UI: http://localhost:8025\n- H2 Console: http://localhost:8080/h2-console

    \n

    AWS Deployment

    \n

    The project includes scripts and documentation for deploying to AWS using ECS Fargate.

    \n

    Prerequisites

    \n
      \n
    • AWS CLI configured with appropriate permissions.
    • \n
    • Docker installed and running.
    • \n
    • An ECR repository created for the application image.
    • \n
    \n

    Deployment Process

    \n
      \n
    1. Build and Push: Use the provided scripts in scripts/ to build and push images to ECR.
    2. \n
    3. .\\scripts\\deploy-aws.ps1
    4. \n
    5. ECS Service Update: The script also triggers a new deployment on the ECS services.
    6. \n
    \n

    For detailed AWS setup and Fargate configuration, refer to AWS Fargate Deployment.

    \n

    CI/CD

    \n

    Continuous Integration and Deployment are handled via GitHub Actions.\n- Build & Test: Triggered on every push and pull request.\n- SonarCloud: Static analysis and quality gate checks.\n- Automated Deployment: Configurable to deploy to AWS on successful master branch builds.

    ", - "risk-radar": "

    AI Risk Radar

    \n

    The AI Risk Radar is a core engineering intelligence feature that automatically detects recurring quality, delivery, and documentation risks across the project.

    \n

    🎯 Goal

    \n

    To identify systematic quality problems and delivery blockers early, before they impact release readiness or architectural integrity.

    \n

    🔍 How it works

    \n

    The Risk Radar analyzes various data sources to detect patterns:\n1. Task Logs: Analyzes the Junie Log section in task files for recurring issues, high iteration counts, and blockers.\n2. Verification Sections: Checks if verification instructions are present, clear, and actually followed.\n3. Task Status Inconsistencies: Detects tasks marked as DONE but still containing Open items or missing Verification evidence.\n4. Delivery Patterns: Identifies if certain types of tasks (e.g., AI-ARCH) consistently take longer or have more failures.

    \n

    🚦 Risk Levels

    \n

    Risks are categorized into three severity levels:\n- 🔴 High Risk: Critical blockers or systematic failures that require immediate attention (e.g., core security features missing verification).\n- 🟡 Medium Risk: Quality issues or delivery delays that might impact the sprint goal if not addressed.\n- 🟢 Low Risk: Minor documentation inconsistencies or isolated process deviations.

    \n

    🛠️ Mitigations

    \n

    For every detected risk, the AI provides:\n- Evidence: Concrete task keys or log entries where the pattern was detected.\n- Impact: Assessment of how this risk affects the project (e.g., \"Increases technical debt in the AI layer\").\n- Suggested Mitigations: Actionable steps to resolve the risk (e.g., \"Add mandatory verification template to AI-ARCH tasks\").

    \n

    🖥️ Usage

    \n

    You can access the Risk Radar through the Engineering Intelligence dashboard or directly via the AI Risk Radar page.\n1. Select the relevant Taskset or Sprint.\n2. Define the Date Range for analysis.\n3. Generate the report to see the prioritized list of risks.

    \n

    🔒 Governance & Transparency

    \n

    The Risk Radar is designed for transparency:\n- It never invents facts: Every risk must be backed by concrete evidence from the documentation.\n- It provides a Confidence Score for its analysis.\n- All AI calls are logged and observable for auditing.

    \n
    \n

    Related to: AI-RETRO-02-AI-Risk-Radar.md

    ", - "navigation": "

    Navigation & Features Glossary

    \n

    Welcome to the GoodOne platform. This guide explains the various menus, features, and terms you will encounter in the application.

    \n

    1. General Navigation

    \n

    Dashboard

    \n
      \n
    • What is it: The central hub of the application.
    • \n
    • What it does: Provides a high-level overview of system activity, including open tasks, active users, recent logs, and your most important \"Priority Tasks\".
    • \n
    • Meaning: Your starting point for a daily overview of the project's health.
    • \n
    \n

    Tasks

    \n
      \n
    • What is it: A comprehensive task management system.
    • \n
    • What it does: Allows you to create, edit, delete, and organize your work items. Features include drag-and-drop reordering, priority levels, and status tracking.
    • \n
    • Meaning: The place where the actual work is documented and tracked.
    • \n
    \n

    AI Features

    \n
      \n
    • What is it: A category in the side menu grouping all intelligent capabilities of the platform.
    • \n
    • What it does: Provides access to tools that use Artificial Intelligence to analyze the project.
    • \n
    • Meaning: Highlights the \"AI-First\" nature of the GoodOne platform.
    • \n
    \n

    AI Copilot

    \n
      \n
    • What is it: A persistent AI assistant available throughout the workspace.
    • \n
    • What it does: Offers different modes like Architecture Q&A, Engineering Chat, and Onboarding Help. It uses Retrieval-Augmented Generation (RAG) to provide answers grounded in the project's own documentation.
    • \n
    • Meaning: Your intelligent partner for navigating and understanding the complex codebase.
    • \n
    \n

    2. Engineering Intelligence

    \n

    Engineering Intelligence

    \n
      \n
    • What is it: A dashboard for data-driven engineering insights.
    • \n
    • What it does: Aggregates signals from various AI features to show the overall \"Health Score\" of a sprint or taskset.
    • \n
    • Meaning: Moving from intuition to data-driven management of software projects.
    • \n
    \n

    AI Project Roadmap (Epics)

    \n
      \n
    • What is it: A high-level view of project progress and milestones.
    • \n
    • What it does: Visualizes how individual tasks contribute to larger goals (Epics) and tracks completion rates over time.
    • \n
    • Meaning: Helps stakeholders understand the long-term trajectory of the project.
    • \n
    \n

    Architecture Q&A

    \n
      \n
    • What is it: A specialized AI interface for asking questions about the system design.
    • \n
    • What it does: Scans indexed technical documents and Architecture Decision Records (ADRs) to explain how the system works.
    • \n
    • Meaning: Eliminates the need to manually hunt through hundreds of pages of documentation.
    • \n
    \n

    AI Retrospective (AI Sprint Retrospective)

    \n
      \n
    • What is it: An AI-generated report summarizing a sprint or a set of tasks.
    • \n
    • What it does: Analyzes achievements, technical debt, risks, and process bottlenecks to provide actionable suggestions for the next iteration.
    • \n
    • Meaning: Automates the time-consuming process of gathering data for sprint reviews.
    • \n
    \n

    AI Risk Radar

    \n
      \n
    • What is it: A proactive risk detection tool.
    • \n
    • What it does: Identifies recurring quality problems, delivery blockers, and documentation gaps across task logs.
    • \n
    • Meaning: An \"early warning system\" for project managers and tech leads.
    • \n
    \n

    AI ADR Drift (ADR Drift Detection)

    \n
      \n
    • What is it: A tool that checks if code/implementation matches architectural decisions.
    • \n
    • What it does: Compares recent task outcomes against established Architecture Decision Records (ADRs) to detect \"architectural drift\".
    • \n
    • Meaning: Ensures that the long-term integrity of the system is maintained during rapid development.
    • \n
    \n

    AI Knowledge Coverage

    \n
      \n
    • What is it: An administrative dashboard for the AI's \"brain\".
    • \n
    • What it does: Shows which parts of the documentation are well-indexed and which are \"stale\" or never used by the AI assistant.
    • \n
    • Meaning: Helps documentation owners identify gaps in the project's knowledge base.
    • \n
    \n

    3. Integrations & Analytics

    \n

    GitHub

    \n
      \n
    • What is it: A link to the project's source code repository.
    • \n
    • What it does: Opens the GitHub repository in a new tab, allowing you to inspect the code directly.
    • \n
    • Meaning: Promotes transparency and \"Open Source\" principles within the team.
    • \n
    \n

    Analytics

    \n
      \n
    • What is it: A category for tracking the performance and usage of the system.
    • \n
    • What it does: Groups tools related to AI usage, costs, and system metrics.
    • \n
    • Meaning: Provides transparency into the operational side of the platform.
    • \n
    \n

    AI Economy (AI Usage, Credit Requests, AI Cost Dashboard)

    \n
      \n
    • What is it: The system managing AI resource consumption.
    • \n
    • What it does:
        \n
      • AI Usage: Shows how many AI calls and tokens are consumed by each user or feature.
      • \n
      • Credit Requests: Allows users to request more daily \"AI Credits\" if they reach their limit.
      • \n
      • AI Cost Dashboard: (Admin only) Provides a financial overview of estimated AI costs (e.g., in EUR) per model and feature.
      • \n
      \n
    • \n
    • Meaning: Ensures sustainable and transparent use of expensive AI resources.
    • \n
    \n

    4. Administration

    \n

    Administration

    \n
      \n
    • What is it: The control center for system administrators.
    • \n
    • What it does: Groups all tools required to manage users, security, and global system settings.
    • \n
    • Meaning: Restricted to users with ROLE_ADMIN privileges.
    • \n
    \n

    User Admin

    \n
      \n
    • What is it: User management interface.
    • \n
    • What it does: Allows administrators to create, edit, delete, and assign roles to users.
    • \n
    • Meaning: Controls who has access to the platform and what they can do.
    • \n
    \n

    Documentation (Admin Docs)

    \n
      \n
    • What is it: A management tool for the knowledge base.
    • \n
    • What it does: Allows administrators to upload new documentation (ZIP files) and trigger the reindexing process for AI features.
    • \n
    • Meaning: The mechanism for updating the AI's \"source of truth\".
    • \n
    \n

    AI Settings

    \n
      \n
    • What is it: Global configuration for AI behavior.
    • \n
    • What it does: Allows setting default daily limits, configuring email suffix rules for auto-approving credits, and selecting AI models.
    • \n
    • Meaning: Fine-tunes how AI is integrated into the application.
    • \n
    \n

    System Status

    \n
      \n
    • What is it: Real-time health monitoring.
    • \n
    • What it does: Shows the status of the backend, database, and various versions. It also provides a \"Reset Demo\" button for clearing the environment.
    • \n
    • Meaning: Ensures the platform is running smoothly.
    • \n
    \n

    Logs

    \n
      \n
    • What is it: The system's audit trail.
    • \n
    • What it does: Records every important action (login, task creation, user updates) for security and auditing purposes.
    • \n
    • Meaning: Provides accountability and a history of changes.
    • \n
    \n

    5. Specialized AI Concepts

    \n

    Core AI Capabilities

    \n
      \n
    • What is it: The underlying set of AI functions that power the app.
    • \n
    • What it does: Includes embedding generation, vector search, and prompt engineering using models like GPT-4o or Ollama.
    • \n
    • Meaning: The \"engine\" under the hood of GoodOne.
    • \n
    \n

    AI Task Parsing

    \n
      \n
    • What is it: Natural language task entry.
    • \n
    • What it does: When you type a task description, the AI automatically extracts the title, priority, status, and due date.
    • \n
    • Meaning: Speeds up administrative overhead by understanding human intent.
    • \n
    \n

    Engineering Chat & Onboarding Help

    \n
      \n
    • What is it: Specialized modes of the AI Copilot.
    • \n
    • What it does:
        \n
      • Engineering Chat: Helps with technical questions and coding context.
      • \n
      • Onboarding Help: Specifically answers questions about how to use GoodOne and where to find information.
      • \n
      \n
    • \n
    • Meaning: Personalized assistance for every stage of the developer journey.
    • \n
    ", - "index": "

    Features Index

    \n

    This directory provides detailed information about the core features of the AI Engineering Intelligence Platform.

    \n

    🚀 Core Features

    \n
      \n
    • AI Risk Radar: Detects systematic quality, delivery, and documentation risks.
    • \n
    • AI Sprint Retrospective: Generates AI-assisted sprint retrospectives based on development tasks.
    • \n
    • ADR Drift Detection: Monitors implementation and detects when systems drift away from architectural decisions.
    • \n
    • AI Task Parsing: Turns natural language into structured work items.
    • \n
    • AI Onboarding Assistant: Provides context-aware onboarding help for engineers.
    • \n
    • AI Economy Dashboard: Tracks and understands AI usage and costs across the platform.
    • \n
    • Navigation & Features Glossary: Detailed explanation of all UI elements and capabilities.
    • \n
    \n
    \n

    For a high-level overview, see the Project Index.

    ", - "md-to-confluence": "
    import markdown\nimport requests\nimport json\nimport os\n\n# Configuration\nCONFLUENCE_URL = "https://your-domain.atlassian.net/wiki/rest/api/content"\nUSERNAME = "your-email@example.com"\nAPI_TOKEN = "your-api-token"\nSPACE_KEY = "DOC"\nPARENT_PAGE_ID = "12345" # Optional: ID of the parent page\n\ndef md_to_confluence_storage(md_file_path):\n    """\n    Converts a Markdown file to HTML which is compatible with Confluence Storage Format.\n    Note: Standard HTML is often accepted by Confluence API, but some macros might need special tags.\n    """\n    with open(md_file_path, 'r', encoding='utf-8') as f:\n        md_content = f.read()\n\n    # Convert Markdown to HTML\n    html_content = markdown.markdown(md_content, extensions=['extra', 'toc'])\n    return html_content\n\ndef post_to_confluence(title, html_content, page_id=None):\n    """\n    Posts content to Confluence. If page_id is provided, it updates the page.\n    """\n    headers = {\n        "Accept": "application/json",\n        "Content-Type": "application/json"\n    }\n\n    auth = (USERNAME, API_TOKEN)\n\n    data = {\n        "type": "page",\n        "title": title,\n        "space": {"key": SPACE_KEY},\n        "body": {\n            "storage": {\n                "value": html_content,\n                "representation": "storage"\n            }\n        }\n    }\n\n    if PARENT_PAGE_ID:\n        data["ancestors"] = [{"id": PARENT_PAGE_ID}]\n\n    if page_id:\n        # Update existing page (needs version increment)\n        # First, get current version\n        resp = requests.get(f"{CONFLUENCE_URL}/{page_id}?expand=version", auth=auth)\n        version = resp.json()['version']['number'] + 1\n        data["version"] = {"number": version}\n        url = f"{CONFLUENCE_URL}/{page_id}"\n        response = requests.put(url, data=json.dumps(data), headers=headers, auth=auth)\n    else:\n        # Create new page\n        url = CONFLUENCE_URL\n        response = requests.post(url, data=json.dumps(data), headers=headers, auth=auth)\n\n    return response.status_code, response.text\n\nif __name__ == "__main__":\n    docs = [\n        ("User Guide", "doc/userguide/user-guide.md"),\n        ("Admin Guide", "doc/userguide/admin-guide.md"),\n        ("FAQ", "doc/userguide/faq.md")\n    ]\n\n    print("This script is a proposal. Please configure your Confluence credentials before running.")\n    # for title, path in docs:\n    #     if os.path.exists(path):\n    #         print(f"Converting {path}...")\n    #         storage_format = md_to_confluence_storage(path)\n    #         # status, text = post_to_confluence(title, storage_format)\n    #         # print(f"Status: {status}")\n\n
    " -} \ No newline at end of file diff --git a/frontend/public/assets/help/help-data.json b/frontend/public/assets/help/help-data.json deleted file mode 100644 index 742cde25..00000000 --- a/frontend/public/assets/help/help-data.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "readme": "

    GoodOne Application

    \n

    This is a full-stack application with a Spring Boot backend and an Angular frontend.

    \n

    Prerequisites

    \n\n

    Running with Docker

    \n

    To run the entire application using Docker Compose, navigate to the root directory and run:

    \n
    docker compose up --build\n
    \n

    The application will be available at:\n- Frontend: http://localhost\n- Backend API: http://localhost:8080/api\n- H2 Console: http://localhost:8080/h2-console (JDBC URL: jdbc:h2:mem:testdb)

    \n

    Deployment Scripts

    \n

    Scripts are available in the scripts/ folder for common deployment tasks (PowerShell and Windows CMD):

    \n
      \n
    • Local Docker Deployment: .\\scripts\\deploy-local.ps1 or .\\scripts\\deploy-local.bat
    • \n
    • Runs docker compose up --build -d to start the application locally in the background.
    • \n
    • AWS Deployment: .\\scripts\\deploy-aws.ps1 or .\\scripts\\deploy-aws.bat
    • \n
    • Authenticates with AWS ECR, builds, tags, and pushes frontend and backend images, and forces a new deployment on ECS services.
    • \n
    \n

    Project Structure

    \n
      \n
    • backend/: Spring Boot application.
    • \n
    • frontend/: Angular application.
    • \n
    • android/: Android Jetpack Compose application.
    • \n
    • docker-compose.yml: Orchestration for both services.
    • \n
    \n

    Development

    \n

    Backend

    \n

    Navigate to backend/ and run ./mvnw spring-boot:run.

    \n

    Frontend (Web)

    \n

    Navigate to frontend/ and run npm install and then npm start.\nThe Angular development server is configured to proxy /api requests to http://localhost:8080. Ensure the backend is running.

    \n

    Documentation

    \n", - "user-guide": "

    User Guide

    \n

    Welcome to the GoodOne User Guide. This document provides instructions on how to use the frontend application features.

    \n

    Table of Contents

    \n
      \n
    1. Getting Started
    2. \n
    3. Dashboard
    4. \n
    5. Task Management
    6. \n
    7. User Profile
    8. \n
    9. Logout
    10. \n
    \n

    Getting Started

    \n

    To access the application, navigate to the frontend URL (typically http://localhost). You will be prompted to log in. If you don't have an account, you can register a new one.

    \n

    Login

    \n

    Enter your username and password to access your account.

    \n

    Registration

    \n

    If you are a new user, click on the \"Register\" link. Provide your first name, last name, desired login, email address, and password.

    \n

    Dashboard

    \n

    The Dashboard provides an overview of your activities and the system status:\n- Summary Cards: Quick stats on Open Tasks, Active Users, Completed Tasks, and Today's Logs.\n- Task Overview: A visual distribution of tasks by status (Open, In Progress, Completed).\n- Recent Activity: A list of the latest actions performed in the system.\n- Priority Tasks: A list of high-priority tasks that need your attention.

    \n

    Task Management

    \n

    The Task Management page allows you to organize your work:\n- Add Task: Click the \"Add Task\" button to create a new task. You can specify a title, description, due date, priority, and status.\n- Filter and Sort: Filter tasks by status (Open, In Progress, Completed) or reset sorting to view them by priority.\n- Edit Task: Click the edit icon on a task card to modify its details.\n- Delete Task: Click the delete icon to remove a task.\n- Drag and Drop: You can reorder tasks by dragging them using the handle (available when not filtering).

    \n

    User Profile

    \n

    In the Profile section, you can view your personal details, including your name, email, and assigned role.

    \n

    Logout

    \n

    To securely leave the application, click the \"Logout\" button in the side navigation menu.

    ", - "admin-guide": "

    Admin Guide

    \n

    This guide is intended for system administrators of the GoodOne application. Administrators have access to additional features for user management and system monitoring.

    \n

    Table of Contents

    \n
      \n
    1. User Administration
    2. \n
    3. System Logs
    4. \n
    5. Roles and Permissions
    6. \n
    \n

    User Administration

    \n

    The User Administration page allows you to manage all users in the system:\n- List Users: View a list of all registered users, including their login name, full name, email, and role.\n- Add User: Create a new user account manually by providing their personal details and assigning a role.\n- Edit User: Modify the details of an existing user. Note that you cannot change the login name once a user is created.\n- Delete User: Remove a user from the system. You cannot delete your own account.\n- View User (Read-only): Users with the ROLE_ADMIN_READ role can view user details but cannot make changes.

    \n

    System Logs

    \n

    The System Logs page provides an audit trail of actions performed within the application:\n- Audit Trail: View logs including timestamp, user login, action performed, and additional details.\n- Filtering: Filter logs by action type (Login, Tasks, User Admin) and date range.\n- Sorting: Sort logs by timestamp.\n- Paging: Navigate through large sets of logs using the paginator.\n- Clear Logs: Administrators with full write access can clear all logs using the \"Clear All Logs\" button.

    \n

    Roles and Permissions

    \n

    The application uses the following roles to control access:\n- ROLE_USER: Standard user access. Can manage their own tasks and view their profile.\n- ROLE_ADMIN: Full administrative access. Can manage users, view all logs, and perform system-wide actions.\n- ROLE_ADMIN_READ: Read-only administrative access. Can view user lists and logs but cannot perform modifications or deletions.

    ", - "faq": "

    Frequently Asked Questions (FAQ)

    \n

    General

    \n

    Q: What is GoodOne?

    \n

    A: GoodOne is a task management application featuring a modern Angular frontend, a Spring Boot backend, and an Android mobile app.

    \n

    Q: How do I get started?

    \n

    A: Register for an account, log in, and start creating tasks on the Task Management page.

    \n

    Accounts and Security

    \n

    Q: I forgot my password. How can I reset it?

    \n

    A: Currently, password reset must be handled by an administrator. Please contact your system administrator.

    \n

    Q: Can I change my role?

    \n

    A: User roles can only be changed by an administrator via the User Administration panel.

    \n

    Task Management

    \n

    Q: Can I reorder my tasks?

    \n

    A: Yes, you can use the drag handle on the left side of each task card to reorder them manually. Note that manual reordering is disabled when a status filter is active.

    \n

    Q: What do the different task priorities mean?

    \n

    A:\n- High: Urgent tasks that should be addressed immediately.\n- Medium: Important tasks that should be completed soon.\n- Low: Non-urgent tasks.

    \n

    Troubleshooting

    \n

    Q: The application is not loading. What should I do?

    \n

    A: Ensure that both the backend and frontend services are running. If you are using Docker, run docker compose up to start all services.

    \n

    Q: I am getting an \"Access Denied\" error.

    \n

    A: This error occurs if you try to access a page for which you do not have the required permissions (e.g., trying to access User Administration as a regular user).

    " -} \ No newline at end of file diff --git a/frontend/public/assets/help/help-map-de-ch.json b/frontend/public/assets/help/help-map-de-ch.json new file mode 100644 index 00000000..f9f26340 --- /dev/null +++ b/frontend/public/assets/help/help-map-de-ch.json @@ -0,0 +1,1436 @@ +{ + "user-guide": "doc/user-guide/user-guide_de.md", + "faq": "doc/user-guide/faq_de.md", + "admin-guide": "doc/admin-guide/admin-guide_de.md", + "risk-radar": "doc/features/risk-radar_de.md", + "navigation": "doc/features/navigation_de.md", + "index": "doc/features/index_de.md", + "CONTRIBUTING": "doc/CONTRIBUTING.md", + "contributing": "doc/CONTRIBUTING.md", + "indexed-files-count": "doc/indexed-files-count.md", + "known-issues": "doc/known-issues.md", + "operations-guide": "doc/operations-guide.md", + "operations-guide_de": "doc/operations-guide_de.md", + "README-old": "doc/README-old.md", + "readme-old": "doc/README-old.md", + "README_enhanced": "doc/README_enhanced.md", + "readme_enhanced": "doc/README_enhanced.md", + "ROADMAP": "doc/ROADMAP.md", + "roadmap": "doc/ROADMAP.md", + "admin-guide_de": "doc/admin-guide/admin-guide_de.md", + "ollama-docker-performance": "doc/ai/ollama-docker-performance.md", + "ollama-setup": "doc/ai/ollama-setup.md", + "jackson-runtime-conflict-analysis": "doc/analysis/jackson-runtime-conflict-analysis.md", + "fargate-deployment": "doc/deployment/fargate-deployment.md", + "h2-lock-fargate": "doc/deployment/h2-lock-fargate.md", + "aws-technical-reference": "doc/development/aws-technical-reference.md", + "adr-ai-mode-of-use": "doc/development/ai-use/adr-ai-mode-of-use.md", + "ai-mode-comparison-table": "doc/development/ai-use/ai-mode-comparison-table.md", + "ai-mode-developer": "doc/development/ai-use/ai-mode-developer.md", + "ai-mode-slides": "doc/development/ai-use/ai-mode-slides.md", + "how-we-use-ai": "doc/development/ai-use/how-we-use-ai.md", + "dark-mode-chrome": "doc/development/analysis/dark-mode-chrome.md", + "lighthouse-dark-mode-guide": "doc/development/analysis/lighthouse-dark-mode-guide.md", + "lighthouse-economic-feasibility": "doc/development/analysis/lighthouse-economic-feasibility.md", + "web-auditing-alternatives": "doc/development/analysis/web-auditing-alternatives.md", + "android-build": "doc/development/android/android-build.md", + "Android-Development": "doc/development/android/Android-Development.md", + "android-development": "doc/development/android/Android-Development.md", + "android-studio-instructions": "doc/development/android/android-studio-instructions.md", + "Backend-Development": "doc/development/backend/Backend-Development.md", + "backend-development": "doc/development/backend/Backend-Development.md", + "backend-log-location": "doc/development/backend/backend-log-location.md", + "postgres_setup": "doc/development/backend/postgres_setup.md", + "Development-Standards": "doc/development/common/Development-Standards.md", + "development-standards": "doc/development/common/Development-Standards.md", + "mcp-analysis": "doc/development/common/mcp-analysis.md", + "mcp-architecture": "doc/development/common/mcp-architecture.md", + "mcp-server": "doc/development/common/mcp-server.md", + "sonar-console-stall": "doc/development/devops/sonar-console-stall.md", + "sonar-integration": "doc/development/devops/sonar-integration.md", + "Frontend-Development": "doc/development/frontend/Frontend-Development.md", + "frontend-development": "doc/development/frontend/Frontend-Development.md", + "playwright": "doc/development/frontend/playwright.md", + "ui-primitives": "doc/development/frontend/ui-primitives.md", + "Updating-Documentation-Screenshots": "doc/development/frontend/Updating-Documentation-Screenshots.md", + "updating-documentation-screenshots": "doc/development/frontend/Updating-Documentation-Screenshots.md", + "aws-waf-costs": "doc/development/security/aws-waf-costs.md", + "csrf-hardening-drawback": "doc/development/security/csrf-hardening-drawback.md", + "lightweight-threat-model": "doc/development/security/lightweight-threat-model.md", + "s3-gateway-endpoint-setup": "doc/development/security/s3-gateway-endpoint-setup.md", + "security-assessment": "doc/development/security/security-assessment.md", + "security-roadmap-2": "doc/development/security/security-roadmap-2.md", + "security-roadmap-3": "doc/development/security/security-roadmap-3.md", + "security-roadmap-4": "doc/development/security/security-roadmap-4.md", + "security-roadmap": "doc/development/security/security-roadmap.md", + "snyk-integration-guide": "doc/development/security/snyk-integration-guide.md", + "transmitting-snyk-results": "doc/development/security/transmitting-snyk-results.md", + "reduce-styling-iterations": "doc/development/ux-improvement/reduce-styling-iterations.md", + "sidenav-toggle": "doc/development/ux-improvement/sidenav-toggle.md", + "ux-assessment-junie-prompts": "doc/development/ux-improvement/ux-assessment-junie-prompts.md", + "ux-review-assets-logs": "doc/development/ux-improvement/ux-review-assets-logs.md", + "knowledge-classification": "doc/evaluation/knowledge-classification.md", + "REVIEW_WORKFLOW": "doc/evaluation/benchmarks/REVIEW_WORKFLOW.md", + "review_workflow": "doc/evaluation/benchmarks/REVIEW_WORKFLOW.md", + "index_de": "doc/features/index_de.md", + "navigation_de": "doc/features/navigation_de.md", + "risk-radar_de": "doc/features/risk-radar_de.md", + "Deployment": "doc/infrastructure/Deployment.md", + "deployment": "doc/infrastructure/Deployment.md", + "Docker-Optimization": "doc/infrastructure/Docker-Optimization.md", + "docker-optimization": "doc/infrastructure/Docker-Optimization.md", + "k8s-setup": "doc/infrastructure/k8s/k8s-setup.md", + "placeholder": "doc/knowledge/placeholder.md", + "REPOSITORY-BRAIN": "doc/knowledge/REPOSITORY-BRAIN.md", + "repository-brain": "doc/knowledge/REPOSITORY-BRAIN.md", + "test-uploaded": "doc/knowledge/test-uploaded.md", + "adr-format-guideline": "doc/knowledge/adrs/adr-format-guideline.md", + "adr-full-set": "doc/knowledge/adrs/adr-full-set.md", + "AGENT-RULES": "doc/knowledge/ai-execution/AGENT-RULES.md", + "agent-rules": "doc/knowledge/ai-execution/AGENT-RULES.md", + "AI-CODEBASE-INDEX": "doc/knowledge/ai-execution/AI-CODEBASE-INDEX.md", + "ai-codebase-index": "doc/knowledge/ai-execution/AI-CODEBASE-INDEX.md", + "AI-CONTEXT-MAP": "doc/knowledge/ai-execution/AI-CONTEXT-MAP.md", + "ai-context-map": "doc/knowledge/ai-execution/AI-CONTEXT-MAP.md", + "AI-PROJECT-INTELLIGENCE-DASHBOARD": "doc/knowledge/ai-execution/AI-PROJECT-INTELLIGENCE-DASHBOARD.md", + "ai-project-intelligence-dashboard": "doc/knowledge/ai-execution/AI-PROJECT-INTELLIGENCE-DASHBOARD.md", + "AI-SYSTEM-DIAGRAM": "doc/knowledge/ai-execution/AI-SYSTEM-DIAGRAM.md", + "ai-system-diagram": "doc/knowledge/ai-execution/AI-SYSTEM-DIAGRAM.md", + "AI-TASK-PLANNING-GUIDE": "doc/knowledge/ai-execution/AI-TASK-PLANNING-GUIDE.md", + "ai-task-planning-guide": "doc/knowledge/ai-execution/AI-TASK-PLANNING-GUIDE.md", + "DO-NOT-TOUCH": "doc/knowledge/ai-execution/DO-NOT-TOUCH.md", + "do-not-touch": "doc/knowledge/ai-execution/DO-NOT-TOUCH.md", + "KNOWN-PITFALLS": "doc/knowledge/ai-execution/KNOWN-PITFALLS.md", + "known-pitfalls": "doc/knowledge/ai-execution/KNOWN-PITFALLS.md", + "REPO-ENTRY-POINTS": "doc/knowledge/ai-execution/REPO-ENTRY-POINTS.md", + "repo-entry-points": "doc/knowledge/ai-execution/REPO-ENTRY-POINTS.md", + "START-HERE": "doc/knowledge/ai-execution/START-HERE.md", + "start-here": "doc/knowledge/ai-execution/START-HERE.md", + "TASK-EXECUTION-CHECKLIST": "doc/knowledge/ai-execution/TASK-EXECUTION-CHECKLIST.md", + "task-execution-checklist": "doc/knowledge/ai-execution/TASK-EXECUTION-CHECKLIST.md", + "AI-FEEDBACK-LOOP": "doc/knowledge/ai-feedback/AI-FEEDBACK-LOOP.md", + "ai-feedback-loop": "doc/knowledge/ai-feedback/AI-FEEDBACK-LOOP.md", + "FINDING-SCHEMA": "doc/knowledge/ai-feedback/FINDING-SCHEMA.md", + "finding-schema": "doc/knowledge/ai-feedback/FINDING-SCHEMA.md", + "TASK-GENERATION-RULES": "doc/knowledge/ai-feedback/TASK-GENERATION-RULES.md", + "task-generation-rules": "doc/knowledge/ai-feedback/TASK-GENERATION-RULES.md", + "visualizing-the-final-system": "doc/knowledge/ai-readme/visualizing-the-final-system.md", + "ai-data-flow": "doc/knowledge/architecture/ai-data-flow.md", + "AI-ENGINEERING-CONTEXT": "doc/knowledge/architecture/AI-ENGINEERING-CONTEXT.md", + "ai-engineering-context": "doc/knowledge/architecture/AI-ENGINEERING-CONTEXT.md", + "AI-ROADMAP-VISUAL": "doc/knowledge/architecture/AI-ROADMAP-VISUAL.md", + "ai-roadmap-visual": "doc/knowledge/architecture/AI-ROADMAP-VISUAL.md", + "AI-SYSTEM-OVERVIEW": "doc/knowledge/architecture/AI-SYSTEM-OVERVIEW.md", + "ai-system-overview": "doc/knowledge/architecture/AI-SYSTEM-OVERVIEW.md", + "AI_SYSTEM_MENTAL_MODEL": "doc/knowledge/architecture/AI_SYSTEM_MENTAL_MODEL.md", + "ai_system_mental_model": "doc/knowledge/architecture/AI_SYSTEM_MENTAL_MODEL.md", + "api-overview": "doc/knowledge/architecture/api-overview.md", + "ARCHITECTURE-QA-SEEDS": "doc/knowledge/architecture/ARCHITECTURE-QA-SEEDS.md", + "architecture-qa-seeds": "doc/knowledge/architecture/ARCHITECTURE-QA-SEEDS.md", + "backend-architecture": "doc/knowledge/architecture/backend-architecture.md", + "current-system-analysis": "doc/knowledge/architecture/current-system-analysis.md", + "developer-onboarding": "doc/knowledge/architecture/developer-onboarding.md", + "erd": "doc/knowledge/architecture/erd.md", + "frontend-architecture": "doc/knowledge/architecture/frontend-architecture.md", + "module-dependencies": "doc/knowledge/architecture/module-dependencies.md", + "spring-boot-profiles": "doc/knowledge/architecture/spring-boot-profiles.md", + "system-overview": "doc/knowledge/architecture/system-overview.md", + "AI-ARCHITECTURE-POSTER": "doc/knowledge/architecture/backlog/AI-ARCHITECTURE-POSTER.md", + "ai-architecture-poster": "doc/knowledge/architecture/backlog/AI-ARCHITECTURE-POSTER.md", + "01-roadmap-overview": "doc/knowledge/architecture/overview/01-roadmap-overview.md", + "02-phase-and-epic-priority": "doc/knowledge/architecture/overview/02-phase-and-epic-priority.md", + "03-architecture-layers": "doc/knowledge/architecture/overview/03-architecture-layers.md", + "04-roadmap-graph": "doc/knowledge/architecture/overview/04-roadmap-graph.md", + "05-governance-notes": "doc/knowledge/architecture/overview/05-governance-notes.md", + "06-task-index": "doc/knowledge/architecture/overview/06-task-index.md", + "AI-ROADMAP-OVERVIEW": "doc/knowledge/architecture/roadmap/AI-ROADMAP-OVERVIEW.md", + "ai-roadmap-overview": "doc/knowledge/architecture/roadmap/AI-ROADMAP-OVERVIEW.md", + "README": "doc/knowledge/architecture/roadmap/README.md", + "readme": "doc/knowledge/architecture/roadmap/README.md", + "diagram-tool-comparison": "doc/knowledge/architecture/workflows/diagram-tool-comparison.md", + "registration-workflows": "doc/knowledge/architecture/workflows/registration-workflows.md", + "task-workflows": "doc/knowledge/architecture/workflows/task-workflows.md", + "use-cases": "doc/knowledge/architecture/workflows/use-cases.md", + "AI-TASK-PREFIX-INDEX": "doc/knowledge/junie-tasks/AI-TASK-PREFIX-INDEX.md", + "ai-task-prefix-index": "doc/knowledge/junie-tasks/AI-TASK-PREFIX-INDEX.md", + "fix-sonar-issues": "doc/knowledge/junie-tasks/fix-sonar-issues.md", + "internal-presentation": "doc/knowledge/junie-tasks/internal-presentation.md", + "JUNIE_TASK_INDEX": "doc/knowledge/junie-tasks/JUNIE_TASK_INDEX.md", + "junie_task_index": "doc/knowledge/junie-tasks/JUNIE_TASK_INDEX.md", + "local-quodana": "doc/knowledge/junie-tasks/local-quodana.md", + "md-prompt-log": "doc/knowledge/junie-tasks/md-prompt-log.md", + "taskindex": "doc/knowledge/junie-tasks/taskindex.md", + "tasks-overview": "doc/knowledge/junie-tasks/tasks-overview.md", + "test-coverage-sonar": "doc/knowledge/junie-tasks/test-coverage-sonar.md", + "AI-AI-01-Improve-Architecture-QA-Retrieval": "doc/knowledge/junie-tasks/AI-AI/AI-AI-01-Improve-Architecture-QA-Retrieval.md", + "ai-ai-01-improve-architecture-qa-retrieval": "doc/knowledge/junie-tasks/AI-AI/AI-AI-01-Improve-Architecture-QA-Retrieval.md", + "AI-AI-02 - Add Risk Radar Rule Engine": "doc/knowledge/junie-tasks/AI-AI/AI-AI-02 - Add Risk Radar Rule Engine.md", + "ai-ai-02 - add risk radar rule engine": "doc/knowledge/junie-tasks/AI-AI/AI-AI-02 - Add Risk Radar Rule Engine.md", + "AI-AI-03-Improve-Sprint-Retrospective-Prompting": "doc/knowledge/junie-tasks/AI-AI/AI-AI-03-Improve-Sprint-Retrospective-Prompting.md", + "ai-ai-03-improve-sprint-retrospective-prompting": "doc/knowledge/junie-tasks/AI-AI/AI-AI-03-Improve-Sprint-Retrospective-Prompting.md", + "AI-AI-04 - Add AI Onboarding Assistant": "doc/knowledge/junie-tasks/AI-AI/AI-AI-04 - Add AI Onboarding Assistant.md", + "ai-ai-04 - add ai onboarding assistant": "doc/knowledge/junie-tasks/AI-AI/AI-AI-04 - Add AI Onboarding Assistant.md", + "AI-AI-05 - Add AI What-If Impact Simulator": "doc/knowledge/junie-tasks/AI-AI/AI-AI-05 - Add AI What-If Impact Simulator.md", + "ai-ai-05 - add ai what-if impact simulator": "doc/knowledge/junie-tasks/AI-AI/AI-AI-05 - Add AI What-If Impact Simulator.md", + "AI-AI-06-Add-AI-Backlog-Analyzer": "doc/knowledge/junie-tasks/AI-AI/AI-AI-06-Add-AI-Backlog-Analyzer.md", + "ai-ai-06-add-ai-backlog-analyzer": "doc/knowledge/junie-tasks/AI-AI/AI-AI-06-Add-AI-Backlog-Analyzer.md", + "AI-AI-07-Engineering-Context-Index": "doc/knowledge/junie-tasks/AI-AI/AI-AI-07-Engineering-Context-Index.md", + "ai-ai-07-engineering-context-index": "doc/knowledge/junie-tasks/AI-AI/AI-AI-07-Engineering-Context-Index.md", + "AI-AI-08 - Task Relationship Engine": "doc/knowledge/junie-tasks/AI-AI/AI-AI-08 - Task Relationship Engine.md", + "ai-ai-08 - task relationship engine": "doc/knowledge/junie-tasks/AI-AI/AI-AI-08 - Task Relationship Engine.md", + "AI-AI-09-Engineering-Insight-Ranking-Engine": "doc/knowledge/junie-tasks/AI-AI/AI-AI-09-Engineering-Insight-Ranking-Engine.md", + "ai-ai-09-engineering-insight-ranking-engine": "doc/knowledge/junie-tasks/AI-AI/AI-AI-09-Engineering-Insight-Ranking-Engine.md", + "AI-AI-09A-Task-Relationship-Provenance-and-Trust-Controls": "doc/knowledge/junie-tasks/AI-AI/AI-AI-09A-Task-Relationship-Provenance-and-Trust-Controls.md", + "ai-ai-09a-task-relationship-provenance-and-trust-controls": "doc/knowledge/junie-tasks/AI-AI/AI-AI-09A-Task-Relationship-Provenance-and-Trust-Controls.md", + "AI-AI-10-Fix-Onboarding-Assistant-Endpoint": "doc/knowledge/junie-tasks/AI-AI/AI-AI-10-Fix-Onboarding-Assistant-Endpoint.md", + "ai-ai-10-fix-onboarding-assistant-endpoint": "doc/knowledge/junie-tasks/AI-AI/AI-AI-10-Fix-Onboarding-Assistant-Endpoint.md", + "AI-AI-11-document-tree-coverage": "doc/knowledge/junie-tasks/AI-AI/AI-AI-11-document-tree-coverage.md", + "ai-ai-11-document-tree-coverage": "doc/knowledge/junie-tasks/AI-AI/AI-AI-11-document-tree-coverage.md", + "AI-AI-12-Fix-Architecture-QA-Schema-Validation": "doc/knowledge/junie-tasks/AI-AI/AI-AI-12-Fix-Architecture-QA-Schema-Validation.md", + "ai-ai-12-fix-architecture-qa-schema-validation": "doc/knowledge/junie-tasks/AI-AI/AI-AI-12-Fix-Architecture-QA-Schema-Validation.md", + "AI-AI-13-Fix-Copilot-JSON-Schema-Extraction": "doc/knowledge/junie-tasks/AI-AI/AI-AI-13-Fix-Copilot-JSON-Schema-Extraction.md", + "ai-ai-13-fix-copilot-json-schema-extraction": "doc/knowledge/junie-tasks/AI-AI/AI-AI-13-Fix-Copilot-JSON-Schema-Extraction.md", + "AI-AI-20-Continuous-Insight-Scheduler": "doc/knowledge/junie-tasks/AI-AI/AI-AI-20-Continuous-Insight-Scheduler.md", + "ai-ai-20-continuous-insight-scheduler": "doc/knowledge/junie-tasks/AI-AI/AI-AI-20-Continuous-Insight-Scheduler.md", + "AI-AI-21-Insight-History-Store": "doc/knowledge/junie-tasks/AI-AI/AI-AI-21-Insight-History-Store.md", + "ai-ai-21-insight-history-store": "doc/knowledge/junie-tasks/AI-AI/AI-AI-21-Insight-History-Store.md", + "AI-AN-21-jackson-runtime-conflict-analysis": "doc/knowledge/junie-tasks/AI-AN/AI-AN-21-jackson-runtime-conflict-analysis.md", + "ai-an-21-jackson-runtime-conflict-analysis": "doc/knowledge/junie-tasks/AI-AN/AI-AN-21-jackson-runtime-conflict-analysis.md", + "AI-ARCH-01-ADR-Knowledge-Index": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-01-ADR-Knowledge-Index.md", + "ai-arch-01-adr-knowledge-index": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-01-ADR-Knowledge-Index.md", + "AI-ARCH-02 - Architecture Change Detector": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-02 - Architecture Change Detector.md", + "ai-arch-02 - architecture change detector": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-02 - Architecture Change Detector.md", + "AI-ARCH-03-Prompt-templates-v1-strict-structured-JSON-outputs": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-03-Prompt-templates-v1-strict-structured-JSON-outputs.md", + "ai-arch-03-prompt-templates-v1-strict-structured-json-outputs": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-03-Prompt-templates-v1-strict-structured-JSON-outputs.md", + "AI-ARCH-03R-Architecture-Change-Signal-Extraction": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-03R-Architecture-Change-Signal-Extraction.md", + "ai-arch-03r-architecture-change-signal-extraction": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-03R-Architecture-Change-Signal-Extraction.md", + "AI-ARCH-04-AI-backend-endpoints-application-layer-no-model-calls-in-controllers": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-04-AI-backend-endpoints-application-layer-no-model-calls-in-controllers.md", + "ai-arch-04-ai-backend-endpoints-application-layer-no-model-calls-in-controllers": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-04-AI-backend-endpoints-application-layer-no-model-calls-in-controllers.md", + "AI-ARCH-05-Docs-ingestion-into-Postgres-pgvector-schema-reindex-endpoint": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-05-Docs-ingestion-into-Postgres-pgvector-schema-reindex-endpoint.md", + "ai-arch-05-docs-ingestion-into-postgres-pgvector-schema-reindex-endpoint": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-05-Docs-ingestion-into-Postgres-pgvector-schema-reindex-endpoint.md", + "AI-ARCH-06-Embeddings-vector-retrieval-sources-in-Architecture-explain": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-06-Embeddings-vector-retrieval-sources-in-Architecture-explain.md", + "ai-arch-06-embeddings-vector-retrieval-sources-in-architecture-explain": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-06-Embeddings-vector-retrieval-sources-in-Architecture-explain.md", + "AI-ARCH-07-Quick-Add-AI-enhancement-hybrid-deterministic-parser-AI-parse-preview-workflow": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-07-Quick-Add-AI-enhancement-hybrid-deterministic-parser-AI-parse-preview-workflow.md", + "ai-arch-07-quick-add-ai-enhancement-hybrid-deterministic-parser-ai-parse-preview-workflow": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-07-Quick-Add-AI-enhancement-hybrid-deterministic-parser-AI-parse-preview-workflow.md", + "AI-ARCH-08-Angular-UI-Architecture-Q-A-page-with-sources-Quick-Add-preview-components": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-08-Angular-UI-Architecture-Q-A-page-with-sources-Quick-Add-preview-components.md", + "ai-arch-08-angular-ui-architecture-q-a-page-with-sources-quick-add-preview-components": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-08-Angular-UI-Architecture-Q-A-page-with-sources-Quick-Add-preview-components.md", + "AI-ARCH-09-Security-observability-for-AI-endpoints": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-09-Security-observability-for-AI-endpoints.md", + "ai-arch-09-security-observability-for-ai-endpoints": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-09-Security-observability-for-AI-endpoints.md", + "AI-ARCH-10-CI-CD-tests-pgvector-service-Playwright-smoke-suite": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-10-CI-CD-tests-pgvector-service-Playwright-smoke-suite.md", + "ai-arch-10-ci-cd-tests-pgvector-service-playwright-smoke-suite": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-10-CI-CD-tests-pgvector-service-Playwright-smoke-suite.md", + "AI-ARCH-11-Add-Open-AI-Config": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-11-Add-Open-AI-Config.md", + "ai-arch-11-add-open-ai-config": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-11-Add-Open-AI-Config.md", + "AI-ARCH-12-Uppload-Docs": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-12-Uppload-Docs.md", + "ai-arch-12-uppload-docs": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-12-Uppload-Docs.md", + "AI-ARCH-13-AI-Credits-Limit": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-13-AI-Credits-Limit.md", + "ai-arch-13-ai-credits-limit": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-13-AI-Credits-Limit.md", + "AI-ARCH-14-AI-Credits-Dashboard": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-14-AI-Credits-Dashboard.md", + "ai-arch-14-ai-credits-dashboard": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-14-AI-Credits-Dashboard.md", + "AI-ARCH-15-AI-Runtime-Fargate": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-15-AI-Runtime-Fargate.md", + "ai-arch-15-ai-runtime-fargate": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-15-AI-Runtime-Fargate.md", + "AI-ARCH-16-AI-Observability-NAT-Free": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-16-AI-Observability-NAT-Free.md", + "ai-arch-16-ai-observability-nat-free": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-16-AI-Observability-NAT-Free.md", + "AI-ARCH-17-AI-Cost-Dashboard": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-17-AI-Cost-Dashboard.md", + "ai-arch-17-ai-cost-dashboard": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-17-AI-Cost-Dashboard.md", + "AI-ARCH-18-Profile-Anonymization": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-18-Profile-Anonymization.md", + "ai-arch-18-profile-anonymization": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-18-Profile-Anonymization.md", + "AI-ARCH-19-adr-service-and-indexing-abstraction": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-19-adr-service-and-indexing-abstraction.md", + "ai-arch-19-adr-service-and-indexing-abstraction": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-19-adr-service-and-indexing-abstraction.md", + "AI-ARCH-20-Ollama-Timeout-Tuning": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-20-Ollama-Timeout-Tuning.md", + "ai-arch-20-ollama-timeout-tuning": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-20-Ollama-Timeout-Tuning.md", + "AI-ARCH-21-Llama-Parsing-Robustness": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-21-Llama-Parsing-Robustness.md", + "ai-arch-21-llama-parsing-robustness": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-21-Llama-Parsing-Robustness.md", + "AI-ARCH-22-ADR-Auto-Generator": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-22-ADR-Auto-Generator.md", + "ai-arch-22-adr-auto-generator": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-22-ADR-Auto-Generator.md", + "AI-ARCH-23-Architecture-Recommendation-Engine": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-23-Architecture-Recommendation-Engine.md", + "ai-arch-23-architecture-recommendation-engine": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-23-Architecture-Recommendation-Engine.md", + "AI-ARCH-41-unify-sprint-taskset-resolution-and-selector-ux": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-41-unify-sprint-taskset-resolution-and-selector-ux.md", + "ai-arch-41-unify-sprint-taskset-resolution-and-selector-ux": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-41-unify-sprint-taskset-resolution-and-selector-ux.md", + "AI-ARCH-42-optimize-task-group-indexing-for-fast-iteration-testing": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-42-optimize-task-group-indexing-for-fast-iteration-testing.md", + "ai-arch-42-optimize-task-group-indexing-for-fast-iteration-testing": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-42-optimize-task-group-indexing-for-fast-iteration-testing.md", + "AI-ARCH-43-Consolidate-Architecture-Doc-Roots-and-Write-AI-System-Mental-Model": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-43-Consolidate-Architecture-Doc-Roots-and-Write-AI-System-Mental-Model.md", + "ai-arch-43-consolidate-architecture-doc-roots-and-write-ai-system-mental-model": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-43-Consolidate-Architecture-Doc-Roots-and-Write-AI-System-Mental-Model.md", + "AI-ARCH-50-single-serialization-ownership": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-50-single-serialization-ownership.md", + "ai-arch-50-single-serialization-ownership": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-50-single-serialization-ownership.md", + "AI-ARCH-55-AI-Response-Repair-Robustness": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-55-AI-Response-Repair-Robustness.md", + "ai-arch-55-ai-response-repair-robustness": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-55-AI-Response-Repair-Robustness.md", + "AI-ARCH-56-final-ai-pipeline": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-56-final-ai-pipeline.md", + "ai-arch-56-final-ai-pipeline": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-56-final-ai-pipeline.md", + "AI-ARCH-57-Score-captcha": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-57-Score-captcha.md", + "ai-arch-57-score-captcha": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-57-Score-captcha.md", + "AI-ARCH-58-Monorepo-structure-dev-orchestration-Postgres-pgvector-Ollama": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-58-Monorepo-structure-dev-orchestration-Postgres-pgvector-Ollama.md", + "ai-arch-58-monorepo-structure-dev-orchestration-postgres-pgvector-ollama": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-58-Monorepo-structure-dev-orchestration-Postgres-pgvector-Ollama.md", + "AI-ARCH-59-Spring-AI-wiring-provider-profiles-local-Ollama-first": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-59-Spring-AI-wiring-provider-profiles-local-Ollama-first.md", + "ai-arch-59-spring-ai-wiring-provider-profiles-local-ollama-first": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-59-Spring-AI-wiring-provider-profiles-local-Ollama-first.md", + "AI-ARCH-60-Seed-Architecture-QA-Content": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-60-Seed-Architecture-QA-Content.md", + "ai-arch-60-seed-architecture-qa-content": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-60-Seed-Architecture-QA-Content.md", + "AI-ARCH-61-Balance-Architecture-Page-Structure": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-61-Balance-Architecture-Page-Structure.md", + "ai-arch-61-balance-architecture-page-structure": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-61-Balance-Architecture-Page-Structure.md", + "AI-ARCH-62-Comprehensive-Documentation-Update": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-62-Comprehensive-Documentation-Update.md", + "ai-arch-62-comprehensive-documentation-update": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-62-Comprehensive-Documentation-Update.md", + "AI-ARCH-63-Introduction-of-Architectural-Decision-Records": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-63-Introduction-of-Architectural-Decision-Records.md", + "ai-arch-63-introduction-of-architectural-decision-records": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-63-Introduction-of-Architectural-Decision-Records.md", + "AI-BE-01-Expose-AI-Usage-Metrics-API": "doc/knowledge/junie-tasks/AI-BE/AI-BE-01-Expose-AI-Usage-Metrics-API.md", + "ai-be-01-expose-ai-usage-metrics-api": "doc/knowledge/junie-tasks/AI-BE/AI-BE-01-Expose-AI-Usage-Metrics-API.md", + "AI-BE-02 - Implement AI Credit Tracking Persistence": "doc/knowledge/junie-tasks/AI-BE/AI-BE-02 - Implement AI Credit Tracking Persistence.md", + "ai-be-02 - implement ai credit tracking persistence": "doc/knowledge/junie-tasks/AI-BE/AI-BE-02 - Implement AI Credit Tracking Persistence.md", + "AI-BE-14-Fix AI intelligence dashboard sprint scoping and epic status calculation": "doc/knowledge/junie-tasks/AI-BE/AI-BE-14-Fix AI intelligence dashboard sprint scoping and epic status calculation.md", + "ai-be-14-fix ai intelligence dashboard sprint scoping and epic status calculation": "doc/knowledge/junie-tasks/AI-BE/AI-BE-14-Fix AI intelligence dashboard sprint scoping and epic status calculation.md", + "AI-BE-15-Use-sprint-plan-docs-as-authoritative-source-for-intelligence-dashboard-sprint-scoping": "doc/knowledge/junie-tasks/AI-BE/AI-BE-15-Use-sprint-plan-docs-as-authoritative-source-for-intelligence-dashboard-sprint-scoping.md", + "ai-be-15-use-sprint-plan-docs-as-authoritative-source-for-intelligence-dashboard-sprint-scoping": "doc/knowledge/junie-tasks/AI-BE/AI-BE-15-Use-sprint-plan-docs-as-authoritative-source-for-intelligence-dashboard-sprint-scoping.md", + "AI-BE-16-Discover-available-sprints-from-repo-sprint-plan-docs": "doc/knowledge/junie-tasks/AI-BE/AI-BE-16-Discover-available-sprints-from-repo-sprint-plan-docs.md", + "ai-be-16-discover-available-sprints-from-repo-sprint-plan-docs": "doc/knowledge/junie-tasks/AI-BE/AI-BE-16-Discover-available-sprints-from-repo-sprint-plan-docs.md", + "AI-BE-17-Make-sprint-discovery-and-sorting-robust-for-future-naming-variants": "doc/knowledge/junie-tasks/AI-BE/AI-BE-17-Make-sprint-discovery-and-sorting-robust-for-future-naming-variants.md", + "ai-be-17-make-sprint-discovery-and-sorting-robust-for-future-naming-variants": "doc/knowledge/junie-tasks/AI-BE/AI-BE-17-Make-sprint-discovery-and-sorting-robust-for-future-naming-variants.md", + "AI-BE-18-Fix-exact-sprint-id-matching": "doc/knowledge/junie-tasks/AI-BE/AI-BE-18-Fix-exact-sprint-id-matching.md", + "ai-be-18-fix-exact-sprint-id-matching": "doc/knowledge/junie-tasks/AI-BE/AI-BE-18-Fix-exact-sprint-id-matching.md", + "AI-BE-19-Establish-consistent-Jackson-strategy-for-Spring-Boot-4": "doc/knowledge/junie-tasks/AI-BE/AI-BE-19-Establish-consistent-Jackson-strategy-for-Spring-Boot-4.md", + "ai-be-19-establish-consistent-jackson-strategy-for-spring-boot-4": "doc/knowledge/junie-tasks/AI-BE/AI-BE-19-Establish-consistent-Jackson-strategy-for-Spring-Boot-4.md", + "AI-BE-20-unified-ai-usecase-interface": "doc/knowledge/junie-tasks/AI-BE/AI-BE-20-unified-ai-usecase-interface.md", + "ai-be-20-unified-ai-usecase-interface": "doc/knowledge/junie-tasks/AI-BE/AI-BE-20-unified-ai-usecase-interface.md", + "AI-BE-21-ai-routing-simplification": "doc/knowledge/junie-tasks/AI-BE/AI-BE-21-ai-routing-simplification.md", + "ai-be-21-ai-routing-simplification": "doc/knowledge/junie-tasks/AI-BE/AI-BE-21-ai-routing-simplification.md", + "AI-BE-22-Deterministic-AI-Test-Profile": "doc/knowledge/junie-tasks/AI-BE/AI-BE-22-Deterministic-AI-Test-Profile.md", + "ai-be-22-deterministic-ai-test-profile": "doc/knowledge/junie-tasks/AI-BE/AI-BE-22-Deterministic-AI-Test-Profile.md", + "AI-BE-30-deterministic-prompt-layer": "doc/knowledge/junie-tasks/AI-BE/AI-BE-30-deterministic-prompt-layer.md", + "ai-be-30-deterministic-prompt-layer": "doc/knowledge/junie-tasks/AI-BE/AI-BE-30-deterministic-prompt-layer.md", + "AI-BE-31-response-stabilization": "doc/knowledge/junie-tasks/AI-BE/AI-BE-31-response-stabilization.md", + "ai-be-31-response-stabilization": "doc/knowledge/junie-tasks/AI-BE/AI-BE-31-response-stabilization.md", + "AI-BE-32-ollama-performance-phase2": "doc/knowledge/junie-tasks/AI-BE/AI-BE-32-ollama-performance-phase2.md", + "ai-be-32-ollama-performance-phase2": "doc/knowledge/junie-tasks/AI-BE/AI-BE-32-ollama-performance-phase2.md", + "AI-BE-33-ai-trace-logging": "doc/knowledge/junie-tasks/AI-BE/AI-BE-33-ai-trace-logging.md", + "ai-be-33-ai-trace-logging": "doc/knowledge/junie-tasks/AI-BE/AI-BE-33-ai-trace-logging.md", + "AI-BE-34-stale-document-detector": "doc/knowledge/junie-tasks/AI-BE/AI-BE-34-stale-document-detector.md", + "ai-be-34-stale-document-detector": "doc/knowledge/junie-tasks/AI-BE/AI-BE-34-stale-document-detector.md", + "AI-BE-35-knowledge-coverage-report": "doc/knowledge/junie-tasks/AI-BE/AI-BE-35-knowledge-coverage-report.md", + "ai-be-35-knowledge-coverage-report": "doc/knowledge/junie-tasks/AI-BE/AI-BE-35-knowledge-coverage-report.md", + "AI-BE-36-ollama-compatibility": "doc/knowledge/junie-tasks/AI-BE/AI-BE-36-ollama-compatibility.md", + "ai-be-36-ollama-compatibility": "doc/knowledge/junie-tasks/AI-BE/AI-BE-36-ollama-compatibility.md", + "AI-BE-37-structured-ai-client": "doc/knowledge/junie-tasks/AI-BE/AI-BE-37-structured-ai-client.md", + "ai-be-37-structured-ai-client": "doc/knowledge/junie-tasks/AI-BE/AI-BE-37-structured-ai-client.md", + "AI-BE-38-json-schema-pack": "doc/knowledge/junie-tasks/AI-BE/AI-BE-38-json-schema-pack.md", + "ai-be-38-json-schema-pack": "doc/knowledge/junie-tasks/AI-BE/AI-BE-38-json-schema-pack.md", + "AI-BE-39-evidence-builder": "doc/knowledge/junie-tasks/AI-BE/AI-BE-39-evidence-builder.md", + "ai-be-39-evidence-builder": "doc/knowledge/junie-tasks/AI-BE/AI-BE-39-evidence-builder.md", + "AI-BE-40-document-classifier": "doc/knowledge/junie-tasks/AI-BE/AI-BE-40-document-classifier.md", + "ai-be-40-document-classifier": "doc/knowledge/junie-tasks/AI-BE/AI-BE-40-document-classifier.md", + "AI-BE-41-deterministic-ai-response-wrapper": "doc/knowledge/junie-tasks/AI-BE/AI-BE-41-deterministic-ai-response-wrapper.md", + "ai-be-41-deterministic-ai-response-wrapper": "doc/knowledge/junie-tasks/AI-BE/AI-BE-41-deterministic-ai-response-wrapper.md", + "AI-BE-42-jackson-classpath-hardening": "doc/knowledge/junie-tasks/AI-BE/AI-BE-42-jackson-classpath-hardening.md", + "ai-be-42-jackson-classpath-hardening": "doc/knowledge/junie-tasks/AI-BE/AI-BE-42-jackson-classpath-hardening.md", + "AI-BE-43-ai-determinism-test-suite": "doc/knowledge/junie-tasks/AI-BE/AI-BE-43-ai-determinism-test-suite.md", + "ai-be-43-ai-determinism-test-suite": "doc/knowledge/junie-tasks/AI-BE/AI-BE-43-ai-determinism-test-suite.md", + "AI-BE-44-trace-graph-builder": "doc/knowledge/junie-tasks/AI-BE/AI-BE-44-trace-graph-builder.md", + "ai-be-44-trace-graph-builder": "doc/knowledge/junie-tasks/AI-BE/AI-BE-44-trace-graph-builder.md", + "AI-BE-45-knowledge-coverage-metric": "doc/knowledge/junie-tasks/AI-BE/AI-BE-45-knowledge-coverage-metric.md", + "ai-be-45-knowledge-coverage-metric": "doc/knowledge/junie-tasks/AI-BE/AI-BE-45-knowledge-coverage-metric.md", + "AI-BE-46-cross-document-consistency-check": "doc/knowledge/junie-tasks/AI-BE/AI-BE-46-cross-document-consistency-check.md", + "ai-be-46-cross-document-consistency-check": "doc/knowledge/junie-tasks/AI-BE/AI-BE-46-cross-document-consistency-check.md", + "AI-BE-47-stale-doc-detector-runtime": "doc/knowledge/junie-tasks/AI-BE/AI-BE-47-stale-doc-detector-runtime.md", + "ai-be-47-stale-doc-detector-runtime": "doc/knowledge/junie-tasks/AI-BE/AI-BE-47-stale-doc-detector-runtime.md", + "AI-BE-48-recursive-document-tree-api": "doc/knowledge/junie-tasks/AI-BE/AI-BE-48-recursive-document-tree-api.md", + "ai-be-48-recursive-document-tree-api": "doc/knowledge/junie-tasks/AI-BE/AI-BE-48-recursive-document-tree-api.md", + "AI-BE-49-document-usage-aggregation-service": "doc/knowledge/junie-tasks/AI-BE/AI-BE-49-document-usage-aggregation-service.md", + "ai-be-49-document-usage-aggregation-service": "doc/knowledge/junie-tasks/AI-BE/AI-BE-49-document-usage-aggregation-service.md", + "AI-BE-50-remove-dual-mapper-architecture": "doc/knowledge/junie-tasks/AI-BE/AI-BE-50-remove-dual-mapper-architecture.md", + "ai-be-50-remove-dual-mapper-architecture": "doc/knowledge/junie-tasks/AI-BE/AI-BE-50-remove-dual-mapper-architecture.md", + "AI-BE-51-retrieval-telemetry-enrichment": "doc/knowledge/junie-tasks/AI-BE/AI-BE-51-retrieval-telemetry-enrichment.md", + "ai-be-51-retrieval-telemetry-enrichment": "doc/knowledge/junie-tasks/AI-BE/AI-BE-51-retrieval-telemetry-enrichment.md", + "AI-BE-52-document-detail-endpoint": "doc/knowledge/junie-tasks/AI-BE/AI-BE-52-document-detail-endpoint.md", + "ai-be-52-document-detail-endpoint": "doc/knowledge/junie-tasks/AI-BE/AI-BE-52-document-detail-endpoint.md", + "AI-BE-53-canonical-dto-normalization": "doc/knowledge/junie-tasks/AI-BE/AI-BE-53-canonical-dto-normalization.md", + "ai-be-53-canonical-dto-normalization": "doc/knowledge/junie-tasks/AI-BE/AI-BE-53-canonical-dto-normalization.md", + "AI-BE-54-schema-pack-normalization": "doc/knowledge/junie-tasks/AI-BE/AI-BE-54-schema-pack-normalization.md", + "ai-be-54-schema-pack-normalization": "doc/knowledge/junie-tasks/AI-BE/AI-BE-54-schema-pack-normalization.md", + "AI-BE-55-sse-stream-completion-fix": "doc/knowledge/junie-tasks/AI-BE/AI-BE-55-sse-stream-completion-fix.md", + "ai-be-55-sse-stream-completion-fix": "doc/knowledge/junie-tasks/AI-BE/AI-BE-55-sse-stream-completion-fix.md", + "AI-BE-56-ollama-performance-optimization": "doc/knowledge/junie-tasks/AI-BE/AI-BE-56-ollama-performance-optimization.md", + "ai-be-56-ollama-performance-optimization": "doc/knowledge/junie-tasks/AI-BE/AI-BE-56-ollama-performance-optimization.md", + "AI-BE-57-unify-json-stack": "doc/knowledge/junie-tasks/AI-BE/AI-BE-57-unify-json-stack.md", + "ai-be-57-unify-json-stack": "doc/knowledge/junie-tasks/AI-BE/AI-BE-57-unify-json-stack.md", + "AI-BE-58-remove-json-repair": "doc/knowledge/junie-tasks/AI-BE/AI-BE-58-remove-json-repair.md", + "ai-be-58-remove-json-repair": "doc/knowledge/junie-tasks/AI-BE/AI-BE-58-remove-json-repair.md", + "AI-BE-59-prompt-versioning": "doc/knowledge/junie-tasks/AI-BE/AI-BE-59-prompt-versioning.md", + "ai-be-59-prompt-versioning": "doc/knowledge/junie-tasks/AI-BE/AI-BE-59-prompt-versioning.md", + "AI-BE-60-stale-reason-classifier": "doc/knowledge/junie-tasks/AI-BE/AI-BE-60-stale-reason-classifier.md", + "ai-be-60-stale-reason-classifier": "doc/knowledge/junie-tasks/AI-BE/AI-BE-60-stale-reason-classifier.md", + "AI-BE-61-strict-structured-output-policy": "doc/knowledge/junie-tasks/AI-BE/AI-BE-61-strict-structured-output-policy.md", + "ai-be-61-strict-structured-output-policy": "doc/knowledge/junie-tasks/AI-BE/AI-BE-61-strict-structured-output-policy.md", + "AI-BE-62-remove-json-repair-logic": "doc/knowledge/junie-tasks/AI-BE/AI-BE-62-remove-json-repair-logic.md", + "ai-be-62-remove-json-repair-logic": "doc/knowledge/junie-tasks/AI-BE/AI-BE-62-remove-json-repair-logic.md", + "AI-BE-INTEL-01-Add-project-intelligence-summary-endpoint": "doc/knowledge/junie-tasks/AI-BE-INTEL/AI-BE-INTEL-01-Add-project-intelligence-summary-endpoint.md", + "ai-be-intel-01-add-project-intelligence-summary-endpoint": "doc/knowledge/junie-tasks/AI-BE-INTEL/AI-BE-INTEL-01-Add-project-intelligence-summary-endpoint.md", + "AI-BE-INTEL-02-Add-architecture-drift-summary-provider": "doc/knowledge/junie-tasks/AI-BE-INTEL/AI-BE-INTEL-02-Add-architecture-drift-summary-provider.md", + "ai-be-intel-02-add-architecture-drift-summary-provider": "doc/knowledge/junie-tasks/AI-BE-INTEL/AI-BE-INTEL-02-Add-architecture-drift-summary-provider.md", + "AI-BE-INTEL-03-Add-AI-regression-trend-summary-provider": "doc/knowledge/junie-tasks/AI-BE-INTEL/AI-BE-INTEL-03-Add-AI-regression-trend-summary-provider.md", + "ai-be-intel-03-add-ai-regression-trend-summary-provider": "doc/knowledge/junie-tasks/AI-BE-INTEL/AI-BE-INTEL-03-Add-AI-regression-trend-summary-provider.md", + "AI-BE-INTEL-04-Add-backlog-leakage-summary-provider": "doc/knowledge/junie-tasks/AI-BE-INTEL/AI-BE-INTEL-04-Add-backlog-leakage-summary-provider.md", + "ai-be-intel-04-add-backlog-leakage-summary-provider": "doc/knowledge/junie-tasks/AI-BE-INTEL/AI-BE-INTEL-04-Add-backlog-leakage-summary-provider.md", + "AI-BE-INTEL-05-Add-sprint-progress-summary-provider": "doc/knowledge/junie-tasks/AI-BE-INTEL/AI-BE-INTEL-05-Add-sprint-progress-summary-provider.md", + "ai-be-intel-05-add-sprint-progress-summary-provider": "doc/knowledge/junie-tasks/AI-BE-INTEL/AI-BE-INTEL-05-Add-sprint-progress-summary-provider.md", + "AI-CI-20-fail-fast-invalid-json-gate": "doc/knowledge/junie-tasks/AI-CI/AI-CI-20-fail-fast-invalid-json-gate.md", + "ai-ci-20-fail-fast-invalid-json-gate": "doc/knowledge/junie-tasks/AI-CI/AI-CI-20-fail-fast-invalid-json-gate.md", + "AI-COP-01 - Context-Aware Engineering Chat": "doc/knowledge/junie-tasks/AI-COP/AI-COP-01 - Context-Aware Engineering Chat.md", + "ai-cop-01 - context-aware engineering chat": "doc/knowledge/junie-tasks/AI-COP/AI-COP-01 - Context-Aware Engineering Chat.md", + "AI-COP-02 - Code Change Explanation": "doc/knowledge/junie-tasks/AI-COP/AI-COP-02 - Code Change Explanation.md", + "ai-cop-02 - code change explanation": "doc/knowledge/junie-tasks/AI-COP/AI-COP-02 - Code Change Explanation.md", + "AI-COP-03 - Engineering Intelligence Dashboard": "doc/knowledge/junie-tasks/AI-COP/AI-COP-03 - Engineering Intelligence Dashboard.md", + "ai-cop-03 - engineering intelligence dashboard": "doc/knowledge/junie-tasks/AI-COP/AI-COP-03 - Engineering Intelligence Dashboard.md", + "AI-COP-04-Explicit-Copilot-Context-Orchestration-Layer": "doc/knowledge/junie-tasks/AI-COP/AI-COP-04-Explicit-Copilot-Context-Orchestration-Layer.md", + "ai-cop-04-explicit-copilot-context-orchestration-layer": "doc/knowledge/junie-tasks/AI-COP/AI-COP-04-Explicit-Copilot-Context-Orchestration-Layer.md", + "AI-COP-05-Separate-Copilot-Workspaces-from-Architecture-Page": "doc/knowledge/junie-tasks/AI-COP/AI-COP-05-Separate-Copilot-Workspaces-from-Architecture-Page.md", + "ai-cop-05-separate-copilot-workspaces-from-architecture-page": "doc/knowledge/junie-tasks/AI-COP/AI-COP-05-Separate-Copilot-Workspaces-from-Architecture-Page.md", + "AI-COP-06-Copilot-Capability-Routing-Contract": "doc/knowledge/junie-tasks/AI-COP/AI-COP-06-Copilot-Capability-Routing-Contract.md", + "ai-cop-06-copilot-capability-routing-contract": "doc/knowledge/junie-tasks/AI-COP/AI-COP-06-Copilot-Capability-Routing-Contract.md", + "AI-COP-07-Shared-Copilot-Response-Contract": "doc/knowledge/junie-tasks/AI-COP/AI-COP-07-Shared-Copilot-Response-Contract.md", + "ai-cop-07-shared-copilot-response-contract": "doc/knowledge/junie-tasks/AI-COP/AI-COP-07-Shared-Copilot-Response-Contract.md", + "AI-COP-08-Signal-Aware-Engineering-Chat": "doc/knowledge/junie-tasks/AI-COP/AI-COP-08-Signal-Aware-Engineering-Chat.md", + "ai-cop-08-signal-aware-engineering-chat": "doc/knowledge/junie-tasks/AI-COP/AI-COP-08-Signal-Aware-Engineering-Chat.md", + "AI-COP-09-Fix-Engineering-Chat-Wiring": "doc/knowledge/junie-tasks/AI-COP/AI-COP-09-Fix-Engineering-Chat-Wiring.md", + "ai-cop-09-fix-engineering-chat-wiring": "doc/knowledge/junie-tasks/AI-COP/AI-COP-09-Fix-Engineering-Chat-Wiring.md", + "AI-COP-10-Partition-Copilot-History-by-Mode-with-Safe-Migration": "doc/knowledge/junie-tasks/AI-COP/AI-COP-10-Partition-Copilot-History-by-Mode-with-Safe-Migration.md", + "ai-cop-10-partition-copilot-history-by-mode-with-safe-migration": "doc/knowledge/junie-tasks/AI-COP/AI-COP-10-Partition-Copilot-History-by-Mode-with-Safe-Migration.md", + "AI-COP-11-Add-Active-Mode-Banner-and-Context-Explainer": "doc/knowledge/junie-tasks/AI-COP/AI-COP-11-Add-Active-Mode-Banner-and-Context-Explainer.md", + "ai-cop-11-add-active-mode-banner-and-context-explainer": "doc/knowledge/junie-tasks/AI-COP/AI-COP-11-Add-Active-Mode-Banner-and-Context-Explainer.md", + "AI-COP-12-Registry-Based-Copilot-UseCase-Contract": "doc/knowledge/junie-tasks/AI-COP/AI-COP-12-Registry-Based-Copilot-UseCase-Contract.md", + "ai-cop-12-registry-based-copilot-usecase-contract": "doc/knowledge/junie-tasks/AI-COP/AI-COP-12-Registry-Based-Copilot-UseCase-Contract.md", + "AI-COP-13-Explicit-Retrieval-Policy-Manifest-for-Copilot-Modes": "doc/knowledge/junie-tasks/AI-COP/AI-COP-13-Explicit-Retrieval-Policy-Manifest-for-Copilot-Modes.md", + "ai-cop-13-explicit-retrieval-policy-manifest-for-copilot-modes": "doc/knowledge/junie-tasks/AI-COP/AI-COP-13-Explicit-Retrieval-Policy-Manifest-for-Copilot-Modes.md", + "AI-COP-14-Copilot-Response-Validation-and-Fallback-Normalization": "doc/knowledge/junie-tasks/AI-COP/AI-COP-14-Copilot-Response-Validation-and-Fallback-Normalization.md", + "ai-cop-14-copilot-response-validation-and-fallback-normalization": "doc/knowledge/junie-tasks/AI-COP/AI-COP-14-Copilot-Response-Validation-and-Fallback-Normalization.md", + "AI-COP-20-PR-AI-Review": "doc/knowledge/junie-tasks/AI-COP/AI-COP-20-PR-AI-Review.md", + "ai-cop-20-pr-ai-review": "doc/knowledge/junie-tasks/AI-COP/AI-COP-20-PR-AI-Review.md", + "AI-COP-21-PR-Comment-Generator": "doc/knowledge/junie-tasks/AI-COP/AI-COP-21-PR-Comment-Generator.md", + "ai-cop-21-pr-comment-generator": "doc/knowledge/junie-tasks/AI-COP/AI-COP-21-PR-Comment-Generator.md", + "AI-COP-22-Separate-Copilot-Workspaces": "doc/knowledge/junie-tasks/AI-COP/AI-COP-22-Separate-Copilot-Workspaces.md", + "ai-cop-22-separate-copilot-workspaces": "doc/knowledge/junie-tasks/AI-COP/AI-COP-22-Separate-Copilot-Workspaces.md", + "AI-DEC-01-AI-Decision-Assistant": "doc/knowledge/junie-tasks/AI-DEC/AI-DEC-01-AI-Decision-Assistant.md", + "ai-dec-01-ai-decision-assistant": "doc/knowledge/junie-tasks/AI-DEC/AI-DEC-01-AI-Decision-Assistant.md", + "AI-DOC-03-Document-Risk-Radar": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-03-Document-Risk-Radar.md", + "ai-doc-03-document-risk-radar": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-03-Document-Risk-Radar.md", + "AI-DOC-04-Navigation-Glossary": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-04-Navigation-Glossary.md", + "ai-doc-04-navigation-glossary": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-04-Navigation-Glossary.md", + "AI-DOC-07-Refine-Iteration-4-Mermaid-Diagrams": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-07-Refine-Iteration-4-Mermaid-Diagrams.md", + "ai-doc-07-refine-iteration-4-mermaid-diagrams": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-07-Refine-Iteration-4-Mermaid-Diagrams.md", + "AI-DOC-08-doc-consolidation": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-08-doc-consolidation.md", + "ai-doc-08-doc-consolidation": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-08-doc-consolidation.md", + "AI-DOC-09-ai-system-mental-model": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-09-ai-system-mental-model.md", + "ai-doc-09-ai-system-mental-model": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-09-ai-system-mental-model.md", + "AI-DOC-10-Regenerate-Documentation-From-Code-Reality": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-10-Regenerate-Documentation-From-Code-Reality.md", + "ai-doc-10-regenerate-documentation-from-code-reality": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-10-Regenerate-Documentation-From-Code-Reality.md", + "AI-DOC-11-architecture-inventory": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-11-architecture-inventory.md", + "ai-doc-11-architecture-inventory": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-11-architecture-inventory.md", + "AI-DOC-12-architecture-diagrams": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-12-architecture-diagrams.md", + "ai-doc-12-architecture-diagrams": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-12-architecture-diagrams.md", + "AI-DOC-13-generate-erd": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-13-generate-erd.md", + "ai-doc-13-generate-erd": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-13-generate-erd.md", + "AI-DOC-14-Refresh-Documentation-Links-and-References": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-14-Refresh-Documentation-Links-and-References.md", + "ai-doc-14-refresh-documentation-links-and-references": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-14-Refresh-Documentation-Links-and-References.md", + "AI-DOC-20-super-documentation-generator": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-20-super-documentation-generator.md", + "ai-doc-20-super-documentation-generator": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-20-super-documentation-generator.md", + "AI-DOC-21-Update-Iteration-4-Slide-Generation-Docs": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-21-Update-Iteration-4-Slide-Generation-Docs.md", + "ai-doc-21-update-iteration-4-slide-generation-docs": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-21-Update-Iteration-4-Slide-Generation-Docs.md", + "AI-DOC-INTEL-01-Document-dashboard-purpose-and-next-evolution-steps": "doc/knowledge/junie-tasks/AI-DOC-INTEL/AI-DOC-INTEL-01-Document-dashboard-purpose-and-next-evolution-steps.md", + "ai-doc-intel-01-document-dashboard-purpose-and-next-evolution-steps": "doc/knowledge/junie-tasks/AI-DOC-INTEL/AI-DOC-INTEL-01-Document-dashboard-purpose-and-next-evolution-steps.md", + "AI-EVAL-01 - Knowledge Retrieval Trace Logging": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-01 - Knowledge Retrieval Trace Logging.md", + "ai-eval-01 - knowledge retrieval trace logging": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-01 - Knowledge Retrieval Trace Logging.md", + "AI-EVAL-02 - Prompt Assembly Trace Logging": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-02 - Prompt Assembly Trace Logging.md", + "ai-eval-02 - prompt assembly trace logging": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-02 - Prompt Assembly Trace Logging.md", + "AI-EVAL-03 - Deterministic Retrieval Tests": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-03 - Deterministic Retrieval Tests.md", + "ai-eval-03 - deterministic retrieval tests": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-03 - Deterministic Retrieval Tests.md", + "AI-EVAL-04 - Ollama Local AI Test Runtime": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-04 - Ollama Local AI Test Runtime.md", + "ai-eval-04 - ollama local ai test runtime": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-04 - Ollama Local AI Test Runtime.md", + "AI-EVAL-05-AI-Benchmark-Dataset": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-05-AI-Benchmark-Dataset.md", + "ai-eval-05-ai-benchmark-dataset": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-05-AI-Benchmark-Dataset.md", + "AI-EVAL-06-AI-Answer-Evaluation-Engine": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-06-AI-Answer-Evaluation-Engine.md", + "ai-eval-06-ai-answer-evaluation-engine": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-06-AI-Answer-Evaluation-Engine.md", + "AI-EVAL-07-AI-Regression-Test-Suite": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-07-AI-Regression-Test-Suite.md", + "ai-eval-07-ai-regression-test-suite": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-07-AI-Regression-Test-Suite.md", + "AI-EVAL-08-Knowledge-Coverage-Analyzer": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-08-Knowledge-Coverage-Analyzer.md", + "ai-eval-08-knowledge-coverage-analyzer": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-08-Knowledge-Coverage-Analyzer.md", + "AI-EVAL-09-Backlog-Leakage-Detection": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-09-Backlog-Leakage-Detection.md", + "ai-eval-09-backlog-leakage-detection": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-09-Backlog-Leakage-Detection.md", + "AI-EVAL-10-Internal-AI-Trace-Viewer": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-10-Internal-AI-Trace-Viewer.md", + "ai-eval-10-internal-ai-trace-viewer": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-10-Internal-AI-Trace-Viewer.md", + "AI-EVAL-11-AI-Output-Evaluation-Framework": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-11-AI-Output-Evaluation-Framework.md", + "ai-eval-11-ai-output-evaluation-framework": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-11-AI-Output-Evaluation-Framework.md", + "AI-EVAL-12-AI-Regression-Test-Runner": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-12-AI-Regression-Test-Runner.md", + "ai-eval-12-ai-regression-test-runner": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-12-AI-Regression-Test-Runner.md", + "AI-EVAL-17 - Knowledge Test Dataset Generator": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-17 - Knowledge Test Dataset Generator.md", + "ai-eval-17 - knowledge test dataset generator": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-17 - Knowledge Test Dataset Generator.md", + "AI-EVAL-18 - Knowledge File Classification Rules": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-18 - Knowledge File Classification Rules.md", + "ai-eval-18 - knowledge file classification rules": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-18 - Knowledge File Classification Rules.md", + "AI-EVAL-19 - Generated Test Review Workflow": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-19 - Generated Test Review Workflow.md", + "ai-eval-19 - generated test review workflow": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-19 - Generated Test Review Workflow.md", + "AI-EVAL-20-Roadmap-vs-Current-State-Query-Split-Tests": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-20-Roadmap-vs-Current-State-Query-Split-Tests.md", + "ai-eval-20-roadmap-vs-current-state-query-split-tests": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-20-Roadmap-vs-Current-State-Query-Split-Tests.md", + "AI-EVAL-21-Retrieval-Coverage-Benchmark-Suite": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-21-Retrieval-Coverage-Benchmark-Suite.md", + "ai-eval-21-retrieval-coverage-benchmark-suite": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-21-Retrieval-Coverage-Benchmark-Suite.md", + "AI-EVAL-22-Stale-Knowledge-Coverage-Analyzer": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-22-Stale-Knowledge-Coverage-Analyzer.md", + "ai-eval-22-stale-knowledge-coverage-analyzer": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-22-Stale-Knowledge-Coverage-Analyzer.md", + "AI-EVAL-23-Provider-Consistency-Harness": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-23-Provider-Consistency-Harness.md", + "ai-eval-23-provider-consistency-harness": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-23-Provider-Consistency-Harness.md", + "AI-FE-30-unified-ai-trace-view": "doc/knowledge/junie-tasks/AI-FE/AI-FE-30-unified-ai-trace-view.md", + "ai-fe-30-unified-ai-trace-view": "doc/knowledge/junie-tasks/AI-FE/AI-FE-30-unified-ai-trace-view.md", + "AI-FE-31-tree-based-coverage-dashboard": "doc/knowledge/junie-tasks/AI-FE/AI-FE-31-tree-based-coverage-dashboard.md", + "ai-fe-31-tree-based-coverage-dashboard": "doc/knowledge/junie-tasks/AI-FE/AI-FE-31-tree-based-coverage-dashboard.md", + "AI-FE-32-document-detail-panel": "doc/knowledge/junie-tasks/AI-FE/AI-FE-32-document-detail-panel.md", + "ai-fe-32-document-detail-panel": "doc/knowledge/junie-tasks/AI-FE/AI-FE-32-document-detail-panel.md", + "AI-FE-33-coverage-filter-controls": "doc/knowledge/junie-tasks/AI-FE/AI-FE-33-coverage-filter-controls.md", + "ai-fe-33-coverage-filter-controls": "doc/knowledge/junie-tasks/AI-FE/AI-FE-33-coverage-filter-controls.md", + "AI-FE-34-branch-coverage-heatmap-refinement": "doc/knowledge/junie-tasks/AI-FE/AI-FE-34-branch-coverage-heatmap-refinement.md", + "ai-fe-34-branch-coverage-heatmap-refinement": "doc/knowledge/junie-tasks/AI-FE/AI-FE-34-branch-coverage-heatmap-refinement.md", + "AI-FIX-01-Fix-AI-Parsing-Hallucinations": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-01-Fix-AI-Parsing-Hallucinations.md", + "ai-fix-01-fix-ai-parsing-hallucinations": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-01-Fix-AI-Parsing-Hallucinations.md", + "AI-FIX-02-Ollama-Octet-Stream-Extraction": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-02-Ollama-Octet-Stream-Extraction.md", + "ai-fix-02-ollama-octet-stream-extraction": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-02-Ollama-Octet-Stream-Extraction.md", + "AI-FIX-03-Sprint-Selection-Automation": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-03-Sprint-Selection-Automation.md", + "ai-fix-03-sprint-selection-automation": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-03-Sprint-Selection-Automation.md", + "AI-FIX-04-Engineering-Chat-Response-Visibility": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-04-Engineering-Chat-Response-Visibility.md", + "ai-fix-04-engineering-chat-response-visibility": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-04-Engineering-Chat-Response-Visibility.md", + "AI-FIX-05-AiController-Syntax-and-Jackson-Fix": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-05-AiController-Syntax-and-Jackson-Fix.md", + "ai-fix-05-aicontroller-syntax-and-jackson-fix": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-05-AiController-Syntax-and-Jackson-Fix.md", + "AI-FIX-06-Checkstyle-Warnings-Backend": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-06-Checkstyle-Warnings-Backend.md", + "ai-fix-06-checkstyle-warnings-backend": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-06-Checkstyle-Warnings-Backend.md", + "AI-FIX-07-AI-Trace-Observability-and-Regression-Resilience": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-07-AI-Trace-Observability-and-Regression-Resilience.md", + "ai-fix-07-ai-trace-observability-and-regression-resilience": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-07-AI-Trace-Observability-and-Regression-Resilience.md", + "AI-FIX-08-Session-Invalidation-Robustness": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-08-Session-Invalidation-Robustness.md", + "ai-fix-08-session-invalidation-robustness": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-08-Session-Invalidation-Robustness.md", + "AI-GOV-01-Sprint-1.7-Task-Normalization": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-01-Sprint-1.7-Task-Normalization.md", + "ai-gov-01-sprint-1.7-task-normalization": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-01-Sprint-1.7-Task-Normalization.md", + "AI-GOV-02-Introduce-Task-Contract-Standard": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-02-Introduce-Task-Contract-Standard.md", + "ai-gov-02-introduce-task-contract-standard": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-02-Introduce-Task-Contract-Standard.md", + "AI-GOV-03-Enforce-Task-Contract-in-CI": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-03-Enforce-Task-Contract-in-CI.md", + "ai-gov-03-enforce-task-contract-in-ci": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-03-Enforce-Task-Contract-in-CI.md", + "AI-GOV-06-context-isolation-rules": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-06-context-isolation-rules.md", + "ai-gov-06-context-isolation-rules": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-06-context-isolation-rules.md", + "AI-GOV-07-prompt-registry-versioning": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-07-prompt-registry-versioning.md", + "ai-gov-07-prompt-registry-versioning": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-07-prompt-registry-versioning.md", + "AI-GOV-08-response-validation-layer": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-08-response-validation-layer.md", + "ai-gov-08-response-validation-layer": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-08-response-validation-layer.md", + "AI-GOV-10-Guardrails-Validator-Script": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-10-Guardrails-Validator-Script.md", + "ai-gov-10-guardrails-validator-script": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-10-Guardrails-Validator-Script.md", + "AI-GOV-11-CI-Enforcement-Integration": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-11-CI-Enforcement-Integration.md", + "ai-gov-11-ci-enforcement-integration": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-11-CI-Enforcement-Integration.md", + "AI-GOV-12-Auto-Fix-on-PR": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-12-Auto-Fix-on-PR.md", + "ai-gov-12-auto-fix-on-pr": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-12-Auto-Fix-on-PR.md", + "AI-GOV-13-Task-Refactoring-Engine": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-13-Task-Refactoring-Engine.md", + "ai-gov-13-task-refactoring-engine": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-13-Task-Refactoring-Engine.md", + "AI-GOV-14-Prompt-Manifest-Version-Inventory-and-Integrity-Test": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-14-Prompt-Manifest-Version-Inventory-and-Integrity-Test.md", + "ai-gov-14-prompt-manifest-version-inventory-and-integrity-test": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-14-Prompt-Manifest-Version-Inventory-and-Integrity-Test.md", + "AI-GOV-15-Benchmark-Query-Registry": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-15-Benchmark-Query-Registry.md", + "ai-gov-15-benchmark-query-registry": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-15-Benchmark-Query-Registry.md", + "AI-GOV-20-Guardrails-Enforcement-Metrics": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-20-Guardrails-Enforcement-Metrics.md", + "ai-gov-20-guardrails-enforcement-metrics": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-20-Guardrails-Enforcement-Metrics.md", + "AI-GOV-21-Guardrails-Exception-Tracking": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-21-Guardrails-Exception-Tracking.md", + "ai-gov-21-guardrails-exception-tracking": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-21-Guardrails-Exception-Tracking.md", + "AI-GOV-22-Task-Auto-Linking": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-22-Task-Auto-Linking.md", + "ai-gov-22-task-auto-linking": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-22-Task-Auto-Linking.md", + "AI-GOV-23-Autofix-CLI-Integration": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-23-Autofix-CLI-Integration.md", + "ai-gov-23-autofix-cli-integration": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-23-Autofix-CLI-Integration.md", + "AI-GOV-24-Autofix-CI-Mode": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-24-Autofix-CI-Mode.md", + "ai-gov-24-autofix-ci-mode": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-24-Autofix-CI-Mode.md", + "AI-GOV-25-Autofix-Safe-Commit-Mode": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-25-Autofix-Safe-Commit-Mode.md", + "ai-gov-25-autofix-safe-commit-mode": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-25-Autofix-Safe-Commit-Mode.md", + "AI-GOV-30-ai-failure-detection": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-30-ai-failure-detection.md", + "ai-gov-30-ai-failure-detection": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-30-ai-failure-detection.md", + "AI-GOV-31-auto-retry-strategy": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-31-auto-retry-strategy.md", + "ai-gov-31-auto-retry-strategy": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-31-auto-retry-strategy.md", + "AI-GOV-32-ai-quality-score": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-32-ai-quality-score.md", + "ai-gov-32-ai-quality-score": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-32-ai-quality-score.md", + "AI-GOV-33-schema-validation-gate": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-33-schema-validation-gate.md", + "ai-gov-33-schema-validation-gate": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-33-schema-validation-gate.md", + "AI-GOV-34-Implement-Traceability-Governance": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-34-Implement-Traceability-Governance.md", + "ai-gov-34-implement-traceability-governance": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-34-Implement-Traceability-Governance.md", + "AI-IMP-01-AI-Impact-Simulator": "doc/knowledge/junie-tasks/AI-IMP/AI-IMP-01-AI-Impact-Simulator.md", + "ai-imp-01-ai-impact-simulator": "doc/knowledge/junie-tasks/AI-IMP/AI-IMP-01-AI-Impact-Simulator.md", + "AI-IMP-02-Impact-Simulator-v2-on-Signals-and-Task-Graph": "doc/knowledge/junie-tasks/AI-IMP/AI-IMP-02-Impact-Simulator-v2-on-Signals-and-Task-Graph.md", + "ai-imp-02-impact-simulator-v2-on-signals-and-task-graph": "doc/knowledge/junie-tasks/AI-IMP/AI-IMP-02-Impact-Simulator-v2-on-Signals-and-Task-Graph.md", + "AI-INFRA-01 - Local Docker Runtime for PostgreSQL": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-01 - Local Docker Runtime for PostgreSQL.md", + "ai-infra-01 - local docker runtime for postgresql": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-01 - Local Docker Runtime for PostgreSQL.md", + "AI-INFRA-02 - OpenAI Runtime Configuration": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-02 - OpenAI Runtime Configuration.md", + "ai-infra-02 - openai runtime configuration": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-02 - OpenAI Runtime Configuration.md", + "AI-INFRA-03-Ollama-Local-Runtime-Integration": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-03-Ollama-Local-Runtime-Integration.md", + "ai-infra-03-ollama-local-runtime-integration": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-03-Ollama-Local-Runtime-Integration.md", + "AI-INFRA-04 - Fargate Demo Deployment Variant": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-04 - Fargate Demo Deployment Variant.md", + "ai-infra-04 - fargate demo deployment variant": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-04 - Fargate Demo Deployment Variant.md", + "AI-INFRA-05 - Multi-Model Routing Layer": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-05 - Multi-Model Routing Layer.md", + "ai-infra-05 - multi-model routing layer": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-05 - Multi-Model Routing Layer.md", + "AI-INFRA-06-AI-Response-Cache-Layer": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-06-AI-Response-Cache-Layer.md", + "ai-infra-06-ai-response-cache-layer": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-06-AI-Response-Cache-Layer.md", + "AI-INFRA-06B-Ollama-Docker-Performance-Profile-and-Fast-Path": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-06B-Ollama-Docker-Performance-Profile-and-Fast-Path.md", + "ai-infra-06b-ollama-docker-performance-profile-and-fast-path": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-06B-Ollama-Docker-Performance-Profile-and-Fast-Path.md", + "AI-INFRA-06H-Host-Run-Ollama-Setup-and-Fast-Local-Profile": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-06H-Host-Run-Ollama-Setup-and-Fast-Local-Profile.md", + "ai-infra-06h-host-run-ollama-setup-and-fast-local-profile": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-06H-Host-Run-Ollama-Setup-and-Fast-Local-Profile.md", + "AI-INFRA-07-Knowledge-Index-Filter": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-07-Knowledge-Index-Filter.md", + "ai-infra-07-knowledge-index-filter": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-07-Knowledge-Index-Filter.md", + "AI-INFRA-10-AI-Traces-Fargate-Persistence": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-10-AI-Traces-Fargate-Persistence.md", + "ai-infra-10-ai-traces-fargate-persistence": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-10-AI-Traces-Fargate-Persistence.md", + "AI-INFRA-11-Configure-Alternative-Domains": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-11-Configure-Alternative-Domains.md", + "ai-infra-11-configure-alternative-domains": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-11-Configure-Alternative-Domains.md", + "AI-INT-01-Canonical-Engineering-Signal-Model": "doc/knowledge/junie-tasks/AI-INT/AI-INT-01-Canonical-Engineering-Signal-Model.md", + "ai-int-01-canonical-engineering-signal-model": "doc/knowledge/junie-tasks/AI-INT/AI-INT-01-Canonical-Engineering-Signal-Model.md", + "AI-INT-02-Intelligence-Aggregation-Service-Extraction": "doc/knowledge/junie-tasks/AI-INT/AI-INT-02-Intelligence-Aggregation-Service-Extraction.md", + "ai-int-02-intelligence-aggregation-service-extraction": "doc/knowledge/junie-tasks/AI-INT/AI-INT-02-Intelligence-Aggregation-Service-Extraction.md", + "AI-INT-03-Shared-Engineering-Taxonomy-and-Vocabularies": "doc/knowledge/junie-tasks/AI-INT/AI-INT-03-Shared-Engineering-Taxonomy-and-Vocabularies.md", + "ai-int-03-shared-engineering-taxonomy-and-vocabularies": "doc/knowledge/junie-tasks/AI-INT/AI-INT-03-Shared-Engineering-Taxonomy-and-Vocabularies.md", + "AI-INTEL-01-Define-dashboard-scope-and-data-contract": "doc/knowledge/junie-tasks/AI-INTEL/AI-INTEL-01-Define-dashboard-scope-and-data-contract.md", + "ai-intel-01-define-dashboard-scope-and-data-contract": "doc/knowledge/junie-tasks/AI-INTEL/AI-INTEL-01-Define-dashboard-scope-and-data-contract.md", + "AI-KNOW-20-Knowledge-Gap-Detector": "doc/knowledge/junie-tasks/AI-KNOW/AI-KNOW-20-Knowledge-Gap-Detector.md", + "ai-know-20-knowledge-gap-detector": "doc/knowledge/junie-tasks/AI-KNOW/AI-KNOW-20-Knowledge-Gap-Detector.md", + "AI-OBS-01 - Grafana AI Usage Dashboard": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-01 - Grafana AI Usage Dashboard.md", + "ai-obs-01 - grafana ai usage dashboard": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-01 - Grafana AI Usage Dashboard.md", + "AI-OBS-02-Add-AI-Cost-Dashboard-Metrics": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-02-Add-AI-Cost-Dashboard-Metrics.md", + "ai-obs-02-add-ai-cost-dashboard-metrics": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-02-Add-AI-Cost-Dashboard-Metrics.md", + "AI-OBS-03-Add-AI-Latency-Monitoring": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-03-Add-AI-Latency-Monitoring.md", + "ai-obs-03-add-ai-latency-monitoring": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-03-Add-AI-Latency-Monitoring.md", + "AI-OBS-04-AI-Trace-Viewer": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-04-AI-Trace-Viewer.md", + "ai-obs-04-ai-trace-viewer": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-04-AI-Trace-Viewer.md", + "AI-OBS-04A-Copilot-and-Intelligence-Diagnostics": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-04A-Copilot-and-Intelligence-Diagnostics.md", + "ai-obs-04a-copilot-and-intelligence-diagnostics": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-04A-Copilot-and-Intelligence-Diagnostics.md", + "AI-OBS-05-failure-visibility": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-05-failure-visibility.md", + "ai-obs-05-failure-visibility": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-05-failure-visibility.md", + "AI-OBS-06-Enrich-AI-Traces-with-Capability-and-Context-Filters": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-06-Enrich-AI-Traces-with-Capability-and-Context-Filters.md", + "ai-obs-06-enrich-ai-traces-with-capability-and-context-filters": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-06-Enrich-AI-Traces-with-Capability-and-Context-Filters.md", + "AI-OBS-07-Retrieval-Usage-Telemetry": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-07-Retrieval-Usage-Telemetry.md", + "ai-obs-07-retrieval-usage-telemetry": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-07-Retrieval-Usage-Telemetry.md", + "AI-OBS-08-Knowledge-Branch-Coverage-Dashboard": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-08-Knowledge-Branch-Coverage-Dashboard.md", + "ai-obs-08-knowledge-branch-coverage-dashboard": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-08-Knowledge-Branch-Coverage-Dashboard.md", + "AI-OBS-20-trace-and-coverage-verification": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-20-trace-and-coverage-verification.md", + "ai-obs-20-trace-and-coverage-verification": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-20-trace-and-coverage-verification.md", + "AI-OBS-21-trace-correlation": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-21-trace-correlation.md", + "ai-obs-21-trace-correlation": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-21-trace-correlation.md", + "AI-OBS-22-Intelligence-Endpoint-SLOs-and-Performance-Observability": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-22-Intelligence-Endpoint-SLOs-and-Performance-Observability.md", + "ai-obs-22-intelligence-endpoint-slos-and-performance-observability": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-22-Intelligence-Endpoint-SLOs-and-Performance-Observability.md", + "AI-OPS-01-AI-Health-Monitoring": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-01-AI-Health-Monitoring.md", + "ai-ops-01-ai-health-monitoring": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-01-AI-Health-Monitoring.md", + "AI-OPS-01A-Stabilize-Intelligence-Dashboard-Streaming-and-Partial-Results": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-01A-Stabilize-Intelligence-Dashboard-Streaming-and-Partial-Results.md", + "ai-ops-01a-stabilize-intelligence-dashboard-streaming-and-partial-results": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-01A-Stabilize-Intelligence-Dashboard-Streaming-and-Partial-Results.md", + "AI-OPS-01H-Hotfix-epics-intelligence-stream-timeout-and-late-emitter-failures": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-01H-Hotfix-epics-intelligence-stream-timeout-and-late-emitter-failures.md", + "ai-ops-01h-hotfix-epics-intelligence-stream-timeout-and-late-emitter-failures": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-01H-Hotfix-epics-intelligence-stream-timeout-and-late-emitter-failures.md", + "AI-OPS-10-merge-master-and-rebrand-to-angularai": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-10-merge-master-and-rebrand-to-angularai.md", + "ai-ops-10-merge-master-and-rebrand-to-angularai": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-10-merge-master-and-rebrand-to-angularai.md", + "AI-OPS-11-adaptive-model-routing": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-11-adaptive-model-routing.md", + "ai-ops-11-adaptive-model-routing": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-11-adaptive-model-routing.md", + "AI-OPS-12-ollama-latency-benchmark": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-12-ollama-latency-benchmark.md", + "ai-ops-12-ollama-latency-benchmark": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-12-ollama-latency-benchmark.md", + "AI-OPS-22-Fargate-Readiness-2.2": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-22-Fargate-Readiness-2.2.md", + "ai-ops-22-fargate-readiness-2.2": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-22-Fargate-Readiness-2.2.md", + "AI-PERF-01-Ollama-Host-Optimization": "doc/knowledge/junie-tasks/AI-PERF/AI-PERF-01-Ollama-Host-Optimization.md", + "ai-perf-01-ollama-host-optimization": "doc/knowledge/junie-tasks/AI-PERF/AI-PERF-01-Ollama-Host-Optimization.md", + "AI-PLAN-20-Backlog-Grooming-Assistant": "doc/knowledge/junie-tasks/AI-PLAN/AI-PLAN-20-Backlog-Grooming-Assistant.md", + "ai-plan-20-backlog-grooming-assistant": "doc/knowledge/junie-tasks/AI-PLAN/AI-PLAN-20-Backlog-Grooming-Assistant.md", + "AI-PLAN-21-Task-Breakdown-Generator": "doc/knowledge/junie-tasks/AI-PLAN/AI-PLAN-21-Task-Breakdown-Generator.md", + "ai-plan-21-task-breakdown-generator": "doc/knowledge/junie-tasks/AI-PLAN/AI-PLAN-21-Task-Breakdown-Generator.md", + "AI-PLAN-50-sprint-2.1-proper-stabilization-plan": "doc/knowledge/junie-tasks/AI-PLAN/AI-PLAN-50-sprint-2.1-proper-stabilization-plan.md", + "ai-plan-50-sprint-2.1-proper-stabilization-plan": "doc/knowledge/junie-tasks/AI-PLAN/AI-PLAN-50-sprint-2.1-proper-stabilization-plan.md", + "AI-PLAN-51-sprint-2.1-execution-order": "doc/knowledge/junie-tasks/AI-PLAN/AI-PLAN-51-sprint-2.1-execution-order.md", + "ai-plan-51-sprint-2.1-execution-order": "doc/knowledge/junie-tasks/AI-PLAN/AI-PLAN-51-sprint-2.1-execution-order.md", + "AI-PLAN-52-sprint-2.1-definition-of-done": "doc/knowledge/junie-tasks/AI-PLAN/AI-PLAN-52-sprint-2.1-definition-of-done.md", + "ai-plan-52-sprint-2.1-definition-of-done": "doc/knowledge/junie-tasks/AI-PLAN/AI-PLAN-52-sprint-2.1-definition-of-done.md", + "AI-PLAN-53-sprint-2.1-demo-risk-checklist": "doc/knowledge/junie-tasks/AI-PLAN/AI-PLAN-53-sprint-2.1-demo-risk-checklist.md", + "ai-plan-53-sprint-2.1-demo-risk-checklist": "doc/knowledge/junie-tasks/AI-PLAN/AI-PLAN-53-sprint-2.1-demo-risk-checklist.md", + "AI-QA-01-full-ai-regression-suite": "doc/knowledge/junie-tasks/AI-QA/AI-QA-01-full-ai-regression-suite.md", + "ai-qa-01-full-ai-regression-suite": "doc/knowledge/junie-tasks/AI-QA/AI-QA-01-full-ai-regression-suite.md", + "AI-QA-02-test-results-html-index": "doc/knowledge/junie-tasks/AI-QA/AI-QA-02-test-results-html-index.md", + "ai-qa-02-test-results-html-index": "doc/knowledge/junie-tasks/AI-QA/AI-QA-02-test-results-html-index.md", + "AI-QA-10-deterministic-regression-runner": "doc/knowledge/junie-tasks/AI-QA/AI-QA-10-deterministic-regression-runner.md", + "ai-qa-10-deterministic-regression-runner": "doc/knowledge/junie-tasks/AI-QA/AI-QA-10-deterministic-regression-runner.md", + "AI-QA-11-snapshot-baseline-system": "doc/knowledge/junie-tasks/AI-QA/AI-QA-11-snapshot-baseline-system.md", + "ai-qa-11-snapshot-baseline-system": "doc/knowledge/junie-tasks/AI-QA/AI-QA-11-snapshot-baseline-system.md", + "AI-QA-12-regression-matrix": "doc/knowledge/junie-tasks/AI-QA/AI-QA-12-regression-matrix.md", + "ai-qa-12-regression-matrix": "doc/knowledge/junie-tasks/AI-QA/AI-QA-12-regression-matrix.md", + "AI-QA-13-test-reporting": "doc/knowledge/junie-tasks/AI-QA/AI-QA-13-test-reporting.md", + "ai-qa-13-test-reporting": "doc/knowledge/junie-tasks/AI-QA/AI-QA-13-test-reporting.md", + "AI-QA-20-demo-scenario-freeze": "doc/knowledge/junie-tasks/AI-QA/AI-QA-20-demo-scenario-freeze.md", + "ai-qa-20-demo-scenario-freeze": "doc/knowledge/junie-tasks/AI-QA/AI-QA-20-demo-scenario-freeze.md", + "AI-QA-21-golden-output-snapshots": "doc/knowledge/junie-tasks/AI-QA/AI-QA-21-golden-output-snapshots.md", + "ai-qa-21-golden-output-snapshots": "doc/knowledge/junie-tasks/AI-QA/AI-QA-21-golden-output-snapshots.md", + "AI-QA-22-playwright-deterministic-tests": "doc/knowledge/junie-tasks/AI-QA/AI-QA-22-playwright-deterministic-tests.md", + "ai-qa-22-playwright-deterministic-tests": "doc/knowledge/junie-tasks/AI-QA/AI-QA-22-playwright-deterministic-tests.md", + "AI-QA-23-regression-dataset": "doc/knowledge/junie-tasks/AI-QA/AI-QA-23-regression-dataset.md", + "ai-qa-23-regression-dataset": "doc/knowledge/junie-tasks/AI-QA/AI-QA-23-regression-dataset.md", + "AI-REL-01-AI-Release-Intelligence": "doc/knowledge/junie-tasks/AI-REL/AI-REL-01-AI-Release-Intelligence.md", + "ai-rel-01-ai-release-intelligence": "doc/knowledge/junie-tasks/AI-REL/AI-REL-01-AI-Release-Intelligence.md", + "AI-REL-02-align-static-analysis-rules": "doc/knowledge/junie-tasks/AI-REL/AI-REL-02-align-static-analysis-rules.md", + "ai-rel-02-align-static-analysis-rules": "doc/knowledge/junie-tasks/AI-REL/AI-REL-02-align-static-analysis-rules.md", + "AI-REL-03-sonar-major-fix-loop": "doc/knowledge/junie-tasks/AI-REL/AI-REL-03-sonar-major-fix-loop.md", + "ai-rel-03-sonar-major-fix-loop": "doc/knowledge/junie-tasks/AI-REL/AI-REL-03-sonar-major-fix-loop.md", + "AI-REL-04-frontend-sonar-major-fix-loop": "doc/knowledge/junie-tasks/AI-REL/AI-REL-04-frontend-sonar-major-fix-loop.md", + "ai-rel-04-frontend-sonar-major-fix-loop": "doc/knowledge/junie-tasks/AI-REL/AI-REL-04-frontend-sonar-major-fix-loop.md", + "AI-REL-05-sonar-remediation-process": "doc/knowledge/junie-tasks/AI-REL/AI-REL-05-sonar-remediation-process.md", + "ai-rel-05-sonar-remediation-process": "doc/knowledge/junie-tasks/AI-REL/AI-REL-05-sonar-remediation-process.md", + "AI-REL-06-release-stabilization": "doc/knowledge/junie-tasks/AI-REL/AI-REL-06-release-stabilization.md", + "ai-rel-06-release-stabilization": "doc/knowledge/junie-tasks/AI-REL/AI-REL-06-release-stabilization.md", + "AI-REL-07-Release-Intelligence-v2-on-Canonical-Signals": "doc/knowledge/junie-tasks/AI-REL/AI-REL-07-Release-Intelligence-v2-on-Canonical-Signals.md", + "ai-rel-07-release-intelligence-v2-on-canonical-signals": "doc/knowledge/junie-tasks/AI-REL/AI-REL-07-Release-Intelligence-v2-on-Canonical-Signals.md", + "AI-RETRO-01-AI-Retrospective-Generator": "doc/knowledge/junie-tasks/AI-RETRO/AI-RETRO-01-AI-Retrospective-Generator.md", + "ai-retro-01-ai-retrospective-generator": "doc/knowledge/junie-tasks/AI-RETRO/AI-RETRO-01-AI-Retrospective-Generator.md", + "AI-RETRO-02-AI-Risk-Radar": "doc/knowledge/junie-tasks/AI-RETRO/AI-RETRO-02-AI-Risk-Radar.md", + "ai-retro-02-ai-risk-radar": "doc/knowledge/junie-tasks/AI-RETRO/AI-RETRO-02-AI-Risk-Radar.md", + "AI-RETRO-03-ADR-Drift-Detector": "doc/knowledge/junie-tasks/AI-RETRO/AI-RETRO-03-ADR-Drift-Detector.md", + "ai-retro-03-adr-drift-detector": "doc/knowledge/junie-tasks/AI-RETRO/AI-RETRO-03-ADR-Drift-Detector.md", + "AI-SONAR-EXPORT-LOOP": "doc/knowledge/junie-tasks/AI-SONAR/AI-SONAR-EXPORT-LOOP.md", + "ai-sonar-export-loop": "doc/knowledge/junie-tasks/AI-SONAR/AI-SONAR-EXPORT-LOOP.md", + "AI-SONAR-JUNIE-V2": "doc/knowledge/junie-tasks/AI-SONAR/AI-SONAR-JUNIE-V2.md", + "ai-sonar-junie-v2": "doc/knowledge/junie-tasks/AI-SONAR/AI-SONAR-JUNIE-V2.md", + "AI-SPR-01-Sprint-Risk-Predictor": "doc/knowledge/junie-tasks/AI-SPR/AI-SPR-01-Sprint-Risk-Predictor.md", + "ai-spr-01-sprint-risk-predictor": "doc/knowledge/junie-tasks/AI-SPR/AI-SPR-01-Sprint-Risk-Predictor.md", + "AI-SPR-02 - Delivery Forecast": "doc/knowledge/junie-tasks/AI-SPR/AI-SPR-02 - Delivery Forecast.md", + "ai-spr-02 - delivery forecast": "doc/knowledge/junie-tasks/AI-SPR/AI-SPR-02 - Delivery Forecast.md", + "AI-SPR-03-Sprint-Health-Predictor": "doc/knowledge/junie-tasks/AI-SPR/AI-SPR-03-Sprint-Health-Predictor.md", + "ai-spr-03-sprint-health-predictor": "doc/knowledge/junie-tasks/AI-SPR/AI-SPR-03-Sprint-Health-Predictor.md", + "AI-SPR-03R-Delivery-Forecast-Evidence-Contract-and-Calibration": "doc/knowledge/junie-tasks/AI-SPR/AI-SPR-03R-Delivery-Forecast-Evidence-Contract-and-Calibration.md", + "ai-spr-03r-delivery-forecast-evidence-contract-and-calibration": "doc/knowledge/junie-tasks/AI-SPR/AI-SPR-03R-Delivery-Forecast-Evidence-Contract-and-Calibration.md", + "AI-SPR-04-Sprint-1.8-Reconciliation-Assessment": "doc/knowledge/junie-tasks/AI-SPR/AI-SPR-04-Sprint-1.8-Reconciliation-Assessment.md", + "ai-spr-04-sprint-1.8-reconciliation-assessment": "doc/knowledge/junie-tasks/AI-SPR/AI-SPR-04-Sprint-1.8-Reconciliation-Assessment.md", + "AI-SPR-05-Sprint-1.8-Completion-Assessment": "doc/knowledge/junie-tasks/AI-SPR/AI-SPR-05-Sprint-1.8-Completion-Assessment.md", + "ai-spr-05-sprint-1.8-completion-assessment": "doc/knowledge/junie-tasks/AI-SPR/AI-SPR-05-Sprint-1.8-Completion-Assessment.md", + "AI-SYS-01-update-system-prompt-guidelines": "doc/knowledge/junie-tasks/AI-SYS/AI-SYS-01-update-system-prompt-guidelines.md", + "ai-sys-01-update-system-prompt-guidelines": "doc/knowledge/junie-tasks/AI-SYS/AI-SYS-01-update-system-prompt-guidelines.md", + "AI-TEST-01-Copilot-Regression": "doc/knowledge/junie-tasks/AI-TEST/AI-TEST-01-Copilot-Regression.md", + "ai-test-01-copilot-regression": "doc/knowledge/junie-tasks/AI-TEST/AI-TEST-01-Copilot-Regression.md", + "AI-TEST-23-sonar-frontend-coverage-and-threshold": "doc/knowledge/junie-tasks/AI-TEST/AI-TEST-23-sonar-frontend-coverage-and-threshold.md", + "ai-test-23-sonar-frontend-coverage-and-threshold": "doc/knowledge/junie-tasks/AI-TEST/AI-TEST-23-sonar-frontend-coverage-and-threshold.md", + "AI-TEST-50-schema-contract-tests": "doc/knowledge/junie-tasks/AI-TEST/AI-TEST-50-schema-contract-tests.md", + "ai-test-50-schema-contract-tests": "doc/knowledge/junie-tasks/AI-TEST/AI-TEST-50-schema-contract-tests.md", + "AI-TEST-51-provider-integration-tests": "doc/knowledge/junie-tasks/AI-TEST/AI-TEST-51-provider-integration-tests.md", + "ai-test-51-provider-integration-tests": "doc/knowledge/junie-tasks/AI-TEST/AI-TEST-51-provider-integration-tests.md", + "AI-TEST-52-deterministic-regression-suite": "doc/knowledge/junie-tasks/AI-TEST/AI-TEST-52-deterministic-regression-suite.md", + "ai-test-52-deterministic-regression-suite": "doc/knowledge/junie-tasks/AI-TEST/AI-TEST-52-deterministic-regression-suite.md", + "AI-UI-01-Debounce-Quick-Add-AI-Parsing": "doc/knowledge/junie-tasks/AI-UI/AI-UI-01-Debounce-Quick-Add-AI-Parsing.md", + "ai-ui-01-debounce-quick-add-ai-parsing": "doc/knowledge/junie-tasks/AI-UI/AI-UI-01-Debounce-Quick-Add-AI-Parsing.md", + "AI-UI-02-Split-Architecture-and-Architecture-Demo-Routes": "doc/knowledge/junie-tasks/AI-UI/AI-UI-02-Split-Architecture-and-Architecture-Demo-Routes.md", + "ai-ui-02-split-architecture-and-architecture-demo-routes": "doc/knowledge/junie-tasks/AI-UI/AI-UI-02-Split-Architecture-and-Architecture-Demo-Routes.md", + "AI-UI-03-Improve-Architecture-QA-Answer-Formatting": "doc/knowledge/junie-tasks/AI-UI/AI-UI-03-Improve-Architecture-QA-Answer-Formatting.md", + "ai-ui-03-improve-architecture-qa-answer-formatting": "doc/knowledge/junie-tasks/AI-UI/AI-UI-03-Improve-Architecture-QA-Answer-Formatting.md", + "AI-UI-04-Refine-AI-Features-Grid-Layout": "doc/knowledge/junie-tasks/AI-UI/AI-UI-04-Refine-AI-Features-Grid-Layout.md", + "ai-ui-04-refine-ai-features-grid-layout": "doc/knowledge/junie-tasks/AI-UI/AI-UI-04-Refine-AI-Features-Grid-Layout.md", + "AI-UI-05 - Improve Risk Radar Visual Hierarchy": "doc/knowledge/junie-tasks/AI-UI/AI-UI-05 - Improve Risk Radar Visual Hierarchy.md", + "ai-ui-05 - improve risk radar visual hierarchy": "doc/knowledge/junie-tasks/AI-UI/AI-UI-05 - Improve Risk Radar Visual Hierarchy.md", + "AI-UI-06 - Improve Retrospective Summary Card Layout": "doc/knowledge/junie-tasks/AI-UI/AI-UI-06 - Improve Retrospective Summary Card Layout.md", + "ai-ui-06 - improve retrospective summary card layout": "doc/knowledge/junie-tasks/AI-UI/AI-UI-06 - Improve Retrospective Summary Card Layout.md", + "AI-UI-07-Improve-Intelligence-Dashboard-Loading-State": "doc/knowledge/junie-tasks/AI-UI/AI-UI-07-Improve-Intelligence-Dashboard-Loading-State.md", + "ai-ui-07-improve-intelligence-dashboard-loading-state": "doc/knowledge/junie-tasks/AI-UI/AI-UI-07-Improve-Intelligence-Dashboard-Loading-State.md", + "AI-UI-08-Increase-Copilot-Header-Font-Size": "doc/knowledge/junie-tasks/AI-UI/AI-UI-08-Increase-Copilot-Header-Font-Size.md", + "ai-ui-08-increase-copilot-header-font-size": "doc/knowledge/junie-tasks/AI-UI/AI-UI-08-Increase-Copilot-Header-Font-Size.md", + "AI-UI-09-Refine-Onboarding-Assistant-UX": "doc/knowledge/junie-tasks/AI-UI/AI-UI-09-Refine-Onboarding-Assistant-UX.md", + "ai-ui-09-refine-onboarding-assistant-ux": "doc/knowledge/junie-tasks/AI-UI/AI-UI-09-Refine-Onboarding-Assistant-UX.md", + "AI-UI-10-Refine-Copilot-Markdown-Formatting": "doc/knowledge/junie-tasks/AI-UI/AI-UI-10-Refine-Copilot-Markdown-Formatting.md", + "ai-ui-10-refine-copilot-markdown-formatting": "doc/knowledge/junie-tasks/AI-UI/AI-UI-10-Refine-Copilot-Markdown-Formatting.md", + "AI-UI-11-Make-Copilot-Evidence-Navigable": "doc/knowledge/junie-tasks/AI-UI/AI-UI-11-Make-Copilot-Evidence-Navigable.md", + "ai-ui-11-make-copilot-evidence-navigable": "doc/knowledge/junie-tasks/AI-UI/AI-UI-11-Make-Copilot-Evidence-Navigable.md", + "AI-UI-12-Fix-Copilot-Help-Links-and-Metadata-Formatting": "doc/knowledge/junie-tasks/AI-UI/AI-UI-12-Fix-Copilot-Help-Links-and-Metadata-Formatting.md", + "ai-ui-12-fix-copilot-help-links-and-metadata-formatting": "doc/knowledge/junie-tasks/AI-UI/AI-UI-12-Fix-Copilot-Help-Links-and-Metadata-Formatting.md", + "AI-UI-13-Restore-Copilot-Metadata-On-Refresh": "doc/knowledge/junie-tasks/AI-UI/AI-UI-13-Restore-Copilot-Metadata-On-Refresh.md", + "ai-ui-13-restore-copilot-metadata-on-refresh": "doc/knowledge/junie-tasks/AI-UI/AI-UI-13-Restore-Copilot-Metadata-On-Refresh.md", + "AI-UI-COPILOT-SECTION-CONTEXT-01": "doc/knowledge/junie-tasks/AI-UI/AI-UI-COPILOT-SECTION-CONTEXT-01.md", + "ai-ui-copilot-section-context-01": "doc/knowledge/junie-tasks/AI-UI/AI-UI-COPILOT-SECTION-CONTEXT-01.md", + "AI-UI-INTEL-01-Create-AI-Project-Intelligence-Dashboard-page": "doc/knowledge/junie-tasks/AI-UI-INTEL/AI-UI-INTEL-01-Create-AI-Project-Intelligence-Dashboard-page.md", + "ai-ui-intel-01-create-ai-project-intelligence-dashboard-page": "doc/knowledge/junie-tasks/AI-UI-INTEL/AI-UI-INTEL-01-Create-AI-Project-Intelligence-Dashboard-page.md", + "AI-UI-INTEL-02-Render-intelligence-cards-and-sections": "doc/knowledge/junie-tasks/AI-UI-INTEL/AI-UI-INTEL-02-Render-intelligence-cards-and-sections.md", + "ai-ui-intel-02-render-intelligence-cards-and-sections": "doc/knowledge/junie-tasks/AI-UI-INTEL/AI-UI-INTEL-02-Render-intelligence-cards-and-sections.md", + "AI-UX-01-AI-Teaser-Badge": "doc/knowledge/junie-tasks/AI-UX/AI-UX-01-AI-Teaser-Badge.md", + "ai-ux-01-ai-teaser-badge": "doc/knowledge/junie-tasks/AI-UX/AI-UX-01-AI-Teaser-Badge.md", + "AI-UX-02-AI-Teaser-Badge-Polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-02-AI-Teaser-Badge-Polish.md", + "ai-ux-02-ai-teaser-badge-polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-02-AI-Teaser-Badge-Polish.md", + "AI-UX-03-Login-Register-AI-Teaser-Redesign": "doc/knowledge/junie-tasks/AI-UX/AI-UX-03-Login-Register-AI-Teaser-Redesign.md", + "ai-ux-03-login-register-ai-teaser-redesign": "doc/knowledge/junie-tasks/AI-UX/AI-UX-03-Login-Register-AI-Teaser-Redesign.md", + "AI-UX-04-Copilot-Sprint-Selection-Refinement": "doc/knowledge/junie-tasks/AI-UX/AI-UX-04-Copilot-Sprint-Selection-Refinement.md", + "ai-ux-04-copilot-sprint-selection-refinement": "doc/knowledge/junie-tasks/AI-UX/AI-UX-04-Copilot-Sprint-Selection-Refinement.md", + "AI-UX-05-Login-Register-AI-Hero-Intro": "doc/knowledge/junie-tasks/AI-UX/AI-UX-05-Login-Register-AI-Hero-Intro.md", + "ai-ux-05-login-register-ai-hero-intro": "doc/knowledge/junie-tasks/AI-UX/AI-UX-05-Login-Register-AI-Hero-Intro.md", + "AI-UX-06-Auth-AI-Intro-Copy-Polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-06-Auth-AI-Intro-Copy-Polish.md", + "ai-ux-06-auth-ai-intro-copy-polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-06-Auth-AI-Intro-Copy-Polish.md", + "AI-UX-08-section-aware-chat-context": "doc/knowledge/junie-tasks/AI-UX/AI-UX-08-section-aware-chat-context.md", + "ai-ux-08-section-aware-chat-context": "doc/knowledge/junie-tasks/AI-UX/AI-UX-08-section-aware-chat-context.md", + "AI-UX-09-ai-routing-transparency": "doc/knowledge/junie-tasks/AI-UX/AI-UX-09-ai-routing-transparency.md", + "ai-ux-09-ai-routing-transparency": "doc/knowledge/junie-tasks/AI-UX/AI-UX-09-ai-routing-transparency.md", + "AI-UX-10-Frontend-Polish-Epic": "doc/knowledge/junie-tasks/AI-UX/AI-UX-10-Frontend-Polish-Epic.md", + "ai-ux-10-frontend-polish-epic": "doc/knowledge/junie-tasks/AI-UX/AI-UX-10-Frontend-Polish-Epic.md", + "AI-UX-100-Copilot-Workspace-Completion": "doc/knowledge/junie-tasks/AI-UX/AI-UX-100-Copilot-Workspace-Completion.md", + "ai-ux-100-copilot-workspace-completion": "doc/knowledge/junie-tasks/AI-UX/AI-UX-100-Copilot-Workspace-Completion.md", + "AI-UX-100B-credit-top-up": "doc/knowledge/junie-tasks/AI-UX/AI-UX-100B-credit-top-up.md", + "ai-ux-100b-credit-top-up": "doc/knowledge/junie-tasks/AI-UX/AI-UX-100B-credit-top-up.md", + "AI-UX-101-Contact-Form-Redesign": "doc/knowledge/junie-tasks/AI-UX/AI-UX-101-Contact-Form-Redesign.md", + "ai-ux-101-contact-form-redesign": "doc/knowledge/junie-tasks/AI-UX/AI-UX-101-Contact-Form-Redesign.md", + "AI-UX-102-AI-Credit-Usage-Header": "doc/knowledge/junie-tasks/AI-UX/AI-UX-102-AI-Credit-Usage-Header.md", + "ai-ux-102-ai-credit-usage-header": "doc/knowledge/junie-tasks/AI-UX/AI-UX-102-AI-Credit-Usage-Header.md", + "AI-UX-103-adr-discoverability-and-document-viewer": "doc/knowledge/junie-tasks/AI-UX/AI-UX-103-adr-discoverability-and-document-viewer.md", + "ai-ux-103-adr-discoverability-and-document-viewer": "doc/knowledge/junie-tasks/AI-UX/AI-UX-103-adr-discoverability-and-document-viewer.md", + "AI-UX-104-UI-Polish-Fix-Pack": "doc/knowledge/junie-tasks/AI-UX/AI-UX-104-UI-Polish-Fix-Pack.md", + "ai-ux-104-ui-polish-fix-pack": "doc/knowledge/junie-tasks/AI-UX/AI-UX-104-UI-Polish-Fix-Pack.md", + "AI-UX-105-Surface-Partial-AI-Failure-State-in-Intelligence-and-Copilot-UI": "doc/knowledge/junie-tasks/AI-UX/AI-UX-105-Surface-Partial-AI-Failure-State-in-Intelligence-and-Copilot-UI.md", + "ai-ux-105-surface-partial-ai-failure-state-in-intelligence-and-copilot-ui": "doc/knowledge/junie-tasks/AI-UX/AI-UX-105-Surface-Partial-AI-Failure-State-in-Intelligence-and-Copilot-UI.md", + "AI-UX-11-ai-debounce-fix": "doc/knowledge/junie-tasks/AI-UX/AI-UX-11-ai-debounce-fix.md", + "ai-ux-11-ai-debounce-fix": "doc/knowledge/junie-tasks/AI-UX/AI-UX-11-ai-debounce-fix.md", + "AI-UX-12-Auth-Entry-Polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-12-Auth-Entry-Polish.md", + "ai-ux-12-auth-entry-polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-12-Auth-Entry-Polish.md", + "AI-UX-120-AI-Suggestions-Panel": "doc/knowledge/junie-tasks/AI-UX/AI-UX-120-AI-Suggestions-Panel.md", + "ai-ux-120-ai-suggestions-panel": "doc/knowledge/junie-tasks/AI-UX/AI-UX-120-AI-Suggestions-Panel.md", + "AI-UX-121-Actionable-Suggestions": "doc/knowledge/junie-tasks/AI-UX/AI-UX-121-Actionable-Suggestions.md", + "ai-ux-121-actionable-suggestions": "doc/knowledge/junie-tasks/AI-UX/AI-UX-121-Actionable-Suggestions.md", + "AI-UX-122-unified-sprint-selector": "doc/knowledge/junie-tasks/AI-UX/AI-UX-122-unified-sprint-selector.md", + "ai-ux-122-unified-sprint-selector": "doc/knowledge/junie-tasks/AI-UX/AI-UX-122-unified-sprint-selector.md", + "AI-UX-123-Fix-Epic-Dashboard-Icon-Overlap": "doc/knowledge/junie-tasks/AI-UX/AI-UX-123-Fix-Epic-Dashboard-Icon-Overlap.md", + "ai-ux-123-fix-epic-dashboard-icon-overlap": "doc/knowledge/junie-tasks/AI-UX/AI-UX-123-Fix-Epic-Dashboard-Icon-Overlap.md", + "AI-UX-124-Shared-UI-Primitives": "doc/knowledge/junie-tasks/AI-UX/AI-UX-124-Shared-UI-Primitives.md", + "ai-ux-124-shared-ui-primitives": "doc/knowledge/junie-tasks/AI-UX/AI-UX-124-Shared-UI-Primitives.md", + "AI-UX-125-Risk-Details-Text-Wrapping-and-Density": "doc/knowledge/junie-tasks/AI-UX/AI-UX-125-Risk-Details-Text-Wrapping-and-Density.md", + "ai-ux-125-risk-details-text-wrapping-and-density": "doc/knowledge/junie-tasks/AI-UX/AI-UX-125-Risk-Details-Text-Wrapping-and-Density.md", + "AI-UX-126-section-aware-chat": "doc/knowledge/junie-tasks/AI-UX/AI-UX-126-section-aware-chat.md", + "ai-ux-126-section-aware-chat": "doc/knowledge/junie-tasks/AI-UX/AI-UX-126-section-aware-chat.md", + "AI-UX-127-Overflow-to-Scroll-Behavior": "doc/knowledge/junie-tasks/AI-UX/AI-UX-127-Overflow-to-Scroll-Behavior.md", + "ai-ux-127-overflow-to-scroll-behavior": "doc/knowledge/junie-tasks/AI-UX/AI-UX-127-Overflow-to-Scroll-Behavior.md", + "AI-UX-128-Architecture-Chat-Prompt-Suggestions": "doc/knowledge/junie-tasks/AI-UX/AI-UX-128-Architecture-Chat-Prompt-Suggestions.md", + "ai-ux-128-architecture-chat-prompt-suggestions": "doc/knowledge/junie-tasks/AI-UX/AI-UX-128-Architecture-Chat-Prompt-Suggestions.md", + "AI-UX-129-Intelligence-Dashboard-Explanations": "doc/knowledge/junie-tasks/AI-UX/AI-UX-129-Intelligence-Dashboard-Explanations.md", + "ai-ux-129-intelligence-dashboard-explanations": "doc/knowledge/junie-tasks/AI-UX/AI-UX-129-Intelligence-Dashboard-Explanations.md", + "AI-UX-13-Header-Sidenav-Polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-13-Header-Sidenav-Polish.md", + "ai-ux-13-header-sidenav-polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-13-Header-Sidenav-Polish.md", + "AI-UX-130-Split-Epic-Dashboard-and-Intelligence-Dashboard-Concerns": "doc/knowledge/junie-tasks/AI-UX/AI-UX-130-Split-Epic-Dashboard-and-Intelligence-Dashboard-Concerns.md", + "ai-ux-130-split-epic-dashboard-and-intelligence-dashboard-concerns": "doc/knowledge/junie-tasks/AI-UX/AI-UX-130-Split-Epic-Dashboard-and-Intelligence-Dashboard-Concerns.md", + "AI-UX-131-Copilot-Layout-Polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-131-Copilot-Layout-Polish.md", + "ai-ux-131-copilot-layout-polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-131-Copilot-Layout-Polish.md", + "AI-UX-14-AI-Feature-Pages-Consistency": "doc/knowledge/junie-tasks/AI-UX/AI-UX-14-AI-Feature-Pages-Consistency.md", + "ai-ux-14-ai-feature-pages-consistency": "doc/knowledge/junie-tasks/AI-UX/AI-UX-14-AI-Feature-Pages-Consistency.md", + "AI-UX-15-Dashboard-Tasks-Polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-15-Dashboard-Tasks-Polish.md", + "ai-ux-15-dashboard-tasks-polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-15-Dashboard-Tasks-Polish.md", + "AI-UX-16-Visual-Consistency-Guardrails": "doc/knowledge/junie-tasks/AI-UX/AI-UX-16-Visual-Consistency-Guardrails.md", + "ai-ux-16-visual-consistency-guardrails": "doc/knowledge/junie-tasks/AI-UX/AI-UX-16-Visual-Consistency-Guardrails.md", + "AI-UX-19-Risk-Radar-Full-Width-Layout": "doc/knowledge/junie-tasks/AI-UX/AI-UX-19-Risk-Radar-Full-Width-Layout.md", + "ai-ux-19-risk-radar-full-width-layout": "doc/knowledge/junie-tasks/AI-UX/AI-UX-19-Risk-Radar-Full-Width-Layout.md", + "AI-UX-20-ai-routing-transparency": "doc/knowledge/junie-tasks/AI-UX/AI-UX-20-ai-routing-transparency.md", + "ai-ux-20-ai-routing-transparency": "doc/knowledge/junie-tasks/AI-UX/AI-UX-20-ai-routing-transparency.md", + "AI-UX-21-Dark-Mode-Token-Consolidation": "doc/knowledge/junie-tasks/AI-UX/AI-UX-21-Dark-Mode-Token-Consolidation.md", + "ai-ux-21-dark-mode-token-consolidation": "doc/knowledge/junie-tasks/AI-UX/AI-UX-21-Dark-Mode-Token-Consolidation.md", + "AI-UX-22-chat-context-isolation": "doc/knowledge/junie-tasks/AI-UX/AI-UX-22-chat-context-isolation.md", + "ai-ux-22-chat-context-isolation": "doc/knowledge/junie-tasks/AI-UX/AI-UX-22-chat-context-isolation.md", + "AI-UX-23-Mobile-and-Narrow-Viewport-Stabilization": "doc/knowledge/junie-tasks/AI-UX/AI-UX-23-Mobile-and-Narrow-Viewport-Stabilization.md", + "ai-ux-23-mobile-and-narrow-viewport-stabilization": "doc/knowledge/junie-tasks/AI-UX/AI-UX-23-Mobile-and-Narrow-Viewport-Stabilization.md", + "AI-UX-24-AI-Panels-Visual-Hierarchy-Polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-24-AI-Panels-Visual-Hierarchy-Polish.md", + "ai-ux-24-ai-panels-visual-hierarchy-polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-24-AI-Panels-Visual-Hierarchy-Polish.md", + "AI-UX-25-AI-Panel-Layout-Stabilization": "doc/knowledge/junie-tasks/AI-UX/AI-UX-25-AI-Panel-Layout-Stabilization.md", + "ai-ux-25-ai-panel-layout-stabilization": "doc/knowledge/junie-tasks/AI-UX/AI-UX-25-AI-Panel-Layout-Stabilization.md", + "AI-UX-26-Dark-Mode-Pseudo-Checkbox-Fix-for-AI-Taskset-Panels": "doc/knowledge/junie-tasks/AI-UX/AI-UX-26-Dark-Mode-Pseudo-Checkbox-Fix-for-AI-Taskset-Panels.md", + "ai-ux-26-dark-mode-pseudo-checkbox-fix-for-ai-taskset-panels": "doc/knowledge/junie-tasks/AI-UX/AI-UX-26-Dark-Mode-Pseudo-Checkbox-Fix-for-AI-Taskset-Panels.md", + "AI-UX-27-AI-Accent-Token-Split-for-Light-and-Dark-Surfaces": "doc/knowledge/junie-tasks/AI-UX/AI-UX-27-AI-Accent-Token-Split-for-Light-and-Dark-Surfaces.md", + "ai-ux-27-ai-accent-token-split-for-light-and-dark-surfaces": "doc/knowledge/junie-tasks/AI-UX/AI-UX-27-AI-Accent-Token-Split-for-Light-and-Dark-Surfaces.md", + "AI-UX-28-Shared-AI-Taskset-Panel-Styling-Consolidation": "doc/knowledge/junie-tasks/AI-UX/AI-UX-28-Shared-AI-Taskset-Panel-Styling-Consolidation.md", + "ai-ux-28-shared-ai-taskset-panel-styling-consolidation": "doc/knowledge/junie-tasks/AI-UX/AI-UX-28-Shared-AI-Taskset-Panel-Styling-Consolidation.md", + "AI-UX-29-Theme-Variable-Cleanup-for-Undefined-Tokens": "doc/knowledge/junie-tasks/AI-UX/AI-UX-29-Theme-Variable-Cleanup-for-Undefined-Tokens.md", + "ai-ux-29-theme-variable-cleanup-for-undefined-tokens": "doc/knowledge/junie-tasks/AI-UX/AI-UX-29-Theme-Variable-Cleanup-for-Undefined-Tokens.md", + "AI-UX-30-AI-Icon-Consistency-Pass": "doc/knowledge/junie-tasks/AI-UX/AI-UX-30-AI-Icon-Consistency-Pass.md", + "ai-ux-30-ai-icon-consistency-pass": "doc/knowledge/junie-tasks/AI-UX/AI-UX-30-AI-Icon-Consistency-Pass.md", + "AI-UX-31-User-Admin-Action-Icon-Semantic-Differentiation": "doc/knowledge/junie-tasks/AI-UX/AI-UX-31-User-Admin-Action-Icon-Semantic-Differentiation.md", + "ai-ux-31-user-admin-action-icon-semantic-differentiation": "doc/knowledge/junie-tasks/AI-UX/AI-UX-31-User-Admin-Action-Icon-Semantic-Differentiation.md", + "AI-UX-32-Login-Register-Branding-with-Product-Identity": "doc/knowledge/junie-tasks/AI-UX/AI-UX-32-Login-Register-Branding-with-Product-Identity.md", + "ai-ux-32-login-register-branding-with-product-identity": "doc/knowledge/junie-tasks/AI-UX/AI-UX-32-Login-Register-Branding-with-Product-Identity.md", + "AI-UX-33-Standard-Page-Header-Component": "doc/knowledge/junie-tasks/AI-UX/AI-UX-33-Standard-Page-Header-Component.md", + "ai-ux-33-standard-page-header-component": "doc/knowledge/junie-tasks/AI-UX/AI-UX-33-Standard-Page-Header-Component.md", + "AI-UX-34-Admin-Page-Card-Layout-for-Tables": "doc/knowledge/junie-tasks/AI-UX/AI-UX-34-Admin-Page-Card-Layout-for-Tables.md", + "ai-ux-34-admin-page-card-layout-for-tables": "doc/knowledge/junie-tasks/AI-UX/AI-UX-34-Admin-Page-Card-Layout-for-Tables.md", + "AI-UX-35-Navigation-Menu-Structure-Improvement": "doc/knowledge/junie-tasks/AI-UX/AI-UX-35-Navigation-Menu-Structure-Improvement.md", + "ai-ux-35-navigation-menu-structure-improvement": "doc/knowledge/junie-tasks/AI-UX/AI-UX-35-Navigation-Menu-Structure-Improvement.md", + "AI-UX-36-AI-Task-Quick-Add-UX-Improvement": "doc/knowledge/junie-tasks/AI-UX/AI-UX-36-AI-Task-Quick-Add-UX-Improvement.md", + "ai-ux-36-ai-task-quick-add-ux-improvement": "doc/knowledge/junie-tasks/AI-UX/AI-UX-36-AI-Task-Quick-Add-UX-Improvement.md", + "AI-UX-37-System-Status-Layout-Alignment": "doc/knowledge/junie-tasks/AI-UX/AI-UX-37-System-Status-Layout-Alignment.md", + "ai-ux-37-system-status-layout-alignment": "doc/knowledge/junie-tasks/AI-UX/AI-UX-37-System-Status-Layout-Alignment.md", + "AI-UX-38-Dashboard-Metrics-Enhancement": "doc/knowledge/junie-tasks/AI-UX/AI-UX-38-Dashboard-Metrics-Enhancement.md", + "ai-ux-38-dashboard-metrics-enhancement": "doc/knowledge/junie-tasks/AI-UX/AI-UX-38-Dashboard-Metrics-Enhancement.md", + "AI-UX-39-Lightweight-UI-Design-System": "doc/knowledge/junie-tasks/AI-UX/AI-UX-39-Lightweight-UI-Design-System.md", + "ai-ux-39-lightweight-ui-design-system": "doc/knowledge/junie-tasks/AI-UX/AI-UX-39-Lightweight-UI-Design-System.md", + "AI-UX-40-Empty-State-Design": "doc/knowledge/junie-tasks/AI-UX/AI-UX-40-Empty-State-Design.md", + "ai-ux-40-empty-state-design": "doc/knowledge/junie-tasks/AI-UX/AI-UX-40-Empty-State-Design.md", + "AI-UX-41-Loading-Skeletons": "doc/knowledge/junie-tasks/AI-UX/AI-UX-41-Loading-Skeletons.md", + "ai-ux-41-loading-skeletons": "doc/knowledge/junie-tasks/AI-UX/AI-UX-41-Loading-Skeletons.md", + "AI-UX-42-AI-Result-Visualization": "doc/knowledge/junie-tasks/AI-UX/AI-UX-42-AI-Result-Visualization.md", + "ai-ux-42-ai-result-visualization": "doc/knowledge/junie-tasks/AI-UX/AI-UX-42-AI-Result-Visualization.md", + "AI-UX-43-Risk-Radar-Report-Layout": "doc/knowledge/junie-tasks/AI-UX/AI-UX-43-Risk-Radar-Report-Layout.md", + "ai-ux-43-risk-radar-report-layout": "doc/knowledge/junie-tasks/AI-UX/AI-UX-43-Risk-Radar-Report-Layout.md", + "AI-UX-44-Retrospective-Report-UI": "doc/knowledge/junie-tasks/AI-UX/AI-UX-44-Retrospective-Report-UI.md", + "ai-ux-44-retrospective-report-ui": "doc/knowledge/junie-tasks/AI-UX/AI-UX-44-Retrospective-Report-UI.md", + "AI-UX-45-Architecture-Chat-UI": "doc/knowledge/junie-tasks/AI-UX/AI-UX-45-Architecture-Chat-UI.md", + "ai-ux-45-architecture-chat-ui": "doc/knowledge/junie-tasks/AI-UX/AI-UX-45-Architecture-Chat-UI.md", + "AI-UX-46-Streaming-AI-Response-UX": "doc/knowledge/junie-tasks/AI-UX/AI-UX-46-Streaming-AI-Response-UX.md", + "ai-ux-46-streaming-ai-response-ux": "doc/knowledge/junie-tasks/AI-UX/AI-UX-46-Streaming-AI-Response-UX.md", + "AI-UX-47-Architecture-Chat-Conversation-History": "doc/knowledge/junie-tasks/AI-UX/AI-UX-47-Architecture-Chat-Conversation-History.md", + "ai-ux-47-architecture-chat-conversation-history": "doc/knowledge/junie-tasks/AI-UX/AI-UX-47-Architecture-Chat-Conversation-History.md", + "AI-UX-48-Risk-Radar-Severity-Visualization": "doc/knowledge/junie-tasks/AI-UX/AI-UX-48-Risk-Radar-Severity-Visualization.md", + "ai-ux-48-risk-radar-severity-visualization": "doc/knowledge/junie-tasks/AI-UX/AI-UX-48-Risk-Radar-Severity-Visualization.md", + "AI-UX-49-Retrospective-Insights-Card-Layout": "doc/knowledge/junie-tasks/AI-UX/AI-UX-49-Retrospective-Insights-Card-Layout.md", + "ai-ux-49-retrospective-insights-card-layout": "doc/knowledge/junie-tasks/AI-UX/AI-UX-49-Retrospective-Insights-Card-Layout.md", + "AI-UX-50-Dashboard-Mini-Trends-Sparklines": "doc/knowledge/junie-tasks/AI-UX/AI-UX-50-Dashboard-Mini-Trends-Sparklines.md", + "ai-ux-50-dashboard-mini-trends-sparklines": "doc/knowledge/junie-tasks/AI-UX/AI-UX-50-Dashboard-Mini-Trends-Sparklines.md", + "AI-UX-51-AI-Activity-Timeline": "doc/knowledge/junie-tasks/AI-UX/AI-UX-51-AI-Activity-Timeline.md", + "ai-ux-51-ai-activity-timeline": "doc/knowledge/junie-tasks/AI-UX/AI-UX-51-AI-Activity-Timeline.md", + "AI-UX-52-Generated-Report-Export-Readiness": "doc/knowledge/junie-tasks/AI-UX/AI-UX-52-Generated-Report-Export-Readiness.md", + "ai-ux-52-generated-report-export-readiness": "doc/knowledge/junie-tasks/AI-UX/AI-UX-52-Generated-Report-Export-Readiness.md", + "AI-UX-53-Product-Empty-States": "doc/knowledge/junie-tasks/AI-UX/AI-UX-53-Product-Empty-States.md", + "ai-ux-53-product-empty-states": "doc/knowledge/junie-tasks/AI-UX/AI-UX-53-Product-Empty-States.md", + "AI-UX-54-Unified-AI-Result-Container": "doc/knowledge/junie-tasks/AI-UX/AI-UX-54-Unified-AI-Result-Container.md", + "ai-ux-54-unified-ai-result-container": "doc/knowledge/junie-tasks/AI-UX/AI-UX-54-Unified-AI-Result-Container.md", + "AI-UX-55-Demo-Mode-Visual-Polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-55-Demo-Mode-Visual-Polish.md", + "ai-ux-55-demo-mode-visual-polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-55-Demo-Mode-Visual-Polish.md", + "AI-UX-96-authentication-screen-simplification": "doc/knowledge/junie-tasks/AI-UX/AI-UX-96-authentication-screen-simplification.md", + "ai-ux-96-authentication-screen-simplification": "doc/knowledge/junie-tasks/AI-UX/AI-UX-96-authentication-screen-simplification.md", + "AI-UX-97-architecture-chat-improvements": "doc/knowledge/junie-tasks/AI-UX/AI-UX-97-architecture-chat-improvements.md", + "ai-ux-97-architecture-chat-improvements": "doc/knowledge/junie-tasks/AI-UX/AI-UX-97-architecture-chat-improvements.md", + "AI-UX-98 - Epic Dashboard Page": "doc/knowledge/junie-tasks/AI-UX/AI-UX-98 - Epic Dashboard Page.md", + "ai-ux-98 - epic dashboard page": "doc/knowledge/junie-tasks/AI-UX/AI-UX-98 - Epic Dashboard Page.md", + "AI-UX-99-architecture-chat-streaming-response": "doc/knowledge/junie-tasks/AI-UX/AI-UX-99-architecture-chat-streaming-response.md", + "ai-ux-99-architecture-chat-streaming-response": "doc/knowledge/junie-tasks/AI-UX/AI-UX-99-architecture-chat-streaming-response.md", + "AI-UX-99R-Split-Epic-and-Intelligence-Dashboards": "doc/knowledge/junie-tasks/AI-UX/AI-UX-99R-Split-Epic-and-Intelligence-Dashboards.md", + "ai-ux-99r-split-epic-and-intelligence-dashboards": "doc/knowledge/junie-tasks/AI-UX/AI-UX-99R-Split-Epic-and-Intelligence-Dashboards.md", + "AI-WEB-21-Add-GitHub-Repository-Link-to-Navigation": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-21-Add-GitHub-Repository-Link-to-Navigation.md", + "ai-web-21-add-github-repository-link-to-navigation": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-21-Add-GitHub-Repository-Link-to-Navigation.md", + "AI-WEB-22-Add-View-on-GitHub-CTA-Button": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-22-Add-View-on-GitHub-CTA-Button.md", + "ai-web-22-add-view-on-github-cta-button": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-22-Add-View-on-GitHub-CTA-Button.md", + "AI-WEB-23-Add-Live-Demo-Architecture-AI-Features-Landing-Section": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-23-Add-Live-Demo-Architecture-AI-Features-Landing-Section.md", + "ai-web-23-add-live-demo-architecture-ai-features-landing-section": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-23-Add-Live-Demo-Architecture-AI-Features-Landing-Section.md", + "AI-WEB-24-Extended-Refine-GitHub-CTA-Landing-Links-and-UI-Polish": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-24-Extended-Refine-GitHub-CTA-Landing-Links-and-UI-Polish.md", + "ai-web-24-extended-refine-github-cta-landing-links-and-ui-polish": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-24-Extended-Refine-GitHub-CTA-Landing-Links-and-UI-Polish.md", + "AI-WEB-27-Implement-Architecture-and-Features-Landing-Pages": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-27-Implement-Architecture-and-Features-Landing-Pages.md", + "ai-web-27-implement-architecture-and-features-landing-pages": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-27-Implement-Architecture-and-Features-Landing-Pages.md", + "AI-WEB-28-architecture-page-public-access-safeguard": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-28-architecture-page-public-access-safeguard.md", + "ai-web-28-architecture-page-public-access-safeguard": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-28-architecture-page-public-access-safeguard.md", + "AI-WEB-29-reduce-architecture-hero-color": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-29-reduce-architecture-hero-color.md", + "ai-web-29-reduce-architecture-hero-color": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-29-reduce-architecture-hero-color.md", + "AI-WEB-30-card-hover-polish": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-30-card-hover-polish.md", + "ai-web-30-card-hover-polish": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-30-card-hover-polish.md", + "AI-WEB-31-semantic-surface-tokens": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-31-semantic-surface-tokens.md", + "ai-web-31-semantic-surface-tokens": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-31-semantic-surface-tokens.md", + "AI-WEB-32-dark-mode-fix": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-32-dark-mode-fix.md", + "ai-web-32-dark-mode-fix": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-32-dark-mode-fix.md", + "AI-WEB-33-Add-sprint-selector-dropdown-for-intelligence-dashboards": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-33-Add-sprint-selector-dropdown-for-intelligence-dashboards.md", + "ai-web-33-add-sprint-selector-dropdown-for-intelligence-dashboards": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-33-Add-sprint-selector-dropdown-for-intelligence-dashboards.md", + "AI-WEB-34-global-responsive-form-layout-standard": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-34-global-responsive-form-layout-standard.md", + "ai-web-34-global-responsive-form-layout-standard": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-34-global-responsive-form-layout-standard.md", + "AI-WEB-35-Reposition-GoodOne-demo-and-rebalance-GitHub-CTA": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-35-Reposition-GoodOne-demo-and-rebalance-GitHub-CTA.md", + "ai-web-35-reposition-goodone-demo-and-rebalance-github-cta": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-35-Reposition-GoodOne-demo-and-rebalance-GitHub-CTA.md", + "AI-WEB-36-Provide-menu-items-for-Copilot-and-Intelligence": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-36-Provide-menu-items-for-Copilot-and-Intelligence.md", + "ai-web-36-provide-menu-items-for-copilot-and-intelligence": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-36-Provide-menu-items-for-Copilot-and-Intelligence.md", + "AI-WEB-37-login-page-visual-hierarchy-polish": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-37-login-page-visual-hierarchy-polish.md", + "ai-web-37-login-page-visual-hierarchy-polish": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-37-login-page-visual-hierarchy-polish.md", + "AI-WEB-38-UI-and-Runtime-Fixes-Bundle": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-38-UI-and-Runtime-Fixes-Bundle.md", + "ai-web-38-ui-and-runtime-fixes-bundle": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-38-UI-and-Runtime-Fixes-Bundle.md", + "AI-WEB-39-Architecture-Page-UI-Fixes": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-39-Architecture-Page-UI-Fixes.md", + "ai-web-39-architecture-page-ui-fixes": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-39-Architecture-Page-UI-Fixes.md", + "AI-WEB-40-ai-transparency-panel": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-40-ai-transparency-panel.md", + "ai-web-40-ai-transparency-panel": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-40-ai-transparency-panel.md", + "AI-WEB-41-split-architecture-product-and-demo-pages": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-41-split-architecture-product-and-demo-pages.md", + "ai-web-41-split-architecture-product-and-demo-pages": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-41-split-architecture-product-and-demo-pages.md", + "AI-WEB-42-debounce-quick-add-parser": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-42-debounce-quick-add-parser.md", + "ai-web-42-debounce-quick-add-parser": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-42-debounce-quick-add-parser.md", + "AI-WEB-43-features-visual-balance": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-43-features-visual-balance.md", + "ai-web-43-features-visual-balance": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-43-features-visual-balance.md", + "AI-WEB-44-Fix epics SSE UI not refreshing after final dashboard update": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-44-Fix epics SSE UI not refreshing after final dashboard update.md", + "ai-web-44-fix epics sse ui not refreshing after final dashboard update": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-44-Fix epics SSE UI not refreshing after final dashboard update.md", + "AI-WEB-45-fix-retrospective-todate-overflow": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-45-fix-retrospective-todate-overflow.md", + "ai-web-45-fix-retrospective-todate-overflow": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-45-fix-retrospective-todate-overflow.md", + "AI-WEB-46–Improve–GitHub–Visibility": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-46–Improve–GitHub–Visibility.md", + "ai-web-46–improve–github–visibility": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-46–Improve–GitHub–Visibility.md", + "AI-WEB-47-GoodOne-UI-Polish-Bundle": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-47-GoodOne-UI-Polish-Bundle.md", + "ai-web-47-goodone-ui-polish-bundle": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-47-GoodOne-UI-Polish-Bundle.md", + "AI-WEB-48-Polish-sprint-selector-UI-for-intelligence-dashboards": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-48-Polish-sprint-selector-UI-for-intelligence-dashboards.md", + "ai-web-48-polish-sprint-selector-ui-for-intelligence-dashboards": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-48-Polish-sprint-selector-UI-for-intelligence-dashboards.md", + "AI-WEB-49-shared-angular-form-row-component": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-49-shared-angular-form-row-component.md", + "ai-web-49-shared-angular-form-row-component": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-49-shared-angular-form-row-component.md", + "AI-WEB-50-standardize-taskgroup-filter-bar-layout": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-50-standardize-taskgroup-filter-bar-layout.md", + "ai-web-50-standardize-taskgroup-filter-bar-layout": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-50-standardize-taskgroup-filter-bar-layout.md", + "AI-WEB-51-Rebalance-login-page-after-demo-move": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-51-Rebalance-login-page-after-demo-move.md", + "ai-web-51-rebalance-login-page-after-demo-move": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-51-Rebalance-login-page-after-demo-move.md", + "AI-WEB-52-reduce-github-cta-prominence-login-page": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-52-reduce-github-cta-prominence-login-page.md", + "ai-web-52-reduce-github-cta-prominence-login-page": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-52-reduce-github-cta-prominence-login-page.md", + "AI-WEB-53-Restore-Monitoring-Server": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-53-Restore-Monitoring-Server.md", + "ai-web-53-restore-monitoring-server": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-53-Restore-Monitoring-Server.md", + "taskset-4-7": "doc/knowledge/junie-tasks/backlog/taskset-4-7.md", + "guardrails-implementation-order": "doc/knowledge/junie-tasks/sprints/guardrails-implementation-order.md", + "sprint-1.3-plan": "doc/knowledge/junie-tasks/sprints/sprint-1.3-plan.md", + "sprint-1.4-execution-order": "doc/knowledge/junie-tasks/sprints/sprint-1.4-execution-order.md", + "sprint-1.4-plan": "doc/knowledge/junie-tasks/sprints/sprint-1.4-plan.md", + "sprint-1.4-prompt": "doc/knowledge/junie-tasks/sprints/sprint-1.4-prompt.md", + "sprint-1.5-execution-order": "doc/knowledge/junie-tasks/sprints/sprint-1.5-execution-order.md", + "sprint-1.5-plan": "doc/knowledge/junie-tasks/sprints/sprint-1.5-plan.md", + "sprint-1.7-execution-order": "doc/knowledge/junie-tasks/sprints/sprint-1.7-execution-order.md", + "sprint-1.7-plan": "doc/knowledge/junie-tasks/sprints/sprint-1.7-plan.md", + "sprint-AI-INTEL-01-plan": "doc/knowledge/junie-tasks/sprints/sprint-AI-INTEL-01-plan.md", + "sprint-ai-intel-01-plan": "doc/knowledge/junie-tasks/sprints/sprint-AI-INTEL-01-plan.md", + "sprint-prompt-template-disciplined": "doc/knowledge/junie-tasks/sprints/sprint-prompt-template-disciplined.md", + "sprint-prompt-template": "doc/knowledge/junie-tasks/sprints/sprint-prompt-template.md", + "sprint-prompt": "doc/knowledge/junie-tasks/sprints/sprint-prompt.md", + "SPRINT_TEMPLATE": "doc/knowledge/junie-tasks/sprints/SPRINT_TEMPLATE.md", + "sprint_template": "doc/knowledge/junie-tasks/sprints/SPRINT_TEMPLATE.md", + "updated-roadmap-after-sprint-1.7": "doc/knowledge/junie-tasks/sprints/updated-roadmap-after-sprint-1.7.md", + "sprint-1.6-execution-order": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6-execution-order.md", + "sprint-1.6-plan": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6-plan.md", + "sprint-1.6-status-assessment": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6-status-assessment.md", + "sprint-1.6A-cleanup-execution-order": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6A-cleanup-execution-order.md", + "sprint-1.6a-cleanup-execution-order": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6A-cleanup-execution-order.md", + "sprint-1.6A-cleanup-plan": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6A-cleanup-plan.md", + "sprint-1.6a-cleanup-plan": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6A-cleanup-plan.md", + "sprint-1.6A-review-guide": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6A-review-guide.md", + "sprint-1.6a-review-guide": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6A-review-guide.md", + "sprint-1.6B-epic-dashboard-execution-order": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6B-epic-dashboard-execution-order.md", + "sprint-1.6b-epic-dashboard-execution-order": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6B-epic-dashboard-execution-order.md", + "sprint-1.6B-epic-dashboard-plan": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6B-epic-dashboard-plan.md", + "sprint-1.6b-epic-dashboard-plan": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6B-epic-dashboard-plan.md", + "sprint-1.8-execution-order": "doc/knowledge/junie-tasks/sprints/sprint-1.8/sprint-1.8-execution-order.md", + "sprint-1.8-plan": "doc/knowledge/junie-tasks/sprints/sprint-1.8/sprint-1.8-plan.md", + "sprint-1.9-execution-order": "doc/knowledge/junie-tasks/sprints/sprint-1.9/sprint-1.9-execution-order.md", + "sprint-1.9-plan": "doc/knowledge/junie-tasks/sprints/sprint-1.9/sprint-1.9-plan.md", + "sprint-2.0-execution-order": "doc/knowledge/junie-tasks/sprints/sprint-2.0/sprint-2.0-execution-order.md", + "sprint-2.0-plan": "doc/knowledge/junie-tasks/sprints/sprint-2.0/sprint-2.0-plan.md", + "ai-regression-test": "doc/knowledge/junie-tasks/sprints/sprint-2.1/ai-regression-test.md", + "README-backlog": "doc/knowledge/junie-tasks/sprints/sprint-2.1/README-backlog.md", + "readme-backlog": "doc/knowledge/junie-tasks/sprints/sprint-2.1/README-backlog.md", + "sprint-2.1-chat-history": "doc/knowledge/junie-tasks/sprints/sprint-2.1/sprint-2.1-chat-history.md", + "sprint-2.1-corrective-plan": "doc/knowledge/junie-tasks/sprints/sprint-2.1/sprint-2.1-corrective-plan.md", + "sprint-2.1-definition-of-done": "doc/knowledge/junie-tasks/sprints/sprint-2.1/sprint-2.1-definition-of-done.md", + "sprint-2.1-execution-order": "doc/knowledge/junie-tasks/sprints/sprint-2.1/sprint-2.1-execution-order.md", + "sprint-2.1-plan": "doc/knowledge/junie-tasks/sprints/sprint-2.1/sprint-2.1-plan.md", + "sprint-2.1-risk-checklist": "doc/knowledge/junie-tasks/sprints/sprint-2.1/sprint-2.1-risk-checklist.md", + "architecture-q1.expected": "doc/knowledge/junie-tasks/sprints/sprint-2.1/qa/ai-baselines/copilot/architecture-q1.expected.md", + "report-layout": "doc/knowledge/junie-tasks/sprints/sprint-2.1/qa/playwright/report-layout.md", + "sprint-2-2-retro-problems": "doc/knowledge/junie-tasks/sprints/sprint-2.2/sprint-2-2-retro-problems.md", + "sprint-2.2-plan": "doc/knowledge/junie-tasks/sprints/sprint-2.2/sprint-2.2-plan.md", + "dto-proposal": "doc/knowledge/junie-tasks/sprints/sprint-2.2/api/dto-proposal.md", + "integration-notes": "doc/knowledge/junie-tasks/sprints/sprint-2.2/backend/integration-notes.md", + "ai-coverage-wireframe": "doc/knowledge/junie-tasks/sprints/sprint-2.2/wireframes/ai-coverage-wireframe.md", + "AI-ARCH-Summary": "doc/knowledge/junie-tasks/task-governance/AI-ARCH-Summary.md", + "ai-arch-summary": "doc/knowledge/junie-tasks/task-governance/AI-ARCH-Summary.md", + "AI-TASK-CONTRACT-STANDARD": "doc/knowledge/junie-tasks/task-governance/AI-TASK-CONTRACT-STANDARD.md", + "ai-task-contract-standard": "doc/knowledge/junie-tasks/task-governance/AI-TASK-CONTRACT-STANDARD.md", + "AI-TASK-GOVERNANCE": "doc/knowledge/junie-tasks/task-governance/AI-TASK-GOVERNANCE.md", + "ai-task-governance": "doc/knowledge/junie-tasks/task-governance/AI-TASK-GOVERNANCE.md", + "guardrails-next-steps": "doc/knowledge/junie-tasks/task-governance/guardrails-next-steps.md", + "JUNIE-EXECUTION-PROMPT-TEMPLATE": "doc/knowledge/junie-tasks/task-governance/JUNIE-EXECUTION-PROMPT-TEMPLATE.md", + "junie-execution-prompt-template": "doc/knowledge/junie-tasks/task-governance/JUNIE-EXECUTION-PROMPT-TEMPLATE.md", + "junie-task-format-guideline": "doc/knowledge/junie-tasks/task-governance/junie-task-format-guideline.md", + "junie-task-template": "doc/knowledge/junie-tasks/task-governance/junie-task-template.md", + "junie-task-validator": "doc/knowledge/junie-tasks/task-governance/junie-task-validator.md", + "JUNIE_TASK_GOVERNANCE": "doc/knowledge/junie-tasks/task-governance/JUNIE_TASK_GOVERNANCE.md", + "junie_task_governance": "doc/knowledge/junie-tasks/task-governance/JUNIE_TASK_GOVERNANCE.md", + "README-task-contract-linter": "doc/knowledge/junie-tasks/task-governance/README-task-contract-linter.md", + "readme-task-contract-linter": "doc/knowledge/junie-tasks/task-governance/README-task-contract-linter.md", + "TASK-TEMPLATE-v2": "doc/knowledge/junie-tasks/task-governance/TASK-TEMPLATE-v2.md", + "task-template-v2": "doc/knowledge/junie-tasks/task-governance/TASK-TEMPLATE-v2.md", + "TASK-TEMPLATE": "doc/knowledge/junie-tasks/task-governance/TASK-TEMPLATE.md", + "task-template": "doc/knowledge/junie-tasks/task-governance/TASK-TEMPLATE.md", + "TASK_TEMPLATE": "doc/knowledge/junie-tasks/task-governance/TASK_TEMPLATE.md", + "task_template": "doc/knowledge/junie-tasks/task-governance/TASK_TEMPLATE.md", + "4-week-roadmap": "doc/knowledge/junie-tasks/taskset-1/4-week-roadmap.md", + "CFG-01-Introduce-Spring-Profiles-dev-demo-prod": "doc/knowledge/junie-tasks/taskset-1/p0/CFG-01-Introduce-Spring-Profiles-dev-demo-prod.md", + "cfg-01-introduce-spring-profiles-dev-demo-prod": "doc/knowledge/junie-tasks/taskset-1/p0/CFG-01-Introduce-Spring-Profiles-dev-demo-prod.md", + "CFG-02-Remove-Default-Secrets-and-Passwords": "doc/knowledge/junie-tasks/taskset-1/p0/CFG-02-Remove-Default-Secrets-and-Passwords.md", + "cfg-02-remove-default-secrets-and-passwords": "doc/knowledge/junie-tasks/taskset-1/p0/CFG-02-Remove-Default-Secrets-and-Passwords.md", + "DEMO-01-Deterministic-Demo-Reset": "doc/knowledge/junie-tasks/taskset-1/p0/DEMO-01-Deterministic-Demo-Reset.md", + "demo-01-deterministic-demo-reset": "doc/knowledge/junie-tasks/taskset-1/p0/DEMO-01-Deterministic-Demo-Reset.md", + "DEMO-02-Demo-Reset-UI": "doc/knowledge/junie-tasks/taskset-1/p0/DEMO-02-Demo-Reset-UI.md", + "demo-02-demo-reset-ui": "doc/knowledge/junie-tasks/taskset-1/p0/DEMO-02-Demo-Reset-UI.md", + "SEC-01-Disable-H2-Console-Exposure-in-Demo-Prod": "doc/knowledge/junie-tasks/taskset-1/p0/SEC-01-Disable-H2-Console-Exposure-in-Demo-Prod.md", + "sec-01-disable-h2-console-exposure-in-demo-prod": "doc/knowledge/junie-tasks/taskset-1/p0/SEC-01-Disable-H2-Console-Exposure-in-Demo-Prod.md", + "CI-01-Add-CI-Pipeline-Build-Test": "doc/knowledge/junie-tasks/taskset-1/p1/CI-01-Add-CI-Pipeline-Build-Test.md", + "ci-01-add-ci-pipeline-build-test": "doc/knowledge/junie-tasks/taskset-1/p1/CI-01-Add-CI-Pipeline-Build-Test.md", + "CI-02-Publish-Playwright-Artifacts": "doc/knowledge/junie-tasks/taskset-1/p1/CI-02-Publish-Playwright-Artifacts.md", + "ci-02-publish-playwright-artifacts": "doc/knowledge/junie-tasks/taskset-1/p1/CI-02-Publish-Playwright-Artifacts.md", + "PERF-01-Static-Asset-Caching": "doc/knowledge/junie-tasks/taskset-1/p1/PERF-01-Static-Asset-Caching.md", + "perf-01-static-asset-caching": "doc/knowledge/junie-tasks/taskset-1/p1/PERF-01-Static-Asset-Caching.md", + "UX-01-Mobile-UX-Guardrails-360px": "doc/knowledge/junie-tasks/taskset-1/p1/UX-01-Mobile-UX-Guardrails-360px.md", + "ux-01-mobile-ux-guardrails-360px": "doc/knowledge/junie-tasks/taskset-1/p1/UX-01-Mobile-UX-Guardrails-360px.md", + "UX-02-Screenshot-Baseline-for-Demo-Screens": "doc/knowledge/junie-tasks/taskset-1/p1/UX-02-Screenshot-Baseline-for-Demo-Screens.md", + "ux-02-screenshot-baseline-for-demo-screens": "doc/knowledge/junie-tasks/taskset-1/p1/UX-02-Screenshot-Baseline-for-Demo-Screens.md", + "Execution-Rules-Definition-of-Done": "doc/knowledge/junie-tasks/taskset-1/p2/Execution-Rules-Definition-of-Done.md", + "execution-rules-definition-of-done": "doc/knowledge/junie-tasks/taskset-1/p2/Execution-Rules-Definition-of-Done.md", + "OBS-01-Health-Readiness-Endpoints": "doc/knowledge/junie-tasks/taskset-1/p2/OBS-01-Health-Readiness-Endpoints.md", + "obs-01-health-readiness-endpoints": "doc/knowledge/junie-tasks/taskset-1/p2/OBS-01-Health-Readiness-Endpoints.md", + "OBS-02-Correlation-IDs-End-to-End": "doc/knowledge/junie-tasks/taskset-1/p2/OBS-02-Correlation-IDs-End-to-End.md", + "obs-02-correlation-ids-end-to-end": "doc/knowledge/junie-tasks/taskset-1/p2/OBS-02-Correlation-IDs-End-to-End.md", + "OBS-03-Support-System-Info-Page": "doc/knowledge/junie-tasks/taskset-1/p2/OBS-03-Support-System-Info-Page.md", + "obs-03-support-system-info-page": "doc/knowledge/junie-tasks/taskset-1/p2/OBS-03-Support-System-Info-Page.md", + "rebrand_goodone_README": "doc/knowledge/junie-tasks/taskset-10/rebrand_goodone_README.md", + "rebrand_goodone_readme": "doc/knowledge/junie-tasks/taskset-10/rebrand_goodone_README.md", + "SEC-41-CloudWatch-Cost-Reduction": "doc/knowledge/junie-tasks/taskset-10/SEC-41-CloudWatch-Cost-Reduction.md", + "sec-41-cloudwatch-cost-reduction": "doc/knowledge/junie-tasks/taskset-10/SEC-41-CloudWatch-Cost-Reduction.md", + "Acceptance-criteria-manual": "doc/knowledge/junie-tasks/taskset-3/Acceptance-criteria-manual.md", + "acceptance-criteria-manual": "doc/knowledge/junie-tasks/taskset-3/Acceptance-criteria-manual.md", + "CI-DEDUP-01-Remove-duplicate-guardrail-execution-across-workflows": "doc/knowledge/junie-tasks/taskset-3/CI-DEDUP-01-Remove-duplicate-guardrail-execution-across-workflows.md", + "ci-dedup-01-remove-duplicate-guardrail-execution-across-workflows": "doc/knowledge/junie-tasks/taskset-3/CI-DEDUP-01-Remove-duplicate-guardrail-execution-across-workflows.md", + "CI-FIX-01-Fix-GitHub-Action-Failures": "doc/knowledge/junie-tasks/taskset-3/CI-FIX-01-Fix-GitHub-Action-Failures.md", + "ci-fix-01-fix-github-action-failures": "doc/knowledge/junie-tasks/taskset-3/CI-FIX-01-Fix-GitHub-Action-Failures.md", + "CI-FIX-01-Fix-SonarCloud-job-path-bug-standardize-npm-install": "doc/knowledge/junie-tasks/taskset-3/CI-FIX-01-Fix-SonarCloud-job-path-bug-standardize-npm-install.md", + "ci-fix-01-fix-sonarcloud-job-path-bug-standardize-npm-install": "doc/knowledge/junie-tasks/taskset-3/CI-FIX-01-Fix-SonarCloud-job-path-bug-standardize-npm-install.md", + "CI-FLAKE-01-Playwright-retries-trace-video-on-first-retry-CI-only": "doc/knowledge/junie-tasks/taskset-3/CI-FLAKE-01-Playwright-retries-trace-video-on-first-retry-CI-only.md", + "ci-flake-01-playwright-retries-trace-video-on-first-retry-ci-only": "doc/knowledge/junie-tasks/taskset-3/CI-FLAKE-01-Playwright-retries-trace-video-on-first-retry-CI-only.md", + "CI-PERF-01-Add-concurrency-cancel-in-progress-for-PRs": "doc/knowledge/junie-tasks/taskset-3/CI-PERF-01-Add-concurrency-cancel-in-progress-for-PRs.md", + "ci-perf-01-add-concurrency-cancel-in-progress-for-prs": "doc/knowledge/junie-tasks/taskset-3/CI-PERF-01-Add-concurrency-cancel-in-progress-for-PRs.md", + "CI-PERF-02-Use-npm-cache-properly-avoid-caching-node-modules": "doc/knowledge/junie-tasks/taskset-3/CI-PERF-02-Use-npm-cache-properly-avoid-caching-node-modules.md", + "ci-perf-02-use-npm-cache-properly-avoid-caching-node-modules": "doc/knowledge/junie-tasks/taskset-3/CI-PERF-02-Use-npm-cache-properly-avoid-caching-node-modules.md", + "CI-PIN-01-Pin-third-party-GitHub-Actions-versions-avoid-master": "doc/knowledge/junie-tasks/taskset-3/CI-PIN-01-Pin-third-party-GitHub-Actions-versions-avoid-master.md", + "ci-pin-01-pin-third-party-github-actions-versions-avoid-master": "doc/knowledge/junie-tasks/taskset-3/CI-PIN-01-Pin-third-party-GitHub-Actions-versions-avoid-master.md", + "E2E-CI-01-Start-backend-frontend-in-CI-and-run-Playwright-E2E-suite": "doc/knowledge/junie-tasks/taskset-3/E2E-CI-01-Start-backend-frontend-in-CI-and-run-Playwright-E2E-suite.md", + "e2e-ci-01-start-backend-frontend-in-ci-and-run-playwright-e2e-suite": "doc/knowledge/junie-tasks/taskset-3/E2E-CI-01-Start-backend-frontend-in-CI-and-run-Playwright-E2E-suite.md", + "iteration2": "doc/knowledge/junie-tasks/taskset-3/iteration2.md", + "QA-COV-01-Make-coverage-generation-explicit-enforced": "doc/knowledge/junie-tasks/taskset-3/QA-COV-01-Make-coverage-generation-explicit-enforced.md", + "qa-cov-01-make-coverage-generation-explicit-enforced": "doc/knowledge/junie-tasks/taskset-3/QA-COV-01-Make-coverage-generation-explicit-enforced.md", + "QA-PATHS-01-Add-path-filters-to-heavy-jobs": "doc/knowledge/junie-tasks/taskset-3/QA-PATHS-01-Add-path-filters-to-heavy-jobs.md", + "qa-paths-01-add-path-filters-to-heavy-jobs": "doc/knowledge/junie-tasks/taskset-3/QA-PATHS-01-Add-path-filters-to-heavy-jobs.md", + "REL-01-Add-build-metadata-to-artifacts-and-UI": "doc/knowledge/junie-tasks/taskset-3/REL-01-Add-build-metadata-to-artifacts-and-UI.md", + "rel-01-add-build-metadata-to-artifacts-and-ui": "doc/knowledge/junie-tasks/taskset-3/REL-01-Add-build-metadata-to-artifacts-and-UI.md", + "SEC-SARIF-01-Upload-Snyk-SARIF-to-GitHub-Code-Scanning": "doc/knowledge/junie-tasks/taskset-3/SEC-SARIF-01-Upload-Snyk-SARIF-to-GitHub-Code-Scanning.md", + "sec-sarif-01-upload-snyk-sarif-to-github-code-scanning": "doc/knowledge/junie-tasks/taskset-3/SEC-SARIF-01-Upload-Snyk-SARIF-to-GitHub-Code-Scanning.md", + "SEC-SARIF-02-Upload-Trivy-results-as-SARIF-optional-but-recommended": "doc/knowledge/junie-tasks/taskset-3/SEC-SARIF-02-Upload-Trivy-results-as-SARIF-optional-but-recommended.md", + "sec-sarif-02-upload-trivy-results-as-sarif-optional-but-recommended": "doc/knowledge/junie-tasks/taskset-3/SEC-SARIF-02-Upload-Trivy-results-as-SARIF-optional-but-recommended.md", + "graphana-config": "doc/knowledge/junie-tasks/taskset-4/graphana-config.md", + "graphana-debug": "doc/knowledge/junie-tasks/taskset-4/graphana-debug.md", + "OBS-ERR-01-Frontend-Error-Boundary-Support-Context": "doc/knowledge/junie-tasks/taskset-4/OBS-ERR-01-Frontend-Error-Boundary-Support-Context.md", + "obs-err-01-frontend-error-boundary-support-context": "doc/knowledge/junie-tasks/taskset-4/OBS-ERR-01-Frontend-Error-Boundary-Support-Context.md", + "OBS-LOG-01-Structured-Logging-Standard": "doc/knowledge/junie-tasks/taskset-4/OBS-LOG-01-Structured-Logging-Standard.md", + "obs-log-01-structured-logging-standard": "doc/knowledge/junie-tasks/taskset-4/OBS-LOG-01-Structured-Logging-Standard.md", + "OBS-MET-01-Basic-Metrics-Exposure": "doc/knowledge/junie-tasks/taskset-4/OBS-MET-01-Basic-Metrics-Exposure.md", + "obs-met-01-basic-metrics-exposure": "doc/knowledge/junie-tasks/taskset-4/OBS-MET-01-Basic-Metrics-Exposure.md", + "OBS-MET-02-Metrics-ON-AWS": "doc/knowledge/junie-tasks/taskset-4/OBS-MET-02-Metrics-ON-AWS.md", + "obs-met-02-metrics-on-aws": "doc/knowledge/junie-tasks/taskset-4/OBS-MET-02-Metrics-ON-AWS.md", + "OBS-MET-03-Metrics-ON-AWS": "doc/knowledge/junie-tasks/taskset-4/OBS-MET-03-Metrics-ON-AWS.md", + "obs-met-03-metrics-on-aws": "doc/knowledge/junie-tasks/taskset-4/OBS-MET-03-Metrics-ON-AWS.md", + "OBS-TRACE-01-Correlation-ID-Propagation": "doc/knowledge/junie-tasks/taskset-4/OBS-TRACE-01-Correlation-ID-Propagation.md", + "obs-trace-01-correlation-id-propagation": "doc/knowledge/junie-tasks/taskset-4/OBS-TRACE-01-Correlation-ID-Propagation.md", + "OPS-RUN-01-Operations-Runbook": "doc/knowledge/junie-tasks/taskset-4/OPS-RUN-01-Operations-Runbook.md", + "ops-run-01-operations-runbook": "doc/knowledge/junie-tasks/taskset-4/OPS-RUN-01-Operations-Runbook.md", + "API-CONTRACT-01-OpenAPI-Contract-Tests": "doc/knowledge/junie-tasks/taskset-5/API-CONTRACT-01-OpenAPI-Contract-Tests.md", + "api-contract-01-openapi-contract-tests": "doc/knowledge/junie-tasks/taskset-5/API-CONTRACT-01-OpenAPI-Contract-Tests.md", + "DB-MIG-01-Database-Migration-Tests": "doc/knowledge/junie-tasks/taskset-5/DB-MIG-01-Database-Migration-Tests.md", + "db-mig-01-database-migration-tests": "doc/knowledge/junie-tasks/taskset-5/DB-MIG-01-Database-Migration-Tests.md", + "E2E-GOLD-01-Expand-Golden-Path-E2E-Tests": "doc/knowledge/junie-tasks/taskset-5/E2E-GOLD-01-Expand-Golden-Path-E2E-Tests.md", + "e2e-gold-01-expand-golden-path-e2e-tests": "doc/knowledge/junie-tasks/taskset-5/E2E-GOLD-01-Expand-Golden-Path-E2E-Tests.md", + "E2E-NEG-01-Negative-Path-E2E-Tests": "doc/knowledge/junie-tasks/taskset-5/E2E-NEG-01-Negative-Path-E2E-Tests.md", + "e2e-neg-01-negative-path-e2e-tests": "doc/knowledge/junie-tasks/taskset-5/E2E-NEG-01-Negative-Path-E2E-Tests.md", + "VIS-REG-01-Visual-Regression-for-Demo-Screens": "doc/knowledge/junie-tasks/taskset-5/VIS-REG-01-Visual-Regression-for-Demo-Screens.md", + "vis-reg-01-visual-regression-for-demo-screens": "doc/knowledge/junie-tasks/taskset-5/VIS-REG-01-Visual-Regression-for-Demo-Screens.md", + "SEC-AUD-01-Audit-Events": "doc/knowledge/junie-tasks/taskset-6/SEC-AUD-01-Audit-Events.md", + "sec-aud-01-audit-events": "doc/knowledge/junie-tasks/taskset-6/SEC-AUD-01-Audit-Events.md", + "SEC-HEAD-02-CSP-Tightening": "doc/knowledge/junie-tasks/taskset-6/SEC-HEAD-02-CSP-Tightening.md", + "sec-head-02-csp-tightening": "doc/knowledge/junie-tasks/taskset-6/SEC-HEAD-02-CSP-Tightening.md", + "SEC-RATE-01-Rate-Limiting-slide": "doc/knowledge/junie-tasks/taskset-6/SEC-RATE-01-Rate-Limiting-slide.md", + "sec-rate-01-rate-limiting-slide": "doc/knowledge/junie-tasks/taskset-6/SEC-RATE-01-Rate-Limiting-slide.md", + "SEC-RATE-01-Rate-Limiting": "doc/knowledge/junie-tasks/taskset-6/SEC-RATE-01-Rate-Limiting.md", + "sec-rate-01-rate-limiting": "doc/knowledge/junie-tasks/taskset-6/SEC-RATE-01-Rate-Limiting.md", + "SEC-SAST-01-Actionable-SAST-Gates": "doc/knowledge/junie-tasks/taskset-6/SEC-SAST-01-Actionable-SAST-Gates.md", + "sec-sast-01-actionable-sast-gates": "doc/knowledge/junie-tasks/taskset-6/SEC-SAST-01-Actionable-SAST-Gates.md", + "SEC-TM-01-Lightweight-Threat-Model": "doc/knowledge/junie-tasks/taskset-6/SEC-TM-01-Lightweight-Threat-Model.md", + "sec-tm-01-lightweight-threat-model": "doc/knowledge/junie-tasks/taskset-6/SEC-TM-01-Lightweight-Threat-Model.md", + "DEPLOY-PIPE-01-Optional-CD-to-Demo-Environment": "doc/knowledge/junie-tasks/taskset-7/DEPLOY-PIPE-01-Optional-CD-to-Demo-Environment.md", + "deploy-pipe-01-optional-cd-to-demo-environment": "doc/knowledge/junie-tasks/taskset-7/DEPLOY-PIPE-01-Optional-CD-to-Demo-Environment.md", + "DOC-SNAP-01-Documentation-Snapshot-per-Release": "doc/knowledge/junie-tasks/taskset-7/DOC-SNAP-01-Documentation-Snapshot-per-Release.md", + "doc-snap-01-documentation-snapshot-per-release": "doc/knowledge/junie-tasks/taskset-7/DOC-SNAP-01-Documentation-Snapshot-per-Release.md", + "ENV-SYNC-01-Configuration-Drift-Protection": "doc/knowledge/junie-tasks/taskset-7/ENV-SYNC-01-Configuration-Drift-Protection.md", + "env-sync-01-configuration-drift-protection": "doc/knowledge/junie-tasks/taskset-7/ENV-SYNC-01-Configuration-Drift-Protection.md", + "REL-NOTES-01-Automated-Release-Notes": "doc/knowledge/junie-tasks/taskset-7/REL-NOTES-01-Automated-Release-Notes.md", + "rel-notes-01-automated-release-notes": "doc/knowledge/junie-tasks/taskset-7/REL-NOTES-01-Automated-Release-Notes.md", + "REL-SEM-01-Semantic-Versioning": "doc/knowledge/junie-tasks/taskset-7/REL-SEM-01-Semantic-Versioning.md", + "rel-sem-01-semantic-versioning": "doc/knowledge/junie-tasks/taskset-7/REL-SEM-01-Semantic-Versioning.md", + "SONAR-V7-02-Sustainable-Fix-for-Sonar-Issues": "doc/knowledge/junie-tasks/taskset-7/SONAR-V7-02-Sustainable-Fix-for-Sonar-Issues.md", + "sonar-v7-02-sustainable-fix-for-sonar-issues": "doc/knowledge/junie-tasks/taskset-7/SONAR-V7-02-Sustainable-Fix-for-Sonar-Issues.md", + "AUTH-DEPLOY-01-Fix-Fargate-auth-inconsistency": "doc/knowledge/junie-tasks/taskset-8/AUTH-DEPLOY-01-Fix-Fargate-auth-inconsistency.md", + "auth-deploy-01-fix-fargate-auth-inconsistency": "doc/knowledge/junie-tasks/taskset-8/AUTH-DEPLOY-01-Fix-Fargate-auth-inconsistency.md", + "E2E-01-Add-navigation-regression-suite": "doc/knowledge/junie-tasks/taskset-8/E2E-01-Add-navigation-regression-suite.md", + "e2e-01-add-navigation-regression-suite": "doc/knowledge/junie-tasks/taskset-8/E2E-01-Add-navigation-regression-suite.md", + "E2E-02-Add-no-console-errors-guardrail": "doc/knowledge/junie-tasks/taskset-8/E2E-02-Add-no-console-errors-guardrail.md", + "e2e-02-add-no-console-errors-guardrail": "doc/knowledge/junie-tasks/taskset-8/E2E-02-Add-no-console-errors-guardrail.md", + "E2E-03-Add-Auth-state-consistency-tests": "doc/knowledge/junie-tasks/taskset-8/E2E-03-Add-Auth-state-consistency-tests.md", + "e2e-03-add-auth-state-consistency-tests": "doc/knowledge/junie-tasks/taskset-8/E2E-03-Add-Auth-state-consistency-tests.md", + "LEGAL-01-Fix-exception-on-closing-Terms-Legal-dialog": "doc/knowledge/junie-tasks/taskset-8/LEGAL-01-Fix-exception-on-closing-Terms-Legal-dialog.md", + "legal-01-fix-exception-on-closing-terms-legal-dialog": "doc/knowledge/junie-tasks/taskset-8/LEGAL-01-Fix-exception-on-closing-Terms-Legal-dialog.md", + "NAV-01-Fix-hamburger-menu-on-mobile": "doc/knowledge/junie-tasks/taskset-8/NAV-01-Fix-hamburger-menu-on-mobile.md", + "nav-01-fix-hamburger-menu-on-mobile": "doc/knowledge/junie-tasks/taskset-8/NAV-01-Fix-hamburger-menu-on-mobile.md", + "NAV-02-Fix-tablet-collapse-expand": "doc/knowledge/junie-tasks/taskset-8/NAV-02-Fix-tablet-collapse-expand.md", + "nav-02-fix-tablet-collapse-expand": "doc/knowledge/junie-tasks/taskset-8/NAV-02-Fix-tablet-collapse-expand.md", + "UX-NAV-01-Improve-visible-affordance-for-nav-state": "doc/knowledge/junie-tasks/taskset-8/UX-NAV-01-Improve-visible-affordance-for-nav-state.md", + "ux-nav-01-improve-visible-affordance-for-nav-state": "doc/knowledge/junie-tasks/taskset-8/UX-NAV-01-Improve-visible-affordance-for-nav-state.md", + "UX-UA-01-Fix-mobile-action-buttons": "doc/knowledge/junie-tasks/taskset-8/UX-UA-01-Fix-mobile-action-buttons.md", + "ux-ua-01-fix-mobile-action-buttons": "doc/knowledge/junie-tasks/taskset-8/UX-UA-01-Fix-mobile-action-buttons.md", + "taskset-ux-19-25-execution-plan": "doc/knowledge/junie-tasks/taskset-9/p3/taskset-ux-19-25-execution-plan.md", + "taskset-ux-19-25-roadmap": "doc/knowledge/junie-tasks/taskset-9/p3/taskset-ux-19-25-roadmap.md", + "taskset-ux-26-31-execution-plan": "doc/knowledge/junie-tasks/taskset-9/p3/taskset-ux-26-31-execution-plan.md", + "taskset-ux-26-31-index": "doc/knowledge/junie-tasks/taskset-9/p3/taskset-ux-26-31-index.md", + "taskset-ux-26-31-roadmap": "doc/knowledge/junie-tasks/taskset-9/p3/taskset-ux-26-31-roadmap.md", + "junie-task-enforce-acceptance-checkbox-all-tasksets": "doc/knowledge/junie-tasks/taskset-9/p4/junie-task-enforce-acceptance-checkbox-all-tasksets.md", + "junie-task-normalize-acceptance-checkbox-taskset-9": "doc/knowledge/junie-tasks/taskset-9/p4/junie-task-normalize-acceptance-checkbox-taskset-9.md", + "junie-task-template-generator-with-acceptance-confirmation": "doc/knowledge/junie-tasks/taskset-9/p4/junie-task-template-generator-with-acceptance-confirmation.md", + "ai-golden-snapshots": "doc/knowledge/reports/ai-golden-snapshots.md", + "coverage-metrics-definitions": "doc/knowledge/reports/coverage-metrics-definitions.md", + "demo-scenario-baseline": "doc/knowledge/reports/demo-scenario-baseline.md", + "ollama-latency-benchmarks": "doc/knowledge/reports/ollama-latency-benchmarks.md", + "guardrails-ci-guide": "doc/knowledge/task-governance/guardrails-ci-guide.md", + "sprint-2.0-task-id-uniqueness-report": "doc/knowledge/task-governance/sprint-2.0-task-id-uniqueness-report.md", + "RUNBOOK": "doc/operations/RUNBOOK.md", + "runbook": "doc/operations/RUNBOOK.md", + "architecture-overview-snippet": "doc/readme-assets/architecture-overview-snippet.md", + "feature-cards-section": "doc/readme-assets/feature-cards-section.md", + "feature-overview-snippet": "doc/readme-assets/feature-overview-snippet.md", + "github-badges-snippet": "doc/readme-assets/github-badges-snippet.md", + "intelligence-map-snippet": "doc/readme-assets/intelligence-map-snippet.md", + "readme-hero-snippet": "doc/readme-assets/readme-hero-snippet.md", + "release-hardening-deferred-issues": "doc/release/release-hardening-deferred-issues.md", + "static-analysis-conflict-matrix": "doc/release/static-analysis-conflict-matrix.md", + "2026-02-26-Swagger-401-Unauthorized-Fix": "doc/troubleshooting/2026-02-26-Swagger-401-Unauthorized-Fix.md", + "2026-02-26-swagger-401-unauthorized-fix": "doc/troubleshooting/2026-02-26-Swagger-401-Unauthorized-Fix.md", + "faq_de": "doc/user-guide/faq_de.md", + "release-notes": "doc/user-guide/release-notes.md", + "user-guide_de": "doc/user-guide/user-guide_de.md", + "forgot-password-ui-guide": "doc/user-guide/workflows/forgot-password-ui-guide.md", + "navigation-guide": "doc/user-guide/workflows/navigation-guide.md", + "registration-ui-guide": "doc/user-guide/workflows/registration-ui-guide.md", + "HELP": "backend/HELP.md", + "help": "backend/HELP.md", + "coverage": "backend/doc/knowledge/reports/coverage.md", + "no-reindex": "backend/src/test/resources/test-docs/no-reindex.md", + "test-uploaded-no-csrf": "backend/src/test/resources/test-docs/test-uploaded-no-csrf.md", + "test": "backend/src/test/resources/test-docs/test.md", + "conflicting-adr-1": "frontend/e2e/data/ai-stability/conflicting-adr-1.md", + "conflicting-adr-2": "frontend/e2e/data/ai-stability/conflicting-adr-2.md", + "duplicate-adr-v2": "frontend/e2e/data/ai-stability/duplicate-adr-v2.md", + "duplicate-adr": "frontend/e2e/data/ai-stability/duplicate-adr.md", + "missing-ref": "frontend/e2e/data/ai-stability/missing-ref.md", + "CHANGELOG": "frontend/node/node_modules/corepack/CHANGELOG.md", + "changelog": "frontend/node/node_modules/corepack/CHANGELOG.md", + "LICENSE": "frontend/node/node_modules/corepack/LICENSE.md", + "license": "frontend/node/node_modules/corepack/LICENSE.md", + "npm-access": "frontend/node/node_modules/npm/docs/content/commands/npm-access.md", + "npm-adduser": "frontend/node/node_modules/npm/docs/content/commands/npm-adduser.md", + "npm-audit": "frontend/node/node_modules/npm/docs/content/commands/npm-audit.md", + "npm-bugs": "frontend/node/node_modules/npm/docs/content/commands/npm-bugs.md", + "npm-cache": "frontend/node/node_modules/npm/docs/content/commands/npm-cache.md", + "npm-ci": "frontend/node/node_modules/npm/docs/content/commands/npm-ci.md", + "npm-completion": "frontend/node/node_modules/npm/docs/content/commands/npm-completion.md", + "npm-config": "frontend/node/node_modules/npm/docs/content/commands/npm-config.md", + "npm-dedupe": "frontend/node/node_modules/npm/docs/content/commands/npm-dedupe.md", + "npm-deprecate": "frontend/node/node_modules/npm/docs/content/commands/npm-deprecate.md", + "npm-diff": "frontend/node/node_modules/npm/docs/content/commands/npm-diff.md", + "npm-dist-tag": "frontend/node/node_modules/npm/docs/content/commands/npm-dist-tag.md", + "npm-docs": "frontend/node/node_modules/npm/docs/content/commands/npm-docs.md", + "npm-doctor": "frontend/node/node_modules/npm/docs/content/commands/npm-doctor.md", + "npm-edit": "frontend/node/node_modules/npm/docs/content/commands/npm-edit.md", + "npm-exec": "frontend/node/node_modules/npm/docs/content/commands/npm-exec.md", + "npm-explain": "frontend/node/node_modules/npm/docs/content/commands/npm-explain.md", + "npm-explore": "frontend/node/node_modules/npm/docs/content/commands/npm-explore.md", + "npm-find-dupes": "frontend/node/node_modules/npm/docs/content/commands/npm-find-dupes.md", + "npm-fund": "frontend/node/node_modules/npm/docs/content/commands/npm-fund.md", + "npm-help-search": "frontend/node/node_modules/npm/docs/content/commands/npm-help-search.md", + "npm-help": "frontend/node/node_modules/npm/docs/content/commands/npm-help.md", + "npm-hook": "frontend/node/node_modules/npm/docs/content/commands/npm-hook.md", + "npm-init": "frontend/node/node_modules/npm/docs/content/commands/npm-init.md", + "npm-install-ci-test": "frontend/node/node_modules/npm/docs/content/commands/npm-install-ci-test.md", + "npm-install-test": "frontend/node/node_modules/npm/docs/content/commands/npm-install-test.md", + "npm-install": "frontend/node/node_modules/npm/docs/content/commands/npm-install.md", + "npm-link": "frontend/node/node_modules/npm/docs/content/commands/npm-link.md", + "npm-login": "frontend/node/node_modules/npm/docs/content/commands/npm-login.md", + "npm-logout": "frontend/node/node_modules/npm/docs/content/commands/npm-logout.md", + "npm-ls": "frontend/node/node_modules/npm/docs/content/commands/npm-ls.md", + "npm-org": "frontend/node/node_modules/npm/docs/content/commands/npm-org.md", + "npm-outdated": "frontend/node/node_modules/npm/docs/content/commands/npm-outdated.md", + "npm-owner": "frontend/node/node_modules/npm/docs/content/commands/npm-owner.md", + "npm-pack": "frontend/node/node_modules/npm/docs/content/commands/npm-pack.md", + "npm-ping": "frontend/node/node_modules/npm/docs/content/commands/npm-ping.md", + "npm-pkg": "frontend/node/node_modules/npm/docs/content/commands/npm-pkg.md", + "npm-prefix": "frontend/node/node_modules/npm/docs/content/commands/npm-prefix.md", + "npm-profile": "frontend/node/node_modules/npm/docs/content/commands/npm-profile.md", + "npm-prune": "frontend/node/node_modules/npm/docs/content/commands/npm-prune.md", + "npm-publish": "frontend/node/node_modules/npm/docs/content/commands/npm-publish.md", + "npm-query": "frontend/node/node_modules/npm/docs/content/commands/npm-query.md", + "npm-rebuild": "frontend/node/node_modules/npm/docs/content/commands/npm-rebuild.md", + "npm-repo": "frontend/node/node_modules/npm/docs/content/commands/npm-repo.md", + "npm-restart": "frontend/node/node_modules/npm/docs/content/commands/npm-restart.md", + "npm-root": "frontend/node/node_modules/npm/docs/content/commands/npm-root.md", + "npm-run-script": "frontend/node/node_modules/npm/docs/content/commands/npm-run-script.md", + "npm-sbom": "frontend/node/node_modules/npm/docs/content/commands/npm-sbom.md", + "npm-search": "frontend/node/node_modules/npm/docs/content/commands/npm-search.md", + "npm-shrinkwrap": "frontend/node/node_modules/npm/docs/content/commands/npm-shrinkwrap.md", + "npm-star": "frontend/node/node_modules/npm/docs/content/commands/npm-star.md", + "npm-stars": "frontend/node/node_modules/npm/docs/content/commands/npm-stars.md", + "npm-start": "frontend/node/node_modules/npm/docs/content/commands/npm-start.md", + "npm-stop": "frontend/node/node_modules/npm/docs/content/commands/npm-stop.md", + "npm-team": "frontend/node/node_modules/npm/docs/content/commands/npm-team.md", + "npm-test": "frontend/node/node_modules/npm/docs/content/commands/npm-test.md", + "npm-token": "frontend/node/node_modules/npm/docs/content/commands/npm-token.md", + "npm-uninstall": "frontend/node/node_modules/npm/docs/content/commands/npm-uninstall.md", + "npm-unpublish": "frontend/node/node_modules/npm/docs/content/commands/npm-unpublish.md", + "npm-unstar": "frontend/node/node_modules/npm/docs/content/commands/npm-unstar.md", + "npm-update": "frontend/node/node_modules/npm/docs/content/commands/npm-update.md", + "npm-version": "frontend/node/node_modules/npm/docs/content/commands/npm-version.md", + "npm-view": "frontend/node/node_modules/npm/docs/content/commands/npm-view.md", + "npm-whoami": "frontend/node/node_modules/npm/docs/content/commands/npm-whoami.md", + "npm": "frontend/node/node_modules/npm/docs/content/commands/npm.md", + "npx": "frontend/node/node_modules/npm/docs/content/commands/npx.md", + "folders": "frontend/node/node_modules/npm/docs/content/configuring-npm/folders.md", + "install": "frontend/node/node_modules/npm/docs/content/configuring-npm/install.md", + "npm-shrinkwrap-json": "frontend/node/node_modules/npm/docs/content/configuring-npm/npm-shrinkwrap-json.md", + "npmrc": "frontend/node/node_modules/npm/docs/content/configuring-npm/npmrc.md", + "package-json": "frontend/node/node_modules/npm/docs/content/configuring-npm/package-json.md", + "package-lock-json": "frontend/node/node_modules/npm/docs/content/configuring-npm/package-lock-json.md", + "config": "frontend/node/node_modules/npm/docs/content/using-npm/config.md", + "dependency-selectors": "frontend/node/node_modules/npm/docs/content/using-npm/dependency-selectors.md", + "developers": "frontend/node/node_modules/npm/docs/content/using-npm/developers.md", + "logging": "frontend/node/node_modules/npm/docs/content/using-npm/logging.md", + "orgs": "frontend/node/node_modules/npm/docs/content/using-npm/orgs.md", + "package-spec": "frontend/node/node_modules/npm/docs/content/using-npm/package-spec.md", + "registry": "frontend/node/node_modules/npm/docs/content/using-npm/registry.md", + "removal": "frontend/node/node_modules/npm/docs/content/using-npm/removal.md", + "scope": "frontend/node/node_modules/npm/docs/content/using-npm/scope.md", + "scripts": "frontend/node/node_modules/npm/docs/content/using-npm/scripts.md", + "workspaces": "frontend/node/node_modules/npm/docs/content/using-npm/workspaces.md", + "HISTORY": "frontend/node/node_modules/npm/node_modules/make-fetch-happen/node_modules/negotiator/HISTORY.md", + "history": "frontend/node/node_modules/npm/node_modules/make-fetch-happen/node_modules/negotiator/HISTORY.md", + "CODE_OF_CONDUCT": "frontend/node/node_modules/npm/node_modules/node-gyp/CODE_OF_CONDUCT.md", + "code_of_conduct": "frontend/node/node_modules/npm/node_modules/node-gyp/CODE_OF_CONDUCT.md", + "SECURITY": "frontend/node/node_modules/npm/node_modules/node-gyp/SECURITY.md", + "security": "frontend/node/node_modules/npm/node_modules/node-gyp/SECURITY.md", + "GypVsCMake": "frontend/node/node_modules/npm/node_modules/node-gyp/gyp/docs/GypVsCMake.md", + "gypvscmake": "frontend/node/node_modules/npm/node_modules/node-gyp/gyp/docs/GypVsCMake.md", + "Hacking": "frontend/node/node_modules/npm/node_modules/node-gyp/gyp/docs/Hacking.md", + "hacking": "frontend/node/node_modules/npm/node_modules/node-gyp/gyp/docs/Hacking.md", + "InputFormatReference": "frontend/node/node_modules/npm/node_modules/node-gyp/gyp/docs/InputFormatReference.md", + "inputformatreference": "frontend/node/node_modules/npm/node_modules/node-gyp/gyp/docs/InputFormatReference.md", + "LanguageSpecification": "frontend/node/node_modules/npm/node_modules/node-gyp/gyp/docs/LanguageSpecification.md", + "languagespecification": "frontend/node/node_modules/npm/node_modules/node-gyp/gyp/docs/LanguageSpecification.md", + "Testing": "frontend/node/node_modules/npm/node_modules/node-gyp/gyp/docs/Testing.md", + "testing": "frontend/node/node_modules/npm/node_modules/node-gyp/gyp/docs/Testing.md", + "UserDocumentation": "frontend/node/node_modules/npm/node_modules/node-gyp/gyp/docs/UserDocumentation.md", + "userdocumentation": "frontend/node/node_modules/npm/node_modules/node-gyp/gyp/docs/UserDocumentation.md", + "API": "frontend/node/node_modules/npm/node_modules/postcss-selector-parser/API.md", + "api": "frontend/node/node_modules/npm/node_modules/postcss-selector-parser/API.md", + "Porting-Buffer": "frontend/node/node_modules/npm/node_modules/safer-buffer/Porting-Buffer.md", + "porting-buffer": "frontend/node/node_modules/npm/node_modules/safer-buffer/Porting-Buffer.md", + "migratingFromV1": "frontend/node/node_modules/npm/node_modules/socks/docs/migratingFromV1.md", + "migratingfromv1": "frontend/node/node_modules/npm/node_modules/socks/docs/migratingFromV1.md", + "associateExample": "frontend/node/node_modules/npm/node_modules/socks/docs/examples/javascript/associateExample.md", + "associateexample": "frontend/node/node_modules/npm/node_modules/socks/docs/examples/javascript/associateExample.md", + "bindExample": "frontend/node/node_modules/npm/node_modules/socks/docs/examples/javascript/bindExample.md", + "bindexample": "frontend/node/node_modules/npm/node_modules/socks/docs/examples/javascript/bindExample.md", + "connectExample": "frontend/node/node_modules/npm/node_modules/socks/docs/examples/javascript/connectExample.md", + "connectexample": "frontend/node/node_modules/npm/node_modules/socks/docs/examples/javascript/connectExample.md", + "CONTRIBUTORS": "frontend/node/node_modules/npm/node_modules/sprintf-js/CONTRIBUTORS.md", + "contributors": "frontend/node/node_modules/npm/node_modules/sprintf-js/CONTRIBUTORS.md", + "History": "frontend/node/node_modules/npm/node_modules/util-deprecate/History.md", + "long-description": "frontend/node_modules/@angular/cli/src/commands/add/long-description.md", + "ai-tutor": "frontend/node_modules/@angular/cli/src/commands/mcp/resources/ai-tutor.md", + "best-practices": "frontend/node_modules/@angular/cli/src/commands/mcp/resources/best-practices.md", + "Readme": "frontend/node_modules/@leichtgewicht/ip-codec/Readme.md", + "CHANGES": "frontend/node_modules/chrome-trace-event/CHANGES.md", + "changes": "frontend/node_modules/chrome-trace-event/CHANGES.md", + "LICENCE": "frontend/node_modules/decimal.js/LICENCE.md", + "licence": "frontend/node_modules/decimal.js/LICENCE.md", + "GOVERNANCE": "frontend/node_modules/hpack.js/node_modules/readable-stream/GOVERNANCE.md", + "governance": "frontend/node_modules/hpack.js/node_modules/readable-stream/GOVERNANCE.md", + "2015-01-30": "frontend/node_modules/hpack.js/node_modules/readable-stream/doc/wg-meetings/2015-01-30.md", + "DOCUMENTATION": "frontend/node_modules/license-webpack-plugin/DOCUMENTATION.md", + "documentation": "frontend/node_modules/license-webpack-plugin/DOCUMENTATION.md", + "MIGRATION": "frontend/node_modules/license-webpack-plugin/MIGRATION.md", + "migration": "frontend/node_modules/license-webpack-plugin/MIGRATION.md", + "benchmark": "frontend/node_modules/msgpackr/benchmark.md", + "Changelog": "frontend/node_modules/needle/node_modules/iconv-lite/Changelog.md", + "Introduction": "frontend/node_modules/piscina/docs/docs/Introduction.md", + "introduction": "frontend/node_modules/piscina/docs/docs/Introduction.md", + "class": "frontend/node_modules/piscina/docs/docs/api-reference/class.md", + "event": "frontend/node_modules/piscina/docs/docs/api-reference/event.md", + "interface": "frontend/node_modules/piscina/docs/docs/api-reference/interface.md", + "method": "frontend/node_modules/piscina/docs/docs/api-reference/method.md", + "property": "frontend/node_modules/piscina/docs/docs/api-reference/property.md", + "static-property": "frontend/node_modules/piscina/docs/docs/api-reference/static-property.md", + "playwright-test-coverage.prompt": "frontend/node_modules/playwright/lib/agents/playwright-test-coverage.prompt.md", + "playwright-test-generate.prompt": "frontend/node_modules/playwright/lib/agents/playwright-test-generate.prompt.md", + "playwright-test-generator.agent": "frontend/node_modules/playwright/lib/agents/playwright-test-generator.agent.md", + "playwright-test-heal.prompt": "frontend/node_modules/playwright/lib/agents/playwright-test-heal.prompt.md", + "playwright-test-healer.agent": "frontend/node_modules/playwright/lib/agents/playwright-test-healer.agent.md", + "playwright-test-plan.prompt": "frontend/node_modules/playwright/lib/agents/playwright-test-plan.prompt.md", + "playwright-test-planner.agent": "frontend/node_modules/playwright/lib/agents/playwright-test-planner.agent.md", + "THREAT_MODEL": "frontend/node_modules/qs/.github/THREAT_MODEL.md", + "threat_model": "frontend/node_modules/qs/.github/THREAT_MODEL.md", + "AUTHORS": "frontend/node_modules/reflect-metadata/AUTHORS.md", + "authors": "frontend/node_modules/reflect-metadata/AUTHORS.md", + "INCIDENT_RESPONSE_PROCESS": "frontend/node_modules/resolve/.github/INCIDENT_RESPONSE_PROCESS.md", + "incident_response_process": "frontend/node_modules/resolve/.github/INCIDENT_RESPONSE_PROCESS.md", + "advanced-features": "frontend/node_modules/resolve-url-loader/docs/advanced-features.md", + "how-it-works": "frontend/node_modules/resolve-url-loader/docs/how-it-works.md", + "troubleshooting": "frontend/node_modules/resolve-url-loader/docs/troubleshooting.md", + "README_v3": "frontend/node_modules/smart-buffer/docs/README_v3.md", + "readme_v3": "frontend/node_modules/smart-buffer/docs/README_v3.md", + "PATRONS": "frontend/node_modules/terser/PATRONS.md", + "patrons": "frontend/node_modules/terser/PATRONS.md", + "NODE-LICENSE": "frontend/node_modules/ts-node/dist-raw/NODE-LICENSE.md", + "node-license": "frontend/node_modules/ts-node/dist-raw/NODE-LICENSE.md", + "Agent": "frontend/node_modules/undici/docs/docs/api/Agent.md", + "agent": "frontend/node_modules/undici/docs/docs/api/Agent.md", + "api-lifecycle": "frontend/node_modules/undici/docs/docs/api/api-lifecycle.md", + "BalancedPool": "frontend/node_modules/undici/docs/docs/api/BalancedPool.md", + "balancedpool": "frontend/node_modules/undici/docs/docs/api/BalancedPool.md", + "CacheStorage": "frontend/node_modules/undici/docs/docs/api/CacheStorage.md", + "cachestorage": "frontend/node_modules/undici/docs/docs/api/CacheStorage.md", + "CacheStore": "frontend/node_modules/undici/docs/docs/api/CacheStore.md", + "cachestore": "frontend/node_modules/undici/docs/docs/api/CacheStore.md", + "Client": "frontend/node_modules/undici/docs/docs/api/Client.md", + "client": "frontend/node_modules/undici/docs/docs/api/Client.md", + "ClientStats": "frontend/node_modules/undici/docs/docs/api/ClientStats.md", + "clientstats": "frontend/node_modules/undici/docs/docs/api/ClientStats.md", + "Connector": "frontend/node_modules/undici/docs/docs/api/Connector.md", + "connector": "frontend/node_modules/undici/docs/docs/api/Connector.md", + "ContentType": "frontend/node_modules/undici/docs/docs/api/ContentType.md", + "contenttype": "frontend/node_modules/undici/docs/docs/api/ContentType.md", + "Cookies": "frontend/node_modules/undici/docs/docs/api/Cookies.md", + "cookies": "frontend/node_modules/undici/docs/docs/api/Cookies.md", + "Debug": "frontend/node_modules/undici/docs/docs/api/Debug.md", + "debug": "frontend/node_modules/undici/docs/docs/api/Debug.md", + "DiagnosticsChannel": "frontend/node_modules/undici/docs/docs/api/DiagnosticsChannel.md", + "diagnosticschannel": "frontend/node_modules/undici/docs/docs/api/DiagnosticsChannel.md", + "Dispatcher": "frontend/node_modules/undici/docs/docs/api/Dispatcher.md", + "dispatcher": "frontend/node_modules/undici/docs/docs/api/Dispatcher.md", + "EnvHttpProxyAgent": "frontend/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md", + "envhttpproxyagent": "frontend/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md", + "Errors": "frontend/node_modules/undici/docs/docs/api/Errors.md", + "errors": "frontend/node_modules/undici/docs/docs/api/Errors.md", + "EventSource": "frontend/node_modules/undici/docs/docs/api/EventSource.md", + "eventsource": "frontend/node_modules/undici/docs/docs/api/EventSource.md", + "Fetch": "frontend/node_modules/undici/docs/docs/api/Fetch.md", + "fetch": "frontend/node_modules/undici/docs/docs/api/Fetch.md", + "GlobalInstallation": "frontend/node_modules/undici/docs/docs/api/GlobalInstallation.md", + "globalinstallation": "frontend/node_modules/undici/docs/docs/api/GlobalInstallation.md", + "H2CClient": "frontend/node_modules/undici/docs/docs/api/H2CClient.md", + "h2cclient": "frontend/node_modules/undici/docs/docs/api/H2CClient.md", + "MockAgent": "frontend/node_modules/undici/docs/docs/api/MockAgent.md", + "mockagent": "frontend/node_modules/undici/docs/docs/api/MockAgent.md", + "MockCallHistory": "frontend/node_modules/undici/docs/docs/api/MockCallHistory.md", + "mockcallhistory": "frontend/node_modules/undici/docs/docs/api/MockCallHistory.md", + "MockCallHistoryLog": "frontend/node_modules/undici/docs/docs/api/MockCallHistoryLog.md", + "mockcallhistorylog": "frontend/node_modules/undici/docs/docs/api/MockCallHistoryLog.md", + "MockClient": "frontend/node_modules/undici/docs/docs/api/MockClient.md", + "mockclient": "frontend/node_modules/undici/docs/docs/api/MockClient.md", + "MockErrors": "frontend/node_modules/undici/docs/docs/api/MockErrors.md", + "mockerrors": "frontend/node_modules/undici/docs/docs/api/MockErrors.md", + "MockPool": "frontend/node_modules/undici/docs/docs/api/MockPool.md", + "mockpool": "frontend/node_modules/undici/docs/docs/api/MockPool.md", + "Pool": "frontend/node_modules/undici/docs/docs/api/Pool.md", + "pool": "frontend/node_modules/undici/docs/docs/api/Pool.md", + "PoolStats": "frontend/node_modules/undici/docs/docs/api/PoolStats.md", + "poolstats": "frontend/node_modules/undici/docs/docs/api/PoolStats.md", + "ProxyAgent": "frontend/node_modules/undici/docs/docs/api/ProxyAgent.md", + "proxyagent": "frontend/node_modules/undici/docs/docs/api/ProxyAgent.md", + "RedirectHandler": "frontend/node_modules/undici/docs/docs/api/RedirectHandler.md", + "redirecthandler": "frontend/node_modules/undici/docs/docs/api/RedirectHandler.md", + "RetryAgent": "frontend/node_modules/undici/docs/docs/api/RetryAgent.md", + "retryagent": "frontend/node_modules/undici/docs/docs/api/RetryAgent.md", + "RetryHandler": "frontend/node_modules/undici/docs/docs/api/RetryHandler.md", + "retryhandler": "frontend/node_modules/undici/docs/docs/api/RetryHandler.md", + "RoundRobinPool": "frontend/node_modules/undici/docs/docs/api/RoundRobinPool.md", + "roundrobinpool": "frontend/node_modules/undici/docs/docs/api/RoundRobinPool.md", + "SnapshotAgent": "frontend/node_modules/undici/docs/docs/api/SnapshotAgent.md", + "snapshotagent": "frontend/node_modules/undici/docs/docs/api/SnapshotAgent.md", + "Util": "frontend/node_modules/undici/docs/docs/api/Util.md", + "util": "frontend/node_modules/undici/docs/docs/api/Util.md", + "WebSocket": "frontend/node_modules/undici/docs/docs/api/WebSocket.md", + "websocket": "frontend/node_modules/undici/docs/docs/api/WebSocket.md", + "client-certificate": "frontend/node_modules/undici/docs/docs/best-practices/client-certificate.md", + "crawling": "frontend/node_modules/undici/docs/docs/best-practices/crawling.md", + "mocking-request": "frontend/node_modules/undici/docs/docs/best-practices/mocking-request.md", + "proxy": "frontend/node_modules/undici/docs/docs/best-practices/proxy.md", + "writing-tests": "frontend/node_modules/undici/docs/docs/best-practices/writing-tests.md" +} \ No newline at end of file diff --git a/frontend/public/assets/help/help-map-en.json b/frontend/public/assets/help/help-map-en.json new file mode 100644 index 00000000..704125dc --- /dev/null +++ b/frontend/public/assets/help/help-map-en.json @@ -0,0 +1,1439 @@ +{ + "readme": "README.md", + "user-guide": "doc/user-guide/user-guide.md", + "faq": "doc/user-guide/faq.md", + "release-notes": "doc/user-guide/release-notes.md", + "docker-optimization": "doc/infrastructure/Docker-Optimization.md", + "admin-guide": "doc/admin-guide/admin-guide.md", + "android-build": "doc/development/android/android-build.md", + "backend-dev": "doc/development/backend/Backend-Development.md", + "postgres-setup": "doc/development/backend/postgres_setup.md", + "frontend-dev": "doc/development/frontend/Frontend-Development.md", + "deployment": "doc/infrastructure/Deployment.md", + "risk-radar": "doc/features/risk-radar.md", + "navigation": "doc/features/navigation.md", + "index": "doc/features/index.md", + "registration-workflows": "doc/knowledge/architecture/workflows/registration-workflows.md", + "task-workflows": "doc/knowledge/architecture/workflows/task-workflows.md", + "use-cases": "doc/knowledge/architecture/workflows/use-cases.md", + "diagram-tool-comparison": "doc/knowledge/architecture/workflows/diagram-tool-comparison.md", + "developer-onboarding": "doc/knowledge/architecture/developer-onboarding.md", + "README": "README.md", + "CONTRIBUTING": "doc/CONTRIBUTING.md", + "contributing": "doc/CONTRIBUTING.md", + "indexed-files-count": "doc/indexed-files-count.md", + "known-issues": "doc/known-issues.md", + "operations-guide": "doc/operations-guide.md", + "operations-guide_de": "doc/operations-guide_de.md", + "README-old": "doc/README-old.md", + "readme-old": "doc/README-old.md", + "README_enhanced": "doc/README_enhanced.md", + "readme_enhanced": "doc/README_enhanced.md", + "ROADMAP": "doc/ROADMAP.md", + "roadmap": "doc/ROADMAP.md", + "admin-guide_de": "doc/admin-guide/admin-guide_de.md", + "ollama-docker-performance": "doc/ai/ollama-docker-performance.md", + "ollama-setup": "doc/ai/ollama-setup.md", + "jackson-runtime-conflict-analysis": "doc/analysis/jackson-runtime-conflict-analysis.md", + "fargate-deployment": "doc/deployment/fargate-deployment.md", + "h2-lock-fargate": "doc/deployment/h2-lock-fargate.md", + "aws-technical-reference": "doc/development/aws-technical-reference.md", + "adr-ai-mode-of-use": "doc/development/ai-use/adr-ai-mode-of-use.md", + "ai-mode-comparison-table": "doc/development/ai-use/ai-mode-comparison-table.md", + "ai-mode-developer": "doc/development/ai-use/ai-mode-developer.md", + "ai-mode-slides": "doc/development/ai-use/ai-mode-slides.md", + "how-we-use-ai": "doc/development/ai-use/how-we-use-ai.md", + "dark-mode-chrome": "doc/development/analysis/dark-mode-chrome.md", + "lighthouse-dark-mode-guide": "doc/development/analysis/lighthouse-dark-mode-guide.md", + "lighthouse-economic-feasibility": "doc/development/analysis/lighthouse-economic-feasibility.md", + "web-auditing-alternatives": "doc/development/analysis/web-auditing-alternatives.md", + "Android-Development": "doc/development/android/Android-Development.md", + "android-development": "doc/development/android/Android-Development.md", + "android-studio-instructions": "doc/development/android/android-studio-instructions.md", + "Backend-Development": "doc/development/backend/Backend-Development.md", + "backend-development": "doc/development/backend/Backend-Development.md", + "backend-log-location": "doc/development/backend/backend-log-location.md", + "postgres_setup": "doc/development/backend/postgres_setup.md", + "Development-Standards": "doc/development/common/Development-Standards.md", + "development-standards": "doc/development/common/Development-Standards.md", + "mcp-analysis": "doc/development/common/mcp-analysis.md", + "mcp-architecture": "doc/development/common/mcp-architecture.md", + "mcp-server": "doc/development/common/mcp-server.md", + "sonar-console-stall": "doc/development/devops/sonar-console-stall.md", + "sonar-integration": "doc/development/devops/sonar-integration.md", + "Frontend-Development": "doc/development/frontend/Frontend-Development.md", + "frontend-development": "doc/development/frontend/Frontend-Development.md", + "playwright": "doc/development/frontend/playwright.md", + "ui-primitives": "doc/development/frontend/ui-primitives.md", + "Updating-Documentation-Screenshots": "doc/development/frontend/Updating-Documentation-Screenshots.md", + "updating-documentation-screenshots": "doc/development/frontend/Updating-Documentation-Screenshots.md", + "aws-waf-costs": "doc/development/security/aws-waf-costs.md", + "csrf-hardening-drawback": "doc/development/security/csrf-hardening-drawback.md", + "lightweight-threat-model": "doc/development/security/lightweight-threat-model.md", + "s3-gateway-endpoint-setup": "doc/development/security/s3-gateway-endpoint-setup.md", + "security-assessment": "doc/development/security/security-assessment.md", + "security-roadmap-2": "doc/development/security/security-roadmap-2.md", + "security-roadmap-3": "doc/development/security/security-roadmap-3.md", + "security-roadmap-4": "doc/development/security/security-roadmap-4.md", + "security-roadmap": "doc/development/security/security-roadmap.md", + "snyk-integration-guide": "doc/development/security/snyk-integration-guide.md", + "transmitting-snyk-results": "doc/development/security/transmitting-snyk-results.md", + "reduce-styling-iterations": "doc/development/ux-improvement/reduce-styling-iterations.md", + "sidenav-toggle": "doc/development/ux-improvement/sidenav-toggle.md", + "ux-assessment-junie-prompts": "doc/development/ux-improvement/ux-assessment-junie-prompts.md", + "ux-review-assets-logs": "doc/development/ux-improvement/ux-review-assets-logs.md", + "knowledge-classification": "doc/evaluation/knowledge-classification.md", + "REVIEW_WORKFLOW": "doc/evaluation/benchmarks/REVIEW_WORKFLOW.md", + "review_workflow": "doc/evaluation/benchmarks/REVIEW_WORKFLOW.md", + "index_de": "doc/features/index_de.md", + "navigation_de": "doc/features/navigation_de.md", + "risk-radar_de": "doc/features/risk-radar_de.md", + "Deployment": "doc/infrastructure/Deployment.md", + "Docker-Optimization": "doc/infrastructure/Docker-Optimization.md", + "k8s-setup": "doc/infrastructure/k8s/k8s-setup.md", + "placeholder": "doc/knowledge/placeholder.md", + "REPOSITORY-BRAIN": "doc/knowledge/REPOSITORY-BRAIN.md", + "repository-brain": "doc/knowledge/REPOSITORY-BRAIN.md", + "test-uploaded": "doc/knowledge/test-uploaded.md", + "adr-format-guideline": "doc/knowledge/adrs/adr-format-guideline.md", + "adr-full-set": "doc/knowledge/adrs/adr-full-set.md", + "AGENT-RULES": "doc/knowledge/ai-execution/AGENT-RULES.md", + "agent-rules": "doc/knowledge/ai-execution/AGENT-RULES.md", + "AI-CODEBASE-INDEX": "doc/knowledge/ai-execution/AI-CODEBASE-INDEX.md", + "ai-codebase-index": "doc/knowledge/ai-execution/AI-CODEBASE-INDEX.md", + "AI-CONTEXT-MAP": "doc/knowledge/ai-execution/AI-CONTEXT-MAP.md", + "ai-context-map": "doc/knowledge/ai-execution/AI-CONTEXT-MAP.md", + "AI-PROJECT-INTELLIGENCE-DASHBOARD": "doc/knowledge/ai-execution/AI-PROJECT-INTELLIGENCE-DASHBOARD.md", + "ai-project-intelligence-dashboard": "doc/knowledge/ai-execution/AI-PROJECT-INTELLIGENCE-DASHBOARD.md", + "AI-SYSTEM-DIAGRAM": "doc/knowledge/ai-execution/AI-SYSTEM-DIAGRAM.md", + "ai-system-diagram": "doc/knowledge/ai-execution/AI-SYSTEM-DIAGRAM.md", + "AI-TASK-PLANNING-GUIDE": "doc/knowledge/ai-execution/AI-TASK-PLANNING-GUIDE.md", + "ai-task-planning-guide": "doc/knowledge/ai-execution/AI-TASK-PLANNING-GUIDE.md", + "DO-NOT-TOUCH": "doc/knowledge/ai-execution/DO-NOT-TOUCH.md", + "do-not-touch": "doc/knowledge/ai-execution/DO-NOT-TOUCH.md", + "KNOWN-PITFALLS": "doc/knowledge/ai-execution/KNOWN-PITFALLS.md", + "known-pitfalls": "doc/knowledge/ai-execution/KNOWN-PITFALLS.md", + "REPO-ENTRY-POINTS": "doc/knowledge/ai-execution/REPO-ENTRY-POINTS.md", + "repo-entry-points": "doc/knowledge/ai-execution/REPO-ENTRY-POINTS.md", + "START-HERE": "doc/knowledge/ai-execution/START-HERE.md", + "start-here": "doc/knowledge/ai-execution/START-HERE.md", + "TASK-EXECUTION-CHECKLIST": "doc/knowledge/ai-execution/TASK-EXECUTION-CHECKLIST.md", + "task-execution-checklist": "doc/knowledge/ai-execution/TASK-EXECUTION-CHECKLIST.md", + "AI-FEEDBACK-LOOP": "doc/knowledge/ai-feedback/AI-FEEDBACK-LOOP.md", + "ai-feedback-loop": "doc/knowledge/ai-feedback/AI-FEEDBACK-LOOP.md", + "FINDING-SCHEMA": "doc/knowledge/ai-feedback/FINDING-SCHEMA.md", + "finding-schema": "doc/knowledge/ai-feedback/FINDING-SCHEMA.md", + "TASK-GENERATION-RULES": "doc/knowledge/ai-feedback/TASK-GENERATION-RULES.md", + "task-generation-rules": "doc/knowledge/ai-feedback/TASK-GENERATION-RULES.md", + "visualizing-the-final-system": "doc/knowledge/ai-readme/visualizing-the-final-system.md", + "ai-data-flow": "doc/knowledge/architecture/ai-data-flow.md", + "AI-ENGINEERING-CONTEXT": "doc/knowledge/architecture/AI-ENGINEERING-CONTEXT.md", + "ai-engineering-context": "doc/knowledge/architecture/AI-ENGINEERING-CONTEXT.md", + "AI-ROADMAP-VISUAL": "doc/knowledge/architecture/AI-ROADMAP-VISUAL.md", + "ai-roadmap-visual": "doc/knowledge/architecture/AI-ROADMAP-VISUAL.md", + "AI-SYSTEM-OVERVIEW": "doc/knowledge/architecture/AI-SYSTEM-OVERVIEW.md", + "ai-system-overview": "doc/knowledge/architecture/AI-SYSTEM-OVERVIEW.md", + "AI_SYSTEM_MENTAL_MODEL": "doc/knowledge/architecture/AI_SYSTEM_MENTAL_MODEL.md", + "ai_system_mental_model": "doc/knowledge/architecture/AI_SYSTEM_MENTAL_MODEL.md", + "api-overview": "doc/knowledge/architecture/api-overview.md", + "ARCHITECTURE-QA-SEEDS": "doc/knowledge/architecture/ARCHITECTURE-QA-SEEDS.md", + "architecture-qa-seeds": "doc/knowledge/architecture/ARCHITECTURE-QA-SEEDS.md", + "backend-architecture": "doc/knowledge/architecture/backend-architecture.md", + "current-system-analysis": "doc/knowledge/architecture/current-system-analysis.md", + "erd": "doc/knowledge/architecture/erd.md", + "frontend-architecture": "doc/knowledge/architecture/frontend-architecture.md", + "module-dependencies": "doc/knowledge/architecture/module-dependencies.md", + "spring-boot-profiles": "doc/knowledge/architecture/spring-boot-profiles.md", + "system-overview": "doc/knowledge/architecture/system-overview.md", + "AI-ARCHITECTURE-POSTER": "doc/knowledge/architecture/backlog/AI-ARCHITECTURE-POSTER.md", + "ai-architecture-poster": "doc/knowledge/architecture/backlog/AI-ARCHITECTURE-POSTER.md", + "01-roadmap-overview": "doc/knowledge/architecture/overview/01-roadmap-overview.md", + "02-phase-and-epic-priority": "doc/knowledge/architecture/overview/02-phase-and-epic-priority.md", + "03-architecture-layers": "doc/knowledge/architecture/overview/03-architecture-layers.md", + "04-roadmap-graph": "doc/knowledge/architecture/overview/04-roadmap-graph.md", + "05-governance-notes": "doc/knowledge/architecture/overview/05-governance-notes.md", + "06-task-index": "doc/knowledge/architecture/overview/06-task-index.md", + "AI-ROADMAP-OVERVIEW": "doc/knowledge/architecture/roadmap/AI-ROADMAP-OVERVIEW.md", + "ai-roadmap-overview": "doc/knowledge/architecture/roadmap/AI-ROADMAP-OVERVIEW.md", + "AI-TASK-PREFIX-INDEX": "doc/knowledge/junie-tasks/AI-TASK-PREFIX-INDEX.md", + "ai-task-prefix-index": "doc/knowledge/junie-tasks/AI-TASK-PREFIX-INDEX.md", + "fix-sonar-issues": "doc/knowledge/junie-tasks/fix-sonar-issues.md", + "internal-presentation": "doc/knowledge/junie-tasks/internal-presentation.md", + "JUNIE_TASK_INDEX": "doc/knowledge/junie-tasks/JUNIE_TASK_INDEX.md", + "junie_task_index": "doc/knowledge/junie-tasks/JUNIE_TASK_INDEX.md", + "local-quodana": "doc/knowledge/junie-tasks/local-quodana.md", + "md-prompt-log": "doc/knowledge/junie-tasks/md-prompt-log.md", + "taskindex": "doc/knowledge/junie-tasks/taskindex.md", + "tasks-overview": "doc/knowledge/junie-tasks/tasks-overview.md", + "test-coverage-sonar": "doc/knowledge/junie-tasks/test-coverage-sonar.md", + "AI-AI-01-Improve-Architecture-QA-Retrieval": "doc/knowledge/junie-tasks/AI-AI/AI-AI-01-Improve-Architecture-QA-Retrieval.md", + "ai-ai-01-improve-architecture-qa-retrieval": "doc/knowledge/junie-tasks/AI-AI/AI-AI-01-Improve-Architecture-QA-Retrieval.md", + "AI-AI-02 - Add Risk Radar Rule Engine": "doc/knowledge/junie-tasks/AI-AI/AI-AI-02 - Add Risk Radar Rule Engine.md", + "ai-ai-02 - add risk radar rule engine": "doc/knowledge/junie-tasks/AI-AI/AI-AI-02 - Add Risk Radar Rule Engine.md", + "AI-AI-03-Improve-Sprint-Retrospective-Prompting": "doc/knowledge/junie-tasks/AI-AI/AI-AI-03-Improve-Sprint-Retrospective-Prompting.md", + "ai-ai-03-improve-sprint-retrospective-prompting": "doc/knowledge/junie-tasks/AI-AI/AI-AI-03-Improve-Sprint-Retrospective-Prompting.md", + "AI-AI-04 - Add AI Onboarding Assistant": "doc/knowledge/junie-tasks/AI-AI/AI-AI-04 - Add AI Onboarding Assistant.md", + "ai-ai-04 - add ai onboarding assistant": "doc/knowledge/junie-tasks/AI-AI/AI-AI-04 - Add AI Onboarding Assistant.md", + "AI-AI-05 - Add AI What-If Impact Simulator": "doc/knowledge/junie-tasks/AI-AI/AI-AI-05 - Add AI What-If Impact Simulator.md", + "ai-ai-05 - add ai what-if impact simulator": "doc/knowledge/junie-tasks/AI-AI/AI-AI-05 - Add AI What-If Impact Simulator.md", + "AI-AI-06-Add-AI-Backlog-Analyzer": "doc/knowledge/junie-tasks/AI-AI/AI-AI-06-Add-AI-Backlog-Analyzer.md", + "ai-ai-06-add-ai-backlog-analyzer": "doc/knowledge/junie-tasks/AI-AI/AI-AI-06-Add-AI-Backlog-Analyzer.md", + "AI-AI-07-Engineering-Context-Index": "doc/knowledge/junie-tasks/AI-AI/AI-AI-07-Engineering-Context-Index.md", + "ai-ai-07-engineering-context-index": "doc/knowledge/junie-tasks/AI-AI/AI-AI-07-Engineering-Context-Index.md", + "AI-AI-08 - Task Relationship Engine": "doc/knowledge/junie-tasks/AI-AI/AI-AI-08 - Task Relationship Engine.md", + "ai-ai-08 - task relationship engine": "doc/knowledge/junie-tasks/AI-AI/AI-AI-08 - Task Relationship Engine.md", + "AI-AI-09-Engineering-Insight-Ranking-Engine": "doc/knowledge/junie-tasks/AI-AI/AI-AI-09-Engineering-Insight-Ranking-Engine.md", + "ai-ai-09-engineering-insight-ranking-engine": "doc/knowledge/junie-tasks/AI-AI/AI-AI-09-Engineering-Insight-Ranking-Engine.md", + "AI-AI-09A-Task-Relationship-Provenance-and-Trust-Controls": "doc/knowledge/junie-tasks/AI-AI/AI-AI-09A-Task-Relationship-Provenance-and-Trust-Controls.md", + "ai-ai-09a-task-relationship-provenance-and-trust-controls": "doc/knowledge/junie-tasks/AI-AI/AI-AI-09A-Task-Relationship-Provenance-and-Trust-Controls.md", + "AI-AI-10-Fix-Onboarding-Assistant-Endpoint": "doc/knowledge/junie-tasks/AI-AI/AI-AI-10-Fix-Onboarding-Assistant-Endpoint.md", + "ai-ai-10-fix-onboarding-assistant-endpoint": "doc/knowledge/junie-tasks/AI-AI/AI-AI-10-Fix-Onboarding-Assistant-Endpoint.md", + "AI-AI-11-document-tree-coverage": "doc/knowledge/junie-tasks/AI-AI/AI-AI-11-document-tree-coverage.md", + "ai-ai-11-document-tree-coverage": "doc/knowledge/junie-tasks/AI-AI/AI-AI-11-document-tree-coverage.md", + "AI-AI-12-Fix-Architecture-QA-Schema-Validation": "doc/knowledge/junie-tasks/AI-AI/AI-AI-12-Fix-Architecture-QA-Schema-Validation.md", + "ai-ai-12-fix-architecture-qa-schema-validation": "doc/knowledge/junie-tasks/AI-AI/AI-AI-12-Fix-Architecture-QA-Schema-Validation.md", + "AI-AI-13-Fix-Copilot-JSON-Schema-Extraction": "doc/knowledge/junie-tasks/AI-AI/AI-AI-13-Fix-Copilot-JSON-Schema-Extraction.md", + "ai-ai-13-fix-copilot-json-schema-extraction": "doc/knowledge/junie-tasks/AI-AI/AI-AI-13-Fix-Copilot-JSON-Schema-Extraction.md", + "AI-AI-20-Continuous-Insight-Scheduler": "doc/knowledge/junie-tasks/AI-AI/AI-AI-20-Continuous-Insight-Scheduler.md", + "ai-ai-20-continuous-insight-scheduler": "doc/knowledge/junie-tasks/AI-AI/AI-AI-20-Continuous-Insight-Scheduler.md", + "AI-AI-21-Insight-History-Store": "doc/knowledge/junie-tasks/AI-AI/AI-AI-21-Insight-History-Store.md", + "ai-ai-21-insight-history-store": "doc/knowledge/junie-tasks/AI-AI/AI-AI-21-Insight-History-Store.md", + "AI-AN-21-jackson-runtime-conflict-analysis": "doc/knowledge/junie-tasks/AI-AN/AI-AN-21-jackson-runtime-conflict-analysis.md", + "ai-an-21-jackson-runtime-conflict-analysis": "doc/knowledge/junie-tasks/AI-AN/AI-AN-21-jackson-runtime-conflict-analysis.md", + "AI-ARCH-01-ADR-Knowledge-Index": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-01-ADR-Knowledge-Index.md", + "ai-arch-01-adr-knowledge-index": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-01-ADR-Knowledge-Index.md", + "AI-ARCH-02 - Architecture Change Detector": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-02 - Architecture Change Detector.md", + "ai-arch-02 - architecture change detector": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-02 - Architecture Change Detector.md", + "AI-ARCH-03-Prompt-templates-v1-strict-structured-JSON-outputs": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-03-Prompt-templates-v1-strict-structured-JSON-outputs.md", + "ai-arch-03-prompt-templates-v1-strict-structured-json-outputs": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-03-Prompt-templates-v1-strict-structured-JSON-outputs.md", + "AI-ARCH-03R-Architecture-Change-Signal-Extraction": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-03R-Architecture-Change-Signal-Extraction.md", + "ai-arch-03r-architecture-change-signal-extraction": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-03R-Architecture-Change-Signal-Extraction.md", + "AI-ARCH-04-AI-backend-endpoints-application-layer-no-model-calls-in-controllers": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-04-AI-backend-endpoints-application-layer-no-model-calls-in-controllers.md", + "ai-arch-04-ai-backend-endpoints-application-layer-no-model-calls-in-controllers": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-04-AI-backend-endpoints-application-layer-no-model-calls-in-controllers.md", + "AI-ARCH-05-Docs-ingestion-into-Postgres-pgvector-schema-reindex-endpoint": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-05-Docs-ingestion-into-Postgres-pgvector-schema-reindex-endpoint.md", + "ai-arch-05-docs-ingestion-into-postgres-pgvector-schema-reindex-endpoint": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-05-Docs-ingestion-into-Postgres-pgvector-schema-reindex-endpoint.md", + "AI-ARCH-06-Embeddings-vector-retrieval-sources-in-Architecture-explain": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-06-Embeddings-vector-retrieval-sources-in-Architecture-explain.md", + "ai-arch-06-embeddings-vector-retrieval-sources-in-architecture-explain": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-06-Embeddings-vector-retrieval-sources-in-Architecture-explain.md", + "AI-ARCH-07-Quick-Add-AI-enhancement-hybrid-deterministic-parser-AI-parse-preview-workflow": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-07-Quick-Add-AI-enhancement-hybrid-deterministic-parser-AI-parse-preview-workflow.md", + "ai-arch-07-quick-add-ai-enhancement-hybrid-deterministic-parser-ai-parse-preview-workflow": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-07-Quick-Add-AI-enhancement-hybrid-deterministic-parser-AI-parse-preview-workflow.md", + "AI-ARCH-08-Angular-UI-Architecture-Q-A-page-with-sources-Quick-Add-preview-components": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-08-Angular-UI-Architecture-Q-A-page-with-sources-Quick-Add-preview-components.md", + "ai-arch-08-angular-ui-architecture-q-a-page-with-sources-quick-add-preview-components": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-08-Angular-UI-Architecture-Q-A-page-with-sources-Quick-Add-preview-components.md", + "AI-ARCH-09-Security-observability-for-AI-endpoints": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-09-Security-observability-for-AI-endpoints.md", + "ai-arch-09-security-observability-for-ai-endpoints": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-09-Security-observability-for-AI-endpoints.md", + "AI-ARCH-10-CI-CD-tests-pgvector-service-Playwright-smoke-suite": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-10-CI-CD-tests-pgvector-service-Playwright-smoke-suite.md", + "ai-arch-10-ci-cd-tests-pgvector-service-playwright-smoke-suite": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-10-CI-CD-tests-pgvector-service-Playwright-smoke-suite.md", + "AI-ARCH-11-Add-Open-AI-Config": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-11-Add-Open-AI-Config.md", + "ai-arch-11-add-open-ai-config": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-11-Add-Open-AI-Config.md", + "AI-ARCH-12-Uppload-Docs": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-12-Uppload-Docs.md", + "ai-arch-12-uppload-docs": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-12-Uppload-Docs.md", + "AI-ARCH-13-AI-Credits-Limit": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-13-AI-Credits-Limit.md", + "ai-arch-13-ai-credits-limit": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-13-AI-Credits-Limit.md", + "AI-ARCH-14-AI-Credits-Dashboard": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-14-AI-Credits-Dashboard.md", + "ai-arch-14-ai-credits-dashboard": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-14-AI-Credits-Dashboard.md", + "AI-ARCH-15-AI-Runtime-Fargate": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-15-AI-Runtime-Fargate.md", + "ai-arch-15-ai-runtime-fargate": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-15-AI-Runtime-Fargate.md", + "AI-ARCH-16-AI-Observability-NAT-Free": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-16-AI-Observability-NAT-Free.md", + "ai-arch-16-ai-observability-nat-free": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-16-AI-Observability-NAT-Free.md", + "AI-ARCH-17-AI-Cost-Dashboard": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-17-AI-Cost-Dashboard.md", + "ai-arch-17-ai-cost-dashboard": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-17-AI-Cost-Dashboard.md", + "AI-ARCH-18-Profile-Anonymization": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-18-Profile-Anonymization.md", + "ai-arch-18-profile-anonymization": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-18-Profile-Anonymization.md", + "AI-ARCH-19-adr-service-and-indexing-abstraction": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-19-adr-service-and-indexing-abstraction.md", + "ai-arch-19-adr-service-and-indexing-abstraction": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-19-adr-service-and-indexing-abstraction.md", + "AI-ARCH-20-Ollama-Timeout-Tuning": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-20-Ollama-Timeout-Tuning.md", + "ai-arch-20-ollama-timeout-tuning": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-20-Ollama-Timeout-Tuning.md", + "AI-ARCH-21-Llama-Parsing-Robustness": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-21-Llama-Parsing-Robustness.md", + "ai-arch-21-llama-parsing-robustness": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-21-Llama-Parsing-Robustness.md", + "AI-ARCH-22-ADR-Auto-Generator": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-22-ADR-Auto-Generator.md", + "ai-arch-22-adr-auto-generator": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-22-ADR-Auto-Generator.md", + "AI-ARCH-23-Architecture-Recommendation-Engine": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-23-Architecture-Recommendation-Engine.md", + "ai-arch-23-architecture-recommendation-engine": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-23-Architecture-Recommendation-Engine.md", + "AI-ARCH-41-unify-sprint-taskset-resolution-and-selector-ux": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-41-unify-sprint-taskset-resolution-and-selector-ux.md", + "ai-arch-41-unify-sprint-taskset-resolution-and-selector-ux": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-41-unify-sprint-taskset-resolution-and-selector-ux.md", + "AI-ARCH-42-optimize-task-group-indexing-for-fast-iteration-testing": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-42-optimize-task-group-indexing-for-fast-iteration-testing.md", + "ai-arch-42-optimize-task-group-indexing-for-fast-iteration-testing": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-42-optimize-task-group-indexing-for-fast-iteration-testing.md", + "AI-ARCH-43-Consolidate-Architecture-Doc-Roots-and-Write-AI-System-Mental-Model": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-43-Consolidate-Architecture-Doc-Roots-and-Write-AI-System-Mental-Model.md", + "ai-arch-43-consolidate-architecture-doc-roots-and-write-ai-system-mental-model": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-43-Consolidate-Architecture-Doc-Roots-and-Write-AI-System-Mental-Model.md", + "AI-ARCH-50-single-serialization-ownership": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-50-single-serialization-ownership.md", + "ai-arch-50-single-serialization-ownership": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-50-single-serialization-ownership.md", + "AI-ARCH-55-AI-Response-Repair-Robustness": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-55-AI-Response-Repair-Robustness.md", + "ai-arch-55-ai-response-repair-robustness": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-55-AI-Response-Repair-Robustness.md", + "AI-ARCH-56-final-ai-pipeline": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-56-final-ai-pipeline.md", + "ai-arch-56-final-ai-pipeline": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-56-final-ai-pipeline.md", + "AI-ARCH-57-Score-captcha": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-57-Score-captcha.md", + "ai-arch-57-score-captcha": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-57-Score-captcha.md", + "AI-ARCH-58-Monorepo-structure-dev-orchestration-Postgres-pgvector-Ollama": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-58-Monorepo-structure-dev-orchestration-Postgres-pgvector-Ollama.md", + "ai-arch-58-monorepo-structure-dev-orchestration-postgres-pgvector-ollama": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-58-Monorepo-structure-dev-orchestration-Postgres-pgvector-Ollama.md", + "AI-ARCH-59-Spring-AI-wiring-provider-profiles-local-Ollama-first": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-59-Spring-AI-wiring-provider-profiles-local-Ollama-first.md", + "ai-arch-59-spring-ai-wiring-provider-profiles-local-ollama-first": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-59-Spring-AI-wiring-provider-profiles-local-Ollama-first.md", + "AI-ARCH-60-Seed-Architecture-QA-Content": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-60-Seed-Architecture-QA-Content.md", + "ai-arch-60-seed-architecture-qa-content": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-60-Seed-Architecture-QA-Content.md", + "AI-ARCH-61-Balance-Architecture-Page-Structure": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-61-Balance-Architecture-Page-Structure.md", + "ai-arch-61-balance-architecture-page-structure": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-61-Balance-Architecture-Page-Structure.md", + "AI-ARCH-62-Comprehensive-Documentation-Update": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-62-Comprehensive-Documentation-Update.md", + "ai-arch-62-comprehensive-documentation-update": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-62-Comprehensive-Documentation-Update.md", + "AI-ARCH-63-Introduction-of-Architectural-Decision-Records": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-63-Introduction-of-Architectural-Decision-Records.md", + "ai-arch-63-introduction-of-architectural-decision-records": "doc/knowledge/junie-tasks/AI-ARCH/AI-ARCH-63-Introduction-of-Architectural-Decision-Records.md", + "AI-BE-01-Expose-AI-Usage-Metrics-API": "doc/knowledge/junie-tasks/AI-BE/AI-BE-01-Expose-AI-Usage-Metrics-API.md", + "ai-be-01-expose-ai-usage-metrics-api": "doc/knowledge/junie-tasks/AI-BE/AI-BE-01-Expose-AI-Usage-Metrics-API.md", + "AI-BE-02 - Implement AI Credit Tracking Persistence": "doc/knowledge/junie-tasks/AI-BE/AI-BE-02 - Implement AI Credit Tracking Persistence.md", + "ai-be-02 - implement ai credit tracking persistence": "doc/knowledge/junie-tasks/AI-BE/AI-BE-02 - Implement AI Credit Tracking Persistence.md", + "AI-BE-14-Fix AI intelligence dashboard sprint scoping and epic status calculation": "doc/knowledge/junie-tasks/AI-BE/AI-BE-14-Fix AI intelligence dashboard sprint scoping and epic status calculation.md", + "ai-be-14-fix ai intelligence dashboard sprint scoping and epic status calculation": "doc/knowledge/junie-tasks/AI-BE/AI-BE-14-Fix AI intelligence dashboard sprint scoping and epic status calculation.md", + "AI-BE-15-Use-sprint-plan-docs-as-authoritative-source-for-intelligence-dashboard-sprint-scoping": "doc/knowledge/junie-tasks/AI-BE/AI-BE-15-Use-sprint-plan-docs-as-authoritative-source-for-intelligence-dashboard-sprint-scoping.md", + "ai-be-15-use-sprint-plan-docs-as-authoritative-source-for-intelligence-dashboard-sprint-scoping": "doc/knowledge/junie-tasks/AI-BE/AI-BE-15-Use-sprint-plan-docs-as-authoritative-source-for-intelligence-dashboard-sprint-scoping.md", + "AI-BE-16-Discover-available-sprints-from-repo-sprint-plan-docs": "doc/knowledge/junie-tasks/AI-BE/AI-BE-16-Discover-available-sprints-from-repo-sprint-plan-docs.md", + "ai-be-16-discover-available-sprints-from-repo-sprint-plan-docs": "doc/knowledge/junie-tasks/AI-BE/AI-BE-16-Discover-available-sprints-from-repo-sprint-plan-docs.md", + "AI-BE-17-Make-sprint-discovery-and-sorting-robust-for-future-naming-variants": "doc/knowledge/junie-tasks/AI-BE/AI-BE-17-Make-sprint-discovery-and-sorting-robust-for-future-naming-variants.md", + "ai-be-17-make-sprint-discovery-and-sorting-robust-for-future-naming-variants": "doc/knowledge/junie-tasks/AI-BE/AI-BE-17-Make-sprint-discovery-and-sorting-robust-for-future-naming-variants.md", + "AI-BE-18-Fix-exact-sprint-id-matching": "doc/knowledge/junie-tasks/AI-BE/AI-BE-18-Fix-exact-sprint-id-matching.md", + "ai-be-18-fix-exact-sprint-id-matching": "doc/knowledge/junie-tasks/AI-BE/AI-BE-18-Fix-exact-sprint-id-matching.md", + "AI-BE-19-Establish-consistent-Jackson-strategy-for-Spring-Boot-4": "doc/knowledge/junie-tasks/AI-BE/AI-BE-19-Establish-consistent-Jackson-strategy-for-Spring-Boot-4.md", + "ai-be-19-establish-consistent-jackson-strategy-for-spring-boot-4": "doc/knowledge/junie-tasks/AI-BE/AI-BE-19-Establish-consistent-Jackson-strategy-for-Spring-Boot-4.md", + "AI-BE-20-unified-ai-usecase-interface": "doc/knowledge/junie-tasks/AI-BE/AI-BE-20-unified-ai-usecase-interface.md", + "ai-be-20-unified-ai-usecase-interface": "doc/knowledge/junie-tasks/AI-BE/AI-BE-20-unified-ai-usecase-interface.md", + "AI-BE-21-ai-routing-simplification": "doc/knowledge/junie-tasks/AI-BE/AI-BE-21-ai-routing-simplification.md", + "ai-be-21-ai-routing-simplification": "doc/knowledge/junie-tasks/AI-BE/AI-BE-21-ai-routing-simplification.md", + "AI-BE-22-Deterministic-AI-Test-Profile": "doc/knowledge/junie-tasks/AI-BE/AI-BE-22-Deterministic-AI-Test-Profile.md", + "ai-be-22-deterministic-ai-test-profile": "doc/knowledge/junie-tasks/AI-BE/AI-BE-22-Deterministic-AI-Test-Profile.md", + "AI-BE-30-deterministic-prompt-layer": "doc/knowledge/junie-tasks/AI-BE/AI-BE-30-deterministic-prompt-layer.md", + "ai-be-30-deterministic-prompt-layer": "doc/knowledge/junie-tasks/AI-BE/AI-BE-30-deterministic-prompt-layer.md", + "AI-BE-31-response-stabilization": "doc/knowledge/junie-tasks/AI-BE/AI-BE-31-response-stabilization.md", + "ai-be-31-response-stabilization": "doc/knowledge/junie-tasks/AI-BE/AI-BE-31-response-stabilization.md", + "AI-BE-32-ollama-performance-phase2": "doc/knowledge/junie-tasks/AI-BE/AI-BE-32-ollama-performance-phase2.md", + "ai-be-32-ollama-performance-phase2": "doc/knowledge/junie-tasks/AI-BE/AI-BE-32-ollama-performance-phase2.md", + "AI-BE-33-ai-trace-logging": "doc/knowledge/junie-tasks/AI-BE/AI-BE-33-ai-trace-logging.md", + "ai-be-33-ai-trace-logging": "doc/knowledge/junie-tasks/AI-BE/AI-BE-33-ai-trace-logging.md", + "AI-BE-34-stale-document-detector": "doc/knowledge/junie-tasks/AI-BE/AI-BE-34-stale-document-detector.md", + "ai-be-34-stale-document-detector": "doc/knowledge/junie-tasks/AI-BE/AI-BE-34-stale-document-detector.md", + "AI-BE-35-knowledge-coverage-report": "doc/knowledge/junie-tasks/AI-BE/AI-BE-35-knowledge-coverage-report.md", + "ai-be-35-knowledge-coverage-report": "doc/knowledge/junie-tasks/AI-BE/AI-BE-35-knowledge-coverage-report.md", + "AI-BE-36-ollama-compatibility": "doc/knowledge/junie-tasks/AI-BE/AI-BE-36-ollama-compatibility.md", + "ai-be-36-ollama-compatibility": "doc/knowledge/junie-tasks/AI-BE/AI-BE-36-ollama-compatibility.md", + "AI-BE-37-structured-ai-client": "doc/knowledge/junie-tasks/AI-BE/AI-BE-37-structured-ai-client.md", + "ai-be-37-structured-ai-client": "doc/knowledge/junie-tasks/AI-BE/AI-BE-37-structured-ai-client.md", + "AI-BE-38-json-schema-pack": "doc/knowledge/junie-tasks/AI-BE/AI-BE-38-json-schema-pack.md", + "ai-be-38-json-schema-pack": "doc/knowledge/junie-tasks/AI-BE/AI-BE-38-json-schema-pack.md", + "AI-BE-39-evidence-builder": "doc/knowledge/junie-tasks/AI-BE/AI-BE-39-evidence-builder.md", + "ai-be-39-evidence-builder": "doc/knowledge/junie-tasks/AI-BE/AI-BE-39-evidence-builder.md", + "AI-BE-40-document-classifier": "doc/knowledge/junie-tasks/AI-BE/AI-BE-40-document-classifier.md", + "ai-be-40-document-classifier": "doc/knowledge/junie-tasks/AI-BE/AI-BE-40-document-classifier.md", + "AI-BE-41-deterministic-ai-response-wrapper": "doc/knowledge/junie-tasks/AI-BE/AI-BE-41-deterministic-ai-response-wrapper.md", + "ai-be-41-deterministic-ai-response-wrapper": "doc/knowledge/junie-tasks/AI-BE/AI-BE-41-deterministic-ai-response-wrapper.md", + "AI-BE-42-jackson-classpath-hardening": "doc/knowledge/junie-tasks/AI-BE/AI-BE-42-jackson-classpath-hardening.md", + "ai-be-42-jackson-classpath-hardening": "doc/knowledge/junie-tasks/AI-BE/AI-BE-42-jackson-classpath-hardening.md", + "AI-BE-43-ai-determinism-test-suite": "doc/knowledge/junie-tasks/AI-BE/AI-BE-43-ai-determinism-test-suite.md", + "ai-be-43-ai-determinism-test-suite": "doc/knowledge/junie-tasks/AI-BE/AI-BE-43-ai-determinism-test-suite.md", + "AI-BE-44-trace-graph-builder": "doc/knowledge/junie-tasks/AI-BE/AI-BE-44-trace-graph-builder.md", + "ai-be-44-trace-graph-builder": "doc/knowledge/junie-tasks/AI-BE/AI-BE-44-trace-graph-builder.md", + "AI-BE-45-knowledge-coverage-metric": "doc/knowledge/junie-tasks/AI-BE/AI-BE-45-knowledge-coverage-metric.md", + "ai-be-45-knowledge-coverage-metric": "doc/knowledge/junie-tasks/AI-BE/AI-BE-45-knowledge-coverage-metric.md", + "AI-BE-46-cross-document-consistency-check": "doc/knowledge/junie-tasks/AI-BE/AI-BE-46-cross-document-consistency-check.md", + "ai-be-46-cross-document-consistency-check": "doc/knowledge/junie-tasks/AI-BE/AI-BE-46-cross-document-consistency-check.md", + "AI-BE-47-stale-doc-detector-runtime": "doc/knowledge/junie-tasks/AI-BE/AI-BE-47-stale-doc-detector-runtime.md", + "ai-be-47-stale-doc-detector-runtime": "doc/knowledge/junie-tasks/AI-BE/AI-BE-47-stale-doc-detector-runtime.md", + "AI-BE-48-recursive-document-tree-api": "doc/knowledge/junie-tasks/AI-BE/AI-BE-48-recursive-document-tree-api.md", + "ai-be-48-recursive-document-tree-api": "doc/knowledge/junie-tasks/AI-BE/AI-BE-48-recursive-document-tree-api.md", + "AI-BE-49-document-usage-aggregation-service": "doc/knowledge/junie-tasks/AI-BE/AI-BE-49-document-usage-aggregation-service.md", + "ai-be-49-document-usage-aggregation-service": "doc/knowledge/junie-tasks/AI-BE/AI-BE-49-document-usage-aggregation-service.md", + "AI-BE-50-remove-dual-mapper-architecture": "doc/knowledge/junie-tasks/AI-BE/AI-BE-50-remove-dual-mapper-architecture.md", + "ai-be-50-remove-dual-mapper-architecture": "doc/knowledge/junie-tasks/AI-BE/AI-BE-50-remove-dual-mapper-architecture.md", + "AI-BE-51-retrieval-telemetry-enrichment": "doc/knowledge/junie-tasks/AI-BE/AI-BE-51-retrieval-telemetry-enrichment.md", + "ai-be-51-retrieval-telemetry-enrichment": "doc/knowledge/junie-tasks/AI-BE/AI-BE-51-retrieval-telemetry-enrichment.md", + "AI-BE-52-document-detail-endpoint": "doc/knowledge/junie-tasks/AI-BE/AI-BE-52-document-detail-endpoint.md", + "ai-be-52-document-detail-endpoint": "doc/knowledge/junie-tasks/AI-BE/AI-BE-52-document-detail-endpoint.md", + "AI-BE-53-canonical-dto-normalization": "doc/knowledge/junie-tasks/AI-BE/AI-BE-53-canonical-dto-normalization.md", + "ai-be-53-canonical-dto-normalization": "doc/knowledge/junie-tasks/AI-BE/AI-BE-53-canonical-dto-normalization.md", + "AI-BE-54-schema-pack-normalization": "doc/knowledge/junie-tasks/AI-BE/AI-BE-54-schema-pack-normalization.md", + "ai-be-54-schema-pack-normalization": "doc/knowledge/junie-tasks/AI-BE/AI-BE-54-schema-pack-normalization.md", + "AI-BE-55-sse-stream-completion-fix": "doc/knowledge/junie-tasks/AI-BE/AI-BE-55-sse-stream-completion-fix.md", + "ai-be-55-sse-stream-completion-fix": "doc/knowledge/junie-tasks/AI-BE/AI-BE-55-sse-stream-completion-fix.md", + "AI-BE-56-ollama-performance-optimization": "doc/knowledge/junie-tasks/AI-BE/AI-BE-56-ollama-performance-optimization.md", + "ai-be-56-ollama-performance-optimization": "doc/knowledge/junie-tasks/AI-BE/AI-BE-56-ollama-performance-optimization.md", + "AI-BE-57-unify-json-stack": "doc/knowledge/junie-tasks/AI-BE/AI-BE-57-unify-json-stack.md", + "ai-be-57-unify-json-stack": "doc/knowledge/junie-tasks/AI-BE/AI-BE-57-unify-json-stack.md", + "AI-BE-58-remove-json-repair": "doc/knowledge/junie-tasks/AI-BE/AI-BE-58-remove-json-repair.md", + "ai-be-58-remove-json-repair": "doc/knowledge/junie-tasks/AI-BE/AI-BE-58-remove-json-repair.md", + "AI-BE-59-prompt-versioning": "doc/knowledge/junie-tasks/AI-BE/AI-BE-59-prompt-versioning.md", + "ai-be-59-prompt-versioning": "doc/knowledge/junie-tasks/AI-BE/AI-BE-59-prompt-versioning.md", + "AI-BE-60-stale-reason-classifier": "doc/knowledge/junie-tasks/AI-BE/AI-BE-60-stale-reason-classifier.md", + "ai-be-60-stale-reason-classifier": "doc/knowledge/junie-tasks/AI-BE/AI-BE-60-stale-reason-classifier.md", + "AI-BE-61-strict-structured-output-policy": "doc/knowledge/junie-tasks/AI-BE/AI-BE-61-strict-structured-output-policy.md", + "ai-be-61-strict-structured-output-policy": "doc/knowledge/junie-tasks/AI-BE/AI-BE-61-strict-structured-output-policy.md", + "AI-BE-62-remove-json-repair-logic": "doc/knowledge/junie-tasks/AI-BE/AI-BE-62-remove-json-repair-logic.md", + "ai-be-62-remove-json-repair-logic": "doc/knowledge/junie-tasks/AI-BE/AI-BE-62-remove-json-repair-logic.md", + "AI-BE-INTEL-01-Add-project-intelligence-summary-endpoint": "doc/knowledge/junie-tasks/AI-BE-INTEL/AI-BE-INTEL-01-Add-project-intelligence-summary-endpoint.md", + "ai-be-intel-01-add-project-intelligence-summary-endpoint": "doc/knowledge/junie-tasks/AI-BE-INTEL/AI-BE-INTEL-01-Add-project-intelligence-summary-endpoint.md", + "AI-BE-INTEL-02-Add-architecture-drift-summary-provider": "doc/knowledge/junie-tasks/AI-BE-INTEL/AI-BE-INTEL-02-Add-architecture-drift-summary-provider.md", + "ai-be-intel-02-add-architecture-drift-summary-provider": "doc/knowledge/junie-tasks/AI-BE-INTEL/AI-BE-INTEL-02-Add-architecture-drift-summary-provider.md", + "AI-BE-INTEL-03-Add-AI-regression-trend-summary-provider": "doc/knowledge/junie-tasks/AI-BE-INTEL/AI-BE-INTEL-03-Add-AI-regression-trend-summary-provider.md", + "ai-be-intel-03-add-ai-regression-trend-summary-provider": "doc/knowledge/junie-tasks/AI-BE-INTEL/AI-BE-INTEL-03-Add-AI-regression-trend-summary-provider.md", + "AI-BE-INTEL-04-Add-backlog-leakage-summary-provider": "doc/knowledge/junie-tasks/AI-BE-INTEL/AI-BE-INTEL-04-Add-backlog-leakage-summary-provider.md", + "ai-be-intel-04-add-backlog-leakage-summary-provider": "doc/knowledge/junie-tasks/AI-BE-INTEL/AI-BE-INTEL-04-Add-backlog-leakage-summary-provider.md", + "AI-BE-INTEL-05-Add-sprint-progress-summary-provider": "doc/knowledge/junie-tasks/AI-BE-INTEL/AI-BE-INTEL-05-Add-sprint-progress-summary-provider.md", + "ai-be-intel-05-add-sprint-progress-summary-provider": "doc/knowledge/junie-tasks/AI-BE-INTEL/AI-BE-INTEL-05-Add-sprint-progress-summary-provider.md", + "AI-CI-20-fail-fast-invalid-json-gate": "doc/knowledge/junie-tasks/AI-CI/AI-CI-20-fail-fast-invalid-json-gate.md", + "ai-ci-20-fail-fast-invalid-json-gate": "doc/knowledge/junie-tasks/AI-CI/AI-CI-20-fail-fast-invalid-json-gate.md", + "AI-COP-01 - Context-Aware Engineering Chat": "doc/knowledge/junie-tasks/AI-COP/AI-COP-01 - Context-Aware Engineering Chat.md", + "ai-cop-01 - context-aware engineering chat": "doc/knowledge/junie-tasks/AI-COP/AI-COP-01 - Context-Aware Engineering Chat.md", + "AI-COP-02 - Code Change Explanation": "doc/knowledge/junie-tasks/AI-COP/AI-COP-02 - Code Change Explanation.md", + "ai-cop-02 - code change explanation": "doc/knowledge/junie-tasks/AI-COP/AI-COP-02 - Code Change Explanation.md", + "AI-COP-03 - Engineering Intelligence Dashboard": "doc/knowledge/junie-tasks/AI-COP/AI-COP-03 - Engineering Intelligence Dashboard.md", + "ai-cop-03 - engineering intelligence dashboard": "doc/knowledge/junie-tasks/AI-COP/AI-COP-03 - Engineering Intelligence Dashboard.md", + "AI-COP-04-Explicit-Copilot-Context-Orchestration-Layer": "doc/knowledge/junie-tasks/AI-COP/AI-COP-04-Explicit-Copilot-Context-Orchestration-Layer.md", + "ai-cop-04-explicit-copilot-context-orchestration-layer": "doc/knowledge/junie-tasks/AI-COP/AI-COP-04-Explicit-Copilot-Context-Orchestration-Layer.md", + "AI-COP-05-Separate-Copilot-Workspaces-from-Architecture-Page": "doc/knowledge/junie-tasks/AI-COP/AI-COP-05-Separate-Copilot-Workspaces-from-Architecture-Page.md", + "ai-cop-05-separate-copilot-workspaces-from-architecture-page": "doc/knowledge/junie-tasks/AI-COP/AI-COP-05-Separate-Copilot-Workspaces-from-Architecture-Page.md", + "AI-COP-06-Copilot-Capability-Routing-Contract": "doc/knowledge/junie-tasks/AI-COP/AI-COP-06-Copilot-Capability-Routing-Contract.md", + "ai-cop-06-copilot-capability-routing-contract": "doc/knowledge/junie-tasks/AI-COP/AI-COP-06-Copilot-Capability-Routing-Contract.md", + "AI-COP-07-Shared-Copilot-Response-Contract": "doc/knowledge/junie-tasks/AI-COP/AI-COP-07-Shared-Copilot-Response-Contract.md", + "ai-cop-07-shared-copilot-response-contract": "doc/knowledge/junie-tasks/AI-COP/AI-COP-07-Shared-Copilot-Response-Contract.md", + "AI-COP-08-Signal-Aware-Engineering-Chat": "doc/knowledge/junie-tasks/AI-COP/AI-COP-08-Signal-Aware-Engineering-Chat.md", + "ai-cop-08-signal-aware-engineering-chat": "doc/knowledge/junie-tasks/AI-COP/AI-COP-08-Signal-Aware-Engineering-Chat.md", + "AI-COP-09-Fix-Engineering-Chat-Wiring": "doc/knowledge/junie-tasks/AI-COP/AI-COP-09-Fix-Engineering-Chat-Wiring.md", + "ai-cop-09-fix-engineering-chat-wiring": "doc/knowledge/junie-tasks/AI-COP/AI-COP-09-Fix-Engineering-Chat-Wiring.md", + "AI-COP-10-Partition-Copilot-History-by-Mode-with-Safe-Migration": "doc/knowledge/junie-tasks/AI-COP/AI-COP-10-Partition-Copilot-History-by-Mode-with-Safe-Migration.md", + "ai-cop-10-partition-copilot-history-by-mode-with-safe-migration": "doc/knowledge/junie-tasks/AI-COP/AI-COP-10-Partition-Copilot-History-by-Mode-with-Safe-Migration.md", + "AI-COP-11-Add-Active-Mode-Banner-and-Context-Explainer": "doc/knowledge/junie-tasks/AI-COP/AI-COP-11-Add-Active-Mode-Banner-and-Context-Explainer.md", + "ai-cop-11-add-active-mode-banner-and-context-explainer": "doc/knowledge/junie-tasks/AI-COP/AI-COP-11-Add-Active-Mode-Banner-and-Context-Explainer.md", + "AI-COP-12-Registry-Based-Copilot-UseCase-Contract": "doc/knowledge/junie-tasks/AI-COP/AI-COP-12-Registry-Based-Copilot-UseCase-Contract.md", + "ai-cop-12-registry-based-copilot-usecase-contract": "doc/knowledge/junie-tasks/AI-COP/AI-COP-12-Registry-Based-Copilot-UseCase-Contract.md", + "AI-COP-13-Explicit-Retrieval-Policy-Manifest-for-Copilot-Modes": "doc/knowledge/junie-tasks/AI-COP/AI-COP-13-Explicit-Retrieval-Policy-Manifest-for-Copilot-Modes.md", + "ai-cop-13-explicit-retrieval-policy-manifest-for-copilot-modes": "doc/knowledge/junie-tasks/AI-COP/AI-COP-13-Explicit-Retrieval-Policy-Manifest-for-Copilot-Modes.md", + "AI-COP-14-Copilot-Response-Validation-and-Fallback-Normalization": "doc/knowledge/junie-tasks/AI-COP/AI-COP-14-Copilot-Response-Validation-and-Fallback-Normalization.md", + "ai-cop-14-copilot-response-validation-and-fallback-normalization": "doc/knowledge/junie-tasks/AI-COP/AI-COP-14-Copilot-Response-Validation-and-Fallback-Normalization.md", + "AI-COP-20-PR-AI-Review": "doc/knowledge/junie-tasks/AI-COP/AI-COP-20-PR-AI-Review.md", + "ai-cop-20-pr-ai-review": "doc/knowledge/junie-tasks/AI-COP/AI-COP-20-PR-AI-Review.md", + "AI-COP-21-PR-Comment-Generator": "doc/knowledge/junie-tasks/AI-COP/AI-COP-21-PR-Comment-Generator.md", + "ai-cop-21-pr-comment-generator": "doc/knowledge/junie-tasks/AI-COP/AI-COP-21-PR-Comment-Generator.md", + "AI-COP-22-Separate-Copilot-Workspaces": "doc/knowledge/junie-tasks/AI-COP/AI-COP-22-Separate-Copilot-Workspaces.md", + "ai-cop-22-separate-copilot-workspaces": "doc/knowledge/junie-tasks/AI-COP/AI-COP-22-Separate-Copilot-Workspaces.md", + "AI-DEC-01-AI-Decision-Assistant": "doc/knowledge/junie-tasks/AI-DEC/AI-DEC-01-AI-Decision-Assistant.md", + "ai-dec-01-ai-decision-assistant": "doc/knowledge/junie-tasks/AI-DEC/AI-DEC-01-AI-Decision-Assistant.md", + "AI-DOC-03-Document-Risk-Radar": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-03-Document-Risk-Radar.md", + "ai-doc-03-document-risk-radar": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-03-Document-Risk-Radar.md", + "AI-DOC-04-Navigation-Glossary": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-04-Navigation-Glossary.md", + "ai-doc-04-navigation-glossary": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-04-Navigation-Glossary.md", + "AI-DOC-07-Refine-Iteration-4-Mermaid-Diagrams": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-07-Refine-Iteration-4-Mermaid-Diagrams.md", + "ai-doc-07-refine-iteration-4-mermaid-diagrams": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-07-Refine-Iteration-4-Mermaid-Diagrams.md", + "AI-DOC-08-doc-consolidation": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-08-doc-consolidation.md", + "ai-doc-08-doc-consolidation": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-08-doc-consolidation.md", + "AI-DOC-09-ai-system-mental-model": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-09-ai-system-mental-model.md", + "ai-doc-09-ai-system-mental-model": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-09-ai-system-mental-model.md", + "AI-DOC-10-Regenerate-Documentation-From-Code-Reality": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-10-Regenerate-Documentation-From-Code-Reality.md", + "ai-doc-10-regenerate-documentation-from-code-reality": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-10-Regenerate-Documentation-From-Code-Reality.md", + "AI-DOC-11-architecture-inventory": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-11-architecture-inventory.md", + "ai-doc-11-architecture-inventory": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-11-architecture-inventory.md", + "AI-DOC-12-architecture-diagrams": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-12-architecture-diagrams.md", + "ai-doc-12-architecture-diagrams": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-12-architecture-diagrams.md", + "AI-DOC-13-generate-erd": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-13-generate-erd.md", + "ai-doc-13-generate-erd": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-13-generate-erd.md", + "AI-DOC-14-Refresh-Documentation-Links-and-References": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-14-Refresh-Documentation-Links-and-References.md", + "ai-doc-14-refresh-documentation-links-and-references": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-14-Refresh-Documentation-Links-and-References.md", + "AI-DOC-20-super-documentation-generator": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-20-super-documentation-generator.md", + "ai-doc-20-super-documentation-generator": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-20-super-documentation-generator.md", + "AI-DOC-21-Update-Iteration-4-Slide-Generation-Docs": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-21-Update-Iteration-4-Slide-Generation-Docs.md", + "ai-doc-21-update-iteration-4-slide-generation-docs": "doc/knowledge/junie-tasks/AI-DOC/AI-DOC-21-Update-Iteration-4-Slide-Generation-Docs.md", + "AI-DOC-INTEL-01-Document-dashboard-purpose-and-next-evolution-steps": "doc/knowledge/junie-tasks/AI-DOC-INTEL/AI-DOC-INTEL-01-Document-dashboard-purpose-and-next-evolution-steps.md", + "ai-doc-intel-01-document-dashboard-purpose-and-next-evolution-steps": "doc/knowledge/junie-tasks/AI-DOC-INTEL/AI-DOC-INTEL-01-Document-dashboard-purpose-and-next-evolution-steps.md", + "AI-EVAL-01 - Knowledge Retrieval Trace Logging": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-01 - Knowledge Retrieval Trace Logging.md", + "ai-eval-01 - knowledge retrieval trace logging": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-01 - Knowledge Retrieval Trace Logging.md", + "AI-EVAL-02 - Prompt Assembly Trace Logging": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-02 - Prompt Assembly Trace Logging.md", + "ai-eval-02 - prompt assembly trace logging": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-02 - Prompt Assembly Trace Logging.md", + "AI-EVAL-03 - Deterministic Retrieval Tests": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-03 - Deterministic Retrieval Tests.md", + "ai-eval-03 - deterministic retrieval tests": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-03 - Deterministic Retrieval Tests.md", + "AI-EVAL-04 - Ollama Local AI Test Runtime": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-04 - Ollama Local AI Test Runtime.md", + "ai-eval-04 - ollama local ai test runtime": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-04 - Ollama Local AI Test Runtime.md", + "AI-EVAL-05-AI-Benchmark-Dataset": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-05-AI-Benchmark-Dataset.md", + "ai-eval-05-ai-benchmark-dataset": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-05-AI-Benchmark-Dataset.md", + "AI-EVAL-06-AI-Answer-Evaluation-Engine": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-06-AI-Answer-Evaluation-Engine.md", + "ai-eval-06-ai-answer-evaluation-engine": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-06-AI-Answer-Evaluation-Engine.md", + "AI-EVAL-07-AI-Regression-Test-Suite": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-07-AI-Regression-Test-Suite.md", + "ai-eval-07-ai-regression-test-suite": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-07-AI-Regression-Test-Suite.md", + "AI-EVAL-08-Knowledge-Coverage-Analyzer": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-08-Knowledge-Coverage-Analyzer.md", + "ai-eval-08-knowledge-coverage-analyzer": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-08-Knowledge-Coverage-Analyzer.md", + "AI-EVAL-09-Backlog-Leakage-Detection": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-09-Backlog-Leakage-Detection.md", + "ai-eval-09-backlog-leakage-detection": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-09-Backlog-Leakage-Detection.md", + "AI-EVAL-10-Internal-AI-Trace-Viewer": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-10-Internal-AI-Trace-Viewer.md", + "ai-eval-10-internal-ai-trace-viewer": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-10-Internal-AI-Trace-Viewer.md", + "AI-EVAL-11-AI-Output-Evaluation-Framework": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-11-AI-Output-Evaluation-Framework.md", + "ai-eval-11-ai-output-evaluation-framework": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-11-AI-Output-Evaluation-Framework.md", + "AI-EVAL-12-AI-Regression-Test-Runner": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-12-AI-Regression-Test-Runner.md", + "ai-eval-12-ai-regression-test-runner": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-12-AI-Regression-Test-Runner.md", + "AI-EVAL-17 - Knowledge Test Dataset Generator": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-17 - Knowledge Test Dataset Generator.md", + "ai-eval-17 - knowledge test dataset generator": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-17 - Knowledge Test Dataset Generator.md", + "AI-EVAL-18 - Knowledge File Classification Rules": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-18 - Knowledge File Classification Rules.md", + "ai-eval-18 - knowledge file classification rules": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-18 - Knowledge File Classification Rules.md", + "AI-EVAL-19 - Generated Test Review Workflow": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-19 - Generated Test Review Workflow.md", + "ai-eval-19 - generated test review workflow": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-19 - Generated Test Review Workflow.md", + "AI-EVAL-20-Roadmap-vs-Current-State-Query-Split-Tests": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-20-Roadmap-vs-Current-State-Query-Split-Tests.md", + "ai-eval-20-roadmap-vs-current-state-query-split-tests": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-20-Roadmap-vs-Current-State-Query-Split-Tests.md", + "AI-EVAL-21-Retrieval-Coverage-Benchmark-Suite": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-21-Retrieval-Coverage-Benchmark-Suite.md", + "ai-eval-21-retrieval-coverage-benchmark-suite": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-21-Retrieval-Coverage-Benchmark-Suite.md", + "AI-EVAL-22-Stale-Knowledge-Coverage-Analyzer": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-22-Stale-Knowledge-Coverage-Analyzer.md", + "ai-eval-22-stale-knowledge-coverage-analyzer": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-22-Stale-Knowledge-Coverage-Analyzer.md", + "AI-EVAL-23-Provider-Consistency-Harness": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-23-Provider-Consistency-Harness.md", + "ai-eval-23-provider-consistency-harness": "doc/knowledge/junie-tasks/AI-EVAL/AI-EVAL-23-Provider-Consistency-Harness.md", + "AI-FE-30-unified-ai-trace-view": "doc/knowledge/junie-tasks/AI-FE/AI-FE-30-unified-ai-trace-view.md", + "ai-fe-30-unified-ai-trace-view": "doc/knowledge/junie-tasks/AI-FE/AI-FE-30-unified-ai-trace-view.md", + "AI-FE-31-tree-based-coverage-dashboard": "doc/knowledge/junie-tasks/AI-FE/AI-FE-31-tree-based-coverage-dashboard.md", + "ai-fe-31-tree-based-coverage-dashboard": "doc/knowledge/junie-tasks/AI-FE/AI-FE-31-tree-based-coverage-dashboard.md", + "AI-FE-32-document-detail-panel": "doc/knowledge/junie-tasks/AI-FE/AI-FE-32-document-detail-panel.md", + "ai-fe-32-document-detail-panel": "doc/knowledge/junie-tasks/AI-FE/AI-FE-32-document-detail-panel.md", + "AI-FE-33-coverage-filter-controls": "doc/knowledge/junie-tasks/AI-FE/AI-FE-33-coverage-filter-controls.md", + "ai-fe-33-coverage-filter-controls": "doc/knowledge/junie-tasks/AI-FE/AI-FE-33-coverage-filter-controls.md", + "AI-FE-34-branch-coverage-heatmap-refinement": "doc/knowledge/junie-tasks/AI-FE/AI-FE-34-branch-coverage-heatmap-refinement.md", + "ai-fe-34-branch-coverage-heatmap-refinement": "doc/knowledge/junie-tasks/AI-FE/AI-FE-34-branch-coverage-heatmap-refinement.md", + "AI-FIX-01-Fix-AI-Parsing-Hallucinations": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-01-Fix-AI-Parsing-Hallucinations.md", + "ai-fix-01-fix-ai-parsing-hallucinations": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-01-Fix-AI-Parsing-Hallucinations.md", + "AI-FIX-02-Ollama-Octet-Stream-Extraction": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-02-Ollama-Octet-Stream-Extraction.md", + "ai-fix-02-ollama-octet-stream-extraction": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-02-Ollama-Octet-Stream-Extraction.md", + "AI-FIX-03-Sprint-Selection-Automation": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-03-Sprint-Selection-Automation.md", + "ai-fix-03-sprint-selection-automation": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-03-Sprint-Selection-Automation.md", + "AI-FIX-04-Engineering-Chat-Response-Visibility": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-04-Engineering-Chat-Response-Visibility.md", + "ai-fix-04-engineering-chat-response-visibility": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-04-Engineering-Chat-Response-Visibility.md", + "AI-FIX-05-AiController-Syntax-and-Jackson-Fix": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-05-AiController-Syntax-and-Jackson-Fix.md", + "ai-fix-05-aicontroller-syntax-and-jackson-fix": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-05-AiController-Syntax-and-Jackson-Fix.md", + "AI-FIX-06-Checkstyle-Warnings-Backend": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-06-Checkstyle-Warnings-Backend.md", + "ai-fix-06-checkstyle-warnings-backend": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-06-Checkstyle-Warnings-Backend.md", + "AI-FIX-07-AI-Trace-Observability-and-Regression-Resilience": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-07-AI-Trace-Observability-and-Regression-Resilience.md", + "ai-fix-07-ai-trace-observability-and-regression-resilience": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-07-AI-Trace-Observability-and-Regression-Resilience.md", + "AI-FIX-08-Session-Invalidation-Robustness": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-08-Session-Invalidation-Robustness.md", + "ai-fix-08-session-invalidation-robustness": "doc/knowledge/junie-tasks/AI-FIX/AI-FIX-08-Session-Invalidation-Robustness.md", + "AI-GOV-01-Sprint-1.7-Task-Normalization": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-01-Sprint-1.7-Task-Normalization.md", + "ai-gov-01-sprint-1.7-task-normalization": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-01-Sprint-1.7-Task-Normalization.md", + "AI-GOV-02-Introduce-Task-Contract-Standard": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-02-Introduce-Task-Contract-Standard.md", + "ai-gov-02-introduce-task-contract-standard": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-02-Introduce-Task-Contract-Standard.md", + "AI-GOV-03-Enforce-Task-Contract-in-CI": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-03-Enforce-Task-Contract-in-CI.md", + "ai-gov-03-enforce-task-contract-in-ci": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-03-Enforce-Task-Contract-in-CI.md", + "AI-GOV-06-context-isolation-rules": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-06-context-isolation-rules.md", + "ai-gov-06-context-isolation-rules": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-06-context-isolation-rules.md", + "AI-GOV-07-prompt-registry-versioning": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-07-prompt-registry-versioning.md", + "ai-gov-07-prompt-registry-versioning": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-07-prompt-registry-versioning.md", + "AI-GOV-08-response-validation-layer": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-08-response-validation-layer.md", + "ai-gov-08-response-validation-layer": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-08-response-validation-layer.md", + "AI-GOV-10-Guardrails-Validator-Script": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-10-Guardrails-Validator-Script.md", + "ai-gov-10-guardrails-validator-script": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-10-Guardrails-Validator-Script.md", + "AI-GOV-11-CI-Enforcement-Integration": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-11-CI-Enforcement-Integration.md", + "ai-gov-11-ci-enforcement-integration": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-11-CI-Enforcement-Integration.md", + "AI-GOV-12-Auto-Fix-on-PR": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-12-Auto-Fix-on-PR.md", + "ai-gov-12-auto-fix-on-pr": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-12-Auto-Fix-on-PR.md", + "AI-GOV-13-Task-Refactoring-Engine": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-13-Task-Refactoring-Engine.md", + "ai-gov-13-task-refactoring-engine": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-13-Task-Refactoring-Engine.md", + "AI-GOV-14-Prompt-Manifest-Version-Inventory-and-Integrity-Test": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-14-Prompt-Manifest-Version-Inventory-and-Integrity-Test.md", + "ai-gov-14-prompt-manifest-version-inventory-and-integrity-test": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-14-Prompt-Manifest-Version-Inventory-and-Integrity-Test.md", + "AI-GOV-15-Benchmark-Query-Registry": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-15-Benchmark-Query-Registry.md", + "ai-gov-15-benchmark-query-registry": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-15-Benchmark-Query-Registry.md", + "AI-GOV-20-Guardrails-Enforcement-Metrics": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-20-Guardrails-Enforcement-Metrics.md", + "ai-gov-20-guardrails-enforcement-metrics": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-20-Guardrails-Enforcement-Metrics.md", + "AI-GOV-21-Guardrails-Exception-Tracking": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-21-Guardrails-Exception-Tracking.md", + "ai-gov-21-guardrails-exception-tracking": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-21-Guardrails-Exception-Tracking.md", + "AI-GOV-22-Task-Auto-Linking": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-22-Task-Auto-Linking.md", + "ai-gov-22-task-auto-linking": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-22-Task-Auto-Linking.md", + "AI-GOV-23-Autofix-CLI-Integration": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-23-Autofix-CLI-Integration.md", + "ai-gov-23-autofix-cli-integration": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-23-Autofix-CLI-Integration.md", + "AI-GOV-24-Autofix-CI-Mode": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-24-Autofix-CI-Mode.md", + "ai-gov-24-autofix-ci-mode": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-24-Autofix-CI-Mode.md", + "AI-GOV-25-Autofix-Safe-Commit-Mode": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-25-Autofix-Safe-Commit-Mode.md", + "ai-gov-25-autofix-safe-commit-mode": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-25-Autofix-Safe-Commit-Mode.md", + "AI-GOV-30-ai-failure-detection": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-30-ai-failure-detection.md", + "ai-gov-30-ai-failure-detection": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-30-ai-failure-detection.md", + "AI-GOV-31-auto-retry-strategy": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-31-auto-retry-strategy.md", + "ai-gov-31-auto-retry-strategy": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-31-auto-retry-strategy.md", + "AI-GOV-32-ai-quality-score": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-32-ai-quality-score.md", + "ai-gov-32-ai-quality-score": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-32-ai-quality-score.md", + "AI-GOV-33-schema-validation-gate": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-33-schema-validation-gate.md", + "ai-gov-33-schema-validation-gate": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-33-schema-validation-gate.md", + "AI-GOV-34-Implement-Traceability-Governance": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-34-Implement-Traceability-Governance.md", + "ai-gov-34-implement-traceability-governance": "doc/knowledge/junie-tasks/AI-GOV/AI-GOV-34-Implement-Traceability-Governance.md", + "AI-IMP-01-AI-Impact-Simulator": "doc/knowledge/junie-tasks/AI-IMP/AI-IMP-01-AI-Impact-Simulator.md", + "ai-imp-01-ai-impact-simulator": "doc/knowledge/junie-tasks/AI-IMP/AI-IMP-01-AI-Impact-Simulator.md", + "AI-IMP-02-Impact-Simulator-v2-on-Signals-and-Task-Graph": "doc/knowledge/junie-tasks/AI-IMP/AI-IMP-02-Impact-Simulator-v2-on-Signals-and-Task-Graph.md", + "ai-imp-02-impact-simulator-v2-on-signals-and-task-graph": "doc/knowledge/junie-tasks/AI-IMP/AI-IMP-02-Impact-Simulator-v2-on-Signals-and-Task-Graph.md", + "AI-INFRA-01 - Local Docker Runtime for PostgreSQL": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-01 - Local Docker Runtime for PostgreSQL.md", + "ai-infra-01 - local docker runtime for postgresql": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-01 - Local Docker Runtime for PostgreSQL.md", + "AI-INFRA-02 - OpenAI Runtime Configuration": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-02 - OpenAI Runtime Configuration.md", + "ai-infra-02 - openai runtime configuration": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-02 - OpenAI Runtime Configuration.md", + "AI-INFRA-03-Ollama-Local-Runtime-Integration": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-03-Ollama-Local-Runtime-Integration.md", + "ai-infra-03-ollama-local-runtime-integration": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-03-Ollama-Local-Runtime-Integration.md", + "AI-INFRA-04 - Fargate Demo Deployment Variant": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-04 - Fargate Demo Deployment Variant.md", + "ai-infra-04 - fargate demo deployment variant": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-04 - Fargate Demo Deployment Variant.md", + "AI-INFRA-05 - Multi-Model Routing Layer": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-05 - Multi-Model Routing Layer.md", + "ai-infra-05 - multi-model routing layer": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-05 - Multi-Model Routing Layer.md", + "AI-INFRA-06-AI-Response-Cache-Layer": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-06-AI-Response-Cache-Layer.md", + "ai-infra-06-ai-response-cache-layer": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-06-AI-Response-Cache-Layer.md", + "AI-INFRA-06B-Ollama-Docker-Performance-Profile-and-Fast-Path": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-06B-Ollama-Docker-Performance-Profile-and-Fast-Path.md", + "ai-infra-06b-ollama-docker-performance-profile-and-fast-path": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-06B-Ollama-Docker-Performance-Profile-and-Fast-Path.md", + "AI-INFRA-06H-Host-Run-Ollama-Setup-and-Fast-Local-Profile": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-06H-Host-Run-Ollama-Setup-and-Fast-Local-Profile.md", + "ai-infra-06h-host-run-ollama-setup-and-fast-local-profile": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-06H-Host-Run-Ollama-Setup-and-Fast-Local-Profile.md", + "AI-INFRA-07-Knowledge-Index-Filter": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-07-Knowledge-Index-Filter.md", + "ai-infra-07-knowledge-index-filter": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-07-Knowledge-Index-Filter.md", + "AI-INFRA-10-AI-Traces-Fargate-Persistence": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-10-AI-Traces-Fargate-Persistence.md", + "ai-infra-10-ai-traces-fargate-persistence": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-10-AI-Traces-Fargate-Persistence.md", + "AI-INFRA-11-Configure-Alternative-Domains": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-11-Configure-Alternative-Domains.md", + "ai-infra-11-configure-alternative-domains": "doc/knowledge/junie-tasks/AI-INFRA/AI-INFRA-11-Configure-Alternative-Domains.md", + "AI-INT-01-Canonical-Engineering-Signal-Model": "doc/knowledge/junie-tasks/AI-INT/AI-INT-01-Canonical-Engineering-Signal-Model.md", + "ai-int-01-canonical-engineering-signal-model": "doc/knowledge/junie-tasks/AI-INT/AI-INT-01-Canonical-Engineering-Signal-Model.md", + "AI-INT-02-Intelligence-Aggregation-Service-Extraction": "doc/knowledge/junie-tasks/AI-INT/AI-INT-02-Intelligence-Aggregation-Service-Extraction.md", + "ai-int-02-intelligence-aggregation-service-extraction": "doc/knowledge/junie-tasks/AI-INT/AI-INT-02-Intelligence-Aggregation-Service-Extraction.md", + "AI-INT-03-Shared-Engineering-Taxonomy-and-Vocabularies": "doc/knowledge/junie-tasks/AI-INT/AI-INT-03-Shared-Engineering-Taxonomy-and-Vocabularies.md", + "ai-int-03-shared-engineering-taxonomy-and-vocabularies": "doc/knowledge/junie-tasks/AI-INT/AI-INT-03-Shared-Engineering-Taxonomy-and-Vocabularies.md", + "AI-INTEL-01-Define-dashboard-scope-and-data-contract": "doc/knowledge/junie-tasks/AI-INTEL/AI-INTEL-01-Define-dashboard-scope-and-data-contract.md", + "ai-intel-01-define-dashboard-scope-and-data-contract": "doc/knowledge/junie-tasks/AI-INTEL/AI-INTEL-01-Define-dashboard-scope-and-data-contract.md", + "AI-KNOW-20-Knowledge-Gap-Detector": "doc/knowledge/junie-tasks/AI-KNOW/AI-KNOW-20-Knowledge-Gap-Detector.md", + "ai-know-20-knowledge-gap-detector": "doc/knowledge/junie-tasks/AI-KNOW/AI-KNOW-20-Knowledge-Gap-Detector.md", + "AI-OBS-01 - Grafana AI Usage Dashboard": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-01 - Grafana AI Usage Dashboard.md", + "ai-obs-01 - grafana ai usage dashboard": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-01 - Grafana AI Usage Dashboard.md", + "AI-OBS-02-Add-AI-Cost-Dashboard-Metrics": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-02-Add-AI-Cost-Dashboard-Metrics.md", + "ai-obs-02-add-ai-cost-dashboard-metrics": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-02-Add-AI-Cost-Dashboard-Metrics.md", + "AI-OBS-03-Add-AI-Latency-Monitoring": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-03-Add-AI-Latency-Monitoring.md", + "ai-obs-03-add-ai-latency-monitoring": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-03-Add-AI-Latency-Monitoring.md", + "AI-OBS-04-AI-Trace-Viewer": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-04-AI-Trace-Viewer.md", + "ai-obs-04-ai-trace-viewer": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-04-AI-Trace-Viewer.md", + "AI-OBS-04A-Copilot-and-Intelligence-Diagnostics": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-04A-Copilot-and-Intelligence-Diagnostics.md", + "ai-obs-04a-copilot-and-intelligence-diagnostics": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-04A-Copilot-and-Intelligence-Diagnostics.md", + "AI-OBS-05-failure-visibility": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-05-failure-visibility.md", + "ai-obs-05-failure-visibility": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-05-failure-visibility.md", + "AI-OBS-06-Enrich-AI-Traces-with-Capability-and-Context-Filters": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-06-Enrich-AI-Traces-with-Capability-and-Context-Filters.md", + "ai-obs-06-enrich-ai-traces-with-capability-and-context-filters": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-06-Enrich-AI-Traces-with-Capability-and-Context-Filters.md", + "AI-OBS-07-Retrieval-Usage-Telemetry": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-07-Retrieval-Usage-Telemetry.md", + "ai-obs-07-retrieval-usage-telemetry": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-07-Retrieval-Usage-Telemetry.md", + "AI-OBS-08-Knowledge-Branch-Coverage-Dashboard": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-08-Knowledge-Branch-Coverage-Dashboard.md", + "ai-obs-08-knowledge-branch-coverage-dashboard": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-08-Knowledge-Branch-Coverage-Dashboard.md", + "AI-OBS-20-trace-and-coverage-verification": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-20-trace-and-coverage-verification.md", + "ai-obs-20-trace-and-coverage-verification": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-20-trace-and-coverage-verification.md", + "AI-OBS-21-trace-correlation": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-21-trace-correlation.md", + "ai-obs-21-trace-correlation": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-21-trace-correlation.md", + "AI-OBS-22-Intelligence-Endpoint-SLOs-and-Performance-Observability": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-22-Intelligence-Endpoint-SLOs-and-Performance-Observability.md", + "ai-obs-22-intelligence-endpoint-slos-and-performance-observability": "doc/knowledge/junie-tasks/AI-OBS/AI-OBS-22-Intelligence-Endpoint-SLOs-and-Performance-Observability.md", + "AI-OPS-01-AI-Health-Monitoring": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-01-AI-Health-Monitoring.md", + "ai-ops-01-ai-health-monitoring": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-01-AI-Health-Monitoring.md", + "AI-OPS-01A-Stabilize-Intelligence-Dashboard-Streaming-and-Partial-Results": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-01A-Stabilize-Intelligence-Dashboard-Streaming-and-Partial-Results.md", + "ai-ops-01a-stabilize-intelligence-dashboard-streaming-and-partial-results": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-01A-Stabilize-Intelligence-Dashboard-Streaming-and-Partial-Results.md", + "AI-OPS-01H-Hotfix-epics-intelligence-stream-timeout-and-late-emitter-failures": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-01H-Hotfix-epics-intelligence-stream-timeout-and-late-emitter-failures.md", + "ai-ops-01h-hotfix-epics-intelligence-stream-timeout-and-late-emitter-failures": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-01H-Hotfix-epics-intelligence-stream-timeout-and-late-emitter-failures.md", + "AI-OPS-10-merge-master-and-rebrand-to-angularai": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-10-merge-master-and-rebrand-to-angularai.md", + "ai-ops-10-merge-master-and-rebrand-to-angularai": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-10-merge-master-and-rebrand-to-angularai.md", + "AI-OPS-11-adaptive-model-routing": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-11-adaptive-model-routing.md", + "ai-ops-11-adaptive-model-routing": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-11-adaptive-model-routing.md", + "AI-OPS-12-ollama-latency-benchmark": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-12-ollama-latency-benchmark.md", + "ai-ops-12-ollama-latency-benchmark": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-12-ollama-latency-benchmark.md", + "AI-OPS-22-Fargate-Readiness-2.2": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-22-Fargate-Readiness-2.2.md", + "ai-ops-22-fargate-readiness-2.2": "doc/knowledge/junie-tasks/AI-OPS/AI-OPS-22-Fargate-Readiness-2.2.md", + "AI-PERF-01-Ollama-Host-Optimization": "doc/knowledge/junie-tasks/AI-PERF/AI-PERF-01-Ollama-Host-Optimization.md", + "ai-perf-01-ollama-host-optimization": "doc/knowledge/junie-tasks/AI-PERF/AI-PERF-01-Ollama-Host-Optimization.md", + "AI-PLAN-20-Backlog-Grooming-Assistant": "doc/knowledge/junie-tasks/AI-PLAN/AI-PLAN-20-Backlog-Grooming-Assistant.md", + "ai-plan-20-backlog-grooming-assistant": "doc/knowledge/junie-tasks/AI-PLAN/AI-PLAN-20-Backlog-Grooming-Assistant.md", + "AI-PLAN-21-Task-Breakdown-Generator": "doc/knowledge/junie-tasks/AI-PLAN/AI-PLAN-21-Task-Breakdown-Generator.md", + "ai-plan-21-task-breakdown-generator": "doc/knowledge/junie-tasks/AI-PLAN/AI-PLAN-21-Task-Breakdown-Generator.md", + "AI-PLAN-50-sprint-2.1-proper-stabilization-plan": "doc/knowledge/junie-tasks/AI-PLAN/AI-PLAN-50-sprint-2.1-proper-stabilization-plan.md", + "ai-plan-50-sprint-2.1-proper-stabilization-plan": "doc/knowledge/junie-tasks/AI-PLAN/AI-PLAN-50-sprint-2.1-proper-stabilization-plan.md", + "AI-PLAN-51-sprint-2.1-execution-order": "doc/knowledge/junie-tasks/AI-PLAN/AI-PLAN-51-sprint-2.1-execution-order.md", + "ai-plan-51-sprint-2.1-execution-order": "doc/knowledge/junie-tasks/AI-PLAN/AI-PLAN-51-sprint-2.1-execution-order.md", + "AI-PLAN-52-sprint-2.1-definition-of-done": "doc/knowledge/junie-tasks/AI-PLAN/AI-PLAN-52-sprint-2.1-definition-of-done.md", + "ai-plan-52-sprint-2.1-definition-of-done": "doc/knowledge/junie-tasks/AI-PLAN/AI-PLAN-52-sprint-2.1-definition-of-done.md", + "AI-PLAN-53-sprint-2.1-demo-risk-checklist": "doc/knowledge/junie-tasks/AI-PLAN/AI-PLAN-53-sprint-2.1-demo-risk-checklist.md", + "ai-plan-53-sprint-2.1-demo-risk-checklist": "doc/knowledge/junie-tasks/AI-PLAN/AI-PLAN-53-sprint-2.1-demo-risk-checklist.md", + "AI-QA-01-full-ai-regression-suite": "doc/knowledge/junie-tasks/AI-QA/AI-QA-01-full-ai-regression-suite.md", + "ai-qa-01-full-ai-regression-suite": "doc/knowledge/junie-tasks/AI-QA/AI-QA-01-full-ai-regression-suite.md", + "AI-QA-02-test-results-html-index": "doc/knowledge/junie-tasks/AI-QA/AI-QA-02-test-results-html-index.md", + "ai-qa-02-test-results-html-index": "doc/knowledge/junie-tasks/AI-QA/AI-QA-02-test-results-html-index.md", + "AI-QA-10-deterministic-regression-runner": "doc/knowledge/junie-tasks/AI-QA/AI-QA-10-deterministic-regression-runner.md", + "ai-qa-10-deterministic-regression-runner": "doc/knowledge/junie-tasks/AI-QA/AI-QA-10-deterministic-regression-runner.md", + "AI-QA-11-snapshot-baseline-system": "doc/knowledge/junie-tasks/AI-QA/AI-QA-11-snapshot-baseline-system.md", + "ai-qa-11-snapshot-baseline-system": "doc/knowledge/junie-tasks/AI-QA/AI-QA-11-snapshot-baseline-system.md", + "AI-QA-12-regression-matrix": "doc/knowledge/junie-tasks/AI-QA/AI-QA-12-regression-matrix.md", + "ai-qa-12-regression-matrix": "doc/knowledge/junie-tasks/AI-QA/AI-QA-12-regression-matrix.md", + "AI-QA-13-test-reporting": "doc/knowledge/junie-tasks/AI-QA/AI-QA-13-test-reporting.md", + "ai-qa-13-test-reporting": "doc/knowledge/junie-tasks/AI-QA/AI-QA-13-test-reporting.md", + "AI-QA-20-demo-scenario-freeze": "doc/knowledge/junie-tasks/AI-QA/AI-QA-20-demo-scenario-freeze.md", + "ai-qa-20-demo-scenario-freeze": "doc/knowledge/junie-tasks/AI-QA/AI-QA-20-demo-scenario-freeze.md", + "AI-QA-21-golden-output-snapshots": "doc/knowledge/junie-tasks/AI-QA/AI-QA-21-golden-output-snapshots.md", + "ai-qa-21-golden-output-snapshots": "doc/knowledge/junie-tasks/AI-QA/AI-QA-21-golden-output-snapshots.md", + "AI-QA-22-playwright-deterministic-tests": "doc/knowledge/junie-tasks/AI-QA/AI-QA-22-playwright-deterministic-tests.md", + "ai-qa-22-playwright-deterministic-tests": "doc/knowledge/junie-tasks/AI-QA/AI-QA-22-playwright-deterministic-tests.md", + "AI-QA-23-regression-dataset": "doc/knowledge/junie-tasks/AI-QA/AI-QA-23-regression-dataset.md", + "ai-qa-23-regression-dataset": "doc/knowledge/junie-tasks/AI-QA/AI-QA-23-regression-dataset.md", + "AI-REL-01-AI-Release-Intelligence": "doc/knowledge/junie-tasks/AI-REL/AI-REL-01-AI-Release-Intelligence.md", + "ai-rel-01-ai-release-intelligence": "doc/knowledge/junie-tasks/AI-REL/AI-REL-01-AI-Release-Intelligence.md", + "AI-REL-02-align-static-analysis-rules": "doc/knowledge/junie-tasks/AI-REL/AI-REL-02-align-static-analysis-rules.md", + "ai-rel-02-align-static-analysis-rules": "doc/knowledge/junie-tasks/AI-REL/AI-REL-02-align-static-analysis-rules.md", + "AI-REL-03-sonar-major-fix-loop": "doc/knowledge/junie-tasks/AI-REL/AI-REL-03-sonar-major-fix-loop.md", + "ai-rel-03-sonar-major-fix-loop": "doc/knowledge/junie-tasks/AI-REL/AI-REL-03-sonar-major-fix-loop.md", + "AI-REL-04-frontend-sonar-major-fix-loop": "doc/knowledge/junie-tasks/AI-REL/AI-REL-04-frontend-sonar-major-fix-loop.md", + "ai-rel-04-frontend-sonar-major-fix-loop": "doc/knowledge/junie-tasks/AI-REL/AI-REL-04-frontend-sonar-major-fix-loop.md", + "AI-REL-05-sonar-remediation-process": "doc/knowledge/junie-tasks/AI-REL/AI-REL-05-sonar-remediation-process.md", + "ai-rel-05-sonar-remediation-process": "doc/knowledge/junie-tasks/AI-REL/AI-REL-05-sonar-remediation-process.md", + "AI-REL-06-release-stabilization": "doc/knowledge/junie-tasks/AI-REL/AI-REL-06-release-stabilization.md", + "ai-rel-06-release-stabilization": "doc/knowledge/junie-tasks/AI-REL/AI-REL-06-release-stabilization.md", + "AI-REL-07-Release-Intelligence-v2-on-Canonical-Signals": "doc/knowledge/junie-tasks/AI-REL/AI-REL-07-Release-Intelligence-v2-on-Canonical-Signals.md", + "ai-rel-07-release-intelligence-v2-on-canonical-signals": "doc/knowledge/junie-tasks/AI-REL/AI-REL-07-Release-Intelligence-v2-on-Canonical-Signals.md", + "AI-RETRO-01-AI-Retrospective-Generator": "doc/knowledge/junie-tasks/AI-RETRO/AI-RETRO-01-AI-Retrospective-Generator.md", + "ai-retro-01-ai-retrospective-generator": "doc/knowledge/junie-tasks/AI-RETRO/AI-RETRO-01-AI-Retrospective-Generator.md", + "AI-RETRO-02-AI-Risk-Radar": "doc/knowledge/junie-tasks/AI-RETRO/AI-RETRO-02-AI-Risk-Radar.md", + "ai-retro-02-ai-risk-radar": "doc/knowledge/junie-tasks/AI-RETRO/AI-RETRO-02-AI-Risk-Radar.md", + "AI-RETRO-03-ADR-Drift-Detector": "doc/knowledge/junie-tasks/AI-RETRO/AI-RETRO-03-ADR-Drift-Detector.md", + "ai-retro-03-adr-drift-detector": "doc/knowledge/junie-tasks/AI-RETRO/AI-RETRO-03-ADR-Drift-Detector.md", + "AI-SONAR-EXPORT-LOOP": "doc/knowledge/junie-tasks/AI-SONAR/AI-SONAR-EXPORT-LOOP.md", + "ai-sonar-export-loop": "doc/knowledge/junie-tasks/AI-SONAR/AI-SONAR-EXPORT-LOOP.md", + "AI-SONAR-JUNIE-V2": "doc/knowledge/junie-tasks/AI-SONAR/AI-SONAR-JUNIE-V2.md", + "ai-sonar-junie-v2": "doc/knowledge/junie-tasks/AI-SONAR/AI-SONAR-JUNIE-V2.md", + "AI-SPR-01-Sprint-Risk-Predictor": "doc/knowledge/junie-tasks/AI-SPR/AI-SPR-01-Sprint-Risk-Predictor.md", + "ai-spr-01-sprint-risk-predictor": "doc/knowledge/junie-tasks/AI-SPR/AI-SPR-01-Sprint-Risk-Predictor.md", + "AI-SPR-02 - Delivery Forecast": "doc/knowledge/junie-tasks/AI-SPR/AI-SPR-02 - Delivery Forecast.md", + "ai-spr-02 - delivery forecast": "doc/knowledge/junie-tasks/AI-SPR/AI-SPR-02 - Delivery Forecast.md", + "AI-SPR-03-Sprint-Health-Predictor": "doc/knowledge/junie-tasks/AI-SPR/AI-SPR-03-Sprint-Health-Predictor.md", + "ai-spr-03-sprint-health-predictor": "doc/knowledge/junie-tasks/AI-SPR/AI-SPR-03-Sprint-Health-Predictor.md", + "AI-SPR-03R-Delivery-Forecast-Evidence-Contract-and-Calibration": "doc/knowledge/junie-tasks/AI-SPR/AI-SPR-03R-Delivery-Forecast-Evidence-Contract-and-Calibration.md", + "ai-spr-03r-delivery-forecast-evidence-contract-and-calibration": "doc/knowledge/junie-tasks/AI-SPR/AI-SPR-03R-Delivery-Forecast-Evidence-Contract-and-Calibration.md", + "AI-SPR-04-Sprint-1.8-Reconciliation-Assessment": "doc/knowledge/junie-tasks/AI-SPR/AI-SPR-04-Sprint-1.8-Reconciliation-Assessment.md", + "ai-spr-04-sprint-1.8-reconciliation-assessment": "doc/knowledge/junie-tasks/AI-SPR/AI-SPR-04-Sprint-1.8-Reconciliation-Assessment.md", + "AI-SPR-05-Sprint-1.8-Completion-Assessment": "doc/knowledge/junie-tasks/AI-SPR/AI-SPR-05-Sprint-1.8-Completion-Assessment.md", + "ai-spr-05-sprint-1.8-completion-assessment": "doc/knowledge/junie-tasks/AI-SPR/AI-SPR-05-Sprint-1.8-Completion-Assessment.md", + "AI-SYS-01-update-system-prompt-guidelines": "doc/knowledge/junie-tasks/AI-SYS/AI-SYS-01-update-system-prompt-guidelines.md", + "ai-sys-01-update-system-prompt-guidelines": "doc/knowledge/junie-tasks/AI-SYS/AI-SYS-01-update-system-prompt-guidelines.md", + "AI-TEST-01-Copilot-Regression": "doc/knowledge/junie-tasks/AI-TEST/AI-TEST-01-Copilot-Regression.md", + "ai-test-01-copilot-regression": "doc/knowledge/junie-tasks/AI-TEST/AI-TEST-01-Copilot-Regression.md", + "AI-TEST-23-sonar-frontend-coverage-and-threshold": "doc/knowledge/junie-tasks/AI-TEST/AI-TEST-23-sonar-frontend-coverage-and-threshold.md", + "ai-test-23-sonar-frontend-coverage-and-threshold": "doc/knowledge/junie-tasks/AI-TEST/AI-TEST-23-sonar-frontend-coverage-and-threshold.md", + "AI-TEST-50-schema-contract-tests": "doc/knowledge/junie-tasks/AI-TEST/AI-TEST-50-schema-contract-tests.md", + "ai-test-50-schema-contract-tests": "doc/knowledge/junie-tasks/AI-TEST/AI-TEST-50-schema-contract-tests.md", + "AI-TEST-51-provider-integration-tests": "doc/knowledge/junie-tasks/AI-TEST/AI-TEST-51-provider-integration-tests.md", + "ai-test-51-provider-integration-tests": "doc/knowledge/junie-tasks/AI-TEST/AI-TEST-51-provider-integration-tests.md", + "AI-TEST-52-deterministic-regression-suite": "doc/knowledge/junie-tasks/AI-TEST/AI-TEST-52-deterministic-regression-suite.md", + "ai-test-52-deterministic-regression-suite": "doc/knowledge/junie-tasks/AI-TEST/AI-TEST-52-deterministic-regression-suite.md", + "AI-UI-01-Debounce-Quick-Add-AI-Parsing": "doc/knowledge/junie-tasks/AI-UI/AI-UI-01-Debounce-Quick-Add-AI-Parsing.md", + "ai-ui-01-debounce-quick-add-ai-parsing": "doc/knowledge/junie-tasks/AI-UI/AI-UI-01-Debounce-Quick-Add-AI-Parsing.md", + "AI-UI-02-Split-Architecture-and-Architecture-Demo-Routes": "doc/knowledge/junie-tasks/AI-UI/AI-UI-02-Split-Architecture-and-Architecture-Demo-Routes.md", + "ai-ui-02-split-architecture-and-architecture-demo-routes": "doc/knowledge/junie-tasks/AI-UI/AI-UI-02-Split-Architecture-and-Architecture-Demo-Routes.md", + "AI-UI-03-Improve-Architecture-QA-Answer-Formatting": "doc/knowledge/junie-tasks/AI-UI/AI-UI-03-Improve-Architecture-QA-Answer-Formatting.md", + "ai-ui-03-improve-architecture-qa-answer-formatting": "doc/knowledge/junie-tasks/AI-UI/AI-UI-03-Improve-Architecture-QA-Answer-Formatting.md", + "AI-UI-04-Refine-AI-Features-Grid-Layout": "doc/knowledge/junie-tasks/AI-UI/AI-UI-04-Refine-AI-Features-Grid-Layout.md", + "ai-ui-04-refine-ai-features-grid-layout": "doc/knowledge/junie-tasks/AI-UI/AI-UI-04-Refine-AI-Features-Grid-Layout.md", + "AI-UI-05 - Improve Risk Radar Visual Hierarchy": "doc/knowledge/junie-tasks/AI-UI/AI-UI-05 - Improve Risk Radar Visual Hierarchy.md", + "ai-ui-05 - improve risk radar visual hierarchy": "doc/knowledge/junie-tasks/AI-UI/AI-UI-05 - Improve Risk Radar Visual Hierarchy.md", + "AI-UI-06 - Improve Retrospective Summary Card Layout": "doc/knowledge/junie-tasks/AI-UI/AI-UI-06 - Improve Retrospective Summary Card Layout.md", + "ai-ui-06 - improve retrospective summary card layout": "doc/knowledge/junie-tasks/AI-UI/AI-UI-06 - Improve Retrospective Summary Card Layout.md", + "AI-UI-07-Improve-Intelligence-Dashboard-Loading-State": "doc/knowledge/junie-tasks/AI-UI/AI-UI-07-Improve-Intelligence-Dashboard-Loading-State.md", + "ai-ui-07-improve-intelligence-dashboard-loading-state": "doc/knowledge/junie-tasks/AI-UI/AI-UI-07-Improve-Intelligence-Dashboard-Loading-State.md", + "AI-UI-08-Increase-Copilot-Header-Font-Size": "doc/knowledge/junie-tasks/AI-UI/AI-UI-08-Increase-Copilot-Header-Font-Size.md", + "ai-ui-08-increase-copilot-header-font-size": "doc/knowledge/junie-tasks/AI-UI/AI-UI-08-Increase-Copilot-Header-Font-Size.md", + "AI-UI-09-Refine-Onboarding-Assistant-UX": "doc/knowledge/junie-tasks/AI-UI/AI-UI-09-Refine-Onboarding-Assistant-UX.md", + "ai-ui-09-refine-onboarding-assistant-ux": "doc/knowledge/junie-tasks/AI-UI/AI-UI-09-Refine-Onboarding-Assistant-UX.md", + "AI-UI-10-Refine-Copilot-Markdown-Formatting": "doc/knowledge/junie-tasks/AI-UI/AI-UI-10-Refine-Copilot-Markdown-Formatting.md", + "ai-ui-10-refine-copilot-markdown-formatting": "doc/knowledge/junie-tasks/AI-UI/AI-UI-10-Refine-Copilot-Markdown-Formatting.md", + "AI-UI-11-Make-Copilot-Evidence-Navigable": "doc/knowledge/junie-tasks/AI-UI/AI-UI-11-Make-Copilot-Evidence-Navigable.md", + "ai-ui-11-make-copilot-evidence-navigable": "doc/knowledge/junie-tasks/AI-UI/AI-UI-11-Make-Copilot-Evidence-Navigable.md", + "AI-UI-12-Fix-Copilot-Help-Links-and-Metadata-Formatting": "doc/knowledge/junie-tasks/AI-UI/AI-UI-12-Fix-Copilot-Help-Links-and-Metadata-Formatting.md", + "ai-ui-12-fix-copilot-help-links-and-metadata-formatting": "doc/knowledge/junie-tasks/AI-UI/AI-UI-12-Fix-Copilot-Help-Links-and-Metadata-Formatting.md", + "AI-UI-13-Restore-Copilot-Metadata-On-Refresh": "doc/knowledge/junie-tasks/AI-UI/AI-UI-13-Restore-Copilot-Metadata-On-Refresh.md", + "ai-ui-13-restore-copilot-metadata-on-refresh": "doc/knowledge/junie-tasks/AI-UI/AI-UI-13-Restore-Copilot-Metadata-On-Refresh.md", + "AI-UI-COPILOT-SECTION-CONTEXT-01": "doc/knowledge/junie-tasks/AI-UI/AI-UI-COPILOT-SECTION-CONTEXT-01.md", + "ai-ui-copilot-section-context-01": "doc/knowledge/junie-tasks/AI-UI/AI-UI-COPILOT-SECTION-CONTEXT-01.md", + "AI-UI-INTEL-01-Create-AI-Project-Intelligence-Dashboard-page": "doc/knowledge/junie-tasks/AI-UI-INTEL/AI-UI-INTEL-01-Create-AI-Project-Intelligence-Dashboard-page.md", + "ai-ui-intel-01-create-ai-project-intelligence-dashboard-page": "doc/knowledge/junie-tasks/AI-UI-INTEL/AI-UI-INTEL-01-Create-AI-Project-Intelligence-Dashboard-page.md", + "AI-UI-INTEL-02-Render-intelligence-cards-and-sections": "doc/knowledge/junie-tasks/AI-UI-INTEL/AI-UI-INTEL-02-Render-intelligence-cards-and-sections.md", + "ai-ui-intel-02-render-intelligence-cards-and-sections": "doc/knowledge/junie-tasks/AI-UI-INTEL/AI-UI-INTEL-02-Render-intelligence-cards-and-sections.md", + "AI-UX-01-AI-Teaser-Badge": "doc/knowledge/junie-tasks/AI-UX/AI-UX-01-AI-Teaser-Badge.md", + "ai-ux-01-ai-teaser-badge": "doc/knowledge/junie-tasks/AI-UX/AI-UX-01-AI-Teaser-Badge.md", + "AI-UX-02-AI-Teaser-Badge-Polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-02-AI-Teaser-Badge-Polish.md", + "ai-ux-02-ai-teaser-badge-polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-02-AI-Teaser-Badge-Polish.md", + "AI-UX-03-Login-Register-AI-Teaser-Redesign": "doc/knowledge/junie-tasks/AI-UX/AI-UX-03-Login-Register-AI-Teaser-Redesign.md", + "ai-ux-03-login-register-ai-teaser-redesign": "doc/knowledge/junie-tasks/AI-UX/AI-UX-03-Login-Register-AI-Teaser-Redesign.md", + "AI-UX-04-Copilot-Sprint-Selection-Refinement": "doc/knowledge/junie-tasks/AI-UX/AI-UX-04-Copilot-Sprint-Selection-Refinement.md", + "ai-ux-04-copilot-sprint-selection-refinement": "doc/knowledge/junie-tasks/AI-UX/AI-UX-04-Copilot-Sprint-Selection-Refinement.md", + "AI-UX-05-Login-Register-AI-Hero-Intro": "doc/knowledge/junie-tasks/AI-UX/AI-UX-05-Login-Register-AI-Hero-Intro.md", + "ai-ux-05-login-register-ai-hero-intro": "doc/knowledge/junie-tasks/AI-UX/AI-UX-05-Login-Register-AI-Hero-Intro.md", + "AI-UX-06-Auth-AI-Intro-Copy-Polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-06-Auth-AI-Intro-Copy-Polish.md", + "ai-ux-06-auth-ai-intro-copy-polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-06-Auth-AI-Intro-Copy-Polish.md", + "AI-UX-08-section-aware-chat-context": "doc/knowledge/junie-tasks/AI-UX/AI-UX-08-section-aware-chat-context.md", + "ai-ux-08-section-aware-chat-context": "doc/knowledge/junie-tasks/AI-UX/AI-UX-08-section-aware-chat-context.md", + "AI-UX-09-ai-routing-transparency": "doc/knowledge/junie-tasks/AI-UX/AI-UX-09-ai-routing-transparency.md", + "ai-ux-09-ai-routing-transparency": "doc/knowledge/junie-tasks/AI-UX/AI-UX-09-ai-routing-transparency.md", + "AI-UX-10-Frontend-Polish-Epic": "doc/knowledge/junie-tasks/AI-UX/AI-UX-10-Frontend-Polish-Epic.md", + "ai-ux-10-frontend-polish-epic": "doc/knowledge/junie-tasks/AI-UX/AI-UX-10-Frontend-Polish-Epic.md", + "AI-UX-100-Copilot-Workspace-Completion": "doc/knowledge/junie-tasks/AI-UX/AI-UX-100-Copilot-Workspace-Completion.md", + "ai-ux-100-copilot-workspace-completion": "doc/knowledge/junie-tasks/AI-UX/AI-UX-100-Copilot-Workspace-Completion.md", + "AI-UX-100B-credit-top-up": "doc/knowledge/junie-tasks/AI-UX/AI-UX-100B-credit-top-up.md", + "ai-ux-100b-credit-top-up": "doc/knowledge/junie-tasks/AI-UX/AI-UX-100B-credit-top-up.md", + "AI-UX-101-Contact-Form-Redesign": "doc/knowledge/junie-tasks/AI-UX/AI-UX-101-Contact-Form-Redesign.md", + "ai-ux-101-contact-form-redesign": "doc/knowledge/junie-tasks/AI-UX/AI-UX-101-Contact-Form-Redesign.md", + "AI-UX-102-AI-Credit-Usage-Header": "doc/knowledge/junie-tasks/AI-UX/AI-UX-102-AI-Credit-Usage-Header.md", + "ai-ux-102-ai-credit-usage-header": "doc/knowledge/junie-tasks/AI-UX/AI-UX-102-AI-Credit-Usage-Header.md", + "AI-UX-103-adr-discoverability-and-document-viewer": "doc/knowledge/junie-tasks/AI-UX/AI-UX-103-adr-discoverability-and-document-viewer.md", + "ai-ux-103-adr-discoverability-and-document-viewer": "doc/knowledge/junie-tasks/AI-UX/AI-UX-103-adr-discoverability-and-document-viewer.md", + "AI-UX-104-UI-Polish-Fix-Pack": "doc/knowledge/junie-tasks/AI-UX/AI-UX-104-UI-Polish-Fix-Pack.md", + "ai-ux-104-ui-polish-fix-pack": "doc/knowledge/junie-tasks/AI-UX/AI-UX-104-UI-Polish-Fix-Pack.md", + "AI-UX-105-Surface-Partial-AI-Failure-State-in-Intelligence-and-Copilot-UI": "doc/knowledge/junie-tasks/AI-UX/AI-UX-105-Surface-Partial-AI-Failure-State-in-Intelligence-and-Copilot-UI.md", + "ai-ux-105-surface-partial-ai-failure-state-in-intelligence-and-copilot-ui": "doc/knowledge/junie-tasks/AI-UX/AI-UX-105-Surface-Partial-AI-Failure-State-in-Intelligence-and-Copilot-UI.md", + "AI-UX-11-ai-debounce-fix": "doc/knowledge/junie-tasks/AI-UX/AI-UX-11-ai-debounce-fix.md", + "ai-ux-11-ai-debounce-fix": "doc/knowledge/junie-tasks/AI-UX/AI-UX-11-ai-debounce-fix.md", + "AI-UX-12-Auth-Entry-Polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-12-Auth-Entry-Polish.md", + "ai-ux-12-auth-entry-polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-12-Auth-Entry-Polish.md", + "AI-UX-120-AI-Suggestions-Panel": "doc/knowledge/junie-tasks/AI-UX/AI-UX-120-AI-Suggestions-Panel.md", + "ai-ux-120-ai-suggestions-panel": "doc/knowledge/junie-tasks/AI-UX/AI-UX-120-AI-Suggestions-Panel.md", + "AI-UX-121-Actionable-Suggestions": "doc/knowledge/junie-tasks/AI-UX/AI-UX-121-Actionable-Suggestions.md", + "ai-ux-121-actionable-suggestions": "doc/knowledge/junie-tasks/AI-UX/AI-UX-121-Actionable-Suggestions.md", + "AI-UX-122-unified-sprint-selector": "doc/knowledge/junie-tasks/AI-UX/AI-UX-122-unified-sprint-selector.md", + "ai-ux-122-unified-sprint-selector": "doc/knowledge/junie-tasks/AI-UX/AI-UX-122-unified-sprint-selector.md", + "AI-UX-123-Fix-Epic-Dashboard-Icon-Overlap": "doc/knowledge/junie-tasks/AI-UX/AI-UX-123-Fix-Epic-Dashboard-Icon-Overlap.md", + "ai-ux-123-fix-epic-dashboard-icon-overlap": "doc/knowledge/junie-tasks/AI-UX/AI-UX-123-Fix-Epic-Dashboard-Icon-Overlap.md", + "AI-UX-124-Shared-UI-Primitives": "doc/knowledge/junie-tasks/AI-UX/AI-UX-124-Shared-UI-Primitives.md", + "ai-ux-124-shared-ui-primitives": "doc/knowledge/junie-tasks/AI-UX/AI-UX-124-Shared-UI-Primitives.md", + "AI-UX-125-Risk-Details-Text-Wrapping-and-Density": "doc/knowledge/junie-tasks/AI-UX/AI-UX-125-Risk-Details-Text-Wrapping-and-Density.md", + "ai-ux-125-risk-details-text-wrapping-and-density": "doc/knowledge/junie-tasks/AI-UX/AI-UX-125-Risk-Details-Text-Wrapping-and-Density.md", + "AI-UX-126-section-aware-chat": "doc/knowledge/junie-tasks/AI-UX/AI-UX-126-section-aware-chat.md", + "ai-ux-126-section-aware-chat": "doc/knowledge/junie-tasks/AI-UX/AI-UX-126-section-aware-chat.md", + "AI-UX-127-Overflow-to-Scroll-Behavior": "doc/knowledge/junie-tasks/AI-UX/AI-UX-127-Overflow-to-Scroll-Behavior.md", + "ai-ux-127-overflow-to-scroll-behavior": "doc/knowledge/junie-tasks/AI-UX/AI-UX-127-Overflow-to-Scroll-Behavior.md", + "AI-UX-128-Architecture-Chat-Prompt-Suggestions": "doc/knowledge/junie-tasks/AI-UX/AI-UX-128-Architecture-Chat-Prompt-Suggestions.md", + "ai-ux-128-architecture-chat-prompt-suggestions": "doc/knowledge/junie-tasks/AI-UX/AI-UX-128-Architecture-Chat-Prompt-Suggestions.md", + "AI-UX-129-Intelligence-Dashboard-Explanations": "doc/knowledge/junie-tasks/AI-UX/AI-UX-129-Intelligence-Dashboard-Explanations.md", + "ai-ux-129-intelligence-dashboard-explanations": "doc/knowledge/junie-tasks/AI-UX/AI-UX-129-Intelligence-Dashboard-Explanations.md", + "AI-UX-13-Header-Sidenav-Polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-13-Header-Sidenav-Polish.md", + "ai-ux-13-header-sidenav-polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-13-Header-Sidenav-Polish.md", + "AI-UX-130-Split-Epic-Dashboard-and-Intelligence-Dashboard-Concerns": "doc/knowledge/junie-tasks/AI-UX/AI-UX-130-Split-Epic-Dashboard-and-Intelligence-Dashboard-Concerns.md", + "ai-ux-130-split-epic-dashboard-and-intelligence-dashboard-concerns": "doc/knowledge/junie-tasks/AI-UX/AI-UX-130-Split-Epic-Dashboard-and-Intelligence-Dashboard-Concerns.md", + "AI-UX-131-Copilot-Layout-Polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-131-Copilot-Layout-Polish.md", + "ai-ux-131-copilot-layout-polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-131-Copilot-Layout-Polish.md", + "AI-UX-14-AI-Feature-Pages-Consistency": "doc/knowledge/junie-tasks/AI-UX/AI-UX-14-AI-Feature-Pages-Consistency.md", + "ai-ux-14-ai-feature-pages-consistency": "doc/knowledge/junie-tasks/AI-UX/AI-UX-14-AI-Feature-Pages-Consistency.md", + "AI-UX-15-Dashboard-Tasks-Polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-15-Dashboard-Tasks-Polish.md", + "ai-ux-15-dashboard-tasks-polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-15-Dashboard-Tasks-Polish.md", + "AI-UX-16-Visual-Consistency-Guardrails": "doc/knowledge/junie-tasks/AI-UX/AI-UX-16-Visual-Consistency-Guardrails.md", + "ai-ux-16-visual-consistency-guardrails": "doc/knowledge/junie-tasks/AI-UX/AI-UX-16-Visual-Consistency-Guardrails.md", + "AI-UX-19-Risk-Radar-Full-Width-Layout": "doc/knowledge/junie-tasks/AI-UX/AI-UX-19-Risk-Radar-Full-Width-Layout.md", + "ai-ux-19-risk-radar-full-width-layout": "doc/knowledge/junie-tasks/AI-UX/AI-UX-19-Risk-Radar-Full-Width-Layout.md", + "AI-UX-20-ai-routing-transparency": "doc/knowledge/junie-tasks/AI-UX/AI-UX-20-ai-routing-transparency.md", + "ai-ux-20-ai-routing-transparency": "doc/knowledge/junie-tasks/AI-UX/AI-UX-20-ai-routing-transparency.md", + "AI-UX-21-Dark-Mode-Token-Consolidation": "doc/knowledge/junie-tasks/AI-UX/AI-UX-21-Dark-Mode-Token-Consolidation.md", + "ai-ux-21-dark-mode-token-consolidation": "doc/knowledge/junie-tasks/AI-UX/AI-UX-21-Dark-Mode-Token-Consolidation.md", + "AI-UX-22-chat-context-isolation": "doc/knowledge/junie-tasks/AI-UX/AI-UX-22-chat-context-isolation.md", + "ai-ux-22-chat-context-isolation": "doc/knowledge/junie-tasks/AI-UX/AI-UX-22-chat-context-isolation.md", + "AI-UX-23-Mobile-and-Narrow-Viewport-Stabilization": "doc/knowledge/junie-tasks/AI-UX/AI-UX-23-Mobile-and-Narrow-Viewport-Stabilization.md", + "ai-ux-23-mobile-and-narrow-viewport-stabilization": "doc/knowledge/junie-tasks/AI-UX/AI-UX-23-Mobile-and-Narrow-Viewport-Stabilization.md", + "AI-UX-24-AI-Panels-Visual-Hierarchy-Polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-24-AI-Panels-Visual-Hierarchy-Polish.md", + "ai-ux-24-ai-panels-visual-hierarchy-polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-24-AI-Panels-Visual-Hierarchy-Polish.md", + "AI-UX-25-AI-Panel-Layout-Stabilization": "doc/knowledge/junie-tasks/AI-UX/AI-UX-25-AI-Panel-Layout-Stabilization.md", + "ai-ux-25-ai-panel-layout-stabilization": "doc/knowledge/junie-tasks/AI-UX/AI-UX-25-AI-Panel-Layout-Stabilization.md", + "AI-UX-26-Dark-Mode-Pseudo-Checkbox-Fix-for-AI-Taskset-Panels": "doc/knowledge/junie-tasks/AI-UX/AI-UX-26-Dark-Mode-Pseudo-Checkbox-Fix-for-AI-Taskset-Panels.md", + "ai-ux-26-dark-mode-pseudo-checkbox-fix-for-ai-taskset-panels": "doc/knowledge/junie-tasks/AI-UX/AI-UX-26-Dark-Mode-Pseudo-Checkbox-Fix-for-AI-Taskset-Panels.md", + "AI-UX-27-AI-Accent-Token-Split-for-Light-and-Dark-Surfaces": "doc/knowledge/junie-tasks/AI-UX/AI-UX-27-AI-Accent-Token-Split-for-Light-and-Dark-Surfaces.md", + "ai-ux-27-ai-accent-token-split-for-light-and-dark-surfaces": "doc/knowledge/junie-tasks/AI-UX/AI-UX-27-AI-Accent-Token-Split-for-Light-and-Dark-Surfaces.md", + "AI-UX-28-Shared-AI-Taskset-Panel-Styling-Consolidation": "doc/knowledge/junie-tasks/AI-UX/AI-UX-28-Shared-AI-Taskset-Panel-Styling-Consolidation.md", + "ai-ux-28-shared-ai-taskset-panel-styling-consolidation": "doc/knowledge/junie-tasks/AI-UX/AI-UX-28-Shared-AI-Taskset-Panel-Styling-Consolidation.md", + "AI-UX-29-Theme-Variable-Cleanup-for-Undefined-Tokens": "doc/knowledge/junie-tasks/AI-UX/AI-UX-29-Theme-Variable-Cleanup-for-Undefined-Tokens.md", + "ai-ux-29-theme-variable-cleanup-for-undefined-tokens": "doc/knowledge/junie-tasks/AI-UX/AI-UX-29-Theme-Variable-Cleanup-for-Undefined-Tokens.md", + "AI-UX-30-AI-Icon-Consistency-Pass": "doc/knowledge/junie-tasks/AI-UX/AI-UX-30-AI-Icon-Consistency-Pass.md", + "ai-ux-30-ai-icon-consistency-pass": "doc/knowledge/junie-tasks/AI-UX/AI-UX-30-AI-Icon-Consistency-Pass.md", + "AI-UX-31-User-Admin-Action-Icon-Semantic-Differentiation": "doc/knowledge/junie-tasks/AI-UX/AI-UX-31-User-Admin-Action-Icon-Semantic-Differentiation.md", + "ai-ux-31-user-admin-action-icon-semantic-differentiation": "doc/knowledge/junie-tasks/AI-UX/AI-UX-31-User-Admin-Action-Icon-Semantic-Differentiation.md", + "AI-UX-32-Login-Register-Branding-with-Product-Identity": "doc/knowledge/junie-tasks/AI-UX/AI-UX-32-Login-Register-Branding-with-Product-Identity.md", + "ai-ux-32-login-register-branding-with-product-identity": "doc/knowledge/junie-tasks/AI-UX/AI-UX-32-Login-Register-Branding-with-Product-Identity.md", + "AI-UX-33-Standard-Page-Header-Component": "doc/knowledge/junie-tasks/AI-UX/AI-UX-33-Standard-Page-Header-Component.md", + "ai-ux-33-standard-page-header-component": "doc/knowledge/junie-tasks/AI-UX/AI-UX-33-Standard-Page-Header-Component.md", + "AI-UX-34-Admin-Page-Card-Layout-for-Tables": "doc/knowledge/junie-tasks/AI-UX/AI-UX-34-Admin-Page-Card-Layout-for-Tables.md", + "ai-ux-34-admin-page-card-layout-for-tables": "doc/knowledge/junie-tasks/AI-UX/AI-UX-34-Admin-Page-Card-Layout-for-Tables.md", + "AI-UX-35-Navigation-Menu-Structure-Improvement": "doc/knowledge/junie-tasks/AI-UX/AI-UX-35-Navigation-Menu-Structure-Improvement.md", + "ai-ux-35-navigation-menu-structure-improvement": "doc/knowledge/junie-tasks/AI-UX/AI-UX-35-Navigation-Menu-Structure-Improvement.md", + "AI-UX-36-AI-Task-Quick-Add-UX-Improvement": "doc/knowledge/junie-tasks/AI-UX/AI-UX-36-AI-Task-Quick-Add-UX-Improvement.md", + "ai-ux-36-ai-task-quick-add-ux-improvement": "doc/knowledge/junie-tasks/AI-UX/AI-UX-36-AI-Task-Quick-Add-UX-Improvement.md", + "AI-UX-37-System-Status-Layout-Alignment": "doc/knowledge/junie-tasks/AI-UX/AI-UX-37-System-Status-Layout-Alignment.md", + "ai-ux-37-system-status-layout-alignment": "doc/knowledge/junie-tasks/AI-UX/AI-UX-37-System-Status-Layout-Alignment.md", + "AI-UX-38-Dashboard-Metrics-Enhancement": "doc/knowledge/junie-tasks/AI-UX/AI-UX-38-Dashboard-Metrics-Enhancement.md", + "ai-ux-38-dashboard-metrics-enhancement": "doc/knowledge/junie-tasks/AI-UX/AI-UX-38-Dashboard-Metrics-Enhancement.md", + "AI-UX-39-Lightweight-UI-Design-System": "doc/knowledge/junie-tasks/AI-UX/AI-UX-39-Lightweight-UI-Design-System.md", + "ai-ux-39-lightweight-ui-design-system": "doc/knowledge/junie-tasks/AI-UX/AI-UX-39-Lightweight-UI-Design-System.md", + "AI-UX-40-Empty-State-Design": "doc/knowledge/junie-tasks/AI-UX/AI-UX-40-Empty-State-Design.md", + "ai-ux-40-empty-state-design": "doc/knowledge/junie-tasks/AI-UX/AI-UX-40-Empty-State-Design.md", + "AI-UX-41-Loading-Skeletons": "doc/knowledge/junie-tasks/AI-UX/AI-UX-41-Loading-Skeletons.md", + "ai-ux-41-loading-skeletons": "doc/knowledge/junie-tasks/AI-UX/AI-UX-41-Loading-Skeletons.md", + "AI-UX-42-AI-Result-Visualization": "doc/knowledge/junie-tasks/AI-UX/AI-UX-42-AI-Result-Visualization.md", + "ai-ux-42-ai-result-visualization": "doc/knowledge/junie-tasks/AI-UX/AI-UX-42-AI-Result-Visualization.md", + "AI-UX-43-Risk-Radar-Report-Layout": "doc/knowledge/junie-tasks/AI-UX/AI-UX-43-Risk-Radar-Report-Layout.md", + "ai-ux-43-risk-radar-report-layout": "doc/knowledge/junie-tasks/AI-UX/AI-UX-43-Risk-Radar-Report-Layout.md", + "AI-UX-44-Retrospective-Report-UI": "doc/knowledge/junie-tasks/AI-UX/AI-UX-44-Retrospective-Report-UI.md", + "ai-ux-44-retrospective-report-ui": "doc/knowledge/junie-tasks/AI-UX/AI-UX-44-Retrospective-Report-UI.md", + "AI-UX-45-Architecture-Chat-UI": "doc/knowledge/junie-tasks/AI-UX/AI-UX-45-Architecture-Chat-UI.md", + "ai-ux-45-architecture-chat-ui": "doc/knowledge/junie-tasks/AI-UX/AI-UX-45-Architecture-Chat-UI.md", + "AI-UX-46-Streaming-AI-Response-UX": "doc/knowledge/junie-tasks/AI-UX/AI-UX-46-Streaming-AI-Response-UX.md", + "ai-ux-46-streaming-ai-response-ux": "doc/knowledge/junie-tasks/AI-UX/AI-UX-46-Streaming-AI-Response-UX.md", + "AI-UX-47-Architecture-Chat-Conversation-History": "doc/knowledge/junie-tasks/AI-UX/AI-UX-47-Architecture-Chat-Conversation-History.md", + "ai-ux-47-architecture-chat-conversation-history": "doc/knowledge/junie-tasks/AI-UX/AI-UX-47-Architecture-Chat-Conversation-History.md", + "AI-UX-48-Risk-Radar-Severity-Visualization": "doc/knowledge/junie-tasks/AI-UX/AI-UX-48-Risk-Radar-Severity-Visualization.md", + "ai-ux-48-risk-radar-severity-visualization": "doc/knowledge/junie-tasks/AI-UX/AI-UX-48-Risk-Radar-Severity-Visualization.md", + "AI-UX-49-Retrospective-Insights-Card-Layout": "doc/knowledge/junie-tasks/AI-UX/AI-UX-49-Retrospective-Insights-Card-Layout.md", + "ai-ux-49-retrospective-insights-card-layout": "doc/knowledge/junie-tasks/AI-UX/AI-UX-49-Retrospective-Insights-Card-Layout.md", + "AI-UX-50-Dashboard-Mini-Trends-Sparklines": "doc/knowledge/junie-tasks/AI-UX/AI-UX-50-Dashboard-Mini-Trends-Sparklines.md", + "ai-ux-50-dashboard-mini-trends-sparklines": "doc/knowledge/junie-tasks/AI-UX/AI-UX-50-Dashboard-Mini-Trends-Sparklines.md", + "AI-UX-51-AI-Activity-Timeline": "doc/knowledge/junie-tasks/AI-UX/AI-UX-51-AI-Activity-Timeline.md", + "ai-ux-51-ai-activity-timeline": "doc/knowledge/junie-tasks/AI-UX/AI-UX-51-AI-Activity-Timeline.md", + "AI-UX-52-Generated-Report-Export-Readiness": "doc/knowledge/junie-tasks/AI-UX/AI-UX-52-Generated-Report-Export-Readiness.md", + "ai-ux-52-generated-report-export-readiness": "doc/knowledge/junie-tasks/AI-UX/AI-UX-52-Generated-Report-Export-Readiness.md", + "AI-UX-53-Product-Empty-States": "doc/knowledge/junie-tasks/AI-UX/AI-UX-53-Product-Empty-States.md", + "ai-ux-53-product-empty-states": "doc/knowledge/junie-tasks/AI-UX/AI-UX-53-Product-Empty-States.md", + "AI-UX-54-Unified-AI-Result-Container": "doc/knowledge/junie-tasks/AI-UX/AI-UX-54-Unified-AI-Result-Container.md", + "ai-ux-54-unified-ai-result-container": "doc/knowledge/junie-tasks/AI-UX/AI-UX-54-Unified-AI-Result-Container.md", + "AI-UX-55-Demo-Mode-Visual-Polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-55-Demo-Mode-Visual-Polish.md", + "ai-ux-55-demo-mode-visual-polish": "doc/knowledge/junie-tasks/AI-UX/AI-UX-55-Demo-Mode-Visual-Polish.md", + "AI-UX-96-authentication-screen-simplification": "doc/knowledge/junie-tasks/AI-UX/AI-UX-96-authentication-screen-simplification.md", + "ai-ux-96-authentication-screen-simplification": "doc/knowledge/junie-tasks/AI-UX/AI-UX-96-authentication-screen-simplification.md", + "AI-UX-97-architecture-chat-improvements": "doc/knowledge/junie-tasks/AI-UX/AI-UX-97-architecture-chat-improvements.md", + "ai-ux-97-architecture-chat-improvements": "doc/knowledge/junie-tasks/AI-UX/AI-UX-97-architecture-chat-improvements.md", + "AI-UX-98 - Epic Dashboard Page": "doc/knowledge/junie-tasks/AI-UX/AI-UX-98 - Epic Dashboard Page.md", + "ai-ux-98 - epic dashboard page": "doc/knowledge/junie-tasks/AI-UX/AI-UX-98 - Epic Dashboard Page.md", + "AI-UX-99-architecture-chat-streaming-response": "doc/knowledge/junie-tasks/AI-UX/AI-UX-99-architecture-chat-streaming-response.md", + "ai-ux-99-architecture-chat-streaming-response": "doc/knowledge/junie-tasks/AI-UX/AI-UX-99-architecture-chat-streaming-response.md", + "AI-UX-99R-Split-Epic-and-Intelligence-Dashboards": "doc/knowledge/junie-tasks/AI-UX/AI-UX-99R-Split-Epic-and-Intelligence-Dashboards.md", + "ai-ux-99r-split-epic-and-intelligence-dashboards": "doc/knowledge/junie-tasks/AI-UX/AI-UX-99R-Split-Epic-and-Intelligence-Dashboards.md", + "AI-WEB-21-Add-GitHub-Repository-Link-to-Navigation": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-21-Add-GitHub-Repository-Link-to-Navigation.md", + "ai-web-21-add-github-repository-link-to-navigation": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-21-Add-GitHub-Repository-Link-to-Navigation.md", + "AI-WEB-22-Add-View-on-GitHub-CTA-Button": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-22-Add-View-on-GitHub-CTA-Button.md", + "ai-web-22-add-view-on-github-cta-button": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-22-Add-View-on-GitHub-CTA-Button.md", + "AI-WEB-23-Add-Live-Demo-Architecture-AI-Features-Landing-Section": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-23-Add-Live-Demo-Architecture-AI-Features-Landing-Section.md", + "ai-web-23-add-live-demo-architecture-ai-features-landing-section": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-23-Add-Live-Demo-Architecture-AI-Features-Landing-Section.md", + "AI-WEB-24-Extended-Refine-GitHub-CTA-Landing-Links-and-UI-Polish": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-24-Extended-Refine-GitHub-CTA-Landing-Links-and-UI-Polish.md", + "ai-web-24-extended-refine-github-cta-landing-links-and-ui-polish": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-24-Extended-Refine-GitHub-CTA-Landing-Links-and-UI-Polish.md", + "AI-WEB-27-Implement-Architecture-and-Features-Landing-Pages": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-27-Implement-Architecture-and-Features-Landing-Pages.md", + "ai-web-27-implement-architecture-and-features-landing-pages": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-27-Implement-Architecture-and-Features-Landing-Pages.md", + "AI-WEB-28-architecture-page-public-access-safeguard": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-28-architecture-page-public-access-safeguard.md", + "ai-web-28-architecture-page-public-access-safeguard": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-28-architecture-page-public-access-safeguard.md", + "AI-WEB-29-reduce-architecture-hero-color": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-29-reduce-architecture-hero-color.md", + "ai-web-29-reduce-architecture-hero-color": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-29-reduce-architecture-hero-color.md", + "AI-WEB-30-card-hover-polish": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-30-card-hover-polish.md", + "ai-web-30-card-hover-polish": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-30-card-hover-polish.md", + "AI-WEB-31-semantic-surface-tokens": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-31-semantic-surface-tokens.md", + "ai-web-31-semantic-surface-tokens": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-31-semantic-surface-tokens.md", + "AI-WEB-32-dark-mode-fix": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-32-dark-mode-fix.md", + "ai-web-32-dark-mode-fix": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-32-dark-mode-fix.md", + "AI-WEB-33-Add-sprint-selector-dropdown-for-intelligence-dashboards": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-33-Add-sprint-selector-dropdown-for-intelligence-dashboards.md", + "ai-web-33-add-sprint-selector-dropdown-for-intelligence-dashboards": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-33-Add-sprint-selector-dropdown-for-intelligence-dashboards.md", + "AI-WEB-34-global-responsive-form-layout-standard": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-34-global-responsive-form-layout-standard.md", + "ai-web-34-global-responsive-form-layout-standard": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-34-global-responsive-form-layout-standard.md", + "AI-WEB-35-Reposition-GoodOne-demo-and-rebalance-GitHub-CTA": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-35-Reposition-GoodOne-demo-and-rebalance-GitHub-CTA.md", + "ai-web-35-reposition-goodone-demo-and-rebalance-github-cta": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-35-Reposition-GoodOne-demo-and-rebalance-GitHub-CTA.md", + "AI-WEB-36-Provide-menu-items-for-Copilot-and-Intelligence": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-36-Provide-menu-items-for-Copilot-and-Intelligence.md", + "ai-web-36-provide-menu-items-for-copilot-and-intelligence": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-36-Provide-menu-items-for-Copilot-and-Intelligence.md", + "AI-WEB-37-login-page-visual-hierarchy-polish": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-37-login-page-visual-hierarchy-polish.md", + "ai-web-37-login-page-visual-hierarchy-polish": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-37-login-page-visual-hierarchy-polish.md", + "AI-WEB-38-UI-and-Runtime-Fixes-Bundle": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-38-UI-and-Runtime-Fixes-Bundle.md", + "ai-web-38-ui-and-runtime-fixes-bundle": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-38-UI-and-Runtime-Fixes-Bundle.md", + "AI-WEB-39-Architecture-Page-UI-Fixes": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-39-Architecture-Page-UI-Fixes.md", + "ai-web-39-architecture-page-ui-fixes": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-39-Architecture-Page-UI-Fixes.md", + "AI-WEB-40-ai-transparency-panel": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-40-ai-transparency-panel.md", + "ai-web-40-ai-transparency-panel": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-40-ai-transparency-panel.md", + "AI-WEB-41-split-architecture-product-and-demo-pages": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-41-split-architecture-product-and-demo-pages.md", + "ai-web-41-split-architecture-product-and-demo-pages": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-41-split-architecture-product-and-demo-pages.md", + "AI-WEB-42-debounce-quick-add-parser": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-42-debounce-quick-add-parser.md", + "ai-web-42-debounce-quick-add-parser": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-42-debounce-quick-add-parser.md", + "AI-WEB-43-features-visual-balance": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-43-features-visual-balance.md", + "ai-web-43-features-visual-balance": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-43-features-visual-balance.md", + "AI-WEB-44-Fix epics SSE UI not refreshing after final dashboard update": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-44-Fix epics SSE UI not refreshing after final dashboard update.md", + "ai-web-44-fix epics sse ui not refreshing after final dashboard update": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-44-Fix epics SSE UI not refreshing after final dashboard update.md", + "AI-WEB-45-fix-retrospective-todate-overflow": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-45-fix-retrospective-todate-overflow.md", + "ai-web-45-fix-retrospective-todate-overflow": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-45-fix-retrospective-todate-overflow.md", + "AI-WEB-46–Improve–GitHub–Visibility": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-46–Improve–GitHub–Visibility.md", + "ai-web-46–improve–github–visibility": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-46–Improve–GitHub–Visibility.md", + "AI-WEB-47-GoodOne-UI-Polish-Bundle": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-47-GoodOne-UI-Polish-Bundle.md", + "ai-web-47-goodone-ui-polish-bundle": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-47-GoodOne-UI-Polish-Bundle.md", + "AI-WEB-48-Polish-sprint-selector-UI-for-intelligence-dashboards": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-48-Polish-sprint-selector-UI-for-intelligence-dashboards.md", + "ai-web-48-polish-sprint-selector-ui-for-intelligence-dashboards": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-48-Polish-sprint-selector-UI-for-intelligence-dashboards.md", + "AI-WEB-49-shared-angular-form-row-component": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-49-shared-angular-form-row-component.md", + "ai-web-49-shared-angular-form-row-component": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-49-shared-angular-form-row-component.md", + "AI-WEB-50-standardize-taskgroup-filter-bar-layout": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-50-standardize-taskgroup-filter-bar-layout.md", + "ai-web-50-standardize-taskgroup-filter-bar-layout": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-50-standardize-taskgroup-filter-bar-layout.md", + "AI-WEB-51-Rebalance-login-page-after-demo-move": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-51-Rebalance-login-page-after-demo-move.md", + "ai-web-51-rebalance-login-page-after-demo-move": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-51-Rebalance-login-page-after-demo-move.md", + "AI-WEB-52-reduce-github-cta-prominence-login-page": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-52-reduce-github-cta-prominence-login-page.md", + "ai-web-52-reduce-github-cta-prominence-login-page": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-52-reduce-github-cta-prominence-login-page.md", + "AI-WEB-53-Restore-Monitoring-Server": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-53-Restore-Monitoring-Server.md", + "ai-web-53-restore-monitoring-server": "doc/knowledge/junie-tasks/AI-WEB/AI-WEB-53-Restore-Monitoring-Server.md", + "taskset-4-7": "doc/knowledge/junie-tasks/backlog/taskset-4-7.md", + "guardrails-implementation-order": "doc/knowledge/junie-tasks/sprints/guardrails-implementation-order.md", + "sprint-1.3-plan": "doc/knowledge/junie-tasks/sprints/sprint-1.3-plan.md", + "sprint-1.4-execution-order": "doc/knowledge/junie-tasks/sprints/sprint-1.4-execution-order.md", + "sprint-1.4-plan": "doc/knowledge/junie-tasks/sprints/sprint-1.4-plan.md", + "sprint-1.4-prompt": "doc/knowledge/junie-tasks/sprints/sprint-1.4-prompt.md", + "sprint-1.5-execution-order": "doc/knowledge/junie-tasks/sprints/sprint-1.5-execution-order.md", + "sprint-1.5-plan": "doc/knowledge/junie-tasks/sprints/sprint-1.5-plan.md", + "sprint-1.7-execution-order": "doc/knowledge/junie-tasks/sprints/sprint-1.7-execution-order.md", + "sprint-1.7-plan": "doc/knowledge/junie-tasks/sprints/sprint-1.7-plan.md", + "sprint-AI-INTEL-01-plan": "doc/knowledge/junie-tasks/sprints/sprint-AI-INTEL-01-plan.md", + "sprint-ai-intel-01-plan": "doc/knowledge/junie-tasks/sprints/sprint-AI-INTEL-01-plan.md", + "sprint-prompt-template-disciplined": "doc/knowledge/junie-tasks/sprints/sprint-prompt-template-disciplined.md", + "sprint-prompt-template": "doc/knowledge/junie-tasks/sprints/sprint-prompt-template.md", + "sprint-prompt": "doc/knowledge/junie-tasks/sprints/sprint-prompt.md", + "SPRINT_TEMPLATE": "doc/knowledge/junie-tasks/sprints/SPRINT_TEMPLATE.md", + "sprint_template": "doc/knowledge/junie-tasks/sprints/SPRINT_TEMPLATE.md", + "updated-roadmap-after-sprint-1.7": "doc/knowledge/junie-tasks/sprints/updated-roadmap-after-sprint-1.7.md", + "sprint-1.6-execution-order": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6-execution-order.md", + "sprint-1.6-plan": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6-plan.md", + "sprint-1.6-status-assessment": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6-status-assessment.md", + "sprint-1.6A-cleanup-execution-order": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6A-cleanup-execution-order.md", + "sprint-1.6a-cleanup-execution-order": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6A-cleanup-execution-order.md", + "sprint-1.6A-cleanup-plan": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6A-cleanup-plan.md", + "sprint-1.6a-cleanup-plan": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6A-cleanup-plan.md", + "sprint-1.6A-review-guide": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6A-review-guide.md", + "sprint-1.6a-review-guide": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6A-review-guide.md", + "sprint-1.6B-epic-dashboard-execution-order": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6B-epic-dashboard-execution-order.md", + "sprint-1.6b-epic-dashboard-execution-order": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6B-epic-dashboard-execution-order.md", + "sprint-1.6B-epic-dashboard-plan": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6B-epic-dashboard-plan.md", + "sprint-1.6b-epic-dashboard-plan": "doc/knowledge/junie-tasks/sprints/sprint-1.6/sprint-1.6B-epic-dashboard-plan.md", + "sprint-1.8-execution-order": "doc/knowledge/junie-tasks/sprints/sprint-1.8/sprint-1.8-execution-order.md", + "sprint-1.8-plan": "doc/knowledge/junie-tasks/sprints/sprint-1.8/sprint-1.8-plan.md", + "sprint-1.9-execution-order": "doc/knowledge/junie-tasks/sprints/sprint-1.9/sprint-1.9-execution-order.md", + "sprint-1.9-plan": "doc/knowledge/junie-tasks/sprints/sprint-1.9/sprint-1.9-plan.md", + "sprint-2.0-execution-order": "doc/knowledge/junie-tasks/sprints/sprint-2.0/sprint-2.0-execution-order.md", + "sprint-2.0-plan": "doc/knowledge/junie-tasks/sprints/sprint-2.0/sprint-2.0-plan.md", + "ai-regression-test": "doc/knowledge/junie-tasks/sprints/sprint-2.1/ai-regression-test.md", + "README-backlog": "doc/knowledge/junie-tasks/sprints/sprint-2.1/README-backlog.md", + "readme-backlog": "doc/knowledge/junie-tasks/sprints/sprint-2.1/README-backlog.md", + "sprint-2.1-chat-history": "doc/knowledge/junie-tasks/sprints/sprint-2.1/sprint-2.1-chat-history.md", + "sprint-2.1-corrective-plan": "doc/knowledge/junie-tasks/sprints/sprint-2.1/sprint-2.1-corrective-plan.md", + "sprint-2.1-definition-of-done": "doc/knowledge/junie-tasks/sprints/sprint-2.1/sprint-2.1-definition-of-done.md", + "sprint-2.1-execution-order": "doc/knowledge/junie-tasks/sprints/sprint-2.1/sprint-2.1-execution-order.md", + "sprint-2.1-plan": "doc/knowledge/junie-tasks/sprints/sprint-2.1/sprint-2.1-plan.md", + "sprint-2.1-risk-checklist": "doc/knowledge/junie-tasks/sprints/sprint-2.1/sprint-2.1-risk-checklist.md", + "architecture-q1.expected": "doc/knowledge/junie-tasks/sprints/sprint-2.1/qa/ai-baselines/copilot/architecture-q1.expected.md", + "report-layout": "doc/knowledge/junie-tasks/sprints/sprint-2.1/qa/playwright/report-layout.md", + "sprint-2-2-retro-problems": "doc/knowledge/junie-tasks/sprints/sprint-2.2/sprint-2-2-retro-problems.md", + "sprint-2.2-plan": "doc/knowledge/junie-tasks/sprints/sprint-2.2/sprint-2.2-plan.md", + "dto-proposal": "doc/knowledge/junie-tasks/sprints/sprint-2.2/api/dto-proposal.md", + "integration-notes": "doc/knowledge/junie-tasks/sprints/sprint-2.2/backend/integration-notes.md", + "ai-coverage-wireframe": "doc/knowledge/junie-tasks/sprints/sprint-2.2/wireframes/ai-coverage-wireframe.md", + "AI-ARCH-Summary": "doc/knowledge/junie-tasks/task-governance/AI-ARCH-Summary.md", + "ai-arch-summary": "doc/knowledge/junie-tasks/task-governance/AI-ARCH-Summary.md", + "AI-TASK-CONTRACT-STANDARD": "doc/knowledge/junie-tasks/task-governance/AI-TASK-CONTRACT-STANDARD.md", + "ai-task-contract-standard": "doc/knowledge/junie-tasks/task-governance/AI-TASK-CONTRACT-STANDARD.md", + "AI-TASK-GOVERNANCE": "doc/knowledge/junie-tasks/task-governance/AI-TASK-GOVERNANCE.md", + "ai-task-governance": "doc/knowledge/junie-tasks/task-governance/AI-TASK-GOVERNANCE.md", + "guardrails-next-steps": "doc/knowledge/junie-tasks/task-governance/guardrails-next-steps.md", + "JUNIE-EXECUTION-PROMPT-TEMPLATE": "doc/knowledge/junie-tasks/task-governance/JUNIE-EXECUTION-PROMPT-TEMPLATE.md", + "junie-execution-prompt-template": "doc/knowledge/junie-tasks/task-governance/JUNIE-EXECUTION-PROMPT-TEMPLATE.md", + "junie-task-format-guideline": "doc/knowledge/junie-tasks/task-governance/junie-task-format-guideline.md", + "junie-task-template": "doc/knowledge/junie-tasks/task-governance/junie-task-template.md", + "junie-task-validator": "doc/knowledge/junie-tasks/task-governance/junie-task-validator.md", + "JUNIE_TASK_GOVERNANCE": "doc/knowledge/junie-tasks/task-governance/JUNIE_TASK_GOVERNANCE.md", + "junie_task_governance": "doc/knowledge/junie-tasks/task-governance/JUNIE_TASK_GOVERNANCE.md", + "README-task-contract-linter": "doc/knowledge/junie-tasks/task-governance/README-task-contract-linter.md", + "readme-task-contract-linter": "doc/knowledge/junie-tasks/task-governance/README-task-contract-linter.md", + "TASK-TEMPLATE-v2": "doc/knowledge/junie-tasks/task-governance/TASK-TEMPLATE-v2.md", + "task-template-v2": "doc/knowledge/junie-tasks/task-governance/TASK-TEMPLATE-v2.md", + "TASK-TEMPLATE": "doc/knowledge/junie-tasks/task-governance/TASK-TEMPLATE.md", + "task-template": "doc/knowledge/junie-tasks/task-governance/TASK-TEMPLATE.md", + "TASK_TEMPLATE": "doc/knowledge/junie-tasks/task-governance/TASK_TEMPLATE.md", + "task_template": "doc/knowledge/junie-tasks/task-governance/TASK_TEMPLATE.md", + "4-week-roadmap": "doc/knowledge/junie-tasks/taskset-1/4-week-roadmap.md", + "CFG-01-Introduce-Spring-Profiles-dev-demo-prod": "doc/knowledge/junie-tasks/taskset-1/p0/CFG-01-Introduce-Spring-Profiles-dev-demo-prod.md", + "cfg-01-introduce-spring-profiles-dev-demo-prod": "doc/knowledge/junie-tasks/taskset-1/p0/CFG-01-Introduce-Spring-Profiles-dev-demo-prod.md", + "CFG-02-Remove-Default-Secrets-and-Passwords": "doc/knowledge/junie-tasks/taskset-1/p0/CFG-02-Remove-Default-Secrets-and-Passwords.md", + "cfg-02-remove-default-secrets-and-passwords": "doc/knowledge/junie-tasks/taskset-1/p0/CFG-02-Remove-Default-Secrets-and-Passwords.md", + "DEMO-01-Deterministic-Demo-Reset": "doc/knowledge/junie-tasks/taskset-1/p0/DEMO-01-Deterministic-Demo-Reset.md", + "demo-01-deterministic-demo-reset": "doc/knowledge/junie-tasks/taskset-1/p0/DEMO-01-Deterministic-Demo-Reset.md", + "DEMO-02-Demo-Reset-UI": "doc/knowledge/junie-tasks/taskset-1/p0/DEMO-02-Demo-Reset-UI.md", + "demo-02-demo-reset-ui": "doc/knowledge/junie-tasks/taskset-1/p0/DEMO-02-Demo-Reset-UI.md", + "SEC-01-Disable-H2-Console-Exposure-in-Demo-Prod": "doc/knowledge/junie-tasks/taskset-1/p0/SEC-01-Disable-H2-Console-Exposure-in-Demo-Prod.md", + "sec-01-disable-h2-console-exposure-in-demo-prod": "doc/knowledge/junie-tasks/taskset-1/p0/SEC-01-Disable-H2-Console-Exposure-in-Demo-Prod.md", + "CI-01-Add-CI-Pipeline-Build-Test": "doc/knowledge/junie-tasks/taskset-1/p1/CI-01-Add-CI-Pipeline-Build-Test.md", + "ci-01-add-ci-pipeline-build-test": "doc/knowledge/junie-tasks/taskset-1/p1/CI-01-Add-CI-Pipeline-Build-Test.md", + "CI-02-Publish-Playwright-Artifacts": "doc/knowledge/junie-tasks/taskset-1/p1/CI-02-Publish-Playwright-Artifacts.md", + "ci-02-publish-playwright-artifacts": "doc/knowledge/junie-tasks/taskset-1/p1/CI-02-Publish-Playwright-Artifacts.md", + "PERF-01-Static-Asset-Caching": "doc/knowledge/junie-tasks/taskset-1/p1/PERF-01-Static-Asset-Caching.md", + "perf-01-static-asset-caching": "doc/knowledge/junie-tasks/taskset-1/p1/PERF-01-Static-Asset-Caching.md", + "UX-01-Mobile-UX-Guardrails-360px": "doc/knowledge/junie-tasks/taskset-1/p1/UX-01-Mobile-UX-Guardrails-360px.md", + "ux-01-mobile-ux-guardrails-360px": "doc/knowledge/junie-tasks/taskset-1/p1/UX-01-Mobile-UX-Guardrails-360px.md", + "UX-02-Screenshot-Baseline-for-Demo-Screens": "doc/knowledge/junie-tasks/taskset-1/p1/UX-02-Screenshot-Baseline-for-Demo-Screens.md", + "ux-02-screenshot-baseline-for-demo-screens": "doc/knowledge/junie-tasks/taskset-1/p1/UX-02-Screenshot-Baseline-for-Demo-Screens.md", + "Execution-Rules-Definition-of-Done": "doc/knowledge/junie-tasks/taskset-1/p2/Execution-Rules-Definition-of-Done.md", + "execution-rules-definition-of-done": "doc/knowledge/junie-tasks/taskset-1/p2/Execution-Rules-Definition-of-Done.md", + "OBS-01-Health-Readiness-Endpoints": "doc/knowledge/junie-tasks/taskset-1/p2/OBS-01-Health-Readiness-Endpoints.md", + "obs-01-health-readiness-endpoints": "doc/knowledge/junie-tasks/taskset-1/p2/OBS-01-Health-Readiness-Endpoints.md", + "OBS-02-Correlation-IDs-End-to-End": "doc/knowledge/junie-tasks/taskset-1/p2/OBS-02-Correlation-IDs-End-to-End.md", + "obs-02-correlation-ids-end-to-end": "doc/knowledge/junie-tasks/taskset-1/p2/OBS-02-Correlation-IDs-End-to-End.md", + "OBS-03-Support-System-Info-Page": "doc/knowledge/junie-tasks/taskset-1/p2/OBS-03-Support-System-Info-Page.md", + "obs-03-support-system-info-page": "doc/knowledge/junie-tasks/taskset-1/p2/OBS-03-Support-System-Info-Page.md", + "rebrand_goodone_README": "doc/knowledge/junie-tasks/taskset-10/rebrand_goodone_README.md", + "rebrand_goodone_readme": "doc/knowledge/junie-tasks/taskset-10/rebrand_goodone_README.md", + "SEC-41-CloudWatch-Cost-Reduction": "doc/knowledge/junie-tasks/taskset-10/SEC-41-CloudWatch-Cost-Reduction.md", + "sec-41-cloudwatch-cost-reduction": "doc/knowledge/junie-tasks/taskset-10/SEC-41-CloudWatch-Cost-Reduction.md", + "Acceptance-criteria-manual": "doc/knowledge/junie-tasks/taskset-3/Acceptance-criteria-manual.md", + "acceptance-criteria-manual": "doc/knowledge/junie-tasks/taskset-3/Acceptance-criteria-manual.md", + "CI-DEDUP-01-Remove-duplicate-guardrail-execution-across-workflows": "doc/knowledge/junie-tasks/taskset-3/CI-DEDUP-01-Remove-duplicate-guardrail-execution-across-workflows.md", + "ci-dedup-01-remove-duplicate-guardrail-execution-across-workflows": "doc/knowledge/junie-tasks/taskset-3/CI-DEDUP-01-Remove-duplicate-guardrail-execution-across-workflows.md", + "CI-FIX-01-Fix-GitHub-Action-Failures": "doc/knowledge/junie-tasks/taskset-3/CI-FIX-01-Fix-GitHub-Action-Failures.md", + "ci-fix-01-fix-github-action-failures": "doc/knowledge/junie-tasks/taskset-3/CI-FIX-01-Fix-GitHub-Action-Failures.md", + "CI-FIX-01-Fix-SonarCloud-job-path-bug-standardize-npm-install": "doc/knowledge/junie-tasks/taskset-3/CI-FIX-01-Fix-SonarCloud-job-path-bug-standardize-npm-install.md", + "ci-fix-01-fix-sonarcloud-job-path-bug-standardize-npm-install": "doc/knowledge/junie-tasks/taskset-3/CI-FIX-01-Fix-SonarCloud-job-path-bug-standardize-npm-install.md", + "CI-FLAKE-01-Playwright-retries-trace-video-on-first-retry-CI-only": "doc/knowledge/junie-tasks/taskset-3/CI-FLAKE-01-Playwright-retries-trace-video-on-first-retry-CI-only.md", + "ci-flake-01-playwright-retries-trace-video-on-first-retry-ci-only": "doc/knowledge/junie-tasks/taskset-3/CI-FLAKE-01-Playwright-retries-trace-video-on-first-retry-CI-only.md", + "CI-PERF-01-Add-concurrency-cancel-in-progress-for-PRs": "doc/knowledge/junie-tasks/taskset-3/CI-PERF-01-Add-concurrency-cancel-in-progress-for-PRs.md", + "ci-perf-01-add-concurrency-cancel-in-progress-for-prs": "doc/knowledge/junie-tasks/taskset-3/CI-PERF-01-Add-concurrency-cancel-in-progress-for-PRs.md", + "CI-PERF-02-Use-npm-cache-properly-avoid-caching-node-modules": "doc/knowledge/junie-tasks/taskset-3/CI-PERF-02-Use-npm-cache-properly-avoid-caching-node-modules.md", + "ci-perf-02-use-npm-cache-properly-avoid-caching-node-modules": "doc/knowledge/junie-tasks/taskset-3/CI-PERF-02-Use-npm-cache-properly-avoid-caching-node-modules.md", + "CI-PIN-01-Pin-third-party-GitHub-Actions-versions-avoid-master": "doc/knowledge/junie-tasks/taskset-3/CI-PIN-01-Pin-third-party-GitHub-Actions-versions-avoid-master.md", + "ci-pin-01-pin-third-party-github-actions-versions-avoid-master": "doc/knowledge/junie-tasks/taskset-3/CI-PIN-01-Pin-third-party-GitHub-Actions-versions-avoid-master.md", + "E2E-CI-01-Start-backend-frontend-in-CI-and-run-Playwright-E2E-suite": "doc/knowledge/junie-tasks/taskset-3/E2E-CI-01-Start-backend-frontend-in-CI-and-run-Playwright-E2E-suite.md", + "e2e-ci-01-start-backend-frontend-in-ci-and-run-playwright-e2e-suite": "doc/knowledge/junie-tasks/taskset-3/E2E-CI-01-Start-backend-frontend-in-CI-and-run-Playwright-E2E-suite.md", + "iteration2": "doc/knowledge/junie-tasks/taskset-3/iteration2.md", + "QA-COV-01-Make-coverage-generation-explicit-enforced": "doc/knowledge/junie-tasks/taskset-3/QA-COV-01-Make-coverage-generation-explicit-enforced.md", + "qa-cov-01-make-coverage-generation-explicit-enforced": "doc/knowledge/junie-tasks/taskset-3/QA-COV-01-Make-coverage-generation-explicit-enforced.md", + "QA-PATHS-01-Add-path-filters-to-heavy-jobs": "doc/knowledge/junie-tasks/taskset-3/QA-PATHS-01-Add-path-filters-to-heavy-jobs.md", + "qa-paths-01-add-path-filters-to-heavy-jobs": "doc/knowledge/junie-tasks/taskset-3/QA-PATHS-01-Add-path-filters-to-heavy-jobs.md", + "REL-01-Add-build-metadata-to-artifacts-and-UI": "doc/knowledge/junie-tasks/taskset-3/REL-01-Add-build-metadata-to-artifacts-and-UI.md", + "rel-01-add-build-metadata-to-artifacts-and-ui": "doc/knowledge/junie-tasks/taskset-3/REL-01-Add-build-metadata-to-artifacts-and-UI.md", + "SEC-SARIF-01-Upload-Snyk-SARIF-to-GitHub-Code-Scanning": "doc/knowledge/junie-tasks/taskset-3/SEC-SARIF-01-Upload-Snyk-SARIF-to-GitHub-Code-Scanning.md", + "sec-sarif-01-upload-snyk-sarif-to-github-code-scanning": "doc/knowledge/junie-tasks/taskset-3/SEC-SARIF-01-Upload-Snyk-SARIF-to-GitHub-Code-Scanning.md", + "SEC-SARIF-02-Upload-Trivy-results-as-SARIF-optional-but-recommended": "doc/knowledge/junie-tasks/taskset-3/SEC-SARIF-02-Upload-Trivy-results-as-SARIF-optional-but-recommended.md", + "sec-sarif-02-upload-trivy-results-as-sarif-optional-but-recommended": "doc/knowledge/junie-tasks/taskset-3/SEC-SARIF-02-Upload-Trivy-results-as-SARIF-optional-but-recommended.md", + "graphana-config": "doc/knowledge/junie-tasks/taskset-4/graphana-config.md", + "graphana-debug": "doc/knowledge/junie-tasks/taskset-4/graphana-debug.md", + "OBS-ERR-01-Frontend-Error-Boundary-Support-Context": "doc/knowledge/junie-tasks/taskset-4/OBS-ERR-01-Frontend-Error-Boundary-Support-Context.md", + "obs-err-01-frontend-error-boundary-support-context": "doc/knowledge/junie-tasks/taskset-4/OBS-ERR-01-Frontend-Error-Boundary-Support-Context.md", + "OBS-LOG-01-Structured-Logging-Standard": "doc/knowledge/junie-tasks/taskset-4/OBS-LOG-01-Structured-Logging-Standard.md", + "obs-log-01-structured-logging-standard": "doc/knowledge/junie-tasks/taskset-4/OBS-LOG-01-Structured-Logging-Standard.md", + "OBS-MET-01-Basic-Metrics-Exposure": "doc/knowledge/junie-tasks/taskset-4/OBS-MET-01-Basic-Metrics-Exposure.md", + "obs-met-01-basic-metrics-exposure": "doc/knowledge/junie-tasks/taskset-4/OBS-MET-01-Basic-Metrics-Exposure.md", + "OBS-MET-02-Metrics-ON-AWS": "doc/knowledge/junie-tasks/taskset-4/OBS-MET-02-Metrics-ON-AWS.md", + "obs-met-02-metrics-on-aws": "doc/knowledge/junie-tasks/taskset-4/OBS-MET-02-Metrics-ON-AWS.md", + "OBS-MET-03-Metrics-ON-AWS": "doc/knowledge/junie-tasks/taskset-4/OBS-MET-03-Metrics-ON-AWS.md", + "obs-met-03-metrics-on-aws": "doc/knowledge/junie-tasks/taskset-4/OBS-MET-03-Metrics-ON-AWS.md", + "OBS-TRACE-01-Correlation-ID-Propagation": "doc/knowledge/junie-tasks/taskset-4/OBS-TRACE-01-Correlation-ID-Propagation.md", + "obs-trace-01-correlation-id-propagation": "doc/knowledge/junie-tasks/taskset-4/OBS-TRACE-01-Correlation-ID-Propagation.md", + "OPS-RUN-01-Operations-Runbook": "doc/knowledge/junie-tasks/taskset-4/OPS-RUN-01-Operations-Runbook.md", + "ops-run-01-operations-runbook": "doc/knowledge/junie-tasks/taskset-4/OPS-RUN-01-Operations-Runbook.md", + "API-CONTRACT-01-OpenAPI-Contract-Tests": "doc/knowledge/junie-tasks/taskset-5/API-CONTRACT-01-OpenAPI-Contract-Tests.md", + "api-contract-01-openapi-contract-tests": "doc/knowledge/junie-tasks/taskset-5/API-CONTRACT-01-OpenAPI-Contract-Tests.md", + "DB-MIG-01-Database-Migration-Tests": "doc/knowledge/junie-tasks/taskset-5/DB-MIG-01-Database-Migration-Tests.md", + "db-mig-01-database-migration-tests": "doc/knowledge/junie-tasks/taskset-5/DB-MIG-01-Database-Migration-Tests.md", + "E2E-GOLD-01-Expand-Golden-Path-E2E-Tests": "doc/knowledge/junie-tasks/taskset-5/E2E-GOLD-01-Expand-Golden-Path-E2E-Tests.md", + "e2e-gold-01-expand-golden-path-e2e-tests": "doc/knowledge/junie-tasks/taskset-5/E2E-GOLD-01-Expand-Golden-Path-E2E-Tests.md", + "E2E-NEG-01-Negative-Path-E2E-Tests": "doc/knowledge/junie-tasks/taskset-5/E2E-NEG-01-Negative-Path-E2E-Tests.md", + "e2e-neg-01-negative-path-e2e-tests": "doc/knowledge/junie-tasks/taskset-5/E2E-NEG-01-Negative-Path-E2E-Tests.md", + "VIS-REG-01-Visual-Regression-for-Demo-Screens": "doc/knowledge/junie-tasks/taskset-5/VIS-REG-01-Visual-Regression-for-Demo-Screens.md", + "vis-reg-01-visual-regression-for-demo-screens": "doc/knowledge/junie-tasks/taskset-5/VIS-REG-01-Visual-Regression-for-Demo-Screens.md", + "SEC-AUD-01-Audit-Events": "doc/knowledge/junie-tasks/taskset-6/SEC-AUD-01-Audit-Events.md", + "sec-aud-01-audit-events": "doc/knowledge/junie-tasks/taskset-6/SEC-AUD-01-Audit-Events.md", + "SEC-HEAD-02-CSP-Tightening": "doc/knowledge/junie-tasks/taskset-6/SEC-HEAD-02-CSP-Tightening.md", + "sec-head-02-csp-tightening": "doc/knowledge/junie-tasks/taskset-6/SEC-HEAD-02-CSP-Tightening.md", + "SEC-RATE-01-Rate-Limiting-slide": "doc/knowledge/junie-tasks/taskset-6/SEC-RATE-01-Rate-Limiting-slide.md", + "sec-rate-01-rate-limiting-slide": "doc/knowledge/junie-tasks/taskset-6/SEC-RATE-01-Rate-Limiting-slide.md", + "SEC-RATE-01-Rate-Limiting": "doc/knowledge/junie-tasks/taskset-6/SEC-RATE-01-Rate-Limiting.md", + "sec-rate-01-rate-limiting": "doc/knowledge/junie-tasks/taskset-6/SEC-RATE-01-Rate-Limiting.md", + "SEC-SAST-01-Actionable-SAST-Gates": "doc/knowledge/junie-tasks/taskset-6/SEC-SAST-01-Actionable-SAST-Gates.md", + "sec-sast-01-actionable-sast-gates": "doc/knowledge/junie-tasks/taskset-6/SEC-SAST-01-Actionable-SAST-Gates.md", + "SEC-TM-01-Lightweight-Threat-Model": "doc/knowledge/junie-tasks/taskset-6/SEC-TM-01-Lightweight-Threat-Model.md", + "sec-tm-01-lightweight-threat-model": "doc/knowledge/junie-tasks/taskset-6/SEC-TM-01-Lightweight-Threat-Model.md", + "DEPLOY-PIPE-01-Optional-CD-to-Demo-Environment": "doc/knowledge/junie-tasks/taskset-7/DEPLOY-PIPE-01-Optional-CD-to-Demo-Environment.md", + "deploy-pipe-01-optional-cd-to-demo-environment": "doc/knowledge/junie-tasks/taskset-7/DEPLOY-PIPE-01-Optional-CD-to-Demo-Environment.md", + "DOC-SNAP-01-Documentation-Snapshot-per-Release": "doc/knowledge/junie-tasks/taskset-7/DOC-SNAP-01-Documentation-Snapshot-per-Release.md", + "doc-snap-01-documentation-snapshot-per-release": "doc/knowledge/junie-tasks/taskset-7/DOC-SNAP-01-Documentation-Snapshot-per-Release.md", + "ENV-SYNC-01-Configuration-Drift-Protection": "doc/knowledge/junie-tasks/taskset-7/ENV-SYNC-01-Configuration-Drift-Protection.md", + "env-sync-01-configuration-drift-protection": "doc/knowledge/junie-tasks/taskset-7/ENV-SYNC-01-Configuration-Drift-Protection.md", + "REL-NOTES-01-Automated-Release-Notes": "doc/knowledge/junie-tasks/taskset-7/REL-NOTES-01-Automated-Release-Notes.md", + "rel-notes-01-automated-release-notes": "doc/knowledge/junie-tasks/taskset-7/REL-NOTES-01-Automated-Release-Notes.md", + "REL-SEM-01-Semantic-Versioning": "doc/knowledge/junie-tasks/taskset-7/REL-SEM-01-Semantic-Versioning.md", + "rel-sem-01-semantic-versioning": "doc/knowledge/junie-tasks/taskset-7/REL-SEM-01-Semantic-Versioning.md", + "SONAR-V7-02-Sustainable-Fix-for-Sonar-Issues": "doc/knowledge/junie-tasks/taskset-7/SONAR-V7-02-Sustainable-Fix-for-Sonar-Issues.md", + "sonar-v7-02-sustainable-fix-for-sonar-issues": "doc/knowledge/junie-tasks/taskset-7/SONAR-V7-02-Sustainable-Fix-for-Sonar-Issues.md", + "AUTH-DEPLOY-01-Fix-Fargate-auth-inconsistency": "doc/knowledge/junie-tasks/taskset-8/AUTH-DEPLOY-01-Fix-Fargate-auth-inconsistency.md", + "auth-deploy-01-fix-fargate-auth-inconsistency": "doc/knowledge/junie-tasks/taskset-8/AUTH-DEPLOY-01-Fix-Fargate-auth-inconsistency.md", + "E2E-01-Add-navigation-regression-suite": "doc/knowledge/junie-tasks/taskset-8/E2E-01-Add-navigation-regression-suite.md", + "e2e-01-add-navigation-regression-suite": "doc/knowledge/junie-tasks/taskset-8/E2E-01-Add-navigation-regression-suite.md", + "E2E-02-Add-no-console-errors-guardrail": "doc/knowledge/junie-tasks/taskset-8/E2E-02-Add-no-console-errors-guardrail.md", + "e2e-02-add-no-console-errors-guardrail": "doc/knowledge/junie-tasks/taskset-8/E2E-02-Add-no-console-errors-guardrail.md", + "E2E-03-Add-Auth-state-consistency-tests": "doc/knowledge/junie-tasks/taskset-8/E2E-03-Add-Auth-state-consistency-tests.md", + "e2e-03-add-auth-state-consistency-tests": "doc/knowledge/junie-tasks/taskset-8/E2E-03-Add-Auth-state-consistency-tests.md", + "LEGAL-01-Fix-exception-on-closing-Terms-Legal-dialog": "doc/knowledge/junie-tasks/taskset-8/LEGAL-01-Fix-exception-on-closing-Terms-Legal-dialog.md", + "legal-01-fix-exception-on-closing-terms-legal-dialog": "doc/knowledge/junie-tasks/taskset-8/LEGAL-01-Fix-exception-on-closing-Terms-Legal-dialog.md", + "NAV-01-Fix-hamburger-menu-on-mobile": "doc/knowledge/junie-tasks/taskset-8/NAV-01-Fix-hamburger-menu-on-mobile.md", + "nav-01-fix-hamburger-menu-on-mobile": "doc/knowledge/junie-tasks/taskset-8/NAV-01-Fix-hamburger-menu-on-mobile.md", + "NAV-02-Fix-tablet-collapse-expand": "doc/knowledge/junie-tasks/taskset-8/NAV-02-Fix-tablet-collapse-expand.md", + "nav-02-fix-tablet-collapse-expand": "doc/knowledge/junie-tasks/taskset-8/NAV-02-Fix-tablet-collapse-expand.md", + "UX-NAV-01-Improve-visible-affordance-for-nav-state": "doc/knowledge/junie-tasks/taskset-8/UX-NAV-01-Improve-visible-affordance-for-nav-state.md", + "ux-nav-01-improve-visible-affordance-for-nav-state": "doc/knowledge/junie-tasks/taskset-8/UX-NAV-01-Improve-visible-affordance-for-nav-state.md", + "UX-UA-01-Fix-mobile-action-buttons": "doc/knowledge/junie-tasks/taskset-8/UX-UA-01-Fix-mobile-action-buttons.md", + "ux-ua-01-fix-mobile-action-buttons": "doc/knowledge/junie-tasks/taskset-8/UX-UA-01-Fix-mobile-action-buttons.md", + "taskset-ux-19-25-execution-plan": "doc/knowledge/junie-tasks/taskset-9/p3/taskset-ux-19-25-execution-plan.md", + "taskset-ux-19-25-roadmap": "doc/knowledge/junie-tasks/taskset-9/p3/taskset-ux-19-25-roadmap.md", + "taskset-ux-26-31-execution-plan": "doc/knowledge/junie-tasks/taskset-9/p3/taskset-ux-26-31-execution-plan.md", + "taskset-ux-26-31-index": "doc/knowledge/junie-tasks/taskset-9/p3/taskset-ux-26-31-index.md", + "taskset-ux-26-31-roadmap": "doc/knowledge/junie-tasks/taskset-9/p3/taskset-ux-26-31-roadmap.md", + "junie-task-enforce-acceptance-checkbox-all-tasksets": "doc/knowledge/junie-tasks/taskset-9/p4/junie-task-enforce-acceptance-checkbox-all-tasksets.md", + "junie-task-normalize-acceptance-checkbox-taskset-9": "doc/knowledge/junie-tasks/taskset-9/p4/junie-task-normalize-acceptance-checkbox-taskset-9.md", + "junie-task-template-generator-with-acceptance-confirmation": "doc/knowledge/junie-tasks/taskset-9/p4/junie-task-template-generator-with-acceptance-confirmation.md", + "ai-golden-snapshots": "doc/knowledge/reports/ai-golden-snapshots.md", + "coverage-metrics-definitions": "doc/knowledge/reports/coverage-metrics-definitions.md", + "demo-scenario-baseline": "doc/knowledge/reports/demo-scenario-baseline.md", + "ollama-latency-benchmarks": "doc/knowledge/reports/ollama-latency-benchmarks.md", + "guardrails-ci-guide": "doc/knowledge/task-governance/guardrails-ci-guide.md", + "sprint-2.0-task-id-uniqueness-report": "doc/knowledge/task-governance/sprint-2.0-task-id-uniqueness-report.md", + "RUNBOOK": "doc/operations/RUNBOOK.md", + "runbook": "doc/operations/RUNBOOK.md", + "architecture-overview-snippet": "doc/readme-assets/architecture-overview-snippet.md", + "feature-cards-section": "doc/readme-assets/feature-cards-section.md", + "feature-overview-snippet": "doc/readme-assets/feature-overview-snippet.md", + "github-badges-snippet": "doc/readme-assets/github-badges-snippet.md", + "intelligence-map-snippet": "doc/readme-assets/intelligence-map-snippet.md", + "readme-hero-snippet": "doc/readme-assets/readme-hero-snippet.md", + "release-hardening-deferred-issues": "doc/release/release-hardening-deferred-issues.md", + "static-analysis-conflict-matrix": "doc/release/static-analysis-conflict-matrix.md", + "2026-02-26-Swagger-401-Unauthorized-Fix": "doc/troubleshooting/2026-02-26-Swagger-401-Unauthorized-Fix.md", + "2026-02-26-swagger-401-unauthorized-fix": "doc/troubleshooting/2026-02-26-Swagger-401-Unauthorized-Fix.md", + "faq_de": "doc/user-guide/faq_de.md", + "user-guide_de": "doc/user-guide/user-guide_de.md", + "forgot-password-ui-guide": "doc/user-guide/workflows/forgot-password-ui-guide.md", + "navigation-guide": "doc/user-guide/workflows/navigation-guide.md", + "registration-ui-guide": "doc/user-guide/workflows/registration-ui-guide.md", + "HELP": "backend/HELP.md", + "help": "backend/HELP.md", + "coverage": "backend/doc/knowledge/reports/coverage.md", + "no-reindex": "backend/src/test/resources/test-docs/no-reindex.md", + "test-uploaded-no-csrf": "backend/src/test/resources/test-docs/test-uploaded-no-csrf.md", + "test": "backend/src/test/resources/test-docs/test.md", + "conflicting-adr-1": "frontend/e2e/data/ai-stability/conflicting-adr-1.md", + "conflicting-adr-2": "frontend/e2e/data/ai-stability/conflicting-adr-2.md", + "duplicate-adr-v2": "frontend/e2e/data/ai-stability/duplicate-adr-v2.md", + "duplicate-adr": "frontend/e2e/data/ai-stability/duplicate-adr.md", + "missing-ref": "frontend/e2e/data/ai-stability/missing-ref.md", + "CHANGELOG": "frontend/node/node_modules/corepack/CHANGELOG.md", + "changelog": "frontend/node/node_modules/corepack/CHANGELOG.md", + "LICENSE": "frontend/node/node_modules/corepack/LICENSE.md", + "license": "frontend/node/node_modules/corepack/LICENSE.md", + "npm-access": "frontend/node/node_modules/npm/docs/content/commands/npm-access.md", + "npm-adduser": "frontend/node/node_modules/npm/docs/content/commands/npm-adduser.md", + "npm-audit": "frontend/node/node_modules/npm/docs/content/commands/npm-audit.md", + "npm-bugs": "frontend/node/node_modules/npm/docs/content/commands/npm-bugs.md", + "npm-cache": "frontend/node/node_modules/npm/docs/content/commands/npm-cache.md", + "npm-ci": "frontend/node/node_modules/npm/docs/content/commands/npm-ci.md", + "npm-completion": "frontend/node/node_modules/npm/docs/content/commands/npm-completion.md", + "npm-config": "frontend/node/node_modules/npm/docs/content/commands/npm-config.md", + "npm-dedupe": "frontend/node/node_modules/npm/docs/content/commands/npm-dedupe.md", + "npm-deprecate": "frontend/node/node_modules/npm/docs/content/commands/npm-deprecate.md", + "npm-diff": "frontend/node/node_modules/npm/docs/content/commands/npm-diff.md", + "npm-dist-tag": "frontend/node/node_modules/npm/docs/content/commands/npm-dist-tag.md", + "npm-docs": "frontend/node/node_modules/npm/docs/content/commands/npm-docs.md", + "npm-doctor": "frontend/node/node_modules/npm/docs/content/commands/npm-doctor.md", + "npm-edit": "frontend/node/node_modules/npm/docs/content/commands/npm-edit.md", + "npm-exec": "frontend/node/node_modules/npm/docs/content/commands/npm-exec.md", + "npm-explain": "frontend/node/node_modules/npm/docs/content/commands/npm-explain.md", + "npm-explore": "frontend/node/node_modules/npm/docs/content/commands/npm-explore.md", + "npm-find-dupes": "frontend/node/node_modules/npm/docs/content/commands/npm-find-dupes.md", + "npm-fund": "frontend/node/node_modules/npm/docs/content/commands/npm-fund.md", + "npm-help-search": "frontend/node/node_modules/npm/docs/content/commands/npm-help-search.md", + "npm-help": "frontend/node/node_modules/npm/docs/content/commands/npm-help.md", + "npm-hook": "frontend/node/node_modules/npm/docs/content/commands/npm-hook.md", + "npm-init": "frontend/node/node_modules/npm/docs/content/commands/npm-init.md", + "npm-install-ci-test": "frontend/node/node_modules/npm/docs/content/commands/npm-install-ci-test.md", + "npm-install-test": "frontend/node/node_modules/npm/docs/content/commands/npm-install-test.md", + "npm-install": "frontend/node/node_modules/npm/docs/content/commands/npm-install.md", + "npm-link": "frontend/node/node_modules/npm/docs/content/commands/npm-link.md", + "npm-login": "frontend/node/node_modules/npm/docs/content/commands/npm-login.md", + "npm-logout": "frontend/node/node_modules/npm/docs/content/commands/npm-logout.md", + "npm-ls": "frontend/node/node_modules/npm/docs/content/commands/npm-ls.md", + "npm-org": "frontend/node/node_modules/npm/docs/content/commands/npm-org.md", + "npm-outdated": "frontend/node/node_modules/npm/docs/content/commands/npm-outdated.md", + "npm-owner": "frontend/node/node_modules/npm/docs/content/commands/npm-owner.md", + "npm-pack": "frontend/node/node_modules/npm/docs/content/commands/npm-pack.md", + "npm-ping": "frontend/node/node_modules/npm/docs/content/commands/npm-ping.md", + "npm-pkg": "frontend/node/node_modules/npm/docs/content/commands/npm-pkg.md", + "npm-prefix": "frontend/node/node_modules/npm/docs/content/commands/npm-prefix.md", + "npm-profile": "frontend/node/node_modules/npm/docs/content/commands/npm-profile.md", + "npm-prune": "frontend/node/node_modules/npm/docs/content/commands/npm-prune.md", + "npm-publish": "frontend/node/node_modules/npm/docs/content/commands/npm-publish.md", + "npm-query": "frontend/node/node_modules/npm/docs/content/commands/npm-query.md", + "npm-rebuild": "frontend/node/node_modules/npm/docs/content/commands/npm-rebuild.md", + "npm-repo": "frontend/node/node_modules/npm/docs/content/commands/npm-repo.md", + "npm-restart": "frontend/node/node_modules/npm/docs/content/commands/npm-restart.md", + "npm-root": "frontend/node/node_modules/npm/docs/content/commands/npm-root.md", + "npm-run-script": "frontend/node/node_modules/npm/docs/content/commands/npm-run-script.md", + "npm-sbom": "frontend/node/node_modules/npm/docs/content/commands/npm-sbom.md", + "npm-search": "frontend/node/node_modules/npm/docs/content/commands/npm-search.md", + "npm-shrinkwrap": "frontend/node/node_modules/npm/docs/content/commands/npm-shrinkwrap.md", + "npm-star": "frontend/node/node_modules/npm/docs/content/commands/npm-star.md", + "npm-stars": "frontend/node/node_modules/npm/docs/content/commands/npm-stars.md", + "npm-start": "frontend/node/node_modules/npm/docs/content/commands/npm-start.md", + "npm-stop": "frontend/node/node_modules/npm/docs/content/commands/npm-stop.md", + "npm-team": "frontend/node/node_modules/npm/docs/content/commands/npm-team.md", + "npm-test": "frontend/node/node_modules/npm/docs/content/commands/npm-test.md", + "npm-token": "frontend/node/node_modules/npm/docs/content/commands/npm-token.md", + "npm-uninstall": "frontend/node/node_modules/npm/docs/content/commands/npm-uninstall.md", + "npm-unpublish": "frontend/node/node_modules/npm/docs/content/commands/npm-unpublish.md", + "npm-unstar": "frontend/node/node_modules/npm/docs/content/commands/npm-unstar.md", + "npm-update": "frontend/node/node_modules/npm/docs/content/commands/npm-update.md", + "npm-version": "frontend/node/node_modules/npm/docs/content/commands/npm-version.md", + "npm-view": "frontend/node/node_modules/npm/docs/content/commands/npm-view.md", + "npm-whoami": "frontend/node/node_modules/npm/docs/content/commands/npm-whoami.md", + "npm": "frontend/node/node_modules/npm/docs/content/commands/npm.md", + "npx": "frontend/node/node_modules/npm/docs/content/commands/npx.md", + "folders": "frontend/node/node_modules/npm/docs/content/configuring-npm/folders.md", + "install": "frontend/node/node_modules/npm/docs/content/configuring-npm/install.md", + "npm-shrinkwrap-json": "frontend/node/node_modules/npm/docs/content/configuring-npm/npm-shrinkwrap-json.md", + "npmrc": "frontend/node/node_modules/npm/docs/content/configuring-npm/npmrc.md", + "package-json": "frontend/node/node_modules/npm/docs/content/configuring-npm/package-json.md", + "package-lock-json": "frontend/node/node_modules/npm/docs/content/configuring-npm/package-lock-json.md", + "config": "frontend/node/node_modules/npm/docs/content/using-npm/config.md", + "dependency-selectors": "frontend/node/node_modules/npm/docs/content/using-npm/dependency-selectors.md", + "developers": "frontend/node/node_modules/npm/docs/content/using-npm/developers.md", + "logging": "frontend/node/node_modules/npm/docs/content/using-npm/logging.md", + "orgs": "frontend/node/node_modules/npm/docs/content/using-npm/orgs.md", + "package-spec": "frontend/node/node_modules/npm/docs/content/using-npm/package-spec.md", + "registry": "frontend/node/node_modules/npm/docs/content/using-npm/registry.md", + "removal": "frontend/node/node_modules/npm/docs/content/using-npm/removal.md", + "scope": "frontend/node/node_modules/npm/docs/content/using-npm/scope.md", + "scripts": "frontend/node/node_modules/npm/docs/content/using-npm/scripts.md", + "workspaces": "frontend/node/node_modules/npm/docs/content/using-npm/workspaces.md", + "HISTORY": "frontend/node/node_modules/npm/node_modules/make-fetch-happen/node_modules/negotiator/HISTORY.md", + "history": "frontend/node/node_modules/npm/node_modules/make-fetch-happen/node_modules/negotiator/HISTORY.md", + "CODE_OF_CONDUCT": "frontend/node/node_modules/npm/node_modules/node-gyp/CODE_OF_CONDUCT.md", + "code_of_conduct": "frontend/node/node_modules/npm/node_modules/node-gyp/CODE_OF_CONDUCT.md", + "SECURITY": "frontend/node/node_modules/npm/node_modules/node-gyp/SECURITY.md", + "security": "frontend/node/node_modules/npm/node_modules/node-gyp/SECURITY.md", + "GypVsCMake": "frontend/node/node_modules/npm/node_modules/node-gyp/gyp/docs/GypVsCMake.md", + "gypvscmake": "frontend/node/node_modules/npm/node_modules/node-gyp/gyp/docs/GypVsCMake.md", + "Hacking": "frontend/node/node_modules/npm/node_modules/node-gyp/gyp/docs/Hacking.md", + "hacking": "frontend/node/node_modules/npm/node_modules/node-gyp/gyp/docs/Hacking.md", + "InputFormatReference": "frontend/node/node_modules/npm/node_modules/node-gyp/gyp/docs/InputFormatReference.md", + "inputformatreference": "frontend/node/node_modules/npm/node_modules/node-gyp/gyp/docs/InputFormatReference.md", + "LanguageSpecification": "frontend/node/node_modules/npm/node_modules/node-gyp/gyp/docs/LanguageSpecification.md", + "languagespecification": "frontend/node/node_modules/npm/node_modules/node-gyp/gyp/docs/LanguageSpecification.md", + "Testing": "frontend/node/node_modules/npm/node_modules/node-gyp/gyp/docs/Testing.md", + "testing": "frontend/node/node_modules/npm/node_modules/node-gyp/gyp/docs/Testing.md", + "UserDocumentation": "frontend/node/node_modules/npm/node_modules/node-gyp/gyp/docs/UserDocumentation.md", + "userdocumentation": "frontend/node/node_modules/npm/node_modules/node-gyp/gyp/docs/UserDocumentation.md", + "API": "frontend/node/node_modules/npm/node_modules/postcss-selector-parser/API.md", + "api": "frontend/node/node_modules/npm/node_modules/postcss-selector-parser/API.md", + "Porting-Buffer": "frontend/node/node_modules/npm/node_modules/safer-buffer/Porting-Buffer.md", + "porting-buffer": "frontend/node/node_modules/npm/node_modules/safer-buffer/Porting-Buffer.md", + "migratingFromV1": "frontend/node/node_modules/npm/node_modules/socks/docs/migratingFromV1.md", + "migratingfromv1": "frontend/node/node_modules/npm/node_modules/socks/docs/migratingFromV1.md", + "associateExample": "frontend/node/node_modules/npm/node_modules/socks/docs/examples/javascript/associateExample.md", + "associateexample": "frontend/node/node_modules/npm/node_modules/socks/docs/examples/javascript/associateExample.md", + "bindExample": "frontend/node/node_modules/npm/node_modules/socks/docs/examples/javascript/bindExample.md", + "bindexample": "frontend/node/node_modules/npm/node_modules/socks/docs/examples/javascript/bindExample.md", + "connectExample": "frontend/node/node_modules/npm/node_modules/socks/docs/examples/javascript/connectExample.md", + "connectexample": "frontend/node/node_modules/npm/node_modules/socks/docs/examples/javascript/connectExample.md", + "CONTRIBUTORS": "frontend/node/node_modules/npm/node_modules/sprintf-js/CONTRIBUTORS.md", + "contributors": "frontend/node/node_modules/npm/node_modules/sprintf-js/CONTRIBUTORS.md", + "History": "frontend/node/node_modules/npm/node_modules/util-deprecate/History.md", + "long-description": "frontend/node_modules/@angular/cli/src/commands/add/long-description.md", + "ai-tutor": "frontend/node_modules/@angular/cli/src/commands/mcp/resources/ai-tutor.md", + "best-practices": "frontend/node_modules/@angular/cli/src/commands/mcp/resources/best-practices.md", + "Readme": "frontend/node_modules/@leichtgewicht/ip-codec/Readme.md", + "CHANGES": "frontend/node_modules/chrome-trace-event/CHANGES.md", + "changes": "frontend/node_modules/chrome-trace-event/CHANGES.md", + "LICENCE": "frontend/node_modules/decimal.js/LICENCE.md", + "licence": "frontend/node_modules/decimal.js/LICENCE.md", + "GOVERNANCE": "frontend/node_modules/hpack.js/node_modules/readable-stream/GOVERNANCE.md", + "governance": "frontend/node_modules/hpack.js/node_modules/readable-stream/GOVERNANCE.md", + "2015-01-30": "frontend/node_modules/hpack.js/node_modules/readable-stream/doc/wg-meetings/2015-01-30.md", + "DOCUMENTATION": "frontend/node_modules/license-webpack-plugin/DOCUMENTATION.md", + "documentation": "frontend/node_modules/license-webpack-plugin/DOCUMENTATION.md", + "MIGRATION": "frontend/node_modules/license-webpack-plugin/MIGRATION.md", + "migration": "frontend/node_modules/license-webpack-plugin/MIGRATION.md", + "benchmark": "frontend/node_modules/msgpackr/benchmark.md", + "Changelog": "frontend/node_modules/needle/node_modules/iconv-lite/Changelog.md", + "Introduction": "frontend/node_modules/piscina/docs/docs/Introduction.md", + "introduction": "frontend/node_modules/piscina/docs/docs/Introduction.md", + "class": "frontend/node_modules/piscina/docs/docs/api-reference/class.md", + "event": "frontend/node_modules/piscina/docs/docs/api-reference/event.md", + "interface": "frontend/node_modules/piscina/docs/docs/api-reference/interface.md", + "method": "frontend/node_modules/piscina/docs/docs/api-reference/method.md", + "property": "frontend/node_modules/piscina/docs/docs/api-reference/property.md", + "static-property": "frontend/node_modules/piscina/docs/docs/api-reference/static-property.md", + "playwright-test-coverage.prompt": "frontend/node_modules/playwright/lib/agents/playwright-test-coverage.prompt.md", + "playwright-test-generate.prompt": "frontend/node_modules/playwright/lib/agents/playwright-test-generate.prompt.md", + "playwright-test-generator.agent": "frontend/node_modules/playwright/lib/agents/playwright-test-generator.agent.md", + "playwright-test-heal.prompt": "frontend/node_modules/playwright/lib/agents/playwright-test-heal.prompt.md", + "playwright-test-healer.agent": "frontend/node_modules/playwright/lib/agents/playwright-test-healer.agent.md", + "playwright-test-plan.prompt": "frontend/node_modules/playwright/lib/agents/playwright-test-plan.prompt.md", + "playwright-test-planner.agent": "frontend/node_modules/playwright/lib/agents/playwright-test-planner.agent.md", + "THREAT_MODEL": "frontend/node_modules/qs/.github/THREAT_MODEL.md", + "threat_model": "frontend/node_modules/qs/.github/THREAT_MODEL.md", + "AUTHORS": "frontend/node_modules/reflect-metadata/AUTHORS.md", + "authors": "frontend/node_modules/reflect-metadata/AUTHORS.md", + "INCIDENT_RESPONSE_PROCESS": "frontend/node_modules/resolve/.github/INCIDENT_RESPONSE_PROCESS.md", + "incident_response_process": "frontend/node_modules/resolve/.github/INCIDENT_RESPONSE_PROCESS.md", + "advanced-features": "frontend/node_modules/resolve-url-loader/docs/advanced-features.md", + "how-it-works": "frontend/node_modules/resolve-url-loader/docs/how-it-works.md", + "troubleshooting": "frontend/node_modules/resolve-url-loader/docs/troubleshooting.md", + "README_v3": "frontend/node_modules/smart-buffer/docs/README_v3.md", + "readme_v3": "frontend/node_modules/smart-buffer/docs/README_v3.md", + "PATRONS": "frontend/node_modules/terser/PATRONS.md", + "patrons": "frontend/node_modules/terser/PATRONS.md", + "NODE-LICENSE": "frontend/node_modules/ts-node/dist-raw/NODE-LICENSE.md", + "node-license": "frontend/node_modules/ts-node/dist-raw/NODE-LICENSE.md", + "Agent": "frontend/node_modules/undici/docs/docs/api/Agent.md", + "agent": "frontend/node_modules/undici/docs/docs/api/Agent.md", + "api-lifecycle": "frontend/node_modules/undici/docs/docs/api/api-lifecycle.md", + "BalancedPool": "frontend/node_modules/undici/docs/docs/api/BalancedPool.md", + "balancedpool": "frontend/node_modules/undici/docs/docs/api/BalancedPool.md", + "CacheStorage": "frontend/node_modules/undici/docs/docs/api/CacheStorage.md", + "cachestorage": "frontend/node_modules/undici/docs/docs/api/CacheStorage.md", + "CacheStore": "frontend/node_modules/undici/docs/docs/api/CacheStore.md", + "cachestore": "frontend/node_modules/undici/docs/docs/api/CacheStore.md", + "Client": "frontend/node_modules/undici/docs/docs/api/Client.md", + "client": "frontend/node_modules/undici/docs/docs/api/Client.md", + "ClientStats": "frontend/node_modules/undici/docs/docs/api/ClientStats.md", + "clientstats": "frontend/node_modules/undici/docs/docs/api/ClientStats.md", + "Connector": "frontend/node_modules/undici/docs/docs/api/Connector.md", + "connector": "frontend/node_modules/undici/docs/docs/api/Connector.md", + "ContentType": "frontend/node_modules/undici/docs/docs/api/ContentType.md", + "contenttype": "frontend/node_modules/undici/docs/docs/api/ContentType.md", + "Cookies": "frontend/node_modules/undici/docs/docs/api/Cookies.md", + "cookies": "frontend/node_modules/undici/docs/docs/api/Cookies.md", + "Debug": "frontend/node_modules/undici/docs/docs/api/Debug.md", + "debug": "frontend/node_modules/undici/docs/docs/api/Debug.md", + "DiagnosticsChannel": "frontend/node_modules/undici/docs/docs/api/DiagnosticsChannel.md", + "diagnosticschannel": "frontend/node_modules/undici/docs/docs/api/DiagnosticsChannel.md", + "Dispatcher": "frontend/node_modules/undici/docs/docs/api/Dispatcher.md", + "dispatcher": "frontend/node_modules/undici/docs/docs/api/Dispatcher.md", + "EnvHttpProxyAgent": "frontend/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md", + "envhttpproxyagent": "frontend/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md", + "Errors": "frontend/node_modules/undici/docs/docs/api/Errors.md", + "errors": "frontend/node_modules/undici/docs/docs/api/Errors.md", + "EventSource": "frontend/node_modules/undici/docs/docs/api/EventSource.md", + "eventsource": "frontend/node_modules/undici/docs/docs/api/EventSource.md", + "Fetch": "frontend/node_modules/undici/docs/docs/api/Fetch.md", + "fetch": "frontend/node_modules/undici/docs/docs/api/Fetch.md", + "GlobalInstallation": "frontend/node_modules/undici/docs/docs/api/GlobalInstallation.md", + "globalinstallation": "frontend/node_modules/undici/docs/docs/api/GlobalInstallation.md", + "H2CClient": "frontend/node_modules/undici/docs/docs/api/H2CClient.md", + "h2cclient": "frontend/node_modules/undici/docs/docs/api/H2CClient.md", + "MockAgent": "frontend/node_modules/undici/docs/docs/api/MockAgent.md", + "mockagent": "frontend/node_modules/undici/docs/docs/api/MockAgent.md", + "MockCallHistory": "frontend/node_modules/undici/docs/docs/api/MockCallHistory.md", + "mockcallhistory": "frontend/node_modules/undici/docs/docs/api/MockCallHistory.md", + "MockCallHistoryLog": "frontend/node_modules/undici/docs/docs/api/MockCallHistoryLog.md", + "mockcallhistorylog": "frontend/node_modules/undici/docs/docs/api/MockCallHistoryLog.md", + "MockClient": "frontend/node_modules/undici/docs/docs/api/MockClient.md", + "mockclient": "frontend/node_modules/undici/docs/docs/api/MockClient.md", + "MockErrors": "frontend/node_modules/undici/docs/docs/api/MockErrors.md", + "mockerrors": "frontend/node_modules/undici/docs/docs/api/MockErrors.md", + "MockPool": "frontend/node_modules/undici/docs/docs/api/MockPool.md", + "mockpool": "frontend/node_modules/undici/docs/docs/api/MockPool.md", + "Pool": "frontend/node_modules/undici/docs/docs/api/Pool.md", + "pool": "frontend/node_modules/undici/docs/docs/api/Pool.md", + "PoolStats": "frontend/node_modules/undici/docs/docs/api/PoolStats.md", + "poolstats": "frontend/node_modules/undici/docs/docs/api/PoolStats.md", + "ProxyAgent": "frontend/node_modules/undici/docs/docs/api/ProxyAgent.md", + "proxyagent": "frontend/node_modules/undici/docs/docs/api/ProxyAgent.md", + "RedirectHandler": "frontend/node_modules/undici/docs/docs/api/RedirectHandler.md", + "redirecthandler": "frontend/node_modules/undici/docs/docs/api/RedirectHandler.md", + "RetryAgent": "frontend/node_modules/undici/docs/docs/api/RetryAgent.md", + "retryagent": "frontend/node_modules/undici/docs/docs/api/RetryAgent.md", + "RetryHandler": "frontend/node_modules/undici/docs/docs/api/RetryHandler.md", + "retryhandler": "frontend/node_modules/undici/docs/docs/api/RetryHandler.md", + "RoundRobinPool": "frontend/node_modules/undici/docs/docs/api/RoundRobinPool.md", + "roundrobinpool": "frontend/node_modules/undici/docs/docs/api/RoundRobinPool.md", + "SnapshotAgent": "frontend/node_modules/undici/docs/docs/api/SnapshotAgent.md", + "snapshotagent": "frontend/node_modules/undici/docs/docs/api/SnapshotAgent.md", + "Util": "frontend/node_modules/undici/docs/docs/api/Util.md", + "util": "frontend/node_modules/undici/docs/docs/api/Util.md", + "WebSocket": "frontend/node_modules/undici/docs/docs/api/WebSocket.md", + "websocket": "frontend/node_modules/undici/docs/docs/api/WebSocket.md", + "client-certificate": "frontend/node_modules/undici/docs/docs/best-practices/client-certificate.md", + "crawling": "frontend/node_modules/undici/docs/docs/best-practices/crawling.md", + "mocking-request": "frontend/node_modules/undici/docs/docs/best-practices/mocking-request.md", + "proxy": "frontend/node_modules/undici/docs/docs/best-practices/proxy.md", + "writing-tests": "frontend/node_modules/undici/docs/docs/best-practices/writing-tests.md" +} \ No newline at end of file diff --git a/frontend/public/assets/i18n/de-ch.json b/frontend/public/assets/i18n/de-ch.json index 36dc9d12..e1653875 100644 --- a/frontend/public/assets/i18n/de-ch.json +++ b/frontend/public/assets/i18n/de-ch.json @@ -954,5 +954,20 @@ "FALLBACK_USED": "Fallback verwendet", "PROMPT_HASH": "Prompt Hash (Kanonisch)", "CONFIDENCE_SUFFIX": "Vertrauen" + }, + "ONBOARDING_ASSISTANT": { + "TITLE": "KI-Onboarding-Assistent", + "SUBTITLE": "Fragen Sie mich, wie man GoodOne benutzt!", + "CLEAR_HISTORY": "Verlauf löschen", + "WELCOME": "Hallo! Ich bin Ihr KI-Assistent. Sie können mich Dinge fragen wie:", + "Q1": "Was ist die Hauptfunktion dieser Anwendung für Benutzer?", + "Q2": "Wie erstelle ich eine neue Aufgabe?", + "Q3": "Was ist der KI-Risiko-Radar?", + "Q4": "Wo kann ich die Roadmap sehen?", + "THINKING": "Ich überlege...", + "NEXT_STEPS": "Nächste Schritte:", + "RELATED_HELP": "Verwandte Hilfe:", + "INPUT_LABEL": "Stellen Sie eine Frage...", + "SEND_TOOLTIP": "Frage senden" } } diff --git a/frontend/public/assets/i18n/en.json b/frontend/public/assets/i18n/en.json index 12c01566..a4de8863 100644 --- a/frontend/public/assets/i18n/en.json +++ b/frontend/public/assets/i18n/en.json @@ -955,5 +955,20 @@ "FALLBACK_USED": "Fallback used", "PROMPT_HASH": "Prompt Hash (Canonical)", "CONFIDENCE_SUFFIX": "Confidence" + }, + "ONBOARDING_ASSISTANT": { + "TITLE": "AI Onboarding Assistant", + "SUBTITLE": "Ask me how to use GoodOne!", + "CLEAR_HISTORY": "Clear history", + "WELCOME": "Hi! I'm your AI assistant. You can ask me things like:", + "Q1": "What is the main user feature of this application?", + "Q2": "How do I create a new task?", + "Q3": "What is the AI Risk Radar?", + "Q4": "Where can I see the roadmap?", + "THINKING": "Thinking...", + "NEXT_STEPS": "Next Steps:", + "RELATED_HELP": "Related Help:", + "INPUT_LABEL": "Ask a question...", + "SEND_TOOLTIP": "Send question" } } diff --git a/frontend/src/app/components/adr-drift/adr-drift.component.css b/frontend/src/app/components/adr-drift/adr-drift.component.css index 11c08f23..0f0b0509 100644 --- a/frontend/src/app/components/adr-drift/adr-drift.component.css +++ b/frontend/src/app/components/adr-drift/adr-drift.component.css @@ -143,3 +143,16 @@ mat-expansion-panel:last-child { color: var(--text-muted); font-size: 0.85rem; } + +.evidence-link { + color: var(--brand); + text-decoration: none; + border-bottom: 1px dashed var(--brand-weak); + transition: all 0.2s ease; + cursor: pointer; +} + +.evidence-link:hover { + background-color: var(--surface-2); + border-bottom-style: solid; +} diff --git a/frontend/src/app/components/adr-drift/adr-drift.component.html b/frontend/src/app/components/adr-drift/adr-drift.component.html index 1529bc0e..cf9a2d82 100644 --- a/frontend/src/app/components/adr-drift/adr-drift.component.html +++ b/frontend/src/app/components/adr-drift/adr-drift.component.html @@ -137,7 +137,14 @@

    {{ 'ADR_DRIFT.POTENTIAL_DRIFTS' | translate }}

    {{ 'ADR_DRIFT.EVIDENCE' | translate }}:
      @for (ev of drift.taskEvidence; track $index) { -
    • {{ ev }}
    • + @let evidence = parseEvidence(ev); +
    • + @if (evidence.linkUrl) { + {{ evidence.prefix }}{{ evidence.linkText }} + } @else { + {{ ev }} + } +
    • }
    diff --git a/frontend/src/app/components/adr-drift/adr-drift.component.spec.ts b/frontend/src/app/components/adr-drift/adr-drift.component.spec.ts index 7b7c7616..c97d9662 100644 --- a/frontend/src/app/components/adr-drift/adr-drift.component.spec.ts +++ b/frontend/src/app/components/adr-drift/adr-drift.component.spec.ts @@ -147,4 +147,29 @@ describe('AdrDriftComponent', () => { const ts: any = { id: '1', title: 'Sprint 1', type: 'SPRINT' }; expect(component.getTaskGroupLabel(ts)).toContain('Sprint 1'); }); + + describe('parseEvidence', () => { + it('should parse doc path correctly', () => { + const ev = 'Task Source: doc/knowledge/junie-tasks/sprints/sprint-2.2/backend/integration-notes.md'; + const result = component.parseEvidence(ev); + expect(result.prefix).toBe('Task Source: '); + expect(result.linkText).toBe('doc/knowledge/junie-tasks/sprints/sprint-2.2/backend/integration-notes.md'); + expect(result.linkUrl).toBe('/help/doc/knowledge/junie-tasks/sprints/sprint-2.2/backend/integration-notes.md'); + }); + + it('should parse task ID correctly', () => { + const ev = 'AI-INFRA-06 – AI Response Cache Layer'; + const result = component.parseEvidence(ev); + expect(result.prefix).toBeUndefined(); + expect(result.linkText).toBe(ev); + expect(result.linkUrl).toBe('/help/AI-INFRA-06'); + }); + + it('should handle non-link evidence', () => { + const ev = 'Some random evidence text'; + const result = component.parseEvidence(ev); + expect(result.linkUrl).toBe(''); + expect(result.linkText).toBe(ev); + }); + }); }); diff --git a/frontend/src/app/components/adr-drift/adr-drift.component.ts b/frontend/src/app/components/adr-drift/adr-drift.component.ts index 3ccfa1da..5efd6c51 100644 --- a/frontend/src/app/components/adr-drift/adr-drift.component.ts +++ b/frontend/src/app/components/adr-drift/adr-drift.component.ts @@ -15,6 +15,7 @@ import { MatNativeDateModule } from '@angular/material/core'; import { MatSelectModule } from '@angular/material/select'; import { MatTooltipModule } from '@angular/material/tooltip'; import { MatDialog, MatDialogModule } from '@angular/material/dialog'; +import { RouterLink } from '@angular/router'; import { TranslateModule } from '@ngx-translate/core'; import { AdrDriftRequest, AdrDriftResponse } from '../../models/retrospective.model'; import { BaseAiComponent } from '../base/base-ai.component'; @@ -49,6 +50,7 @@ import { IndexingScope } from '../../services/admin.service'; MatSelectModule, MatTooltipModule, MatDialogModule, + RouterLink, TranslateModule, AiDisabledPlaceholderComponent, AiResultComponent, @@ -194,4 +196,31 @@ export class AdrDriftComponent extends BaseAiComponent implements OnInit { panelClass: 'adr-viewer-panel' }); } + + /** + * Parses evidence string to identify file paths or task IDs and return link info. + */ + parseEvidence(ev: string): { prefix?: string, linkText: string, linkUrl: string } { + const docIdx = ev.indexOf('doc/'); + if (docIdx !== -1) { + return { + prefix: ev.substring(0, docIdx), + linkText: ev.substring(docIdx), + linkUrl: '/help/' + ev.substring(docIdx) + }; + } + + const taskMatch = ev.match(/^(AI-|SEC-|sprint-)[^ \s\u2013]*/); + if (taskMatch) { + return { + linkText: ev, + linkUrl: '/help/' + taskMatch[0] + }; + } + + return { + linkText: ev, + linkUrl: '' + }; + } } diff --git a/frontend/src/app/components/ai-document-tree/ai-document-tree.component.html b/frontend/src/app/components/ai-document-tree/ai-document-tree.component.html index bc64d98b..d935b6e2 100644 --- a/frontend/src/app/components/ai-document-tree/ai-document-tree.component.html +++ b/frontend/src/app/components/ai-document-tree/ai-document-tree.component.html @@ -1,20 +1,22 @@ - - - description - {{ node.name }} + +
    + + description + {{ node.name }} -
    - - - - {{ 'AI_COVERAGE.BADGES.' + badge | translate }} - - - +
    + @if (getBadge(node); as badge) { + + + {{ 'AI_COVERAGE.BADGES.' + badge | translate }} + + + } +
    - + diff --git a/frontend/src/app/components/ai-document-tree/ai-document-tree.component.ts b/frontend/src/app/components/ai-document-tree/ai-document-tree.component.ts index ffb96150..6d87add0 100644 --- a/frontend/src/app/components/ai-document-tree/ai-document-tree.component.ts +++ b/frontend/src/app/components/ai-document-tree/ai-document-tree.component.ts @@ -1,5 +1,4 @@ import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core'; -import { CommonModule } from '@angular/common'; import { MatTreeModule, MatTreeNestedDataSource } from '@angular/material/tree'; import { NestedTreeControl } from '@angular/cdk/tree'; import { MatIconModule } from '@angular/material/icon'; @@ -16,7 +15,6 @@ import { FolderNode, StaleReason } from '../../services/ai-admin.service'; selector: 'app-ai-document-tree', standalone: true, imports: [ - CommonModule, MatTreeModule, MatIconModule, MatButtonModule, diff --git a/frontend/src/app/components/error-boundary/error-boundary.component.ts b/frontend/src/app/components/error-boundary/error-boundary.component.ts index ab94fe2c..b0bc1597 100644 --- a/frontend/src/app/components/error-boundary/error-boundary.component.ts +++ b/frontend/src/app/components/error-boundary/error-boundary.component.ts @@ -1,4 +1,4 @@ -import { Component, inject, signal } from '@angular/core'; +import { Component, inject } from '@angular/core'; import { CommonModule } from '@angular/common'; import { MatCardModule } from '@angular/material/card'; import { MatButtonModule } from '@angular/material/button'; diff --git a/frontend/src/app/components/help/help-content.component.html b/frontend/src/app/components/help/help-content.component.html index 62c6b6a8..d14b6979 100644 --- a/frontend/src/app/components/help/help-content.component.html +++ b/frontend/src/app/components/help/help-content.component.html @@ -4,7 +4,11 @@ @if (loading()) {

    {{ 'COMMON.LOADING' | translate }}

    } @else { -
    + @if (rawMarkdown()) { + + } @else { +
    + } } diff --git a/frontend/src/app/components/help/help-content.component.spec.ts b/frontend/src/app/components/help/help-content.component.spec.ts new file mode 100644 index 00000000..29496d8c --- /dev/null +++ b/frontend/src/app/components/help/help-content.component.spec.ts @@ -0,0 +1,144 @@ +import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing'; +import { HelpContentComponent } from './help-content.component'; +import { ActivatedRoute, Router } from '@angular/router'; +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; +import { RouterTestingModule } from '@angular/router/testing'; +import { TranslateModule } from '@ngx-translate/core'; +import { Subject, of } from 'rxjs'; +import { I18nService } from '../../services/i18n.service'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { vi } from 'vitest'; + +describe('HelpContentComponent', () => { + let component: HelpContentComponent; + let fixture: ComponentFixture; + let httpMock: HttpTestingController; + let paramsSubject: Subject; + let fragmentSubject: Subject; + + beforeEach(async () => { + paramsSubject = new Subject(); + fragmentSubject = new Subject(); + + const routeMock = { + params: paramsSubject, + fragment: fragmentSubject, + snapshot: { + params: {}, + fragment: null, + url: [] + } + }; + + const i18nServiceMock = { + currentLang: () => 'en', + getCurrentLanguage: () => 'en', + currentLangSignal: { set: vi.fn(), get: () => 'en' } + }; + + await TestBed.configureTestingModule({ + imports: [ + HelpContentComponent, + HttpClientTestingModule, + RouterTestingModule, + TranslateModule.forRoot(), + NoopAnimationsModule + ], + providers: [ + { + provide: ActivatedRoute, + useValue: routeMock + }, + { provide: I18nService, useValue: i18nServiceMock } + ] + }).compileComponents(); + + fixture = TestBed.createComponent(HelpContentComponent); + component = fixture.componentInstance; + httpMock = TestBed.inject(HttpTestingController); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should handle page navigation with fragment correctly', fakeAsync(() => { + // 1. Simulate navigation to a page with fragment + paramsSubject.next({ pageId: 'test-page' }); + fragmentSubject.next('section-1'); + tick(); + + // 2. Expect help map request + const mapReq = httpMock.expectOne('./assets/help/help-map-en.json'); + mapReq.flush({ 'test-page': 'doc/test.md' }); + tick(); + + // 3. Expect markdown request + const mdReq = httpMock.expectOne('/api/docs/raw?path=doc/test.md'); + mdReq.flush('## Header 1\n\nContent'); + tick(); + + fixture.detectChanges(); + + // Verification: currentFragment should be 'section-1' and loading should be false + expect(component.loading()).toBe(false); + expect((component as any).currentFragment).toBe('section-1'); + })); + + it('should not clear fragment if params emits after fragment', fakeAsync(() => { + // This reproduces the race condition identified + + // 1. Fragment emits first + fragmentSubject.next('section-1'); + // 2. Params emits second (for same or new page) + paramsSubject.next({ pageId: 'test-page' }); + tick(); + + const mapReq = httpMock.expectOne('./assets/help/help-map-en.json'); + mapReq.flush({ 'test-page': 'doc/test.md' }); + tick(); + + const mdReq = httpMock.expectOne('/api/docs/raw?path=doc/test.md'); + mdReq.flush('## Header 1\n\nContent'); + tick(); + + fixture.detectChanges(); + + // Verification: fragment should persist even if params emitted after it + expect((component as any).currentFragment).toBe('section-1'); + })); + + it('should retry scrolling if element not found immediately', fakeAsync(() => { + // Setup + (component as any).currentFragment = 'test-id'; + component.loading.set(false); + + // Spy on scrollIntoView + const scrollSpy = vi.fn(); + + // Trigger scrollToFragment via ngAfterViewChecked + component.ngAfterViewChecked(); + + // Not found yet (mock element not in DOM) + expect((component as any).scrollRetryCount).toBe(1); + expect((component as any).currentFragment).toBe('test-id'); + + // Add element to DOM later + const el = document.createElement('div'); + el.id = 'test-id'; + // We mock querySelector on nativeElement + vi.spyOn(fixture.nativeElement, 'querySelector').mockReturnValue(el); + el.scrollIntoView = scrollSpy; + + // Next check + component.ngAfterViewChecked(); + + expect(scrollSpy).not.toHaveBeenCalled(); // Still needs timeout + tick(250); // wait for setTimeout(200) + + expect(scrollSpy).toHaveBeenCalled(); + expect((component as any).currentFragment).toBe(''); + expect((component as any).scrollRetryCount).toBe(0); + })); +}); diff --git a/frontend/src/app/components/help/help-content.component.ts b/frontend/src/app/components/help/help-content.component.ts index 84c0094f..96ae2333 100644 --- a/frontend/src/app/components/help/help-content.component.ts +++ b/frontend/src/app/components/help/help-content.component.ts @@ -4,12 +4,14 @@ import { ActivatedRoute, Router } from '@angular/router'; import { HttpClient } from '@angular/common/http'; import { MatCardModule } from '@angular/material/card'; import { TranslateModule } from '@ngx-translate/core'; +import { combineLatest, startWith, distinctUntilChanged } from 'rxjs'; import { I18nService } from '../../services/i18n.service'; +import { MarkdownViewerComponent } from '../shared/markdown-viewer/markdown-viewer.component'; @Component({ selector: 'app-help-content', standalone: true, - imports: [CommonModule, MatCardModule, TranslateModule], + imports: [CommonModule, MatCardModule, TranslateModule, MarkdownViewerComponent], templateUrl: './help-content.component.html', styles: [` .help-container { @@ -41,8 +43,12 @@ export class HelpContentComponent implements OnInit, AfterViewChecked { private readonly el = inject(ElementRef); htmlContent = signal(''); + rawMarkdown = signal(''); loading = signal(true); private currentPageId = ''; + private currentFragment = ''; + private scrollRetryCount = 0; + private readonly MAX_RETRY = 50; constructor() { effect(() => { @@ -55,75 +61,201 @@ export class HelpContentComponent implements OnInit, AfterViewChecked { } ngOnInit() { - this.route.params.subscribe(params => { - this.currentPageId = params['pageId']; - - // If no pageId from param, extract from full URL (for wildcard routes) - if (!this.currentPageId) { - const url = this.router.url; - if (url.includes('/help/')) { - this.currentPageId = url.split('/help/')[1]; + combineLatest([ + this.route.params.pipe(startWith(this.route.snapshot.params)), + this.route.fragment.pipe(startWith(this.route.snapshot.fragment)) + ]).pipe( + distinctUntilChanged((prev, curr) => JSON.stringify(prev) === JSON.stringify(curr)) + ).subscribe({ + next: ([params, fragment]) => { + try { + let pageId = params['pageId']; + + // If no pageId from param, extract from segments (for wildcard routes) + if (!pageId && this.route.snapshot.url.length > 0) { + const segments = this.route.snapshot.url.map(segment => segment.path); + // Skip the first segment if it's 'help' (the route prefix) + if (segments[0] === 'help') { + pageId = segments.slice(1).join('/'); + } else { + pageId = segments.join('/'); + } + } + + // Fallback: extract from full URL if still missing + if (!pageId) { + const url = this.router.url; + if (url.includes('/help/')) { + const parts = url.split('/help/'); + pageId = parts[1]; + } + } + + // Normalize potentially unsafe or odd inputs + if (pageId) { + // decode, drop leading ./ or /, and remove any ../ segments to avoid backend 403 + pageId = decodeURIComponent(pageId).replace(/^([./])+/, '').replace(/\.{2}\//g, ''); + } + + // Extract fragment from pageId if present (e.g. from router.url) + let urlFragment = fragment; + if (pageId && pageId.includes('#')) { + const parts = pageId.split('#'); + pageId = parts[0]; + if (!urlFragment) { + urlFragment = parts[1]; + } + } + + // Final fallback: if no pageId, don't just hang in Loading... + if (!pageId) { + this.loading.set(false); + return; + } + + // Only reload if the page actually changed (to preserve state on fragment navigation) + if (pageId !== this.currentPageId) { + this.currentPageId = pageId; + this.loadHelpPage(this.currentPageId, this.i18nService.getCurrentLanguage()); + } else if (this.loading()) { + // If same page but still showing loading, something is wrong, force stop loading + this.loading.set(false); + } + + if (urlFragment) { + this.currentFragment = urlFragment; + this.scrollRetryCount = 0; + } + } catch { + // Fail-safe to avoid Loading... hang on unexpected errors + this.loading.set(false); } + }, + error: () => { + this.loading.set(false); } - - this.loadHelpPage(this.currentPageId, this.i18nService.getCurrentLanguage()); }); } ngAfterViewChecked() { this.handleLinks(); + this.scrollToFragment(); } loadHelpPage(pageId: string, lang: string) { + if (!pageId) return; + this.loading.set(true); - const resolvedPageId = this.resolvePageId(pageId); - this.http.get<{ [key: string]: string }>(`./assets/help/help-data-${lang}.json`).subscribe({ - next: (data) => { - if (lang === 'en') { - this.htmlContent.set(data[resolvedPageId] || `

    Page not found (${lang}). PageId: ${resolvedPageId}

    `); - this.loading.set(false); + // 1. Look up in the help map first to resolve clean IDs or partial paths + this.http.get<{ [key: string]: string }>(`./assets/help/help-map-${lang}.json`).subscribe({ + next: (map) => { + // Try exact match, then lowercase, then without .md extension + const cleanPageId = pageId.endsWith('.md') ? pageId.replace('.md', '') : pageId; + const path = map[pageId] || map[pageId.toLowerCase()] || map[cleanPageId] || map[cleanPageId.toLowerCase()]; + + if (path) { + this.loadRawMarkdown(path); + } else if (pageId.includes('/') || pageId.endsWith('.md')) { + // If not in map but looks like a path, try it directly + this.loadRawMarkdown(pageId); } else { - // Fallback to English if the page doesn't exist in the selected language - const content = data[resolvedPageId]; - if (content) { - this.htmlContent.set(content); - this.loading.set(false); - } else { - this.http.get<{ [key: string]: string }>(`./assets/help/help-data-en.json`).subscribe({ - next: (enData) => { - this.htmlContent.set(enData[resolvedPageId] || `

    Page not found (en). PageId: ${resolvedPageId}

    `); - this.loading.set(false); - }, - error: () => { - this.htmlContent.set('

    Error loading help content.

    '); - this.loading.set(false); - } - }); - } + // Fallback to pageId as path + this.loadRawMarkdown(pageId); } }, error: () => { - // Try English as a last resort if the localized file cannot be loaded at all - if (lang === 'en') { - this.htmlContent.set('

    Error loading help content.

    '); - this.loading.set(false); - } else { - this.http.get<{ [key: string]: string }>(`./assets/help/help-data-en.json`).subscribe({ - next: (enData) => { - this.htmlContent.set(enData[resolvedPageId] || '

    Error loading help content.

    '); - this.loading.set(false); - }, - error: () => { - this.htmlContent.set('

    Error loading help content.

    '); - this.loading.set(false); - } - }); - } + // Fallback to direct path if map loading fails + this.loadRawMarkdown(pageId); + } + }); + } + + private loadRawMarkdown(path: string) { + // Strip fragment again just in case it leaks here + let cleanPath = path; + if (path.includes('#')) { + cleanPath = path.split('#')[0]; + } + + this.http.get(`/api/docs/raw?path=${cleanPath}`, { responseType: 'text' }).subscribe({ + next: (content) => { + this.rawMarkdown.set(content); + this.htmlContent.set(''); // Clear HTML content if using raw markdown + this.loading.set(false); + }, + error: (err) => { + console.error('Error loading raw doc:', err); + this.rawMarkdown.set(`## Error\n\nFailed to load documentation from path: \`${path}\``); + this.htmlContent.set(''); + this.loading.set(false); } }); } + private scrollToFragment() { + if (this.currentFragment && !this.loading()) { + // Decode fragment if it was URI encoded (like in AI evidence) + const decodedFragment = decodeURIComponent(this.currentFragment); + + // Try to find element by ID or name (markdown headers often have IDs) + // We also try to match the text content of headers if no ID matches + // First try standard getElementById for direct ID matches (case-sensitive) + let element = document.getElementById(decodedFragment); + + if (!element) { + // Scoped query for elements with matching ID attribute (more robust for some characters) + element = this.el.nativeElement.querySelector(`[id="${decodedFragment}"]`); + } + + if (!element) { + // Fallback: search for headers or anchors that might match the fragment (case-insensitive) + const candidates = this.el.nativeElement.querySelectorAll('h1, h2, h3, h4, h5, h6, a[id]'); + const upperFragment = decodedFragment.toUpperCase(); + + for (const node of Array.from(candidates)) { + const h = node as HTMLElement; + const text = h.textContent?.trim() || ''; + const id = h.id || ''; + + const normalizedId = id.toUpperCase(); + const normalizedFragment = upperFragment; + const slugifiedFragment = decodedFragment.toLowerCase().replace(/\s+/g, '-').replace(/[^\w-]/g, ''); + + if (normalizedId === normalizedFragment || + text.toUpperCase() === normalizedFragment || + text.toUpperCase().startsWith(normalizedFragment + ':') || + text.toUpperCase().startsWith(normalizedFragment + ' ') || + (normalizedId && normalizedFragment.startsWith(normalizedId)) || + id === slugifiedFragment) { + element = h; + break; + } + } + } + + if (element) { + // Use a small timeout to ensure rendering is complete and browser can scroll + // 200ms is more stable for large documents like adr-full-set.md + setTimeout(() => { + element.scrollIntoView({ behavior: 'smooth', block: 'start' }); + }, 200); + + // Clear fragment after scrolling once to avoid continuous scrolling on every view check + this.currentFragment = ''; + this.scrollRetryCount = 0; + } else { + // Increment retry count if not found + this.scrollRetryCount++; + if (this.scrollRetryCount >= this.MAX_RETRY) { + // Give up after several retries to avoid infinite attempts on non-existent fragments + this.currentFragment = ''; + this.scrollRetryCount = 0; + } + } + } + } + private resolvePageId(pageId: string): string { if (!pageId) return ''; @@ -145,7 +277,7 @@ export class HelpContentComponent implements OnInit, AfterViewChecked { } private handleLinks() { - const links = this.el.nativeElement.querySelectorAll('.help-content a'); + const links = this.el.nativeElement.querySelectorAll('.help-content a, .markdown-body a'); links.forEach((link: HTMLAnchorElement) => { link.onclick ??= (event: MouseEvent) => { const href = link.getAttribute('href'); @@ -163,11 +295,37 @@ export class HelpContentComponent implements OnInit, AfterViewChecked { if (element) { element.scrollIntoView({ behavior: 'smooth' }); } - } else if (href.startsWith('doc/') || href === 'README.md' || href === 'README_de.md' || href.startsWith('scripts/')) { + } else if (href.startsWith('/help/')) { + // Normalize any help links generated from markdown (may contain ../) + event.preventDefault(); + const internal = href.split('/help/')[1] ?? ''; + + // Separate path and fragment before decoding path to preserve fragment encoding + let [pathPart, ...fragmentParts] = internal.split('#'); + let fragmentPart = fragmentParts.join('#'); + + const decodedPath = decodeURIComponent(pathPart).replace(/^([./])+/, '').replace(/\.{2}\//g, ''); + const pageId = this.mapHrefToPageId(decodedPath) || decodedPath; + + // Reconstruct URL preserving fragment + this.router.navigateByUrl(`/help/${pageId}${fragmentPart ? '#' + fragmentPart : ''}`); + } else if (href.startsWith('doc/') || href.endsWith('.md') || href.startsWith('scripts/') || href.includes('README')) { event.preventDefault(); - const pageId = this.mapHrefToPageId(href); - if (pageId) { - this.router.navigate(['/help', pageId]); + + // Separate path and fragment + let [pathPart, ...fragmentParts] = href.split('#'); + let fragmentPart = fragmentParts.join('#'); + + const sanitizedPath = pathPart.replace(/^([./])+/, '').replace(/\.{2}\//g, ''); + const pageId = this.mapHrefToPageId(sanitizedPath) || sanitizedPath; + + // Reconstruct URL preserving fragment + this.router.navigateByUrl(`/help/${pageId}${fragmentPart ? '#' + fragmentPart : ''}`); + } else if (href.startsWith('/') || (href.includes('/') && !href.startsWith('doc/') && !href.startsWith('scripts/') && !href.includes('.md'))) { + // App route link or absolute link - let it navigate normally or handle via router + if (href.startsWith('/')) { + event.preventDefault(); + this.router.navigateByUrl(href); } } else if (!href.startsWith('http') && !href.startsWith('mailto')) { event.preventDefault(); @@ -184,8 +342,13 @@ export class HelpContentComponent implements OnInit, AfterViewChecked { if (href.includes('android-build-instructions')) return 'android-build-instructions'; if (href.includes('aws_setup')) return 'aws-setup'; if (href.includes('postgres_setup')) return 'postgres-setup'; - if (href.includes('risk-radar')) return 'risk-radar'; if (href.includes('navigation')) return 'navigation'; + if (href.includes('index')) return 'index'; + if (href.includes('risk-radar')) return 'risk-radar'; + if (href.includes('retrospective')) return 'retrospective'; + if (href.includes('adr-drift')) return 'adr-drift'; + if (href.includes('onboarding')) return 'onboarding'; + if (href.includes('economy') || href.includes('credits')) return 'economy-dashboard'; if (href.includes('aws_fargate_config')) return 'aws-fargate-config'; if (href.includes('aws_create_target_group')) return 'aws-create-target-group'; if (href.includes('aws_alb_troubleshooting')) return 'aws-alb-troubleshooting'; diff --git a/frontend/src/app/components/retrospective/retrospective.component.css b/frontend/src/app/components/retrospective/retrospective.component.css index bd6293f0..7c704b1e 100644 --- a/frontend/src/app/components/retrospective/retrospective.component.css +++ b/frontend/src/app/components/retrospective/retrospective.component.css @@ -129,6 +129,46 @@ margin-top: 16px; } +.sources-section h4 { + margin-bottom: 8px; + color: var(--text-weak); + font-size: 0.9rem; + font-weight: 500; +} + +.source-chip { + background-color: var(--surface-2) !important; + border: 1px solid var(--border) !important; +} + +.source-chip app-markdown-viewer ::ng-deep .markdown-body p { + margin: 0; + font-size: 13px; + color: var(--brand); + font-weight: 500; +} + +.insight-card li app-markdown-viewer ::ng-deep .markdown-body p { + margin: 0; + display: inline; +} + +.insight-card li app-markdown-viewer ::ng-deep .markdown-body a, +.source-chip app-markdown-viewer ::ng-deep .markdown-body a { + color: var(--brand); + text-decoration: none; + font-weight: 600; +} + +.insight-card li app-markdown-viewer ::ng-deep .markdown-body a:hover, +.source-chip app-markdown-viewer ::ng-deep .markdown-body a:hover { + text-decoration: underline; +} + +.summary-text app-markdown-viewer ::ng-deep .markdown-body p { + margin-bottom: 12px; +} + .filter-actions { display: flex; flex-direction: column; diff --git a/frontend/src/app/components/retrospective/retrospective.component.html b/frontend/src/app/components/retrospective/retrospective.component.html index 2aa70464..a2deaa2b 100644 --- a/frontend/src/app/components/retrospective/retrospective.component.html +++ b/frontend/src/app/components/retrospective/retrospective.component.html @@ -112,7 +112,9 @@
    -

    {{ res.summary }}

    +
    + +
    @@ -121,7 +123,7 @@

    star {{ 'ADMIN.RETROSPECTIVE.HIGHLIGHTS' | translate }}

      @for (item of res.highlights; track $index) { -
    • {{ item }}
    • +
    • }
    @@ -130,7 +132,7 @@

    star {{ 'ADMIN.RETROSPECTIVE.HIGHLIGHTS' | translate }}

    warning {{ 'ADMIN.RETROSPECTIVE.PROBLEMS' | translate }}

      @for (item of res.problems; track $index) { -
    • {{ item }}
    • +
    • }
    @@ -139,7 +141,7 @@

    warning {{ 'ADMIN.RETROSPECTIVE.PROBLEMS' | translate }

    lightbulb {{ 'ADMIN.RETROSPECTIVE.SUGGESTIONS' | translate }}

      @for (item of res.suggestions; track $index) { -
    • {{ item }}
    • +
    • }
    @@ -148,7 +150,7 @@

    lightbulb {{ 'ADMIN.RETROSPECTIVE.SUGGESTIONS' | transl

    assignment_turned_in {{ 'ADMIN.RETROSPECTIVE.ACTION_ITEMS' | translate }}

      @for (item of res.actionItems; track $index) { -
    • {{ item }}
    • +
    • }
    @@ -160,7 +162,9 @@

    assignment_turned_in {{ 'ADMIN.RETROSPECTIVE.ACTION_ITE

    Sources:

    @for (source of res.sources; track source.id) { - {{ source.id }} ({{ source.section }}) + + + } diff --git a/frontend/src/app/components/retrospective/retrospective.component.ts b/frontend/src/app/components/retrospective/retrospective.component.ts index a6c9354d..96f16b93 100644 --- a/frontend/src/app/components/retrospective/retrospective.component.ts +++ b/frontend/src/app/components/retrospective/retrospective.component.ts @@ -26,6 +26,7 @@ import { IndexingScopeSelectorComponent } from '../shared/indexing-scope-selecto import { IndexingScope } from '../../services/admin.service'; import { TaskGroup, TaskGroupType } from '../../services/ai.service'; import { TaskGroupSelectorComponent } from '../shared/task-group-selector/task-group-selector.component'; +import { MarkdownViewerComponent } from '../shared/markdown-viewer/markdown-viewer.component'; @Component({ selector: 'app-retrospective', @@ -53,7 +54,8 @@ import { TaskGroupSelectorComponent } from '../shared/task-group-selector/task-g SkeletonComponent, FormRowComponent, TaskGroupSelectorComponent, - IndexingScopeSelectorComponent + IndexingScopeSelectorComponent, + MarkdownViewerComponent ], templateUrl: './retrospective.component.html', styleUrl: './retrospective.component.css' diff --git a/frontend/src/app/components/risk-radar/risk-radar.component.css b/frontend/src/app/components/risk-radar/risk-radar.component.css index 0615d9da..14237f0c 100644 --- a/frontend/src/app/components/risk-radar/risk-radar.component.css +++ b/frontend/src/app/components/risk-radar/risk-radar.component.css @@ -35,6 +35,18 @@ margin-top: var(--spacing-8); } +.evidence-link { + color: inherit; + text-decoration: none; + font-weight: 500; + cursor: pointer; +} + +.evidence-link:hover { + text-decoration: underline; + color: var(--primary-color); +} + .risk-column { display: flex; flex-direction: column; diff --git a/frontend/src/app/components/risk-radar/risk-radar.component.html b/frontend/src/app/components/risk-radar/risk-radar.component.html index 900b9e53..879878f3 100644 --- a/frontend/src/app/components/risk-radar/risk-radar.component.html +++ b/frontend/src/app/components/risk-radar/risk-radar.component.html @@ -117,7 +117,13 @@

    error {{ 'RISK_RADAR.HIGH_RISKS'

    {{ 'RISK_RADAR.EVIDENCE' | translate }}:

    @for (ev of risk.evidence; track $index) { - {{ ev }} + + @if (risk.evidencePaths?.[ev]) { + {{ ev }} + } @else { + {{ ev }} + } + } @@ -151,7 +157,13 @@

    settings_suggest {{ 'RISK_RADAR

    {{ 'RISK_RADAR.EVIDENCE' | translate }}:

    @for (ev of risk.evidence; track $index) { - {{ ev }} + + @if (risk.evidencePaths?.[ev]) { + {{ ev }} + } @else { + {{ ev }} + } + } @@ -185,7 +197,13 @@

    auto_stories {{ 'RISK_RADAR.DOC_GA

    {{ 'RISK_RADAR.EVIDENCE' | translate }}:

    @for (ev of risk.evidence; track $index) { - {{ ev }} + + @if (risk.evidencePaths?.[ev]) { + {{ ev }} + } @else { + {{ ev }} + } + } @@ -219,7 +237,13 @@

    verified_user {{ 'RISK_RADAR.QUALI

    {{ 'RISK_RADAR.EVIDENCE' | translate }}:

    @for (ev of risk.evidence; track $index) { - {{ ev }} + + @if (risk.evidencePaths?.[ev]) { + {{ ev }} + } @else { + {{ ev }} + } + } diff --git a/frontend/src/app/components/risk-radar/risk-radar.component.ts b/frontend/src/app/components/risk-radar/risk-radar.component.ts index 89cfeb96..7a6bac88 100644 --- a/frontend/src/app/components/risk-radar/risk-radar.component.ts +++ b/frontend/src/app/components/risk-radar/risk-radar.component.ts @@ -15,6 +15,7 @@ import { MatNativeDateModule } from '@angular/material/core'; import { MatSelectModule } from '@angular/material/select'; import { MatTooltipModule } from '@angular/material/tooltip'; import { TranslateModule } from '@ngx-translate/core'; +import { RouterModule } from '@angular/router'; import { RiskRadarRequest, RiskRadarResponse } from '../../models/retrospective.model'; import { BaseAiComponent } from '../base/base-ai.component'; import { AiDisabledPlaceholderComponent } from '../shared/ai-disabled-placeholder.component'; @@ -47,6 +48,7 @@ import { IndexingScope } from '../../services/admin.service'; MatSelectModule, MatTooltipModule, TranslateModule, + RouterModule, AiDisabledPlaceholderComponent, EmptyStateComponent, AiResultComponent, diff --git a/frontend/src/app/components/shared/markdown-viewer/markdown-viewer.component.spec.ts b/frontend/src/app/components/shared/markdown-viewer/markdown-viewer.component.spec.ts index b0112df6..2d8a4005 100644 --- a/frontend/src/app/components/shared/markdown-viewer/markdown-viewer.component.spec.ts +++ b/frontend/src/app/components/shared/markdown-viewer/markdown-viewer.component.spec.ts @@ -2,18 +2,31 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MarkdownViewerComponent } from './markdown-viewer.component'; import { By } from '@angular/platform-browser'; import { SimpleChange } from '@angular/core'; +import { Router } from '@angular/router'; +import { vi } from 'vitest'; describe('MarkdownViewerComponent', () => { let component: MarkdownViewerComponent; let fixture: ComponentFixture; + let router: Router; beforeEach(async () => { + const routerMock = { + navigateByUrl: vi.fn().mockResolvedValue(true), + serializeUrl: vi.fn(), + createUrlTree: vi.fn() + }; + await TestBed.configureTestingModule({ - imports: [MarkdownViewerComponent] + imports: [MarkdownViewerComponent], + providers: [ + { provide: Router, useValue: routerMock } + ] }).compileComponents(); fixture = TestBed.createComponent(MarkdownViewerComponent); component = fixture.componentInstance; + router = TestBed.inject(Router); }); it('should create', () => { @@ -50,6 +63,31 @@ describe('MarkdownViewerComponent', () => { expect(strong.nativeElement.textContent).toBe('bold'); }); + it('should handle multiple bold segments on one line (non-greedy)', () => { + component.content = 'This is **bold1** and **bold2** text'; + component.ngOnChanges({ + content: new SimpleChange('', component.content, true) + }); + fixture.detectChanges(); + + const strongs = fixture.debugElement.queryAll(By.css('strong')); + expect(strongs.length).toBe(2); + expect(strongs[0].nativeElement.textContent).toBe('bold1'); + expect(strongs[1].nativeElement.textContent).toBe('bold2'); + }); + + it('should handle headers with leading whitespace', () => { + component.content = ' ## Header with spaces'; + component.ngOnChanges({ + content: new SimpleChange('', component.content, true) + }); + fixture.detectChanges(); + + const h2 = fixture.debugElement.query(By.css('h2')); + expect(h2).toBeTruthy(); + expect(h2.nativeElement.textContent.trim()).toBe('Header with spaces'); + }); + it('should render lists', () => { component.content = '- Item 1\n- Item 2'; component.ngOnChanges({ @@ -79,4 +117,230 @@ describe('MarkdownViewerComponent', () => { expect(code).toBeTruthy(); expect(code.nativeElement.textContent.trim()).toBe('const x = 1;'); }); + + it('should render tables', () => { + component.content = '| Header 1 | Header 2 |\n| :--- | :--- |\n| Cell 1 | Cell 2 |'; + component.ngOnChanges({ + content: new SimpleChange('', component.content, true) + }); + fixture.detectChanges(); + + const table = fixture.debugElement.query(By.css('table')); + const thead = fixture.debugElement.query(By.css('thead')); + const tbody = fixture.debugElement.query(By.css('tbody')); + const rows = fixture.debugElement.queryAll(By.css('tr')); + const headers = fixture.debugElement.queryAll(By.css('th')); + const cells = fixture.debugElement.queryAll(By.css('td')); + + expect(table).toBeTruthy(); + expect(thead).toBeTruthy(); + expect(tbody).toBeTruthy(); + expect(rows.length).toBe(2); // Header row + 1 data row + expect(headers.length).toBe(2); + expect(cells.length).toBe(2); + expect(headers[0].nativeElement.textContent.trim()).toBe('Header 1'); + expect(cells[0].nativeElement.textContent.trim()).toBe('Cell 1'); + }); + + it('should preserve doc/ paths and fragments in links', () => { + component.content = '[ADR](doc/knowledge/adrs/adr-full-set.md#ADR-0056)'; + component.ngOnChanges({ + content: new SimpleChange('', component.content, true) + }); + fixture.detectChanges(); + + const a = fixture.debugElement.query(By.css('a')); + expect(a.nativeElement.getAttribute('href')).toBe('/help/doc/knowledge/adrs/adr-full-set.md#ADR-0056'); + }); + + it('should handle simple inline links correctly', () => { + component.content = 'Check [this out](/help/some-page)'; + component.ngOnChanges({ + content: new SimpleChange('', component.content, true) + }); + fixture.detectChanges(); + + const a = fixture.debugElement.query(By.css('a')); + expect(a.nativeElement.getAttribute('href')).toBe('/help/some-page'); + }); + + it('should render all rows in a table, including the last one', () => { + component.content = `| Endpoint | Method | Role | Description | +| :--- | :--- | :--- | :--- | +| /api/ai/retrospective | POST | USER | Generates a project retrospective using RAG. | +| /api/ai/risk-radar | POST | USER | Analyzes project risks based on current tasks/docs. | +| /api/ai/adr-drift | POST | USER | Detects drift between code and ADRs. | +| /api/ai/explain | POST | USER | Explains architectural concepts using RAG. |`; + + component.ngOnChanges({ + content: new SimpleChange('', component.content, true) + }); + fixture.detectChanges(); + + const rows = fixture.debugElement.queryAll(By.css('tbody tr')); + expect(rows.length).toBe(4); + if (rows.length > 3) { + expect(rows[3].nativeElement.textContent).toContain('/api/ai/explain'); + } + }); + + it('should handle table without trailing pipes', () => { + component.content = "| H1 | H2\n| --- | ---\n| C1 | C2"; + component.ngOnChanges({ + content: new SimpleChange('', component.content, true) + }); + fixture.detectChanges(); + + const rows = fixture.debugElement.queryAll(By.css('tbody tr')); + expect(rows.length).toBe(1); + expect(rows[0].nativeElement.textContent).toContain('C1'); + }); + + it('should handle CRLF correctly', () => { + component.content = "| H1 | H2 |\r\n| --- | --- |\r\n| C1 | C2 |\r\n\r\nNext"; + component.ngOnChanges({ + content: new SimpleChange('', component.content, true) + }); + fixture.detectChanges(); + + const rows = fixture.debugElement.queryAll(By.css('tbody tr')); + expect(rows.length).toBe(1); + expect(rows[0].nativeElement.textContent).toContain('C1'); + }); + + it('should intercept internal links and use router', () => { + const navigateSpy = vi.spyOn(router, 'navigateByUrl'); + + component.content = '[Help](doc/knowledge/test.md)'; + component.ngOnChanges({ + content: new SimpleChange('', component.content, true) + }); + fixture.detectChanges(); + + const a = fixture.debugElement.query(By.css('a')); + a.nativeElement.click(); + + expect(navigateSpy).toHaveBeenCalledWith('/help/doc/knowledge/test.md'); + }); + + it('should handle deep paths with fragments in links', () => { + component.content = '[ADR](doc/knowledge/adrs/adr-full-set.md#ADR-0056)'; + component.ngOnChanges({ + content: new SimpleChange('', component.content, true) + }); + fixture.detectChanges(); + + const a = fixture.debugElement.query(By.css('a')); + expect(a.nativeElement.getAttribute('href')).toBe('/help/doc/knowledge/adrs/adr-full-set.md#ADR-0056'); + }); + + it('should auto-link ADR references', () => { + component.content = 'See ADR-0011 for details'; + component.ngOnChanges({ + content: new SimpleChange('', component.content, true) + }); + fixture.detectChanges(); + + const a = fixture.debugElement.query(By.css('a')); + expect(a).toBeTruthy(); + expect(a.nativeElement.getAttribute('href')).toBe('/help/doc/knowledge/adrs/adr-full-set.md#ADR-0011'); + expect(a.nativeElement.textContent).toBe('ADR-0011'); + }); + + it('should not auto-link ADR if already inside a link', () => { + component.content = '[Already linked ADR-0011](doc/some-file.md)'; + component.ngOnChanges({ + content: new SimpleChange('', component.content, true) + }); + fixture.detectChanges(); + + const links = fixture.debugElement.queryAll(By.css('a')); + expect(links.length).toBe(1); + expect(links[0].nativeElement.getAttribute('href')).toBe('/help/doc/some-file.md'); + }); + + it('should render ordered lists', () => { + component.content = '1. First\n2. Second'; + component.ngOnChanges({ + content: new SimpleChange('', component.content, true) + }); + fixture.detectChanges(); + + const ol = fixture.debugElement.query(By.css('ol')); + const li = fixture.debugElement.queryAll(By.css('li')); + + expect(ol).toBeTruthy(); + expect(li.length).toBe(2); + expect(li[0].nativeElement.textContent).toBe('First'); + }); + + it('should handle escaped pipes in tables', () => { + component.content = '| Header | Description |\n| --- | --- |\n| Cell 1 | Cell with \\| pipe |'; + component.ngOnChanges({ + content: new SimpleChange('', component.content, true) + }); + fixture.detectChanges(); + + const cells = fixture.debugElement.queryAll(By.css('td')); + expect(cells[1].nativeElement.textContent.trim()).toBe('Cell with | pipe'); + }); + + it('should handle tables without leading/trailing pipes', () => { + component.content = 'H1 | H2\n---|---\nV1 | V2'; + component.ngOnChanges({ + content: new SimpleChange('', component.content, true) + }); + fixture.detectChanges(); + + const table = fixture.debugElement.query(By.css('table')); + expect(table).toBeTruthy(); + const cells = fixture.debugElement.queryAll(By.css('td')); + expect(cells[0].nativeElement.textContent.trim()).toBe('V1'); + }); + + it('should NOT merge heading into table if they are on separate lines', () => { + component.content = '| Col 1 | Col 2 |\n|---|---|\n| Val 1 | Val 2 |\n\n### Next Header'; + component.ngOnChanges({ + content: new SimpleChange('', component.content, true) + }); + fixture.detectChanges(); + + const cells = fixture.debugElement.queryAll(By.css('td')); + expect(cells.length).toBe(2); + const h3 = fixture.debugElement.query(By.css('h3')); + expect(h3).toBeTruthy(); + }); + + it('should normalize mixed line endings (CRLF, CR, LF)', () => { + // Mixture of \r\n, \r, and \n + component.content = "H1 | H2\r\n---|---\rV1 | V2\nNext"; + component.ngOnChanges({ + content: new SimpleChange('', component.content, true) + }); + fixture.detectChanges(); + + const table = fixture.debugElement.query(By.css('table')); + expect(table).toBeTruthy(); + const cells = fixture.debugElement.queryAll(By.css('td')); + expect(cells.length).toBe(2); + expect(cells[0].nativeElement.textContent.trim()).toBe('V1'); + const p = fixture.debugElement.query(By.css('p')); + expect(p.nativeElement.textContent.trim()).toBe('Next'); + }); + + it('should add ADR anchors inside headings', () => { + component.content = '#### ADR-0017: Title'; + component.ngOnChanges({ + content: new SimpleChange('', component.content, true) + }); + fixture.detectChanges(); + + const h4 = fixture.debugElement.query(By.css('h4')); + const anchor = fixture.debugElement.query(By.css('h4 a')); + + expect(h4).toBeTruthy(); + expect(anchor).toBeTruthy(); + expect(anchor.nativeElement.getAttribute('id')).toBe('ADR-0017'); + expect(h4.nativeElement.id).toBe('adr-0017-title'); + }); }); diff --git a/frontend/src/app/components/shared/markdown-viewer/markdown-viewer.component.ts b/frontend/src/app/components/shared/markdown-viewer/markdown-viewer.component.ts index 240ce193..81836aed 100644 --- a/frontend/src/app/components/shared/markdown-viewer/markdown-viewer.component.ts +++ b/frontend/src/app/components/shared/markdown-viewer/markdown-viewer.component.ts @@ -1,4 +1,6 @@ -import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; +import { Component, inject, Input, OnChanges, SimpleChanges, HostListener } from '@angular/core'; +import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; +import { Router } from '@angular/router'; /** * A lightweight component to render simple markdown content as HTML. @@ -18,7 +20,7 @@ import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; :host ::ng-deep .markdown-body h2, :host ::ng-deep .markdown-body h3, :host ::ng-deep .markdown-body h4 { - margin-top: 24px; + margin-top: 32px; margin-bottom: 16px; font-weight: 600; line-height: 1.25; @@ -69,13 +71,31 @@ import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; border: 0; } :host ::ng-deep .markdown-body a { - color: #0d6efd !important; /* Neutral blue (Bootstrap 5 Primary) */ + color: var(--brand) !important; text-decoration: underline !important; font-weight: 500; } :host ::ng-deep .markdown-body a:hover { text-decoration: underline !important; - color: #0a58ca !important; + opacity: 0.8; + } + :host ::ng-deep .markdown-body table { + border-collapse: collapse; + width: 100%; + margin-bottom: 16px; + } + :host ::ng-deep .markdown-body th, + :host ::ng-deep .markdown-body td { + border: 1px solid var(--brand-weak); + padding: 8px 12px; + text-align: left; + } + :host ::ng-deep .markdown-body th { + background-color: var(--surface-weak); + font-weight: 600; + } + :host ::ng-deep .markdown-body tr:nth-child(even) { + background-color: var(--surface-weak-transparent, rgba(0,0,0,0.02)); } `] }) @@ -85,14 +105,24 @@ export class MarkdownViewerComponent implements OnChanges { */ @Input() content: string = ''; + /** + * Optional base path for relative links in the markdown. + * Useful when rendering snippets from a known source file. + */ + @Input() basePath?: string; + /** * Safe HTML content to be displayed in the template. */ - safeHtml: string = ''; + safeHtml: SafeHtml | string = ''; + + private readonly sanitizer = inject(DomSanitizer); + private readonly router = inject(Router); ngOnChanges(changes: SimpleChanges): void { - if (changes['content']) { - this.safeHtml = this.renderMarkdown(this.content); + if (changes['content'] || changes['basePath']) { + const rendered = this.renderMarkdown(this.content); + this.safeHtml = this.sanitizer.bypassSecurityTrustHtml(rendered); } } @@ -105,8 +135,11 @@ export class MarkdownViewerComponent implements OnChanges { return ''; } - // Escape basic HTML to prevent XSS - let html = md + // 0. Normalize line endings to avoid issues with \r and greedy matches + let html = md.replace(/\r\n/g, '\n').replace(/\r/g, '\n'); + + // 1. Escape basic HTML to prevent XSS + html = html .replaceAll('&', '&') .replaceAll('<', '<') .replaceAll('>', '>'); @@ -114,19 +147,27 @@ export class MarkdownViewerComponent implements OnChanges { // 1. Code blocks (extract and protect to avoid wrapping them in paragraphs) const codeBlocks: string[] = []; html = html.replaceAll(/```([\s\S]*?)```/g, (_match, code) => { - const placeholder = `__CODE_BLOCK_${codeBlocks.length}__`; + const placeholder = `:::CODE_BLOCK_${codeBlocks.length}:::`; codeBlocks.push(`
    ${code}
    `); return placeholder; }); // 2. Headings - html = html.replaceAll(/^# (.*$)/gim, '

    $1

    '); - html = html.replaceAll(/^## (.*$)/gim, '

    $1

    '); - html = html.replaceAll(/^### (.*$)/gim, '

    $1

    '); - html = html.replaceAll(/^#### (.*$)/gim, '

    $1

    '); + html = html.replaceAll(/^\s*(#+) (.*$)/gim, (_match, hashes, title) => { + const level = hashes.length; + const cleanTitle = title.trim(); + const id = cleanTitle.toLowerCase().replace(/\s+/g, '-').replace(/[^\w-]/g, ''); + + // If title starts with ADR-XXXX or AI-XXXX, add an anchor with that ID for easier linking + const adrMatch = cleanTitle.match(/^(ADR-\d{4}|AI-[A-Z-]+-\d+)/i); + const anchor = adrMatch ? `` : ''; + + return `${anchor}${cleanTitle}`; + }); // 3. Bold text - html = html.replaceAll(/\*\*(.*)\*\*/gim, '$1'); + html = html.replaceAll(/\*\*(.*?)\*\*/gim, '$1'); + html = html.replaceAll(/__(.*?)__/gim, '$1'); // 4. Horizontal Rule html = html.replaceAll(/^---$/gim, '
    '); @@ -135,69 +176,295 @@ export class MarkdownViewerComponent implements OnChanges { html = html.replaceAll(/`(.*?)`/g, '$1'); // 6. Links [text](url) - html = this.transformLinks(html.replaceAll(/\[([^\]]+)\]\(([^)]+)\)/g, '$1')); + html = this.transformLinks(html.replaceAll(/\[([^\]]+)\]\(([^)]+)\)/g, (_match, text, url) => { + // Basic escaping for attribute value + const safeUrl = url.replace(/"/g, '"'); + return `${text}`; + })); - // 7. Lists - html = html.replaceAll(/^\s*-\s+(.*$)/gim, '
  2. $1
  3. '); + // 7. Auto-link project references (e.g. ADRs) - do this AFTER markdown links to avoid nesting + html = this.autoLinkProjectReferences(html); - // 8. Paragraphs - wrap non-block elements in

    + // 8. Lists (Unordered and Ordered) + html = html.replaceAll(/^\s*-\s+(.*$)/gim, '

  4. $1
  5. '); + html = html.replaceAll(/^\s*\d+\.\s+(.*$)/gim, '
  6. $1
  7. '); + + // 8. Tables const lines = html.split('\n'); - const processedLines = lines.map(line => { + const processedLines: string[] = []; + let tableLines: string[] = []; + + const isSeparatorLine = (line: string) => { + const trimmed = line.trim(); + if (!trimmed.includes('|') && !trimmed.startsWith('---')) return false; + // Remove optional leading/trailing pipes + let content = trimmed; + if (content.startsWith('|')) content = content.slice(1); + if (content.endsWith('|')) content = content.slice(0, -1); + const cells = content.split('|'); + return cells.length > 0 && cells.every(cell => /^[ :-]+$/.test(cell.trim())); + }; + + const isTableLine = (line: string) => line.trim().includes('|'); + + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + if (isTableLine(line) || (tableLines.length === 1 && isSeparatorLine(line))) { + tableLines.push(line); + } else { + if (tableLines.length >= 2 && isSeparatorLine(tableLines[1])) { + processedLines.push(this.parseTable(tableLines)); + tableLines = []; + } else if (tableLines.length > 0) { + processedLines.push(...tableLines); + tableLines = []; + } + processedLines.push(line); + } + } + if (tableLines.length >= 2 && isSeparatorLine(tableLines[1])) { + processedLines.push(this.parseTable(tableLines)); + } else if (tableLines.length > 0) { + processedLines.push(...tableLines); + } + + // 9. Paragraphs - wrap non-block elements in

    and group lists + const finalLines = processedLines.join('\n').split('\n'); + const groupedLines: string[] = []; + let currentListType: 'ul' | 'ol' | null = null; + + finalLines.forEach(line => { const trimmed = line.trim(); - if (!trimmed || trimmed.startsWith('__CODE_BLOCK_')) { - return line; + const isUl = trimmed.includes('class="ul-item"'); + const isOl = trimmed.includes('class="ol-item"'); + + // 1. Handle list transitions + if (isUl) { + if (currentListType !== 'ul') { + if (currentListType) groupedLines.push(``); + groupedLines.push('

      '); + currentListType = 'ul'; + } + groupedLines.push(line.replace(' class="ul-item"', '')); + return; + } else if (isOl) { + if (currentListType !== 'ol') { + if (currentListType) groupedLines.push(``); + groupedLines.push('
        '); + currentListType = 'ol'; + } + groupedLines.push(line.replace(' class="ol-item"', '')); + return; + } else { + if (currentListType) { + groupedLines.push(``); + currentListType = null; + } + } + + // 2. Handle non-list lines + if (!trimmed || trimmed.startsWith(':::CODE_BLOCK_')) { + groupedLines.push(line); + return; } + if (trimmed.startsWith('${line}

        `; + groupedLines.push(`

        ${line}

        `); }); - html = processedLines.join('\n'); + if (currentListType) { + groupedLines.push(``); + } - // Group adjacent
      1. items into
          - html = html.replaceAll(/(
        • .*<\/li>\s*)+/g, (match) => { - return `
            ${match}
          `; - }); + html = groupedLines.join('\n'); - // 9. Restore code blocks + // 10. Restore code blocks codeBlocks.forEach((block, i) => { - html = html.replaceAll(`__CODE_BLOCK_${i}__`, block); + html = html.replaceAll(`:::CODE_BLOCK_${i}:::`, block); }); return html; } + /** + * Automatically turn project-specific references into links. + * e.g. ADR-0011 -> link to adr-full-set.md#ADR-0011 + */ + private autoLinkProjectReferences(html: string): string { + // 1. ADR-XXXX -> link to full set + // 2. AI-XX-NN -> link to specific task file + // We match all tags/links first to avoid nesting within existing or blocks + // and to avoid matching inside attributes of other tags + return html.replaceAll(/(<(a|code|pre|span)[^>]*>[\s\S]*?<\/\2>)|(<[^>]+>)|(\bADR-(\d{4})\b)|(\b(AI-[A-Z-]+)-(\d+)\b)/gi, (match, specialTag, _tagName, normalTag, adr, adrId, ai, category) => { + if (specialTag || normalTag) return match; // Return existing tags as is + if (adr) return `${match}`; + if (ai) { + return `${match}`; + } + return match; + }); + } + + /** + * Intercept clicks on links to use Angular router for internal links. + */ + @HostListener('click', ['$event']) + onHtmlClick(event: MouseEvent): void { + const target = event.target as HTMLElement; + const anchor = target.closest('a'); + + if (anchor) { + const href = anchor.getAttribute('href'); + if (href) { + if (href.startsWith('/help/') || href.startsWith('help/')) { + event.preventDefault(); + // router.navigateByUrl handles both path and fragment correctly + this.router.navigateByUrl(href); + } else if (href.startsWith('#')) { + // If it's a fragment link, it might be intended for the current help page + // but if we are in Copilot, we don't know which help page it refers to. + // For now, let it be. + } + } + } + } + + private parseTable(lines: string[]): string { + if (lines.length < 2) return lines.join('\n'); + + const rows = lines.map(line => { + let content = line.trim(); + // Remove leading and trailing pipes if present + if (content.startsWith('|')) content = content.slice(1); + if (content.endsWith('|')) content = content.slice(0, -1); + + // Temporarily protect pipes inside links and inline code to avoid splitting them into separate cells + const tagPipePlaceholder = '___PIPE_P___'; + const protectedContent = content.replace(/(<(a|code|span)[^>]*>.*?<\/\2>)/gi, (match) => { + return match.replaceAll('|', tagPipePlaceholder); + }); + + // Split by pipe but respect escaped pipes \| + // We use a temporary placeholder for escaped pipes + const parts = protectedContent.replaceAll('\\|', ':::PIPE:::').split('|'); + return parts.map(p => p.replaceAll(':::PIPE:::', '|').replaceAll(tagPipePlaceholder, '|').trim()); + }); + + // Verify separator row again (it must be at index 1) + const isSeparator = rows[1].every(cell => /^[ :-]+$/.test(cell)); + if (!isSeparator) return lines.join('\n'); + + const headers = rows[0]; + const dataRows = rows.slice(2); + + let tableHtml = '\n\n\n'; + headers.forEach(h => { + tableHtml += `\n`; + }); + tableHtml += '\n\n\n'; + + dataRows.forEach(row => { + // If a row has fewer columns than headers, pad it + // If it has more, it will just have extra columns + tableHtml += '\n'; + row.forEach(cell => { + // If the cell contains a header tag (accidental merge), we might want to split it? + // But for now, let's just render it. + tableHtml += `\n`; + }); + tableHtml += '\n'; + }); + + tableHtml += '\n
          ${h}
          ${cell}
          '; + return tableHtml; + } + private transformLinks(html: string): string { // Transform [text](doc/path/to/file.md) to [text](/help/file) // and [text](http://.../help/doc/path/to/file.md) to [text](/help/file) - return html.replace(/]*?\s+)?href="([^"]*)"/g, (match, href) => { - if (href.includes('/help/') || href.endsWith('.md') || href.startsWith('doc/')) { - let newHref = href; + // We use a more robust regex to match the whole tag and preserve other attributes + return html.replaceAll(/]*?)href="([^"]*)"([^>]*?)>/g, (match, before, href, after) => { + let finalHref = href; + + // 1. Handle fragment-only links if basePath is provided + if (finalHref.startsWith('#') && this.basePath) { + finalHref = this.basePath + finalHref; + } - // Strip domain and /help/ prefix if present - if (newHref.includes('/help/')) { - newHref = newHref.split('/help/')[1]; + // Safety check for dangerous protocols + const lowerHref = finalHref.toLowerCase().trim(); + if (lowerHref.startsWith('javascript:') || lowerHref.startsWith('data:') || lowerHref.startsWith('vbscript:')) { + // Neutralize dangerous links by keeping the content but removing the link functionality + // We preserve other attributes but replace href with # + const cleanBefore = before && !before.endsWith(' ') ? before + ' ' : before; + const cleanAfter = after && !after.startsWith(' ') ? ' ' + after : after; + return ``; + } + + const isHelpLink = (finalHref.includes('/help/') || finalHref.endsWith('.md') || + finalHref.startsWith('doc/') || finalHref.includes('.md#') || + (!finalHref.startsWith('/') && !finalHref.includes('://') && !finalHref.startsWith('mailto:') && !finalHref.startsWith('tel:'))); + + if (isHelpLink) { + let newHref = finalHref; + + // Separate path and fragment + let [pathPart, ...fragmentParts] = newHref.split('#'); + let fragmentPart = fragmentParts.join('#'); + + // Strip domain and /help/ prefix if present from pathPart + if (pathPart.includes('/help/')) { + pathPart = pathPart.split('/help/')[1]; } - // Strip file extension - newHref = newHref.replace('.md', ''); + // Extract last filename segment ONLY IF it's not already a deep path starting with doc/ + if (pathPart.includes('/') && !pathPart.startsWith('doc/') && !pathPart.startsWith('scripts/') && !pathPart.startsWith('/') && !pathPart.includes('..')) { + const parts = pathPart.split('/'); + pathPart = parts[parts.length - 1]; + } - // Extract last filename segment if it's a path - if (newHref.includes('/')) { - const parts = newHref.split('/'); - newHref = parts[parts.length - 1]; + // Remove .md extension for cleaner help links + if (pathPart.endsWith('.md')) { + // But only if it's not a deep path, or if we want to clean those too + if (!pathPart.startsWith('doc/') && !pathPart.startsWith('scripts/') && !pathPart.includes('/')) { + pathPart = pathPart.replace('.md', ''); + } } - // Return the simplified help link - return ``; } + return match; }); } diff --git a/frontend/src/app/components/shared/onboarding-assistant.component.spec.ts b/frontend/src/app/components/shared/onboarding-assistant.component.spec.ts index e43c5425..9efc1707 100644 --- a/frontend/src/app/components/shared/onboarding-assistant.component.spec.ts +++ b/frontend/src/app/components/shared/onboarding-assistant.component.spec.ts @@ -2,6 +2,7 @@ import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testin import { OnboardingAssistantComponent } from './onboarding-assistant.component'; import { AiService } from '../../services/ai.service'; import { AuthService } from '../../services/auth.service'; +import { Router } from '@angular/router'; import { of, throwError } from 'rxjs'; import { signal } from '@angular/core'; import { provideHttpClient } from '@angular/common/http'; @@ -14,6 +15,7 @@ describe('OnboardingAssistantComponent', () => { let fixture: ComponentFixture; let aiServiceSpy: any; let authServiceSpy: any; + let routerSpy: any; let currentUserSignal = signal(null); beforeEach(async () => { @@ -25,11 +27,17 @@ describe('OnboardingAssistantComponent', () => { currentUser: currentUserSignal }; + routerSpy = { + navigate: vi.fn(), + navigateByUrl: vi.fn() + }; + await TestBed.configureTestingModule({ imports: [OnboardingAssistantComponent], providers: [ { provide: AiService, useValue: aiServiceSpy }, { provide: AuthService, useValue: authServiceSpy }, + { provide: Router, useValue: routerSpy }, provideHttpClient(), provideHttpClientTesting(), provideAnimationsAsync() @@ -104,4 +112,52 @@ describe('OnboardingAssistantComponent', () => { expect(component.isLoading()).toBeFalsy(); expect(component.response()).toBeNull(); }); + + it('should navigate and close when an action is clicked', () => { + currentUserSignal.set({ login: 'testuser', role: 'ROLE_USER' } as User); + fixture.detectChanges(); + component.isOpen.set(true); + + component.onActionClick('Check the Risk Radar'); + expect(routerSpy.navigate).toHaveBeenCalledWith(['/risk-radar']); + expect(component.isOpen()).toBeFalsy(); + + component.isOpen.set(true); + component.onActionClick('Manage Tasks'); + expect(routerSpy.navigate).toHaveBeenCalledWith(['/tasks']); + expect(component.isOpen()).toBeFalsy(); + + component.isOpen.set(true); + const askSpy = vi.spyOn(component, 'ask'); + component.onActionClick('Unknown action'); + expect(askSpy).toHaveBeenCalledWith('Unknown action'); + expect(component.isOpen()).toBeTruthy(); // Should stay open for the new answer + }); + + it('should handle markdown links in actions', () => { + currentUserSignal.set({ login: 'testuser', role: 'ROLE_USER' } as User); + fixture.detectChanges(); + component.isOpen.set(true); + + component.onActionClick('Check this [Help Page](/help/navigation)'); + expect(routerSpy.navigateByUrl).toHaveBeenCalledWith('/help/navigation'); + expect(component.isOpen()).toBeFalsy(); + + component.isOpen.set(true); + const windowSpy = vi.spyOn(window, 'open').mockImplementation(() => ({} as any)); + component.onActionClick('External [Link](https://example.com)'); + expect(windowSpy).toHaveBeenCalledWith('https://example.com', '_blank'); + expect(component.isOpen()).toBeFalsy(); + }); + + it('should clear history', () => { + currentUserSignal.set({ login: 'testuser', role: 'ROLE_USER' } as User); + fixture.detectChanges(); + component.response.set({ answer: 'Mock answer' } as any); + component.query.set('test question'); + + component.clearHistory(); + expect(component.response()).toBeNull(); + expect(component.query()).toBe(''); + }); }); diff --git a/frontend/src/app/components/shared/onboarding-assistant.component.ts b/frontend/src/app/components/shared/onboarding-assistant.component.ts index d0ddaeff..06403fea 100644 --- a/frontend/src/app/components/shared/onboarding-assistant.component.ts +++ b/frontend/src/app/components/shared/onboarding-assistant.component.ts @@ -1,6 +1,7 @@ import { Component, signal, inject, computed, effect } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; +import { Router, RouterModule } from '@angular/router'; import { MatCardModule } from '@angular/material/card'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; @@ -9,6 +10,9 @@ import { MatInputModule } from '@angular/material/input'; import { MatProgressBarModule } from '@angular/material/progress-bar'; import { MatListModule } from '@angular/material/list'; import { MatDividerModule } from '@angular/material/divider'; +import { MatTooltipModule } from '@angular/material/tooltip'; +import { TranslateModule } from '@ngx-translate/core'; +import { MarkdownViewerComponent } from '../shared/markdown-viewer/markdown-viewer.component'; import { AiService } from '../../services/ai.service'; import { AuthService } from '../../services/auth.service'; import { CopilotResponse } from '../../models/ai.model'; @@ -19,6 +23,7 @@ import { CopilotResponse } from '../../models/ai.model'; imports: [ CommonModule, FormsModule, + RouterModule, MatCardModule, MatButtonModule, MatIconModule, @@ -26,7 +31,10 @@ import { CopilotResponse } from '../../models/ai.model'; MatInputModule, MatProgressBarModule, MatListModule, - MatDividerModule + MatDividerModule, + MatTooltipModule, + TranslateModule, + MarkdownViewerComponent ], template: ` @if (isLoggedIn()) { @@ -37,40 +45,48 @@ import { CopilotResponse } from '../../models/ai.model'; @if (isOpen()) { - - AI Onboarding Assistant - Ask me how to use GoodOne! + +
          + {{ 'ONBOARDING_ASSISTANT.TITLE' | translate }} + {{ 'ONBOARDING_ASSISTANT.SUBTITLE' | translate }} +
          + @if (response() || isLoading()) { + + }
          @if (!response() && !isLoading()) { -

          Hi! I'm your AI assistant. You can ask me things like:

          +

          {{ 'ONBOARDING_ASSISTANT.WELCOME' | translate }}

            -
          • How do I create a new task?
          • -
          • What is the AI Risk Radar?
          • -
          • Where can I see the roadmap?
          • +
          • {{ 'ONBOARDING_ASSISTANT.Q1' | translate }}
          • +
          • {{ 'ONBOARDING_ASSISTANT.Q2' | translate }}
          • +
          • {{ 'ONBOARDING_ASSISTANT.Q3' | translate }}
          • +
          • {{ 'ONBOARDING_ASSISTANT.Q4' | translate }}
          } @if (isLoading()) {
          -

          Thinking...

          +

          {{ 'ONBOARDING_ASSISTANT.THINKING' | translate }}

          } @if (response(); as res) {
          - Ask a question... + {{ 'ONBOARDING_ASSISTANT.INPUT_LABEL' | translate }} - @@ -152,11 +168,6 @@ import { CopilotResponse } from '../../models/ai.model'; text-align: center; margin-top: 24px; } - .answer { - line-height: 1.5; - margin: 16px 0; - white-space: pre-wrap; - } .full-width { width: 100%; margin-top: 8px; @@ -171,6 +182,30 @@ import { CopilotResponse } from '../../models/ai.model'; flex-wrap: wrap; gap: 4px; } + .action-item { + cursor: pointer; + height: auto !important; + min-height: 32px; + } + .action-item:hover { + background: rgba(0,0,0,0.04); + } + .action-text { + white-space: normal; + line-height: 1.2; + font-size: 0.85rem; + display: block; + padding: 4px 0; + color: var(--brand); + transition: opacity 0.2s; + } + .action-item:hover .action-text { + text-decoration: underline; + opacity: 0.8; + } + ::ng-deep .action-item .mat-mdc-list-item-line { + white-space: normal !important; + } .animate-slide-up { animation: slideUp 0.3s ease-out; } @@ -190,6 +225,7 @@ import { CopilotResponse } from '../../models/ai.model'; export class OnboardingAssistantComponent { private readonly aiService = inject(AiService); private readonly authService = inject(AuthService); + private readonly router = inject(Router); readonly isLoggedIn = computed(() => !!this.authService.currentUser()); @@ -207,10 +243,77 @@ export class OnboardingAssistantComponent { }); } + getPath(ev: string): string { + if (!ev) return ''; + const rawPath = ev.includes('#') ? ev.split('#')[0] : ev; + try { + return decodeURIComponent(rawPath); + } catch { + return rawPath; + } + } + + getFragment(ev: string): string { + if (!ev || !ev.includes('#')) return ''; + const rawFragment = ev.split('#')[1]; + try { + return decodeURIComponent(rawFragment); + } catch { + return rawFragment; + } + } + toggleOpen() { this.isOpen.update(v => !v); } + clearHistory() { + this.response.set(null); + this.query.set(''); + } + + onActionClick(step: string) { + // 1. Check for markdown links in the step text [text](url) + const linkMatch = step.match(/\[([^\]]+)\]\(([^)]+)\)/); + if (linkMatch) { + const url = linkMatch[2]; + if (url.startsWith('/') || url.startsWith('http')) { + if (url.startsWith('http://localhost:4200')) { + const path = url.replace('http://localhost:4200', ''); + this.router.navigateByUrl(path); + } else if (url.startsWith('/')) { + this.router.navigateByUrl(url); + } else { + window.open(url, '_blank'); + } + this.isOpen.set(false); + return; + } + } + + const s = step.toLowerCase(); + if (s.includes('risk radar')) { + this.router.navigate(['/risk-radar']); + this.isOpen.set(false); + } else if (s.includes('task')) { + this.router.navigate(['/tasks']); + this.isOpen.set(false); + } else if (s.includes('architecture')) { + this.router.navigate(['/architecture']); + this.isOpen.set(false); + } else if (s.includes('intelligence')) { + this.router.navigate(['/intelligence']); + this.isOpen.set(false); + } else if (s.includes('epic')) { + this.router.navigate(['/epics']); + this.isOpen.set(false); + } else { + // Default fallback: ask the assistant again instead of navigating to a broken search page + this.ask(step); + // Keep chat open for the new answer + } + } + ask(presetQuery?: string) { const q = presetQuery || this.query().trim(); if (!q || this.isLoading()) return; diff --git a/frontend/src/app/components/shared/task-group-selector/task-group-selector.component.ts b/frontend/src/app/components/shared/task-group-selector/task-group-selector.component.ts index 39b8d398..74c9b9a3 100644 --- a/frontend/src/app/components/shared/task-group-selector/task-group-selector.component.ts +++ b/frontend/src/app/components/shared/task-group-selector/task-group-selector.component.ts @@ -34,8 +34,8 @@ import { TaskGroup, TaskGroupType } from '../../../services/ai.service'; @for (group of availableGroups; track group.id; let isFirst = $first) {
          @if (multiple) { - - {{ getFullLabel(group) }} + + {{ getFullLabel(group) }} @if (showLatestTag && isFirst) { ({{ 'INTELLIGENCE.LATEST_TAG' | translate }}) } } @else { diff --git a/frontend/src/app/features/architecture/architecture-qa.component.css b/frontend/src/app/features/architecture/architecture-qa.component.css index 41cc97a2..62d30c4c 100644 --- a/frontend/src/app/features/architecture/architecture-qa.component.css +++ b/frontend/src/app/features/architecture/architecture-qa.component.css @@ -312,7 +312,6 @@ mat-card-content { display: flex; justify-content: space-between; align-items: center; - margin-bottom: 4px; } .source-title { @@ -322,13 +321,6 @@ mat-card-content { transition: color 0.2s; } -.source-path { - font-size: 12px; - color: var(--text-muted); - word-break: break-all; - font-family: 'JetBrains Mono', 'Fira Code', monospace; - opacity: 0.8; -} .source-relevance { font-size: 11px; diff --git a/frontend/src/app/features/architecture/architecture-qa.component.html b/frontend/src/app/features/architecture/architecture-qa.component.html index fc0c4eec..55f4f361 100644 --- a/frontend/src/app/features/architecture/architecture-qa.component.html +++ b/frontend/src/app/features/architecture/architecture-qa.component.html @@ -77,18 +77,14 @@

          @if (msg.result.evidence && msg.result.evidence.length > 0) {
          @for (source of msg.result.evidence; track source + '-' + $index) { - + }
          } @else { diff --git a/frontend/src/app/features/architecture/architecture-qa.component.spec.ts b/frontend/src/app/features/architecture/architecture-qa.component.spec.ts index 72f42d4b..e3042d80 100644 --- a/frontend/src/app/features/architecture/architecture-qa.component.spec.ts +++ b/frontend/src/app/features/architecture/architecture-qa.component.spec.ts @@ -146,16 +146,11 @@ describe('ArchitectureQaComponent', () => { expect(writeTextSpy).toHaveBeenCalledWith('E1'); }); - it('should map path to page id correctly', () => { - expect(component.mapPathToPageId('doc/user-guide.md')).toBe('user-guide'); - expect(component.mapPathToPageId('admin-guide/intro.md')).toBe('admin-guide'); - expect(component.mapPathToPageId('unknown')).toBe(''); - }); - - it('should navigate to source when it is linkable', () => { - const navigateSpy = vi.spyOn((component as any).router, 'navigate'); - component.navigateToSource('doc/user-guide.md'); - expect(navigateSpy).toHaveBeenCalledWith(['/help', 'user-guide']); + it('should get path and fragment correctly', () => { + expect(component.getPath('doc/adr.md#section')).toBe('doc/adr.md'); + expect(component.getFragment('doc/adr.md#section')).toBe('section'); + expect(component.getPath('doc/readme.md')).toBe('doc/readme.md'); + expect(component.getFragment('doc/readme.md')).toBe(''); }); it('should handle duplicate sources without error', async () => { diff --git a/frontend/src/app/features/architecture/architecture-qa.component.ts b/frontend/src/app/features/architecture/architecture-qa.component.ts index 31f8ff30..d0e6692b 100644 --- a/frontend/src/app/features/architecture/architecture-qa.component.ts +++ b/frontend/src/app/features/architecture/architecture-qa.component.ts @@ -1,5 +1,6 @@ import { Component, signal, computed, ViewChild, ElementRef, AfterViewChecked, OnInit } from '@angular/core'; import { CommonModule } from '@angular/common'; +import { RouterModule } from '@angular/router'; import { FormControl, ReactiveFormsModule } from '@angular/forms'; import { MatCardModule } from '@angular/material/card'; import { MatFormFieldModule } from '@angular/material/form-field'; @@ -29,6 +30,7 @@ import { AiResultComponent } from '../../components/shared/ai-result/ai-result.c MatProgressSpinnerModule, MatSnackBarModule, TranslateModule, + RouterModule, MarkdownViewerComponent, AiDisabledPlaceholderComponent, AiResultComponent @@ -150,6 +152,26 @@ export class ArchitectureQaComponent extends BaseAiComponent implements AfterVie }); } + getPath(ev: string): string { + if (!ev) return ''; + const rawPath = ev.includes('#') ? ev.split('#')[0] : ev; + try { + return decodeURIComponent(rawPath); + } catch { + return rawPath; + } + } + + getFragment(ev: string): string { + if (!ev || !ev.includes('#')) return ''; + const rawFragment = ev.split('#')[1]; + try { + return decodeURIComponent(rawFragment); + } catch { + return rawFragment; + } + } + clear() { this.messages.set([]); this.questionControl.setValue(''); @@ -218,26 +240,4 @@ export class ArchitectureQaComponent extends BaseAiComponent implements AfterVie }); }); } - - mapPathToPageId(path: string): string { - const p = path.toLowerCase(); - if (p.includes('user-guide')) return 'user-guide'; - if (p.includes('admin-guide')) return 'admin-guide'; - if (p.includes('faq')) return 'faq'; - if (p.includes('release-notes')) return 'release-notes'; - if (p.includes('readme')) return 'readme'; - if (p.includes('deployment')) return 'deployment'; - if (p.includes('postgres')) return 'postgres-setup'; - if (p.includes('frontend')) return 'frontend-dev'; - if (p.includes('backend')) return 'backend-dev'; - if (p.includes('docker')) return 'docker-optimization'; - return ''; - } - - navigateToSource(path: string) { - const pageId = this.mapPathToPageId(path); - if (pageId) { - this.router.navigate(['/help', pageId]); - } - } } diff --git a/frontend/src/app/features/copilot/copilot-workspace.component.css b/frontend/src/app/features/copilot/copilot-workspace.component.css index e8e517d6..768ee7d3 100644 --- a/frontend/src/app/features/copilot/copilot-workspace.component.css +++ b/frontend/src/app/features/copilot/copilot-workspace.component.css @@ -318,8 +318,27 @@ color: #888; } -.evidence-list { display: flex; flex-direction: column; gap: 4px; } -.evidence-item { font-family: monospace; font-size: 0.8rem; color: #666; } +.evidence-list { display: flex; flex-wrap: wrap; gap: 8px; } +.evidence-link { + height: 32px !important; + line-height: 32px !important; + font-size: 0.85rem !important; + background: rgba(63, 81, 181, 0.05) !important; + border-radius: 6px !important; + padding: 0 12px !important; + text-transform: none !important; + font-family: inherit !important; +} +.evidence-link mat-icon { + font-size: 18px !important; + width: 18px !important; + height: 18px !important; + margin-right: 4px !important; +} +.evidence-link:hover { + background: rgba(63, 81, 181, 0.1) !important; + text-decoration: underline !important; +} .actions-section h4 { margin: 0 0 12px; diff --git a/frontend/src/app/features/copilot/copilot-workspace.component.html b/frontend/src/app/features/copilot/copilot-workspace.component.html index a34acdc5..a7f48cbb 100644 --- a/frontend/src/app/features/copilot/copilot-workspace.component.html +++ b/frontend/src/app/features/copilot/copilot-workspace.component.html @@ -125,7 +125,10 @@

          {{ 'COPILOT.EMPTY_STATE_TITLE' | translate }}

          {{ 'COPILOT.SOURCES_TITLE' | translate }}

          @for (ev of msg.result.evidence; track $index) { -
          {{ ev }}
          + + description + {{ ev }} + }
          diff --git a/frontend/src/app/features/copilot/copilot-workspace.component.spec.ts b/frontend/src/app/features/copilot/copilot-workspace.component.spec.ts new file mode 100644 index 00000000..9396463a --- /dev/null +++ b/frontend/src/app/features/copilot/copilot-workspace.component.spec.ts @@ -0,0 +1,83 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { CopilotWorkspaceComponent } from './copilot-workspace.component'; +import { AiService } from '../../services/ai.service'; +import { AuthService } from '../../services/auth.service'; +import { TranslateModule } from '@ngx-translate/core'; +import { provideHttpClient } from '@angular/common/http'; +import { provideHttpClientTesting } from '@angular/common/http/testing'; +import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; +import { of } from 'rxjs'; +import { signal } from '@angular/core'; +import { By } from '@angular/platform-browser'; +import { provideRouter } from '@angular/router'; + +describe('CopilotWorkspaceComponent', () => { + let component: CopilotWorkspaceComponent; + let fixture: ComponentFixture; + let aiServiceSpy: any; + let authServiceSpy: any; + + beforeEach(async () => { + aiServiceSpy = { + getTaskGroups: vi.fn().mockReturnValue(of([])), + setSelectedTaskGroupIds: vi.fn(), + askCopilot: vi.fn(), + setContext: vi.fn(), + getSelectedTaskGroupIds: vi.fn().mockReturnValue(of([])), + getCopilotHistory: vi.fn().mockReturnValue(of([])) + }; + + authServiceSpy = { + isLoggedIn: vi.fn().mockReturnValue(true), + isAiAvailable: vi.fn().mockReturnValue(true), + hasAiCredits: vi.fn().mockReturnValue(true), + currentUser: signal({ login: 'testuser', role: 'ROLE_USER' }) + }; + + await TestBed.configureTestingModule({ + imports: [CopilotWorkspaceComponent, TranslateModule.forRoot()], + providers: [ + { provide: AiService, useValue: aiServiceSpy }, + { provide: AuthService, useValue: authServiceSpy }, + provideHttpClient(), + provideHttpClientTesting(), + provideAnimationsAsync(), + provideRouter([]) + ] + }).compileComponents(); + + fixture = TestBed.createComponent(CopilotWorkspaceComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should render evidence as links', () => { + // Setup message with evidence + const mockMessage = { + role: 'assistant', + text: 'Here is the info.', + timestamp: new Date(), + section: 'ARCHITECTURE_QA', + result: { + answer: 'Here is the info.', + evidence: ['doc/features/index.md', 'doc/features/navigation.md'], + suggestedActions: [], + relatedSignals: [] + } + }; + + component.messages.set([mockMessage as any]); + fixture.detectChanges(); + + const evidenceLinks = fixture.debugElement.queryAll(By.css('.evidence-link')); + expect(evidenceLinks.length).toBe(2); + + expect(evidenceLinks[0].nativeElement.textContent).toContain('doc/features/index.md'); + // For routerLink, we check the [routerLink] directive or the resulting href + // Since we used [routerLink]="['/help', ev]", it should point to /help/doc/features/index.md + expect(evidenceLinks[0].nativeElement.getAttribute('href')).toBe('/help/doc/features/index.md'); + + expect(evidenceLinks[1].nativeElement.textContent).toContain('doc/features/navigation.md'); + expect(evidenceLinks[1].nativeElement.getAttribute('href')).toBe('/help/doc/features/navigation.md'); + }); +}); diff --git a/frontend/src/app/features/copilot/copilot-workspace.component.ts b/frontend/src/app/features/copilot/copilot-workspace.component.ts index 1d1ac2b5..4b410b5e 100644 --- a/frontend/src/app/features/copilot/copilot-workspace.component.ts +++ b/frontend/src/app/features/copilot/copilot-workspace.component.ts @@ -1,5 +1,6 @@ import { Component, signal, computed, ViewChild, ElementRef, AfterViewChecked, OnInit } from '@angular/core'; import { CommonModule } from '@angular/common'; +import { RouterModule } from '@angular/router'; import { FormControl, ReactiveFormsModule } from '@angular/forms'; import { MatCardModule } from '@angular/material/card'; import { MatFormFieldModule } from '@angular/material/form-field'; @@ -39,6 +40,7 @@ import { AiTransparencyModel } from '../../shared/ai-transparency/ai-transparenc MatChipsModule, MatTooltipModule, TranslateModule, + RouterModule, MarkdownViewerComponent, AiResultComponent, AiTransparencyPanelComponent, @@ -125,6 +127,28 @@ export class CopilotWorkspaceComponent extends BaseAiComponent implements AfterV this.aiService.setSelectedTaskGroupIds(newIds); } + getPath(ev: string): string { + if (!ev) return ''; + const rawPath = ev.includes('#') ? ev.split('#')[0] : ev; + // Decode in case it was already encoded (to avoid double encoding in routerLink) + try { + return decodeURIComponent(rawPath); + } catch { + return rawPath; + } + } + + getFragment(ev: string): string { + if (!ev || !ev.includes('#')) return ''; + const rawFragment = ev.split('#')[1]; + // Decode in case it was already encoded (to avoid double encoding in fragment) + try { + return decodeURIComponent(rawFragment); + } catch { + return rawFragment; + } + } + ngAfterViewChecked() { this.scrollToBottom(); } @@ -322,7 +346,8 @@ export class CopilotWorkspaceComponent extends BaseAiComponent implements AfterV role: h.role, text: h.content, timestamp: new Date(h.timestamp), - section: h.mode + section: h.mode, + result: h.result ? JSON.parse(h.result) : undefined })); this.messages.set(msgs); } else { @@ -372,6 +397,7 @@ export class CopilotWorkspaceComponent extends BaseAiComponent implements AfterV promptHash: result.promptHash || (result.metadata?.['promptHash'] as string), retrievedDocumentCount: result.retrievedDocumentCount ?? (result.metadata?.['retrievedDocumentCount'] as number) ?? 0, retrievedDocumentPaths: result.retrievedDocumentPaths || (result.metadata?.['retrievedDocumentPaths'] as string[]) || [], + retrievedDocumentContents: result.retrievedDocumentContents, latencyMs: result.latencyMs ?? (result.metadata?.['latencyMs'] as number), section: (result.metadata?.['section'] as string) || this.getModeLabelKey(this.activeMode()), confidence: result.confidence diff --git a/frontend/src/app/features/intelligence/engineering-intelligence-dashboard.component.css b/frontend/src/app/features/intelligence/engineering-intelligence-dashboard.component.css index adb3baf9..928b4d3f 100644 --- a/frontend/src/app/features/intelligence/engineering-intelligence-dashboard.component.css +++ b/frontend/src/app/features/intelligence/engineering-intelligence-dashboard.component.css @@ -112,6 +112,21 @@ h2 { display: flex; align-items: center; gap: 12px; margin: 40px 0 20px; font-si .fallback-data { color: #888; font-style: italic; margin: 16px 0; } .adr-link { color: #3f51b5; font-weight: 500; } + +.task-link { + color: #3f51b5; + text-decoration: none; + font-weight: 500; + border-bottom: 1px dashed #3f51b5; + transition: all 0.2s ease; +} + +.task-link:hover { + color: #303f9f; + border-bottom-style: solid; + background-color: rgba(63, 81, 181, 0.05); +} + .evidence-chips { display: flex; gap: 8px; flex-wrap: wrap; } .truncate-reason { max-width: 300px; diff --git a/frontend/src/app/features/intelligence/engineering-intelligence-dashboard.component.html b/frontend/src/app/features/intelligence/engineering-intelligence-dashboard.component.html index 7fd536f2..2c67869a 100644 --- a/frontend/src/app/features/intelligence/engineering-intelligence-dashboard.component.html +++ b/frontend/src/app/features/intelligence/engineering-intelligence-dashboard.component.html @@ -296,7 +296,13 @@

          account_tree Automated Relationship Discovery

          - + @@ -306,7 +312,13 @@

          account_tree Automated Relationship Discovery

          - + diff --git a/frontend/src/app/features/intelligence/engineering-intelligence-dashboard.component.ts b/frontend/src/app/features/intelligence/engineering-intelligence-dashboard.component.ts index 9fe63724..136824eb 100644 --- a/frontend/src/app/features/intelligence/engineering-intelligence-dashboard.component.ts +++ b/frontend/src/app/features/intelligence/engineering-intelligence-dashboard.component.ts @@ -12,6 +12,7 @@ import { MatFormFieldModule } from '@angular/material/form-field'; import { MatSelectModule } from '@angular/material/select'; import { MatMenuModule } from '@angular/material/menu'; import { MatButtonModule } from '@angular/material/button'; +import { RouterLink } from '@angular/router'; import { Subscription } from 'rxjs'; import { TranslateModule } from '@ngx-translate/core'; import { AiService, TaskGroup, TaskGroupType } from '../../services/ai.service'; @@ -29,7 +30,7 @@ import { IndexingScope } from '../../services/admin.service'; @Component({ selector: 'app-engineering-intelligence-dashboard', standalone: true, - imports: [CommonModule, FormsModule, MatCardModule, MatProgressBarModule, MatIconModule, MatChipsModule, MatTableModule, MatDividerModule, MatTooltipModule, MatFormFieldModule, MatSelectModule, MatMenuModule, MatButtonModule, TranslateModule, TaskGroupSelectorComponent, AiSuggestionsPanelComponent, IndexingScopeSelectorComponent], + imports: [CommonModule, FormsModule, MatCardModule, MatProgressBarModule, MatIconModule, MatChipsModule, MatTableModule, MatDividerModule, MatTooltipModule, MatFormFieldModule, MatSelectModule, MatMenuModule, MatButtonModule, RouterLink, TranslateModule, TaskGroupSelectorComponent, AiSuggestionsPanelComponent, IndexingScopeSelectorComponent], templateUrl: './engineering-intelligence-dashboard.component.html', styleUrl: './engineering-intelligence-dashboard.component.css' }) @@ -187,4 +188,9 @@ export class EngineeringIntelligenceDashboardComponent implements OnInit, OnDest } }); } + + isTaskReference(text: string | undefined | null): boolean { + if (!text) return false; + return text.startsWith('AI-') || text.startsWith('sprint-'); + } } diff --git a/frontend/src/app/features/intelligence/epic-dashboard.component.ts b/frontend/src/app/features/intelligence/epic-dashboard.component.ts index 5029dc19..7cef08df 100644 --- a/frontend/src/app/features/intelligence/epic-dashboard.component.ts +++ b/frontend/src/app/features/intelligence/epic-dashboard.component.ts @@ -12,6 +12,7 @@ import { MatFormFieldModule } from '@angular/material/form-field'; import { MatSelectModule } from '@angular/material/select'; import { MatMenuModule } from '@angular/material/menu'; import { MatButtonModule } from '@angular/material/button'; +import { RouterLink } from '@angular/router'; import { Subscription } from 'rxjs'; import { TranslateModule } from '@ngx-translate/core'; import { AiService, TaskGroup, TaskGroupType } from '../../services/ai.service'; @@ -25,7 +26,7 @@ import { AuthService } from '../../services/auth.service'; @Component({ selector: 'app-epic-dashboard', standalone: true, - imports: [CommonModule, FormsModule, MatCardModule, MatProgressBarModule, MatIconModule, MatChipsModule, MatTableModule, MatDividerModule, MatTooltipModule, MatFormFieldModule, MatSelectModule, MatMenuModule, MatButtonModule, TranslateModule, TaskGroupSelectorComponent, IndexingScopeSelectorComponent], + imports: [CommonModule, FormsModule, MatCardModule, MatProgressBarModule, MatIconModule, MatChipsModule, MatTableModule, MatDividerModule, MatTooltipModule, MatFormFieldModule, MatSelectModule, MatMenuModule, MatButtonModule, RouterLink, TranslateModule, TaskGroupSelectorComponent, IndexingScopeSelectorComponent], template: `
          @@ -99,7 +100,13 @@ import { AuthService } from '../../services/auth.service'; {{ task.status === 'DONE' ? 'check_circle' : 'radio_button_unchecked' }} - {{ task.title }} + @if (isTaskReference(task.title)) { + + {{ task.title }} + + } @else { + {{ task.title }} + }
          } @@ -192,6 +199,25 @@ import { AuthService } from '../../services/auth.service'; .task-item mat-icon.done { color: #4caf50; } .task-title { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1; min-width: 0; } + .task-link { + color: #3f51b5; + text-decoration: none; + font-weight: 500; + border-bottom: 1px dashed #3f51b5; + transition: all 0.2s ease; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + flex: 1; + min-width: 0; + } + + .task-link:hover { + color: #303f9f; + border-bottom-style: solid; + background-color: rgba(63, 81, 181, 0.05); + } + .loading-container { max-width: 600px; margin: 100px auto; @@ -267,6 +293,17 @@ export class EpicDashboardComponent implements OnInit, OnDestroy { } } + isTaskReference(title: string | undefined | null): boolean { + if (!title) return false; + return title.startsWith('AI-') || title.startsWith('sprint-'); + } + + extractTaskId(title: string): string { + if (!title) return ''; + const match = title.match(/^(AI-[A-Z]+-\d+|sprint-\d+\.\d+[A-Z]?)/i); + return match ? match[0] : title; + } + onSprintChange(sprint: string): void { this.selectedSprint.set(sprint); localStorage.setItem(this.SPRINT_STORAGE_KEY, sprint); diff --git a/frontend/src/app/models/ai.model.ts b/frontend/src/app/models/ai.model.ts index a3ca6c19..450a96fd 100644 --- a/frontend/src/app/models/ai.model.ts +++ b/frontend/src/app/models/ai.model.ts @@ -22,6 +22,7 @@ export interface CopilotResponse { promptHash?: string; retrievedDocumentCount?: number; retrievedDocumentPaths?: string[]; + retrievedDocumentContents?: string[]; latencyMs?: number; } @@ -98,6 +99,7 @@ export interface CopilotChatHistoryDto { id?: number; role: 'user' | 'assistant'; content: string; + result?: string; mode: CopilotContextMode; timestamp: string; } diff --git a/frontend/src/app/models/retrospective.model.ts b/frontend/src/app/models/retrospective.model.ts index 207fa145..8445b6cb 100644 --- a/frontend/src/app/models/retrospective.model.ts +++ b/frontend/src/app/models/retrospective.model.ts @@ -46,6 +46,7 @@ export interface RiskRadarRequest { export interface RiskItem { pattern: string; evidence: string[]; + evidencePaths?: { [key: string]: string }; mitigations: string[]; category: string; severity?: EngineeringSignalSeverity; diff --git a/frontend/src/app/shared/ai-transparency/ai-transparency-panel.component.ts b/frontend/src/app/shared/ai-transparency/ai-transparency-panel.component.ts index e20babc9..3b514dbf 100644 --- a/frontend/src/app/shared/ai-transparency/ai-transparency-panel.component.ts +++ b/frontend/src/app/shared/ai-transparency/ai-transparency-panel.component.ts @@ -2,11 +2,12 @@ import { Component, Input, signal } from '@angular/core'; import { CommonModule, DecimalPipe } from '@angular/common'; import { TranslateModule } from '@ngx-translate/core'; import { AiTransparencyModel } from './ai-transparency.model'; +import { MarkdownViewerComponent } from '../../components/shared/markdown-viewer/markdown-viewer.component'; @Component({ selector: 'app-ai-transparency-panel', standalone: true, - imports: [CommonModule, DecimalPipe, TranslateModule], + imports: [CommonModule, DecimalPipe, TranslateModule, MarkdownViewerComponent], template: ` @if (dataSignal()) {
          @@ -39,14 +40,30 @@ import { AiTransparencyModel } from './ai-transparency.model'; } - @if (dataSignal()?.retrievedDocumentPaths && dataSignal()!.retrievedDocumentPaths.length > 0) { + @if (dataSignal()?.retrievedDocumentContents && dataSignal()!.retrievedDocumentContents!.length > 0) {
          Retrieved Sources:
          -
            +
            + @for (content of dataSignal()!.retrievedDocumentContents; track $index) { +
            + @if (dataSignal()!.retrievedDocumentPaths[$index]) { +
            {{ dataSignal()!.retrievedDocumentPaths[$index] }}
            + } + +
            + } +
            +
          + } @else if (dataSignal()?.retrievedDocumentPaths && dataSignal()!.retrievedDocumentPaths.length > 0) { +
          +
          Retrieved Documents:
          +
          @for (path of dataSignal()!.retrievedDocumentPaths; track $index) { -
        • {{ path }}
        • +
          +
          {{ path }}
          +
          } - +
          } @@ -115,7 +132,37 @@ import { AiTransparencyModel } from './ai-transparency.model'; .value { color: var(--text); } .sources-list { margin-top: 0.5rem; } .sources-title { font-weight: 500; margin-bottom: 0.25rem; } - .sources-list ul { margin: 0; padding-left: 1.25rem; } + .sources-scroll { + max-height: 250px; + overflow-y: auto; + border: 1px solid var(--border-weak); + border-radius: 4px; + padding: 0.25rem; + background: var(--surface-1); + } + .source-item { + padding: 0.5rem; + border-bottom: 1px solid var(--border-weak); + } + .source-path { + font-size: 0.75rem; + color: var(--text-muted); + margin-bottom: 0.25rem; + font-family: monospace; + word-break: break-all; + } + .source-item:last-child { border-bottom: none; } + :host ::ng-deep .source-item app-markdown-viewer .markdown-body h1, + :host ::ng-deep .source-item app-markdown-viewer .markdown-body h2, + :host ::ng-deep .source-item app-markdown-viewer .markdown-body h3, + :host ::ng-deep .source-item app-markdown-viewer .markdown-body h4 { + margin-top: 12px; + margin-bottom: 8px; + font-size: 1rem; + } + :host ::ng-deep .source-item app-markdown-viewer .markdown-body p { + margin-bottom: 8px; + } .hash-debug { margin-top: 0.5rem; font-family: monospace; diff --git a/frontend/src/app/shared/ai-transparency/ai-transparency.model.ts b/frontend/src/app/shared/ai-transparency/ai-transparency.model.ts index 8a4308ac..20bbc093 100644 --- a/frontend/src/app/shared/ai-transparency/ai-transparency.model.ts +++ b/frontend/src/app/shared/ai-transparency/ai-transparency.model.ts @@ -4,6 +4,7 @@ export interface AiTransparencyModel { promptHash?: string; retrievedDocumentCount: number; retrievedDocumentPaths: string[]; + retrievedDocumentContents?: string[]; fallbackUsed: boolean; latencyMs?: number; section?: string; diff --git a/frontend/src/styles.css b/frontend/src/styles.css index 23731943..a25aba92 100644 --- a/frontend/src/styles.css +++ b/frontend/src/styles.css @@ -1120,7 +1120,7 @@ body.theme-dark .mat-mdc-chip:not(.mdc-chip--selected):not(.high-contrast-chip) .help-content a, .copilot-response a, .onboarding-link a { - color: #0d6efd !important; /* Neutral blue (Bootstrap 5 Primary) */ + color: var(--brand) !important; /* Consistent with brand color */ text-decoration: underline !important; /* Underline as expected for links */ font-weight: 500 !important; cursor: pointer !important; @@ -1132,7 +1132,6 @@ body.theme-dark .mat-mdc-chip:not(.mdc-chip--selected):not(.high-contrast-chip) .copilot-response a:hover, .onboarding-link a:hover { text-decoration: underline !important; - color: #0a58ca !important; /* Darker blue on hover */ opacity: 0.8; } @@ -1141,17 +1140,17 @@ body.theme-dark .mat-mdc-chip:not(.mdc-chip--selected):not(.high-contrast-chip) .action-chips .mat-mdc-chip, .action-chips .mat-mdc-chip-row, .action-chips .mat-mdc-chip-option { - background-color: #0d6efd !important; /* Solid blue background */ + background-color: var(--brand) !important; /* Solid brand blue background */ color: #ffffff !important; /* High contrast white text */ border: none !important; font-weight: 600 !important; opacity: 1 !important; cursor: pointer !important; - box-shadow: 0 4px 10px rgba(13, 110, 253, 0.25) !important; + box-shadow: 0 4px 10px rgba(63, 81, 181, 0.25) !important; transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1) !important; - --mdc-chip-elevated-unselected-container-color: #0d6efd !important; + --mdc-chip-elevated-unselected-container-color: var(--brand) !important; --mdc-chip-label-text-color: #ffffff !important; - --mdc-chip-elevated-disabled-container-color: #0d6efd !important; + --mdc-chip-elevated-disabled-container-color: var(--brand) !important; --mdc-chip-disabled-label-text-color: #ffffff !important; user-select: none; } @@ -1160,10 +1159,11 @@ body.theme-dark .mat-mdc-chip:not(.mdc-chip--selected):not(.high-contrast-chip) .action-chips .mat-mdc-chip:hover, .action-chips .mat-mdc-chip-row:hover, .action-chips .mat-mdc-chip-option:hover { - background-color: #0a58ca !important; /* Darker blue on hover */ + background-color: var(--brand) !important; + opacity: 0.9; transform: translateY(-4px) !important; - box-shadow: 0 8px 16px rgba(13, 110, 253, 0.35) !important; - --mdc-chip-elevated-unselected-container-color: #0a58ca !important; + box-shadow: 0 8px 16px rgba(63, 81, 181, 0.35) !important; + --mdc-chip-elevated-unselected-container-color: var(--brand) !important; --mdc-chip-label-text-color: #ffffff !important; } diff --git a/scripts/generate_help_pages.py b/scripts/generate_help_pages.py index 5f38c192..8bee0a15 100644 --- a/scripts/generate_help_pages.py +++ b/scripts/generate_help_pages.py @@ -1,69 +1,105 @@ -import markdown import json import os # Configuration LANGUAGES = ["en", "de-ch"] -SOURCE_FILES = { - "en": [ - ("readme", "README.md"), - ("user-guide", "doc/user-guide/user-guide.md"), - ("faq", "doc/user-guide/faq.md"), - ("release-notes", "doc/user-guide/release-notes.md"), - ("docker-optimization", "doc/infrastructure/Docker-Optimization.md"), - ("admin-guide", "doc/admin-guide/admin-guide.md"), - ("android-build", "doc/development/android/android-build.md"), - ("backend-dev", "doc/development/backend/Backend-Development.md"), - ("postgres-setup", "doc/development/backend/postgres_setup.md"), - ("frontend-dev", "doc/development/frontend/Frontend-Development.md"), - ("deployment", "doc/infrastructure/Deployment.md"), - ("risk-radar", "doc/features/risk-radar.md"), - ("navigation", "doc/features/navigation.md"), - ("index", "doc/features/index.md"), - ("md-to-confluence", "scripts/md_to_confluence.py") - ], - "de-ch": [ - ("readme", "README_de.md"), - ("user-guide", "doc/user-guide/user-guide_de.md"), - ("faq", "doc/user-guide/faq_de.md"), - ("admin-guide", "doc/admin-guide/admin-guide_de.md"), - ("risk-radar", "doc/features/risk-radar_de.md"), - ("navigation", "doc/features/navigation_de.md"), - ("index", "doc/features/index_de.md"), - ("md-to-confluence", "scripts/md_to_confluence.py") - ] +# Directories to scan for markdown files +SCAN_DIRS = ["doc", "scripts", "backend", "frontend"] + +# Root files to always include +ROOT_FILES = { + "en": ["README.md", "CONTRIBUTING.md", "ROADMAP.md"], + "de-ch": ["README_de.md"] +} + +# Specific manual mappings to keep for backwards compatibility or special IDs +# Maps short ID to full path +MANUAL_MAPPINGS = { + "en": { + "readme": "README.md", + "user-guide": "doc/user-guide/user-guide.md", + "faq": "doc/user-guide/faq.md", + "release-notes": "doc/user-guide/release-notes.md", + "docker-optimization": "doc/infrastructure/Docker-Optimization.md", + "admin-guide": "doc/admin-guide/admin-guide.md", + "android-build": "doc/development/android/android-build.md", + "backend-dev": "doc/development/backend/Backend-Development.md", + "postgres-setup": "doc/development/backend/postgres_setup.md", + "frontend-dev": "doc/development/frontend/Frontend-Development.md", + "deployment": "doc/infrastructure/Deployment.md", + "risk-radar": "doc/features/risk-radar.md", + "navigation": "doc/features/navigation.md", + "index": "doc/features/index.md", + "registration-workflows": "doc/knowledge/architecture/workflows/registration-workflows.md", + "task-workflows": "doc/knowledge/architecture/workflows/task-workflows.md", + "use-cases": "doc/knowledge/architecture/workflows/use-cases.md", + "diagram-tool-comparison": "doc/knowledge/architecture/workflows/diagram-tool-comparison.md", + "developer-onboarding": "doc/knowledge/architecture/developer-onboarding.md" + }, + "de-ch": { + "readme": "README_de.md", + "user-guide": "doc/user-guide/user-guide_de.md", + "faq": "doc/user-guide/faq_de.md", + "admin-guide": "doc/admin-guide/admin-guide_de.md", + "risk-radar": "doc/features/risk-radar_de.md", + "navigation": "doc/features/navigation_de.md", + "index": "doc/features/index_de.md" + } } + OUTPUT_DIR = "frontend/public/assets/help" -def convert_md_to_html(md_path): - if not os.path.exists(md_path): - print(f"Warning: {md_path} not found.") - return None - with open(md_path, 'r', encoding='utf-8') as f: - content = f.read() +def discover_markdown_files(lang): + """Recursively find all .md files in SCAN_DIRS.""" + discovered = [] - # Simple check for python files to wrap in code block - if md_path.endswith('.py'): - content = f"```python\n{content}\n```" - - html = markdown.markdown(content, extensions=['extra', 'toc', 'fenced_code']) - return html + # Root files + for f in ROOT_FILES.get(lang, []): + if os.path.exists(f): + discovered.append(f) + + # Scan directories + for doc_dir in SCAN_DIRS: + if not os.path.exists(doc_dir): + continue + for root, _, filenames in os.walk(doc_dir): + for filename in filenames: + if filename.endswith('.md'): + path = os.path.join(root, filename).replace('\\', '/') + discovered.append(path) + return discovered def main(): for lang in LANGUAGES: print(f"Processing language: {lang}") - help_data = {} - for page_id, path in SOURCE_FILES.get(lang, []): - print(f" Converting {path}...") - html_content = convert_md_to_html(path) - if html_content: - help_data[page_id] = html_content + # Map short ID to path + id_to_path = {} + + # 1. Start with manual mappings + for page_id, path in MANUAL_MAPPINGS.get(lang, {}).items(): + if os.path.exists(path): + id_to_path[page_id] = path + + # 2. Add discovered files + discovered_paths = discover_markdown_files(lang) + print(f" Discovered {len(discovered_paths)} files.") + for path in discovered_paths: + # Key: Filename without extension (short ID) + short_id = os.path.splitext(os.path.basename(path))[0] + + # Only if not already exists (manual mappings have priority) + if short_id not in id_to_path: + id_to_path[short_id] = path + + # Also lowercase version + if short_id.lower() not in id_to_path: + id_to_path[short_id.lower()] = path os.makedirs(OUTPUT_DIR, exist_ok=True) - output_file = os.path.join(OUTPUT_DIR, f"help-data-{lang}.json") + output_file = os.path.join(OUTPUT_DIR, f"help-map-{lang}.json") with open(output_file, 'w', encoding='utf-8') as f: - json.dump(help_data, f, ensure_ascii=False, indent=2) - print(f"Successfully generated {output_file}") + json.dump(id_to_path, f, ensure_ascii=False, indent=2) + print(f"Successfully generated {output_file} with {len(id_to_path)} entries.") if __name__ == "__main__": main()
          {{ 'INTELLIGENCE.RELATIONSHIPS.SOURCE' | translate }}{{ rel.sourceTitle }} + @if (isTaskReference(rel.sourceTitle)) { + {{ rel.sourceTitle }} + } @else { + {{ rel.sourceTitle }} + } + {{ 'INTELLIGENCE.RELATIONSHIPS.TYPE' | translate }} {{ 'INTELLIGENCE.RELATIONSHIPS.TARGET' | translate }}{{ rel.targetTitle }} + @if (isTaskReference(rel.targetTitle)) { + {{ rel.targetTitle }} + } @else { + {{ rel.targetTitle }} + } +