Skip to content

feat(review): integrate OAuth, presets and verified agent handoffs - #37

Merged
m-szymanska merged 46 commits into
mainfrom
feat/ss-effort-none
Oct 5, 2026
Merged

m-szymanska merged 46 commits into
mainfrom
feat/ss-effort-none

Conversation

@div0-space

@div0-space div0-space commented Sep 16, 2026 •

Copy link
Copy Markdown
Member

Integrates the existing OAuth, annotation, transcript-source, preset and agent stack into main, with the review fixes needed to use narrated walkthroughs as coding-agent handoffs.

The exported TODO/ZIP preserves the complete timestamped source, later scope limits, reviewer decisions and notes alongside model proposals. Human edits and annotations survive reload; manual captures retain their images across server restart and portable exports. xAI account setup works without a pasted key, auxiliary credentials follow their actual destination, and repeated agent/tool turns keep trusted instructions through stateless history.

Unexpected provider/tool exceptions stay in server logs rather than crossing the SSE, model-tool or non-streaming HTTP boundary; explicit configuration and input-validation messages remain readable.

The stack from #32–36 is retained: #32/#33/#34/#36 are ancestors, while the remaining #35 commits have matching cherry-pick patches. #29/#30/#31 were integrated separately with their own required checks. The earlier feature PRs can be closed as superseded after this integration lands.

The development lockfile also updates PyJWT, urllib3 and virtualenv to patched releases. Semgrep 1.179.0 is aligned between the development floor and repository hook; the local ruleset and fail-closed gates are retained.

Validation:

  • Full make verify on Sztudio: lint, format, mypy, security/secrets, coverage floor, package build and isolated-wheel rendering.
  • Real Chromium smoke and native TODO/JSON/ZIP downloads, including annotations, manual evidence and every packaged image reference.
  • Real xAI OAuth + STT/LLM/VLM on a 93-second Polish narrated recording; human-first analysis, review save/reload, two agent turns and an applied edit with the exact user request preserved. Longer recordings and live Anthropic/TTS fallback were not exercised in this smoke.

div0-space and others added 30 commits September 9, 2026 20:42
…_json

The file transcription path (review, transcribe, every chunk of a long
recording) hardcoded response_format=verbose_json. OpenAI's gpt-transcribe /
gpt-4o-transcribe family answers HTTP 400 (param=response_format,
code=unsupported_value), which killed a 12-minute review at chunk 1/32 with
"Speech-to-text failed (HTTP 400)".

- retry that one request with json when the 400 names response_format
  (OpenAI envelope or flattened message); any other 400 still raises
- remember the refusal per (endpoint, model) for the process, so a chunked
  run pays the rejected request once, not once per chunk
- json carries no segments: the existing synthetic-segment path marks the
  timeline as synthetic; whisper-family models keep verbose_json and real
  segment timing
- RED-first tests: fallback, memory per endpoint+model, unrelated 400 not
  swallowed, flat error body, verbose_json kept when accepted
- live check: 20 s clip through `screenscribe transcribe` on a gpt-transcribe
  config delivered a transcript after one rejected request

Gates: ruff, mypy, bandit clean; unit suite 1268 passed, 6 review-app DOM
tests fail in this checkout for an environment reason (they pass on a clean
worktree with this diff applied).

Authored-By: claude <agents@vetcoders.io>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…clients, gpt-transcribe model table

- providers/xai.py: POST /v1/stt (words → real segments), POST /v1/tts, GET /v1/tts/voices (docs.x.ai 2026-09-10)
- stt_stream.py: StreamingSttClient over websockets; LibraxisStreamClient (session.start, u64-be seq + PCM16LE, flush/end) and XaiStreamClient (interim_results, Finalize/audio.done)
- transcribe.py: gpt-transcribe*/gpt-4o-transcribe* request json directly; whisper keeps verbose_json + 400 fallback; api.x.ai host routes to providers.xai (incl. chunked)
- config.py: provider_preset("xai"), tts_*/stt_live_endpoint fields + SCREENSCRIBE_* env, validate() knows api.x.ai; account-bearer hooks (Lane B) share this file
- cli.py: screenscribe tts, screenscribe transcribe --live, setup option xAI; auth subcommand mount (Lane B)
- 52 new unit tests, no network (MockTransport, loopback websockets.serve)

Authored-By: claude <agents@vetcoders.io>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…I (Codex flow) and xAI (RFC 8628)

- account_auth/: provider registry, PKCE S256, device_code flows ported from codescribe core/llm/account_auth
- token store ~/.config/screenscribe/accounts.json (0700/0600, atomic), refresh, account_status
- resolve_bearer: explicit key wins; xai account token usable (api:access); openai token identity-only with warning (api.openai.com rejects ChatGPT tokens, codescribe 2026-09-08)
- CLI: screenscribe auth login|status|logout
- NOTICE discloses shipped public client ids
- 29 unit tests against httpx.MockTransport

Authored-By: claude <agents@vetcoders.io>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…pec, take Founder's untracked docs

- docs/plans/PLAN_SS_PROVIDERS_OAUTH_TAFLA_20260910.md with Lane A/B reports
- docs/plans/SS_TAFLA_WEBKIT_HOST_SPEC.md: port spec from dragon vibecrafted-app @449af692
- AGENTS.md, .ai-agents/, docs/plans/* (portal plans 2026-06-05) were untracked in the Founder's tree; taken as-is (trailing whitespace fixed by hook)
- tests/package.json {"type":"commonjs"}: review DOM harness no longer breaks under a parent ESM package.json

Authored-By: claude <agents@vetcoders.io>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- Upgrade locked dependencies, including mypy 2.3.1 and Rich 15.0.0.\n- Align development version metadata and changelog at 0.1.20.dev0.\n- Format the transcription example for the updated Ruff checks.\n- Validated with uv sync --dev, make verify, uv lock --check and uv pip check.

Authored-By: junie <agents@vetcoders.io>
Co-authored-by: Junie <junie@jetbrains.com>
…t pass the pre-flight key gate

- Why: `screenscribe auth login xai` + xai preset with no key reports READY in
  `config --show`, but `review` died at "Validating configuration... API Key
  Error: No API key configured" — validate_models() checked the raw
  api_key/stt/llm/vision fields instead of the per-endpoint accessors that
  already fall back to the account bearer (`_key_or_account_bearer`).
- What: the presence gate resolves get_stt/llm/vision_api_key(); openai stays
  identity-only because that accessor returns "" for api.openai.com. The
  error text now also points at `screenscribe auth login xai`.
- Proof: new regression test (xai preset, empty key, stored account token →
  validate_models passes and sends `Bearer at-xai`); tests/test_validation.py
  28 passed, contracts + review-core 93 passed; ruff check/format clean.

Authored-By: claude <agents@vetcoders.io>
- Why: founder could only push/pop/clear; drawn rects also drifted after layout change.
- What: stable annotation ids, select/move/resize/delete, toolbar color/stroke/fontSize, live overlay resync via getActualImageRect.
- Proof: tests/test_annotation_model.py (ids, hit-test, move/resize, delete/properties, overlay-after-scroll).

Authored-By: cursor <agents@vetcoders.io>
- Why: new select/delete/property labels must go through i18n; demo HTML is generated, not hand-edited.
- What: lightbox anchors in the i18n guard, regenerate site/demo/report.html from render_html_report_pro, append Unreleased changelog.
- Proof: test_i18n_no_hardcoded_dom.py; demo contains data-tool=select and overlayLayoutFromImage.

Authored-By: cursor <agents@vetcoders.io>
…R [w1-02-transcript-sources]

- why: review died at _require_audio_or_exit before the model saw anything,
  so --prompt never reached the model for silent recordings (founder case:
  deaf operator, explanations written on screen)
- what: transcript becomes an abstraction over segment sources — new
  transcript_sources.py (protocol + auto/audio/ocr routing, --no-audio alias,
  registry hook for future .srt source) and frame_ocr.py (frames every
  --frame-interval s via the shared ffmpeg helper, consecutive-dedupe on an
  md5 probe of downscaled gray frames, VLM-OCR through the Responses API
  reusing unified.wire payload mechanics, per-frame-content cache); segments
  come out in the exact STT shape (start/end/text) so semantic prefilter,
  chaining, screenshots and reports run unchanged
- cli.review: --transcript-source/--no-audio/--frame-interval flags; the
  audio gate moved UNDER the per-video source decision (explicit 'audio'
  keeps the readable fail-fast error); STT provider check/model validation
  only for audio-routed videos, vision also when OCR is used
- review_pipeline: per-video source resolution, OCR branch for steps 1-2
  (audio extraction skipped, failure panel mirrors STT path, checkpoint
  semantics preserved); audio-quality validation and the STT
  timeline-coverage guard now run for the audio source only
- proof: pytest tests/test_transcript_sources.py tests/test_frame_ocr.py
  green; full suite 1513 passed, 28 skipped; ruff clean

Authored-By: kimi <agents@vetcoders.io>
(cherry picked from commit f1c5532d44c9bb92f31a55514b12ba6f960b6601)
…t-sources]

- tests/test_transcript_sources.py: normalize/resolve unit coverage, OCR
  routing with mocked VLM (no 'has no audio track', pipeline reaches semantic
  on OCR segments), explicit audio keeps the readable error, --prompt reaches
  OCR + semantic configs, --frame-interval plumbing, flag conflict/invalid
  rejection, --help lists the three flags
- tests/test_frame_ocr.py: interval grid extraction, consecutive dedupe,
  request shape (Responses payload with input_image), --prompt override in
  the OCR prompt, cache hit avoids transport, segment shape with frame-grid
  timestamps clamped to duration, empty-OCR frames skipped
- tests/test_review_empty_state.py: legacy no-audio gate test now pins the
  explicit --transcript-source audio path (auto routes to OCR instead)
- docs: USAGE.md review options table + transcript-source section + updated
  no-audio troubleshooting; README.md key options; CHANGELOG.md Unreleased
- proof: 23 new tests green; full suite 1513 passed, 28 skipped
  (baseline 1490); ruff check + format clean

Authored-By: kimi <agents@vetcoders.io>
(cherry picked from commit 5be1649438c30d0442c37f82d757b7f6b9dacd89)
…set-aware keyword loading

Why: Founder asked for --preset (programming, casual, medical, veterinary,
custom) so the same engine serves clinical/veterinary recordings without new
pipeline code.

What:
- new screenscribe/presets package: Preset dataclass, load_preset,
  load_custom_preset, PresetError; YAML definitions for programming
  (historical default, no own dictionary), casual, medical, veterinary
  (finding/observation/risk/followup/other + PL/EN dictionaries, >=15 phrases)
- KeywordsConfig gains extra + active_categories; load priority is now
  --keywords-file > global file > preset dictionary > built-in default
- default load without a preset stays bit-for-bit identical (programming
  preset keeps default_keywords.yaml as the single dictionary source)

Proof: tests/test_presets.py registry + priority tests; full suite green.

Authored-By: kimi <agents@vetcoders.io>
(cherry picked from commit ad841af6798ef3bb8a2776a5b08fbc8bc507de2d)
…through review pipeline

Why: preset categories must reach detection, the JSON report, and the HTML
report instead of the hard-coded six; the preset prompt fragment rides the
existing --prompt channel.

What:
- review --preset flag (programming/casual/medical/veterinary/custom) in one
  compact block in cli.py: resolves the preset, enforces custom requires
  --keywords-file with a readable error, merges the preset prompt fragment
  into analysis_prompt_override, passes the preset to run_review
- semantic_prefilter/_parse_prefilter_response/pois_to_detections accept an
  active category vocabulary; the prefilter prompt category enum is swapped
  for non-default presets; unknown categories still degrade to other
- run_review threads preset_categories into detection and records
  preset {name, categories} in the enhanced JSON report for non-default
  presets only (default report shape unchanged); dry-run counts list preset
  categories when a preset vocabulary is active

Proof: full suite 1509 passed; HTML renderer falls back to raw upper-cased
category names so preset badges render without UI changes.

Authored-By: kimi <agents@vetcoders.io>
(cherry picked from commit 75ab8f736d36b3c1539850af5d26b9865034a0c0)
Why: acceptance requires verifiers for the --preset surface and honest docs
for the new flag.

What:
- tests/test_presets.py (19 tests): preset registry, medical/veterinary
  dictionaries (>=15 phrases, PL+EN), custom from --keywords-file (categories
  from file keys, readable errors), keyword priority with presets, bit-for-bit
  default guarantee, category flow into POIs/detections/JSON/HTML, CLI
  --help and error-path contract
- USAGE.md: --preset row in the review options table, a Presets subsection
  under Detection, a preset example
- README.md: --preset in the review key options
- CHANGELOG.md: Unreleased entry for review --preset

Proof: tests/test_presets.py 19 passed; targeted gate (test_presets +
test_cli_keywords_group + test_keywords_bootstrap) green; ruff check and
format clean.

Authored-By: kimi <agents@vetcoders.io>
(cherry picked from commit c0bc92bab0ab93759ec0de81f897963bfec0b5aa)
…urces

Why: the w1-03-presets cut was built before w1-02-transcript-sources landed;
both touched the same review options block and the run_review signature, so
the second cherry-pick (75ab8f7) conflicted in cli.py (1 hunk) and
review_pipeline.py (2 hunks).

What: resolved every conflict as a union so both features work in one
'review' invocation:
- cli.py: run_review now receives transcript_source + frame_interval AND
  preset=active_preset.
- review_pipeline.py: run_review signature takes transcript_source,
  frame_interval and preset; docstring documents both contracts.
- CHANGELOG.md/USAGE.md: union, HEAD entry first, preset entry after.
Added a combined contract test: --preset veterinary --no-audio passes CLI
validation with mocked OCR/LLM and delivers both transcript_source="ocr"
(frame_interval=5.0) and the veterinary preset to run_review, with the
preset recorded in the JSON report.

Proof: pytest tests/ -m 'not integration': 1538 passed, 0 failed;
ruff check + ruff format --check clean; review --help shows
--transcript-source, --no-audio, --frame-interval and --preset.

Authored-By: kimi <agents@vetcoders.io>
- Why: continue a review conversation with Responses API chaining and tools.
- What: screenscribe/agent — provider routing, SSE contract, tools, JSON seed.
- Proof: donor medical loop rewritten (~400 lines) to the same contracts; tests in the next commit.

Authored-By: grok <agents@vetcoders.io>
(cherry picked from commit 7856f72d6932b095d8c93fcd56473bbc4b05eb47)
- Why: acceptance requires TestClient + fixture verifiers, not only live curl.
- What: tests for SSE contract, chain/seed, egress, tools on the 08.22.27 fixture.
- Proof: uv run pytest tests/test_agent_chat.py tests/test_agent_tools.py tests/test_review_server_agent.py → 28 passed.

Authored-By: grok <agents@vetcoders.io>
(cherry picked from commit 064c7ca2426e6b991101388e5155dee3c4cfa941)
…esponse_id

- Why: UI (w1-05) binds against POST /api/agent/chat(/stream); next review needs the last VLM response_id.
- What: review_server routes, analysis_passes.unified_analysis.response_id, SCREENSCRIBE_AGENT_EGRESS.
- Proof: full suite 1520 passed, 28 skipped; live curl on 08.22.27 returned findings + done.

Authored-By: grok <agents@vetcoders.io>
(cherry picked from commit beb13b3655f0655d9a5450119d7cd2982f650af0)
…onal anthropic extra

- Why: screen recordings are secrets; operators need the deny/allow knob documented.
- What: USAGE + CHANGELOG agent section, optional anthropic extra, lockfile.
- Proof: ruff check/format and bandit -q -r screenscribe -c pyproject.toml exit 0.

Authored-By: grok <agents@vetcoders.io>
(cherry picked from commit 7d98b68e12d2e0b59b6491092c765668bf7ea38f)
- Ship agent_panel.js/css as a separate report surface so W1-01 can keep review_app.js.
- Load the panel only on the review shell (script + style loaders) against the w1-04 SSE contract.
- Prove toggle/persist, SSE tools, offline file mode, and geometry in node vm tests.

Authored-By: cursor <agents@vetcoders.io>
(cherry picked from commit 5598bd15edc7e35a80008707809adcbec045da21)
- Keep panel copy in renderer.py + i18n.js with en/pl parity (offline message names screenscribe serve).
- Expose window.__screenscribeAgentHost so tool_call seek/show_frame jump the player and highlight a finding.
- Extend i18n/token/SRI guards to the new JS/CSS surface.

Authored-By: cursor <agents@vetcoders.io>
(cherry picked from commit b408fd63be8b536f1376c968fb3eaa6c0ef3d365)
- Require ScreenScribeAgentPanel in the review shell script order.
- Record the floating chat in the unreleased changelog.
- Regenerate site/demo/report.html from the product renderer so the sample ships the 『s』 chip.

Authored-By: cursor <agents@vetcoders.io>
(cherry picked from commit 677e361e88713dda36002f4b3861e1de40f13553)
… player

Why: Enter in the textarea inserted a newline, restored positions floated over the video, and error turns left an empty assistant bubble.
What: Enter submits (Shift+Enter keeps a newline, IME composition does not send); overlapping restored coords are discarded and the panel is recomputed beside the player or docked as a side sheet; error text paints the assistant row.
Proof: tests/test_agent_panel.py 12 passed; full suite 1580 passed / 28 skipped; ruff clean; Playwright Chromium screenshots at 1280x800, 1440x900, 1920x1080 with no player/toolbar overlap.

Authored-By: cursor <agents@vetcoders.io>
… the recording

- Why: default SCREENSCRIBE_AGENT_EGRESS=deny marked api.x.ai as external and skipped the same host that already received STT audio, transcript, and VLM frames. Chat then died with "All agent providers were skipped".
- What: infer trust=processor for any provider host matching stt_endpoint, llm_endpoint, or vision_endpoint, and always keep processor under deny. Explicit SCREENSCRIBE_AGENT_PRIMARY_TRUST still wins (external + deny remains the opt-out). Fallback on a foreign host (Anthropic) stays skipped. Docs/CHANGELOG follow.
- Proof: tests/test_agent_chat.py + tests/test_review_server_agent.py cover default xAI kept, foreign fallback skipped, explicit external skipped with a readable message, and /api/agent/chat/stream on default config streams token events. Full suite 1572 passed, 28 skipped, 23 deselected; ruff check/format and bandit clean. Walk-around: 08.22.27 report in-process, egress=deny, primary trust=processor, urllib POST Host 127.0.0.1, events token=1 done=1, first 300 chars of a real xAI answer.

Authored-By: grok <agents@vetcoders.io>
(cherry picked from commit 04a20c0)
…verity, edit_finding, add_finding, propose_review)

- Why: Founder asked to talk to the review agent about findings and have it apply corrections. Chat was read-only (list_findings / get_transcript / seek / show_frame / get_report_summary).
- What: Write tools validate against the loaded report and return a review_patch (or a review_plan from propose_review). They never write report.json — the browser stays the single writer. merge_findings / unmerge_finding return {"unsupported": true} because merge is a client-only fold. System prompt: small edits go straight to a patch; broad requests call propose_review first; never claim an edit is saved. review_finding_state hydrates additive summary_override / category_override.
- Proof: tests/test_agent_review_patch.py covers validation, schemas, SSE tool_result round-trip with mocked provider, and empty API key + stored xAI account bearer. Full suite 1590 passed, 28 skipped, 23 deselected; ruff check/format and bandit clean.

Authored-By: grok <agents@vetcoders.io>
(cherry picked from commit 5d7df95)
…state hydrate test

- Why: W2-02 codes against the patch contract; operators need the write-tool surface documented; additive summary_override / category_override must not break old reports.
- What: USAGE + CHANGELOG note that write tools return a patch (browser saves). tests/test_review_server.py hydrates both new override fields and an older finding without them.
- Proof: test_review_state_exposes_summary_and_category_overrides; full suite 1590 passed, 28 skipped.

Authored-By: grok <agents@vetcoders.io>
(cherry picked from commit aee35aa)
…from the agent

- Why: Founder wants the 『s』 panel to apply the agent's finding edits, but the browser stays the single writer — same Zapisz recenzję path as a human click.
- What: review_app.js exposes applyReviewPatch + saveReview on __screenscribeAgentHost (reuse verdict/severity/notes/manual-mark setters; merge ops stay unsupported). agent_panel.js applies review_patch, renders review_plan checkboxes with Apply/Cancel, blocks file://, shows Retry on 409, and the confirmation line points at Reset review instead of a second undo stack. i18n PL+EN, CHANGELOG, demo regen.
- Proof: tests/test_agent_panel.py + test_f0_js_runtime_smoke.py cover ops, plan card, offline, and 409 Retry; full suite 1609 passed, 28 skipped, 23 deselected; ruff check/format clean. Walk-around: 08.22.27 report, live xAI «zmień finding 3 na high i dopisz notatkę» → severity medium→high, notes saved, reload persisted.

Authored-By: cursor <agents@vetcoders.io>
Why: Founder measurement (2026-09-14, api.libraxis.com/v1/responses, 7
paired prompts) shows reasoning.effort="none" is accepted (HTTP 200,
response.completed, no reasoning events) while "off" ends as
response.failed. Today config validation rejects "none" and silently
falls back to "medium" — exactly the reasoning the user asked to disable.

What: add "none" to LLM_REASONING_EFFORTS (default stays "medium";
"off"/other invalid values still warn and fall back). Every reader of
get_llm_reasoning_effort() passes the value verbatim, so it reaches the
wire as reasoning.effort="none" through both build paths (api_utils
build_llm_request_body, unified wire _build_unified_payload). Docs
(USAGE.md, README.md, config setup template comment) list the full set;
CHANGELOG entry appended.

Proof: pytest tests/ -q -m 'not integration' -> 1613 passed, 28 skipped
(baseline 1609 + 4 new: env none loads without warning, env off warns and
falls back, effort none on both wire paths). ruff check + ruff format
--check + bandit clean.

Authored-By: kimi <agents@vetcoders.io>
(cherry picked from commit 91fe8e04f4dad5e4c173935ed37048268f10b85b)
Copilot AI lite review requested due to automatic review settings September 16, 2026 04:08

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Code review skipped — your organization's remaining monthly code review budget is too low to start another review, so this review was not started.

An organization admin can view or raise the monthly spending cap at claude.ai/admin-settings/claude-code. The cap resets at the start of the next billing period.

Once the cap resets or is raised, reopen this pull request to trigger a review.

@coderabbitai

coderabbitai Bot commented Sep 16, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: ac469c37-6d54-4cce-8228-14cc624176b0
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

Only a minor changelog consistency nit remains; no blocking issues were identified.

Pull request overview

Adds none as a valid LLM reasoning-effort setting while preserving the medium default and fallback behavior.

Changes:

  • Updates configuration validation and templates.
  • Documents the new option.
  • Adds environment and Responses payload coverage.
File summaries
File Summary
USAGE.md Updates configuration documentation.
tests/test_unified_cross_provider_chaining.py Tests unified payload propagation.
tests/test_config_env.py Tests valid and invalid environment values.
tests/test_api_utils.py Verifies none reaches Responses payloads.
screenscribe/config.py Accepts none and updates setup output.
README.md Updates environment documentation.
CHANGELOG.md Records the new option; an older allowed-values reference needs alignment.
Review details

Suppressed comments (1)

CHANGELOG.md:9

  • This entry adds none to the setting, but the earlier unreleased changelog entry at CHANGELOG.md:190 still describes the allowed values as only minimal|low|medium|high. Please update that reference as well so the changelog does not contradict the newly documented configuration contract.
- **Added: `SCREENSCRIBE_LLM_REASONING_EFFORT=none`.** `none` is now a legal
  reasoning-effort value alongside `minimal|low|medium|high`; it turns
  reasoning off on providers that support it (OpenAI Responses, LibraxisAI)
  and is sent to the wire verbatim as `reasoning.effort = "none"`. `medium`
  stays the default, and truly invalid values (e.g. `off`) still warn and
  • Files reviewed: 7/7 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

div0-space and others added 13 commits September 16, 2026 06:31
…drop minimal, add xhigh/max

Why: live probes (2026-09-16) showed no provider supports "minimal" —
OpenAI gpt-5.6-terra rejects it with 400 unsupported_value, xAI grok-4.6
silently aliases it to "low". It only ever lived two days on the stack
base (c3b6174), never tagged, never on main, so there is no one to
deprecate for: remove it outright. Meanwhile main has shipped a
hard-coded reasoning.effort="none" since 68f8f85, and xAI rejects
"none" with a 400 — so the unset default must be resolved per provider
preset instead of one global "medium".

What:
- LLM_REASONING_EFFORTS is now ("none", "low", "medium", "high",
  "xhigh", "max"); "minimal" is invalid like any other unknown value
  (warn + fall back), no deprecation shim.
- New PROVIDER_DEFAULT_REASONING_EFFORTS: xai -> "low" (xAI 400s on
  "none"), libraxis/openai/custom -> "none" (restores main's shipped
  behavior for those providers). get_llm_reasoning_effort() and the
  _normalize_reasoning_effort warning/fallback resolve the default via
  recognized_provider() instead of blindly "medium";
  DEFAULT_LLM_REASONING_EFFORT stays as the last-resort constant.
- The llm_reasoning_effort field defaults to "" (unset) so an explicit
  value always wins and an unset one resolves per provider;
  save_default_config() (the config setup path) writes the resolved
  provider default into config.env explicitly, so a fresh setup never
  starts with a value its provider rejects.
- Docs (USAGE.md, README.md, setup template comment) and CHANGELOG.md
  updated; tests updated and extended (per-preset defaults, invalid-value
  provider fallback, explicit "medium" unchanged, xhigh/max on the wire).

Proof: uv run pytest tests/ -q -m 'not integration' -> 1628 passed,
28 skipped (baseline on branch: 1613 passed); ruff check, ruff format
--check and bandit -r screenscribe all clean.

Authored-By: kimi <agents@vetcoders.io>
(cherry picked from commit f08385acaac55f63b256ef540bdf9add42a900ca)
@m-szymanska m-szymanska changed the title feat(config): accept reasoning effort none feat(review): integrate OAuth, presets and verified agent handoffs Oct 5, 2026
@m-szymanska
m-szymanska changed the base branch from feat/ss-agent-floating to main October 5, 2026 17:32
Comment thread screenscribe/review_server.py Fixed
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.

4 participants