refactor: one field-scoped settings-mutation interface - #264

Merged
Tryanks merged 1 commit into
mainfrom
refactor/c3-settings-mutation
Aug 24, 2026
Merged

refactor: one field-scoped settings-mutation interface#264
Tryanks merged 1 commit into
mainfrom
refactor/c3-settings-mutation

Conversation

@Tryanks

Copy link
Copy Markdown
Owner

Architecture round, candidate C3.

ProblemSettingsPatch mixed field-scoped variants with whole-sub-struct replacements, and the pipeline was mirrored three times: a 16-variant enum, 16 runtime assignment arms, and a 62-line UI clone/diff (which hand-masked child_worktrees to dodge the atomicity mismatch). Whole-struct replacement leaked concurrency semantics: a patch built from a stale replica overwrote sibling fields.

Change

  • All 26 variants are field-scoped (browser, orchestrate, computer-use, title-generation, and top-level fields enumerated individually).
  • Settings::apply(patch) in core is the single home of apply semantics — the patch type moved to core and is re-exported as tcode_protocol::SettingsPatch (dependency direction is protocol → core; the alternative was a cycle). Runtime's match collapses to settings.apply + its existing persist/broadcast/side-effects.
  • UI dispatches the field it owns directly; the clone/diff/mask machinery is deleted.
  • On-disk Settings serde unchanged; the patch enum is process-internal wire (both ends ship in one binary), round-tripped for all 26 variants in protocol tests.

Concurrency win proven — new test: BrowserHomeUrl and BrowserAllowEvaluate patches built from the same stale snapshot, applied sequentially, both survive (previously the second replacement clobbered the first).

Wins — interface shrinks to one apply; two 16-arm mirrors deleted; the stale-replica overwrite class disappears.

Gates: fmt / clippy -D warnings / full workspace tests — green locally.

🤖 Generated with Claude Code

Every SettingsPatch variant is now field-scoped (26 variants); the
whole-sub-struct replacements are gone, so a patch built from a stale
replica can no longer overwrite a sibling field (regression test:
two patches from the same stale browser snapshot both survive).
Apply semantics live in one place — Settings::apply in core (the
patch type moved to core, re-exported by protocol, because the
dependency direction is protocol → core). The runtime's 16-arm
assignment match collapses to settings.apply(patch); the UI's 62-line
clone/diff pipeline with its hand-masked child_worktrees workaround is
deleted in favor of direct field intents. On-disk Settings serde is
untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Tryanks
Tryanks enabled auto-merge (squash) August 24, 2026 07:48
@Tryanks
Tryanks merged commit 3d3af35 into mainAug 24, 2026
3 checks passed
@Tryanks
Tryanks deleted the refactor/c3-settings-mutation branch August 24, 2026 07:55
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Tryanks
, '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

refactor: one field-scoped settings-mutation interface - #264

Merged
Tryanks merged 1 commit into
mainfrom
refactor/c3-settings-mutation
Aug 24, 2026
Merged

refactor: one field-scoped settings-mutation interface#264
Tryanks merged 1 commit into
mainfrom
refactor/c3-settings-mutation

Conversation

@Tryanks

Copy link
Copy Markdown
Owner

Architecture round, candidate C3.

ProblemSettingsPatch mixed field-scoped variants with whole-sub-struct replacements, and the pipeline was mirrored three times: a 16-variant enum, 16 runtime assignment arms, and a 62-line UI clone/diff (which hand-masked child_worktrees to dodge the atomicity mismatch). Whole-struct replacement leaked concurrency semantics: a patch built from a stale replica overwrote sibling fields.

Change

  • All 26 variants are field-scoped (browser, orchestrate, computer-use, title-generation, and top-level fields enumerated individually).
  • Settings::apply(patch) in core is the single home of apply semantics — the patch type moved to core and is re-exported as tcode_protocol::SettingsPatch (dependency direction is protocol → core; the alternative was a cycle). Runtime's match collapses to settings.apply + its existing persist/broadcast/side-effects.
  • UI dispatches the field it owns directly; the clone/diff/mask machinery is deleted.
  • On-disk Settings serde unchanged; the patch enum is process-internal wire (both ends ship in one binary), round-tripped for all 26 variants in protocol tests.

Concurrency win proven — new test: BrowserHomeUrl and BrowserAllowEvaluate patches built from the same stale snapshot, applied sequentially, both survive (previously the second replacement clobbered the first).

Wins — interface shrinks to one apply; two 16-arm mirrors deleted; the stale-replica overwrite class disappears.

Gates: fmt / clippy -D warnings / full workspace tests — green locally.

🤖 Generated with Claude Code

Every SettingsPatch variant is now field-scoped (26 variants); the
whole-sub-struct replacements are gone, so a patch built from a stale
replica can no longer overwrite a sibling field (regression test:
two patches from the same stale browser snapshot both survive).
Apply semantics live in one place — Settings::apply in core (the
patch type moved to core, re-exported by protocol, because the
dependency direction is protocol → core). The runtime's 16-arm
assignment match collapses to settings.apply(patch); the UI's 62-line
clone/diff pipeline with its hand-masked child_worktrees workaround is
deleted in favor of direct field intents. On-disk Settings serde is
untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Tryanks
Tryanks enabled auto-merge (squash) August 24, 2026 07:48
@Tryanks
Tryanks merged commit 3d3af35 into mainAug 24, 2026
3 checks passed
@Tryanks
Tryanks deleted the refactor/c3-settings-mutation branch August 24, 2026 07:55
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Tryanks
, '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

refactor: one field-scoped settings-mutation interface - #264

Merged
Tryanks merged 1 commit into
mainfrom
refactor/c3-settings-mutation
Aug 24, 2026
Merged

refactor: one field-scoped settings-mutation interface#264
Tryanks merged 1 commit into
mainfrom
refactor/c3-settings-mutation

Conversation

@Tryanks

Copy link
Copy Markdown
Owner

Architecture round, candidate C3.

ProblemSettingsPatch mixed field-scoped variants with whole-sub-struct replacements, and the pipeline was mirrored three times: a 16-variant enum, 16 runtime assignment arms, and a 62-line UI clone/diff (which hand-masked child_worktrees to dodge the atomicity mismatch). Whole-struct replacement leaked concurrency semantics: a patch built from a stale replica overwrote sibling fields.

Change

  • All 26 variants are field-scoped (browser, orchestrate, computer-use, title-generation, and top-level fields enumerated individually).
  • Settings::apply(patch) in core is the single home of apply semantics — the patch type moved to core and is re-exported as tcode_protocol::SettingsPatch (dependency direction is protocol → core; the alternative was a cycle). Runtime's match collapses to settings.apply + its existing persist/broadcast/side-effects.
  • UI dispatches the field it owns directly; the clone/diff/mask machinery is deleted.
  • On-disk Settings serde unchanged; the patch enum is process-internal wire (both ends ship in one binary), round-tripped for all 26 variants in protocol tests.

Concurrency win proven — new test: BrowserHomeUrl and BrowserAllowEvaluate patches built from the same stale snapshot, applied sequentially, both survive (previously the second replacement clobbered the first).

Wins — interface shrinks to one apply; two 16-arm mirrors deleted; the stale-replica overwrite class disappears.

Gates: fmt / clippy -D warnings / full workspace tests — green locally.

🤖 Generated with Claude Code

Every SettingsPatch variant is now field-scoped (26 variants); the
whole-sub-struct replacements are gone, so a patch built from a stale
replica can no longer overwrite a sibling field (regression test:
two patches from the same stale browser snapshot both survive).
Apply semantics live in one place — Settings::apply in core (the
patch type moved to core, re-exported by protocol, because the
dependency direction is protocol → core). The runtime's 16-arm
assignment match collapses to settings.apply(patch); the UI's 62-line
clone/diff pipeline with its hand-masked child_worktrees workaround is
deleted in favor of direct field intents. On-disk Settings serde is
untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Tryanks
Tryanks enabled auto-merge (squash) August 24, 2026 07:48
@Tryanks
Tryanks merged commit 3d3af35 into mainAug 24, 2026
3 checks passed
@Tryanks
Tryanks deleted the refactor/c3-settings-mutation branch August 24, 2026 07:55
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Tryanks
, '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

refactor: one field-scoped settings-mutation interface - #264

Merged
Tryanks merged 1 commit into
mainfrom
refactor/c3-settings-mutation
Aug 24, 2026
Merged

refactor: one field-scoped settings-mutation interface#264
Tryanks merged 1 commit into
mainfrom
refactor/c3-settings-mutation

Conversation

@Tryanks

Copy link
Copy Markdown
Owner

Architecture round, candidate C3.

ProblemSettingsPatch mixed field-scoped variants with whole-sub-struct replacements, and the pipeline was mirrored three times: a 16-variant enum, 16 runtime assignment arms, and a 62-line UI clone/diff (which hand-masked child_worktrees to dodge the atomicity mismatch). Whole-struct replacement leaked concurrency semantics: a patch built from a stale replica overwrote sibling fields.

Change

  • All 26 variants are field-scoped (browser, orchestrate, computer-use, title-generation, and top-level fields enumerated individually).
  • Settings::apply(patch) in core is the single home of apply semantics — the patch type moved to core and is re-exported as tcode_protocol::SettingsPatch (dependency direction is protocol → core; the alternative was a cycle). Runtime's match collapses to settings.apply + its existing persist/broadcast/side-effects.
  • UI dispatches the field it owns directly; the clone/diff/mask machinery is deleted.
  • On-disk Settings serde unchanged; the patch enum is process-internal wire (both ends ship in one binary), round-tripped for all 26 variants in protocol tests.

Concurrency win proven — new test: BrowserHomeUrl and BrowserAllowEvaluate patches built from the same stale snapshot, applied sequentially, both survive (previously the second replacement clobbered the first).

Wins — interface shrinks to one apply; two 16-arm mirrors deleted; the stale-replica overwrite class disappears.

Gates: fmt / clippy -D warnings / full workspace tests — green locally.

🤖 Generated with Claude Code

Every SettingsPatch variant is now field-scoped (26 variants); the
whole-sub-struct replacements are gone, so a patch built from a stale
replica can no longer overwrite a sibling field (regression test:
two patches from the same stale browser snapshot both survive).
Apply semantics live in one place — Settings::apply in core (the
patch type moved to core, re-exported by protocol, because the
dependency direction is protocol → core). The runtime's 16-arm
assignment match collapses to settings.apply(patch); the UI's 62-line
clone/diff pipeline with its hand-masked child_worktrees workaround is
deleted in favor of direct field intents. On-disk Settings serde is
untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Tryanks
Tryanks enabled auto-merge (squash) August 24, 2026 07:48
@Tryanks
Tryanks merged commit 3d3af35 into mainAug 24, 2026
3 checks passed
@Tryanks
Tryanks deleted the refactor/c3-settings-mutation branch August 24, 2026 07:55
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Tryanks
, '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

refactor: one field-scoped settings-mutation interface - #264

Merged
Tryanks merged 1 commit into
mainfrom
refactor/c3-settings-mutation
Aug 24, 2026
Merged

refactor: one field-scoped settings-mutation interface#264
Tryanks merged 1 commit into
mainfrom
refactor/c3-settings-mutation

Conversation

@Tryanks

Copy link
Copy Markdown
Owner

Architecture round, candidate C3.

ProblemSettingsPatch mixed field-scoped variants with whole-sub-struct replacements, and the pipeline was mirrored three times: a 16-variant enum, 16 runtime assignment arms, and a 62-line UI clone/diff (which hand-masked child_worktrees to dodge the atomicity mismatch). Whole-struct replacement leaked concurrency semantics: a patch built from a stale replica overwrote sibling fields.

Change

  • All 26 variants are field-scoped (browser, orchestrate, computer-use, title-generation, and top-level fields enumerated individually).
  • Settings::apply(patch) in core is the single home of apply semantics — the patch type moved to core and is re-exported as tcode_protocol::SettingsPatch (dependency direction is protocol → core; the alternative was a cycle). Runtime's match collapses to settings.apply + its existing persist/broadcast/side-effects.
  • UI dispatches the field it owns directly; the clone/diff/mask machinery is deleted.
  • On-disk Settings serde unchanged; the patch enum is process-internal wire (both ends ship in one binary), round-tripped for all 26 variants in protocol tests.

Concurrency win proven — new test: BrowserHomeUrl and BrowserAllowEvaluate patches built from the same stale snapshot, applied sequentially, both survive (previously the second replacement clobbered the first).

Wins — interface shrinks to one apply; two 16-arm mirrors deleted; the stale-replica overwrite class disappears.

Gates: fmt / clippy -D warnings / full workspace tests — green locally.

🤖 Generated with Claude Code

Every SettingsPatch variant is now field-scoped (26 variants); the
whole-sub-struct replacements are gone, so a patch built from a stale
replica can no longer overwrite a sibling field (regression test:
two patches from the same stale browser snapshot both survive).
Apply semantics live in one place — Settings::apply in core (the
patch type moved to core, re-exported by protocol, because the
dependency direction is protocol → core). The runtime's 16-arm
assignment match collapses to settings.apply(patch); the UI's 62-line
clone/diff pipeline with its hand-masked child_worktrees workaround is
deleted in favor of direct field intents. On-disk Settings serde is
untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Tryanks
Tryanks enabled auto-merge (squash) August 24, 2026 07:48
@Tryanks
Tryanks merged commit 3d3af35 into mainAug 24, 2026
3 checks passed
@Tryanks
Tryanks deleted the refactor/c3-settings-mutation branch August 24, 2026 07:55
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Tryanks
, '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

refactor: one field-scoped settings-mutation interface - #264

Merged
Tryanks merged 1 commit into
mainfrom
refactor/c3-settings-mutation
Aug 24, 2026
Merged

refactor: one field-scoped settings-mutation interface#264
Tryanks merged 1 commit into
mainfrom
refactor/c3-settings-mutation

Conversation

@Tryanks

Copy link
Copy Markdown
Owner

Architecture round, candidate C3.

ProblemSettingsPatch mixed field-scoped variants with whole-sub-struct replacements, and the pipeline was mirrored three times: a 16-variant enum, 16 runtime assignment arms, and a 62-line UI clone/diff (which hand-masked child_worktrees to dodge the atomicity mismatch). Whole-struct replacement leaked concurrency semantics: a patch built from a stale replica overwrote sibling fields.

Change

  • All 26 variants are field-scoped (browser, orchestrate, computer-use, title-generation, and top-level fields enumerated individually).
  • Settings::apply(patch) in core is the single home of apply semantics — the patch type moved to core and is re-exported as tcode_protocol::SettingsPatch (dependency direction is protocol → core; the alternative was a cycle). Runtime's match collapses to settings.apply + its existing persist/broadcast/side-effects.
  • UI dispatches the field it owns directly; the clone/diff/mask machinery is deleted.
  • On-disk Settings serde unchanged; the patch enum is process-internal wire (both ends ship in one binary), round-tripped for all 26 variants in protocol tests.

Concurrency win proven — new test: BrowserHomeUrl and BrowserAllowEvaluate patches built from the same stale snapshot, applied sequentially, both survive (previously the second replacement clobbered the first).

Wins — interface shrinks to one apply; two 16-arm mirrors deleted; the stale-replica overwrite class disappears.

Gates: fmt / clippy -D warnings / full workspace tests — green locally.

🤖 Generated with Claude Code

Every SettingsPatch variant is now field-scoped (26 variants); the
whole-sub-struct replacements are gone, so a patch built from a stale
replica can no longer overwrite a sibling field (regression test:
two patches from the same stale browser snapshot both survive).
Apply semantics live in one place — Settings::apply in core (the
patch type moved to core, re-exported by protocol, because the
dependency direction is protocol → core). The runtime's 16-arm
assignment match collapses to settings.apply(patch); the UI's 62-line
clone/diff pipeline with its hand-masked child_worktrees workaround is
deleted in favor of direct field intents. On-disk Settings serde is
untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Tryanks
Tryanks enabled auto-merge (squash) August 24, 2026 07:48
@Tryanks
Tryanks merged commit 3d3af35 into mainAug 24, 2026
3 checks passed
@Tryanks
Tryanks deleted the refactor/c3-settings-mutation branch August 24, 2026 07:55
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Tryanks
, '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

refactor: one field-scoped settings-mutation interface - #264

Merged
Tryanks merged 1 commit into
mainfrom
refactor/c3-settings-mutation
Aug 24, 2026
Merged

refactor: one field-scoped settings-mutation interface#264
Tryanks merged 1 commit into
mainfrom
refactor/c3-settings-mutation

Conversation

@Tryanks

Copy link
Copy Markdown
Owner

Architecture round, candidate C3.

ProblemSettingsPatch mixed field-scoped variants with whole-sub-struct replacements, and the pipeline was mirrored three times: a 16-variant enum, 16 runtime assignment arms, and a 62-line UI clone/diff (which hand-masked child_worktrees to dodge the atomicity mismatch). Whole-struct replacement leaked concurrency semantics: a patch built from a stale replica overwrote sibling fields.

Change

  • All 26 variants are field-scoped (browser, orchestrate, computer-use, title-generation, and top-level fields enumerated individually).
  • Settings::apply(patch) in core is the single home of apply semantics — the patch type moved to core and is re-exported as tcode_protocol::SettingsPatch (dependency direction is protocol → core; the alternative was a cycle). Runtime's match collapses to settings.apply + its existing persist/broadcast/side-effects.
  • UI dispatches the field it owns directly; the clone/diff/mask machinery is deleted.
  • On-disk Settings serde unchanged; the patch enum is process-internal wire (both ends ship in one binary), round-tripped for all 26 variants in protocol tests.

Concurrency win proven — new test: BrowserHomeUrl and BrowserAllowEvaluate patches built from the same stale snapshot, applied sequentially, both survive (previously the second replacement clobbered the first).

Wins — interface shrinks to one apply; two 16-arm mirrors deleted; the stale-replica overwrite class disappears.

Gates: fmt / clippy -D warnings / full workspace tests — green locally.

🤖 Generated with Claude Code

Every SettingsPatch variant is now field-scoped (26 variants); the
whole-sub-struct replacements are gone, so a patch built from a stale
replica can no longer overwrite a sibling field (regression test:
two patches from the same stale browser snapshot both survive).
Apply semantics live in one place — Settings::apply in core (the
patch type moved to core, re-exported by protocol, because the
dependency direction is protocol → core). The runtime's 16-arm
assignment match collapses to settings.apply(patch); the UI's 62-line
clone/diff pipeline with its hand-masked child_worktrees workaround is
deleted in favor of direct field intents. On-disk Settings serde is
untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Tryanks
Tryanks enabled auto-merge (squash) August 24, 2026 07:48
@Tryanks
Tryanks merged commit 3d3af35 into mainAug 24, 2026
3 checks passed
@Tryanks
Tryanks deleted the refactor/c3-settings-mutation branch August 24, 2026 07:55
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Tryanks
, '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

refactor: one field-scoped settings-mutation interface - #264

Merged
Tryanks merged 1 commit into
mainfrom
refactor/c3-settings-mutation
Aug 24, 2026
Merged

refactor: one field-scoped settings-mutation interface#264
Tryanks merged 1 commit into
mainfrom
refactor/c3-settings-mutation

Conversation

@Tryanks

Copy link
Copy Markdown
Owner

Architecture round, candidate C3.

ProblemSettingsPatch mixed field-scoped variants with whole-sub-struct replacements, and the pipeline was mirrored three times: a 16-variant enum, 16 runtime assignment arms, and a 62-line UI clone/diff (which hand-masked child_worktrees to dodge the atomicity mismatch). Whole-struct replacement leaked concurrency semantics: a patch built from a stale replica overwrote sibling fields.

Change

  • All 26 variants are field-scoped (browser, orchestrate, computer-use, title-generation, and top-level fields enumerated individually).
  • Settings::apply(patch) in core is the single home of apply semantics — the patch type moved to core and is re-exported as tcode_protocol::SettingsPatch (dependency direction is protocol → core; the alternative was a cycle). Runtime's match collapses to settings.apply + its existing persist/broadcast/side-effects.
  • UI dispatches the field it owns directly; the clone/diff/mask machinery is deleted.
  • On-disk Settings serde unchanged; the patch enum is process-internal wire (both ends ship in one binary), round-tripped for all 26 variants in protocol tests.

Concurrency win proven — new test: BrowserHomeUrl and BrowserAllowEvaluate patches built from the same stale snapshot, applied sequentially, both survive (previously the second replacement clobbered the first).

Wins — interface shrinks to one apply; two 16-arm mirrors deleted; the stale-replica overwrite class disappears.

Gates: fmt / clippy -D warnings / full workspace tests — green locally.

🤖 Generated with Claude Code

Every SettingsPatch variant is now field-scoped (26 variants); the
whole-sub-struct replacements are gone, so a patch built from a stale
replica can no longer overwrite a sibling field (regression test:
two patches from the same stale browser snapshot both survive).
Apply semantics live in one place — Settings::apply in core (the
patch type moved to core, re-exported by protocol, because the
dependency direction is protocol → core). The runtime's 16-arm
assignment match collapses to settings.apply(patch); the UI's 62-line
clone/diff pipeline with its hand-masked child_worktrees workaround is
deleted in favor of direct field intents. On-disk Settings serde is
untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Tryanks
Tryanks enabled auto-merge (squash) August 24, 2026 07:48
@Tryanks
Tryanks merged commit 3d3af35 into mainAug 24, 2026
3 checks passed
@Tryanks
Tryanks deleted the refactor/c3-settings-mutation branch August 24, 2026 07:55
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Tryanks