Commit Graph

476 Commits

Author SHA1 Message Date
Peter Steinberger b5232bc4dd refactor(markdown): add capability-driven fallbacks (#112985)
* refactor(markdown): add capability-driven fallbacks

* fix(markdown): type task-list core rule state

* style(markdown): make list-prefix return explicit

* fix(markdown): honor label-only plain links

* fix(markdown): retain clipped list provenance
2026-07-23 05:47:48 -04:00
Peter Steinberger ebec398543 refactor: move Telegram and iMessage config schemas to plugins (#112850)
* refactor: move telegram and imessage schemas to plugins

* test: allow bundled schema facade regression coverage

* refactor: remove orphaned command config helper
2026-07-22 23:01:47 -04:00
Peter Steinberger 099d6351b3 refactor(sessions): canonical lineage model — creation provenance, fork ancestry, generation chain, typed row contract (#111861)
* fix(sessions): preserve spawn/fork lineage across implicit daily/idle rollover

* refactor(sessions): canonical creation model with forkSource ancestry and generation chain

* feat(sessions): stamp creation provenance across all creation paths and emit created events

* refactor(gateway): lock lineage patching, split control from navigation, add typed session-row contract

* docs(gateway): document creation provenance stamping and lineage patch tightening

* fix(sessions): keep provenance proof-only on wire fallbacks and strip node-local lineage from cron continuations

* fix(gateway): never journal a created event for session adoption

* fix(gateway): keep post-create work on adoption while gating the created event

* fix(sessions): restore trusted ensure-main provenance and stamp navigation parent at spawn

* fix(sessions): allow parentSessionKey through the direct child spawn patch

* fix(ci): break type cycles, satisfy export scan, regenerate Swift protocol models

* refactor(sessions): replace createdBy with createdActor

* fix(protocol): export session row type

* fix(sessions): preserve proven creation provenance

* fix(sessions): close lineage creation gaps

* test(sessions): align atomic spawn lineage coverage

* test(sessions): widen transcript search reconcile wait

* fix(sessions): stamp reset-created rows

* test(sessions): keep reset provenance coverage focused

* fix(sessions): journal chat-created rows

* test(ci): anchor release skill reads to repo

* test(ci): avoid cached module paths
2026-07-22 22:54:31 -04:00
Peter Steinberger 0724dfda21 refactor(channels): share retry and text break helpers (#112786)
* refactor(channels): share retry and text break helpers

* fix(sdk): keep helper internals private
2026-07-22 19:05:00 -04:00
Md Abrar Ibn Habib d2d3171bb7 fix(agents): strip current exec failure traces (#111877)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: xbrxr03 <abrarhabib03@gmail.com>
2026-07-22 14:19:59 -07:00
Po-Han Shih 7cf6bd5e4b fix: treat EPERM as alive in isPidAlive (#110235)
* fix(pid): treat EPERM as alive in isPidAlive

Match isPidDefinitelyDead: process.kill(pid, 0) throwing EPERM means the
PID exists but cannot be signaled, so it should not look dead.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(pid): check Linux zombies after EPERM existence probe

EPERM means the PID exists but cannot be signaled; still run the zombie check so Linux zombies are not reported as alive.

Co-authored-by: Cursor <cursoragent@cursor.com>

* test(pid): isolate EPERM liveness probe

Co-authored-by: stantheman0128 <stanshih888@gmail.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-22 13:56:09 -07:00
Peter Steinberger df3ff35277 refactor(state): move device auth tokens to SQLite (#112663)
* refactor(state): store device auth tokens in sqlite

* fix(state): keep device auth migration types acyclic

* fix(state): keep migration detection type private
2026-07-22 06:13:03 -07:00
Peter Steinberger cf2f591161 feat(sessions): permanent creator attribution, owner avatars, person filter, multi-user docs (#112658)
* feat(sessions): persist creator attribution

* feat(ui): add session creator filtering

* chore(sessions): refresh sqlite schema baseline

* docs(security): explain shared-agent trust

* fix(sessions): project catalog creator ownership

* fix(ui): restore startup JS budget headroom for creator attribution
2026-07-22 05:47:21 -07:00
Peter Steinberger f0c43dcf72 feat(ui): format international phone numbers for display (#112400)
* feat(ui): format phone numbers for display

* ci: track normalization package exports in Knip
2026-07-21 17:10:25 -07:00
Yuval Dinodia 83ca537778 fix(shared): block prototype-polluting keys in JSON schema default hydration (#107978)
A plugin manifest configSchema declaring a __proto__ property polluted
Object.prototype process-wide during ordinary plugin config validation.
applyObjectPropertyDefaults iterated schema-controlled property keys and
wrote into value[key] with no blocked-key guard; because manifests are
parsed JSON, __proto__ is an own key and value["__proto__"] dereferences
the inherited Object.prototype, onto which nested defaults were written.

Skip __proto__, prototype, and constructor at each write site in
applyObjectPropertyDefaults, reusing the existing isBlockedObjectKey
helper already used at other untrusted object-write boundaries.
2026-07-20 19:33:31 -07:00
Peter Steinberger 49ff6a4497 fix(protocol): classify system agents in rosters (#111920)
* fix(protocol): classify system agents in rosters

* fix(ci): align agent kind client gates

* fix(ci): keep roster filtering in startup bundle

* chore(ui): remove superseded roster module

* style(android): satisfy agent kind test formatting

* style(linux): format merged agent capability assertion

* fix(config): reject reserved system agent ids

* chore(i18n): refresh native source inventory

* style(android): format agent kind surfaces

* fix(gateway): preserve configured agent ownership
2026-07-20 16:57:04 -07:00
Peter Steinberger ccb147518c feat(agents): Swarm core — collector spawn, agents_wait, structured output, caps (gated) (#110932)
* docs: add Swarm implementation spec

* feat(agents): Swarm core — collector spawn, agents_wait, structured output, fastMode, caps

Implements docs/plan/swarms.md §4-6: tools.swarm config gate (default off),
collector-mode sessions_spawn (collect/outputSchema/fastMode/groupId), fail-closed
child approvals, agents_wait race-semantics tool, per-group FIFO scheduler with
maxConcurrent/maxChildrenPerGroup/maxTotalPerGroup caps, additive registry and
state-schema columns (no schema-version bump), and colocated tests.

Part of #110325

* fix(agents): rebase reconciliation — preserve swarm state columns

* fix(agents): O(1) collector session index, cheap-first preflight, collector start lifecycle hooks

Autoreview findings: replace the per-request full registry scan with an
index-maintaining run map and gate the persisted-store fallback behind
isSubagentSessionKey; emit subagent_progress/subagent_spawned from the swarm
scheduler start callback so collector children produce balanced plugin
lifecycle events.

* chore(protocol): regenerate Swift gateway models for swarm fields

* fix(agents): lint cleanup — typed catch, explicit microtask flush, no executor return

* fix(agents): knip/test-support/max-lines cleanup for swarm surfaces

* fix(agents): keep tool-catalog ui-safe — callers pass prepared swarmEnabled fact

resolveSwarmConfig value-import in tool-catalog dragged the server graph into
the Control UI bundle via tool-policy-shared (UNLOADABLE_DEPENDENCY on
subpath aliases). Catalog stays pure; the gateway tools-catalog handler
resolves the gate and passes the boolean.

* fix(agents): reconcile swarm spawn pipeline

* fix(agents): refresh swarm tool metadata

* fix(apps): sync swarm tool localization

* style(agents): compact tool display metadata

* fix(plugin-sdk): account for swarm config surface
2026-07-18 23:30:11 -07:00
Peter Steinberger 756a491a51 fix(speech): strip markdown before TTS and route code-heavy replies sensibly (#110948)
The talk.speak synthesis path passed raw agent text to providers, so talk
mode could read fenced code, links, and tables aloud. Speech normalization
now happens once at the shared synthesis boundary (speech-mode stripMarkdown:
label-only links, decorative bullet/glyph cleanup, punctuation collapsing).
Code-heavy replies (>=50% fenced content, CommonMark-aware scanner incl.
blockquote/list containers and unclosed fences) get routed by surface:
talk.speak speaks a short on-screen fallback line, channel auto-TTS skips
the voice note since the visible text already carries the content, and
explicit conversions (tts.convert, tagged hidden TTS, chat Listen) always
speak stripped best-effort content.
2026-07-18 18:16:43 -07:00
cxbAsDev 593423ecc0 fix(shared): bound ignore-file reads during workspace scans (#101429)
* fix(shared): bound ignore-file reads during workspace scans

* fix(shared): import bounded reader through infra policy wrapper

* fix(shared): preserve chained-symlink ignore files while bounding reads

* fix(shared): correct ignore-rules test calls and remove dead return

* fix(shared): restore ignore matcher return value from addIgnoreRules

* fix(shared): fail closed on oversized ignore files during scans

* style(shared): format ignore-rules signature

* test(shared): rename misleading under-cap ignore-file test

* chore: retrigger CI for unrelated flaky run-with-env shutdown test

* fix(shared): make oversized ignore-file exclusion terminal

* test(shared): remove loadSkillsFromDir dependency for main compat

* chore: retrigger dead-code scan after Periphery/Homebrew flake

* fix(scans): fail closed on ignore read races

* fix(scans): treat fail-closed ignore paths literally

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* fix(scans): preserve native ignore path semantics

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* fix(scans): bound ignore rule amplification

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* fix(scans): preserve case-insensitive fail-closed matching

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* fix(scans): preserve bounded ignore composition

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* fix(scans): satisfy matcher method binding lint

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* fix(scans): preserve ignore matcher case mode

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* fix(scans): keep matcher options internal

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* fix(scans): require matcher case contract

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
2026-07-18 15:31:42 +01:00
tzy-17 a941d3ab72 fix(shared): reject HTTP status codes outside the 100-599 range (#110554)
* fix(shared): reject HTTP status codes outside the 100-599 range

extractHttpStatusMatch only checked Number.isFinite, so 3-digit
sequences such as "000", "099", "600", and "999" were accepted as
valid HTTP statuses. Downstream code then surfaced them as "HTTP 0"
in user-visible messages and fed them into retry/classification
branches (e.g. isCloudflareOrHtmlErrorPage checks `code < 500` and
`code < 600`). Restrict the extracted code to the IANA HTTP status
code range (100-599).

Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>

* fix(shared): validate all parsed HTTP status prefixes

---------

Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 10:44:31 +01:00
Peter Steinberger d7de67ae02 feat: ask_user follow-ups — harness convergence, channel finalization + reactions, native cards, docked web panel (#110372)
* feat(ask-user): follow-up harness slice

* feat(ask-user): follow-up channels slice

* feat(ask-user): follow-up native slice

* feat(ui): dock question panel above composer with stepper and compact stream summaries

* docs: refresh follow-up integration maps

* test(ui): align terminal summary proof

* fix(infra): echo declared option answers in terminal status when free-text is allowed

* fix(infra): keep reaction answering when display labels are formatter-adjusted

* fix(agents): settle plain-text claims only after question registration commits

* fix(agents,apps): commit-ordered claim persistence, claim-aware prompt delivery, non-blocking question refresh

* fix(harness,infra): reaction-appropriate question copy, caller presentations honored

* fix(native,infra,agents): local-expiry eviction, value-addressed reactions, reserve-before-request

* fix(infra,android): dual-mode question resolver for compact callbacks; reset terminal retention on replayed pending

* fix(harness,discord): claim-aware prompt delivery in run helper; escape finalization labels

* fix(macos): merge transient-content visibility with question cards after main sync

* fix: repair ask user follow-up CI

* test: update limited bootstrap scope expectation

* fix: retain shared question card API

* chore: refresh native i18n inventory
2026-07-18 03:32:39 -04:00
dwc1997 ec3eb573bf test(shared): add unit tests for numeric coercion helper (#98663)
* test(shared): add unit tests for numeric coercion helper

* test(shared): cover numeric coercion boundaries

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 07:17:34 +01:00
Peter Steinberger 746d257f05 feat: contract sessions-family tool outputs (#110424)
* feat(agents): contract sessions-family tool outputs

* refactor(agents): remove unused fast-mode exports
2026-07-18 06:43:12 +01:00
Peter Steinberger 92e8e8bca6 test: move deferred-event-buffer test to its packages/ai owner and drop dead protocol test 2026-07-17 17:36:48 -07:00
zengLingbiao 2666cf7174 test(shared): add unit tests for createDeferredEventBuffer (#98670) 2026-07-17 17:21:18 -07:00
zengLingbiao 256a2ece73 test(shared): add unit tests for modelKey (#98795) 2026-07-17 17:20:59 -07:00
zengLingbiao 1d64790bf2 test(shared): add unit tests for normalizeNodePresenceAliveReason (#98802)
* test(shared): add unit tests for normalizeNodePresenceAliveReason

* fix(test): add missing bg_app_refresh and significant_location assertions
2026-07-17 17:19:54 -07:00
zengLingbiao ec35d6b5ba test(shared): add unit tests for agent liveness state helpers (#98546) 2026-07-17 17:09:02 -07:00
zengLingbiao 58a86297f8 test(shared): add unit tests for parseConfigPathArrayIndex (#98543) 2026-07-17 17:08:50 -07:00
Wynne668 f104c51e85 fix(clawhub): reject calendar-invalid feed timestamps (#106942)
* fix(clawhub): reject calendar-invalid feed timestamps

* fix(clawhub): preserve strict feed timestamps

* fix(test): avoid promise executor return in clack prompter test

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(clawhub): preserve feed timestamp semantics

* fix(clawhub): strengthen feed timestamp validation

Co-authored-by: ZengWen-DT <ceng.wen@xydigit.com>

* fix(time): validate full end-of-day fractions

Co-authored-by: ZengWen-DT <ceng.wen@xydigit.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-17 19:02:43 +01:00
maweibin b8c7f31894 fix(sessions): prevent delivery-mirror prompt contamination with adjacent dedup and identity fallback (#99470) (#99504)
* fix(sessions): prevent delivery-mirror prompt contamination with adjacent dedup and identity fallback (#99470)

Two-layer defence against delivery-mirror entries leaking into provider
prompts after session rebuild / side-branch merge strips metadata:

Layer 1 (identity fallback): isTranscriptOnlyOpenClawAssistantMessage
gains an openclawDeliveryMirror field check to catch stripped-metadata
survivors that lost provider/model during rebuild.

Layer 2 (adjacent dedup): normalizeAssistantReplayContent collapses
adjacent byte-identical no-tool-call assistant messages, catching
fully-bare {role,content,usage} survivors invisible to any metadata
filter.

P1 fix: added 'tool_use' (native Anthropic snake_case) to
TOOL_CALL_TYPES in extractToolCallsFromAssistant so adjacent dedup
never collapses tool-call-bearing turns.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(sessions): narrow delivery mirror replay filtering

* test(sessions): preserve tool-call replay duplicates

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 15:19:49 -07:00
Alix-007 6bcf071120 fix(infra): bound macOS process start probes (#109064)
* fix(infra): bound macOS process start probes

* docs(changelog): note macOS process probe deadline

Co-authored-by: Alix-007 <li.long15@xydigit.com>

* test(infra): cover process probe timeout

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 11:36:07 -07:00
wuqxuan e868a1dbd1 fix: recognize provider-wrapped HTTP status for session retry (#106850)
* fix: recognize provider-wrapped HTTP status for session retry

* fix(llm): scope wrapped status parsing to retry

Preserve the leading-status contract for rate-window and formatting callers while letting retry classification recognize built-in provider wrappers.

Co-authored-by: wuqingxuan <wu.qingxuan@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 00:40:15 -07:00
Peter Steinberger 4f40f46a08 docs(shared): clarify ignore anchoring 2026-07-14 12:19:39 -07:00
Peter Steinberger a7f4e72216 test(shared): preserve tabbed ignore anchoring 2026-07-14 12:19:39 -07:00
Peter Steinberger bfa72f8dab fix(shared): classify trailing-space ignore rules 2026-07-14 12:19:39 -07:00
Peter Steinberger 21515ae808 refactor(deps): reuse ignore matcher construction 2026-07-14 12:19:39 -07:00
moguangyu5-design 45395c2fd1 fix(shared): match nested gitignore semantics for unanchored patterns and escaped ! 2026-07-14 12:19:39 -07:00
Peter Steinberger f81f9d8570 chore: enforce max-lines suppression ratchet (#107315)
* ci: enforce max-lines suppression ratchet

* chore: prune stale max-lines suppression

* fix: close max-lines ratchet enforcement gaps

* fix: harden max-lines ratchet checks

* fix(ci): satisfy max-lines ratchet checks

* style: format max-lines declarations

* fix(ci): match oxlint suppression grammar

* test: isolate max-lines git fixtures

* chore: prune resolved max-lines debt

* test: skip newline path fixture on Windows

* fix: harden max-lines suppression ratchet

* chore: refresh max-lines baseline

* fix: close max-lines ratchet bypasses

* fix: derive ratchet base from PR merge tree

* fix: support older Git in staged ratchet

* fix: align max-lines declarations and baseline

* chore: refresh max-lines baseline for current main

* fix: exclude generated wizard locales from max-lines

* chore: prune resolved max-lines debt
2026-07-14 09:27:02 -07:00
Peter Steinberger 8ea5ee2f17 refactor(terminal): unify bounded buffers (#107337)
* refactor(terminal): unify bounded buffers

* refactor(terminal): tighten buffer closure

* refactor(terminal): keep buffer policy private
2026-07-14 03:04:37 -07:00
snowzlmbot e8ad0466ff fix: render assistant transcript headers safely (#99404)
* fix: render assistant transcript headers safely

Co-authored-by: snowzlmbot <293528334+snowzlmbot@users.noreply.github.com>

* fix(markdown): nest crossing annotation spans

* fix(markdown): protect final transport projections

* refactor(markdown): split transcript render ownership

* test(ui): cover assistant transcript render flag

* refactor(markdown): keep transcript helpers private

* docs(changelog): note assistant transcript headers

* chore(plugin-sdk): refresh transcript annotation baseline

* fix(markdown): harden final transcript projections

* docs(changelog): defer transcript note to release

* refactor(markdown): centralize HTML tokenization

* fix(markdown): satisfy lint gates

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: snowzlmbot <293528334+snowzlmbot@users.noreply.github.com>
2026-07-14 02:25:37 -07:00
Peter Steinberger b940339c32 fix: use plain agent progress labels (#107260)
* fix(channels): simplify agent progress labels

* chore: keep changelog release-owned

* chore: refresh bundled channel metadata
2026-07-14 01:00:24 -07:00
Peter Steinberger b58a75d726 refactor(html): share entity decoding 2026-07-14 00:00:05 -07:00
Peter Steinberger 889b4f7dcf fix(control-ui): rotate branded progress labels (#107111)
* fix(control-ui): rotate branded progress labels

* chore: keep progress note in PR body
2026-07-13 21:42:35 -07:00
Peter Steinberger 0b96300fc6 refactor(shared): privatize internal helpers (#106868) 2026-07-13 15:40:31 -07:00
Vincent Koc a8548a1191 refactor(shared): narrow entry status API (#106856) 2026-07-14 06:24:21 +08:00
Vincent Koc d08228eee1 refactor(shared): privatize requirement helpers (#106837) 2026-07-14 05:50:55 +08:00
Peter Steinberger 2aa4ff0825 refactor: consolidate duplicate helper exports (#106016)
* refactor(normalization): consolidate string helpers

* refactor(normalization): consolidate agent ids

* refactor(paths): consolidate user path resolution

* refactor(gateway): preserve transcript helper facade

* fix(normalization): align helper build aliases

* fix(memory): keep helper import line neutral

* chore(plugin-sdk): align consolidated helper surface

* refactor(normalization): reuse lowercase string helper

* refactor(normalization): reuse record guard

* refactor(normalization): share surrogate boundary helper

* refactor(agents): share token estimate constant

* refactor(memory): distinguish standalone helper contracts

* refactor(normalization): share error cause formatter

* refactor(config): distinguish eligibility predicates

* refactor(plugins): share registry state symbol

* refactor(cli): reuse outbound dependency adapter

* refactor(cron): distinguish positive duration parser

* fix(gateway): keep transcript helper private

* fix(paths): preserve public helper status

* refactor(channels): reuse registry normalizer

* refactor(agents): reuse agent core runtime facade

* refactor(auth): reuse locked profile upsert

* refactor(records): distinguish trap-safe guard

* refactor(migrations): distinguish sync directory helper

* test(plugins): drop stale duration alias expectations

* fix(channels): remove stale registry import

* chore(plugin-sdk): refresh helper API baseline

* fix(memory): keep renamed helpers private

* fix(plugins): keep registry state key private

* fix(plugin-sdk): tighten wildcard surface budget

* chore(plugin-sdk): refresh rebased helper API baseline
2026-07-13 03:22:00 -07:00
Peter Steinberger 9ea4b167fa refactor(deadcode): trim channel auth exports (#106247) 2026-07-13 02:45:34 -07:00
Peter Steinberger 938d41014f feat(mobile): default pairing to full node access (#105928)
* feat(mobile): default pairing to full node access

* chore: leave release notes to release workflow

* refactor(mobile): bound pairing helpers

* chore(i18n): refresh mobile access inventory

* chore(ci): lower mobile pairing LOC baseline

* fix(mobile): complete pairing validation artifacts

* ci: remove stale transcript target export baseline

* fix(ios): wrap access upgrade guidance

* fix(ios): preserve localized access key

* fix(ci): dedupe read-only SQLite guardrail

* fix(mobile): secure full-access node setup
2026-07-13 02:30:45 -07:00
Peter Steinberger e2ec8283c4 refactor(deadcode): trim mid-size src exports (#105888)
* refactor(deadcode): trim auto-reply and CLI exports

* refactor(deadcode): trim cron and task exports

* refactor(deadcode): trim fleet and process exports

* test(deadcode): exercise live task and process seams

* test(fleet): cover stream redaction through owner module

* refactor(security): trim dead internal exports

* refactor(secrets): trim dead internal exports

* refactor(deadcode): trim remaining src exports

* refactor(deadcode): remove test-only runtime exports

* refactor(deadcode): trim pairing test exports

* refactor(deadcode): reconcile refreshed baseline

* test(auto-reply): deduplicate queue state imports
2026-07-13 00:42:56 -07:00
Peter Steinberger 5cb074ece5 refactor: dedupe small async primitives (#105961)
* refactor(sqlite): remove unused async Kysely driver

Co-authored-by: Sarah Fortune <sarah.fortune@gmail.com>

* refactor(media): share promise memoization

* chore(sqlite): prune stale Kysely guardrails

* chore(media): lower runner LOC baseline

* style(shared): format promise memo tests

* chore(deadcode): refresh main export baseline

---------

Co-authored-by: Sarah Fortune <sarah.fortune@gmail.com>
2026-07-12 22:34:53 -07:00
Peter Steinberger 1b313dc4d4 chore(tooling): enforce indexed access in core tests (#105375)
* test(tooling): enforce indexed access in core tests

* test(tui): constrain theme environment overrides

* test(doctor): enforce indexed access in migration fixtures
2026-07-12 14:29:52 +01:00
Peter Steinberger 55254c3a0b feat(nodes): route alerts to the active computer (#105083)
* feat(nodes): route alerts by active computer

* fix(ci): allowlist node presence mobile coverage

* test(prompts): refresh node presence snapshots

* fix(macos): await presence reporter actor hop

* fix(macos): type presence test delivery state

* docs(nodes): add active presence guide

* docs(nodes): format presence troubleshooting
2026-07-12 10:05:50 +01:00
Peter Steinberger 6b95f98fe7 fix(core): make indexed access explicit across remaining src (NUIA phase 3b) (#104773)
* fix(core): make indexed access explicit in auto-reply, infra, and config

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.

* 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.
2026-07-11 20:47:34 -07:00