Skip to content

🤖 feat: unify reasoning picker between chat composer and Agents settings - #3887

Open
ibetitsmike wants to merge 24 commits into
mainfrom
mike/unified-reasoning-picker
Open

🤖 feat: unify reasoning picker between chat composer and Agents settings#3887
ibetitsmike wants to merge 24 commits into
mainfrom
mike/unified-reasoning-picker

Conversation

@ibetitsmike

@ibetitsmike ibetitsmike commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Unifies the reasoning picker between the chat composer and the Settings -> Agents cards, and replaces the ~10 scattered model/thinking/reasoning fallback ladders behind those surfaces with one shared field-wise resolver used by every execution path: interactive turns, sub-agent spawns, plan handoff, goals, heartbeats, compaction (/compact, auto, ACP), title generation, memory consolidation, ACP sessions, and the CLI.

Background

The chat composer and the per-agent settings cards previously had separate reasoning UIs with divergent semantics. Settings-configured reasoning defaults were ignored or inconsistently applied on several paths (task spawning, plan handoff, goal kickoff, heartbeats, desktop mode switches), and Pro availability was gated on the wrong model when an agent inherited its model from a base agent.

Under the hood, each of those paths carried its own ad hoc precedence ladder, and delegated (sub-agent) defaults lived in a second root config map (subagentAiDefaults) that had to be mirrored against agentAiDefaults with an active migration marker. The ladders disagreed on ancestor inheritance and coupled fields together, so overriding a model at one layer could silently drop a thinking or reasoning preference from another.

Implementation

UI unification:

  • ThinkingSelector gains a box variant used by the Agents settings cards; both surfaces share option gating, keyboard handling, and Inherit semantics (choosing Inherit clears the stored override instead of persisting a copy).
  • Pro is gated on the model that would actually serve the request (definition or base-chain model, not the raw card model), and the Pro toggle is hidden on cards that cannot honor it (Dream, Name Workspace).
  • AppConfigStore centralizes config fetches so pickers share one subscription; routing refreshes when config writes fail so the UI does not show a state that was never persisted.

Single resolver:

  • src/common/utils/ai/resolveAgentAiSettings.ts is a pure field-wise resolver with one precedence order (explicit overrides -> target workspace bucket -> configured profile -> definition defaults -> declared ancestors -> parent runtime -> workspace/activity fallbacks -> system default). Each field resolves independently, invalid persisted values self-heal by falling through, and invalid explicit values throw. The implicit fallback base rule (plan -> plan, otherwise exec, contributing reasoning mode only) lives inside the resolver instead of being duplicated by every caller.
  • Thin adapters gather environment inputs: resolveNodeAgentAiSettings (Node services, reads definition chains), the ACP adapter (ORPC descriptors), and the browser call sites (persisted config + workspace metadata).
  • The resolver returns selected (the user's preference, what persistence stores) separately from effective (provider-safe values after alias normalization, thinking clamping/floors, and route-aware Pro gating), so temporary capability limits no longer overwrite saved preferences.

Canonical config:

  • Root subagentAiDefaults collapses into sparse agentAiDefaults[id].subagent profiles. Config load folds legacy data into the nested shape; config save emits a one-way legacy projection for downgrade compatibility. The execSubagentDefaultsSplit migration marker and the dual-map mirroring in the ORPC router are deleted.

Also includes an unrelated one-line rider: updater.test.ts feed expectations updated from repo: "mux" to repo: "shux". Main was broken by #3898 (package.json repository URL renamed to coder/shux while the updater derives its feed repo from it), which failed every merge-queue run including this PR's; fixing it here repairs main via this squash merge.

Validation

  • Table-driven precedence/normalization/clamping tests for the pure resolver (resolveAgentAiSettings.test.ts), plus behavioral tests across the resolution surfaces: base-chain inheritance and per-field fallback (taskService.test.ts, workspaceService.test.ts, workspaceGoalService.test.ts, acp.resolveAgentAiSettings.test.ts, acp.configOptions.test.ts), legacy config merge/projection round-trips (config.test.ts, agentAiDefaults.test.ts), Pro gating and Inherit-clears-override (workspaceModeAi.test.ts), picker UI flows (TasksSection.ui.test.tsx), routing refresh on failed writes (useRouting.test.ts).
  • Remote dogfood UAT (real models) passed a full round on the picker/settings surfaces; a follow-up round on the resolver refactor head is in flight.
  • Merge-queue failure diagnosed to broken main (see rider above); bun test src/desktop/updater.test.ts passes on the merged tree.

Risks

Medium. Reasoning/model resolution touches every agent-spawn path; a regression would mis-select thinking level or model for sub-agents, heartbeats, or goal kickoff. Mitigations: the resolver is pure and table-tested against the documented precedence order, adapters fall back to resolver-internal defaults when definitions cannot be read, and invalid persisted config self-heals instead of erroring. The config schema change ships a save-time legacy projection so downgrading builds keep reading delegated defaults.


Generated with Shux • Model: anthropic:claude-fable-5 • Thinking: xhigh

@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d5ff5f3db0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/acp/resolveAgentAiSettings.ts Outdated
Comment thread src/node/services/workspaceService.ts Outdated
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 20edfe77ca

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/features/Settings/Sections/TasksSection.tsx Outdated
Comment thread src/node/services/taskService.ts Outdated
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a937067819

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/features/Settings/Sections/TasksSection.tsx Outdated
Comment thread src/browser/features/Settings/Sections/TasksSection.tsx
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1c3188ef10

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/features/Settings/Sections/TasksSection.tsx Outdated
Comment thread src/browser/features/Settings/Sections/TasksSection.tsx Outdated
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ca2bb19aa2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/features/Settings/Sections/TasksSection.tsx Outdated
Comment thread src/browser/features/Settings/Sections/TasksSection.tsx
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2a46665bad

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/utils/workspaceModeAi.ts Outdated
Comment thread src/browser/features/Settings/Sections/TasksSection.tsx Outdated
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 122b930f99

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/taskService.ts Outdated
Comment thread src/browser/features/Settings/Sections/TasksSection.tsx Outdated
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 801b461d7a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/taskService.ts Outdated
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

The Agents settings page used a plain Select for reasoning that only listed
thinking levels, so per-model features in the chat picker (Pro mode for the
GPT-5.6 family, Fast mode for OpenAI/Grok frontier models) were impossible to
configure there and the two controls drifted in styling.

- Extract ThinkingSelectorControl: a controlled variant of the chat thinking
  picker owning policy resolution + route-aware Pro/Fast availability, with a
  "composer" (chat input) and "box" (settings form field) variant plus an
  optional Inherit row. ThinkingSelector is now a thin wrapper binding it to
  ThinkingContext, so future picker changes apply to both surfaces.
- Add reasoningMode to AgentAiDefaultsEntry/SubagentAiDefaultsEntry (sparse:
  only explicit "pro" is persisted) and plumb it through normalizers, the
  TasksSection save path, workspace mode sync, task/workspace-turn resolution,
  ACP agent defaults, heartbeat/idle-compaction sends, and compaction override
  paths, mirroring thinkingLevel precedence.

---

_Generated with `mux` • Model: `anthropic:claude-fable-5` • Thinking: `xhigh`_

<!-- mux-attribution: model=anthropic:claude-fable-5 thinking=xhigh -->
Remote UAT found the bottom agent row's menu opened below the settings
fold with no auto-scroll.
…f per-field fallback

Codex review: ACP mode switches, model changes, and thinking-level changes
rebuilt persisted AI settings without reasoningMode, silently dropping pro;
goal-continuation kickoff skipped model-less candidates entirely, ignoring
reasoning-only agent defaults.
…tandard override of inherited pro

Codex round 2: the plan-to-exec handoff ignored effectiveReasoningMode from
resolveTaskAISettings (configured exec sub-agent/agent pro defaults never
applied), and the Exec sub-agent row's pro toggle could not disable an
inherited pro because turning it off deleted the already-absent override.
…clears reasoning override

Codex round 3 follow-ons: setAgentReasoningMode deleted overrides that ACP's
base-chain resolution then re-filled with an ancestor's pro, and the Inherit
action retained an invisible explicit-standard reasoning override with no way
to remove it.
Codex round 4: Dream's headless requests (raw streamText) never apply
reasoningMode, so the card offered a toggle that could not affect them; and
cards without a direct override displayed standard while ACP base-chain
resolution ran pro, making the first toggle click a no-op.
…AppConfigStore

Codex round 5: agent cards gated Pro on the ambient default model even when
the base chain supplied a pro-capable one, hiding an active inherited pro;
and every ThinkingSelectorControl instance opened its own config.getConfig
fetch + onConfigChanged subscription via useRouting/useMinThinkingLevels
(O(rows) fan-out on the Agents settings page). AppConfigStore mirrors
ProvidersConfigStore: one fetch + one subscription per app session.
…es and creation

Codex round 6: the desktop mode-switch resolver read only the direct
agentAiDefaults entry (custom agents with base: exec never inherited an
ancestor's pro), and the creation sync copied only model/thinking so a
configured pro default missed the first turn of new workspaces.
resolveConfiguredReasoningModeDefault mirrors ACP's base-chain walk and is
shared by both paths.
… hide Pro on Name Workspace card

Codex round 7: resolveTaskAISettings consulted only the target agent's own
defaults before parent fallbacks, so Explore never inherited a pro configured
on its Exec base (unlike Settings display and ACP resolution); and the Name
Workspace card offered Pro even though name generation runs raw streamText
(same headless class as Dream, now a shared exclusion set).
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

Reviewed commit: 9355ea8c11

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Codex round 8: the sync approximation hardcoded every non-plan agent to
inherit its reasoning default from exec; a custom sub-agent with base: plan
(or a custom ancestor) now resolves its definition's actual chain at
Task.create/createMany time (readAgentDefinition +
resolveAgentInheritanceChain, ACP-parity fallback terminus), keeping the
approximation only where definitions are unreadable or callers are sync (plan
handoff targets literal exec, where the approximation is exact).
@ibetitsmike
ibetitsmike force-pushed the mike/unified-reasoning-picker branch from 9355ea8 to cdf18a5 Compare August 20, 2026 14:42
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 038ab8f4fe

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/utils/workspaceModeAi.ts Outdated
Comment thread src/node/services/workspaceService.ts Outdated
…'s declared base

Codex round 11:
- resolveWorkspaceAiSettingsForAgent resolves model/thinking field-wise
  through DECLARED base chains alongside reasoningMode, so a custom agent
  inheriting GPT-5.6 + pro from its base persists both together instead of
  pro beside an Anthropic workspace model where gating drops it. The
  implicit unknown-agent fallback still contributes reasoningMode only,
  preserving desktop switches that keep the workspace's current model.
- resolveWorkspaceAgentBaseChainIds no longer assumes agents named exec are
  the unmodified built-in: a project-scoped exec.md with base: plan now
  resolves Plan's defaults for goal kickoffs and heartbeats.
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 848bf2e5bb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/utils/messages/compactionOptions.ts Outdated
Comment thread src/node/services/workspaceService.ts Outdated
…beat model/thinking through declared chains

Codex round 12:
- /compact (applyCompactionOverrides) resolves compact's configured base
  chain (compact -> exec) for reasoningMode, so a saved Exec pro default
  reaches compaction as the Settings card displays.
- Backend idle compaction gets the same chain-walk (same defect class:
  it consulted workspace exec settings but never config agentAiDefaults).
- Heartbeats resolve model and thinking through the declared base chain
  alongside reasoningMode; resolving only some fields combined Plan's pro
  with Exec's Anthropic model, where gating drops pro.
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

2 similar comments
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@ibetitsmike
ibetitsmike added this pull request to the merge queue Aug 20, 2026
@ibetitsmike
ibetitsmike removed this pull request from the merge queue due to a manual request Aug 20, 2026
@ibetitsmike
ibetitsmike enabled auto-merge August 20, 2026 19:00
@ibetitsmike
ibetitsmike added this pull request to the merge queue Aug 20, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 20, 2026
…subagent; add pure AI-settings resolver

Checkpoint 1 (Phases 1-2): one root config map with a sparse nested delegated
profile, legacy root map reduced to a save-time downgrade projection, dual-map
mirroring deleted from router/settings/mocks, and a pure field-wise resolver
(model/thinking/reasoning) with chain traversal and table-driven tests.
…d resolver

Task create/createMany, workspace turns, plan->exec handoff, and parent
auto-resume all resolve model/thinking/reasoning via resolveNodeAgentAiSettings.
Deletes resolveTaskReasoningMode, the workspace-turn inline ladder, and the
handoff-specific reasoning patch; resolveDeclaredBaseChainIds is no longer used
by taskService.
…rough the unified resolver

- workspaceService: goal kickoff, idle compaction, and heartbeat send options
  resolve via resolveNodeAgentAiSettings (workspace bucket -> config ->
  definition/base chain -> legacy/activity fallbacks); deletes the three
  bespoke candidate ladders and resolveWorkspaceAgentBaseChainIds.
- agentSession: auto-compaction resolves as agent compact via the pure
  resolver (now including the workspace compact bucket); startup crash
  recovery is documented as request replay; removed a duplicate pre-send
  thinking clamp.
- dream and name_workspace resolve their model through the shared resolver
  (name_workspace defaults are now actually wired into candidates).
- resolveDeclaredBaseChainIds deleted (no remaining consumers).
…hared resolver

- ACP resolveAgentAiSettings is now a thin adapter (declared base chain from
  ORPC descriptors + implicit plan/exec fallback) over the pure resolver;
  target definition defaults now beat ancestor config per the unified order.
- ACP /compact resolves as agent compact with the -m flag as the explicit
  tier, the workspace compact bucket, and live session settings as parent
  runtime; invalid -m values report an error instead of streaming a fallback.
- Composer /compact resolves through the shared resolver (configured compact
  model now honored, matching idle/auto compaction).
- CLI run/workflow -m flags normalize through normalizeModelInput and fail
  fast on invalid input.
…olver

The fallback-base rule (plan -> plan, otherwise exec, reasoningMode only)
was duplicated across four places: the unused common chain helper, the ACP
adapter, the Node adapter, and the composer /compact call site. Adapters now
pass declared ancestors only and the resolver appends the implicit fallback
itself, so AgentAiAncestorLayer.declared disappears. Also drops the unused
adjustments output block, collapses the three per-field precedence loops
into one pickField helper, and reuses the resolver's selected shape for the
ACP ResolvedAiSettings type.
@mintlify

mintlify Bot commented Aug 21, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
Mux 🟢 Ready View Preview Aug 21, 2026, 6:40 AM

💡 Tip: Enable Workflows to automatically generate PRs for you.

… resolver

resolveConfiguredAiDefaults hand-rolled the same declared-chain +
implicit-fallback precedence the pure resolver owns. It now feeds
agentAiDefaults and the declared ancestor layers into the resolver and uses
value provenance (sources tier) to report only genuinely configured fields.
Behavioral contract unchanged: all 19 resolveWorkspaceAiSettingsForAgent
tests pass unmodified.
# Conflicts:
#	src/common/orpc/schemas/api.ts
#	src/desktop/updater.test.ts
#	src/node/orpc/router.ts
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

Head 852c1d8 adds the unified AI-settings resolver refactor on top of the reasoning-picker feature: canonical agentAiDefaults[id].subagent config with legacy load merge + save projection, one pure field-wise resolver (src/common/utils/ai/resolveAgentAiSettings.ts) behind all backend/ACP/CLI/browser resolution paths, and a simplification pass that centralizes the implicit plan/exec fallback rule in the resolver.

Shux acted on ibetitsmike's behalf.

… pro defaults

UAT regression (rounds 3-5): with a configured exec Pro default, toggling a
workspace to Standard was undone on reload or on switching back to the agent;
background sync re-applied the configured Pro and the next send flipped the
persisted bucket. An existing per-agent bucket now owns the reasoning choice
outright (matching the backend targetWorkspaceBucketToLayer contract);
configured defaults apply only when no bucket entry exists.
@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

Head bbadd26 additionally fixes a UAT-found regression: an explicit workspace Standard reasoning choice was reverted to a configured Pro default on reload or agent switch-back. An existing per-agent workspace bucket entry now owns the reasoning choice in the frontend sync path, matching the backend targetWorkspaceBucketToLayer contract.

Shux acted on ibetitsmike's behalf.

@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@claude review

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