fix(use-case-compiler): compile questions from MCs, not hardcoded
Build + Deploy / build-admin-compliance (push) Successful in 14s
Build + Deploy / build-developer-portal (push) Successful in 10s
Build + Deploy / build-tts (push) Successful in 11s
Build + Deploy / build-document-crawler (push) Successful in 20s
Build + Deploy / build-dsms-gateway (push) Successful in 13s
Build + Deploy / build-dsms-node (push) Successful in 13s
CI / branch-name (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / loc-budget (push) Failing after 18s
Build + Deploy / trigger-orca (push) Successful in 2m26s
Build + Deploy / build-backend-compliance (push) Successful in 13s
Build + Deploy / build-ai-sdk (push) Successful in 11s
CI / secret-scan (push) Has been skipped
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / nodejs-build (push) Successful in 2m50s
CI / dep-audit (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / test-go (push) Successful in 43s
CI / test-python-backend (push) Successful in 38s
CI / test-python-document-crawler (push) Successful in 26s
CI / test-python-dsms-gateway (push) Successful in 25s
CI / validate-canonical-controls (push) Successful in 16s

Changes the compile flow to always query Master Controls from DB first:
1. doc_check_controls → Mode A (deterministic)
2. LLM generation via Ollama/Claude → Mode B
3. Derive from MC name → fallback
4. Template hardcoded questions → absolute fallback

Previously, templates with pre-defined questions just returned those
without ever hitting the DB. Now MC-compiled questions take priority
and template questions fill gaps for uncovered topics.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-05-12 17:34:41 +02:00
parent 7be34552bb
commit e785b6d695
2 changed files with 123 additions and 82 deletions
@@ -16,17 +16,16 @@ type UseCaseHandler struct {
store *usecase.Store
compiler *usecase.Compiler
gapDetector *usecase.GapDetector
llmGen *usecase.LLMQuestionGenerator
}
// NewUseCaseHandler creates a new UseCaseHandler.
func NewUseCaseHandler(pool *pgxpool.Pool, registry *llm.ProviderRegistry) *UseCaseHandler {
store := usecase.NewStore(pool)
llmGen := usecase.NewLLMQuestionGenerator(registry)
return &UseCaseHandler{
store: store,
compiler: usecase.NewCompiler(store),
compiler: usecase.NewCompiler(store, llmGen),
gapDetector: usecase.NewGapDetector(store),
llmGen: usecase.NewLLMQuestionGenerator(registry),
}
}
@@ -59,12 +58,11 @@ func (h *UseCaseHandler) GetTemplate(c *gin.Context) {
// Compile generates questions from MC filters ad-hoc.
// POST /sdk/v1/use-case/compile
// Optional: "mode": "llm" to use LLM-based generation
// Uses the full pipeline: doc_check → LLM → deterministic fallback
func (h *UseCaseHandler) Compile(c *gin.Context) {
var req struct {
MCFilters []string `json:"mc_filters" binding:"required"`
Regulations []string `json:"regulations"`
Mode string `json:"mode"` // "deterministic" (default) or "llm"
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
@@ -77,29 +75,13 @@ func (h *UseCaseHandler) Compile(c *gin.Context) {
Regulations: req.Regulations,
}
if req.Mode == "llm" && h.llmGen != nil {
// Fetch MCs first, then generate via LLM
mcs, err := h.store.FetchMCsByFilters(req.MCFilters)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
questions, err := h.llmGen.GenerateQuestions(mcs, req.Regulations)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"questions": questions, "total": len(questions), "mode": "llm"})
return
}
questions, err := h.compiler.Compile(tmpl)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"questions": questions, "total": len(questions), "mode": "deterministic"})
c.JSON(http.StatusOK, gin.H{"questions": questions, "total": len(questions)})
}
// CreateAudit starts a new audit from a template.