diff --git a/app/admin-annotations.cds b/app/admin-annotations.cds index 66138c72d..6e72f572b 100644 --- a/app/admin-annotations.cds +++ b/app/admin-annotations.cds @@ -967,6 +967,23 @@ annotate AdminService.CodeCheckSpecs with @UI: { } }; +// TutorialGradingContext — tutorial-level grading context persisted at +// publish time and consumed by the challenge grader to ground LLM calls. +// Read-only; the admin facet surfaces the context text for visibility. +// Joined via the `gradingContext` to-one association on the Tutorials projection. +annotate AdminService.TutorialGradingContext with { + context @Common.Label: 'Grading Context' @UI.MultiLineText; +}; + +annotate AdminService.TutorialGradingContext with @UI: { + FieldGroup #GradingContext: { + $Type: 'UI.FieldGroupType', + Data: [ + { Value: context, Label: 'Grading Context' } + ] + } +}; + // AuthorAiRequests — per-tutorial AI-author telemetry (OS variant // generation today; future flows extend). Joined via `aiRequests` // association (PR-3 added the tutorial FK). @@ -1033,6 +1050,8 @@ annotate AdminService.Tutorials with @UI: { Target: 'validationRules/@UI.LineItem' }, { $Type: 'UI.ReferenceFacet', Label: 'Code-Check Specs', ID: 'CodeCheckSpecsFacet', Target: 'codeCheckSpecs/@UI.LineItem' }, + { $Type: 'UI.ReferenceFacet', Label: 'AI Grading Context', ID: 'GradingContextFacet', + Target: 'gradingContext/@UI.FieldGroup#GradingContext' }, { $Type: 'UI.ReferenceFacet', Label: 'AI-Author Requests', ID: 'AiRequestsFacet', Target: 'aiRequests/@UI.LineItem' }, { $Type: 'UI.ReferenceFacet', Label: 'Freshness Reports', ID: 'FreshnessReportsFacet', Target: 'freshnessReports/@UI.PresentationVariant' }, diff --git a/app/admin/joule/webapp/controller/Settings.controller.js b/app/admin/joule/webapp/controller/Settings.controller.js index be08560cf..0f6398ec0 100644 --- a/app/admin/joule/webapp/controller/Settings.controller.js +++ b/app/admin/joule/webapp/controller/Settings.controller.js @@ -26,6 +26,12 @@ sap.ui.define([ // in the view makes the cost trade-off explicit. validateAnswerEnabled: false, codeCheckEnabled: false, + // Grading context flag (#3090). Default false to mirror schema default + // (db/schema.cds). When on, all three AI graders (validate-answer, + // code-check, challenge-grade) read each tutorial's TutorialGradingContext + // row to ground the LLM call with domain-specific context about what + // correct answers look like. No extra token cost beyond what the active graders consume. + gradingContextEnabled: false, // Issue #172 pilot master flag. Default false to mirror the schema // default (db/schema.cds:530). When off, the public /api/ChatConfig // singleton reports branchingEnabled=false and the Learning @@ -108,6 +114,7 @@ sap.ui.define([ embeddingMinScore: data.embeddingMinScore != null ? data.embeddingMinScore : 0.25, validateAnswerEnabled: !!data.validateAnswerEnabled, codeCheckEnabled: !!data.codeCheckEnabled, + gradingContextEnabled: !!data.gradingContextEnabled, branchingEnabled: !!data.branchingEnabled, communityPeersEnabled: !!data.communityPeersEnabled, communityLabelLlmBudgetPerDay: data.communityLabelLlmBudgetPerDay != null ? data.communityLabelLlmBudgetPerDay : 50, @@ -154,6 +161,7 @@ sap.ui.define([ embeddingMinScore: data.embeddingMinScore === "" || data.embeddingMinScore == null ? null : Number(data.embeddingMinScore), validateAnswerEnabled: !!data.validateAnswerEnabled, codeCheckEnabled: !!data.codeCheckEnabled, + gradingContextEnabled: !!data.gradingContextEnabled, branchingEnabled: !!data.branchingEnabled, communityPeersEnabled: !!data.communityPeersEnabled, communityLabelLlmBudgetPerDay: parseInt(data.communityLabelLlmBudgetPerDay, 10) || 50, diff --git a/app/admin/joule/webapp/i18n/i18n.properties b/app/admin/joule/webapp/i18n/i18n.properties index 9cc21f8f7..d2730a2fa 100644 --- a/app/admin/joule/webapp/i18n/i18n.properties +++ b/app/admin/joule/webapp/i18n/i18n.properties @@ -36,6 +36,8 @@ validateAnswerEnabled=Free-text answer grading validateAnswerEnabledHelp=When on, [VALIDATE_N] free-text questions are graded by the LLM. When off, the inline widget shows "Answer checking is temporarily unavailable" and the /api/validate-answer endpoint returns 503. Default off — flipping this on starts consuming AI Core tokens per submission. codeCheckEnabled=AI code-check codeCheckEnabledHelp=When on, [CODECHECK_N] blocks call the LLM grader and the checkCode tool is wired into the chat. When off, the /api/codecheck endpoint returns 503. Default off — flipping this on starts consuming AI Core tokens per submission. +gradingContextEnabled=Grading context enrichment +gradingContextEnabledHelp=When on, each tutorial's stored grading context (published via the content pipeline) is injected into all AI graders (validate-answer, code-check, challenge-grade) as domain-specific guidance about correct answers. No extra AI Core tokens beyond what the active graders already consume. Default off. branchingSection=Tutorial Branching Pilot (issue #172) branchingEnabled=Enable adaptive branching diff --git a/app/admin/joule/webapp/view/Settings.view.xml b/app/admin/joule/webapp/view/Settings.view.xml index 944ab7f88..18ee44e71 100644 --- a/app/admin/joule/webapp/view/Settings.view.xml +++ b/app/admin/joule/webapp/view/Settings.view.xml @@ -79,6 +79,12 @@