Skip to content

🤖 feat: add Usage Telemetry toggle to Settings → General - #3850

Open
asm wants to merge 31 commits into
coder:mainfrom
asm:telemetry-settings-toggle
Open

🤖 feat: add Usage Telemetry toggle to Settings → General#3850
asm wants to merge 31 commits into
coder:mainfrom
asm:telemetry-settings-toggle

Conversation

@asm

@asm asm commented Aug 14, 2026

Copy link
Copy Markdown

Summary

Adds a Usage Telemetry toggle to Settings → General (under a new Privacy group) so telemetry can be disabled (and re-enabled) from the UI. The choice persists as telemetryEnabled in ~/.xum/config.json and applies immediately — disabling shuts the PostHog client down mid-session, re-enabling re-runs the full enablement check. XUM_DISABLE_TELEMETRY=1 remains a hard override that wins over the toggle; when the environment forces telemetry off, the switch renders disabled with a note saying so instead of pretending to control anything.

Background

Telemetry originally had a client-side opt-out (referenced in #905 when reporting moved to the backend), but that surface disappeared along the way, leaving the environment variable as the only user-facing switch — which is hard to apply to a Dock-launched macOS app (GUI apps don't inherit shell profiles). A Settings toggle is the conventional surface for this in developer tools; docs continue to point at payload.ts for transparency about what is sent.

Implementation

  • telemetryEnabled?: boolean config field (absent/true = enabled, false = disabled), stored sparsely: re-enabling deletes the key.
  • shouldEnableTelemetry gains a disabledByConfig input; TelemetryService receives an isDisabledByConfig callback from the service container and consults it during initialize() and per capture() — the per-event re-check keeps API-server processes honest even if a toggle apply hasn't reached them.
  • New config.updateTelemetryEnabled route persists the choice and calls telemetryService.setConfigEnabled() for the live apply. Applies are serialized (a promise chain) and initialize() is re-entrant-safe, so rapid toggling can't interleave PostHog shutdown/init and strand a live client after an opt-out; shutdown() nulls the client before awaiting the flush so nothing can capture into a draining client.
  • isExplicitlyDisabled() now includes the config opt-out, so features gated on explicit opt-out (e.g. link sharing) treat the Settings toggle the same as XUM_DISABLE_TELEMETRY=1.
  • getConfig exposes telemetryDisabledByEnv; the Settings row renders the switch hard-disabled with an explanatory note when the environment override is active.
  • Failed writes cannot leave the switch lying: Config.saveConfig swallows disk errors, so the route re-reads the persisted value after editConfig and fails loudly (before touching the live client) when the write didn't land. On the frontend, each toggle records an intent id — a superseded request's failure no-ops, and the latest intent's failure reloads the backend truth; if that truth is unreachable too, the switch renders ON (indeterminate state must never read "off" while collection may continue) until a successful config load reconciles it. Rapid toggling can't be clobbered by an early failure.
  • Settings row mirrors the existing API Debug Logs toggle patterns (load nonce, serialized update chain), with a "What is collected" link to the telemetry docs. Docs updated to describe the toggle, the env-disabled UI state, and that the env var must be exactly 1.

Review-round hardening

Eleven Codex review rounds tightened the privacy edges (all threads resolved):

  • Fail-closed reads: an unreadable or unparseable config.json — including an inaccessible ~/.mux that existsSync would mask as "missing" — reports disabled; only a genuine ENOENT (fresh install) means enabled. The RPC's persistence verification uses a strict read whose failure fails the request rather than masquerading as a confirmed opt-out.
  • Lifecycle races: toggle applies serialize with a re-entrant initialize(); shutdown() nulls before flushing; capture() re-checks the config per event and lazily re-initializes (rate-limited) when another process re-enables telemetry.
  • Switch honesty: indeterminate backend truth renders ON; superseded writes and superseded API clients can't clobber confirmed state; deferred config notifications replay through the current client once writes settle; the subscription re-syncs on connect to close the read-before-subscribe gap; the switch disables without a usable API. Cross-process display sync via config.json watching is documented as a follow-up (Config-level infrastructure).

Validation

  • Unit tests: config-opt-out disables enablement; env hard-off wins over config-enabled; isExplicitlyDisabled() reflects the config opt-out; telemetryEnabled round-trips the saveConfig whitelist (including clearing back to default).
  • UI tests: loading a persisted opt-out and persisting a re-enable; the env-disabled switch renders disabled/unchecked and ignores clicks; a failed write reverts the optimistic state.
  • Verified in Storybook: toggle renders under Privacy, flips both ways against the stateful mock with a clean console.

Risks

Low. The enablement change is additive (one new early-return input); with the field absent, behavior is byte-identical to today. The live-apply path reuses the existing shutdown()/initialize() lifecycle, now serialized against concurrent applies. Worst case on a config read failure inside the callback is telemetry staying in its startup state.


🤖 Generated with Claude Code

@asm
asm marked this pull request as draft August 14, 2026 00:21
@asm
asm marked this pull request as ready for review August 14, 2026 03:20
@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@asm

asm commented Aug 14, 2026

Copy link
Copy Markdown
Author

@codex review

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0b20a688ca

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/features/Settings/Sections/GeneralSection.tsx Outdated
Comment thread src/node/orpc/router.ts
@asm

asm commented Aug 14, 2026

Copy link
Copy Markdown
Author

@codex review

Both findings addressed in 9610baa:

  • Superseded-toggle rollback: each toggle now records a monotonically increasing intent id. A failure belonging to a superseded request no-ops (a later write carries the newest choice and its own handling); a failure of the latest intent reloads the backend truth via getConfig instead of blind-flipping. Covered by a rapid on→off→on test with a deferred first request that fails after later intents are queued.
  • Persistence verification: saveConfig swallows write errors, so updateTelemetryEnabled now re-reads the config from disk after editConfig and throws before touching the live client when the write didn't land — the UI reverts instead of showing "off" while the preference silently un-applies on next launch. Covered by a router test that makes the config dir read-only.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9610baa072

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/features/Settings/Sections/GeneralSection.tsx Outdated
@asm

asm commented Aug 14, 2026

Copy link
Copy Markdown
Author

@codex review

Round-2 finding addressed in 47d8ad0: when the reconciling getConfig fails too (backend truth unknown), the switch now always renders ON instead of !checked — indeterminate state must never read "off" while collection may continue, and the next successful config load reconciles the real value. Covered by a test where both the write and the reload fail on a disable attempt.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 47d8ad024f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/features/Settings/Sections/GeneralSection.tsx Outdated
@asm

asm commented Aug 14, 2026

Copy link
Copy Markdown
Author

@codex review

Round-3 finding addressed in c5e3eae: the switch renders disabled while api is null (browser-mode outage), and the handler refuses to flip optimistically before a deliverable write — covering the race where the connection drops between render and click. A disabled-state test asserts the click leaves the conservative ON state untouched.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c5e3eae115

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/config.ts Outdated
Comment thread src/browser/features/Settings/Sections/GeneralSection.tsx
@asm

asm commented Aug 14, 2026

Copy link
Copy Markdown
Author

@codex review

Both round-4 findings addressed in e54b346:

  • Fail closed on unreadable config: isTelemetryDisabledByConfig() now reads with throwOnError and reports disabled when an existing config.json cannot be read or parsed — corrupted state can no longer silently override an opt-out at startup or per capture(). A missing file (fresh install) still reports enabled, and callers stay non-fatal. Test writes malformed JSON and asserts disabled.
  • Cross-client sync: GeneralSection consumes the config.onConfigChanged stream (same pattern as UserPreferencesContext) and refreshes the telemetry fields on notifications, guarded by the load nonce plus a pending-writes counter so in-flight local writes reconcile through their own settle path instead of racing the refresh. Test drives a mock notification stream and asserts the switch follows an external opt-out.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e54b34668d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/features/Settings/Sections/GeneralSection.tsx
@asm

asm commented Aug 14, 2026

Copy link
Copy Markdown
Author

@codex review

Round-5 finding addressed in a9819ad: notifications arriving while local writes are in flight are no longer dropped — they set a missed-notification flag that replays the backend refresh when the pending-writes counter drains, so an external change landing during the write window (including our own write's early notification) always reconciles. Covered by a test where another client's enable arrives mid-flight during a local opt-out and the switch ends ON.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a9819ad28a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/orpc/router.ts Outdated
@asm

asm commented Aug 14, 2026

Copy link
Copy Markdown
Author

@codex review

Round-6 finding addressed in 34006f2: the persistence verification now re-reads with throwOnError — a read failure fails the RPC with its own error instead of masquerading as a confirmed opt-out, and the fail-closed read stays confined to enablement checks (isTelemetryDisabledByConfig) where reporting disabled on unreadable state is the safe direction. New router test locks config.json unreadable and the dir unwritable and asserts the RPC rejects without touching the live client.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 34006f2930

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/config.ts
@asm

asm commented Aug 14, 2026

Copy link
Copy Markdown
Author

@codex review

Round-7 finding addressed in 893cd6b: isTelemetryDisabledByConfig() now stats the config file explicitly instead of trusting existsSync() (which reports EACCES traversal failures as "missing") — only a genuine ENOENT means fresh-install-enabled; any other stat/read/parse failure fails closed without crashing startup. Test makes the config directory unreachable (chmod 000) and asserts disabled.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 893cd6b2fa

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/features/Settings/Sections/GeneralSection.tsx
@asm

asm commented Aug 14, 2026

Copy link
Copy Markdown
Author

@codex review

Round-8 finding addressed in e6aea88: the subscription now triggers a re-sync as soon as the iterator is connected, so a change landing between the initial snapshot and establishment can no longer strand a stale switch. Covered by a test that holds the subscription unestablished while another client opts out and asserts the switch syncs on connect (no event ever pushed for the missed change).

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e6aea88e97

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/telemetryService.ts Outdated
Comment thread src/browser/features/Settings/Sections/GeneralSection.tsx
@asm

asm commented Aug 14, 2026

Copy link
Copy Markdown
Author

@codex review

Both round-9 findings addressed in 49a35c2:

  • Cross-process re-enable: capture() now kicks a lazy, serialized initialize() when the shared config says enabled but this process's client is null (started while opted-out) — rate-limited to one attempt per 30s since the other enablement gates may legitimately keep it null. The process converges without a restart, in both directions now.
  • Superseded API client: an API replacement bumps the telemetry intent counter, so a late rejection from the old client fails the intent guard instead of reconciling against state the new client has since confirmed; the config subscription re-establishes on the new client and re-syncs on connect.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 49a35c27c8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/features/Settings/Sections/GeneralSection.tsx
@asm
asm force-pushed the telemetry-settings-toggle branch from 49a35c2 to bd10767 Compare August 14, 2026 17:57
@asm

asm commented Aug 14, 2026

Copy link
Copy Markdown
Author

@codex review

Round-10 finding addressed (branch also rebased onto latest main, clean replay): deferred-notification replays now go through a ref the api-change effect keeps pointed at the CURRENT client generation, so a write settling after an API replacement can no longer consume the notification against the disconnected client. Covered by a test choreographing write-pending → API swap → late old-client failure, asserting the switch syncs through the replacement client.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Something went wrong. Try again later by commenting “@codex review”.

Unknown error
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@asm

asm commented Aug 14, 2026

Copy link
Copy Markdown
Author

@codex review

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bd107679e8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/features/Settings/Sections/GeneralSection.tsx
@asm

asm commented Aug 14, 2026

Copy link
Copy Markdown
Author

@codex review

Round-12 finding — cross-process config.json change detection — descoped as a follow-up, with rationale:

  • The privacy-critical behavior already converges across processes without a watcher: capture() re-checks the persisted opt-out per event (disable propagates), fails closed on unreadable state, and lazily re-initializes when the shared config re-enables (enable propagates). What remains is a display-only lag in a second process's Settings pane, which corrects on the pane's next mount or any of that process's own config activity.
  • Watching config.json is Config-level infrastructure, not a toggle-PR bolt-on: write-file-atomic replaces the inode (so it needs directory watching), plus debouncing, self-write suppression to avoid notification loops, and platform-specific watcher semantics — machinery every config consumer would inherit. That deserves its own reviewed change; happy to build it as a follow-up if maintainers want it.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep them coming!

Reviewed commit: bd107679e8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector

Copy link
Copy Markdown

Security review completed. No security issues were found in this pull request.

Reviewed commit: 42ecafd938

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 42ecafd938

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/config.ts Outdated
Comment thread src/common/config/schemas/appConfigOnDisk.ts
…in the generic writer

Codex round 10:

- tryBreakStaleDirLock's cleanup catches (orphan rmdir, marker unlink,
  final rmdir) treated every failure as benign, feeding withDirLock's
  no-await retry — an undeletable stale lock froze the event loop for the
  45s deadline. Benign races (ENOENT, ENOTEMPTY) still continue; real
  cleanup failures (EACCES/EIO) propagate, and the acquire wrapper's
  lock-present rule turns them into a clear rejection.
- writeConfigDocument refuses telemetryEnabled changes: the tool-facing
  generic writer holds neither the write lock nor the marker sync, so a
  direct field write could split the two-record transaction (opt-out with
  no downgrade marker; re-enable with a stale marker). Same-value
  passthrough still writes unrelated fields. Covered in
  xum_config_write.test.ts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@asm

asm commented Aug 29, 2026

Copy link
Copy Markdown
Author

@codex review — addressed both round-10 findings: stale-lock cleanup failures propagate (last no-await spin path closed), and the generic config writer refuses telemetryEnabled so tool writes cannot split the field/marker transaction. Inline replies on the threads. Head is b66aed0.

@chatgpt-codex-connector

Copy link
Copy Markdown

Security review completed. No security issues were found in this pull request.

Reviewed commit: b66aed0731

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b66aed0731

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/tools/shared/configReadWrite.ts Outdated
Comment thread src/node/services/telemetryService.ts
Codex round 11:

- writeConfigDocument's telemetryEnabled compare was a TOCTOU preflight: a
  toggle could complete its field/marker transaction between the writer's
  read and its whole-document save, which then restored the stale field.
  The config-document read/compare/write now runs under the same
  cross-process config_write.lock (via a public Config wrapper), so tool
  writes serialize against every editConfig and telemetry transaction.
- isEnabled() now includes the live config gate: a peer process opt-out
  leaves this process's client non-null while capture() refuses per event,
  and /telemetry/status must agree with the effective state. The env gate
  needs no re-check (env is process-fixed; an env-disabled process never
  creates a client). Unit test flips the gate under a simulated client.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@asm

asm commented Aug 29, 2026

Copy link
Copy Markdown
Author

@codex review — addressed both round-11 findings: the generic config-document writer now runs its read/compare/write under config_write.lock (closing the TOCTOU), and isEnabled() reflects the live config gate so /telemetry/status agrees with capture(). Inline replies on the threads. Head is 1ca8e9f.

@chatgpt-codex-connector

Copy link
Copy Markdown

Security review completed. No security issues were found in this pull request.

Reviewed commit: 1ca8e9f456

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1ca8e9f456

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/tools/shared/configReadWrite.ts Outdated
…e->write

Codex round 12: locking only writeConfigDocument left the tool's SOURCE
read outside the lock — an editConfig landing between
readConfigDocumentUnvalidated and the save would be overwritten by the
stale whole-document snapshot even when telemetryEnabled itself matched.
mux_config_write now wraps the entire read->mutate->write for config.json
in withConfigDocumentWriteLock (exported from configReadWrite), and
writeConfigDocument takes configWriteLockHeld to skip the nested acquire
(the dir lock is not re-entrant). Providers documents keep their existing
path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@asm

asm commented Aug 29, 2026

Copy link
Copy Markdown
Author

@codex review — addressed the round-12 finding: the tool's whole read->mutate->write now runs under config_write.lock, not just the final write (inline reply on the thread). Head is 34ed467.

@chatgpt-codex-connector

Copy link
Copy Markdown

Security review completed. No security issues were found in this pull request.

Reviewed commit: 34ed4679f0

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 34ed4679f0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/browser/features/Settings/Sections/GeneralSection.tsx
Comment thread src/node/config.ts
…d at startup

Codex round 13: a crash between the verified field write and the marker
sync left the two records permanently split. Startup now runs
reconcileTelemetryOptOutMarker (under the write lock, before the enablement
gates read either record): an explicit telemetryEnabled: false recreates a
missing marker — also durably codifying hand-edited opt-outs — and an
explicit true removes a stale one. An absent field with a marker present is
deliberately left alone: that state IS the downgrade round-trip the marker
exists to survive, a crash-mid-enable is indistinguishable from it, and
failing closed is the privacy-safe direction (the next toggle repairs it).
Best-effort by the startup-must-never-crash rule. Covered for all three
states in config.telemetryEnabled.test.ts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@asm

asm commented Aug 29, 2026

Copy link
Copy Markdown
Author

@codex review — round 13: crash-split field/marker records now reconcile at startup from the explicit field (inline reply); the peer-process Settings-UI staleness finding is resolved as out of scope — it is the pre-existing instance-local Config.onConfigChanged architecture affecting every setting, and this PR only improves cross-process behavior (rationale on the thread). Head is dd62993.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dd62993908

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/config.ts Outdated
Comment thread src/node/services/serviceContainer.ts
Comment thread src/browser/features/Settings/Sections/GeneralSection.tsx
@chatgpt-codex-connector

Copy link
Copy Markdown

Security review completed. No security issues were found in this pull request.

Reviewed commit: dd62993908

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

…refresh

Codex round 14:

- The toggle now persists telemetryEnabled explicitly in BOTH directions
  (no sparse delete on enable): a crash between the verified field write
  and the marker removal leaves an explicit true the startup
  reconciliation repairs from, instead of an absent field that reads as
  the downgrade-survivor state and restarts opted out. Absent still means
  enabled-by-default for untouched configs.
- Startup reconciliation acquires the write lock with a 2s budget: a peer
  legitimately holding the lock must not stall app initialization for the
  45s acquisition budget — telemetry stays fail-closed and the next toggle
  (or restart) reconciles.
- GeneralSection's subscription refresh renders indeterminate state as ON
  when its single edge-triggered getConfig read fails (nonce-guarded):
  keeping OFF while collection may have resumed is the one lie the privacy
  switch can't tell — same doctrine as the toggle failure path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@asm

asm commented Aug 29, 2026

Copy link
Copy Markdown
Author

@codex review — addressed all three round-14 findings (explicit two-direction persistence so crash recovery has a field to repair from, 2s startup reconcile budget, fail-ON refresh semantics); inline replies on each thread. Head is 20c878a.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 20c878a0e6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/config.ts
Comment thread src/node/config.ts
…sed markers

Codex round 15:

- tryInstallDirLock treats a rename EPERM as contention only when the
  target lock actually exists (P1): a policy/antivirus denial with no lock
  in place otherwise alternated with the breaker's ENOENT retry-now answer
  into a no-await spin for the full acquisition budget.
- A release-path unlink failure (EIO/ESTALE) left a marker naming this
  still-live pid, which the breaker's owner-alive rule then honored
  forever — every later edit waited out the acquisition budget until
  process exit. Failed releases are now recorded in a per-process registry
  and self-reclaimed by the breaker; marker names are generation-unique,
  so the registry can never match a lock a concurrent section currently
  holds.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@asm

asm commented Aug 29, 2026

Copy link
Copy Markdown
Author

@codex review — addressed both round-15 findings: target-absent EPERM propagates instead of spinning (P1), and unreleased owner markers self-reclaim via a per-process registry. Inline replies on the threads. Head is 89d0cec.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 89d0cec05b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/config.ts Outdated
Comment thread src/node/config.ts Outdated
… succeeds

Codex round 16: the self-reclaim registry moves to module scope — Config
instances can be short-lived (the tool's document writer constructs one per
write), and an instance-held record vanished with its object while the
orphaned marker kept naming this live pid. The registry entry is now
removed only once the marker's unlink provably succeeded (or the marker is
confirmed absent), so a second transient failure cannot consume the one
record that makes the orphan reclaimable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@asm

asm commented Aug 29, 2026

Copy link
Copy Markdown
Author

@codex review — addressed both round-16 findings: the unreleased-marker registry is process-wide (module scope) and entries are retained until the unlink provably succeeds. Inline replies on the threads. Head is 39bde42.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Security Review

Here are some automated security review suggestions for this pull request.

Reviewed commit: 39bde424ee

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

Comment thread src/node/config.ts
…half-released generation

Codex round 17: an unlink failure after a completed write left a marker
naming this live pid that PEER processes (blind to the in-memory orphan
registry) honored as a live owner, stalling their config writes while this
process sat idle. Release now renames the whole generation aside in one
owner-checked syscall — the lock path is vacated atomically for every
process, no partial unlink/rmdir state is observable, and the renamed
remains ride the existing .stage- TTL sweeper when the immediate delete
fails. The unlink+registry path remains as the fallback when the rename
itself fails (same-process self-reclaim, as before).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@asm

asm commented Aug 29, 2026

Copy link
Copy Markdown
Author

@codex review — addressed the round-17 finding with an owner-checked atomic rename-aside release (inline reply on the thread). Head is 6403c29.

@chatgpt-codex-connector

Copy link
Copy Markdown

Security review completed. No security issues were found in this pull request.

Reviewed commit: 6403c29447

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant