Skip to content

refactor: remove what the first-party plugin era left in live code - #250

Merged
HTExplicit merged 38 commits into
mainfrom
refactor/remove-plugin-era-shells
Oct 7, 2026
Merged

HTExplicit merged 38 commits into
mainfrom
refactor/remove-plugin-era-shells

Conversation

@HTExplicit

Copy link
Copy Markdown
Owner

Problem

The first-party plugin system is gone (#229–#248), but code shaped by it still ran: two backend packages named after the old extension API, carrier structs that once crossed a plugin boundary, a frontend "account view" skeleton whose view object is always empty, a telemetry writer whose only reader was a deleted plugin UI, legacy redirects, a button whose backend was deleted, and an error path that cannot trigger. The owner's rule is that a retired feature leaves nothing behind.

Change

Backend

  • internal/nativeapi and internal/codexruntime are folded into their only user, service. The alias extensionv1, the four recovery carrier structs and the three identity-conversion layers are gone. Reasoning recovery keeps its decision order and reason strings; fix(openai): move to the next account when the stripped retry fails for the account's own reason #249's code is untouched.
  • Building an account's Codex User-Agent cannot fail: the error return, ErrInvalidVersion and its propagation through the send paths are removed. The version and identity it rejected are validated where they are produced.
  • Account traffic telemetry is deleted as a whole: the seven Begin/Finish call sites, the observer, its Redis cache and Lua script, the decision table, GET /admin/accounts/:id/traffic-telemetry, the settings switch and gateway.account_traffic_telemetry_disabled. Six HTTP forwarding closures are byte-identical to v0.2.13 again.
  • Migration 273_purge_account_traffic_telemetry_switch.sql removes telemetry_enabled from settings.admin_observability_config and keeps theme_enabled. The decoder stays strict.
  • Removed fields nobody reads or writes: account_view_facts on account responses, the job item action, wire_platform and schema_version on the account test plan, the job list's kind and created_by filters, a request decoder for the removed provider_edit field.
  • The CI selector test_native_domains.sh, its workflow step and its contract assertions go with the packages they selected; the same tests run under make test-unit.

Frontend

  • The account-view skeleton is deleted (useAccountViewContext.ts, accountViewClient.ts, the view parameter on 60 API functions, accountAPIForView). Eight files are byte-identical to v0.2.13 again. The stats dialog, the scheduled-tests panel and the re-auth dialog keep discarding late answers through a local guard, as upstream does in TempUnschedStatusModal.
  • The account drawer keys its usage cache and usage cell by account id.
  • The prompt audit page, its view model and spec are upstream's, with one theme hook.
  • /admin/tasks and /admin/cindy-accounts are removed, with the ?operations=history handling only the redirect produced.
  • The duplicate-account review entry is removed; its backend was deleted in fix: rework connection tests, context capacity, system prompts, Cindy and UI foundation #206.
  • Select.vue, the plugin-era resolver entries and the vitest config are upstream's; orphan page, unread locale keys and dead exports are deleted.

Not in this PR

  • deploy/** still names GATEWAY_ACCOUNT_TRAFFIC_TELEMETRY_DISABLED in six files; the application ignores it. It goes with the deploy pipeline cleanup.

What an admin sees

  • Settings: the "Appearance and observations" panel is titled "Appearance" and loses the traffic telemetry checkbox and its description.
  • Account drawer: reopening the same account within 5 minutes shows the cached usage; manual refresh still re-queries. Switching accounts rebuilds the usage area.
  • Prompt audit page: the save bar is fixed to the window bottom and spans from the sidebar to the right edge. The fork's extra guards against late responses and mid-save edits are gone, as the owner chose.
  • Ops error details: three sentences no longer say "host".
  • Bulk action bar: no "Review duplicates" button.
  • /admin/tasks and /admin/cindy-accounts show the 404 page.
  • A page opened before the deploy needs one refresh: until then the account test dialog lists no models and saving the Appearance panel fails.
  • Previewed with mock data and approved by the owner. The accounts table, drawer, stats dialog and scheduled-tests dialog are pixel-identical before and after.

API clients

  • Account JSON has no account_view_facts. The account test plan view has no wire_platform or schema_version.
  • GET /admin/accounts/:id/traffic-telemetry is gone. GET/PUT /admin/settings/observability carries only theme_enabled.
  • GET /admin/account-jobs ignores kind.

Verification

  • go build ./... (default and GOOS=linux); go vet ./... with no tag, -tags unit, -tags integration on repository, service and handler; wire diff clean; gofmt.
  • Unit tests of every Go package with a changed file. fix(openai): move to the next account when the stripped retry fails for the account's own reason #249's 92 recovery and account-switch tests pass after the rebase onto it.
  • Migration 273 on a throwaway PostgreSQL 18 from an empty database, and once through the real runner on a row carrying the key.
  • vue-tsc, check:i18n, eslint on changed files, the full vitest suite.
  • The User-Agent proof: the builder's two failure branches were exercised against all 7,825 derived identities and 300,000 random stored values before removal; none reaches the error.
  • Two workflows, each with independent review lenses (behaviour, completeness, a runner) and a second agent verifying every finding: 19 confirmed, all fixed or handed to the task that owns them.

Known failures that exist on main and are not touched here: TestOllamaProbeCallback_StaleLongDoesNotOverrideNewShort and, at times, TestAntigravityCompatHandlerRepeatsPreContentKeepalive (timer-sensitive on Windows); groupModelAllowlist.spec.ts "accepts wildcards at any position".

Not run locally: golangci-lint (the local binary cannot read Go 1.27 export data), the full integration suite, real model calls.

🤖 Generated with Claude Code

Codex and others added 30 commits October 6, 2026 20:05
…ackage

Both packages had one user, the service package, and existed because their
contents once crossed a plugin boundary. Nothing an admin, a user or an API
client can observe changes.

- The model capacity structs, the two switch setting structs and the Codex
  client identity are defined next to the code that uses them. JSON tags and
  stored formats are unchanged. The handler builds the setting structs from
  the service package.
- The Codex client identity is one struct with its own methods; the
  conversions between three copies of the same type are gone. Building a
  User-Agent still checks the identity and the version and still returns the
  same errors.
- Reasoning recovery reads the upstream payload and the request body directly.
  The four carrier structs between collecting facts and deciding are gone. The
  order of the checks and the reason strings are the same.
- validOfficialCatalogCapacity repeated validModelContextTokens and is removed.
- The account traffic telemetry types (the decision table, the observation
  policy and the counter snapshot) move unchanged.
- CI: the selector script that ran ./internal/codexruntime is removed together
  with its workflow step and its assertions in the contract test. The tests it
  selected run in the required test job. The contract test also loses the
  assertions that only named files deleted earlier.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… they are

"native" and "legacy" in these names described the move out of plugins, not
the settings themselves.

- readNativeSwitchSetting is readSwitchSetting. Its three errors no longer say
  "native": "settings repository is unavailable", "cannot read setting <key>"
  and "invalid setting <key>". They appear only in the process output when the
  server fails to start.
- LegacyAdminObservabilityConfig is defaultAdminObservabilityConfig: it is the
  deploy-time default read from gateway.account_traffic_telemetry_disabled.
- EffectiveAdminObservabilityConfig reads the switches itself instead of
  forwarding to a second function, and the holder is no longer called an
  override.
- LoadAdminObservabilityConfig loses a branch for a nil service that the read
  above it already returns from.
- Tests: native_setting_load_test.go is setting_switch_load_test.go, and four
  test names lose the word.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…talog lookup's input guard

Two shapes left from calls that used to cross a plugin boundary.

- GET /admin/ops/errors/:id/diagnostics was a method of AccountHandler that
  took the OpsHandler as an argument and used nothing of its own receiver. It
  is OpsHandler.GetCodexErrorDiagnostics, registered like the routes around it.
  Path, headers, status codes and bodies are the same.
- lookupOfficialModelCatalog validated its candidates as if they came over an
  RPC: at most 16, at most 512 bytes each, none blank. Its one caller,
  LookupOfficialModelContextCapacity, passes at most five candidates that each
  passed validModelContextID, so none of these checks could fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…count responses

Every admin account response carried an account_view_facts object (version,
status, plan, privacy_mode) that was built for the plugin account views.
Nothing reads it: the frontend only declared its type.

- service.AccountViewFactsV1 and AccountViewFactsFromAccount are removed with
  the test that covered only them. accountConsoleStatus and accountConsolePlan
  stay; the account filters and facets use them.
- dto.Account starts with ID again, as upstream does, and dto.AccountListItem
  loses the same field.
- The frontend Account type loses the declaration.

Observable change: the admin account JSON (full and list form) no longer has
the account_view_facts key.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… writes

AccountJobItem.Action and AccountJobItemSeed.Action had one writer, the plugin
operation job, which no longer exists. Both seed constructors leave the field
empty, so every item row stores '' and the JSON key, being omitempty, was
never sent.

- The two Go fields are removed.
- The repository no longer names the column: the item insert, the item column
  list and the retry seed query drop it. admin_account_job_items.action stays
  in the database with its NOT NULL DEFAULT '', so inserts keep working and an
  older image can still write to the table.
- The frontend AccountJobItem type loses the declaration.
- account_job_repo_test.go also loses a trailing blank line gofmt rejected.

No migration. Nothing an admin or an API client can observe changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… the test plan

The account test plan was shaped to be shared with a provider plugin: it
stated a wire platform and a schema version. The wire platform was always the
account's own platform and the version was always 1.

Backend
- accountTestPlanView loses WirePlatform and SchemaVersion.
- ordinaryAccountTestPlan is buildAccountTestPlan. basicAccountTestPlan, its
  one helper, is folded into it. The plans are byte for byte what they were in
  the four remaining fields; the server still orders the models and picks each
  mode's default.

Frontend
- isOpenAIAccount in both AccountTestModal components is upstream's
  props.account?.platform === 'openai' again, and so is the check in
  supportsOpenAIImageTest. isOpenAIOAuthAccount no longer tests the platform
  twice.
- AccountTestPlanView and validateAccountTestPlan lose the two fields.
- AccountAvailableModel loses nine fields the server never sends and nothing
  reads: live_upstream_id, base_context_window, codex_context_window,
  endpoints, source_revision, verified, alias_target, managed, public_model.

Tests
- The two cases written against a "cindy" account platform are removed; that
  platform does not exist.
- AccountTestModal.policyPlan.spec.ts is AccountTestModal.testPlan.spec.ts and
  uses an OpenAI account and the "default" mode the server sends. The
  downstream-verify workflow lists the new name.
- TestAccountTestPlanCoreSelectionSmallMatrix is
  TestAccountTestPlanModelOrderAndDefaults.

Observable change: the response of GET /admin/accounts/:id/models
?view=account-test-plan-v1 no longer has wire_platform and schema_version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When an account is edited, the OpenAI protocol modes the admin did not touch
keep their stored encoding. That behaviour stays. The code that implements it
was the remainder of the plugin-era "account edit contract" and still carried
its names and shapes.

Backend
- account_edit_codec.go is openai_apikey_protocol_modes.go.
  openAIAPIKeyOwnedExtraForUpdate and applyAccountEditOwned are
  openAIAPIKeyProtocolModesForUpdate and applyOpenAIAPIKeyProtocolModes.
- accountEditRawValue, a present/value pair with JSON tags nothing serialised,
  is gone: the resolved modes are a plain map, and a key missing from it is a
  key to remove. The branch for a key that was "not owned" could not be taken
  and is removed.
- The seven protected keys, openai_prompt_cache_key_mode among them, and the
  point in UpdateAccount where they are resolved and applied are unchanged.
- New test TestUpdateAccountKeepsOmittedOpenAIAPIKeyProtocolModes pins the
  behaviour through UpdateAccount. It passed before this change and passes
  after it.

Frontend
- utils/accountEditCodec.ts is utils/openaiProtocolModeEdits.ts, and
  types/accountEdit.ts is folded into it: the value unions are derived from
  the table of modes instead of being written twice.
- AccountEditChangesV1 is OpenAIProtocolModeEdits. An edit is the chosen value
  itself; the { op: 'set' | 'clear' } wrapper is gone because 'clear' was
  never produced and only threw.
- applyCoreAccountModeChanges is applyOpenAIProtocolModeEdits; in
  EditAccountModal coreModeChanges and recordAccountMode are protocolModeEdits
  and recordProtocolModeEdit.
- The spec follows the file name and keeps its assertions. Its one test of
  buildModelMappingObject moves to useModelWhitelist.spec.ts, where that
  function is tested. The downstream-verify workflow lists the new name.

Nothing an admin or an API client can observe changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rder

Four upstream files differed from v0.2.13 in places no fork feature needs:

- middleware/group_model_allowlist.go: the GroupModelAllowlist comment
  described a rejection of reserved internal selectors that no longer exists.
  The code under it is upstream's fast path, and the comment is upstream's
  again.
- handler/setting_handler.go: the NewSettingHandler comment is back.
- service/settings_view.go: the blank line before the model fallback fields is
  back.
- service/setting_service.go: "sync" is back at upstream's place in the import
  block.

No code changes. What still differs from upstream in these files is live fork
code: the flat theme flag, the refusal recovery settings and their cache, the
tolerant JSON body read and the wildcard model route.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
codexClientIdentity.buildUserAgent checked the identity and the version again
and returned an error that every send path carried upwards. The check dates
from the time the builder sat behind a plugin boundary. Inside the service
package it cannot fail:

- The version comes only from resolveCodexOutboundIdentity. It is either the
  built-in constant or a value NormalizeCodexClientVersion accepted, with the
  same expression and the same length limit the builder applied.
- The identity comes only from Account.CodexClientIdentity. It is either a
  stored value that passed valid() when it was read, or a derived one, and the
  derivation can only produce identities that pass valid().

So the builder is UserAgent again, a plain formatter, and
resolveCodexOutboundIdentityForAccount and enforceCodexIdentityHeadersForAccount
return no error, as they did before the plugin era. Gone with it:
errCodexClientVersionInvalid, the second copy of the version expression, the
error branches on the send paths (account test, usage probe, alpha search,
models manifest, token refresh, upstream models, the shared header finalizer),
the two readers that discarded the error, and the account-test message
"Codex client identity is invalid", which could never be shown.

Tests: the case that relaxed the version expression to force the error is
replaced by one that hands the resolver an invalid version and checks that the
account still goes out as itself with the built-in version. The check that the
builder refuses a bad profile becomes a check that a stored identity failing
the schema check is not used, and that every branch of the derivation passes
it. Call sites in tests are back to their one-line form.

No request changes what it sends or when it fails.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…er reach

applyOpenAIProtocolModeEdits checked each edit against the table of allowed
values and refused a Responses mode on an account that is not an API-key
account. Both checks threw, and neither can be reached:

- The edits come only from recordProtocolModeEdit in EditAccountModal, which
  checks the value against the same table before it records it, and the
  parameter type admits no other value.
- The Responses mode select is rendered only for an OpenAI API-key account,
  and the recorded edits are cleared whenever the dialog opens or the account,
  its platform or its type changes.

The function has one caller and no spec covers either throw. The type
parameter stays: it still picks the OAuth key for the WebSocket mode.

Four cases in EditAccountModal.spec.ts were titled with the retired
account.edit slot name and its vocabulary. Each title now says what the case
checks. No assertion changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- utils/accountTestModels.ts: the comment about presentation, a data contract
  and provider rules described the test plan that was shared with a provider
  plugin, and it sat above a function it did not describe. Removed.
- service/codex_error_diagnostics.go and its test: both comments explained
  that a count limit and an account filter do not apply any more. They now
  state what the projection returns.

Comments only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s them

When the plugin-era fields were deleted from the two account literals, the
fields next to them stayed where they were: OpenCodeGoUsage at the end of
AccountFromServiceShallow instead of after OllamaCloudUsage, and
ManagementFolder and Tags at the head of AccountListItemFromAccount, which
made gofmt re-align upstream's first line.

OpenCodeGoUsage is back at upstream's position, and ManagementFolder and Tags
follow the proxy fields as they do in the Account literal. mappers.go now
differs from v0.2.13 only by added lines. Both literals are keyed and hold the
same pairs as before, so they build the same values and the JSON is unchanged.

dto/types.go is not touched: moving the OpenCodeGoUsage field there would
change the key order of the account JSON.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…trigger

accountTestPlan refused a nil account and an account without an id with
"account test target is unavailable". Its one caller, GetAvailableModels,
reaches it only after GetAccount returned without an error, and the account
repository returns an account or an error, never neither. The plain model
list in the same handler uses the account without such a check, as upstream
does.

The check dates from the commit that shared the plan with a provider plugin.
No test covers it and no response changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…p upstream's field order

UpdateAccountRequest.UnmarshalJSON only rejected "provider_edit": null, a
field that no longer exists; upstream has no such method. Account's
OpenCodeGoUsage is back where upstream declares it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AccountUsageCell built its cache key from the account-view context, and the
details drawer was the only place that still provided one. Outside the drawer
the key was a constant prefix on the account id. Inside it the key carried the
drawer's open counter, so every open queried usage again, never reused what a
card or compact row had just loaded, and left one more entry in the module
cache.

The cache and the in-flight request map are keyed by the account id again, as
they were before cd8c18b:

- Reopening an account within five minutes shows the cached usage.
- The drawer, the cards, the compact rows and the mobile table share one entry
  per account, in both directions.
- The page's refresh button and the cell's own query buttons still force a
  request.

The drawer keys its usage cell on the account id. When it goes straight from
one account to another, the cell and the probe cells inside it are rebuilt:
the new account loads on its own and a late answer for the previous one ends
in an unmounted instance. Until now the cell was reused. An account that is
not OpenAI OAuth kept the previous account's usage on screen, and if that
account's request was still running the loading state never ended, because
loadUsage resets it only for the account it started with.

That check in loadUsage is unchanged. Every usage cell is now keyed by account
id (table rows, cards, compact rows, the drawer), so it has no case left to
catch.

The view argument of the cell's getUsage calls, the cancellation it threw for
a changed view and the watcher on the context key go with the context. The
watcher could not fire: nothing reactive changed when the drawer changed
account.

Two cases in AccountDetailsDrawer.spec.ts cover the key and the shared cache.
Both fail on the previous code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The statistics dialog, the scheduled-tests panel and the re-authorization
dialog discard an answer that arrives after the dialog was closed or moved to
another account. They did it through useAccountViewOperation, a composable
left from the plugin account views. Its view snapshot is always empty and its
"available" flag is always true, so only its operation counter did anything.

- AccountStatsModal and ScheduledTestsPanel use the guard upstream has in
  TempUnschedStatusModal: a request version that the show/account watcher
  advances in its cleanup and that is compared when the answer arrives. The
  panel's two loaders read one version without advancing it, so the reload
  after a create and the results of an expanded plan do not cancel each
  other, as before. The composable also refused a request for a closed
  dialog; the panel keeps that for the one handler a click can still reach
  while the dialog fades out, toggleExpand.
- ReAuthAccountModal already had its own revision counter and isCurrent
  check. The view snapshot, the "available" checks, the inert binding and the
  watcher that reset the OAuth clients go; none of them could trigger.
  canExchangeCode and handleGenerateUrl are upstream's again. The latter also
  loses a show check: it runs only on the flow component's event, and an
  unmounted child emits nothing.

What an admin sees does not change. A closed or re-targeted dialog still
ignores the old answer, shows no error for it and keeps the current loading
state, and re-authorization still never writes one account's credentials to
another.

Each dialog gets a small spec for this; none had one. All three pass on the
previous code as well.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
useAccountViewContext.ts and accountViewClient.ts threaded a "view" through
the admin account API, the probe cells and the account dialogs. Nothing has
produced a view since the plugin account views were removed (9f7b08d), so
every wrapper passed straight through to apiClient and adminAPI.accounts.

Removed:

- both files;
- the view parameter of 60 functions in api/admin/accounts.ts and of
  reviewDuplicates, accountViewClient(view) in favour of apiClient,
  accountAPIForView with its argument table, and scheduledTestsForView;
- readWithAccountView around the requests of the Ollama Cloud and OpenAI
  quota cells;
- scopedAccounts() in the bulk edit, edit and test dialogs, and in the test
  dialog the "available" checks, the bound request config and the axios
  cancel check (its request is a fetch);
- the header's injected page title, which nothing provided;
- AccountConsoleFacets.view_preset_counts, which nothing sends or reads.

Back to upstream v0.2.13 byte for byte: api/admin/cnProviders.ts, grok.ts and
scheduledTests.ts, CNProviderBalanceCell.vue, CNProviderQuotaCell.vue,
GrokQuotaProbeCell.vue, TempUnschedStatusModal.vue and its spec. The spec's
vue-i18n mock had been widened only because the component loaded the
account-view client.

No request, response or screen changes. In the details drawer the probe cells
relied on the view to drop an answer for a previous account; the drawer
rebuilds them per account instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ally

- README.md, README_CN.md, README_JA.md: Go 1.27.0, as go.mod and upstream say.
- docs/channel-monitor-v2-safe-defaults.md: the three Markdown hard line breaks.
- frontend/src/api/admin/index.ts: the plugin type export on six lines.
- AppSidebar.vue: no comma after the last admin nav item.
- AccountTableFilters.vue: upstream's file. The fork mounts
  AccountConsoleFilters instead and has no production reference to it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…and three dead ends

- AccountTasksView.vue had no route and no importer since the account page
  took over the operation history; its spec and its seven locale keys go
  with it.
- 33 more locale keys the fork added are read by no source file. They are
  removed from both locales; accountConsoleLocales.spec.ts no longer pins
  the text of one of them.
- useAccountTestPrompt writes localStorage itself again. The window event
  it sent through utils/browserPreferences.ts was heard only by its own
  module, which stored the value it had just set.
- AccountActionMenu no longer emits resource-complete: nothing listens.
- accountOperationIdempotency.ts loses captureAccountOperationSession,
  which has no caller.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
For an OpenAI OAuth account the usage endpoint answers through
getOpenAIUsage, which builds quota_windows and fills five_hour and
seven_day only from them. A response with those two fields and no
quota_windows therefore does not exist. The helper that rebuilt windows
from them for such a response is deleted and the usage cell reads
quota_windows.

Fifteen tests fed the cell that response and went through the helper.
Their fixtures now carry quota_windows next to five_hour and seven_day,
as the server's response does; no assertion changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tsconfig.json is upstream's again, and vite.config.ts differs only by the
SUB2API_ARTIFACT_BUILD switch. The removed paths, dedupe and 'vue' alias
served sources outside frontend/, which no longer exist; 'vue' still
resolves to dist/vue.runtime.esm-bundler.js for the client build.

vitest.config.ts loses fs.allow, dedupe and the 'vue' alias. With all
four of its added entries removed, the full unit suite differs in three
SubscriptionPlanCard tests only: they assert translated text, and the
runtime-only vue-i18n returns the key without
__INTLIFY_JIT_COMPILATION__. That entry stays.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ntries

Both were redirects to the account page kept for old bookmarks; those
addresses now reach the 404 page. The account page no longer opens the
operation history for ?operations=history, a query only the /admin/tasks
redirect produced.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Select.vue differs from upstream only by the #overlay-root teleport and
the console theme's dropdown anchor. The interactionDisabled alias of
props.disabled is gone, and so are the four checks that closed an open
dropdown and refused its options once the select became disabled; an open
dropdown now stays open in that case, as upstream's does.
Select.disabled.spec.ts tested only those checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ost"

Three sentences of the continuation diagnostics named the gateway "the
host" (宿主). They now state what happened: a bounded recovery request was
dispatched, replay is not allowed after semantic output, recovery across
sources is not allowed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- CodexRuntime.native.spec.ts becomes CodexRuntime.spec.ts; its suite and
  its diagnostics test no longer say "native".
- SettingsView.spec.ts: the mocks and the test of the observability
  settings and the model catalog no longer say "native".
- features/account-jobs/__tests__/integrationSurface.spec.ts moves next to
  the layout it mounts, as AppLayout.accountTaskDrawer.spec.ts, and stops
  asserting that a removed header button is absent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PromptAuditView.vue is upstream v0.2.13 plus the console theme's page
hook (data-ui="prompt-audit-page" on the root); viewModel.ts and
PromptAuditView.spec.ts are upstream's bytes. EventWorkspace.vue keeps
its one theme hook (data-ui="log-table").

What the page did beyond upstream is gone with it:
- the save bar sticking to the end of the content column: it is fixed to
  the window's bottom again, from the sidebar to the right edge;
- reconcileSavedDraft: a save's response replaces the draft, so edits
  made while the save was in flight are dropped;
- the request generations of the event list and the event detail: the
  response that arrives last is shown, also when it is the older one;
- the generation that tied a filter-deletion preview to its criteria and
  to the open dialog: a late preview is shown after the criteria changed,
  and a one-click deletion goes ahead after the dialog was closed;
- the unmount guard: a request that fails after leaving the page still
  raises its error toast.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The console theme's rule for the save bar selected the sticky bar the
fork's page had (div.sticky.bottom-0 after the page root). Upstream's
bar is fixed to the window's bottom, so the rule matched nothing and the
bar showed upstream's translucent fill, blur and drop shadow under the
theme.

The rule now selects upstream's bar and keeps what it drew before: the
surface fill on the structural line, no shadow; the blur behind the now
opaque fill is switched off as for the header row.

Upstream starts the bar at its own 16rem sidebar (lg:left-64). The
theme's sidebar is clamp(13rem, 20vw, 15rem) wide, so from 1024px the
bar starts at the shell's sidebar width instead; without this it began
16px to 48px right of the sidebar's edge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The per-account traffic counters had writers only. Every OpenAI gateway
entry point counted its forwarded attempts in Redis, and the one reader,
GET /admin/accounts/:id/traffic-telemetry, was never called by any page.

Removed:
- the Begin and Finish calls at the seven entry points: Responses,
  Messages, Chat Completions, Embeddings, Images, alpha search and the
  Responses WebSocket;
- the observer, its Redis cache with the Lua script, the outcome decision
  table and its rules, and the snapshot handler with its route;
- the wire providers (wire_gen.go regenerated);
- OpenAIForwardResult.UpstreamTerminalStatus with its three WebSocket
  writers: only the outcome classifier read it;
- the tests of all of the above.

The six HTTP forward closures are upstream's bytes again. Slot release and
every other call around a forward keep their order; each forwarded attempt
makes two Redis round trips fewer.

The telemetry switch in the observability settings and
gateway.account_traffic_telemetry_disabled switch nothing after this
commit; the next one removes them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ts config option

With the traffic counters gone the telemetry switch switched nothing.

- The observability settings hold the flat theme switch only. GET and PUT
  /admin/settings/observability carry {"theme_enabled": <boolean>}; a PUT
  that still sends telemetry_enabled is refused like any unknown key. The
  settings panel loses the telemetry checkbox and the sentence that
  described the counters. The theme checkbox and its save are unchanged.
- gateway.account_traffic_telemetry_disabled is no longer a config key. The
  files under deploy/ still name it; the server ignores the variable.
- Migration 273 removes telemetry_enabled from the stored
  admin_observability_config row. The reader of that row is strict and a
  key it does not know stops startup. theme_enabled keeps its value.
- What was left of admin_observability.go, the switch holder and
  FlatThemeEnabled, moves into setting_admin_observability.go. The decoder
  test moves to setting_switch_load_test.go with a two-switch type of its
  own, so it still shows that an omitted switch keeps its default.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… loadUsage

cd8c18b made loadUsage remember the account id it started with and
drop the response when the cell showed another account by then. That
could happen while the details drawer reused one cell for whichever
account it displayed.

Every render site now keys the cell by account id: DataTable rows by
row-key="id" (plain rows, windowed rows, stacked cells and mobile cards),
the card grid and the compact list by the key of their v-for, and the
drawer by :key on the cell itself. An instance is never given a second
account, so the comparison was always true.

The three conditions are upstream's again: if (!unmounted.value).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex and others added 8 commits October 6, 2026 21:52
fe89731 defined __INTLIFY_JIT_COMPILATION__ for vitest so that plugin
UI tests rendered translated text, and 6cd89ee rewrote the assertions
of SubscriptionPlanCard.spec.ts to that text. Without the define the
runtime-only vue-i18n build returns the message key, which is what
upstream's spec asserts.

Both files are upstream v0.2.13's bytes again. SubscriptionPlanCard.spec.ts
is the only spec that gives a real vue-i18n instance messages to render,
so no other spec depends on the define.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…f loadRecent

Only AccountTasksView passed kind and page_size to the store's
loadRecent, and that page was deleted in 07f50b2. The callers that are
left, the history dialog and the store's own refresh, pass a page and a
status at most.

loadRecent takes { page, status } now and always asks for the page size
the server last reported. The list keeps one status filter instead of a
filters object, and AccountJobListParams no longer offers kind. The
store, layout and API specs follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The bulk bar offered "Review Duplicates" for 2 to 100 selected accounts,
but #206 (71f056d) deleted the handlers, the routes
POST /admin/accounts/duplicates/review and /merge, and the job kinds
account_duplicate_review and account_duplicate_merge. The button could
only end in a failed request.

Removed: the button and its event, handleDuplicateReview and the two
kinds named in the accounts page's job watcher, the two API functions
with their request and metadata types, the two store actions, the merge
form of AccountOperationProgress, the spec cases and mock members for
all of these, and in both locales bulkActions.duplicateReview,
accountTasks.duplicate.* and the two kind labels.

The kind labels go as well because no stored job can still carry those
kinds: nothing has been able to create one since v0.2.8-codexrip.9, and
the job runtime deletes every job 24 hours after it finishes
(AccountJobResultTTL).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ired page and status

The store's refreshDrawer has had no caller in the application since
175007b (#189); only the store spec called it. 82cce35 counted it as a
caller of loadRecent and kept the call without arguments for it: the
default parameter, the own-property check on status and the fall back to
the page last shown.

refreshDrawer and its export are deleted. loadRecent takes { page, status }
and both are required. The two callers in the application, the history
dialog and openDrawer, already pass both; their requests are unchanged.

The store spec follows:
- every loadRecent call names its page and status;
- the case that refreshed without arguments now asks for another page and
  status and still expects the page size the server last reported;
- the 404 case reaches its last assertion through the poller instead of
  refreshDrawer: one tick after the detail request answered 404, the
  cleared selection must not be fetched again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
activeCount fed the header's task badge. 5d74264 removed the badge and
nothing in the application has read the count since; two specs still did.

The computed and its export are deleted. The five assertions in the store
spec and the task drawer spec read the length of activeJobs, the list the
count was taken from.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GET /admin/account-jobs read a kind query parameter and passed it, with a
creator id that was always 0, through AccountJobService.List to the
repository, which could add kind and created_by conditions to the query.

The tasks page was the one caller that sent kind; 07f50b2 deleted the
page and 82cce35 removed kind from the frontend's list parameters. The
handler has passed 0 for the creator since the route was added, so the
created_by condition never applied.

List takes the status, the page and the page size in the handler call, the
service, the repository interface, the repository and the two test stubs.
For the requests the application sends, the SQL text and its arguments are
what they were: "1=1", or "1=1 AND status=$1".

Observable change: a kind query parameter on this route is ignored.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ance

With traffic telemetry gone the panel has one switch, the flat theme. Its
title and load-failure text no longer mention observations.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@HTExplicit
HTExplicit merged commit 815f33a into main Oct 7, 2026
18 checks passed
@HTExplicit
HTExplicit deleted the refactor/remove-plugin-era-shells branch October 7, 2026 01:52
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