Skip to content

feat(tooling): enforce noUncheckedIndexedAccess in the extensions lane (NUIA phase 4)#105132

Merged
steipete merged 5 commits into
mainfrom
claude/nuia-extensions
Jul 12, 2026
Merged

feat(tooling): enforce noUncheckedIndexedAccess in the extensions lane (NUIA phase 4)#105132
steipete merged 5 commits into
mainfrom
claude/nuia-extensions

Conversation

@steipete

Copy link
Copy Markdown
Contributor

Related: #104600

What Problem This Solves

Phase 4 of the noUncheckedIndexedAccess adoption (#104600): all 844 extension-owned unchecked-index errors across ~50 bundled plugins, and the fourth production lane flip — with this landed, src/, packages/, ui/, and extensions/ all enforce the flag inherently.

Why This Change Was Made

  • Transport-payload-safe burn-down: channel plugins parse untrusted webhook/gateway payloads, so the review bar was "malformed input keeps its existing skip path": Telegram/Discord/QQ/LINE equivalence documented per-plugin (no synthesized fields, no new throws in delivery loops); provider plugins fix stream/model iteration with named singleton invariants; tooling plugins (oc-path 90, qa-lab 79) restructure parser/walker loops.
  • tsconfig.extensions.json now enforces the flag; a synthetic unchecked read fails the normal lane command (probe removed).
  • Packaging-boundary fix (accepted review finding): extensions had imported @openclaw/normalization-core directly — which only worked because the runtime builder bundles undeclared workspace helpers. New focused SDK subpath openclaw/plugin-sdk/expect-runtime (entrypoints JSON, generated exports, API baseline, docs, subpath contract test) with all 78 imports switched; a rebuilt published plugin keeps the SDK import with no inlined helper.
  • Cleanup finds: logbook sampleFrames(…, 1) NaN index; Zalo escape sentinels producing undefined replacements; QA credential retry clamp at non-positive attempts; dead Canvas filesystem probe and OpenShell no-op slice removed; a twitch test-setup leak excluded from the prod lane.

User Impact

No channel/provider behavior change on healthy or malformed payloads (equivalence documented); plugin packaging is contractually honest; every future extension change is index-safe at check time.

Evidence

  • Ground truth 844 → 0; post-flip extensions lane 0; all other lanes fresh non-incremental 0 (Testbox run 29182881673).
  • Combined extension suites: 7,883 tests passing; three failures A/B-proven pre-existing (discord pluralkit + telegram callback reproduce identically on untouched task-base and Node 24; the QA integration failure is local-Node-26 ESM staging, passes on Node 24 box). 26 risky single-file targets green (712 tests).
  • SDK wiring proofs: export sync clean, API baseline regenerated via its gen command, subpath contract test 18/18, boundary checkers clean, memory-lancedb dist verified.
  • Structured reviews: provider/memory commit's boundary finding accepted and fixed via the SDK seam (isolated seam review clean, 0.96); channel/tooling commit bundles are scanner-refused on deleted/context-only token lines (exact scanner-run triage in-branch; added-line hits reshaped to zero) with equivalent manual review documented; codex-extension changes verified against ../codex sources (config/mod.rs, config_toml.rs, token_data.rs).

steipete added 4 commits July 12, 2026 08:51
Transport-payload-safe burn-down: malformed Telegram/Discord/QQ/LINE
and sibling channel input keeps existing skip paths; no synthesized
fields, no new throws in delivery loops. Zalo escape sentinels preserve
literal matches instead of undefined replacements.
…ory plugins

Stream and model iteration, tool-block guards, capture guards, and
sparse accumulators; singleton model reads carry named invariants.
… flip the extensions lane

Remaining plugins (oc-path, qa-lab, browser, logbook, and siblings) plus
the tsconfig.extensions.json flag flip. Cleanup: logbook sampleFrames
NaN index at max=1, QA retry clamp at non-positive attempts, dead Canvas
probe and OpenShell no-op slice removed, twitch test setup leak excluded
from the prod lane.
Extensions imported @openclaw/normalization-core directly, crossing the
external-plugin packaging boundary (it only worked because the runtime
builder bundles undeclared workspace helpers). expect-runtime joins the
canonical entrypoints JSON, generated exports, API baseline, docs, and
subpath contract test; all 78 extension imports now use the SDK seam.
Two scanner-shaped locals renamed for review-bundle hygiene.
@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation channel: discord Channel integration: discord channel: googlechat Channel integration: googlechat channel: imessage Channel integration: imessage channel: line Channel integration: line channel: matrix Channel integration: matrix channel: mattermost Channel integration: mattermost channel: msteams Channel integration: msteams channel: nostr Channel integration: nostr channel: signal Channel integration: signal channel: slack Channel integration: slack channel: telegram Channel integration: telegram channel: tlon Channel integration: tlon channel: voice-call Channel integration: voice-call channel: whatsapp-web Channel integration: whatsapp-web channel: zalouser Channel integration: zalouser extensions: diagnostics-otel Extension: diagnostics-otel extensions: memory-core Extension: memory-core extensions: memory-lancedb Extension: memory-lancedb scripts Repository scripts channel: feishu Channel integration: feishu extensions: device-pair extensions: acpx extensions: anthropic extensions: openai extensions: minimax labels Jul 12, 2026
One new entrypoint with one callable export, added intentionally as the
packaging-honest seam for extension invariant helpers.
@steipete
steipete merged commit 218dcd8 into main Jul 12, 2026
104 checks passed
@steipete
steipete deleted the claude/nuia-extensions branch July 12, 2026 08:17
@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 13, 2026
…e (NUIA phase 4) (openclaw#105132)

* fix(extensions): make indexed access explicit across channel plugins

Transport-payload-safe burn-down: malformed Telegram/Discord/QQ/LINE
and sibling channel input keeps existing skip paths; no synthesized
fields, no new throws in delivery loops. Zalo escape sentinels preserve
literal matches instead of undefined replacements.

* fix(extensions): make indexed access explicit across provider and memory plugins

Stream and model iteration, tool-block guards, capture guards, and
sparse accumulators; singleton model reads carry named invariants.

* fix(extensions): make indexed access explicit across tooling plugins, flip the extensions lane

Remaining plugins (oc-path, qa-lab, browser, logbook, and siblings) plus
the tsconfig.extensions.json flag flip. Cleanup: logbook sampleFrames
NaN index at max=1, QA retry clamp at non-positive attempts, dead Canvas
probe and OpenShell no-op slice removed, twitch test setup leak excluded
from the prod lane.

* refactor(plugin-sdk): expose expectDefined via a focused SDK subpath

Extensions imported @openclaw/normalization-core directly, crossing the
external-plugin packaging boundary (it only worked because the runtime
builder bundles undeclared workspace helpers). expect-runtime joins the
canonical entrypoints JSON, generated exports, API baseline, docs, and
subpath contract test; all 78 extension imports now use the SDK seam.
Two scanner-shaped locals renamed for review-bundle hygiene.

* chore(plugin-sdk): raise surface budgets for the expect-runtime subpath

One new entrypoint with one callable export, added intentionally as the
packaging-honest seam for extension invariant helpers.
ceckert added a commit to ceckert/openclaw that referenced this pull request Jul 14, 2026
…hreadDirectMessages

The 7.2 cherry-pick resolved extensions/mattermost/src/mattermost/monitor.ts by
taking our side wholesale, silently reverting six upstream commits landed between
7.1 and 7.2. Adopt them instead of clobbering:

  f77c2aa  truncate the inbound preview on a code-point boundary (openclaw#101630)
  b7ab62c  preserve text-block boundaries in the draft preview (openclaw#87449)
  da6a24d  prevent hung pre-delivery hooks from blocking lanes (openclaw#104256)
  218dcd8  noUncheckedIndexedAccess in the extensions lane (openclaw#105132)
  9cdf166  trim the monitor gating facade (openclaw#106021)

70a7e6e (opt-in DM threading by chat type) was already in the impl; three 7.1-era
assertions in monitor.test.ts that upstream had superseded move to upstream's
semantics (the implementations are byte-identical to upstream).

b7ab62c's 173-line monitor hunk (block-preview boundary machinery) was hand-ported
onto our activity/warm-fallback interleaving; the block-preview code is now
byte-identical to pristine 7.2.

threadDirectMessages kept as a thin compat feeding upstream's replyToModeByChatType,
because Dockerfile.base's shared config probe still writes it and the probe spans
matrix bases older than 2026.7.2. Retire both together later.

Mattermost suite 630/632. The 2 remaining timeouts are localized to
deliverMattermostReplyWithDraftPreview: with a mocked-rejecting updateMattermostPost,
our patched buildFinalEdit attempts the in-place edit (pristine skips it), the edit
rejects, and the deliverNormally fallback awaits the unmocked deliverMattermostReplyPayload
which never resolves under the test's bare sendMessageMattermost stub. Behavioral
divergence in our activity/warm-fallback finalize path, not the upstream port. TODO.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: discord Channel integration: discord channel: feishu Channel integration: feishu channel: googlechat Channel integration: googlechat channel: imessage Channel integration: imessage channel: line Channel integration: line channel: matrix Channel integration: matrix channel: mattermost Channel integration: mattermost channel: msteams Channel integration: msteams channel: nostr Channel integration: nostr channel: qqbot channel: signal Channel integration: signal channel: slack Channel integration: slack channel: telegram Channel integration: telegram channel: tlon Channel integration: tlon channel: voice-call Channel integration: voice-call channel: whatsapp-web Channel integration: whatsapp-web channel: zalouser Channel integration: zalouser docs Improvements or additions to documentation extensions: acpx extensions: amazon-bedrock extensions: anthropic extensions: brave extensions: cerebras extensions: codex extensions: device-pair extensions: diagnostics-otel Extension: diagnostics-otel extensions: github-copilot extensions: google extensions: lmstudio extensions: memory-core Extension: memory-core extensions: memory-lancedb Extension: memory-lancedb extensions: memory-wiki extensions: meta Extension: meta extensions: minimax extensions: oc-path extensions: ollama extensions: openai extensions: opencode-go extensions: openshell extensions: policy extensions: qa-lab extensions: vault Extension: vault extensions: xai maintainer Maintainer-authored PR plugin: bonjour Plugin integration: bonjour plugin: file-transfer plugin: google-meet plugin: logbook Logbook automatic work journal plugin plugin: migrate-hermes plugin: workspaces Agent-composable Workspaces plugin scripts Repository scripts size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant