diff --git a/.s2s/BACKLOG.md b/.s2s/BACKLOG.md index fa32efba..1e9a46bb 100644 --- a/.s2s/BACKLOG.md +++ b/.s2s/BACKLOG.md @@ -664,6 +664,62 @@ As a result, `conversation.j2` and `TemplateRenderer.render_conversation()` are --- +### DEBT-017: Consolidate namespace-resolution logic in vektra-learn + +**Status**: planned | **Priority**: low | **Created**: 2026-04-21 +**Origin**: CodeRabbit review on PR #66 (v0.5.0), `vektra-learn/src/vektra_learn/api.py:498-512` + +**Context**: `_resolve_namespace_from_token()` (added for WI-1 in v0.5.0) re-implements the same fallback chain that `course_query` does inline around lines 663-673 and 694-695: read `course_id` from the JWT, fall back to `namespace` claim, default to `course_id`. The learn-query path additionally performs an enrollment lookup when `VEKTRA_LEARN_REQUIRE_ENROLLMENT=true` which is interleaved with the plain resolution, so a naive extraction would miss that branch. + +**Proposed approach**: extend `_resolve_namespace_from_token` to return a `(course_id, namespace, namespace_source)` tuple, then refactor `course_query` to call it for the non-enrollment branch while keeping the enrollment path inline. Both endpoints stay in lockstep if the JWT schema evolves (e.g., a new claim is added). + +**Acceptance criteria**: +- [ ] Single helper used by both `get_conversation_turns` and `course_query` (non-enrollment branch) +- [ ] Enrollment-required branch unchanged +- [ ] Tests cover both call sites against a shared fixture set +- [ ] No behaviour change to error codes (ERR-LEARN-003 on missing course_id) + +--- + +### DEBT-018: Scope widget `--vektra-primary` override and dedupe style node + +**Status**: planned | **Priority**: low | **Created**: 2026-04-21 +**Origin**: CodeRabbit review on PR #66 (v0.5.0), `vektra-learn/widget/src/chat-ui.js:138-144` + +**Context**: `ChatUI._injectStyles()` appends a new `