Skip to content

feature: deploy to main - #309

Merged
artcc merged 25 commits into
mainfrom
develop
Aug 26, 2026
Merged

feature: deploy to main#309
artcc merged 25 commits into
mainfrom
develop

Conversation

@artcc

@artcc artcc commented Aug 26, 2026

Copy link
Copy Markdown
Owner

No description provided.

arqo123 and others added 25 commits August 19, 2026 08:29
Every lesson of a unit was generated from the same grammar points and
vocabulary sets, with no knowledge of its siblings and with lesson_type
used only as a label. The model had no differentiation signal, so
consecutive lessons of a unit repeated the same explanation, the same
example sentences and the same common mistakes.

Lesson generation now receives two additional signals:

- The lessons already generated for the same unit are condensed into a
  capped summary (titles, types, explanation excerpts, example sentences,
  vocabulary, common traps) and injected as delimited data the new lesson
  must not reuse. The router builds the list from the lessons it already
  loaded for the plan, so no extra query is needed, and keeps it current
  when several lessons of a unit are generated in one request.
- The declared lesson_type selects an instruction block describing what
  the explanation, the exercise mix and the vocabulary of a grammar,
  vocabulary, reading, writing, listening or review lesson must
  emphasise. Unknown types fall back to a generic block, and review
  lessons keep recycling the unit material but with new sentences and
  contexts.

The output JSON schema is unchanged.
The VAD closed an utterance after 0.9-1.3 s of silence, derived from the
CEFR level and hardcoded in ConversationMode. A learner reaching for a
word routinely pauses longer than that, so the turn was submitted while
they were still speaking and the tutor answered half a sentence. Nothing
in Settings could change it, and a level assigned too high made the
window shorter still.

The automatic values now leave more room — 1800 ms for A1/A2, 1500 ms for
B1/B2, 1200 ms for C1/C2, 1500 ms without a level — and learners who need
more can choose 1, 2 or 3 seconds in Settings under Conversation.

The resolution rule lives in lib/conversation-vad.ts: the stored
conversation_speech_pause wins when set, 0 means automatic. The value is
persisted on the user, validated against the offered set, and read when
the VAD is created, so a change applies to the next session.

The setting is a comfort preference, not a quota, so a subscription
downgrade leaves it untouched.
The placement quiz offered four options and no way out, so a learner who
did not know an item had to guess. With four options a guess is right
about a quarter of the time, the scoring cannot tell it from knowledge,
and the resulting level is too high — which then feeds the study plan,
lesson difficulty and the conversation end-of-speech window.

Each question now offers an explicit "I don't know" next to the options,
kept visually apart so it does not read as a fifth answer. It is
submitted as its own signal, `dont_know: true`, so the evaluator can
separate a declared gap from a wrong answer:

- A declared gap never counts as correct, whatever else the client sends.
- A skill is a weakness when the learner declared a gap on at least half
  of its questions, even if the remaining answers keep its score above
  the usual threshold.
- The legacy LLM evaluation prompt is told that a declared gap is
  reliable evidence the item is above the learner, while a wrong answer
  can still show partial knowledge.

For the adaptive question selection a declared gap behaves exactly like a
wrong answer. Removing the guess is the fix; penalising the honest answer
on top of it would only trade one misplacement for another.
- Add `ANTHROPIC_MAX_TOKENS` to dev and example env files with an 8192 default
- Use the configurable Anthropic output budget in the LLM adapter
- Raise `LLMResponseError` when Anthropic responses stop due to `max_tokens`
- Update tests to cover the new output limit and truncation handling
- Bump version references, changelog, and architecture docs to 1.8.45
The "I don't know" action was 11px text-fl-muted-4 with no vertical
padding: 2.7:1 against the light-theme card and a touch target only as
tall as the glyphs. It is now 12px text-fl-muted-1 with vertical
padding, 5.5:1 light and 6.6:1 dark. It stays borderless and uppercase,
so it still reads as secondary to the four answer options.
The four options sat in one non-wrapping flex row, so the longer German,
Spanish and Russian labels overflowed their buttons below about 375 px.
They now use a two-column grid that becomes four columns from the sm
breakpoint up.
Collect the unit vocabulary from every previous lesson instead of only
the six that get a detailed summary. Scope the minimum share of
grammar-targeting exercises to the lesson type, so a vocabulary lesson
can ask for lexical exercises without contradicting the strict
constraints. Stop claiming the student worked through the listed
lessons, since a sibling can still be pending. Skip explanation blocks
that are not lists, which the lesson schema still allows.
Differentiate lessons within a curriculum unit
…indow

Make the voice end-of-turn pause longer and configurable
- Add `speaking` to the lesson type union and prompt guidance
- Define speaking-specific lesson instructions and grammar ratio
- Extend tests to cover speaking prompts and curriculum policy alignment
- Update curriculum, architecture, testing, and changelog docs with new lesson and test counts
- Refresh frontend layout formatting changes from the staged diff
Let learners decline a placement question instead of guessing
- Require an explicit study_plan_id for STT uploads and validate ownership server-side
- Derive STT language from the persisted study plan and make STT service language mandatory
- Route flashcard generation and review to the owning study plan instead of active client language
- Update voice recording UIs to submit study-plan context and serialize pending reviews
- Forward request cancellation through the STT proxy and warmup calls
- Refresh documentation, changelog, and test counts to reflect the new behavior
- Gate admin overview subscription metrics and past-due alerts on the Stripe config flag
- Hide admin user detail subscription status, subscription tab, and override controls when Stripe is disabled
- Ignore subscription filters in the admin user list when Stripe is disabled and adjust table layout accordingly
- Add tests for Stripe-enabled and Stripe-disabled admin visibility and stale query handling
- Update architecture, testing, and changelog documentation for the new admin subscription behavior
feature: hidden settings when stripe is disabled
@artcc
artcc merged commit d2d16c6 into main Aug 26, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants