Skip to content

feat: migrate Astra to Responses with GPT-6.1 Sol (#582) - #801

Merged
thomasluizon merged 3 commits into
redesign/mainfrom
thomasluizon/ticket-582-astra-model
Oct 19, 2026
Merged

thomasluizon merged 3 commits into
redesign/mainfrom
thomasluizon/ticket-582-astra-model

Conversation

@thomasluizon

@thomasluizon thomasluizon commented Oct 19, 2026 •

Copy link
Copy Markdown
Owner

Refs thomasluizon/orbit-tickets#582. Base: redesign/main.

Astra cannot use GPT-6.1 Sol function tools through Chat Completions. This migrates chat, streaming, JSON and text calls to /v1/responses, with gpt-6.1-sol at low reasoning as primary and gpt-6-luna at low reasoning for subtasks. Model overrides remain configuration.

Intended approach and delivered layers

  • Layer 1: AiCompletionClient.cs centralizes Responses options, tier selection, compatible temperature/reasoning parameters, JSON format, retries and completion cancellation. AiIntentService.cs maps text deltas and terminal response events, keeps every output item including encrypted reasoning for tool continuations, and sends tool results with their call_id. Usage still goes to the existing recorder once per model round. Incomplete tool calls, failed responses and streams without a terminal event fail rather than executing partial arguments.
  • Layer 2: the deadline fake exposes a stream like an HTTP network response. A deterministic cancellation-during-buffering regression reproduces the disposed-memory-stream cleanup failure before this correction. The JSON deadline case repeats 200 times, also verified under coverage.
  • The per-user cache-key portion of layer 3 is included: prompt_cache_key uses the same authenticated user identifier as user, including continuation rounds. Tests cover stable keys, different users, model rollback and pricing coverage.
  • AiSettings.cs and appsettings.json carry the defaults and new prices. Existing rollback prices remain. Test HTTP fixtures now serialize the installed SDK's Responses models. The suppression allowlist only declares the two required OPENAI001 sites: this installed SDK marks its typed Responses surface experimental.

Remaining for the next round on this branch: strict schema conversion and enum audit (thomasluizon/orbit-tickets#583), input reductions (thomasluizon/orbit-tickets#16), and PostHog events (thomasluizon/orbit-tickets#584). This layered delivery does not close #582. Functions explicitly retain strict: false to preserve existing optional-field behavior during the transport migration. Making all fields nullable and required now would change update_habit: explicit null currently clears description, emoji, recurrence, time and end date, whereas absence preserves them. That needs the separate schema and handler audit ordered in layer 3.

The migration, model configuration, prices, cache key and fake-stream correction also apply semantically to main. This PR targets and tests redesign/main; main predates its whole-completion deadline plumbing, so a backport needs that dependency. The generated OpenAPI documents were regenerated and have no diff. No client DTO or quota changes.

Live interface evidence

Verified on 2026-10-19 against official OpenAI documentation and the account's live API:

  • GPT-6.1 Sol requires Responses for function tools and accepts reasoning.effort: low. Standard prices per million tokens: input $2.00, cached input $0.10, output $10.00.
  • GPT-6 Luna is the configured subtask model. Standard prices: input $0.10, cached input $0.01, output $0.50. Migration guidance requires omitting temperature with non-none reasoning.
  • Live GET /v1/models returned both exact IDs. Complete individual entries, with their original field names, are below. Re-derive using curl --fail https://api.openai.com/v1/models -H "Authorization: Bearer $OPENAI_API_KEY" and select those IDs from data.
[
  {
    "id": "gpt-6.1-sol",
    "object": "model",
    "created": 1790552874,
    "owned_by": "system",
    "shutdown_date": null
  },
  {
    "id": "gpt-6-luna",
    "object": "model",
    "created": 1789406102,
    "owned_by": "system",
    "shutdown_date": null
  }
]

The installed NuGet package is OpenAI 2.14.0, repository commit 2e77b08828145f658ec04e49aec87abb1543c553 from its own openai.nuspec. I decompiled the installed DLL, rather than assuming SDK names. Reproduce with ilspycmd -p -o /tmp/openai-installed "$HOME/.nuget/packages/openai/2.14.0/lib/net10.0/OpenAI.dll" and inspect these types:

SDK type/member Confirmed wire field or behavior
ResponsesClient.CreateResponseAsync / CreateResponseStreamingAsync /responses; streaming requires StreamingEnabled = true
CreateResponseOptions.Model, InputItems, Tools model, input, tools
CreateResponseOptions.ReasoningOptions and ResponseReasoningOptions.ReasoningEffortLevel reasoning.effort; ResponseReasoningEffortLevel.Low serializes as low
CreateResponseOptions.PromptCacheKey, EndUserId, StoredOutputEnabled, IncludedProperties prompt_cache_key, user, store, include
ResponseTextOptions.TextFormat / ResponseTextFormat.CreateJsonObjectFormat() text.format.type: json_object
ResponseTool.CreateFunctionTool(name, parameters, strictModeEnabled, description) Flat Responses function definition; strict is a typed argument
ResponseResult.OutputItems, Status, IncompleteStatusDetails, Usage, GetOutputText() output, status, incomplete_details, usage, combined output text
FunctionCallResponseItem.CallId, FunctionName, FunctionArguments call_id, name, JSON string arguments
ResponseItem.CreateFunctionCallOutputItem type: function_call_output, call_id, output
ReasoningResponseItem.EncryptedContent encrypted_content, preserved in the next round with store: false
StreamingResponseOutputTextDeltaUpdate, StreamingResponseCompletedUpdate, StreamingResponseIncompleteUpdate, StreamingResponseFailedUpdate, StreamingResponseErrorUpdate response.output_text.delta, response.completed, response.incomplete, response.failed, error
ResponseTokenUsage / ResponseInputTokenUsageDetails input_tokens, output_tokens, total_tokens, input_tokens_details.cached_tokens

System.ClientModel 1.15.0 was also decompiled. Its HttpClientPipelineTransport.HttpClientTransportResponse.Dispose re-buffers a MemoryStream; cancellation disposes the stream while buffering. That explains why the original fake could replace cancellation with ObjectDisposedException during cleanup. The network-shaped fake avoids that memory-only cleanup path, while still using the real SDK retry policy and cancellation.

A live streaming request using the primary model, low reasoning, store: false, include: ["reasoning.encrypted_content"] and a record_run(date) function returned HTTP 200 and a function call. The complete terminal response follows, with encrypted reasoning content redacted. This request used strict: false; strict acceptance remains part of layer 3.

{
  "id": "resp_092d111b3dba36b1016ad689f3ce4c87d28c5fd5d48ddf7a04",
  "object": "response",
  "created_at": 1792444915,
  "status": "completed",
  "access_programs": null,
  "background": false,
  "completed_at": 1792444917,
  "error": null,
  "frequency_penalty": 0.0,
  "incomplete_details": null,
  "instructions": null,
  "max_output_tokens": null,
  "max_tool_calls": null,
  "model": "gpt-6.1-sol",
  "moderation": null,
  "output": [
    {
      "id": "fc_092d111b3dba36b1016ad689f551dc87d2abab792fef0a7d96",
      "type": "function_call",
      "status": "completed",
      "arguments": "{\"date\":\"2026-10-19\"}",
      "call_id": "call_W1rQEjEq2zQlehoMkvH6rzHo",
      "name": "record_run"
    }
  ],
  "parallel_tool_calls": true,
  "presence_penalty": 0.0,
  "previous_response_id": null,
  "prompt_cache_key": null,
  "prompt_cache_retention": "24h",
  "reasoning": {
    "context": "all_turns",
    "effort": "low",
    "mode": "standard",
    "summary": null
  },
  "safety_identifier": null,
  "service_tier": "default",
  "store": false,
  "temperature": 1.0,
  "text": {
    "format": {
      "type": "text"
    },
    "verbosity": "medium"
  },
  "tool_choice": "auto",
  "tool_usage": {
    "image_gen": {
      "input_tokens": 0,
      "input_tokens_details": {
        "image_tokens": 0,
        "text_tokens": 0
      },
      "output_tokens": 0,
      "output_tokens_details": {
        "image_tokens": 0,
        "text_tokens": 0
      },
      "total_tokens": 0
    },
    "web_search": {
      "num_requests": 0
    }
  },
  "tools": [
    {
      "type": "function",
      "description": "Record a completed run.",
      "name": "record_run",
      "output_schema": null,
      "parameters": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string"
          }
        },
        "required": [
          "date"
        ],
        "additionalProperties": false
      },
      "strict": false
    }
  ],
  "top_logprobs": 0,
  "top_p": 0.98,
  "truncation": "disabled",
  "usage": {
    "input_tokens": 58,
    "input_tokens_details": {
      "cache_write_tokens": 0,
      "cached_tokens": 0
    },
    "output_tokens": 23,
    "output_tokens_details": {
      "reasoning_tokens": 0
    },
    "total_tokens": 81
  },
  "user": null,
  "metadata": {}
}

The actual migrated AiCompletionClient + AiIntentService were then invoked directly, without a server or database: streamed record_run, supplied its synthetic success result, and streamed the final confirmation. Both rounds succeeded and recorded gpt-6.1-sol usage. A real Luna JSON call returned {"value":"ok"} and recorded gpt-6-luna. Repeating the same tool/continuation exercise with only AI:Model = gpt-4.1-mini succeeded through Responses with temperature restored.

Before and after measurements

Live measurements on 2026-10-19. These are first model rounds, not full application turns or production-account acceptance. The input used the repository's real static/dynamic prompt and tool schemas, with a synthetic habit index (Beber água, Ler 10 minutos, Academia, Run) and local date 2026-10-19. Ask was disabled. The real keywordless declaration set is still 44 tools; no input reduction is claimed. No application writes were executed.

Old: gpt-4.1-mini, Chat Completions, temperature 0.1. New: gpt-6.1-sol, Responses, reasoning low. One sample per case/model, up to three concurrent calls, mixed warm/cold caches. TTFT measures the first text or function-argument delta; total ends at the first terminal response. Costs below use the existing AiUsageDaily formula and configured prices, not invoice reconciliation. GPT-6 responses also expose cache-write tokens; their extra write premium is not represented by the existing recorder, so these costs understate that premium. The cost schema/computation is explicitly outside this transport layer. Follow-up filing through tools/create-ticket.mjs was unavailable because that adapter is absent in this repository.

Case Request
T obrigado
S1 log my run today
S2 create a habit every wednesday and sunday: Yoga
M1 Create a daily swimming habit and a daily walking habit.
M2 Crie um hábito diário de yoga e uma meta de fazer yoga 30 vezes até dezembro.
B Registre água e leitura nos últimos 7 dias, menos ontem.
O1 Crie uma meta de ler 12 livros até dezembro e ligue ao hábito de leitura.
O2 Registre água, leitura e meditação nos últimos 7 dias, menos ontem.
O3 Divida a academia em aquecimento, treino e alongamento.
O4 Crie uma tag Saúde e atribua aos hábitos de água e academia.
O5 Quais são meus hábitos de hoje e quantos são?
P crie um hábito de Yoga toda quarta e domingo

O1-O3 reproduce the quoted requests in thomasluizon/orbit-tickets#1568. O4 reconstructs its described tag request; O5 is an explicit probe for its grounding symptom. That ticket does not contain six verbatim requests, so an exact six-request owner replay remains pending. P checks the weekday intent in pt-BR.

Case Model TTFT s Total s Input / cached / output Cost USD First-round calls
T gpt-4.1-mini 1.412 1.594 4921 / 3968 / 18 0.000807 prose only
T gpt-6.1-sol 1.837 2.168 4920 / 0 / 13 0.009970 prose only
S1 gpt-4.1-mini 1.411 1.648 11801 / 0 / 37 0.004780 log_habit x1
S1 gpt-6.1-sol 2.169 2.938 11804 / 0 / 50 0.024108 log_habit x1
S2 gpt-4.1-mini 0.981 1.268 11807 / 11648 / 38 0.001289 create_habit x1
S2 gpt-6.1-sol 1.498 2.092 11810 / 11793 / 42 0.001633 create_habit x1
M1 gpt-4.1-mini 1.136 1.259 11808 / 11648 / 76 0.001350 create_habit x2
M1 gpt-6.1-sol 1.528 2.408 11811 / 11793 / 60 0.001815 bulk_create_habits x1
M2 gpt-4.1-mini 1.360 1.472 11816 / 11648 / 85 0.001368 create_habit x1, create_goal x1
M2 gpt-6.1-sol 1.431 1.931 11819 / 11793 / 35 0.001581 create_habit x1
B gpt-4.1-mini 3.874 4.208 11811 / 11648 / 508 0.002043 bulk_log_habits x12
B gpt-6.1-sol 1.522 2.664 11814 / 11793 / 76 0.001981 bulk_log_habits x1
O1 gpt-4.1-mini 0.876 0.960 11816 / 11648 / 17 0.001259 query_habits x1
O1 gpt-6.1-sol 1.765 2.718 11819 / 11793 / 66 0.001891 create_goal x1
O2 gpt-4.1-mini 4.233 4.582 11814 / 11648 / 580 0.002159 bulk_log_habits x18
O2 gpt-6.1-sol 9.607 9.813 11817 / 11793 / 523 0.006457 bulk_log_habits x6
O3 gpt-4.1-mini 0.901 1.455 11810 / 11648 / 107 0.001401 update_habit x1
O3 gpt-6.1-sol 1.580 2.128 11813 / 11793 / 39 0.001609 prose only
O4 gpt-4.1-mini 1.447 1.557 11812 / 11648 / 126 0.001432 create_tag x1, assign_tags x2
O4 gpt-6.1-sol 1.566 1.999 11815 / 11793 / 27 0.001493 create_tag x1
O5 gpt-4.1-mini 0.856 1.017 11809 / 11648 / 16 0.001255 query_habits x1
O5 gpt-6.1-sol 2.449 2.780 11812 / 11793 / 20 0.001417 query_habits x1
P gpt-4.1-mini 0.822 0.947 11807 / 11648 / 38 0.001289 create_habit x1
P gpt-6.1-sol 1.761 2.431 11810 / 11793 / 42 0.001633 create_habit x1

First-round correctness observations:

Cases Before After
T Correct Portuguese prose, no tools Correct Portuguese prose, no tools
S1 Correct existing run ID; date uses tool's today default Correct existing run ID and explicit local date
S2, P Both weekdays but frequency_unit: Week, contrary to the exact-weekday prompt rule Both weekdays with Day and quantity 1
M1 Two daily create calls with the requested names One bulk-create call containing both requested daily habits
M2 Habit and goal calls emitted together Habit first; goal requires continuation, not scored complete
B Twelve calls include the wrong starting day and omit today One correct first-date filtered call; remaining dates require continuation, not scored complete
O1 Queries reading habit before creation Creates the goal with the existing reading habit ID inline
O2 Incorrectly logs Academia as meditation and uses the wrong date range Six correct dates and the two existing matching IDs; asking about missing meditation still requires continuation
O3 Invents update_habit.sub_habits, which is absent from that schema Asks checklist versus independently tracked stages; no duplicate Academia create
O4 Tag creation and two assignments to existing IDs Tag first; assignments require continuation, not scored complete
O5 Correct current-day query Correct current-day query; final factual prose requires tool results

These results do not prove whole-turn parity, correct previews, successful approvals, or grounded final answers for the owner account. Those acceptance checks remain open alongside thomasluizon/orbit-tickets#1568 and the remaining #582 layers. thomasluizon/orbit-tickets#26 remains open, so its promptfoo gate was unavailable.

Test evidence

Before any implementation changes:

dotnet test tests/Orbit.Infrastructure.Tests --filter 'FullyQualifiedName~AiCompletionClientTests|FullyQualifiedName~AiIntentServiceStreamingTests|FullyQualifiedName~AiCompletionErrorTests'

All 31 unchanged tests passed with the missing cache key, old endpoint and temperature defect present. Strengthened existing tests then failed before the implementation change:

dotnet test tests/Orbit.Infrastructure.Tests --filter 'FullyQualifiedName~CompleteJsonAsync_SubTaskTier_OmitsTemperature|FullyQualifiedName~SendWithToolsAsync_WithUserId_SetsEndUserIdForCacheRouting'

Both failed for the intended reasons: /chat/completions instead of /responses, and missing prompt_cache_key.

dotnet test tests/Orbit.Infrastructure.Tests --filter 'FullyQualifiedName~ShouldApplyTemperature'

Three added rows failed before the fix: reasoning models in primary received temperature, and GPT-4.1 mini in a distinct subtask tier lost it. These cases pass after the capability-based fix.

The original deadline fake also survived 200 JSON iterations under focused coverage, so the sporadic timing failure was not claimed reproduced by repetition. I then strengthened the test to cancel exactly while a memory-backed response is being buffered:

dotnet test tests/Orbit.Infrastructure.Tests --no-restore --filter 'FullyQualifiedName~CompletionDeadline_CancellationDuringResponseBuffering'

Before the fake-stream fix: FAIL, expected OperationCanceledException, got ObjectDisposedException: Cannot access a closed Stream from HttpClientTransportResponse.BufferContent during Dispose. After the fake-stream fix: PASS. The targeted coverage run below also passed all five deadline cases, including the JSON case's 200 iterations:

dotnet test tests/Orbit.Infrastructure.Tests --no-build --no-restore --filter 'FullyQualifiedName~CompletionDeadline' --collect:'XPlat Code Coverage' --results-directory /tmp/582-deadline-after -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Include='[Orbit.Infrastructure]Orbit.Infrastructure.AI.AiCompletionClient'

The initial unrestricted coverage attempt was canceled while instrumenting dependencies; the successful run scoped instrumentation to the completion client. No unrestricted-coverage success is claimed.

Final checks: dotnet build Orbit.slnx: exit 0, zero errors, existing warnings only. dotnet test tests/Orbit.Infrastructure.Tests --no-build --no-restore with the focused AI filter: exit 0, 194 passed. The complete projects each exited 0:

  • dotnet test tests/Orbit.Domain.Tests --no-build --no-restore: 797 passed.
  • dotnet test tests/Orbit.Application.Tests --no-build --no-restore: 5,441 passed.
  • dotnet test tests/Orbit.Infrastructure.Tests --no-build --no-restore: 3,952 passed.
  • dotnet test tests/Orbit.Analyzers.Tests --no-build --no-restore: 40 passed.

Total: 10,230 passed, zero failed and zero skipped.

Additional checks: suppression allowlist, timeless rules, dash check and git diff --check passed. Tests cover streamed and buffered tool continuations, reasoning-item replay, multiple call IDs, image encoding, failure/incomplete handling, usage and recorder failure, cache-key stability, old-model configuration, and pricing rows.

  • Unchanged tests: 132 passed with defects present.

  • Strengthened tests: 19 failed before fixes; 147 passed afterward.

  • Timeout regression: three buffered paths failed before fixes; all four paths passed afterward.

  • Build: exit 0, zero errors.

  • Domain: 797 passed; Application: 5,441; Infrastructure: 3,967.

  • Coverage: deadline cases passed, including 200 JSON iterations.

  • Hooks passed; generated OpenAPI files unchanged.

  • Unchanged AiSettingsTests: 8 passed with the defect present:

    dotnet test tests/Orbit.Infrastructure.Tests --filter FullyQualifiedName~AiSettingsTests

    Strengthening Defaults_AllowBufferedReasoningWithoutExtendingStreamingNetworkTimeout and adding CompletionTimeout_IsIndependentOfNetworkTimeoutsAndRetryCount produced three failures before the fix. All pass afterward.

  • The production constructor regression failed on JSON, text, and buffered chat while the old formula remained active; all three pass afterward:

    dotnet test tests/Orbit.Infrastructure.Tests --filter FullyQualifiedName~CompletionDeadline_ConfiguredBound
  • Moving the model values into staging made the strengthened Terraform test fail. An altered decimal separator and a staging override also failed. Restoring the configuration passed:

    dotnet test tests/Orbit.Infrastructure.Tests --no-build --filter FullyQualifiedName~RenderEnvironmentGroups_UseConfiguredPrimaryAndSubTaskModels

    One focused run overlapped a deliberate mutation and failed that assertion; the restored run passed all 69 tests.

All final checks exited 0:

Command Result
dotnet build Orbit.slnx Zero errors; existing warnings
Focused tests under coverage 69 passed, including 200 JSON cancellation iterations
dotnet test tests/Orbit.Domain.Tests 797 passed
dotnet test tests/Orbit.Application.Tests 5,441 passed
dotnet test tests/Orbit.Infrastructure.Tests 3,972 passed

Pre-commit hooks passed. Regenerated OpenAPI files were unchanged.

Rollout

The observed staging environment has AI__Model=gpt-4.1-mini, which overrides the new code default. Set it to gpt-6.1-sol when deploying this change; AI__SubTaskModel can select gpt-6-luna. Observe new model names and nonzero costs in AiUsageDaily. Restoring AI__Model=gpt-4.1-mini restores the legacy chat model and temperature behavior through Responses. A transport rollback requires reverting this PR. This worker did not deploy or merge.

Assumptions

  • Preserved configured tiers and low reasoning, allowing 8,192 output tokens for each short JSON call.
  • Buffered timeout is 90 seconds; streaming remains 15 seconds.
  • No replacement randomness is required by existing contracts. Slip-alert wording can repeat.
  • The 185-second default allows two 90-second attempts plus five seconds for retry wait and processing, replacing the 450-second derived allowance. Longer server-directed waits consume that deadline.
  • Staging inherits the production model values instead of duplicating them.
  • Slip-alert wording variety now comes from the model’s default sampling.

Manual steps

  1. Release staging code first. The running base image always sends temperature, which reasoning models reject. In GitHub Actions → Release API, dispatch from main with environment=staging and branch=redesign/main, after it contains this change. Confirm the carrying commit is live in Render.

  2. Then, from this repository’s configured infra/ directory, using the initialized backend, operator credentials, and ignored local.tfvars, review and apply:

    terraform plan -var-file=local.tfvars -target=render_env_group.staging_api
    terraform apply -var-file=local.tfvars -target=render_env_group.staging_api
  3. Production: only after the production image carrying this change is live, and only with the owner’s yes:

    terraform plan -var-file=local.tfvars -target=render_env_group.production_api
    terraform apply -var-file=local.tfvars -target=render_env_group.production_api
  4. In Render → Environment Groups → orbit-staging-api or orbit-production-api, verify AI__Model=gpt-6.1-sol and AI__SubTaskModel=gpt-6-luna. Check service Environment overrides. Confirm subsequent AiUsageDaily rows contain the configured model names and nonzero costs.

@thomasluizon
thomasluizon marked this pull request as ready for review October 19, 2026 21:36

@pullfrog pullfrog 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.

✅ No new issues found.

Reviewed changes: Reviewed the complete Responses migration and its effects on Astra tool continuations and shared AI completion callers.

  • Responses transport: Text, JSON and chat calls now use centralized Responses options, model-compatible temperature/reasoning settings, cancellation and per-user cache routing.
  • Tool continuations: Buffered and streamed rounds preserve output items and encrypted reasoning, correlate results by call_id, and reject failed responses, incomplete tool calls and streams without a terminal event.
  • Models and pricing: Defaults move to gpt-6.1-sol and gpt-6-luna, while configuration supports restoring the previous primary model through Responses.
  • Regression coverage: SDK-serialized fixtures cover continuation replay, cache keys, images, failure handling and cancellation during response buffering.

Validation: All 1,247 infrastructure unit tests matching FullyQualifiedName~Ai passed. No verified Critical or High regression was found. Live provider calls and full application-turn acceptance were not independently exercised in this review.

Pullfrog  | View workflow run | Using gpt-6.1-sol | 𝕏

@pullfrog pullfrog 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.

✅ No new issues found.

Reviewed changes: Reviewed 0a39e44 against the previous Pullfrog-reviewed commit, with the complete current PR diff as context.

  • Separated timeout budgets: Buffered completions now receive additional reasoning headroom while streaming retains its existing timeout limits.
  • Expanded reasoning allowances: Summary and reschedule JSON calls now reserve 8,192 output tokens while retaining their user-visible text limits.
  • Preserved response boundaries: Buffered text extraction and streaming deltas separate distinct assistant messages consistently.
  • Refined model compatibility: Requests now use safety_identifier with the existing cache key, and legacy-model requests and continuations omit reasoning-specific data.
  • Aligned deployment configuration: Terraform API environment groups now declare the primary and subtask models, with matching documentation and regression coverage.
  • Validated AI regressions: All 1,262 infrastructure tests matching FullyQualifiedName~Ai passed. Live provider calls and full application-turn acceptance were not independently exercised in this review.

Pullfrog  | View workflow run | Using gpt-6.1-sol | 𝕏

@pullfrog pullfrog 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.

✅ No new issues found.

Reviewed changes: Reviewed ffb62a4 against the previous Pullfrog-reviewed commit 0a39e44, with the complete current PR diff as context.

  • Bounded buffered completions: Replaced the derived 450-second deadline with independently configurable CompletionTimeoutSeconds, defaulting to 185 seconds while preserving streaming limits.
  • Verified cancellation behavior: Added production-constructor tests for JSON, text and buffered chat cancellation during retry waits, plus configuration tests separating the buffered deadline from network timeouts and retry counts.
  • Strengthened configuration coverage: Scoped Terraform assertions to production model values and staging inheritance, and aligned .env.example with the configured primary and subtask models.
  • Validated AI regressions: All 1,267 AI infrastructure tests passed; a separate, overlapping focused run passed all 39 completion-client and settings tests. Live provider calls and full application-turn acceptance were not independently exercised.

Pullfrog  | View workflow run | Using gpt-6.1-sol | 𝕏

@sonarqubecloud

Copy link
Copy Markdown

@thomasluizon
thomasluizon merged commit 3fcc1f9 into redesign/main Oct 19, 2026
21 checks passed
@thomasluizon
thomasluizon deleted the thomasluizon/ticket-582-astra-model branch October 19, 2026 23:09
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.

1 participant