fix(signal): start accounts with spaced keys without Doctor (#145750)
## What Problem This Solves
Signal lists `Work Phone` as `work-phone` but misses its authored number/endpoint. Fresh startup reports unconfigured and never contacts that endpoint until Doctor renames the key. Runtime must work without the #138982 cleanup.
## Why This Change Was Made
The decision 'which stored key serves Signal account id X' is made by exactly one mechanism at `src/routing/account-lookup.ts:94`.
Signal declares its rule once in manifest metadata: exact keys win; normalized aliases use authored settings only with a nonempty own number. The task owner accepted own-number transport/settings, whole-root inheritance for aliases without a number, exact collision winners, and Doctor refusing cleanup that activates ignored settings.
Setup preserves restrictions in the canonical default row, even when empty, and restores its number to root. Promotion targets the runtime winner. The second correction removes command singleton/writer raw-key bypasses: selector-owned optional creation; existing selection for delete/clear. Global owner authority stays separate.
## User Impact
Own-number aliases start at their authored endpoint without Doctor. Root inheritance, exact winners and other channels' maps remain stable; adding an account preserves the active account's inherited credentials. No config keys, schema or protocol versions change. Public SDK exports remain. Code `8828dc61b2da6d7ed02b8765080ed8f474ae2567`: 76 files (+1,941/-360) against e76.
Credit: @marmar9615-cloud for the report; adversarial review found the incomplete repair.
## Evidence
Eight runtime scenarios cover both status paths, 35 startup cases and allowed/excluded senders across setup, reload and restart.
| Fresh alias, no Doctor | Pinned base `3f75b33d67` | Candidate `d4e41539b2aee717e105be61522463d76ad74490` |
|---|---|---|
| Both status paths: configured/running | false/false | true/true; connected |
| Authored endpoint | No requests | Account event stream |
Published v2026.9.4 CLI updated isolated authentic old state to merge `174bdff8057e193b01b3bf63ef969a5f676d737d`, exited 0, and a new Gateway passed both status paths/events. Independent acceptance verified the new process and cleanup. That cell permits updater Doctor; the fresh cell does not. Review of 134 later paths supports applicability through actual historical CI merge `4d2cdb6527d9b3e42f4f7085703a20f358b66c01`. Separate package `20090983b5683ff352ed31e50a15143468913084` is not that CI merge.
## Compatibility
| Consumer | Host/operation | Observed result |
|---|---|---|
| Published Signal 2026.9.4 npm artifact; API floor 2026.9.4 | Released 2026.9.4; install/canonical startup/both status paths | External plugin/events pass |
| Same published artifact | Candidate core; same flow | External source/host peer link pass |
| Matching candidate Signal/core | Fresh spaced account, optional Doctor, setup/reload/restart | Retained controls pass |
| Published v2026.9.4 CLI/authentic old state | Actual update/final driver output/new candidate process | Pass, including independent acceptance |
Preflights remain failed: `34683985589` found 1,113 native translation-ID mismatches; `34684811000` fixed those but found 126 different mismatches plus UI fallback drift. Neither compiled declarations. Focused `34686128844` passed candidate compilation but failed released Node-type enrollment; `34686394191` fixes only that environment and passes both. Sealed source/producer hashes remain; no locale source/release guard changed.
Unpublished candidate Signal imports a new SDK export and cannot run on 2026.9.4 SDK; this pairing is neither published nor claimed. Official release sync raises its API floor to matching host before publication; no fallback selector/invented release version.
## Consumers
Grouped paths use braces to enumerate exact filenames; no wildcard is implied.
Paths cover readers, writers, delivery/status, SDK facades and tests. Facades retain public signatures and delegate to the shared owner; their directory does not imply channel-specific use. Tests and Compatibility record execution and the published/candidate matrix. The pinned base `3f75b33d67` has 299 successful queries across 394 files. Historical CI integration `4d2cdb6527d9b3e42f4f7085703a20f358b66c01` has 147 queries across 401 files (2,385 references, 1,826 positions); its parents are main `67e1a8b0f2` and PR `ec1b82bc0c`. The correction at `8cbd800e3d` adds a 12-query supplement across 242 files (836 references, 767 positions) and two predecessor-local queries. All resolve. These supplements are source evidence, not a replacement CI-merge census. Complete raw outputs and omitted-project coverage are retained; scripts queries close the packed-consumer route and manual edges cover native assets and registrations.
Historical `census.json` stays bound to340. New `census-8828dc6-reviewed-row.json` uses the same pinned base and CI run34688444368 checkout `9fcd956a0f3dad9caed524a55968dbbc19f3346d`, tree `00e4c42d2982b3745f7db6175918155fcef51754`, main parent `cb25f00e24`; second parent is882 above. Prior5b census is preserved. Source-query applicability is separate from CI execution.
### Signal, shared owners, writers and final consumers
- `extensions/signal/api.ts` — Retained public operation export; transport writes use the selected key.
- `extensions/signal/config-doctor-api.ts` — Retained Doctor/compatibility registration; repair owner supplies persisted cleanup.
- `extensions/signal/runtime-api.ts` — Retained generic config/setup runtime exports; selection stays with shared owners.
- Under `extensions/signal/src/` (relative paths):
- `account-key-repair.ts` — Changed Doctor eligibility to selected-key lookup; collision enumeration only reports.
- `account-selection.ts` — Adapter passes manifest policy/routing normalizer to resolveAccountKey; resolveSignalAccountEntry projects that key. No selection loop.
- `accounts.ts` — Changed merged account/reply-mode reads to the shared selector with Signal policy.
- `channel.ts` — Retained registered threading/outbound calls with Signal channel/account identity.
- `config-compat.ts` — Removed normalized-first selector; exhaustive migration reads winners through Signal adapter.
- `config-schema.ts` — Changed default selection; validation still checks every authored row.
- `doctor.ts` — Retained preview hook delegates warnings to key-repair owner; no selection.
- `monitor.ts` — Retained receive/reply flow; threading/chunk reads use selected fields.
- `send.ts` — Retained outbound formatting; Markdown uses selected account.
- `setup-core.ts` — Changed selection/policy forwarding; default restoration keeps canonical winner/settings.
- `setup-transport.ts` — Changed reserved-port/transport reads and writes to runtime-selected key.
- `shared.ts` — Changed scoped adapter forwards Signal policy to runtime/writers; operation ownership stays.
- `extensions/signal/src/monitor/event-handler.ts` — Retained inbound reply/reaction/group policies use runtime-selected account.
- `extensions/signal/src/monitor/inbound-context.ts` — Retained inbound context consumes selected policy from shared owner.
- `scripts/fixtures/packed-plugin-sdk-setup-consumer.ts` — Identical released/candidate fixture calls promotion, setup/setup-runtime patch and allowFrom with full inline adapters/contextual callbacks. Compile results: Tests.
- `scripts/plugin-sdk-surface-report.mts` — Retained SDK budget/report owner; approved delta covers selector exports. No account state.
- `scripts/release-check.ts` — Copies both trusted-tooling fixtures, installs/compiles separate released/candidate consumers; packed smoke invokes/cleans up. Query success is not compilation.
- `src/agents/embedded-agent-runner/{compaction-session-execution.ts,run/attempt-history-prepare.ts}` — Retained history consumers use selected settings before unchanged truncation.
- `src/agents/embedded-agent-runner/history.ts` — Changed history-limit selection; precedence stays.
- `src/agents/{embedded-agent-runner/{model.configured-fallback.ts,model.configured-overrides.ts,model.inline-provider.ts,model.registry-resolution.ts},model-discovery-normalize.ts,provider-attribution.ts,provider-request-config.ts}` — Retained provider metadata readers/types; existing owner facts, not channel policy map.
- `src/agents/identity.ts` — Changed reaction/prefix reads to channel-aware selection.
- `src/agents/runtime-capabilities.ts` — Retained capability projection consumes selected account from shared owner.
- `src/{agents/embedded-agent-runner/model.static-catalog.ts,cli/{plugins-authoring-command.ts,plugins-feature-artifact.ts},commands/models/provider-aliases.ts,gateway/control-ui-plugin-assets.ts,plugins/{bundled-sources.ts,install.runtime.ts}}` — Retained plugin/provider/artifact manifest fields; no Signal key selection or policy interpretation.
- `src/agents/subagents/spawn/acp-spawn-parent-stream.ts` — Changed parent progress-stream selection.
- `src/auto-reply/chunk.ts` — Changed chunk size/mode reads carry channel identity.
- `src/auto-reply/command-auth.ts` — Changed explicit/default/sole fallback allowlists select through owner; no raw singleton return. Authorization/global-owner policy stays.
- `src/auto-reply/reply/block-streaming.ts` — Changed coalesce-setting selection.
- `src/auto-reply/reply/reply-threading.ts` — Changed generic reply-mode selection; registered Signal threading passes explicit policy.
- `src/channels/account-config-enabled.ts` — Changed enabled read uses selected entry.
- `src/channels/draft-streaming-chunking.ts` — Changed draft-stream chunk selection.
- `src/channels/join-intro/report-channel-room-join.ts` — Changed join-intro selection.
- Under `src/channels/plugins/` (relative paths):
- `account-config-mutation.ts` — Active channels.add: normalize ID → shared promotion with execution adapter → applyAccountConfig. Existing lifecycle/config owners commit.
- `account-helpers.ts` — Changed factory forwards channel key to shared merge; explicit normalizer stays.
- `config-helpers.ts` — Changed enable creation uses owner-derived destination; delete/clear require selected existing key. No rejected raw-row fallback; unrelated entries stay.
- `config-write-policy-shared.ts` — Changed configWrites selection before authorization.
- `helpers.ts` — Changed DM guidance uses selected policy/stored path.
- `read-only.ts` — Changed manifest-only reader uses selected record policy, never another snapshot owner.
- `setup-adapter.types.ts` — Extended optional setup policy; existing implementations valid.
- `setup-contract.ts` — Extended setup contract forwards policy to execution adapter.
- `setup-helpers.ts` — Changed name/patch/promotion writes use selected spelling. Sole/default inference cannot restore rejected aliases; full-adapter and metadata-only inputs stay.
- `setup-promotion-discovery.ts` — Retained lightweight discovery forwards promotion/policy declarations; no key selection.
- `setup-promotion-helpers.ts` — Derives five promotion fields from ChannelSetupAdapter; duplicate callback shape removed. Owns movable fields/root preservation/named filtering, not destination selection.
- `setup-wizard-helpers.ts` — Changed patch/allowFrom pass full adapter or derived promotion metadata into shared writing/promotion; destination is owner-selected.
- `setup-wizard-legacy-compat.ts` — Active legacy wizard delegates policy/scoped patches to shared patch/promotion.
- `setup-wizard-types.ts` — Retained setup type carries optional policy.
- `setup-wizard.ts` — Active wizard promotes via owner, temporarily sets legacy defaultAccount, then restores operator default. Temporary scope does not select stored winners.
- `types.adapters.ts` — Retained type barrel; public adapter identity stays.
- `types.plugin.ts` — Retained plugin shape and setup ownership.
- `src/channels/status/account-state.ts` — Retained disabled-state check agrees with runtime selection.
- `src/cli/plugin-install-config-policy.ts` — Historical recovery-metadata caller now delegates manifest/request planning to src/plugins/install-config.ts; no account selection.
- `src/commands/doctor-config-flow.ts` — Retained Doctor binding orchestration delegates selection to repair owner.
- `src/commands/doctor/shared/legacy-config-binding-repair.ts` — Changed binding lookup; Doctor retains persistence.
- `src/commands/doctor/shared/plugin-metadata-snapshot-scope.ts` — Retained metadata rebase refreshes policy within its scope.
- Under `src/config/` (relative paths):
- `channel-account-config.ts` — Shared merge forwards normalizer/channel/policy to one key decision; precedence stays.
- `channel-alias-migration.ts` — Retained migration uses selected inherited-stream account.
- `channel-capabilities.ts` — Changed capability selection.
- `channel-doctor-helpers.ts` — Changed inherited-stream selection; full-map migration stays exhaustive.
- `channel-groups.ts` — Changed merged-group read carries channel identity.
- `context-visibility.ts` — Changed context-visibility selection.
- `group-policy.ts` — Changed group path/policy selection before field precedence.
- `group-scope-tree.ts` — Retained group-tree consumer of selected data.
- `implicit-mentions.ts` — Changed implicit-mention selection.
- `io.plugin-metadata.ts` — Retained config metadata rebase refreshes policy with existing facts.
- `markdown-tables.ts` — Changed table-mode read carries channel identity.
- `zod-schema.providers-whatsapp.ts` — Retained WhatsApp-only schema lookup; undeclared policy preserves old behavior.
- `src/cron/delivery-channel-validation.ts` — Changed enabled selection before delivery validation.
- `src/gateway/server-channels.ts` — Changed health-setting selection; undeclared compatibility forms stay and agree under declared policy. Manager still owns startup/runtime state.
- `src/gateway/server-chat.ts` — Retained heartbeat visibility consumer of selected policy.
- `src/gateway/server-runtime-state-prepare.ts` — Retained manager construction; startup/runtime state owner stays.
- `src/gateway/server-secrets-reload.ts` — Retained secrets-reload manager contract; no selector.
- `src/infra/event-session-routing.ts` — Changed event allowlist selection before routing.
- `src/infra/heartbeat-runner-execution.ts` — Retained heartbeat execution consumes visibility owner.
- `src/infra/heartbeat-visibility.ts` — Changed heartbeat policy selection.
- Under `src/infra/outbound/` (relative paths):
- `deliver-core.ts` — Retained outbound chunk caller carries channel identity.
- `message-account-selection.ts` — Retained disabled check agrees with runtime selection.
- `message-action-params.ts` — Retained media-limit consumer of selected account.
- `message-action-send.ts` — Retained response-prefix consumer of selected identity.
- `src/media/configured-max-bytes.ts` — Changed media-limit selection.
- Under `src/plugin-sdk/` (relative paths):
- `{account-core.ts,account-helpers.ts,account-resolution-runtime.ts,account-resolution.ts,agent-runtime.ts,channel-core.ts,channel-feedback.ts,channel-ingress-runtime.ts,channel-outbound.ts,channel-plugin-common.ts,config-runtime.ts,context-visibility-runtime.ts,discord.ts,markdown-table-runtime.ts,reply-chunking.ts,reply-dispatch-runtime.ts,reply-runtime.ts,routing.ts,runtime-doctor-migrations.ts,setup-runtime.ts,setup.ts}` — Retained public SDK facades/types and argument/declaration identities; typed export/local-binding queries cover forwarding.
- `allowlist-config-edit.ts` — Changed allowlist destination selection; persistence/validation owners stay.
- `channel-config-helpers.ts` — Extended adapter/factory policy forwarding to enable/delete/setup writers.
- `channel-dm-policy.ts` — Active DM getCurrent resolves account; setPolicy computes policy/allowFrom and invokes applyPatch or patchChannelConfigForAccount(setupSurface). Descriptive resolveConfigKeys keeps canonical IDs and has no production caller; live writer is active.
- `channel-policy.ts` — Retained security exports/account wrappers; separate open-group severity change is not selection.
- `channel-setup.ts` — Retained setup exports/types/missing-plugin builder; missing adapters reject writes.
- `core.ts` — Retained exports and active security wrapper forward channelKey/policy to DM path owner.
- `optional-channel-setup.ts` — Retained missing-plugin guidance; applyAccountConfig throws before account selection/mutation.
- Under `src/plugins/` (relative paths):
- `bundled-channel-config-metadata.ts` — Retained manifest-bearing loader; no account/winner selection.
- `bundled-plugin-metadata.ts` — Retained complete manifest transport; optional policy is not interpreted.
- `discovery.ts` — Retained full PluginManifest transport; policy derivation downstream.
- `discovery.types.ts` — Retained optional bundledManifest type accepts added metadata.
- `manifest-capability-normalizers.ts` — Retained providerAuthAliases type use, unrelated to account policy.
- `manifest-registry.ts` — Changed record builder preserves parsed policy; transport stays.
- `manifest-registry.types.ts` — Retained manifest-derived types/record transport carry optional metadata.
- `manifest-setup-normalizers.ts` — Validates declared channel/field shape, drops blocked keys and emits metadata; no account-map selection.
- `manifest-types.ts` — Added optional channel-owned manifest policy.
- `manifest.ts` — Changed parser adds normalized policy; existing fields stay.
- `plugin-cache-files.types.ts` — Retained parsed-manifest cache type; lifecycle invalidation stays.
- `plugin-metadata-snapshot.ts` — Changed installed-index owner-map derivation; existing rebase/project/load lifecycle rebuilds policy.
- `plugin-metadata-snapshot.types.ts` — Added optional derived map; provider-reader fields stay.
- `provider-model-compat.ts` — Retained provider-owner map reader; no channel-policy use.
- `src/plugins/contracts/inventory/bundled-capability-metadata.ts` — Retained type/setup/provider-env projection; no account-policy interpretation.
- `src/plugins/runtime/runtime-channel.ts` — Retained chunk/format runtime facade carries channel identity.
- `src/plugins/runtime/types-channel.ts` — Retained runtime type projection; arguments compatible.
- `src/routing/account-lookup.ts` — Entry helpers delegate to key owner. Declared policy gates aliases and optional allowMissing canonical creation; undeclared raw creation stays.
- `src/status/status-text.ts` — Retained Telegram-only rich-message lookup; Signal cannot reach it.
- `src/system-agent/plugin-artifact.ts` — Retained artifact identity/capability reader; incoming consolidation changes lazy config-owner import, not manifest interpretation.
### Retained non-Signal production consumers
Bundled non-Signal manifests omit Signal eligibility. Existing case-only/normalized reads and ordinary scoped/name/cleanup writes remain. Promotion now writes to the runtime exact-key winner; maps need not stay identical. Groups name readers, writers, delivery and forwarding files.
- `extensions/a2a/src/channel-base.ts` — Retained a2a fixed-root setup; no named account selection.
- `extensions/buzz/src/{gateway.ts,setup-core.ts,types.ts}` — Retained Buzz factory/Markdown delivery; setup preserves root during promotion.
- `extensions/clickclack/src/{accounts.ts,setup-core.ts}` — Retained exact-first normalized reader; registered promotion moves root credentials into runtime winner, preserving active account. Tests covers account-add.
- `extensions/discord/src/{accounts.ts,draft-chunking.ts,monitor/{agent-components.dispatch.ts,agent-components.runtime.ts,message-handler.context.ts,message-handler.process-reactions.ts,message-handler.process-reply-runtime.ts,native-command-agent-reply.ts,native-command-status.ts,native-command.ts,provider.ts},outbound-text.ts,send.outbound.ts,setup-adapter.ts,setup-core.ts,setup-surface.ts,shared.ts,token.ts}` — Retained case-only account/token reads, scoped setup/config, chunk/group/context/ack/outbound. Local calls bind Discord; generic runtime facade and lazy dispatch census stay.
- `extensions/feishu/{runtime-api.ts,src/{accounts.ts,bot.ts,channel.ts,comment-dispatcher.ts,outbound.ts,policy.ts,reply-dispatcher.ts,send.ts,setup-core.ts,setup-surface.ts}}` — Retained account/group/context, scoped setup/config, outbound/formatting. Local calls bind Feishu; generic exports, channel-only Markdown and account chunks stay.
- `extensions/googlechat/src/{accounts.ts,channel-base.ts,monitor-reply-delivery.ts,setup-core.ts,setup-surface.ts}` — Retained factory/setup/channel adapters; reply chunks receive resolved account; writes bind googlechat.
- `extensions/imessage/src/{accounts.ts,monitor/{deliver.runtime.ts,deliver.ts,inbound-processing.ts,monitor-provider.ts},send.ts,setup-core.ts,shared.ts}` — Retained factory/scoped writers/send/monitor. Chunk/ack/context bind iMessage; generic runtime forwarding stays.
- `extensions/irc/src/{accounts.ts,channel.ts,message-adapter.ts,send.ts,setup-core.ts}` — Retained factory/hybrid config/setup/send/message adapter; destructured chunks receive irc/accountId; no Signal policy.
- `extensions/line/{runtime-api.ts,src/{accounts.ts,bot-handlers.ts,config-adapter.ts,gateway.ts,group-keys.ts,outbound.ts,setup-core.ts}}` — Retained account/group/scoped writers/ingress/outbound; local calls bind line; generic exports and optional chunk limit stay.
- `extensions/matrix/src/{account-selection.ts,config-adapter.ts,matrix/{account-config.ts,monitor/{ack-config.ts,handler-context.ts,handler.ts},send/chunking.ts},setup-config.ts,setup-core.ts}` — Retained normalized selection/merge/writers/ack/context/formatting. Logical callback target resolves to runtime winner before promotion; Matrix owns bootstrap.
- `extensions/mattermost/{runtime-api.ts,src/{channel-config-shared.ts,mattermost/{accounts.ts,monitor-activation.ts,monitor-event-plan.ts,monitor-posts.ts,monitor-turn.ts,reply-delivery.ts,send.ts,slash-http.ts},setup-core.ts,setup-surface.ts}}` — Retained account/config/scoped setup/monitor/group/ack/outbound. Local calls bind mattermost/resolved account; generic exports stay.
- `extensions/msteams/src/{messenger.ts,monitor-handler/message-handler.ts,monitor.ts,reply-dispatcher.ts,send.ts,setup-core.ts}` — Retained Teams setup/context/ack/send/formatting; channel-only calls remain without new account argument or Signal policy.
- `extensions/nextcloud-talk/src/{accounts.ts,channel.adapters.ts,gateway.ts,send.runtime.ts,send.ts,setup-core.ts}` — Retained factory/scoped writers/gateway/send bind nextcloud-talk; send.runtime remains generic facade.
- `extensions/nostr/src/{gateway.ts,setup-adapter.ts,types.ts}` — Retained factory/setup/Markdown; both gateway calls keep their resolved account IDs.
- `extensions/qa-channel/src/{accounts.ts,channel-base.ts}` — Retained synthetic factory/fixed channel contract; no Signal policy.
- `extensions/raft/src/{accounts.ts,setup.ts}` — Retained factory/channel-bound setup/promotion; no Signal policy.
- `extensions/reef/src/setup.ts` — Retained fixed-channel setup/promotion declarations.
- `extensions/slack/src/{accounts.ts,actions.ts,config-adapter.ts,message-action-dispatch.ts,monitor/{config.runtime.ts,message-handler/{dispatch.ts,prepare.ts},provider.ts,slash-dispatch.runtime.ts,slash.ts},send.ts,setup-core.ts,setup-shared.ts,setup-surface.ts}` — Retained account/config/scoped setup/actions/ingress/send; slash chunk/Markdown bind slack/route.accountId; generic facades stay.
- `extensions/sms/src/{accounts.ts,channel.ts}` — Retained SMS-bound factory/channel account/config contract.
- `extensions/synology-chat/src/{accounts.ts,channel.ts,setup-surface.ts}` — Retained Synology factory/channel/setup binding and promotion.
- `extensions/telegram/{runtime-api.ts,src/{account-config.ts,account-selection.ts,bot-handlers.message-pipeline.ts,bot-message-context.session.ts,bot-message-context.ts,bot-message-dispatch.runtime.ts,bot-message-dispatch.ts,bot-message.ts,bot-native-command-dispatch.ts,bot-native-commands.runtime.ts,channel.ts,config-adapter.ts,draft-chunking.ts,send-edit.ts,send-message.ts,send.runtime.ts,setup-core.ts,setup-surface.helpers.ts,setup-surface.ts,text-chunk-limit.ts,token.ts}}` — Retained normalized account/token, scoped writers, message/native context, drafts/send/formatting. Calls bind telegram; generic facades/root-default precedence/token promotion stay.
- `extensions/tlon/src/{channel.ts,monitor/utils.ts,setup-core.ts,types.ts}` — Retained factory/hybrid config/scoped setup/name/monitor mentions bind tlon; URL/code promotion stays.
- `extensions/twitch/src/{config.ts,setup-surface.ts,token.ts}` — Retained normalized account/token/root-first default and scoped setup; access-token promotion stays.
- `extensions/whatsapp/src/{account-config.ts,account-ids.ts,auto-reply/{config.runtime.ts,monitor/{inbound-dispatch.ts,process-message.ts,runtime-api.ts}},send.ts,setup-core.ts,shared.ts}` — Retained listing/merge/account-only writers; alwaysUseAccounts/authDir promotion stays. Context/chunk/Markdown bind whatsapp; one inbound text-limit call still omits accountId; generic exports stay.
- `extensions/zalo/{runtime-api.ts,src/{accounts.ts,channel.ts,monitor.ts,setup-core.ts,test-support/lifecycle-test-support.ts,token.ts}}` — Retained factory/case-only token/scoped writers/monitor formatting bind zalo; generic setup exports stay.
- `extensions/zalouser/src/{accounts.ts,channel.adapters.ts,monitor.ts,setup-core.ts,setup-surface.ts,shared.ts}` — Retained profile factory/scoped writers/group-path/chunks bind zalouser/resolved account; empty extra promotion-key declaration stays.
- `extensions/clickclack/src/{channel.ts,channel.setup.ts,setup-core.test.ts}` — Both registered surfaces install ClickClack setup contract; account-add regression preserves exact ops credential (Tests).
- `extensions/matrix/src/setup-contract.ts` — Logical callback target is resolved by shared owner before inheritance copy; callback does not write map.
### Test and fixture consumers
These contract/test-support files assert behavior through production owners; none selects production stored keys. Tests records changed assertions, registered entry points, runtime proof and incomplete checks. Listing a retained test does not claim it was rerun.
- Signal: `extensions/signal/{doctor-contract-api.test.ts,src/{account-policy.test.ts,setup-transport.test.ts}}`.
- Other channel tests and fixtures: `extensions/{feishu/src/delivery-trace.test.ts,matrix/src/{channel.setup.test.ts,delivery-trace.test.ts,matrix/monitor/replies.formatting.test.ts},mattermost/src/delivery-trace.test.ts,msteams/src/delivery-trace.test.ts,slack/src/channel-actions-setup-status.contract.test.ts,telegram/src/{bot-native-command-executors.test-support.ts,bot-native-commands.test-helpers.ts,send.test-harness.ts,setup-surface.test.ts}}`.
- Agent tests and fixtures: `src/agents/{agent-command.compaction.test-support.ts,agent-command.live-model-switch.test.ts,ai-transport-runtime-host.test.ts,conversation-capability-profile.test.ts,embedded-agent-runner/{compact.hooks.harness.ts,history.test.ts,run/runtime-preparation.thinking.test.ts},identity.per-channel-prefix.test.ts,identity.test.ts,model-catalog-view.test.ts,models-config.providers.implicit.discovery-scope.test.ts,provider-auth-aliases.test.ts,provider-request-config.test.ts}`.
- Shared account, config and SDK tests: `src/{auto-reply/{chunk.test.ts,reply/commands-allowlist.test.ts},channels/plugins/{account-config-mutation.test.ts,account-helpers.test.ts,account-key-policy.test.ts,config-helpers.test.ts,helpers.test.ts,read-only.test.ts,setup-contract.test.ts,setup-helpers.test.ts,setup-promotion-helpers.test.ts,setup-wizard-helpers.test.ts,setup-wizard.test.ts},config/{channel-capabilities.test.ts,context-visibility.test.ts,group-policy.test.ts,implicit-mentions.test.ts,markdown-tables.test.ts},plugin-sdk/{channel-config-helpers.test.ts,channel-outbound.draft-chunking.test.ts,test-helpers/plugin-runtime-mock.ts},routing/account-lookup.test.ts}`.
- Command, Gateway and delivery tests: `src/{commands/{agents.providers.test.ts,channels.add.test.ts,channels.adds-non-default-telegram-account.test.ts,channels.remove.test.ts,doctor-config-flow.missing-default-account-bindings.integration.test.ts},flows/bundled-health-checks.test.ts,gateway/{server-channels.approval-bootstrap.test.ts,server-channels.test.ts,server-chat.agent-events.test.ts,server-methods/channels.start.test.ts,server-plugin-reload.activation.test-support.ts,server-plugin-reload.recovery.test-support.ts,server-plugin-reload.recovery.test.ts,server-plugin-reload.suspension.test-support.ts,server-reload-channel-restart.test.ts,server-reload-handlers.test.ts,server.chat.gateway-server-chat-b.test.ts},infra/heartbeat-visibility.test.ts}`.
- Metadata and release tests: `{src/plugins/{bundled-plugin-categories.test.ts,bundled-plugin-metadata.test.ts,contracts/runtime-import-side-effects.contract.test.ts,dashboard-capabilities.test.ts,loader.prefer-over.test.ts,manifest-backup-resources.test.ts,manifest-categories.test.ts,manifest-control-ui.test.ts,manifest-metadata-scan.test.ts,manifest-model-catalog.test.ts,manifest-registry-installed.test.ts,manifest-transcript-sources.test.ts,manifest.json5-tolerance.test.ts,manifest.reserved-id.test.ts,plugin-metadata-account-key-policies.test.ts,plugin-metadata.test-support.ts,plugin-policy-id.test.ts,provider-model-compat.prepared.test.ts,provider-model-routes.installed.test.ts},test/release-check.test.ts}`.
### Manual strings, registration and final pipeline edges
- Under `extensions/signal/src/` (relative paths):
- `aliases.ts` — Retained aliases consume resolved Signal account.
- `{approval-auth.ts,approval-native.ts,approval-handler.runtime.ts}` — Retained account-scoped approval auth/capability/handling; existing owner retains approval authority.
- `{message-actions.ts,reaction-level.ts,send-reactions.ts}` — Retained action/reaction policy/RPC use selected account; no alternate key choice.
- `{rpc-context.ts,signal-ingress.ts,client.ts}` — Selected number/endpoint reach ingress/RPC/event URL; recording endpoint proves final handoff.
- `setup-surface.ts` — Retained setup status reads resolved account.
- `src/{gateway/server-methods/channels.ts,commands/channels/status.ts}` — Registered RPC/CLI status consume manager/adapters; UI/native receive canonical runtime maps, not authored maps. Both entrypoints have runtime proof.
- `src/commands/channels/add.ts` — Registered account-add calls account-config-mutation/shared promotion before persistence; Tests covers absent-default regression.
- `scripts/fixtures/packed-plugin-sdk-type-smoke.ts` — Relative import includes copied setup fixture in candidate smoke; same release-check copy owner.
- `test/scripts/release-check.test.ts` — Generated string calls fixture generator from separate tooling checkout; both copies checked against stale target fixtures.
- `.github/workflows/openclaw-npm-preflight.yml` — Four sparse tooling roots include scripts/both fixtures; copy owner/source stay.
- `src/plugins/install-config.ts` — Receives former CLI manifest read; manifest.id plans recovery and install metadata gates eligibility. No account-policy/route selection.
Full-map validation and migration enumeration in `extensions/signal/src/config-schema.ts`, `extensions/signal/src/config-compat.ts`, `extensions/signal/src/account-key-repair.ts`, and `src/config/channel-doctor-helpers.ts` inspect authored rows for validation, cleanup or diagnostics. Their selection-dependent operations use the shared owner; enumeration is not route selection.
### Pinned-base census dispositions
The pinned-base comparison includes incoming main changes. Rows trace removed declarations/properties; markers count files, except the worker path's two references. Unrelated `type` keywords and `meta` fields are not the removed local properties.
| Census row | Source disposition |
|---|---|
| `anyOf` | The local MCP union conversion moved to `packages/normalization-core/src/json-schema.ts:178`. `src/agents/mcp-json-schema-validator.ts:45` calls that shared normalizer. Remaining schema keywords and fixtures retain their JSON Schema contract. |
| `type` | The removed inventory property is the same MCP converter's `{ type: entry }`. The shared normalizer still emits it at `packages/normalization-core/src/json-schema.ts:178`. No global `type` contract was removed. |
| `AWS_SECRET_ACCESS_KEY_VALUE_PATTERN` | The old regex export and imports were removed. `src/logging/redact-patterns.ts:96,202,368` now supplies the matcher through the default pattern list. No old external reference remains. |
| `config/sessions/session-model-context.worker` | Both remaining references are the source/dist paths in `src/infra/runtime-process-entrypoints.ts:69-70`. Runtime URL resolution and `scripts/lib/runtime-process-core-build-entries.mts:4-24` consume this table; `tsdown.config.ts:423` spreads the derived build entries. The worker remains packaged; these two unchanged main-side readers are retained. |
| `currentModuleUrl` | The inline session-model worker property moved to `runtimeProcessEntrypoints.sessionModelContext`. Its source-relative path was adjusted for the table location. Runtime and build derive from that same table; other worker entries retain the property. |
| `sourceWorkerName` | The source worker name moved into the same table. Both URL resolution and build generation consume it. Other workers' names remain valid. |
| `distWorkerPath` | The same table retains `config/sessions/session-model-context.worker.js`. Runtime joins it under `dist`; build generation derives its output key. The artifact was not retired. |
| `DoctorConfigPreflightResult` | The type moved to `src/commands/doctor/shared/config-migration-result.ts:10`. `src/cli/program/config-guard.ts:6` and `doctor-config-preflight.ts:59` import the new owner. No old import remains. |
| `cronCodexRuntimePolicyTargets` | The moved type retains this field at `config-migration-result.ts:15`. Preflight still records/returns targets, and `doctor-config-flow.ts:332-347` consumes them for repair and persistence. |
| `stateMigrationStepReceipts` | Preflight still records/returns receipts. `config-migration-result.ts:54,61` forwards them; Doctor flow awaits/spreads the result. `doctor-health-contribution-runners.state.ts:149-150` retains the health handoff. |
| `postSessionPluginMigration` | Preflight still returns the prepared plan. `config-migration-result.ts:55,62` forwards it, and `doctor-health-contribution-runners.state.ts:142-143` supplies it to the transcript migration owner. |
| `postSessionPluginMigrationPlanBound` | The preflight flag remains on the moved type and is forwarded by `config-migration-result.ts:56,63`, the health runner at145-146, and the transcript migration entry point at `doctor-session-transcripts.ts:199-214`. |
| `lastTouchedVersion` | Doctor's inline read moved to `config-migration-result.ts:26-27`, before repairs. It still produces `sourceLastTouchedVersion`; the stored metadata key and native/config readers remain valid. |
| `meta` | The removed inventory field was Doctor's inline metadata cast. `config-migration-result.ts:26` now reads typed `snapshot.sourceConfig.meta`. Other metadata identities were not retired. |
| `resolveClaudeCliSessionFilePath` | The synchronous helper remains private at `cli-session-history.claude.ts:455` for its internal synchronous readers. The external snapshot reader imports/awaits the async owner at `cli-session-history.claude-snapshot.ts:15,135`. No stale external import remains. |
| `runSerializedPreparedModelRuntimeTask` | The helper and its only caller/import were removed. `prepared-model-runtime.build.ts` now uses `createFullModelCatalogAccess`; its owner at `prepared-model-runtime.catalog-access.ts:420-440` retains the generation, limits discovery concurrency, and checks the current generation around awaited work. No old caller remains. |
The exact source-dispositioned owner/consumer files counted by each marker are:
| Symbol | Files |
|---|---|
| `anyOf` | `src/agents/mcp-json-schema-validator.ts`; `packages/normalization-core/src/json-schema.ts` |
| `type` | `src/agents/mcp-json-schema-validator.ts`; `packages/normalization-core/src/json-schema.ts` |
| `currentModuleUrl` | `{src/{config/sessions/session-model-context-worker-runtime.ts,infra/{runtime-process-entrypoints.ts,runtime-worker-url.ts}},scripts/lib/runtime-process-core-build-entries.mts}` |
| `sourceWorkerName` | `{src/{config/sessions/session-model-context-worker-runtime.ts,infra/{runtime-process-entrypoints.ts,runtime-worker-url.ts}},scripts/lib/runtime-process-core-build-entries.mts}` |
| `distWorkerPath` | `{src/{config/sessions/session-model-context-worker-runtime.ts,infra/{runtime-process-entrypoints.ts,runtime-worker-url.ts}},scripts/lib/runtime-process-core-build-entries.mts}` |
| `DoctorConfigPreflightResult` | `src/{commands/{doctor/shared/config-migration-result.ts,doctor-config-preflight.ts},cli/program/config-guard.ts}` |
| `cronCodexRuntimePolicyTargets` | `src/commands/{doctor/shared/config-migration-result.ts,doctor-config-preflight.ts,doctor-config-flow.ts}` |
| `stateMigrationStepReceipts` | `src/{commands/{doctor/shared/config-migration-result.ts,doctor-config-preflight.ts,doctor-config-flow.ts},flows/doctor-health-contribution-runners.state.ts}` |
| `postSessionPluginMigration` | `src/{commands/{doctor/shared/config-migration-result.ts,doctor-config-preflight.ts,doctor-config-flow.ts,doctor-session-transcripts.ts},flows/doctor-health-contribution-runners.state.ts}` |
| `postSessionPluginMigrationPlanBound` | `src/{commands/{doctor/shared/config-migration-result.ts,doctor-config-preflight.ts,doctor-config-flow.ts,doctor-session-transcripts.ts},flows/doctor-health-contribution-runners.state.ts}` |
| `lastTouchedVersion` | `src/commands/{doctor/shared/config-migration-result.ts,doctor-config-flow.ts}` |
| `meta` | `src/commands/{doctor/shared/config-migration-result.ts,doctor-config-flow.ts}` |
census: generic `config/sessions/session-model-context.worker` reviewed — 2 callers listed
census: generic anyOf reviewed — 2 callers listed
census: generic type reviewed — 2 callers listed
census: generic currentModuleUrl reviewed — 4 callers listed
census: generic sourceWorkerName reviewed — 4 callers listed
census: generic distWorkerPath reviewed — 4 callers listed
census: generic DoctorConfigPreflightResult reviewed — 3 callers listed
census: generic cronCodexRuntimePolicyTargets reviewed — 3 callers listed
census: generic stateMigrationStepReceipts reviewed — 4 callers listed
census: generic postSessionPluginMigration reviewed — 5 callers listed
census: generic postSessionPluginMigrationPlanBound reviewed — 5 callers listed
census: generic lastTouchedVersion reviewed — 2 callers listed
census: generic meta reviewed — 2 callers listed
### Additional normalization consumers
The source supplement adds 126 files to 401 typed: 527 total. Matrix setup-contract was already named; these 125 were absent. These are existing normalizer consumers, not new production changes; braces enumerate paths.
- `extensions/a2a/src/accounts.ts` — Retained account-context identity normalization.
- `extensions/discord/src/{account-inspect.ts,actions/runtime.messaging.shared.ts,client.ts,directory-cache.ts,directory-config.ts,monitor/{model-picker-preferences.ts,thread-bindings.config.ts,thread-bindings.manager.ts,thread-bindings.session-shared.ts,thread-bindings.state.ts},secret-config-contract.ts,setup-account-state.ts,voice/transcripts-source.ts}` — Retained inspection/setup/client/directory identity, message comparisons, voice secret/transcript scope, model/thread cache/manager/persisted keys.
- `extensions/feishu/src/{bot-identity-cache.ts,config-schema.ts,dynamic-agent.ts,secret-contract.ts,thread-bindings.ts}` — Retained bot/dynamic-agent/thread keys, default schema and secret identity.
- `extensions/googlechat/src/secret-contract.ts` — Retained account secret-owner identity.
- `extensions/imessage/src/approval-native.ts` — Retained approval-target identity/same-account suppression.
- `extensions/matrix/{doctor-contract-api.ts,src/{approval-handler.runtime.ts,approval-reactions.ts,auth-precedence.ts,cli-account.ts,cli-shared.ts,env-vars.ts,matrix/{accounts.ts,client/{config.ts,env-auth.ts,storage.ts},config-paths.ts,config-update.ts,credentials-read.ts,credentials-state.ts,credentials.ts,monitor/reaction-events.ts,read-policy.ts,session-store-metadata.ts},onboarding.ts,profile-update.ts,secret-contract.ts,session-route.ts,setup-dm-policy.ts,storage-paths.ts}}` — Retained Doctor credential identity; account/auth/config/CLI/onboarding/profile/env scope; storage/credential compatibility; session/read routes; approval-reaction registration/lookup/cleanup.
- `extensions/mattermost/src/mattermost/read.ts` — Retained requester-account comparisons for message reads.
- `extensions/msteams/src/approval-native.ts` — Retained named-account approval transport gating.
- `extensions/nostr/src/{channel.setup.ts,secret-contract.ts}` — Retained setup/default-account and secret-assignment identity.
- `extensions/policy/src/doctor/strictness.ts` — Retained Doctor routing-policy canonicalization.
- `extensions/signal/src/{approval-reaction-routes.ts,approval-reactions.ts,question-reactions.ts}` — Retained approval-route matching and delivered approval/question account identity.
- `extensions/slack/src/{account-inspect.ts,action-runtime.ts,channel-migration.ts,directory-config.ts,group-policy.ts,installation-identity-state.ts,monitor/enterprise-install.ts}` — Retained account/directory/group identity, requester checks, migration and installation/enterprise keys.
- `extensions/telegram/src/{account-inspect.ts,accounts.ts,bot/helpers.ts,directory-config.ts,dm-session-key.ts,group-migration.ts,message-topic-binding.ts,miniapp/{command.ts,routes.ts},poll-registry.ts,thread-bindings.ts}` — Retained account/token/action gates; directory/group/DM routes; requester/topic matching; Mini App scope; poll/thread keys.
- `extensions/whatsapp/{auth-presence.ts,src/{accounts.ts,agent-tools-call.ts,auto-reply/monitor/group-activation.ts,group-session-key.ts}}` — Retained auth/call storage, group activation and account session keys.
- `extensions/zalouser/runtime-api.ts` — Retained public normalizer forwarding export.
- `src/agents/agent-tools.policy.ts` — Retained normalization/account matching. Historical merge4d throws for unavailable accounts; prepush8c denies all. Separate base/source behavior, not promotion repair or new CI proof.
- `src/acp/persistent-bindings.types.ts` — Retained persistent-binding/session account identity.
- `src/agents/{subagents/announce/subagent-announce-origin.ts,tools/{message-tool-discovery.ts,message-tool-execution.ts,message-tool-group-thread.ts,sessions-send-tool.ts}}` — Retained announcement origin, message discovery/echo/group-thread and session-send matching.
- `src/auto-reply/{group-thread-dispatch.ts,group-thread.ts,reply/{route-reply.ts,source-turn-id.ts}}` — Retained group dispatch/source-turn/reply-source identity.
- `src/channels/{message/outbound-echo.ts,plugins/{configured-binding-match.ts,media-limits.ts,message-action-dispatch.ts},thread-bindings-policy.ts}` — Retained echo/binding keys, media account input, conversation comparisons and thread policy.
- `src/cli/message-secret-scope.ts` — Retained message secret-account scope.
- `src/commands/{agents.providers.ts,channels/{add-mutators.ts,remove.ts},doctor/shared/{allowlist-policy-repair.ts,default-account-warnings.ts,legacy-config-migrations.runtime.config-tranche.ts}}` — Retained provider indexing, add/remove identity, Doctor allowlist/default/migration scope.
- `src/cron/isolated-agent/delivery-target.ts` — Retained isolated delivery account identity.
- `src/flows/{channel-setup.prompts.ts,channel-setup.ts}` — Retained setup/removal account input normalization.
- `src/gateway/{conversation-route-ownership.ts,server-methods/{cron-caller-scope.ts,send.ts}}` — Retained conversation ownership, cron caller/declaration matching and message routes.
- `src/infra/outbound/{account-scoped-conversation-bindings.ts,session-binding-normalization.ts,source-reply-mirror.ts,targets.ts}` — Retained conversation/session keys, reply matching and heartbeat account/secret scope.
- `src/pairing/pairing-challenge.ts` — Retained optional challenge account scope.
- `src/plugin-sdk/{account-id.ts,approval-client-helpers.ts,approval-native-helpers.ts,pairing-access.ts}` — Retained normalizer export/approval-recipient/native route/pairing comparisons.
- `src/routing/{account-id.test.ts,account-id.ts,binding-scope.ts,channel-route-targets.ts,resolve-route.ts,session-key.ts}` — Retained normalizer/test, bindings/routes/account lists and peer/group session keys.
- `src/secrets/channel-secret-basic-runtime.ts` — Retained account secret-owner and assignment identity.
- `src/state/openclaw-agent-db-session-migrations.ts` — Retained migrated conversation account identity.
- `src/tts/tts-config.ts` — Retained account normalization supplied to TTS override lookup.
Of these 125 files, 124 match the historical integration byte-for-byte. The agent tool-policy source difference is stated above; its normalization and account matching remain. The normalizer still owns lowercase/safe account IDs and default handling. These callers retain their existing lookup, comparison, storage, routing or test duties; they add no Signal eligibility decision.
### Complete fallback audit and authorization consumers
Audit before correction: 73 calls/54 production files (four owner delegations); 160 lexical references/67 files include facades/types/comments/local names. Factory/Signal aliases were traced separately. Coordinates below identify the audited340 source. Commit5b50754 fixes both families; registered red/green is recorded under Tests.
- **Owner/facades:** `src/routing/account-lookup.ts:34,44,60,72` and `src/config/channel-account-config.ts:76,83` consume the selected key; no rescan. `src/channels/plugins/account-helpers.ts:115` forwards generated resolvers. Public `src/plugin-sdk/{account-core,account-helpers,account-resolution,account-resolution-runtime,routing}.ts` retain owner forwarding.
- **Correction sites:** `src/auto-reply/command-auth.ts:454,471-472` now selects inferred sole accounts through the owner. `src/channels/plugins/config-helpers.ts:88,126,177,184` remove raw fallback: delete/clear need existing selection; optional allowMissing creation belongs to selector. Public helpers accept raw IDs; Signal CRUD normalizes at `src/plugin-sdk/channel-config-helpers.ts:227-238`. Undeclared-channel raw creation remains the shipped contract.
- **Retained writer creation:** `src/channels/plugins/setup-helpers.ts:50,93,311,370` and `src/plugin-sdk/allowlist-config-edit.ts:197` normalize creation intent. Promotion selects inferred/default candidates; only explicit callback targets may create a missing normalized key. `src/channels/plugins/helpers.ts:57,63` reads selected/default values; path descriptions do not read raw rows.
- **Root/default field inheritance only:** `src/media/configured-max-bytes.ts:39`; `src/channels/{account-config-enabled.ts:13,draft-streaming-chunking.ts:33,join-intro/report-channel-room-join.ts:74}`; `src/channels/plugins/{config-write-policy-shared.ts:71,read-only.ts:209}`; `src/config/{channel-groups.ts:32,channel-capabilities.ts:51,markdown-tables.ts:57,group-policy.ts:75,104,context-visibility.ts:54,implicit-mentions.ts:29}`; `src/infra/{event-session-routing.ts:113,heartbeat-visibility.ts:54}`; `src/auto-reply/{chunk.ts:49,92,reply/reply-threading.ts:51,reply/block-streaming.ts:60}`; `src/agents/{identity.ts:33,117,subagents/spawn/acp-spawn-parent-stream.ts:124,embedded-agent-runner/history.ts:192}`. No raw retry; group/peer scans stay inside selected maps.
- **Selection or validation only:** `src/cron/delivery-channel-validation.ts:99` and `src/commands/doctor/shared/legacy-config-binding-repair.ts:99` consume selected enabled flags; `src/config/channel-doctor-helpers.ts:196` selects inheritance, migrates all rows. `src/config/zod-schema.providers-whatsapp.ts:126` selects default, validates all rows. `src/status/status-text.ts:97` is Telegram-only. `src/gateway/server-channels.ts:407,415` retains two undeclared forms; declared policy gives the same winner.
- **Plugin direct calls:** `extensions/{zalo/src/token.ts:42,discord/src/token.ts:70,discord/src/accounts.ts:52,line/src/accounts.ts:88,line/src/group-keys.ts:52,imessage/src/accounts.ts:47,slack/src/accounts.ts:93,sms/src/accounts.ts:103,googlechat/src/accounts.ts:71,clickclack/src/accounts.ts:86,122,feishu/src/policy.ts:303,whatsapp/src/account-config.ts:13,33,telegram/src/token.ts:125,telegram/src/account-config.ts:15,matrix/src/matrix/account-config.ts:81,117,matrix/src/account-selection.ts:130,twitch/src/token.ts:64,twitch/src/config.ts:68,116,signal/src/account-selection.ts:10,signal/src/accounts.ts:69}`. Selected values inherit root/shared-default/environment or stop. Twitch reuses selected default; Signal reply/setup/transport/Doctor wrappers use explicit policy (Consumers).
- **Factory aliases:** active: `extensions/{discord,clickclack,line,imessage,slack,googlechat,sms,zalo,zalouser,qa-channel,nextcloud-talk,irc,feishu,raft,synology-chat}/src/accounts.ts`, `extensions/mattermost/src/mattermost/accounts.ts`, and `extensions/tlon/src/types.ts`; factory-owned. List/default-only: `extensions/{nostr/src/types.ts,buzz/src/types.ts,whatsapp/src/account-ids.ts,signal/src/accounts.ts,twitch/src/config.ts,telegram/src/account-selection.ts}`.
- **Separate source-only follow-ups:** `src/channels/thread-bindings-policy.ts:123` and `extensions/discord/src/monitor/thread-bindings.config.ts:18,31` retain exact reads; Signal lacks that field. `extensions/synology-chat/src/accounts.ts:51,113` retains exact webhook/policy reads beside merged config. Both are source-only follow-ups. Runtime maps, all-row scans and pairing's resolved/configured singleton do not restore rejected config.
Authorization scope closes the full additional inventory:
- **Account-derived `isAuthorizedSender` pipeline:** `src/auto-reply/reply/{commands-context,commands-core,commands-handlers.runtime,get-reply-directives,get-reply-native-slash-fast-path,fast-approve,dispatch-from-config.context,dispatch-from-config.prepare-operation,session-reset-command,session,commands-reset,abort-operation,abort}.ts`. Dispatch/reset/abort share corrected auth owner.
- **Flag consumers/handlers:** `src/auto-reply/reply/{command-gates,get-reply-directives-apply,get-reply-directives-routing,get-reply-inline-actions,get-reply-run-context,get-reply,commands-status,commands-plugin,commands-system-agent,commands-diagnostics,commands-session,commands-acp,commands-bash,commands-approve,commands-login}.ts`. `/acp help` proves the flag gate; approve/login/privileged actions retain independent approval/global-owner gates.
- **Facades/type projections:** `src/auto-reply/reply/{commands,abort.runtime,fast-approve.runtime,get-reply-run.types,commands-types}.ts`; no local account selection.
- **Global `senderIsOwner` consumers:** `src/gateway/{talk-client-agent-consult,server-methods/chat-send-message-injection}.ts` and `src/auto-reply/reply/dispatch-from-config.prepare-operation.ts:235-253`. Alias fallback never grants this field; last file also dispatches fast account-authorized commands.
- **Retained tests/fixtures:** `src/auto-reply/{command-control.test,command-auth.owner-default.test}.ts`; `src/auto-reply/test-helpers/{command-auth-registry-fixture,command-auth-registry-fixture.test}.ts`; `src/auto-reply/reply/{commands.test-harness,get-reply.test-mocks,get-reply.test-fixtures,directive-handling.mixed-inline.test-helpers,commands-export-trajectory.test-support,commands-compact.test-support,commands-login.harness-test-support}.ts`. `src/gateway/node-invoke-plugin-policy.ts:291` is an unrelated local closure. `src/gateway/server-plugin-reload.recovery.test-support.ts` was already inventoried.
### Round-2 typed authorization supplement
Candidate `5b5075411706bf8ee1992125335c0ac84a30a6b2`, tree `7029d0d267619b6511f3a7c29c225375cf7dd5ff`: 69 queries (29 root, 18 scripts, 18 test-root, 4 locals/copied CommandContext properties). Eight separate pinned-base auth/context queries supplement the historical 299/147/12 batches; all five new batches exit 0. Candidate: 1,257 references/708 positions/160 files; base supplement: 443/443/87. Added files: 84 (37 production, 47 tests/fixtures), preserving 527 for a union of 611. These are source queries, not a new CI-merge census. Full source evidence stays private; braces enumerate all added paths.
- `extensions/slack/src/monitor/events/interactions.block-actions.ts` — Shared admission when commands.allowFrom is set; retains Slack policy.
- `extensions/telegram/src/{bot-handlers.inbound-authorization,bot-native-command-login}.ts` — Callbacks use command admission when configured, otherwise channel admission; login requires current admission AND global owner.
- Under `src/auto-reply/reply/`:
- `abort-operation.ts`, `commands-{acp,bash,session,status,system-agent}.ts`, `get-reply-native-slash-fast-path.ts` — Admission before abort, ACP, bang alias, session, both status branches, system-agent and native fast routing.
- `command-gates.ts` — Admission and global-owner checks remain distinct.
- `commands-{diagnostics,plugin}.ts` — Gate admission; forward both facts.
- `commands-approve.ts` — Admission or existing explicit approval authority.
- `commands-login.ts` — Recheck current admission AND global owner.
- `commands-plugins.ts` — Privileged work still requires global owner or Gateway admin.
- `commands-{btw,compact,learn}.ts`, `commands-acp/diagnostics.ts` — Forward global-owner fact; ACP diagnostics use it for visible/current entries.
- `commands-{context,types}.ts` — Resolver copies two distinct facts into CommandContext; both receiving declarations were queried.
- `commands-reset.ts`, `session-reset-command.ts` — Shared reset admission, including upstream commandAuthorized.
- `dispatch-from-config.prepare-operation.ts` — Resolve current authorization; forward owner fact and dispatch fast commands.
- `get-reply-directives{,-apply}.ts` — Gate directives/status on admission; retain literal-command suppression and separate owner branches/forwarding.
- `get-reply-inline-actions.ts` — Gate skill/commands on admission; forward owner fact.
- `get-reply-run-context.ts` — Upstream commandAuthorized and resolved admission both apply.
- `get-reply-run-execute.ts` — Forward owner fact; retain existing Gateway-admin alternative.
- `get-reply.ts` — Reset hooks need admission; ordinary replies forward owner fact.
- `src/gateway/{server-methods/chat-send-message-injection,talk-client-agent-consult}.ts`, `src/system-agent/rescue-message.ts` — Derive/forward global-owner fact; account access cannot grant it.
- `src/plugin-sdk/command-auth{,-native}.ts` — Re-export shared resolver. `src/plugin-sdk/command-status.runtime.ts` constructs CommandContext from separately supplied flags.
All 47 tests/fixtures below retain admission/global-owner inputs or assertions; none owns production selection. The new account-policy test covers registered command/reset regression. Inventory does not claim all listed tests reran.
- `extensions/discord/src/monitor/monitor.test.ts`
- `src/acp/control-plane/spawn.test.ts`
- `src/auto-reply/{command-auth.owner-default.test,command-control.test}.ts`
- `src/auto-reply/reply/{abort.target-owner.test,directive-handling.mixed-inline.test-helpers,directive-handling.model.test,get-reply-directives-apply.test,get-reply-inline-actions.skip-when-config-empty.test,get-reply-native-compact-authorization.test,get-reply-run.media-only.test,session.test,commands-{abort-trigger.test,account-policy.test,acp.test,approve.test,bash-alias.test,btw.test,compact.test,diagnostics.test,export-trajectory.test-support,gating.test,handlers.registration.test,info.test,learn.test,login.consent.test,login.harness-test-support,login.test,loop.test,mcp.test,plugin.test,plugins.install.test,plugins.test,reset-hooks.test,session-lifecycle.test,session-restart.test,steer.test,stop-target.test,subagents-routing.test,update.test}}.ts`
- `src/gateway/server-methods/{chat-send-user-turn.test,gateway-client-identity.test,talk.test}.ts`
- `src/plugin-sdk/command-auth.test.ts`
- `src/system-agent/{rescue-channel.live.test,rescue-message.test}.ts`
- `src/tts/tts-entry-delivery.test.ts`
Seven manual scope paths stay outside typed611: `scripts/check-ingress-agent-owner-context.mts` is diagnostic text; `scripts/dev/test-device-pair-telegram.ts` supplies literal plugin-command admission. `test/{helpers/agents/happy-path-prompt-snapshots.ts,transcripts-tool.discord-lifecycle.integration.test.ts,loopback-ask-user-telegram-channel.test.ts,canonical-descendant.integration.test.ts}` supply synthetic prompt/speaker/tool-authority/descendant owner facts. `scripts/e2e/system-agent-rescue-docker-client.ts` supplies literal flags in a client excluded from the scripts project. No competing selector or new execution claim.
## Invalidation
Selection is synchronous, uncached and reads supplied config. Doctor retains scoped metadata, preview without writes, backed-up repair and idempotence. Existing Signal reload prefix/restart refresh account state. Installed-record load/rebase/project rebuild policy; publication, retirement and caches own lifetime. Manifest adapters retain their selected record. Runtime proof covers Doctor preview/repair/repeat, restart, endpoint reload and old-source config boot without Doctor.
## Contention
No new lock, queue, transaction, async wait, listener or state store. Existing config/lifecycle owners retain effects.
## Tests
- Round 2: real admitted-group `buildCommandContext`→`handleCommands` `/acp help` and `resolveAuthorizedSessionResetCommand` prove the optional-resolveAllowFrom path in `src/auto-reply/reply/commands-account-policy.test.ts`. On source340, Alice loses help/reset and Bob gains both, with/without defaultAccount; senderIsOwner stays false. Four dispatch/reset cases fail while all eight eligible sole/default, undeclared, exact/case and global-owner controls pass. Split enable/delete/clear tests add three intended failures: final red 7 failed/27 passed. Source `5b5075411706bf8ee1992125335c0ac84a30a6b2` passes 146 tests (106 focused + 40 sibling), syntax lint/format/max-lines/assertion/SDK surface/diff checks. Native review passes. CI34688067951 found a test cleanup returning number;8828dc6 returns void, with14 command/abort tests passing. Assertions/production stay unchanged; CI/review receipts remain separate.
- Reset uses the actual session reset gate/result. Fast abort at `src/auto-reply/reply/abort-operation.ts:183-190` calls the same authorization owner and rejects before target/cancellation work. This is shared-entry authorization coverage, not executed cancellation side effects or a callback-backed Signal/global-owner escalation claim.
- Promotion: real `channelsAddCommand` plus cold contract tables reproduce root credentials/ignored access moving into absent-default spaced aliases. Corrected controls preserve root identity/restrictions/ignored rows across absent/present defaults, exact/case keys, explicit callback creation, `Default` and collisions: 125/125; earlier broader suite 143/143. Signal's adapter suppresses this generic promotion. `src/channels/plugins/setup-contract.test.ts` covers full/metadata-only contracts; `src/commands/channels.add.test.ts` covers registered add. No test deletion.
- SDK: [run 34686394191](https://github.com/openclaw/openclaw/actions/runs/34686394191), jobs `103534002152`/`103534002115`, compiles released 2026.9.4 and sealed candidate. Identical full inline adapters/contextual callbacks exercise promotion, setup/setup-runtime patch and allowFrom. TypeScript 6.0.3: NodeNext, strict/noEmit, skipLibCheck:false, types:[node]. Package source `20090983b5683ff352ed31e50a15143468913084`, SHA-256 `0b25b612693be3b4629231ff4445342f859bc0399f207d98b5d884c19caa6e6c`; checker `340142aaf7`. Runtime-only promotion correction retains signatures/fixture bytes. Both release-check files pass 60 cases; `test/scripts/release-check.test.ts` proves trusted-tooling copies against stale targets. Declaration proof is not runtime/release qualification. Round2 keeps this fixture/checker and public setup signatures unchanged. Its selector gains an optional final creation argument; prior arguments/inference/returns stay valid. The writer regression executes that mode and new-head CI owns its typecheck; the sealed200 compiler run is not represented as compiling the new mode.
- `extensions/clickclack/src/setup-core.test.ts:484`: registered setup+real reader preserve active exact ops credentials; pinned base fails while 19 controls pass, candidate 20/20.
- `extensions/signal/src/account-selection.test.ts`: registered config/threading/setup/delete cover own-number/inheritance, collision reads/writes, container URL, managed-port and Doctor default-transport collisions in both orders. `src/channels/plugins/account-key-policy.test.ts`: manifest adapter, scoped binding repair, outbound media collision, explicit SDK merge. Metadata tests cover persisted reconstruction, enablement, projection, replacement with/without declaration and no runtime execution.
- Retained receipts: 200 Signal-owner passes; routing/Gateway/metadata/policy/startup checks; final 35-case startup corpus; CI fixture 25/25 and 27/27 with provider-alias/Doctor sequencing assertions retained; setup metadata 142; SDK surface 10 (two exports/one callable); restored two released full-adapter callbacks; setup/contract 83 before metadata-only addition; revised cold-promotion/tooling tests. CI owns typechecking. Two macOS read-only `/var` versus `/private/var` assertions fail identically on base/candidate; neither assertions nor production changed.
- Test ledger: no baseline test deleted. `extensions/signal/src/setup-core.test.ts:144` and `:355` retire deletion of an emptied default row; the canonical empty row now preserves the exact winner. `extensions/signal/src/account-selection.test.ts:16` replaces that cleanup shape with effective identity/restriction continuity for exact and alias winners, including empty collision winners. `src/channels/plugins/setup-contract.test.ts:20` covers cold contract-to-promotion policy forwarding. `extensions/signal/doctor-contract-api.test.ts:45`: Doctor's former own-number inheritance fixture now omits the number per the accepted contract; `extensions/signal/doctor-contract-api.test.ts:87`: its own-number default case now expects optional key cleanup while keeping root transport authoritative. `src/plugins/loader.prefer-over.test.ts:110`: existing preferred-plugin assertions remain and cover both policy variants. `src/agents/provider-auth-aliases.test.ts` retains real installed-record selection in its I/O mock; `src/commands/doctor/repair-sequencing.test.ts` uses existing complete snapshots through `runDoctorRepairSequence`, removing two fixture casts without changing assertions. New metadata coverage uses a separate file; an intermediate clone-only assertion was removed because persisted-index reconstruction already covers the meaningful boundary.
- Runtime controls: exact collision before/after Doctor, own-number plus root, unchanged no-own-number base/head inheritance, optional Doctor/unchanged Telegram map, endpoint reload/restart, legacy default collision, and old config from `3a9d69db30` booting without Doctor. Managed-native inheritance lacks signal-cli; base/head share configured state/fallback/spawn error while root external transport runs. No live Signal messages; recording endpoints prove transport.
- Fresh external npm install on sealed200 passes maintained install/inspect, new Gateway, both status paths, account events/probes and cleanup. Source comparison to actual later merge `4b2f53900bc91b72b4afddaeb219251cda804f26` supports ordinary install/fresh startup only; new batch deferral is unused. Not merge4b package execution. Cold-start event-loop degraded metrics and disabled unrelated config warning remain recorded; no steady-state/live-service/batch/hot-reload claim. Historical merge4b lifecycle job103534548382 passed all nine reload tests, including watcher restart followed by settings persistence after reload closes. Its complete receipt is retained; this is not future-merge execution.
Co-authored-by: Ayaan Zaidi <hi@obviy.us>