fix(server): preserve automatic settlement timestamps - #9254

Merged
juliusmarminge merged 4 commits into
pingdotgg:mainfrom
eimexdev:fix/auto-settlement-timestamps
Sep 3, 2026
Merged

fix(server): preserve automatic settlement timestamps#9254
juliusmarminge merged 4 commits into
pingdotgg:mainfrom
eimexdev:fix/auto-settlement-timestamps

Conversation

@eimexdev

@eimexdeveimexdev commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Problem

Server-side auto-settlement records the sweep time as settledAt. On startup, old threads therefore look newly settled and receive incorrect dates and ordering. #9081 suppresses the resulting notifications, but does not correct the durable timestamp.

Fix

  • Carry the latest user/turn activity timestamp through the internal auto-settle command.
  • Keep updatedAt at command time, preserving normal update semantics.
  • Repair projection_threads.settled_at for identifiable automatic settlements, without changing manual or later re-settled timestamps. The event log is left as recorded: projections and the engine bootstrap from projection rows and cursors, so a projection-only repair is sufficient.
  • Web and mobile sort and label the Settled shelf by the same shared resolveSettledThreadTimestamp.
  • Document the settled-shelf ordering behavior.

Refs #9057
Pairs with #9081

Verification

  • Focused server, client-runtime, web, and mobile tests for the touched files
  • Server, contracts, client-runtime, web, and mobile typechecks
  • Targeted lint and formatting check

Made with GPT-5.6 Sol in T3 Code through the Codex harness. Follow-up commit by Claude Fable 5 in Claude Code.


Note

Medium Risk
Schema-breaking thread.auto-settle now requires settledAt, and migration 046 rewrites settled timestamps on projection rows for identifiable automatic settlements—deployments should run migrations before relying on sidebar ordering.

Overview
Automatic thread settlement now persists when work ended, not when the server sweep ran. resolveAutoSettlementAt returns the activity timestamp (or null); ThreadSettlementReactor passes it as required settledAt on thread.auto-settle, and the decider writes that to settledAt while updatedAt stays the command time.

Migration 046 repairs legacy projection_threads.settled_at rows where auto-settlement stamped the sweep time (identified via server auto-settle events). Manual and later re-settled threads are left alone; orchestration event payloads are unchanged.

Clients share resolveSettledThreadTimestamp from client-runtime so web and mobile sort and label the Settled shelf from the same stamp (settledAt, then latest activity, then updatedAt). Docs describe that ordering behavior.

Reviewed by Cursor Bugbot for commit ab67483. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Preserve settledAt timestamp in automatic thread settlement and repair legacy projections

  • resolveAutoSettlementAt in ThreadSettlementPolicy.ts now returns an ISO timestamp instead of a boolean; ThreadSettlementReactor includes it on thread.auto-settle commands, and the decider in decider.ts persists it as settledAt while updatedAt remains the event time
  • Adds ThreadAutoSettleCommand.settledAt as a required field in orchestration.ts, making commands schema-invalid without a valid settlement timestamp
  • Adds migration 045 in 045_RepairAutomaticSettlementTimestamps.ts to fix legacy projection rows where automatic settledAt equals the event time, replacing it with the latest pre-settlement activity or creation timestamp without touching orchestration event payloads
  • Introduces shared resolveSettledThreadTimestamp in threadSort.ts and adopts it across web sidebar sorting/labels and mobile settled-row ordering and display so clients prefer persisted settledAt, then latest activity, then updatedAt
  • Risk: any out-of-tree consumer dispatching thread.auto-settle without settledAt will now fail schema validation; migration 045 rewrites settled_at on projection rows for automatic settlements where it matched occurred_at, so deployments should verify the migration completes before serving reads

Macroscope summarized 673f2cd.

@chatgpt-codex-connector

chatgpt-codex-connectorBot commented Sep 2, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

ReviewStatusCommitReview trigger
📝 Code ReviewCompleted2026-09-02T19:30:23.274174Z71940bcNew commits
🔒 Security ReviewCompleted2026-09-02T19:07:08.772979Za77a10dPR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Sep 2, 2026
Comment threadapps/server/src/orchestration/ThreadSettlementPolicy.ts Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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:a77a10d157

ℹ️ 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 threaddocs/user/thread-sidebar.md Outdated
Comment threadapps/server/src/orchestration/ThreadSettlementPolicy.ts Outdated

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a77a10d. Configure here.

Comment threadapps/server/src/orchestration/ThreadSettlementPolicy.ts Outdated
@macroscopeapp

macroscopeappBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Would Approve

Macroscope's review found this PR approvable — This is a focused correction to automatic settlement timestamps, with coordinated server persistence, bounded repair of legacy projections, and consistent web/mobile display ordering. The change introduces no new workflow, product default, infrastructure change, or static-analysis override, and the affected behavior is covered by targeted tests.

Not approved because:

  • Monthly spending limit reached (workspace setting). Approvability relies on correctness review in order to determine eligibility

Review your spending limits in Billing settings. You can add or adjust custom eligibility rules. Learn more.

eimexdevand others added 2 commits September 2, 2026 12:25
Drop the orchestration_events rewrite from migration 045. Projectors and
the engine bootstrap from projection rows and cursors, never a full
replay, so repairing projection_threads is enough and the event log
stays as recorded. The migration is a single UPDATE and explains why the
settledAt == occurred_at match identifies an unrepaired sweep.
Migration test covers the no-activity fallback, activity after the sweep,
and asserts event payloads are untouched. Engine tests stamp a distinct
past settledAt and assert it survives while updatedAt stays the command
time; previously they passed the sweep time and asserted nothing.
Remove the resolveSettledTimestamp alias on web and have both call sites
import the client-runtime helper directly. Mobile slim rows drop the
unreachable createdAt fallback. Move the settled ordering line in the
user docs into its own paragraph.
Co-Authored-By: Claude Code <noreply@anthropic.com>
@juliusmarminge

Copy link
Copy Markdown
Member

Pushed 673f2cd to this branch with a few changes on top of the review:

  • Migration 045 no longer rewrites orchestration_events. Projectors bootstrap from projection_state cursors and the engine read model comes from ProjectionSnapshotQuery, so nothing replays the full log. Repairing projection_threads.settled_at is sufficient, and the event log stays as recorded. The migration is now one UPDATE with a comment on why settledAt == occurred_at identifies an unrepaired sweep.
  • Migration test covers the no-activity created_at fallback, activity after the sweep being ignored, and asserts event payloads are byte-identical before and after.
  • Engine tests passed settledAt: now() (the sweep time, i.e. the bug) and only asserted settledOverride. They now pass a distinct past stamp and assert it survives while updatedAt stays the command time.
  • Removed the resolveSettledTimestamp alias in Sidebar.logic.ts; both web call sites import resolveSettledThreadTimestamp directly.
  • Mobile slim rows drop the ?? thread.createdAt fallback, which was unreachable since the resolver already falls through to updatedAt.
  • User doc: settled ordering is its own paragraph instead of a sentence inside the settlement-rules paragraph.

Thanks for the fix, the core change was right.

@eimexdev

Copy link
Copy Markdown
ContributorAuthor

rad! Thanks for the review!

macroscopeapp[bot]
macroscopeappBot previously approved these changes Sep 2, 2026
Migration 045 was taken by ProjectionProjectsAutoPull on main, so the
settlement repair moves to 046. The test also picks up main's move of
NodeSqliteClient into @t3tools/shared.
Co-Authored-By: Claude Code <noreply@anthropic.com>
@macroscopeapp
macroscopeappBot dismissed their stale reviewSeptember 3, 2026 00:08

Dismissing prior approval to re-evaluate ab67483

@juliusmarminge
juliusmarminge merged commit 2971ec3 into pingdotgg:mainSep 3, 2026
27 checks passed
github-actionsBot added a commit to omarcresp/t3code-flake that referenced this pull request Sep 3, 2026
## What's Changed
* feat(desktop): browser profiles for the preview browser by @juliusmarminge in pingdotgg/t3code#7254
* refactor(shared): move the node:sqlite Effect SQL client into shared by @juliusmarminge in pingdotgg/t3code#7272
* feat(web): add opt-in panel animations by @maria-rcks in pingdotgg/t3code#8830
* feat(projects): automatically pull clean default branches by @maria-rcks in pingdotgg/t3code#9277
* fix(web): show pull request state icons in tabs by @flamboh in pingdotgg/t3code#9112
* feat(providers): add context compaction across harnesses by @maria-rcks in pingdotgg/t3code#8808
* feat(web): add proactive panels by @maria-rcks in pingdotgg/t3code#9276
* fix(web): unify control sizing across settings pages by @juliusmarminge in pingdotgg/t3code#9281
* fix(web): offer browser profiles from the empty-panel launcher by @juliusmarminge in pingdotgg/t3code#9279
* Revert "feat(providers): add context compaction across harnesses" by @maria-rcks in pingdotgg/t3code#9284
* fix(web): show scroll-to-end as soon as the last message slips under the composer by @juliusmarminge in pingdotgg/t3code#9280
* fix(cursor): honor auto and full access modes by @maria-rcks in pingdotgg/t3code#9283
* fix(desktop): detect installed Spectre libs for Windows builds by @juliusmarminge in pingdotgg/t3code#9285
* fix(pull-requests): missing features & better behaviour by @maria-rcks in pingdotgg/t3code#9188
* fix(providers): discover workspace skills everywhere by @maria-rcks in pingdotgg/t3code#9180
* fix(server): preserve automatic settlement timestamps by @eimexdev in pingdotgg/t3code#9254
* fix(opencode): show Reasoning selector for OpenCode models by @maria-rcks in pingdotgg/t3code#9287
* feat(web): preview document attachments in the file viewer by @juliusmarminge in pingdotgg/t3code#9292
* chore(ci): narrow the UI consistency check-run agent by @juliusmarminge in pingdotgg/t3code#9297
**Full Changelog**: pingdotgg/t3code@v0.0.39-nightly.20260902.1261...v0.0.39-nightly.20260903.1262
Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.39-nightly.20260903.1262
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@eimexdev@juliusmarminge
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

fix(server): preserve automatic settlement timestamps - #9254

Merged
juliusmarminge merged 4 commits into
pingdotgg:mainfrom
eimexdev:fix/auto-settlement-timestamps
Sep 3, 2026
Merged

fix(server): preserve automatic settlement timestamps#9254
juliusmarminge merged 4 commits into
pingdotgg:mainfrom
eimexdev:fix/auto-settlement-timestamps

Conversation

@eimexdev

@eimexdeveimexdev commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Problem

Server-side auto-settlement records the sweep time as settledAt. On startup, old threads therefore look newly settled and receive incorrect dates and ordering. #9081 suppresses the resulting notifications, but does not correct the durable timestamp.

Fix

  • Carry the latest user/turn activity timestamp through the internal auto-settle command.
  • Keep updatedAt at command time, preserving normal update semantics.
  • Repair projection_threads.settled_at for identifiable automatic settlements, without changing manual or later re-settled timestamps. The event log is left as recorded: projections and the engine bootstrap from projection rows and cursors, so a projection-only repair is sufficient.
  • Web and mobile sort and label the Settled shelf by the same shared resolveSettledThreadTimestamp.
  • Document the settled-shelf ordering behavior.

Refs #9057
Pairs with #9081

Verification

  • Focused server, client-runtime, web, and mobile tests for the touched files
  • Server, contracts, client-runtime, web, and mobile typechecks
  • Targeted lint and formatting check

Made with GPT-5.6 Sol in T3 Code through the Codex harness. Follow-up commit by Claude Fable 5 in Claude Code.


Note

Medium Risk
Schema-breaking thread.auto-settle now requires settledAt, and migration 046 rewrites settled timestamps on projection rows for identifiable automatic settlements—deployments should run migrations before relying on sidebar ordering.

Overview
Automatic thread settlement now persists when work ended, not when the server sweep ran. resolveAutoSettlementAt returns the activity timestamp (or null); ThreadSettlementReactor passes it as required settledAt on thread.auto-settle, and the decider writes that to settledAt while updatedAt stays the command time.

Migration 046 repairs legacy projection_threads.settled_at rows where auto-settlement stamped the sweep time (identified via server auto-settle events). Manual and later re-settled threads are left alone; orchestration event payloads are unchanged.

Clients share resolveSettledThreadTimestamp from client-runtime so web and mobile sort and label the Settled shelf from the same stamp (settledAt, then latest activity, then updatedAt). Docs describe that ordering behavior.

Reviewed by Cursor Bugbot for commit ab67483. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Preserve settledAt timestamp in automatic thread settlement and repair legacy projections

  • resolveAutoSettlementAt in ThreadSettlementPolicy.ts now returns an ISO timestamp instead of a boolean; ThreadSettlementReactor includes it on thread.auto-settle commands, and the decider in decider.ts persists it as settledAt while updatedAt remains the event time
  • Adds ThreadAutoSettleCommand.settledAt as a required field in orchestration.ts, making commands schema-invalid without a valid settlement timestamp
  • Adds migration 045 in 045_RepairAutomaticSettlementTimestamps.ts to fix legacy projection rows where automatic settledAt equals the event time, replacing it with the latest pre-settlement activity or creation timestamp without touching orchestration event payloads
  • Introduces shared resolveSettledThreadTimestamp in threadSort.ts and adopts it across web sidebar sorting/labels and mobile settled-row ordering and display so clients prefer persisted settledAt, then latest activity, then updatedAt
  • Risk: any out-of-tree consumer dispatching thread.auto-settle without settledAt will now fail schema validation; migration 045 rewrites settled_at on projection rows for automatic settlements where it matched occurred_at, so deployments should verify the migration completes before serving reads

Macroscope summarized 673f2cd.

@chatgpt-codex-connector

chatgpt-codex-connectorBot commented Sep 2, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

ReviewStatusCommitReview trigger
📝 Code ReviewCompleted2026-09-02T19:30:23.274174Z71940bcNew commits
🔒 Security ReviewCompleted2026-09-02T19:07:08.772979Za77a10dPR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Sep 2, 2026
Comment threadapps/server/src/orchestration/ThreadSettlementPolicy.ts Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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:a77a10d157

ℹ️ 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 threaddocs/user/thread-sidebar.md Outdated
Comment threadapps/server/src/orchestration/ThreadSettlementPolicy.ts Outdated

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a77a10d. Configure here.

Comment threadapps/server/src/orchestration/ThreadSettlementPolicy.ts Outdated
@macroscopeapp

macroscopeappBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Would Approve

Macroscope's review found this PR approvable — This is a focused correction to automatic settlement timestamps, with coordinated server persistence, bounded repair of legacy projections, and consistent web/mobile display ordering. The change introduces no new workflow, product default, infrastructure change, or static-analysis override, and the affected behavior is covered by targeted tests.

Not approved because:

  • Monthly spending limit reached (workspace setting). Approvability relies on correctness review in order to determine eligibility

Review your spending limits in Billing settings. You can add or adjust custom eligibility rules. Learn more.

eimexdevand others added 2 commits September 2, 2026 12:25
Drop the orchestration_events rewrite from migration 045. Projectors and
the engine bootstrap from projection rows and cursors, never a full
replay, so repairing projection_threads is enough and the event log
stays as recorded. The migration is a single UPDATE and explains why the
settledAt == occurred_at match identifies an unrepaired sweep.
Migration test covers the no-activity fallback, activity after the sweep,
and asserts event payloads are untouched. Engine tests stamp a distinct
past settledAt and assert it survives while updatedAt stays the command
time; previously they passed the sweep time and asserted nothing.
Remove the resolveSettledTimestamp alias on web and have both call sites
import the client-runtime helper directly. Mobile slim rows drop the
unreachable createdAt fallback. Move the settled ordering line in the
user docs into its own paragraph.
Co-Authored-By: Claude Code <noreply@anthropic.com>
@juliusmarminge

Copy link
Copy Markdown
Member

Pushed 673f2cd to this branch with a few changes on top of the review:

  • Migration 045 no longer rewrites orchestration_events. Projectors bootstrap from projection_state cursors and the engine read model comes from ProjectionSnapshotQuery, so nothing replays the full log. Repairing projection_threads.settled_at is sufficient, and the event log stays as recorded. The migration is now one UPDATE with a comment on why settledAt == occurred_at identifies an unrepaired sweep.
  • Migration test covers the no-activity created_at fallback, activity after the sweep being ignored, and asserts event payloads are byte-identical before and after.
  • Engine tests passed settledAt: now() (the sweep time, i.e. the bug) and only asserted settledOverride. They now pass a distinct past stamp and assert it survives while updatedAt stays the command time.
  • Removed the resolveSettledTimestamp alias in Sidebar.logic.ts; both web call sites import resolveSettledThreadTimestamp directly.
  • Mobile slim rows drop the ?? thread.createdAt fallback, which was unreachable since the resolver already falls through to updatedAt.
  • User doc: settled ordering is its own paragraph instead of a sentence inside the settlement-rules paragraph.

Thanks for the fix, the core change was right.

@eimexdev

Copy link
Copy Markdown
ContributorAuthor

rad! Thanks for the review!

macroscopeapp[bot]
macroscopeappBot previously approved these changes Sep 2, 2026
Migration 045 was taken by ProjectionProjectsAutoPull on main, so the
settlement repair moves to 046. The test also picks up main's move of
NodeSqliteClient into @t3tools/shared.
Co-Authored-By: Claude Code <noreply@anthropic.com>
@macroscopeapp
macroscopeappBot dismissed their stale reviewSeptember 3, 2026 00:08

Dismissing prior approval to re-evaluate ab67483

@juliusmarminge
juliusmarminge merged commit 2971ec3 into pingdotgg:mainSep 3, 2026
27 checks passed
github-actionsBot added a commit to omarcresp/t3code-flake that referenced this pull request Sep 3, 2026
## What's Changed
* feat(desktop): browser profiles for the preview browser by @juliusmarminge in pingdotgg/t3code#7254
* refactor(shared): move the node:sqlite Effect SQL client into shared by @juliusmarminge in pingdotgg/t3code#7272
* feat(web): add opt-in panel animations by @maria-rcks in pingdotgg/t3code#8830
* feat(projects): automatically pull clean default branches by @maria-rcks in pingdotgg/t3code#9277
* fix(web): show pull request state icons in tabs by @flamboh in pingdotgg/t3code#9112
* feat(providers): add context compaction across harnesses by @maria-rcks in pingdotgg/t3code#8808
* feat(web): add proactive panels by @maria-rcks in pingdotgg/t3code#9276
* fix(web): unify control sizing across settings pages by @juliusmarminge in pingdotgg/t3code#9281
* fix(web): offer browser profiles from the empty-panel launcher by @juliusmarminge in pingdotgg/t3code#9279
* Revert "feat(providers): add context compaction across harnesses" by @maria-rcks in pingdotgg/t3code#9284
* fix(web): show scroll-to-end as soon as the last message slips under the composer by @juliusmarminge in pingdotgg/t3code#9280
* fix(cursor): honor auto and full access modes by @maria-rcks in pingdotgg/t3code#9283
* fix(desktop): detect installed Spectre libs for Windows builds by @juliusmarminge in pingdotgg/t3code#9285
* fix(pull-requests): missing features & better behaviour by @maria-rcks in pingdotgg/t3code#9188
* fix(providers): discover workspace skills everywhere by @maria-rcks in pingdotgg/t3code#9180
* fix(server): preserve automatic settlement timestamps by @eimexdev in pingdotgg/t3code#9254
* fix(opencode): show Reasoning selector for OpenCode models by @maria-rcks in pingdotgg/t3code#9287
* feat(web): preview document attachments in the file viewer by @juliusmarminge in pingdotgg/t3code#9292
* chore(ci): narrow the UI consistency check-run agent by @juliusmarminge in pingdotgg/t3code#9297
**Full Changelog**: pingdotgg/t3code@v0.0.39-nightly.20260902.1261...v0.0.39-nightly.20260903.1262
Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.39-nightly.20260903.1262
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@eimexdev@juliusmarminge
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(server): preserve automatic settlement timestamps - #9254

Merged
juliusmarminge merged 4 commits into
pingdotgg:mainfrom
eimexdev:fix/auto-settlement-timestamps
Sep 3, 2026
Merged

fix(server): preserve automatic settlement timestamps#9254
juliusmarminge merged 4 commits into
pingdotgg:mainfrom
eimexdev:fix/auto-settlement-timestamps

Conversation

@eimexdev

@eimexdeveimexdev commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Problem

Server-side auto-settlement records the sweep time as settledAt. On startup, old threads therefore look newly settled and receive incorrect dates and ordering. #9081 suppresses the resulting notifications, but does not correct the durable timestamp.

Fix

  • Carry the latest user/turn activity timestamp through the internal auto-settle command.
  • Keep updatedAt at command time, preserving normal update semantics.
  • Repair projection_threads.settled_at for identifiable automatic settlements, without changing manual or later re-settled timestamps. The event log is left as recorded: projections and the engine bootstrap from projection rows and cursors, so a projection-only repair is sufficient.
  • Web and mobile sort and label the Settled shelf by the same shared resolveSettledThreadTimestamp.
  • Document the settled-shelf ordering behavior.

Refs #9057
Pairs with #9081

Verification

  • Focused server, client-runtime, web, and mobile tests for the touched files
  • Server, contracts, client-runtime, web, and mobile typechecks
  • Targeted lint and formatting check

Made with GPT-5.6 Sol in T3 Code through the Codex harness. Follow-up commit by Claude Fable 5 in Claude Code.


Note

Medium Risk
Schema-breaking thread.auto-settle now requires settledAt, and migration 046 rewrites settled timestamps on projection rows for identifiable automatic settlements—deployments should run migrations before relying on sidebar ordering.

Overview
Automatic thread settlement now persists when work ended, not when the server sweep ran. resolveAutoSettlementAt returns the activity timestamp (or null); ThreadSettlementReactor passes it as required settledAt on thread.auto-settle, and the decider writes that to settledAt while updatedAt stays the command time.

Migration 046 repairs legacy projection_threads.settled_at rows where auto-settlement stamped the sweep time (identified via server auto-settle events). Manual and later re-settled threads are left alone; orchestration event payloads are unchanged.

Clients share resolveSettledThreadTimestamp from client-runtime so web and mobile sort and label the Settled shelf from the same stamp (settledAt, then latest activity, then updatedAt). Docs describe that ordering behavior.

Reviewed by Cursor Bugbot for commit ab67483. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Preserve settledAt timestamp in automatic thread settlement and repair legacy projections

  • resolveAutoSettlementAt in ThreadSettlementPolicy.ts now returns an ISO timestamp instead of a boolean; ThreadSettlementReactor includes it on thread.auto-settle commands, and the decider in decider.ts persists it as settledAt while updatedAt remains the event time
  • Adds ThreadAutoSettleCommand.settledAt as a required field in orchestration.ts, making commands schema-invalid without a valid settlement timestamp
  • Adds migration 045 in 045_RepairAutomaticSettlementTimestamps.ts to fix legacy projection rows where automatic settledAt equals the event time, replacing it with the latest pre-settlement activity or creation timestamp without touching orchestration event payloads
  • Introduces shared resolveSettledThreadTimestamp in threadSort.ts and adopts it across web sidebar sorting/labels and mobile settled-row ordering and display so clients prefer persisted settledAt, then latest activity, then updatedAt
  • Risk: any out-of-tree consumer dispatching thread.auto-settle without settledAt will now fail schema validation; migration 045 rewrites settled_at on projection rows for automatic settlements where it matched occurred_at, so deployments should verify the migration completes before serving reads

Macroscope summarized 673f2cd.

@chatgpt-codex-connector

chatgpt-codex-connectorBot commented Sep 2, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

ReviewStatusCommitReview trigger
📝 Code ReviewCompleted2026-09-02T19:30:23.274174Z71940bcNew commits
🔒 Security ReviewCompleted2026-09-02T19:07:08.772979Za77a10dPR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Sep 2, 2026
Comment threadapps/server/src/orchestration/ThreadSettlementPolicy.ts Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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:a77a10d157

ℹ️ 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 threaddocs/user/thread-sidebar.md Outdated
Comment threadapps/server/src/orchestration/ThreadSettlementPolicy.ts Outdated

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a77a10d. Configure here.

Comment threadapps/server/src/orchestration/ThreadSettlementPolicy.ts Outdated
@macroscopeapp

macroscopeappBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Would Approve

Macroscope's review found this PR approvable — This is a focused correction to automatic settlement timestamps, with coordinated server persistence, bounded repair of legacy projections, and consistent web/mobile display ordering. The change introduces no new workflow, product default, infrastructure change, or static-analysis override, and the affected behavior is covered by targeted tests.

Not approved because:

  • Monthly spending limit reached (workspace setting). Approvability relies on correctness review in order to determine eligibility

Review your spending limits in Billing settings. You can add or adjust custom eligibility rules. Learn more.

eimexdevand others added 2 commits September 2, 2026 12:25
Drop the orchestration_events rewrite from migration 045. Projectors and
the engine bootstrap from projection rows and cursors, never a full
replay, so repairing projection_threads is enough and the event log
stays as recorded. The migration is a single UPDATE and explains why the
settledAt == occurred_at match identifies an unrepaired sweep.
Migration test covers the no-activity fallback, activity after the sweep,
and asserts event payloads are untouched. Engine tests stamp a distinct
past settledAt and assert it survives while updatedAt stays the command
time; previously they passed the sweep time and asserted nothing.
Remove the resolveSettledTimestamp alias on web and have both call sites
import the client-runtime helper directly. Mobile slim rows drop the
unreachable createdAt fallback. Move the settled ordering line in the
user docs into its own paragraph.
Co-Authored-By: Claude Code <noreply@anthropic.com>
@juliusmarminge

Copy link
Copy Markdown
Member

Pushed 673f2cd to this branch with a few changes on top of the review:

  • Migration 045 no longer rewrites orchestration_events. Projectors bootstrap from projection_state cursors and the engine read model comes from ProjectionSnapshotQuery, so nothing replays the full log. Repairing projection_threads.settled_at is sufficient, and the event log stays as recorded. The migration is now one UPDATE with a comment on why settledAt == occurred_at identifies an unrepaired sweep.
  • Migration test covers the no-activity created_at fallback, activity after the sweep being ignored, and asserts event payloads are byte-identical before and after.
  • Engine tests passed settledAt: now() (the sweep time, i.e. the bug) and only asserted settledOverride. They now pass a distinct past stamp and assert it survives while updatedAt stays the command time.
  • Removed the resolveSettledTimestamp alias in Sidebar.logic.ts; both web call sites import resolveSettledThreadTimestamp directly.
  • Mobile slim rows drop the ?? thread.createdAt fallback, which was unreachable since the resolver already falls through to updatedAt.
  • User doc: settled ordering is its own paragraph instead of a sentence inside the settlement-rules paragraph.

Thanks for the fix, the core change was right.

@eimexdev

Copy link
Copy Markdown
ContributorAuthor

rad! Thanks for the review!

macroscopeapp[bot]
macroscopeappBot previously approved these changes Sep 2, 2026
Migration 045 was taken by ProjectionProjectsAutoPull on main, so the
settlement repair moves to 046. The test also picks up main's move of
NodeSqliteClient into @t3tools/shared.
Co-Authored-By: Claude Code <noreply@anthropic.com>
@macroscopeapp
macroscopeappBot dismissed their stale reviewSeptember 3, 2026 00:08

Dismissing prior approval to re-evaluate ab67483

@juliusmarminge
juliusmarminge merged commit 2971ec3 into pingdotgg:mainSep 3, 2026
27 checks passed
github-actionsBot added a commit to omarcresp/t3code-flake that referenced this pull request Sep 3, 2026
## What's Changed
* feat(desktop): browser profiles for the preview browser by @juliusmarminge in pingdotgg/t3code#7254
* refactor(shared): move the node:sqlite Effect SQL client into shared by @juliusmarminge in pingdotgg/t3code#7272
* feat(web): add opt-in panel animations by @maria-rcks in pingdotgg/t3code#8830
* feat(projects): automatically pull clean default branches by @maria-rcks in pingdotgg/t3code#9277
* fix(web): show pull request state icons in tabs by @flamboh in pingdotgg/t3code#9112
* feat(providers): add context compaction across harnesses by @maria-rcks in pingdotgg/t3code#8808
* feat(web): add proactive panels by @maria-rcks in pingdotgg/t3code#9276
* fix(web): unify control sizing across settings pages by @juliusmarminge in pingdotgg/t3code#9281
* fix(web): offer browser profiles from the empty-panel launcher by @juliusmarminge in pingdotgg/t3code#9279
* Revert "feat(providers): add context compaction across harnesses" by @maria-rcks in pingdotgg/t3code#9284
* fix(web): show scroll-to-end as soon as the last message slips under the composer by @juliusmarminge in pingdotgg/t3code#9280
* fix(cursor): honor auto and full access modes by @maria-rcks in pingdotgg/t3code#9283
* fix(desktop): detect installed Spectre libs for Windows builds by @juliusmarminge in pingdotgg/t3code#9285
* fix(pull-requests): missing features & better behaviour by @maria-rcks in pingdotgg/t3code#9188
* fix(providers): discover workspace skills everywhere by @maria-rcks in pingdotgg/t3code#9180
* fix(server): preserve automatic settlement timestamps by @eimexdev in pingdotgg/t3code#9254
* fix(opencode): show Reasoning selector for OpenCode models by @maria-rcks in pingdotgg/t3code#9287
* feat(web): preview document attachments in the file viewer by @juliusmarminge in pingdotgg/t3code#9292
* chore(ci): narrow the UI consistency check-run agent by @juliusmarminge in pingdotgg/t3code#9297
**Full Changelog**: pingdotgg/t3code@v0.0.39-nightly.20260902.1261...v0.0.39-nightly.20260903.1262
Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.39-nightly.20260903.1262
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@eimexdev@juliusmarminge
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(server): preserve automatic settlement timestamps - #9254

Merged
juliusmarminge merged 4 commits into
pingdotgg:mainfrom
eimexdev:fix/auto-settlement-timestamps
Sep 3, 2026
Merged

fix(server): preserve automatic settlement timestamps#9254
juliusmarminge merged 4 commits into
pingdotgg:mainfrom
eimexdev:fix/auto-settlement-timestamps

Conversation

@eimexdev

@eimexdeveimexdev commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Problem

Server-side auto-settlement records the sweep time as settledAt. On startup, old threads therefore look newly settled and receive incorrect dates and ordering. #9081 suppresses the resulting notifications, but does not correct the durable timestamp.

Fix

  • Carry the latest user/turn activity timestamp through the internal auto-settle command.
  • Keep updatedAt at command time, preserving normal update semantics.
  • Repair projection_threads.settled_at for identifiable automatic settlements, without changing manual or later re-settled timestamps. The event log is left as recorded: projections and the engine bootstrap from projection rows and cursors, so a projection-only repair is sufficient.
  • Web and mobile sort and label the Settled shelf by the same shared resolveSettledThreadTimestamp.
  • Document the settled-shelf ordering behavior.

Refs #9057
Pairs with #9081

Verification

  • Focused server, client-runtime, web, and mobile tests for the touched files
  • Server, contracts, client-runtime, web, and mobile typechecks
  • Targeted lint and formatting check

Made with GPT-5.6 Sol in T3 Code through the Codex harness. Follow-up commit by Claude Fable 5 in Claude Code.


Note

Medium Risk
Schema-breaking thread.auto-settle now requires settledAt, and migration 046 rewrites settled timestamps on projection rows for identifiable automatic settlements—deployments should run migrations before relying on sidebar ordering.

Overview
Automatic thread settlement now persists when work ended, not when the server sweep ran. resolveAutoSettlementAt returns the activity timestamp (or null); ThreadSettlementReactor passes it as required settledAt on thread.auto-settle, and the decider writes that to settledAt while updatedAt stays the command time.

Migration 046 repairs legacy projection_threads.settled_at rows where auto-settlement stamped the sweep time (identified via server auto-settle events). Manual and later re-settled threads are left alone; orchestration event payloads are unchanged.

Clients share resolveSettledThreadTimestamp from client-runtime so web and mobile sort and label the Settled shelf from the same stamp (settledAt, then latest activity, then updatedAt). Docs describe that ordering behavior.

Reviewed by Cursor Bugbot for commit ab67483. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Preserve settledAt timestamp in automatic thread settlement and repair legacy projections

  • resolveAutoSettlementAt in ThreadSettlementPolicy.ts now returns an ISO timestamp instead of a boolean; ThreadSettlementReactor includes it on thread.auto-settle commands, and the decider in decider.ts persists it as settledAt while updatedAt remains the event time
  • Adds ThreadAutoSettleCommand.settledAt as a required field in orchestration.ts, making commands schema-invalid without a valid settlement timestamp
  • Adds migration 045 in 045_RepairAutomaticSettlementTimestamps.ts to fix legacy projection rows where automatic settledAt equals the event time, replacing it with the latest pre-settlement activity or creation timestamp without touching orchestration event payloads
  • Introduces shared resolveSettledThreadTimestamp in threadSort.ts and adopts it across web sidebar sorting/labels and mobile settled-row ordering and display so clients prefer persisted settledAt, then latest activity, then updatedAt
  • Risk: any out-of-tree consumer dispatching thread.auto-settle without settledAt will now fail schema validation; migration 045 rewrites settled_at on projection rows for automatic settlements where it matched occurred_at, so deployments should verify the migration completes before serving reads

Macroscope summarized 673f2cd.

@chatgpt-codex-connector

chatgpt-codex-connectorBot commented Sep 2, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

ReviewStatusCommitReview trigger
📝 Code ReviewCompleted2026-09-02T19:30:23.274174Z71940bcNew commits
🔒 Security ReviewCompleted2026-09-02T19:07:08.772979Za77a10dPR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Sep 2, 2026
Comment threadapps/server/src/orchestration/ThreadSettlementPolicy.ts Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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:a77a10d157

ℹ️ 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 threaddocs/user/thread-sidebar.md Outdated
Comment threadapps/server/src/orchestration/ThreadSettlementPolicy.ts Outdated

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a77a10d. Configure here.

Comment threadapps/server/src/orchestration/ThreadSettlementPolicy.ts Outdated
@macroscopeapp

macroscopeappBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Would Approve

Macroscope's review found this PR approvable — This is a focused correction to automatic settlement timestamps, with coordinated server persistence, bounded repair of legacy projections, and consistent web/mobile display ordering. The change introduces no new workflow, product default, infrastructure change, or static-analysis override, and the affected behavior is covered by targeted tests.

Not approved because:

  • Monthly spending limit reached (workspace setting). Approvability relies on correctness review in order to determine eligibility

Review your spending limits in Billing settings. You can add or adjust custom eligibility rules. Learn more.

eimexdevand others added 2 commits September 2, 2026 12:25
Drop the orchestration_events rewrite from migration 045. Projectors and
the engine bootstrap from projection rows and cursors, never a full
replay, so repairing projection_threads is enough and the event log
stays as recorded. The migration is a single UPDATE and explains why the
settledAt == occurred_at match identifies an unrepaired sweep.
Migration test covers the no-activity fallback, activity after the sweep,
and asserts event payloads are untouched. Engine tests stamp a distinct
past settledAt and assert it survives while updatedAt stays the command
time; previously they passed the sweep time and asserted nothing.
Remove the resolveSettledTimestamp alias on web and have both call sites
import the client-runtime helper directly. Mobile slim rows drop the
unreachable createdAt fallback. Move the settled ordering line in the
user docs into its own paragraph.
Co-Authored-By: Claude Code <noreply@anthropic.com>
@juliusmarminge

Copy link
Copy Markdown
Member

Pushed 673f2cd to this branch with a few changes on top of the review:

  • Migration 045 no longer rewrites orchestration_events. Projectors bootstrap from projection_state cursors and the engine read model comes from ProjectionSnapshotQuery, so nothing replays the full log. Repairing projection_threads.settled_at is sufficient, and the event log stays as recorded. The migration is now one UPDATE with a comment on why settledAt == occurred_at identifies an unrepaired sweep.
  • Migration test covers the no-activity created_at fallback, activity after the sweep being ignored, and asserts event payloads are byte-identical before and after.
  • Engine tests passed settledAt: now() (the sweep time, i.e. the bug) and only asserted settledOverride. They now pass a distinct past stamp and assert it survives while updatedAt stays the command time.
  • Removed the resolveSettledTimestamp alias in Sidebar.logic.ts; both web call sites import resolveSettledThreadTimestamp directly.
  • Mobile slim rows drop the ?? thread.createdAt fallback, which was unreachable since the resolver already falls through to updatedAt.
  • User doc: settled ordering is its own paragraph instead of a sentence inside the settlement-rules paragraph.

Thanks for the fix, the core change was right.

@eimexdev

Copy link
Copy Markdown
ContributorAuthor

rad! Thanks for the review!

macroscopeapp[bot]
macroscopeappBot previously approved these changes Sep 2, 2026
Migration 045 was taken by ProjectionProjectsAutoPull on main, so the
settlement repair moves to 046. The test also picks up main's move of
NodeSqliteClient into @t3tools/shared.
Co-Authored-By: Claude Code <noreply@anthropic.com>
@macroscopeapp
macroscopeappBot dismissed their stale reviewSeptember 3, 2026 00:08

Dismissing prior approval to re-evaluate ab67483

@juliusmarminge
juliusmarminge merged commit 2971ec3 into pingdotgg:mainSep 3, 2026
27 checks passed
github-actionsBot added a commit to omarcresp/t3code-flake that referenced this pull request Sep 3, 2026
## What's Changed
* feat(desktop): browser profiles for the preview browser by @juliusmarminge in pingdotgg/t3code#7254
* refactor(shared): move the node:sqlite Effect SQL client into shared by @juliusmarminge in pingdotgg/t3code#7272
* feat(web): add opt-in panel animations by @maria-rcks in pingdotgg/t3code#8830
* feat(projects): automatically pull clean default branches by @maria-rcks in pingdotgg/t3code#9277
* fix(web): show pull request state icons in tabs by @flamboh in pingdotgg/t3code#9112
* feat(providers): add context compaction across harnesses by @maria-rcks in pingdotgg/t3code#8808
* feat(web): add proactive panels by @maria-rcks in pingdotgg/t3code#9276
* fix(web): unify control sizing across settings pages by @juliusmarminge in pingdotgg/t3code#9281
* fix(web): offer browser profiles from the empty-panel launcher by @juliusmarminge in pingdotgg/t3code#9279
* Revert "feat(providers): add context compaction across harnesses" by @maria-rcks in pingdotgg/t3code#9284
* fix(web): show scroll-to-end as soon as the last message slips under the composer by @juliusmarminge in pingdotgg/t3code#9280
* fix(cursor): honor auto and full access modes by @maria-rcks in pingdotgg/t3code#9283
* fix(desktop): detect installed Spectre libs for Windows builds by @juliusmarminge in pingdotgg/t3code#9285
* fix(pull-requests): missing features & better behaviour by @maria-rcks in pingdotgg/t3code#9188
* fix(providers): discover workspace skills everywhere by @maria-rcks in pingdotgg/t3code#9180
* fix(server): preserve automatic settlement timestamps by @eimexdev in pingdotgg/t3code#9254
* fix(opencode): show Reasoning selector for OpenCode models by @maria-rcks in pingdotgg/t3code#9287
* feat(web): preview document attachments in the file viewer by @juliusmarminge in pingdotgg/t3code#9292
* chore(ci): narrow the UI consistency check-run agent by @juliusmarminge in pingdotgg/t3code#9297
**Full Changelog**: pingdotgg/t3code@v0.0.39-nightly.20260902.1261...v0.0.39-nightly.20260903.1262
Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.39-nightly.20260903.1262
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@eimexdev@juliusmarminge
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

fix(server): preserve automatic settlement timestamps - #9254

Merged
juliusmarminge merged 4 commits into
pingdotgg:mainfrom
eimexdev:fix/auto-settlement-timestamps
Sep 3, 2026
Merged

fix(server): preserve automatic settlement timestamps#9254
juliusmarminge merged 4 commits into
pingdotgg:mainfrom
eimexdev:fix/auto-settlement-timestamps

Conversation

@eimexdev

@eimexdeveimexdev commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Problem

Server-side auto-settlement records the sweep time as settledAt. On startup, old threads therefore look newly settled and receive incorrect dates and ordering. #9081 suppresses the resulting notifications, but does not correct the durable timestamp.

Fix

  • Carry the latest user/turn activity timestamp through the internal auto-settle command.
  • Keep updatedAt at command time, preserving normal update semantics.
  • Repair projection_threads.settled_at for identifiable automatic settlements, without changing manual or later re-settled timestamps. The event log is left as recorded: projections and the engine bootstrap from projection rows and cursors, so a projection-only repair is sufficient.
  • Web and mobile sort and label the Settled shelf by the same shared resolveSettledThreadTimestamp.
  • Document the settled-shelf ordering behavior.

Refs #9057
Pairs with #9081

Verification

  • Focused server, client-runtime, web, and mobile tests for the touched files
  • Server, contracts, client-runtime, web, and mobile typechecks
  • Targeted lint and formatting check

Made with GPT-5.6 Sol in T3 Code through the Codex harness. Follow-up commit by Claude Fable 5 in Claude Code.


Note

Medium Risk
Schema-breaking thread.auto-settle now requires settledAt, and migration 046 rewrites settled timestamps on projection rows for identifiable automatic settlements—deployments should run migrations before relying on sidebar ordering.

Overview
Automatic thread settlement now persists when work ended, not when the server sweep ran. resolveAutoSettlementAt returns the activity timestamp (or null); ThreadSettlementReactor passes it as required settledAt on thread.auto-settle, and the decider writes that to settledAt while updatedAt stays the command time.

Migration 046 repairs legacy projection_threads.settled_at rows where auto-settlement stamped the sweep time (identified via server auto-settle events). Manual and later re-settled threads are left alone; orchestration event payloads are unchanged.

Clients share resolveSettledThreadTimestamp from client-runtime so web and mobile sort and label the Settled shelf from the same stamp (settledAt, then latest activity, then updatedAt). Docs describe that ordering behavior.

Reviewed by Cursor Bugbot for commit ab67483. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Preserve settledAt timestamp in automatic thread settlement and repair legacy projections

  • resolveAutoSettlementAt in ThreadSettlementPolicy.ts now returns an ISO timestamp instead of a boolean; ThreadSettlementReactor includes it on thread.auto-settle commands, and the decider in decider.ts persists it as settledAt while updatedAt remains the event time
  • Adds ThreadAutoSettleCommand.settledAt as a required field in orchestration.ts, making commands schema-invalid without a valid settlement timestamp
  • Adds migration 045 in 045_RepairAutomaticSettlementTimestamps.ts to fix legacy projection rows where automatic settledAt equals the event time, replacing it with the latest pre-settlement activity or creation timestamp without touching orchestration event payloads
  • Introduces shared resolveSettledThreadTimestamp in threadSort.ts and adopts it across web sidebar sorting/labels and mobile settled-row ordering and display so clients prefer persisted settledAt, then latest activity, then updatedAt
  • Risk: any out-of-tree consumer dispatching thread.auto-settle without settledAt will now fail schema validation; migration 045 rewrites settled_at on projection rows for automatic settlements where it matched occurred_at, so deployments should verify the migration completes before serving reads

Macroscope summarized 673f2cd.

@chatgpt-codex-connector

chatgpt-codex-connectorBot commented Sep 2, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

ReviewStatusCommitReview trigger
📝 Code ReviewCompleted2026-09-02T19:30:23.274174Z71940bcNew commits
🔒 Security ReviewCompleted2026-09-02T19:07:08.772979Za77a10dPR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Sep 2, 2026
Comment threadapps/server/src/orchestration/ThreadSettlementPolicy.ts Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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:a77a10d157

ℹ️ 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 threaddocs/user/thread-sidebar.md Outdated
Comment threadapps/server/src/orchestration/ThreadSettlementPolicy.ts Outdated

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a77a10d. Configure here.

Comment threadapps/server/src/orchestration/ThreadSettlementPolicy.ts Outdated
@macroscopeapp

macroscopeappBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Would Approve

Macroscope's review found this PR approvable — This is a focused correction to automatic settlement timestamps, with coordinated server persistence, bounded repair of legacy projections, and consistent web/mobile display ordering. The change introduces no new workflow, product default, infrastructure change, or static-analysis override, and the affected behavior is covered by targeted tests.

Not approved because:

  • Monthly spending limit reached (workspace setting). Approvability relies on correctness review in order to determine eligibility

Review your spending limits in Billing settings. You can add or adjust custom eligibility rules. Learn more.

eimexdevand others added 2 commits September 2, 2026 12:25
Drop the orchestration_events rewrite from migration 045. Projectors and
the engine bootstrap from projection rows and cursors, never a full
replay, so repairing projection_threads is enough and the event log
stays as recorded. The migration is a single UPDATE and explains why the
settledAt == occurred_at match identifies an unrepaired sweep.
Migration test covers the no-activity fallback, activity after the sweep,
and asserts event payloads are untouched. Engine tests stamp a distinct
past settledAt and assert it survives while updatedAt stays the command
time; previously they passed the sweep time and asserted nothing.
Remove the resolveSettledTimestamp alias on web and have both call sites
import the client-runtime helper directly. Mobile slim rows drop the
unreachable createdAt fallback. Move the settled ordering line in the
user docs into its own paragraph.
Co-Authored-By: Claude Code <noreply@anthropic.com>
@juliusmarminge

Copy link
Copy Markdown
Member

Pushed 673f2cd to this branch with a few changes on top of the review:

  • Migration 045 no longer rewrites orchestration_events. Projectors bootstrap from projection_state cursors and the engine read model comes from ProjectionSnapshotQuery, so nothing replays the full log. Repairing projection_threads.settled_at is sufficient, and the event log stays as recorded. The migration is now one UPDATE with a comment on why settledAt == occurred_at identifies an unrepaired sweep.
  • Migration test covers the no-activity created_at fallback, activity after the sweep being ignored, and asserts event payloads are byte-identical before and after.
  • Engine tests passed settledAt: now() (the sweep time, i.e. the bug) and only asserted settledOverride. They now pass a distinct past stamp and assert it survives while updatedAt stays the command time.
  • Removed the resolveSettledTimestamp alias in Sidebar.logic.ts; both web call sites import resolveSettledThreadTimestamp directly.
  • Mobile slim rows drop the ?? thread.createdAt fallback, which was unreachable since the resolver already falls through to updatedAt.
  • User doc: settled ordering is its own paragraph instead of a sentence inside the settlement-rules paragraph.

Thanks for the fix, the core change was right.

@eimexdev

Copy link
Copy Markdown
ContributorAuthor

rad! Thanks for the review!

macroscopeapp[bot]
macroscopeappBot previously approved these changes Sep 2, 2026
Migration 045 was taken by ProjectionProjectsAutoPull on main, so the
settlement repair moves to 046. The test also picks up main's move of
NodeSqliteClient into @t3tools/shared.
Co-Authored-By: Claude Code <noreply@anthropic.com>
@macroscopeapp
macroscopeappBot dismissed their stale reviewSeptember 3, 2026 00:08

Dismissing prior approval to re-evaluate ab67483

@juliusmarminge
juliusmarminge merged commit 2971ec3 into pingdotgg:mainSep 3, 2026
27 checks passed
github-actionsBot added a commit to omarcresp/t3code-flake that referenced this pull request Sep 3, 2026
## What's Changed
* feat(desktop): browser profiles for the preview browser by @juliusmarminge in pingdotgg/t3code#7254
* refactor(shared): move the node:sqlite Effect SQL client into shared by @juliusmarminge in pingdotgg/t3code#7272
* feat(web): add opt-in panel animations by @maria-rcks in pingdotgg/t3code#8830
* feat(projects): automatically pull clean default branches by @maria-rcks in pingdotgg/t3code#9277
* fix(web): show pull request state icons in tabs by @flamboh in pingdotgg/t3code#9112
* feat(providers): add context compaction across harnesses by @maria-rcks in pingdotgg/t3code#8808
* feat(web): add proactive panels by @maria-rcks in pingdotgg/t3code#9276
* fix(web): unify control sizing across settings pages by @juliusmarminge in pingdotgg/t3code#9281
* fix(web): offer browser profiles from the empty-panel launcher by @juliusmarminge in pingdotgg/t3code#9279
* Revert "feat(providers): add context compaction across harnesses" by @maria-rcks in pingdotgg/t3code#9284
* fix(web): show scroll-to-end as soon as the last message slips under the composer by @juliusmarminge in pingdotgg/t3code#9280
* fix(cursor): honor auto and full access modes by @maria-rcks in pingdotgg/t3code#9283
* fix(desktop): detect installed Spectre libs for Windows builds by @juliusmarminge in pingdotgg/t3code#9285
* fix(pull-requests): missing features & better behaviour by @maria-rcks in pingdotgg/t3code#9188
* fix(providers): discover workspace skills everywhere by @maria-rcks in pingdotgg/t3code#9180
* fix(server): preserve automatic settlement timestamps by @eimexdev in pingdotgg/t3code#9254
* fix(opencode): show Reasoning selector for OpenCode models by @maria-rcks in pingdotgg/t3code#9287
* feat(web): preview document attachments in the file viewer by @juliusmarminge in pingdotgg/t3code#9292
* chore(ci): narrow the UI consistency check-run agent by @juliusmarminge in pingdotgg/t3code#9297
**Full Changelog**: pingdotgg/t3code@v0.0.39-nightly.20260902.1261...v0.0.39-nightly.20260903.1262
Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.39-nightly.20260903.1262
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@eimexdev@juliusmarminge
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(server): preserve automatic settlement timestamps - #9254

Merged
juliusmarminge merged 4 commits into
pingdotgg:mainfrom
eimexdev:fix/auto-settlement-timestamps
Sep 3, 2026
Merged

fix(server): preserve automatic settlement timestamps#9254
juliusmarminge merged 4 commits into
pingdotgg:mainfrom
eimexdev:fix/auto-settlement-timestamps

Conversation

@eimexdev

@eimexdeveimexdev commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Problem

Server-side auto-settlement records the sweep time as settledAt. On startup, old threads therefore look newly settled and receive incorrect dates and ordering. #9081 suppresses the resulting notifications, but does not correct the durable timestamp.

Fix

  • Carry the latest user/turn activity timestamp through the internal auto-settle command.
  • Keep updatedAt at command time, preserving normal update semantics.
  • Repair projection_threads.settled_at for identifiable automatic settlements, without changing manual or later re-settled timestamps. The event log is left as recorded: projections and the engine bootstrap from projection rows and cursors, so a projection-only repair is sufficient.
  • Web and mobile sort and label the Settled shelf by the same shared resolveSettledThreadTimestamp.
  • Document the settled-shelf ordering behavior.

Refs #9057
Pairs with #9081

Verification

  • Focused server, client-runtime, web, and mobile tests for the touched files
  • Server, contracts, client-runtime, web, and mobile typechecks
  • Targeted lint and formatting check

Made with GPT-5.6 Sol in T3 Code through the Codex harness. Follow-up commit by Claude Fable 5 in Claude Code.


Note

Medium Risk
Schema-breaking thread.auto-settle now requires settledAt, and migration 046 rewrites settled timestamps on projection rows for identifiable automatic settlements—deployments should run migrations before relying on sidebar ordering.

Overview
Automatic thread settlement now persists when work ended, not when the server sweep ran. resolveAutoSettlementAt returns the activity timestamp (or null); ThreadSettlementReactor passes it as required settledAt on thread.auto-settle, and the decider writes that to settledAt while updatedAt stays the command time.

Migration 046 repairs legacy projection_threads.settled_at rows where auto-settlement stamped the sweep time (identified via server auto-settle events). Manual and later re-settled threads are left alone; orchestration event payloads are unchanged.

Clients share resolveSettledThreadTimestamp from client-runtime so web and mobile sort and label the Settled shelf from the same stamp (settledAt, then latest activity, then updatedAt). Docs describe that ordering behavior.

Reviewed by Cursor Bugbot for commit ab67483. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Preserve settledAt timestamp in automatic thread settlement and repair legacy projections

  • resolveAutoSettlementAt in ThreadSettlementPolicy.ts now returns an ISO timestamp instead of a boolean; ThreadSettlementReactor includes it on thread.auto-settle commands, and the decider in decider.ts persists it as settledAt while updatedAt remains the event time
  • Adds ThreadAutoSettleCommand.settledAt as a required field in orchestration.ts, making commands schema-invalid without a valid settlement timestamp
  • Adds migration 045 in 045_RepairAutomaticSettlementTimestamps.ts to fix legacy projection rows where automatic settledAt equals the event time, replacing it with the latest pre-settlement activity or creation timestamp without touching orchestration event payloads
  • Introduces shared resolveSettledThreadTimestamp in threadSort.ts and adopts it across web sidebar sorting/labels and mobile settled-row ordering and display so clients prefer persisted settledAt, then latest activity, then updatedAt
  • Risk: any out-of-tree consumer dispatching thread.auto-settle without settledAt will now fail schema validation; migration 045 rewrites settled_at on projection rows for automatic settlements where it matched occurred_at, so deployments should verify the migration completes before serving reads

Macroscope summarized 673f2cd.

@chatgpt-codex-connector

chatgpt-codex-connectorBot commented Sep 2, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

ReviewStatusCommitReview trigger
📝 Code ReviewCompleted2026-09-02T19:30:23.274174Z71940bcNew commits
🔒 Security ReviewCompleted2026-09-02T19:07:08.772979Za77a10dPR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Sep 2, 2026
Comment threadapps/server/src/orchestration/ThreadSettlementPolicy.ts Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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:a77a10d157

ℹ️ 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 threaddocs/user/thread-sidebar.md Outdated
Comment threadapps/server/src/orchestration/ThreadSettlementPolicy.ts Outdated

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a77a10d. Configure here.

Comment threadapps/server/src/orchestration/ThreadSettlementPolicy.ts Outdated
@macroscopeapp

macroscopeappBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Would Approve

Macroscope's review found this PR approvable — This is a focused correction to automatic settlement timestamps, with coordinated server persistence, bounded repair of legacy projections, and consistent web/mobile display ordering. The change introduces no new workflow, product default, infrastructure change, or static-analysis override, and the affected behavior is covered by targeted tests.

Not approved because:

  • Monthly spending limit reached (workspace setting). Approvability relies on correctness review in order to determine eligibility

Review your spending limits in Billing settings. You can add or adjust custom eligibility rules. Learn more.

eimexdevand others added 2 commits September 2, 2026 12:25
Drop the orchestration_events rewrite from migration 045. Projectors and
the engine bootstrap from projection rows and cursors, never a full
replay, so repairing projection_threads is enough and the event log
stays as recorded. The migration is a single UPDATE and explains why the
settledAt == occurred_at match identifies an unrepaired sweep.
Migration test covers the no-activity fallback, activity after the sweep,
and asserts event payloads are untouched. Engine tests stamp a distinct
past settledAt and assert it survives while updatedAt stays the command
time; previously they passed the sweep time and asserted nothing.
Remove the resolveSettledTimestamp alias on web and have both call sites
import the client-runtime helper directly. Mobile slim rows drop the
unreachable createdAt fallback. Move the settled ordering line in the
user docs into its own paragraph.
Co-Authored-By: Claude Code <noreply@anthropic.com>
@juliusmarminge

Copy link
Copy Markdown
Member

Pushed 673f2cd to this branch with a few changes on top of the review:

  • Migration 045 no longer rewrites orchestration_events. Projectors bootstrap from projection_state cursors and the engine read model comes from ProjectionSnapshotQuery, so nothing replays the full log. Repairing projection_threads.settled_at is sufficient, and the event log stays as recorded. The migration is now one UPDATE with a comment on why settledAt == occurred_at identifies an unrepaired sweep.
  • Migration test covers the no-activity created_at fallback, activity after the sweep being ignored, and asserts event payloads are byte-identical before and after.
  • Engine tests passed settledAt: now() (the sweep time, i.e. the bug) and only asserted settledOverride. They now pass a distinct past stamp and assert it survives while updatedAt stays the command time.
  • Removed the resolveSettledTimestamp alias in Sidebar.logic.ts; both web call sites import resolveSettledThreadTimestamp directly.
  • Mobile slim rows drop the ?? thread.createdAt fallback, which was unreachable since the resolver already falls through to updatedAt.
  • User doc: settled ordering is its own paragraph instead of a sentence inside the settlement-rules paragraph.

Thanks for the fix, the core change was right.

@eimexdev

Copy link
Copy Markdown
ContributorAuthor

rad! Thanks for the review!

macroscopeapp[bot]
macroscopeappBot previously approved these changes Sep 2, 2026
Migration 045 was taken by ProjectionProjectsAutoPull on main, so the
settlement repair moves to 046. The test also picks up main's move of
NodeSqliteClient into @t3tools/shared.
Co-Authored-By: Claude Code <noreply@anthropic.com>
@macroscopeapp
macroscopeappBot dismissed their stale reviewSeptember 3, 2026 00:08

Dismissing prior approval to re-evaluate ab67483

@juliusmarminge
juliusmarminge merged commit 2971ec3 into pingdotgg:mainSep 3, 2026
27 checks passed
github-actionsBot added a commit to omarcresp/t3code-flake that referenced this pull request Sep 3, 2026
## What's Changed
* feat(desktop): browser profiles for the preview browser by @juliusmarminge in pingdotgg/t3code#7254
* refactor(shared): move the node:sqlite Effect SQL client into shared by @juliusmarminge in pingdotgg/t3code#7272
* feat(web): add opt-in panel animations by @maria-rcks in pingdotgg/t3code#8830
* feat(projects): automatically pull clean default branches by @maria-rcks in pingdotgg/t3code#9277
* fix(web): show pull request state icons in tabs by @flamboh in pingdotgg/t3code#9112
* feat(providers): add context compaction across harnesses by @maria-rcks in pingdotgg/t3code#8808
* feat(web): add proactive panels by @maria-rcks in pingdotgg/t3code#9276
* fix(web): unify control sizing across settings pages by @juliusmarminge in pingdotgg/t3code#9281
* fix(web): offer browser profiles from the empty-panel launcher by @juliusmarminge in pingdotgg/t3code#9279
* Revert "feat(providers): add context compaction across harnesses" by @maria-rcks in pingdotgg/t3code#9284
* fix(web): show scroll-to-end as soon as the last message slips under the composer by @juliusmarminge in pingdotgg/t3code#9280
* fix(cursor): honor auto and full access modes by @maria-rcks in pingdotgg/t3code#9283
* fix(desktop): detect installed Spectre libs for Windows builds by @juliusmarminge in pingdotgg/t3code#9285
* fix(pull-requests): missing features & better behaviour by @maria-rcks in pingdotgg/t3code#9188
* fix(providers): discover workspace skills everywhere by @maria-rcks in pingdotgg/t3code#9180
* fix(server): preserve automatic settlement timestamps by @eimexdev in pingdotgg/t3code#9254
* fix(opencode): show Reasoning selector for OpenCode models by @maria-rcks in pingdotgg/t3code#9287
* feat(web): preview document attachments in the file viewer by @juliusmarminge in pingdotgg/t3code#9292
* chore(ci): narrow the UI consistency check-run agent by @juliusmarminge in pingdotgg/t3code#9297
**Full Changelog**: pingdotgg/t3code@v0.0.39-nightly.20260902.1261...v0.0.39-nightly.20260903.1262
Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.39-nightly.20260903.1262
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@eimexdev@juliusmarminge
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(server): preserve automatic settlement timestamps - #9254

Merged
juliusmarminge merged 4 commits into
pingdotgg:mainfrom
eimexdev:fix/auto-settlement-timestamps
Sep 3, 2026
Merged

fix(server): preserve automatic settlement timestamps#9254
juliusmarminge merged 4 commits into
pingdotgg:mainfrom
eimexdev:fix/auto-settlement-timestamps

Conversation

@eimexdev

@eimexdeveimexdev commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Problem

Server-side auto-settlement records the sweep time as settledAt. On startup, old threads therefore look newly settled and receive incorrect dates and ordering. #9081 suppresses the resulting notifications, but does not correct the durable timestamp.

Fix

  • Carry the latest user/turn activity timestamp through the internal auto-settle command.
  • Keep updatedAt at command time, preserving normal update semantics.
  • Repair projection_threads.settled_at for identifiable automatic settlements, without changing manual or later re-settled timestamps. The event log is left as recorded: projections and the engine bootstrap from projection rows and cursors, so a projection-only repair is sufficient.
  • Web and mobile sort and label the Settled shelf by the same shared resolveSettledThreadTimestamp.
  • Document the settled-shelf ordering behavior.

Refs #9057
Pairs with #9081

Verification

  • Focused server, client-runtime, web, and mobile tests for the touched files
  • Server, contracts, client-runtime, web, and mobile typechecks
  • Targeted lint and formatting check

Made with GPT-5.6 Sol in T3 Code through the Codex harness. Follow-up commit by Claude Fable 5 in Claude Code.


Note

Medium Risk
Schema-breaking thread.auto-settle now requires settledAt, and migration 046 rewrites settled timestamps on projection rows for identifiable automatic settlements—deployments should run migrations before relying on sidebar ordering.

Overview
Automatic thread settlement now persists when work ended, not when the server sweep ran. resolveAutoSettlementAt returns the activity timestamp (or null); ThreadSettlementReactor passes it as required settledAt on thread.auto-settle, and the decider writes that to settledAt while updatedAt stays the command time.

Migration 046 repairs legacy projection_threads.settled_at rows where auto-settlement stamped the sweep time (identified via server auto-settle events). Manual and later re-settled threads are left alone; orchestration event payloads are unchanged.

Clients share resolveSettledThreadTimestamp from client-runtime so web and mobile sort and label the Settled shelf from the same stamp (settledAt, then latest activity, then updatedAt). Docs describe that ordering behavior.

Reviewed by Cursor Bugbot for commit ab67483. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Preserve settledAt timestamp in automatic thread settlement and repair legacy projections

  • resolveAutoSettlementAt in ThreadSettlementPolicy.ts now returns an ISO timestamp instead of a boolean; ThreadSettlementReactor includes it on thread.auto-settle commands, and the decider in decider.ts persists it as settledAt while updatedAt remains the event time
  • Adds ThreadAutoSettleCommand.settledAt as a required field in orchestration.ts, making commands schema-invalid without a valid settlement timestamp
  • Adds migration 045 in 045_RepairAutomaticSettlementTimestamps.ts to fix legacy projection rows where automatic settledAt equals the event time, replacing it with the latest pre-settlement activity or creation timestamp without touching orchestration event payloads
  • Introduces shared resolveSettledThreadTimestamp in threadSort.ts and adopts it across web sidebar sorting/labels and mobile settled-row ordering and display so clients prefer persisted settledAt, then latest activity, then updatedAt
  • Risk: any out-of-tree consumer dispatching thread.auto-settle without settledAt will now fail schema validation; migration 045 rewrites settled_at on projection rows for automatic settlements where it matched occurred_at, so deployments should verify the migration completes before serving reads

Macroscope summarized 673f2cd.

@chatgpt-codex-connector

chatgpt-codex-connectorBot commented Sep 2, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

ReviewStatusCommitReview trigger
📝 Code ReviewCompleted2026-09-02T19:30:23.274174Z71940bcNew commits
🔒 Security ReviewCompleted2026-09-02T19:07:08.772979Za77a10dPR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Sep 2, 2026
Comment threadapps/server/src/orchestration/ThreadSettlementPolicy.ts Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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:a77a10d157

ℹ️ 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 threaddocs/user/thread-sidebar.md Outdated
Comment threadapps/server/src/orchestration/ThreadSettlementPolicy.ts Outdated

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a77a10d. Configure here.

Comment threadapps/server/src/orchestration/ThreadSettlementPolicy.ts Outdated
@macroscopeapp

macroscopeappBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Would Approve

Macroscope's review found this PR approvable — This is a focused correction to automatic settlement timestamps, with coordinated server persistence, bounded repair of legacy projections, and consistent web/mobile display ordering. The change introduces no new workflow, product default, infrastructure change, or static-analysis override, and the affected behavior is covered by targeted tests.

Not approved because:

  • Monthly spending limit reached (workspace setting). Approvability relies on correctness review in order to determine eligibility

Review your spending limits in Billing settings. You can add or adjust custom eligibility rules. Learn more.

eimexdevand others added 2 commits September 2, 2026 12:25
Drop the orchestration_events rewrite from migration 045. Projectors and
the engine bootstrap from projection rows and cursors, never a full
replay, so repairing projection_threads is enough and the event log
stays as recorded. The migration is a single UPDATE and explains why the
settledAt == occurred_at match identifies an unrepaired sweep.
Migration test covers the no-activity fallback, activity after the sweep,
and asserts event payloads are untouched. Engine tests stamp a distinct
past settledAt and assert it survives while updatedAt stays the command
time; previously they passed the sweep time and asserted nothing.
Remove the resolveSettledTimestamp alias on web and have both call sites
import the client-runtime helper directly. Mobile slim rows drop the
unreachable createdAt fallback. Move the settled ordering line in the
user docs into its own paragraph.
Co-Authored-By: Claude Code <noreply@anthropic.com>
@juliusmarminge

Copy link
Copy Markdown
Member

Pushed 673f2cd to this branch with a few changes on top of the review:

  • Migration 045 no longer rewrites orchestration_events. Projectors bootstrap from projection_state cursors and the engine read model comes from ProjectionSnapshotQuery, so nothing replays the full log. Repairing projection_threads.settled_at is sufficient, and the event log stays as recorded. The migration is now one UPDATE with a comment on why settledAt == occurred_at identifies an unrepaired sweep.
  • Migration test covers the no-activity created_at fallback, activity after the sweep being ignored, and asserts event payloads are byte-identical before and after.
  • Engine tests passed settledAt: now() (the sweep time, i.e. the bug) and only asserted settledOverride. They now pass a distinct past stamp and assert it survives while updatedAt stays the command time.
  • Removed the resolveSettledTimestamp alias in Sidebar.logic.ts; both web call sites import resolveSettledThreadTimestamp directly.
  • Mobile slim rows drop the ?? thread.createdAt fallback, which was unreachable since the resolver already falls through to updatedAt.
  • User doc: settled ordering is its own paragraph instead of a sentence inside the settlement-rules paragraph.

Thanks for the fix, the core change was right.

@eimexdev

Copy link
Copy Markdown
ContributorAuthor

rad! Thanks for the review!

macroscopeapp[bot]
macroscopeappBot previously approved these changes Sep 2, 2026
Migration 045 was taken by ProjectionProjectsAutoPull on main, so the
settlement repair moves to 046. The test also picks up main's move of
NodeSqliteClient into @t3tools/shared.
Co-Authored-By: Claude Code <noreply@anthropic.com>
@macroscopeapp
macroscopeappBot dismissed their stale reviewSeptember 3, 2026 00:08

Dismissing prior approval to re-evaluate ab67483

@juliusmarminge
juliusmarminge merged commit 2971ec3 into pingdotgg:mainSep 3, 2026
27 checks passed
github-actionsBot added a commit to omarcresp/t3code-flake that referenced this pull request Sep 3, 2026
## What's Changed
* feat(desktop): browser profiles for the preview browser by @juliusmarminge in pingdotgg/t3code#7254
* refactor(shared): move the node:sqlite Effect SQL client into shared by @juliusmarminge in pingdotgg/t3code#7272
* feat(web): add opt-in panel animations by @maria-rcks in pingdotgg/t3code#8830
* feat(projects): automatically pull clean default branches by @maria-rcks in pingdotgg/t3code#9277
* fix(web): show pull request state icons in tabs by @flamboh in pingdotgg/t3code#9112
* feat(providers): add context compaction across harnesses by @maria-rcks in pingdotgg/t3code#8808
* feat(web): add proactive panels by @maria-rcks in pingdotgg/t3code#9276
* fix(web): unify control sizing across settings pages by @juliusmarminge in pingdotgg/t3code#9281
* fix(web): offer browser profiles from the empty-panel launcher by @juliusmarminge in pingdotgg/t3code#9279
* Revert "feat(providers): add context compaction across harnesses" by @maria-rcks in pingdotgg/t3code#9284
* fix(web): show scroll-to-end as soon as the last message slips under the composer by @juliusmarminge in pingdotgg/t3code#9280
* fix(cursor): honor auto and full access modes by @maria-rcks in pingdotgg/t3code#9283
* fix(desktop): detect installed Spectre libs for Windows builds by @juliusmarminge in pingdotgg/t3code#9285
* fix(pull-requests): missing features & better behaviour by @maria-rcks in pingdotgg/t3code#9188
* fix(providers): discover workspace skills everywhere by @maria-rcks in pingdotgg/t3code#9180
* fix(server): preserve automatic settlement timestamps by @eimexdev in pingdotgg/t3code#9254
* fix(opencode): show Reasoning selector for OpenCode models by @maria-rcks in pingdotgg/t3code#9287
* feat(web): preview document attachments in the file viewer by @juliusmarminge in pingdotgg/t3code#9292
* chore(ci): narrow the UI consistency check-run agent by @juliusmarminge in pingdotgg/t3code#9297
**Full Changelog**: pingdotgg/t3code@v0.0.39-nightly.20260902.1261...v0.0.39-nightly.20260903.1262
Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.39-nightly.20260903.1262
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@eimexdev@juliusmarminge
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

fix(server): preserve automatic settlement timestamps - #9254

Merged
juliusmarminge merged 4 commits into
pingdotgg:mainfrom
eimexdev:fix/auto-settlement-timestamps
Sep 3, 2026
Merged

fix(server): preserve automatic settlement timestamps#9254
juliusmarminge merged 4 commits into
pingdotgg:mainfrom
eimexdev:fix/auto-settlement-timestamps

Conversation

@eimexdev

@eimexdeveimexdev commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Problem

Server-side auto-settlement records the sweep time as settledAt. On startup, old threads therefore look newly settled and receive incorrect dates and ordering. #9081 suppresses the resulting notifications, but does not correct the durable timestamp.

Fix

  • Carry the latest user/turn activity timestamp through the internal auto-settle command.
  • Keep updatedAt at command time, preserving normal update semantics.
  • Repair projection_threads.settled_at for identifiable automatic settlements, without changing manual or later re-settled timestamps. The event log is left as recorded: projections and the engine bootstrap from projection rows and cursors, so a projection-only repair is sufficient.
  • Web and mobile sort and label the Settled shelf by the same shared resolveSettledThreadTimestamp.
  • Document the settled-shelf ordering behavior.

Refs #9057
Pairs with #9081

Verification

  • Focused server, client-runtime, web, and mobile tests for the touched files
  • Server, contracts, client-runtime, web, and mobile typechecks
  • Targeted lint and formatting check

Made with GPT-5.6 Sol in T3 Code through the Codex harness. Follow-up commit by Claude Fable 5 in Claude Code.


Note

Medium Risk
Schema-breaking thread.auto-settle now requires settledAt, and migration 046 rewrites settled timestamps on projection rows for identifiable automatic settlements—deployments should run migrations before relying on sidebar ordering.

Overview
Automatic thread settlement now persists when work ended, not when the server sweep ran. resolveAutoSettlementAt returns the activity timestamp (or null); ThreadSettlementReactor passes it as required settledAt on thread.auto-settle, and the decider writes that to settledAt while updatedAt stays the command time.

Migration 046 repairs legacy projection_threads.settled_at rows where auto-settlement stamped the sweep time (identified via server auto-settle events). Manual and later re-settled threads are left alone; orchestration event payloads are unchanged.

Clients share resolveSettledThreadTimestamp from client-runtime so web and mobile sort and label the Settled shelf from the same stamp (settledAt, then latest activity, then updatedAt). Docs describe that ordering behavior.

Reviewed by Cursor Bugbot for commit ab67483. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Preserve settledAt timestamp in automatic thread settlement and repair legacy projections

  • resolveAutoSettlementAt in ThreadSettlementPolicy.ts now returns an ISO timestamp instead of a boolean; ThreadSettlementReactor includes it on thread.auto-settle commands, and the decider in decider.ts persists it as settledAt while updatedAt remains the event time
  • Adds ThreadAutoSettleCommand.settledAt as a required field in orchestration.ts, making commands schema-invalid without a valid settlement timestamp
  • Adds migration 045 in 045_RepairAutomaticSettlementTimestamps.ts to fix legacy projection rows where automatic settledAt equals the event time, replacing it with the latest pre-settlement activity or creation timestamp without touching orchestration event payloads
  • Introduces shared resolveSettledThreadTimestamp in threadSort.ts and adopts it across web sidebar sorting/labels and mobile settled-row ordering and display so clients prefer persisted settledAt, then latest activity, then updatedAt
  • Risk: any out-of-tree consumer dispatching thread.auto-settle without settledAt will now fail schema validation; migration 045 rewrites settled_at on projection rows for automatic settlements where it matched occurred_at, so deployments should verify the migration completes before serving reads

Macroscope summarized 673f2cd.

@chatgpt-codex-connector

chatgpt-codex-connectorBot commented Sep 2, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

ReviewStatusCommitReview trigger
📝 Code ReviewCompleted2026-09-02T19:30:23.274174Z71940bcNew commits
🔒 Security ReviewCompleted2026-09-02T19:07:08.772979Za77a10dPR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actionsgithub-actionsBot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Sep 2, 2026
Comment threadapps/server/src/orchestration/ThreadSettlementPolicy.ts Outdated

@chatgpt-codex-connectorchatgpt-codex-connectorBot 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:a77a10d157

ℹ️ 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 threaddocs/user/thread-sidebar.md Outdated
Comment threadapps/server/src/orchestration/ThreadSettlementPolicy.ts Outdated

@cursorcursorBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a77a10d. Configure here.

Comment threadapps/server/src/orchestration/ThreadSettlementPolicy.ts Outdated
@macroscopeapp

macroscopeappBot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Would Approve

Macroscope's review found this PR approvable — This is a focused correction to automatic settlement timestamps, with coordinated server persistence, bounded repair of legacy projections, and consistent web/mobile display ordering. The change introduces no new workflow, product default, infrastructure change, or static-analysis override, and the affected behavior is covered by targeted tests.

Not approved because:

  • Monthly spending limit reached (workspace setting). Approvability relies on correctness review in order to determine eligibility

Review your spending limits in Billing settings. You can add or adjust custom eligibility rules. Learn more.

eimexdevand others added 2 commits September 2, 2026 12:25
Drop the orchestration_events rewrite from migration 045. Projectors and
the engine bootstrap from projection rows and cursors, never a full
replay, so repairing projection_threads is enough and the event log
stays as recorded. The migration is a single UPDATE and explains why the
settledAt == occurred_at match identifies an unrepaired sweep.
Migration test covers the no-activity fallback, activity after the sweep,
and asserts event payloads are untouched. Engine tests stamp a distinct
past settledAt and assert it survives while updatedAt stays the command
time; previously they passed the sweep time and asserted nothing.
Remove the resolveSettledTimestamp alias on web and have both call sites
import the client-runtime helper directly. Mobile slim rows drop the
unreachable createdAt fallback. Move the settled ordering line in the
user docs into its own paragraph.
Co-Authored-By: Claude Code <noreply@anthropic.com>
@juliusmarminge

Copy link
Copy Markdown
Member

Pushed 673f2cd to this branch with a few changes on top of the review:

  • Migration 045 no longer rewrites orchestration_events. Projectors bootstrap from projection_state cursors and the engine read model comes from ProjectionSnapshotQuery, so nothing replays the full log. Repairing projection_threads.settled_at is sufficient, and the event log stays as recorded. The migration is now one UPDATE with a comment on why settledAt == occurred_at identifies an unrepaired sweep.
  • Migration test covers the no-activity created_at fallback, activity after the sweep being ignored, and asserts event payloads are byte-identical before and after.
  • Engine tests passed settledAt: now() (the sweep time, i.e. the bug) and only asserted settledOverride. They now pass a distinct past stamp and assert it survives while updatedAt stays the command time.
  • Removed the resolveSettledTimestamp alias in Sidebar.logic.ts; both web call sites import resolveSettledThreadTimestamp directly.
  • Mobile slim rows drop the ?? thread.createdAt fallback, which was unreachable since the resolver already falls through to updatedAt.
  • User doc: settled ordering is its own paragraph instead of a sentence inside the settlement-rules paragraph.

Thanks for the fix, the core change was right.

@eimexdev

Copy link
Copy Markdown
ContributorAuthor

rad! Thanks for the review!

macroscopeapp[bot]
macroscopeappBot previously approved these changes Sep 2, 2026
Migration 045 was taken by ProjectionProjectsAutoPull on main, so the
settlement repair moves to 046. The test also picks up main's move of
NodeSqliteClient into @t3tools/shared.
Co-Authored-By: Claude Code <noreply@anthropic.com>
@macroscopeapp
macroscopeappBot dismissed their stale reviewSeptember 3, 2026 00:08

Dismissing prior approval to re-evaluate ab67483

@juliusmarminge
juliusmarminge merged commit 2971ec3 into pingdotgg:mainSep 3, 2026
27 checks passed
github-actionsBot added a commit to omarcresp/t3code-flake that referenced this pull request Sep 3, 2026
## What's Changed
* feat(desktop): browser profiles for the preview browser by @juliusmarminge in pingdotgg/t3code#7254
* refactor(shared): move the node:sqlite Effect SQL client into shared by @juliusmarminge in pingdotgg/t3code#7272
* feat(web): add opt-in panel animations by @maria-rcks in pingdotgg/t3code#8830
* feat(projects): automatically pull clean default branches by @maria-rcks in pingdotgg/t3code#9277
* fix(web): show pull request state icons in tabs by @flamboh in pingdotgg/t3code#9112
* feat(providers): add context compaction across harnesses by @maria-rcks in pingdotgg/t3code#8808
* feat(web): add proactive panels by @maria-rcks in pingdotgg/t3code#9276
* fix(web): unify control sizing across settings pages by @juliusmarminge in pingdotgg/t3code#9281
* fix(web): offer browser profiles from the empty-panel launcher by @juliusmarminge in pingdotgg/t3code#9279
* Revert "feat(providers): add context compaction across harnesses" by @maria-rcks in pingdotgg/t3code#9284
* fix(web): show scroll-to-end as soon as the last message slips under the composer by @juliusmarminge in pingdotgg/t3code#9280
* fix(cursor): honor auto and full access modes by @maria-rcks in pingdotgg/t3code#9283
* fix(desktop): detect installed Spectre libs for Windows builds by @juliusmarminge in pingdotgg/t3code#9285
* fix(pull-requests): missing features & better behaviour by @maria-rcks in pingdotgg/t3code#9188
* fix(providers): discover workspace skills everywhere by @maria-rcks in pingdotgg/t3code#9180
* fix(server): preserve automatic settlement timestamps by @eimexdev in pingdotgg/t3code#9254
* fix(opencode): show Reasoning selector for OpenCode models by @maria-rcks in pingdotgg/t3code#9287
* feat(web): preview document attachments in the file viewer by @juliusmarminge in pingdotgg/t3code#9292
* chore(ci): narrow the UI consistency check-run agent by @juliusmarminge in pingdotgg/t3code#9297
**Full Changelog**: pingdotgg/t3code@v0.0.39-nightly.20260902.1261...v0.0.39-nightly.20260903.1262
Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.39-nightly.20260903.1262
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L100-499 changed lines (additions + deletions).vouch:unvouchedPR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@eimexdev@juliusmarminge