Skip to content

fix(core): make indexed access explicit across remaining src (NUIA phase 3b)#104773

Merged
steipete merged 12 commits into
mainfrom
claude/nuia-src-rest
Jul 12, 2026
Merged

fix(core): make indexed access explicit across remaining src (NUIA phase 3b)#104773
steipete merged 12 commits into
mainfrom
claude/nuia-src-rest

Conversation

@steipete

Copy link
Copy Markdown
Contributor

Related: #104600

What Problem This Solves

Phase 3b of the noUncheckedIndexedAccess adoption (#104600): the remaining 669 unchecked-index errors across all of src/** outside src/agents — auto-reply, infra, config, cli, gateway, commands, security, and 20 smaller directories. With this landed, the entire core program (src + packages) is index-safe and ready for the flag flip in phase 3c.

Why This Change Was Made

Pure burn-down to zero (repo probe 669 → 0), 234 files, eight commits (including mid-flight rebases across the sqlite-sessions flip and the pre-2026.4 shim removal, whose new code was made index-safe here too). The fix ladder from prior phases applied: iteration over indexing, boundary guards on genuinely-optional input, named invariants (expectDefined), closed-key tightening.

This chunk needed real review pressure, documented here honestly:

  • The first pass mass-produced 416 expectDefined(..., "indexed value") escape hatches; a rework round eliminated every generic context (72 restructured away, 65 converted to real guards, the rest given site-specific contexts) and removed introduced casts/assertions.
  • Per-commit structured reviews then caught five genuine absence-is-legitimate bugs the pattern had created, each now fixed and test-covered: CLI --profile/route-args missing next tokens must take their existing miss paths (the "rejects missing profile value" test proves absence is input, not invariant); nested help X Y --help normalization must compare against the last positional; first-time plugin install must tolerate an absent cfg.plugins; dependency-denylist scanning must skip omitted manifest dependency sections (the guard was one line below the throw); status-scan must pass its optional params through unchanged.
  • One SDK-boundary lesson: an early fix made getChatChannelMeta honestly optional, which would have changed a shipped plugin-SDK signature (two bundled extensions consume it). Final shape preserves the SDK contract (defined for bundled ids, fail-loud on impossible misses) and adds findChatChannelMeta for the drift-tolerant core paths — reviewed clean (0.98).
  • Root-cause fixes preferred over wrappers: the tailnet resolver now guarantees string at the source (guarded first-IP) instead of a caller-side undefined-throw; PROVIDER_LABELS became a satisfies-typed closed record (static reads provably defined, dynamic lookups through an honest string | undefined helper), deleting ~10 assertions.
  • Sensitive-area equivalence: security parsers remain fail-closed; gateway event/byte ordering untouched; SQLite query shapes unchanged; config migration behavior identical.

User Impact

No behavior change on healthy paths. Plugin install, CLI parsing, and status scanning behave identically including their absence paths (now proven by types instead of convention).

Evidence

  • NUIA probe: repo 669 → 0 under the core lane; fresh non-incremental core, core-test, ui, and scripts lanes all 0 errors.
  • Blacksmith Testbox: full pnpm check + pnpm check:test-types green on the final tree; across seven battery runs every completed test file passed (thousands; the only real failures were the seven bugs fixed above), with all aborts being box-level worker/lease deaths under memory pressure — exact-head sharded CI on this PR is the complete-suite arbiter.
  • Per-commit structured reviews: parts 1–3 reviewed individually (the two "incorrect" verdicts drove the fixes above); both correction commits reviewed clean (0.96 / 0.96).
  • 173 tests across the three originally-failing CLI files now pass; plugins/status/infra suites green.

@steipete
steipete requested a review from a team as a code owner July 11, 2026 23:14
@openclaw-barnacle openclaw-barnacle Bot added app: web-ui App: web-ui gateway Gateway runtime cli CLI command changes commands Command implementations agents Agent runtime and tooling size: XL maintainer Maintainer-authored PR labels Jul 11, 2026
@steipete
steipete force-pushed the claude/nuia-src-rest branch from 58956d4 to 1ac75ce Compare July 11, 2026 23:18

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

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: 58956d4890

ℹ️ 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/crestodian/setup-inference.ts Outdated
...params.target.agents,
defaults: {
...params.target.agents?.defaults,
...expectDefined(params.target.agents?.defaults, "agent defaults"),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Badge Do not require preexisting agent defaults

When app-guided provider setup starts from a sparse/first-run config that has agents.list but no agents.defaults, provider patches from onboard helpers can add prepared.agents.defaults.models; this branch now throws on expectDefined(params.target.agents?.defaults) before the probe/persist path. The old spread created the defaults object, so this merge needs to keep treating the missing container as {}.

Useful? React with 👍 / 👎.

Comment thread src/crestodian/setup-inference.ts Outdated
}
config.models = {
...config.models,
...expectDefined(config.models, "configured models"),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Badge Do not require preexisting models config

For providers whose setup patch carries models.providers and a user's base config has no models block, findSelectedProviderConfigKey is truthy and this spread now throws instead of creating models. That aborts app-guided activation before testing the credential; keep the previous empty-object merge behavior while inserting the selected provider config.

Useful? React with 👍 / 👎.

@clawsweeper

clawsweeper Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 11, 2026, 11:45 PM ET / July 12, 2026, 03:45 UTC.

Summary
The PR completes the remaining core noUncheckedIndexedAccess burn-down by replacing unchecked indexed reads with explicit iteration, guards, or named invariants and splitting strict versus optional channel metadata lookup.

Reproducibility: yes. Source inspection gives deterministic paths for a session with no in-range usage summary and for errorBackoffMs receiving an empty schedule; both now throw where the base behavior returned a supported fallback value.

Review metrics: 1 noteworthy metric.

  • Review continuity: 4 prior blockers fixed, 1 repeated, 1 late. The final head shows substantial correction progress but still has one known blocker and one previously missed unchanged defect.

Stored data model
Persistent data-model change detected: serialized state: src/sessions/session-id-resolution.ts, unknown-truncated-pull-files. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #104600
Summary: This PR is the phase 3b implementation candidate for the canonical noUncheckedIndexedAccess adoption program.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🦪 silver shellfish
Result: blocked until real behavior proof is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P1] Restore both absence contracts and add focused regression coverage.
  • Attach redacted exact-head runtime output or logs for representative corrected paths.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR body reports tests and Testbox runs but provides no inspectable after-fix exact-head live output, logs, recording, or linked artifact; add redacted proof, update the PR body, and request @clawsweeper re-review if review does not retrigger automatically.

Risk before merge

  • [P1] Sessions without an in-range cost summary can fail the entire sessions.usage request instead of returning a nullable row.
  • [P1] An empty configured or injected cron retry schedule can throw instead of using the established default delay.
  • [P1] The 239-file behavioral-equivalence claim still lacks inspectable exact-head live output, logs, a recording, or a linked artifact.

Maintainer options:

  1. Restore both absence contracts (recommended)
    Return null session rows and keep empty custom schedules on the default-delay path, then add focused regression coverage.
  2. Split the broad phase
    Pause this landing candidate and replace it with smaller owner-boundary PRs if the remaining invariant audit cannot be completed confidently.

Next step before merge

  • [P1] Two narrow assertion-placement defects are mechanically repairable on the PR branch; contributor-supplied real behavior proof remains a separate merge gate.

Maintainer decision needed

  • Question: After the two remaining absence regressions are repaired, should this protected broad phase land intact or be split into smaller owner-boundary changes?
  • Rationale: The defects are mechanically repairable, but the maintainer-protected breadth and repeated ordinary-state regressions leave the acceptable audit and landing scope to the feature owner.
  • Likely owner: steipete — This person owns the phased rollout and the recent current-main history of the central affected surfaces.
  • Options:
    • Repair and keep the phase intact (recommended): Fix both regressions, complete the fallback audit, add focused coverage and runtime proof, then review the exact head as one phase.
    • Split by owner boundary: Separate session/gateway, cron, plugin/channel, and remaining mechanical changes if maintainers cannot confidently establish whole-branch equivalence.

Security
Cleared: No concrete security or supply-chain regression was found; dependencies, workflows, permissions, downloaded code, and secret-access policy are unchanged.

Review findings

  • [P1] Preserve null usage rows — src/gateway/server-methods/usage.ts:1597
  • [P2] Keep the empty backoff schedule fallback reachable — src/cron/service/jobs.ts:81-82
Review details

Best possible solution:

Restore the nullable session row and empty-schedule fallback contracts, audit similar assertions that precede fallbacks, add focused regression coverage, and attach redacted exact-head runtime proof before approval.

Do we have a high-confidence way to reproduce the issue?

Yes. Source inspection gives deterministic paths for a session with no in-range usage summary and for errorBackoffMs receiving an empty schedule; both now throw where the base behavior returned a supported fallback value.

Is this the best way to solve the issue?

No, not yet. The phased type-safety burn-down is appropriate, but legitimate null and fallback states must be modeled explicitly rather than converted to invariant failures.

Full review comments:

  • [P1] Preserve null usage rows — src/gateway/server-methods/usage.ts:1597
    Keep the existing nullable usage contract: sessions with no in-range cost summary leave this slot as null, so asserting it makes the whole sessions.usage request fail instead of returning the row to Usage/Profile consumers.
    Confidence: 0.99
  • [P2] Keep the empty backoff schedule fallback reachable — src/cron/service/jobs.ts:81-82
    An empty injected schedule previously selected the default first delay through the existing ?? fallback; expectDefined now throws first. This was equally visible on earlier reviewed heads and is being raised late; preserve the fallback or enforce a tested non-empty input contract.
    Confidence: 0.96
    Late finding: first raised on code an earlier review cycle already covered.

Overall correctness: patch is incorrect
Overall confidence: 0.97

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against ddbec923d4ee.

Label changes

Label justifications:

  • P1: The final head can fail ordinary session usage requests and cron retry computation rather than preserving established absence behavior.
  • merge-risk: 🚨 compatibility: New invariant assertions override existing nullable and fallback contracts used by current runtime paths.
  • merge-risk: 🚨 availability: Normal empty states can now throw and fail an endpoint or scheduled-job retry path.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🦪 silver shellfish.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body reports tests and Testbox runs but provides no inspectable after-fix exact-head live output, logs, recording, or linked artifact; add redacted proof, update the PR body, and request @clawsweeper re-review if review does not retrigger automatically.
Evidence reviewed

Acceptance criteria:

  • [P1] pnpm test src/gateway/server-methods/usage.sessions-usage.test.ts.
  • [P1] pnpm test src/cron/service.jobs.test.ts.
  • [P1] pnpm check:test-types.

What I checked:

  • Nullable usage contract: The final head passes a nullable per-session usage value through expectDefined even though sessions without an in-range summary are represented as null and UI consumers cover null usage rows. (src/gateway/server-methods/usage.ts:1597, eb376605b337)
  • Backoff fallback contract: The exported cron helper asserts the selected custom schedule entry before its existing default fallback, so an empty schedule now throws instead of returning the first default delay. (src/cron/service/jobs.ts:81, eb376605b337)
  • Re-review continuity: The cron assertion was already present and equally visible at all four earlier reviewed heads, so the finding is marked as a late discovery rather than attributed to the latest corrective commit. (src/cron/service/jobs.ts:81, 1ac75ceeeeb7)
  • Prior blocker repairs: The latest corrective commit restores optional sparse setup/config spreads that caused the earlier agent-defaults, model-config, per-agent-model, and first-hook-install findings. (src/crestodian/setup-inference.ts, eb376605b337)
  • Current-main ownership: Current main attributes the central usage, cron, and channel metadata surfaces to Peter Steinberger's recent core work, and the same person authored the staged rollout and corrective commits. (src/cron/service/jobs.ts:75, ecefc6cab69e)

Likely related people:

  • steipete: Introduced the current-main versions of the central affected files, authored the canonical phased rollout, and carried every corrective commit on this PR. (role: feature owner and recent area contributor; confidence: high; commits: ecefc6cab69e, cbb23c90fb2c, eb376605b337; files: src/gateway/server-methods/usage.ts, src/cron/service/jobs.ts, src/channels/chat-meta.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (4 earlier review cycles)
  • reviewed 2026-07-11T23:33:04.607Z sha 1ac75ce :: needs real behavior proof before merge. :: [P1] Preserve missing agent defaults during setup projection | [P1] Preserve missing per-agent models during setup projection | [P1] Preserve missing top-level models during setup projection | [P1] Allow first hook install to create internal config
  • reviewed 2026-07-11T23:56:42.119Z sha bbe409f :: needs real behavior proof before merge. :: [P1] Preserve missing agent defaults during setup projection | [P1] Preserve missing per-agent models during setup projection | [P1] Preserve missing top-level models during setup projection | [P1] Allow first hook install to create internal config | [P1] Keep the next history message optional
  • reviewed 2026-07-12T00:23:35.718Z sha eb30aca :: needs real behavior proof before merge. :: [P1] Preserve missing agent defaults during setup projection | [P1] Preserve missing per-agent models during setup projection | [P1] Preserve missing top-level models during setup projection | [P1] Allow first hook install to create internal config | [P1] Preserve custom channel metadata in the SDK base helper
  • reviewed 2026-07-12T00:50:34.426Z sha 31a233d :: needs real behavior proof before merge. :: [P1] Preserve missing agent defaults during setup projection | [P1] Preserve missing per-agent models during setup projection | [P1] Preserve missing top-level models during setup projection | [P1] Allow the first hook install to create internal config | [P1] Preserve null usage rows

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P1 High-priority user-facing bug, regression, or broken workflow. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. labels Jul 11, 2026
@steipete
steipete force-pushed the claude/nuia-src-rest branch from 1ac75ce to bbe409f Compare July 11, 2026 23:42
@openclaw-barnacle openclaw-barnacle Bot added the channel: qa-channel Channel integration: qa-channel label Jul 11, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

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: bbe409f694

ℹ️ 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/gateway/chat-display-projection.ts Outdated
}
const currentRoleContent = asRoleContentMessage(current);
const next = messages[i + 1];
const next = expectDefined(messages[i + 1], "messages entry at i + 1");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Badge Keep next history message optional

When projectChatDisplayMessages receives a non-empty projected history, the last loop iteration has no messages[i + 1]; this new expectDefined throws before the existing next ? ... : null fallback can run. That makes ordinary one-message histories, and the final message of longer histories, fail during Control UI/session-history projection instead of simply skipping the heartbeat-pair check as before.

Useful? React with 👍 / 👎.

Comment thread src/crestodian/setup-inference.ts Outdated
targetAgent.models = {
...targetAgent.models,
[params.modelRef]: structuredClone(preparedAgent.models[params.modelRef]),
...expectDefined(targetAgent.models, "agent models"),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Badge Do not require per-agent models during setup

When app-guided setup prepares per-agent model metadata, such as a Codex route pinning agentRuntime, and the user's existing agents.list entry has no models object, this spread now throws. The previous ...targetAgent.models treated the missing container as {}, so sparse existing agent configs abort after a successful probe instead of persisting the selected model/runtime metadata.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Jul 11, 2026
@steipete
steipete force-pushed the claude/nuia-src-rest branch 2 times, most recently from eb30aca to 31a233d Compare July 12, 2026 00:33

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

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: 31a233d9bd

ℹ️ 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".

modelProvider: merged.storeEntry?.modelProvider,
model: merged.storeEntry?.model,
usage,
usage: expectDefined(usage, "session usage summary"),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Badge Preserve null usage rows

When a listed session has no in-range cost summary, usageByEntryIndex remains null; the endpoint previously returned usage: null, and src/shared/usage-types.ts explicitly allows SessionUsageEntry.usage to be SessionCostSummary | null with UI coverage for null rows. This expectDefined now throws for ordinary new/empty sessions, causing sessions.usage to fail instead of returning the row to the Usage/Profile pages.

Useful? React with 👍 / 👎.

steipete added 6 commits July 12, 2026 04:35
Part 1/3 of the src NUIA phase-3b burn-down (#104600): iteration and
destructuring over index reads, boundary guards on parsed input, and
named invariants. Config path walkers bind the path head once; SQLite
migration key handling is hoisted without query-shape changes.
…curity, shared

Part 2/3: argv/token selection restructured, gateway event/attachment
invariants named, security parsers stay fail-closed (invariant
violations throw), edit-distance matrices access checked entries.
Part 3/3: channels, plugins, process, cron, plugin-sdk, media, logging,
tui, hooks, daemon, and small directories. Latent bug fixed: a tailnet
resolver could leak undefined through a string|null contract and now
fails with a descriptive local error.
Review findings: expectDefined misused where absence is a legitimate
state. CLI --profile/route-args missing next tokens take their existing
miss paths; help normalization compares --help against the last
positional again; first-time plugin install spreads absent cfg.plugins;
denylist scan iterates manifest dependency entries instead of throwing
on omitted sections; tailnet resolver returns a guaranteed string at
the source instead of a caller-side undefined throw.
…roughs

PROVIDER_LABELS becomes a satisfies-typed closed record (static reads
provably defined; dynamic lookups go through providerUsageLabel with
honest string|undefined). Status-scan overview passes its optional
params through unchanged instead of asserting them.
The original signature claimed ChatChannelMeta while leaking undefined
on bundled channel id metadata drift; three of four callers already
handled absence. The return type now says so, and the one assuming
caller falls back to the raw channel label.
steipete added 6 commits July 12, 2026 04:35
Covers the sqlite-sessions flip and auth-source-plan code that landed
mid-phase, plus the channel-validation test consuming the now honestly
optional getChatChannelMeta.
getChatChannelMeta keeps its shipped plugin-SDK signature (defined for
bundled ids, fail-loud on impossible misses); new findChatChannelMeta
carries the drift-tolerant optional contract for core auto-enable and
formatting paths.
…ed catalog lookup

qa-channel spread getChatChannelMeta over an id that is never in the
bundled catalog, shipping an empty setup meta by accident; the fail-loud
SDK accessor exposed it. The channel now declares its metadata once.
…cript tail

expectDefined wrapped messages[i + 1] whose absence on the final message
is the normal case; the adjacent ternary already handled it. Restores
the plain optional read with an explicit guard in the pair condition.
… ids again

createChannelPluginBase spreads bundled catalog meta for ANY channel id,
where absence is the normal case for external plugins; the resolver is
honestly optional again while the exported bundled-id accessor keeps the
fail-loud contract.
Fresh-setup and first-install paths (crestodian setup inference, hook
installs, agent config base, target agent models) legitimately lack the
section being rebuilt; spreading undefined is the shipped {} semantics.
Removes the remaining gratuitous assertion wraps found by tree audit.
@steipete
steipete force-pushed the claude/nuia-src-rest branch from 31a233d to eb37660 Compare July 12, 2026 03:35

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

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: eb376605b3

ℹ️ 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".

return { provider, displayName: PROVIDER_LABELS[provider], windows };
return {
provider,
displayName: expectDefined(providerUsageLabel(provider), "gemini provider usage label"),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Badge Fall back for custom Gemini usage provider labels

Because fetchGeminiUsage is exported from src/plugin-sdk/provider-usage.ts and UsageProviderId/manifest usageProviders are arbitrary strings, an external provider that reuses this helper with its own id outside PROVIDER_LABELS will now throw here after a successful quota response. That converts a valid usage snapshot into a fetch failure; keep the existing display-name fallback behavior, e.g. providerUsageLabel(provider) ?? provider or resolveProviderUsageDisplayName(provider).

Useful? React with 👍 / 👎.

@steipete
steipete merged commit 6b95f98 into main Jul 12, 2026
106 checks passed
@steipete
steipete deleted the claude/nuia-src-rest branch July 12, 2026 03:47
@steipete

Copy link
Copy Markdown
Contributor Author

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 12, 2026
…ase 3b) (openclaw#104773)

* fix(core): make indexed access explicit in auto-reply, infra, and config

Part 1/3 of the src NUIA phase-3b burn-down (openclaw#104600): iteration and
destructuring over index reads, boundary guards on parsed input, and
named invariants. Config path walkers bind the path head once; SQLite
migration key handling is hoisted without query-shape changes.

* fix(core): make indexed access explicit in cli, gateway, commands, security, shared

Part 2/3: argv/token selection restructured, gateway event/attachment
invariants named, security parsers stay fail-closed (invariant
violations throw), edit-distance matrices access checked entries.

* fix(core): make indexed access explicit across remaining src surfaces

Part 3/3: channels, plugins, process, cron, plugin-sdk, media, logging,
tui, hooks, daemon, and small directories. Latent bug fixed: a tailnet
resolver could leak undefined through a string|null contract and now
fails with a descriptive local error.

* fix(core): keep optional boundaries optional after per-commit review

Review findings: expectDefined misused where absence is a legitimate
state. CLI --profile/route-args missing next tokens take their existing
miss paths; help normalization compares --help against the last
positional again; first-time plugin install spreads absent cfg.plugins;
denylist scan iterates manifest dependency entries instead of throwing
on omitted sections; tailnet resolver returns a guaranteed string at
the source instead of a caller-side undefined throw.

* refactor(core): closed-key provider labels and honest optional passthroughs

PROVIDER_LABELS becomes a satisfies-typed closed record (static reads
provably defined; dynamic lookups go through providerUsageLabel with
honest string|undefined). Status-scan overview passes its optional
params through unchanged instead of asserting them.

* fix(channels): make getChatChannelMeta honestly optional

The original signature claimed ChatChannelMeta while leaking undefined
on bundled channel id metadata drift; three of four callers already
handled absence. The return type now says so, and the one assuming
caller falls back to the raw channel label.

* fix(core): index-safety for post-rebase main drift

Covers the sqlite-sessions flip and auth-source-plan code that landed
mid-phase, plus the channel-validation test consuming the now honestly
optional getChatChannelMeta.

* refactor(channels): split chat-meta accessors along the SDK contract

getChatChannelMeta keeps its shipped plugin-SDK signature (defined for
bundled ids, fail-loud on impossible misses); new findChatChannelMeta
carries the drift-tolerant optional contract for core auto-enable and
formatting paths.

* fix(qa-channel): own channel metadata instead of a guaranteed-undefined catalog lookup

qa-channel spread getChatChannelMeta over an id that is never in the
bundled catalog, shipping an empty setup meta by accident; the fail-loud
SDK accessor exposed it. The channel now declares its metadata once.

* fix(gateway): heartbeat projection lookahead is optional at the transcript tail

expectDefined wrapped messages[i + 1] whose absence on the final message
is the normal case; the adjacent ternary already handled it. Restores
the plain optional read with an explicit guard in the pair condition.

* fix(plugin-sdk): channel plugin factory tolerates non-bundled channel ids again

createChannelPluginBase spreads bundled catalog meta for ANY channel id,
where absence is the normal case for external plugins; the resolver is
honestly optional again while the exported bundled-id accessor keeps the
fail-loud contract.

* fix(core): spreads of optional config sections stay optional

Fresh-setup and first-install paths (crestodian setup inference, hook
installs, agent config base, target agent models) legitimately lack the
section being rebuilt; spreading undefined is the shipped {} semantics.
Removes the remaining gratuitous assertion wraps found by tree audit.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling app: web-ui App: web-ui channel: qa-channel Channel integration: qa-channel cli CLI command changes commands Command implementations gateway Gateway runtime maintainer Maintainer-authored PR merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. P1 High-priority user-facing bug, regression, or broken workflow. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: XL status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant