refactor(desktop): extract goals as a feature slice - #3531

Merged
Astro-Han merged 2 commits into
apache:mainfrom
chihumyum:refactor/goals-feature-slice
Aug 23, 2026
Merged

refactor(desktop): extract goals as a feature slice#3531
Astro-Han merged 2 commits into
apache:mainfrom
chihumyum:refactor/goals-feature-slice

Conversation

@chihumyum

Copy link
Copy Markdown
Contributor

Summary

  • Move Goal read state, subscriptions, controls, dialog ownership, and indicator assembly behind a renderer feature boundary.
  • Isolate Desktop bridge access behind a narrow GoalServices adapter and provider; keep AppShell limited to Session context plus host, commands, and selectors.
  • Add fake services and focused lifecycle, adapter, model, and architecture-boundary coverage.

Refs #3439

Verification

  • npm run lint
  • npm run format:check
  • npm run build
  • npm run typecheck
  • npm --workspace @maka/desktop run test:dist — 1198 passed
  • npx knip --workspace apps/desktop
  • npx knip --workspace packages/ui
  • npm --workspace @maka/desktop run build-storybook
  • npm --workspace @maka/desktop run smoke:storybook — 166 stories passed
  • npx playwright test --config e2e/playwright.config.ts from apps/desktop — 50 passed, 1 skipped

No screenshots are included because this changes no Goal copy, CSS, layout, IPC contract, or user-visible behavior.

Review focus

  • Session-switch fencing for stale Goal reads.
  • Goal-change event filtering and subscription disposal.
  • Dialog ownership of the Session captured when it opens.
  • Per-Session pause/resume re-entry protection.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex assisted with the feature extraction, implementation, tests, and verification.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@chihumyum
chihumyum marked this pull request as ready for review August 22, 2026 19:15

@Astro-HanAstro-Han 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.

Reviewed at head b29e3c4e. One blocking item, and it is a generated file rather than the code — the extraction itself came through clean.

[P1] The Astryx surface inventory wasn't regenerated, and that's what's failing test.

test is FAILURE on this exact head (job 97083453961), and I reproduced it locally: npm run astryx:surface-inventory exits 1 on this branch, consistently. Three moved files are on disk but absent from docs/astryx-surface-file-inventory.pathsapps/desktop/src/renderer/features/goals/ui/goal-dialog.tsx, plus services-context.tsx and goal-host.tsx in the same directory — while the pre-move apps/desktop/src/renderer/goal-dialog.tsx is still listed. docs/astryx-surface-file-inventory.md is likewise out of sync with the generator's output.

Fix is mechanical: run npm run astryx:surface-inventory:write and commit both regenerated files. Nothing about the runtime behaviour is at fault here — the gate is doing its job, the branch just moved surfaces without re-running it.


On the refactor itself: no P0–P3.

For a pure extraction the question is only ever whether behaviour changed under cover of moving things, so that is where I spent the time. use-goal-controller.ts ends up holding the active goal, session-switch clearing, the late-read sequence and disposed guards, the goal-change subscription, per-session control dedupe, and the dialog's session snapshot — and it stays a projection of Host events rather than becoming a second authority, which is the failure mode this kind of slice usually introduces. create-goal-services.ts is the single Desktop bridge adapter, and AppShell only reaches Goals through GoalHost and the controller's public API.

The deletion side checks out too, which is the part that makes an extraction actually reduce entropy rather than add a layer: use-session-goal.ts is gone, the old dialog's direct window.maka dependency is gone, and AppShell no longer carries goal control state. A repo-wide search finds no useSessionGoal and no surviving production entry to the old dialog path.

Verified: Goals focused tests 12/12; controller, model, adapter, and feature-boundary suites all pass; @maka/desktop builds and typechecks across renderer, preload, main, and Storybook; Biome clean on changed files. The full desktop main suite ran 1190 pass / 0 fail with 8 cancelled — the cancellations sit in pre-existing MCP OAuth pending tests and are not attributable to this branch, so I'm reporting it that way rather than calling the suite green.

Regenerate the inventory and this is ready for another look.

@chihumyum

Copy link
Copy Markdown
ContributorAuthor

Fixed in f9554a9af by regenerating both checked-in Astryx surface inventory files.

Local verification:

  • npm run astryx:surface-inventory:write
  • npm run astryx:surface-inventory — 203 files, 1 exclusion
  • git diff --check

The new CI run is currently action_required with no jobs, so it needs maintainer approval before GitHub will execute the workflow.

@Astro-HanAstro-Han 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.

Two independent lines on f9554a9af129f6bede8b7975c0a4bb9a2a0cc3be, from different models, neither able to see the other's conclusion. Both came back with nothing at P0–P3, and — more importantly for a refactor — both answered the question that actually matters here.

A refactor's failure mode isn't "didn't fix it", it's "changed behaviour in transit", and in a diff a relocation and a rewrite look identical. So both lines were asked to split -263 into what genuinely disappeared versus what is just move noise.

What disappeared (~150 lines):

  • use-session-goal.ts is gone as a file, and its authority — goal state, the change subscription, session-switch semantics — moved wholesale to the controller rather than being copied.
  • The indicator construction inlined in app-shell.tsx (~55 lines), plus runGoalControl, pendingGoalControlSessionIdsRef and goalDialogSessionId, all leave the shell. AppShell keeps two lines of wiring.

That is one ownership leaving one place and arriving in another, not a copy. Move noise (~110 lines) is the dialog relocating into features/goals/ui/ and isLiveGoal moving to model/live-goal.ts.

The controller being larger than the hook it replaces is explained rather than hand-waved: it absorbed the behaviour that used to live inline in the shell, so the two are not comparable line-for-line.

Semantic parity was checked point by point rather than asserted: subscription filtering (including the broadcast undefined case), session-switch ordering, the sequence-number race guard, control re-entrancy, dialog keying against the wrong session, and the GoalState type resolving to the same underlying type through a different path. One behavioural difference was found and it is an improvement: the indicator moves from an IIFE rebuilding a closure every render to a memo keyed on the active goal, so the reference is now stable.

No second implementation survives. We verified this at the gate independently: window.maka.goal has zero hits in production code on this head, use-session-goal.ts no longer exists in the tree, and the only remaining references to the old surface are stories pointing at the deliberate testing export.

One thing worth recording without grading it: the adapter's subscribeChanges collapses events down to sessionId | undefined, discarding metadata beyond the reason. That is the right boundary for what goals need today, but if goals ever need another session reason — a removal, say — the adapter is where that has to be reopened. Noting it as a known edge of the seam, not as a defect.

CI is terminal green on this head (test: completed / success), which is the head this approval is bound to.

Approving.

@chihumyum
chihumyumforce-pushed the refactor/goals-feature-slice branch 2 times, most recently from d38904b to cfce73eCompareAugust 23, 2026 07:53
@chihumyum

Copy link
Copy Markdown
ContributorAuthor

Rebased onto current upstream/main (729839ed8) and resolved the GoalDialog conflict in cfce73ee9.

The resolution preserves the newly merged reconnect reconciliation behavior: Goal arm outcomes still fence stale results, lock reconciled states, and prevent duplicate submission, while the bridge call remains behind the Goals service port. The reconciliation model and its tests now live inside the Goals feature boundary.

Verified after the final rebase:

  • npm run lint
  • npm run format:check
  • npm run astryx:surface-inventory
  • npm run build
  • npm run typecheck
  • npm --workspace @maka/desktop run test:dist — 1255 passed
  • npx knip --workspace apps/desktop

GitHub now reports the PR as mergeable. The new fork CI run is action_required and needs maintainer approval before jobs start.

Move Goal state, subscriptions, controls, dialog ownership, and view-model assembly behind a renderer feature boundary and Desktop adapter. Add fake services, lifecycle tests, and architecture guardrails without changing the preload contract or user behavior.
Refs apache#3439
Generated-by: Codex
Regenerate the checked-in surface inventory after moving the Goal dialog and adding the Goals feature service and host surfaces.
Refs apache#3439
Generated-by: Codex
@chihumyum
chihumyumforce-pushed the refactor/goals-feature-slice branch from cfce73e to 0ed2c53CompareAugust 23, 2026 09:10
@chihumyum

Copy link
Copy Markdown
ContributorAuthor

Rechecked against the latest upstream/main (047567c4b). Main had advanced by five commits and the PR had become DIRTY solely because the generated Astryx inventory conflicted again.

Rebased and regenerated the inventory in 0ed2c53c4. Verification:

  • npm run astryx:surface-inventory — 204 files, 1 exclusion
  • git diff --check upstream/main...HEAD
  • merge-tree probe against current main — clean

GitHub no longer reports a merge conflict. The current head workflow is run 32630272181, which is action_required with no jobs and needs maintainer approval to execute.

@jackwenerjackwener left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Incremental technical review of exact head 0ed2c53c4bddef7c97434ad111541ea7111c33d8, executed by the Kabi review agent on behalf of @WAWQAQ under the standing Kabi review/publisher authorization.

GO — no live P0–P3. APPROVE; no merge action.

This review covers the rebase-only delta that incorporated the newly merged Goal arm reconciliation contract. Comparing the pre-extraction implementation at current base 047567c4b with the moved feature code shows semantic parity: only armed closes the dialog; matching/different/null reconciled results and reconciliation_unavailable all lock the form, show the authoritative outcome, and prevent duplicate submission. interpretGoalArmOutcome is unchanged apart from its relative import.

The bridge authority remains singular: main.tsx creates one Desktop Goal service adapter, its bridge.goal.arm result is returned through the service and controller as Promise<GoalArmOutcome>, and GoalHost injects that exact function into GoalDialog. The Goals feature contains no window.maka.goal access and the old direct production path is absent.

Verification: focused Goals suites 18/18; Desktop main 1273/1274 on the first full run, with the sole unrelated shell-env timeout fixture passing 12/12 when rerun alone; Desktop preload/main/renderer/Storybook typechecks passed. Three discussion endpoints were reconciled after provisional sealing: two old-head reviews, no inline comments, and three author status comments; no live P0–P2.

Fresh action gate: OPEN, non-draft, MERGEABLE/CLEAN; exact-head hosted test is completed/success. This Agent-executed approval does not claim to satisfy any separate unresolved human-review wording.

@Astro-Han
Astro-Han merged commit 42cc510 into apache:mainAug 23, 2026
1 of 2 checks passed
@chihumyum
chihumyum deleted the refactor/goals-feature-slice branch August 23, 2026 16:19
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.

3 participants

@chihumyum@jackwener@Astro-Han
, '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(desktop): extract goals as a feature slice - #3531

Merged
Astro-Han merged 2 commits into
apache:mainfrom
chihumyum:refactor/goals-feature-slice
Aug 23, 2026
Merged

refactor(desktop): extract goals as a feature slice#3531
Astro-Han merged 2 commits into
apache:mainfrom
chihumyum:refactor/goals-feature-slice

Conversation

@chihumyum

Copy link
Copy Markdown
Contributor

Summary

  • Move Goal read state, subscriptions, controls, dialog ownership, and indicator assembly behind a renderer feature boundary.
  • Isolate Desktop bridge access behind a narrow GoalServices adapter and provider; keep AppShell limited to Session context plus host, commands, and selectors.
  • Add fake services and focused lifecycle, adapter, model, and architecture-boundary coverage.

Refs #3439

Verification

  • npm run lint
  • npm run format:check
  • npm run build
  • npm run typecheck
  • npm --workspace @maka/desktop run test:dist — 1198 passed
  • npx knip --workspace apps/desktop
  • npx knip --workspace packages/ui
  • npm --workspace @maka/desktop run build-storybook
  • npm --workspace @maka/desktop run smoke:storybook — 166 stories passed
  • npx playwright test --config e2e/playwright.config.ts from apps/desktop — 50 passed, 1 skipped

No screenshots are included because this changes no Goal copy, CSS, layout, IPC contract, or user-visible behavior.

Review focus

  • Session-switch fencing for stale Goal reads.
  • Goal-change event filtering and subscription disposal.
  • Dialog ownership of the Session captured when it opens.
  • Per-Session pause/resume re-entry protection.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex assisted with the feature extraction, implementation, tests, and verification.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@chihumyum
chihumyum marked this pull request as ready for review August 22, 2026 19:15

@Astro-HanAstro-Han 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.

Reviewed at head b29e3c4e. One blocking item, and it is a generated file rather than the code — the extraction itself came through clean.

[P1] The Astryx surface inventory wasn't regenerated, and that's what's failing test.

test is FAILURE on this exact head (job 97083453961), and I reproduced it locally: npm run astryx:surface-inventory exits 1 on this branch, consistently. Three moved files are on disk but absent from docs/astryx-surface-file-inventory.pathsapps/desktop/src/renderer/features/goals/ui/goal-dialog.tsx, plus services-context.tsx and goal-host.tsx in the same directory — while the pre-move apps/desktop/src/renderer/goal-dialog.tsx is still listed. docs/astryx-surface-file-inventory.md is likewise out of sync with the generator's output.

Fix is mechanical: run npm run astryx:surface-inventory:write and commit both regenerated files. Nothing about the runtime behaviour is at fault here — the gate is doing its job, the branch just moved surfaces without re-running it.


On the refactor itself: no P0–P3.

For a pure extraction the question is only ever whether behaviour changed under cover of moving things, so that is where I spent the time. use-goal-controller.ts ends up holding the active goal, session-switch clearing, the late-read sequence and disposed guards, the goal-change subscription, per-session control dedupe, and the dialog's session snapshot — and it stays a projection of Host events rather than becoming a second authority, which is the failure mode this kind of slice usually introduces. create-goal-services.ts is the single Desktop bridge adapter, and AppShell only reaches Goals through GoalHost and the controller's public API.

The deletion side checks out too, which is the part that makes an extraction actually reduce entropy rather than add a layer: use-session-goal.ts is gone, the old dialog's direct window.maka dependency is gone, and AppShell no longer carries goal control state. A repo-wide search finds no useSessionGoal and no surviving production entry to the old dialog path.

Verified: Goals focused tests 12/12; controller, model, adapter, and feature-boundary suites all pass; @maka/desktop builds and typechecks across renderer, preload, main, and Storybook; Biome clean on changed files. The full desktop main suite ran 1190 pass / 0 fail with 8 cancelled — the cancellations sit in pre-existing MCP OAuth pending tests and are not attributable to this branch, so I'm reporting it that way rather than calling the suite green.

Regenerate the inventory and this is ready for another look.

@chihumyum

Copy link
Copy Markdown
ContributorAuthor

Fixed in f9554a9af by regenerating both checked-in Astryx surface inventory files.

Local verification:

  • npm run astryx:surface-inventory:write
  • npm run astryx:surface-inventory — 203 files, 1 exclusion
  • git diff --check

The new CI run is currently action_required with no jobs, so it needs maintainer approval before GitHub will execute the workflow.

@Astro-HanAstro-Han 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.

Two independent lines on f9554a9af129f6bede8b7975c0a4bb9a2a0cc3be, from different models, neither able to see the other's conclusion. Both came back with nothing at P0–P3, and — more importantly for a refactor — both answered the question that actually matters here.

A refactor's failure mode isn't "didn't fix it", it's "changed behaviour in transit", and in a diff a relocation and a rewrite look identical. So both lines were asked to split -263 into what genuinely disappeared versus what is just move noise.

What disappeared (~150 lines):

  • use-session-goal.ts is gone as a file, and its authority — goal state, the change subscription, session-switch semantics — moved wholesale to the controller rather than being copied.
  • The indicator construction inlined in app-shell.tsx (~55 lines), plus runGoalControl, pendingGoalControlSessionIdsRef and goalDialogSessionId, all leave the shell. AppShell keeps two lines of wiring.

That is one ownership leaving one place and arriving in another, not a copy. Move noise (~110 lines) is the dialog relocating into features/goals/ui/ and isLiveGoal moving to model/live-goal.ts.

The controller being larger than the hook it replaces is explained rather than hand-waved: it absorbed the behaviour that used to live inline in the shell, so the two are not comparable line-for-line.

Semantic parity was checked point by point rather than asserted: subscription filtering (including the broadcast undefined case), session-switch ordering, the sequence-number race guard, control re-entrancy, dialog keying against the wrong session, and the GoalState type resolving to the same underlying type through a different path. One behavioural difference was found and it is an improvement: the indicator moves from an IIFE rebuilding a closure every render to a memo keyed on the active goal, so the reference is now stable.

No second implementation survives. We verified this at the gate independently: window.maka.goal has zero hits in production code on this head, use-session-goal.ts no longer exists in the tree, and the only remaining references to the old surface are stories pointing at the deliberate testing export.

One thing worth recording without grading it: the adapter's subscribeChanges collapses events down to sessionId | undefined, discarding metadata beyond the reason. That is the right boundary for what goals need today, but if goals ever need another session reason — a removal, say — the adapter is where that has to be reopened. Noting it as a known edge of the seam, not as a defect.

CI is terminal green on this head (test: completed / success), which is the head this approval is bound to.

Approving.

@chihumyum
chihumyumforce-pushed the refactor/goals-feature-slice branch 2 times, most recently from d38904b to cfce73eCompareAugust 23, 2026 07:53
@chihumyum

Copy link
Copy Markdown
ContributorAuthor

Rebased onto current upstream/main (729839ed8) and resolved the GoalDialog conflict in cfce73ee9.

The resolution preserves the newly merged reconnect reconciliation behavior: Goal arm outcomes still fence stale results, lock reconciled states, and prevent duplicate submission, while the bridge call remains behind the Goals service port. The reconciliation model and its tests now live inside the Goals feature boundary.

Verified after the final rebase:

  • npm run lint
  • npm run format:check
  • npm run astryx:surface-inventory
  • npm run build
  • npm run typecheck
  • npm --workspace @maka/desktop run test:dist — 1255 passed
  • npx knip --workspace apps/desktop

GitHub now reports the PR as mergeable. The new fork CI run is action_required and needs maintainer approval before jobs start.

Move Goal state, subscriptions, controls, dialog ownership, and view-model assembly behind a renderer feature boundary and Desktop adapter. Add fake services, lifecycle tests, and architecture guardrails without changing the preload contract or user behavior.
Refs apache#3439
Generated-by: Codex
Regenerate the checked-in surface inventory after moving the Goal dialog and adding the Goals feature service and host surfaces.
Refs apache#3439
Generated-by: Codex
@chihumyum
chihumyumforce-pushed the refactor/goals-feature-slice branch from cfce73e to 0ed2c53CompareAugust 23, 2026 09:10
@chihumyum

Copy link
Copy Markdown
ContributorAuthor

Rechecked against the latest upstream/main (047567c4b). Main had advanced by five commits and the PR had become DIRTY solely because the generated Astryx inventory conflicted again.

Rebased and regenerated the inventory in 0ed2c53c4. Verification:

  • npm run astryx:surface-inventory — 204 files, 1 exclusion
  • git diff --check upstream/main...HEAD
  • merge-tree probe against current main — clean

GitHub no longer reports a merge conflict. The current head workflow is run 32630272181, which is action_required with no jobs and needs maintainer approval to execute.

@jackwenerjackwener left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Incremental technical review of exact head 0ed2c53c4bddef7c97434ad111541ea7111c33d8, executed by the Kabi review agent on behalf of @WAWQAQ under the standing Kabi review/publisher authorization.

GO — no live P0–P3. APPROVE; no merge action.

This review covers the rebase-only delta that incorporated the newly merged Goal arm reconciliation contract. Comparing the pre-extraction implementation at current base 047567c4b with the moved feature code shows semantic parity: only armed closes the dialog; matching/different/null reconciled results and reconciliation_unavailable all lock the form, show the authoritative outcome, and prevent duplicate submission. interpretGoalArmOutcome is unchanged apart from its relative import.

The bridge authority remains singular: main.tsx creates one Desktop Goal service adapter, its bridge.goal.arm result is returned through the service and controller as Promise<GoalArmOutcome>, and GoalHost injects that exact function into GoalDialog. The Goals feature contains no window.maka.goal access and the old direct production path is absent.

Verification: focused Goals suites 18/18; Desktop main 1273/1274 on the first full run, with the sole unrelated shell-env timeout fixture passing 12/12 when rerun alone; Desktop preload/main/renderer/Storybook typechecks passed. Three discussion endpoints were reconciled after provisional sealing: two old-head reviews, no inline comments, and three author status comments; no live P0–P2.

Fresh action gate: OPEN, non-draft, MERGEABLE/CLEAN; exact-head hosted test is completed/success. This Agent-executed approval does not claim to satisfy any separate unresolved human-review wording.

@Astro-Han
Astro-Han merged commit 42cc510 into apache:mainAug 23, 2026
1 of 2 checks passed
@chihumyum
chihumyum deleted the refactor/goals-feature-slice branch August 23, 2026 16:19
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.

3 participants

@chihumyum@jackwener@Astro-Han
, '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(desktop): extract goals as a feature slice - #3531

Merged
Astro-Han merged 2 commits into
apache:mainfrom
chihumyum:refactor/goals-feature-slice
Aug 23, 2026
Merged

refactor(desktop): extract goals as a feature slice#3531
Astro-Han merged 2 commits into
apache:mainfrom
chihumyum:refactor/goals-feature-slice

Conversation

@chihumyum

Copy link
Copy Markdown
Contributor

Summary

  • Move Goal read state, subscriptions, controls, dialog ownership, and indicator assembly behind a renderer feature boundary.
  • Isolate Desktop bridge access behind a narrow GoalServices adapter and provider; keep AppShell limited to Session context plus host, commands, and selectors.
  • Add fake services and focused lifecycle, adapter, model, and architecture-boundary coverage.

Refs #3439

Verification

  • npm run lint
  • npm run format:check
  • npm run build
  • npm run typecheck
  • npm --workspace @maka/desktop run test:dist — 1198 passed
  • npx knip --workspace apps/desktop
  • npx knip --workspace packages/ui
  • npm --workspace @maka/desktop run build-storybook
  • npm --workspace @maka/desktop run smoke:storybook — 166 stories passed
  • npx playwright test --config e2e/playwright.config.ts from apps/desktop — 50 passed, 1 skipped

No screenshots are included because this changes no Goal copy, CSS, layout, IPC contract, or user-visible behavior.

Review focus

  • Session-switch fencing for stale Goal reads.
  • Goal-change event filtering and subscription disposal.
  • Dialog ownership of the Session captured when it opens.
  • Per-Session pause/resume re-entry protection.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex assisted with the feature extraction, implementation, tests, and verification.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@chihumyum
chihumyum marked this pull request as ready for review August 22, 2026 19:15

@Astro-HanAstro-Han 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.

Reviewed at head b29e3c4e. One blocking item, and it is a generated file rather than the code — the extraction itself came through clean.

[P1] The Astryx surface inventory wasn't regenerated, and that's what's failing test.

test is FAILURE on this exact head (job 97083453961), and I reproduced it locally: npm run astryx:surface-inventory exits 1 on this branch, consistently. Three moved files are on disk but absent from docs/astryx-surface-file-inventory.pathsapps/desktop/src/renderer/features/goals/ui/goal-dialog.tsx, plus services-context.tsx and goal-host.tsx in the same directory — while the pre-move apps/desktop/src/renderer/goal-dialog.tsx is still listed. docs/astryx-surface-file-inventory.md is likewise out of sync with the generator's output.

Fix is mechanical: run npm run astryx:surface-inventory:write and commit both regenerated files. Nothing about the runtime behaviour is at fault here — the gate is doing its job, the branch just moved surfaces without re-running it.


On the refactor itself: no P0–P3.

For a pure extraction the question is only ever whether behaviour changed under cover of moving things, so that is where I spent the time. use-goal-controller.ts ends up holding the active goal, session-switch clearing, the late-read sequence and disposed guards, the goal-change subscription, per-session control dedupe, and the dialog's session snapshot — and it stays a projection of Host events rather than becoming a second authority, which is the failure mode this kind of slice usually introduces. create-goal-services.ts is the single Desktop bridge adapter, and AppShell only reaches Goals through GoalHost and the controller's public API.

The deletion side checks out too, which is the part that makes an extraction actually reduce entropy rather than add a layer: use-session-goal.ts is gone, the old dialog's direct window.maka dependency is gone, and AppShell no longer carries goal control state. A repo-wide search finds no useSessionGoal and no surviving production entry to the old dialog path.

Verified: Goals focused tests 12/12; controller, model, adapter, and feature-boundary suites all pass; @maka/desktop builds and typechecks across renderer, preload, main, and Storybook; Biome clean on changed files. The full desktop main suite ran 1190 pass / 0 fail with 8 cancelled — the cancellations sit in pre-existing MCP OAuth pending tests and are not attributable to this branch, so I'm reporting it that way rather than calling the suite green.

Regenerate the inventory and this is ready for another look.

@chihumyum

Copy link
Copy Markdown
ContributorAuthor

Fixed in f9554a9af by regenerating both checked-in Astryx surface inventory files.

Local verification:

  • npm run astryx:surface-inventory:write
  • npm run astryx:surface-inventory — 203 files, 1 exclusion
  • git diff --check

The new CI run is currently action_required with no jobs, so it needs maintainer approval before GitHub will execute the workflow.

@Astro-HanAstro-Han 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.

Two independent lines on f9554a9af129f6bede8b7975c0a4bb9a2a0cc3be, from different models, neither able to see the other's conclusion. Both came back with nothing at P0–P3, and — more importantly for a refactor — both answered the question that actually matters here.

A refactor's failure mode isn't "didn't fix it", it's "changed behaviour in transit", and in a diff a relocation and a rewrite look identical. So both lines were asked to split -263 into what genuinely disappeared versus what is just move noise.

What disappeared (~150 lines):

  • use-session-goal.ts is gone as a file, and its authority — goal state, the change subscription, session-switch semantics — moved wholesale to the controller rather than being copied.
  • The indicator construction inlined in app-shell.tsx (~55 lines), plus runGoalControl, pendingGoalControlSessionIdsRef and goalDialogSessionId, all leave the shell. AppShell keeps two lines of wiring.

That is one ownership leaving one place and arriving in another, not a copy. Move noise (~110 lines) is the dialog relocating into features/goals/ui/ and isLiveGoal moving to model/live-goal.ts.

The controller being larger than the hook it replaces is explained rather than hand-waved: it absorbed the behaviour that used to live inline in the shell, so the two are not comparable line-for-line.

Semantic parity was checked point by point rather than asserted: subscription filtering (including the broadcast undefined case), session-switch ordering, the sequence-number race guard, control re-entrancy, dialog keying against the wrong session, and the GoalState type resolving to the same underlying type through a different path. One behavioural difference was found and it is an improvement: the indicator moves from an IIFE rebuilding a closure every render to a memo keyed on the active goal, so the reference is now stable.

No second implementation survives. We verified this at the gate independently: window.maka.goal has zero hits in production code on this head, use-session-goal.ts no longer exists in the tree, and the only remaining references to the old surface are stories pointing at the deliberate testing export.

One thing worth recording without grading it: the adapter's subscribeChanges collapses events down to sessionId | undefined, discarding metadata beyond the reason. That is the right boundary for what goals need today, but if goals ever need another session reason — a removal, say — the adapter is where that has to be reopened. Noting it as a known edge of the seam, not as a defect.

CI is terminal green on this head (test: completed / success), which is the head this approval is bound to.

Approving.

@chihumyum
chihumyumforce-pushed the refactor/goals-feature-slice branch 2 times, most recently from d38904b to cfce73eCompareAugust 23, 2026 07:53
@chihumyum

Copy link
Copy Markdown
ContributorAuthor

Rebased onto current upstream/main (729839ed8) and resolved the GoalDialog conflict in cfce73ee9.

The resolution preserves the newly merged reconnect reconciliation behavior: Goal arm outcomes still fence stale results, lock reconciled states, and prevent duplicate submission, while the bridge call remains behind the Goals service port. The reconciliation model and its tests now live inside the Goals feature boundary.

Verified after the final rebase:

  • npm run lint
  • npm run format:check
  • npm run astryx:surface-inventory
  • npm run build
  • npm run typecheck
  • npm --workspace @maka/desktop run test:dist — 1255 passed
  • npx knip --workspace apps/desktop

GitHub now reports the PR as mergeable. The new fork CI run is action_required and needs maintainer approval before jobs start.

Move Goal state, subscriptions, controls, dialog ownership, and view-model assembly behind a renderer feature boundary and Desktop adapter. Add fake services, lifecycle tests, and architecture guardrails without changing the preload contract or user behavior.
Refs apache#3439
Generated-by: Codex
Regenerate the checked-in surface inventory after moving the Goal dialog and adding the Goals feature service and host surfaces.
Refs apache#3439
Generated-by: Codex
@chihumyum
chihumyumforce-pushed the refactor/goals-feature-slice branch from cfce73e to 0ed2c53CompareAugust 23, 2026 09:10
@chihumyum

Copy link
Copy Markdown
ContributorAuthor

Rechecked against the latest upstream/main (047567c4b). Main had advanced by five commits and the PR had become DIRTY solely because the generated Astryx inventory conflicted again.

Rebased and regenerated the inventory in 0ed2c53c4. Verification:

  • npm run astryx:surface-inventory — 204 files, 1 exclusion
  • git diff --check upstream/main...HEAD
  • merge-tree probe against current main — clean

GitHub no longer reports a merge conflict. The current head workflow is run 32630272181, which is action_required with no jobs and needs maintainer approval to execute.

@jackwenerjackwener left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Incremental technical review of exact head 0ed2c53c4bddef7c97434ad111541ea7111c33d8, executed by the Kabi review agent on behalf of @WAWQAQ under the standing Kabi review/publisher authorization.

GO — no live P0–P3. APPROVE; no merge action.

This review covers the rebase-only delta that incorporated the newly merged Goal arm reconciliation contract. Comparing the pre-extraction implementation at current base 047567c4b with the moved feature code shows semantic parity: only armed closes the dialog; matching/different/null reconciled results and reconciliation_unavailable all lock the form, show the authoritative outcome, and prevent duplicate submission. interpretGoalArmOutcome is unchanged apart from its relative import.

The bridge authority remains singular: main.tsx creates one Desktop Goal service adapter, its bridge.goal.arm result is returned through the service and controller as Promise<GoalArmOutcome>, and GoalHost injects that exact function into GoalDialog. The Goals feature contains no window.maka.goal access and the old direct production path is absent.

Verification: focused Goals suites 18/18; Desktop main 1273/1274 on the first full run, with the sole unrelated shell-env timeout fixture passing 12/12 when rerun alone; Desktop preload/main/renderer/Storybook typechecks passed. Three discussion endpoints were reconciled after provisional sealing: two old-head reviews, no inline comments, and three author status comments; no live P0–P2.

Fresh action gate: OPEN, non-draft, MERGEABLE/CLEAN; exact-head hosted test is completed/success. This Agent-executed approval does not claim to satisfy any separate unresolved human-review wording.

@Astro-Han
Astro-Han merged commit 42cc510 into apache:mainAug 23, 2026
1 of 2 checks passed
@chihumyum
chihumyum deleted the refactor/goals-feature-slice branch August 23, 2026 16:19
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.

3 participants

@chihumyum@jackwener@Astro-Han
, '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(desktop): extract goals as a feature slice - #3531

Merged
Astro-Han merged 2 commits into
apache:mainfrom
chihumyum:refactor/goals-feature-slice
Aug 23, 2026
Merged

refactor(desktop): extract goals as a feature slice#3531
Astro-Han merged 2 commits into
apache:mainfrom
chihumyum:refactor/goals-feature-slice

Conversation

@chihumyum

Copy link
Copy Markdown
Contributor

Summary

  • Move Goal read state, subscriptions, controls, dialog ownership, and indicator assembly behind a renderer feature boundary.
  • Isolate Desktop bridge access behind a narrow GoalServices adapter and provider; keep AppShell limited to Session context plus host, commands, and selectors.
  • Add fake services and focused lifecycle, adapter, model, and architecture-boundary coverage.

Refs #3439

Verification

  • npm run lint
  • npm run format:check
  • npm run build
  • npm run typecheck
  • npm --workspace @maka/desktop run test:dist — 1198 passed
  • npx knip --workspace apps/desktop
  • npx knip --workspace packages/ui
  • npm --workspace @maka/desktop run build-storybook
  • npm --workspace @maka/desktop run smoke:storybook — 166 stories passed
  • npx playwright test --config e2e/playwright.config.ts from apps/desktop — 50 passed, 1 skipped

No screenshots are included because this changes no Goal copy, CSS, layout, IPC contract, or user-visible behavior.

Review focus

  • Session-switch fencing for stale Goal reads.
  • Goal-change event filtering and subscription disposal.
  • Dialog ownership of the Session captured when it opens.
  • Per-Session pause/resume re-entry protection.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex assisted with the feature extraction, implementation, tests, and verification.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@chihumyum
chihumyum marked this pull request as ready for review August 22, 2026 19:15

@Astro-HanAstro-Han 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.

Reviewed at head b29e3c4e. One blocking item, and it is a generated file rather than the code — the extraction itself came through clean.

[P1] The Astryx surface inventory wasn't regenerated, and that's what's failing test.

test is FAILURE on this exact head (job 97083453961), and I reproduced it locally: npm run astryx:surface-inventory exits 1 on this branch, consistently. Three moved files are on disk but absent from docs/astryx-surface-file-inventory.pathsapps/desktop/src/renderer/features/goals/ui/goal-dialog.tsx, plus services-context.tsx and goal-host.tsx in the same directory — while the pre-move apps/desktop/src/renderer/goal-dialog.tsx is still listed. docs/astryx-surface-file-inventory.md is likewise out of sync with the generator's output.

Fix is mechanical: run npm run astryx:surface-inventory:write and commit both regenerated files. Nothing about the runtime behaviour is at fault here — the gate is doing its job, the branch just moved surfaces without re-running it.


On the refactor itself: no P0–P3.

For a pure extraction the question is only ever whether behaviour changed under cover of moving things, so that is where I spent the time. use-goal-controller.ts ends up holding the active goal, session-switch clearing, the late-read sequence and disposed guards, the goal-change subscription, per-session control dedupe, and the dialog's session snapshot — and it stays a projection of Host events rather than becoming a second authority, which is the failure mode this kind of slice usually introduces. create-goal-services.ts is the single Desktop bridge adapter, and AppShell only reaches Goals through GoalHost and the controller's public API.

The deletion side checks out too, which is the part that makes an extraction actually reduce entropy rather than add a layer: use-session-goal.ts is gone, the old dialog's direct window.maka dependency is gone, and AppShell no longer carries goal control state. A repo-wide search finds no useSessionGoal and no surviving production entry to the old dialog path.

Verified: Goals focused tests 12/12; controller, model, adapter, and feature-boundary suites all pass; @maka/desktop builds and typechecks across renderer, preload, main, and Storybook; Biome clean on changed files. The full desktop main suite ran 1190 pass / 0 fail with 8 cancelled — the cancellations sit in pre-existing MCP OAuth pending tests and are not attributable to this branch, so I'm reporting it that way rather than calling the suite green.

Regenerate the inventory and this is ready for another look.

@chihumyum

Copy link
Copy Markdown
ContributorAuthor

Fixed in f9554a9af by regenerating both checked-in Astryx surface inventory files.

Local verification:

  • npm run astryx:surface-inventory:write
  • npm run astryx:surface-inventory — 203 files, 1 exclusion
  • git diff --check

The new CI run is currently action_required with no jobs, so it needs maintainer approval before GitHub will execute the workflow.

@Astro-HanAstro-Han 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.

Two independent lines on f9554a9af129f6bede8b7975c0a4bb9a2a0cc3be, from different models, neither able to see the other's conclusion. Both came back with nothing at P0–P3, and — more importantly for a refactor — both answered the question that actually matters here.

A refactor's failure mode isn't "didn't fix it", it's "changed behaviour in transit", and in a diff a relocation and a rewrite look identical. So both lines were asked to split -263 into what genuinely disappeared versus what is just move noise.

What disappeared (~150 lines):

  • use-session-goal.ts is gone as a file, and its authority — goal state, the change subscription, session-switch semantics — moved wholesale to the controller rather than being copied.
  • The indicator construction inlined in app-shell.tsx (~55 lines), plus runGoalControl, pendingGoalControlSessionIdsRef and goalDialogSessionId, all leave the shell. AppShell keeps two lines of wiring.

That is one ownership leaving one place and arriving in another, not a copy. Move noise (~110 lines) is the dialog relocating into features/goals/ui/ and isLiveGoal moving to model/live-goal.ts.

The controller being larger than the hook it replaces is explained rather than hand-waved: it absorbed the behaviour that used to live inline in the shell, so the two are not comparable line-for-line.

Semantic parity was checked point by point rather than asserted: subscription filtering (including the broadcast undefined case), session-switch ordering, the sequence-number race guard, control re-entrancy, dialog keying against the wrong session, and the GoalState type resolving to the same underlying type through a different path. One behavioural difference was found and it is an improvement: the indicator moves from an IIFE rebuilding a closure every render to a memo keyed on the active goal, so the reference is now stable.

No second implementation survives. We verified this at the gate independently: window.maka.goal has zero hits in production code on this head, use-session-goal.ts no longer exists in the tree, and the only remaining references to the old surface are stories pointing at the deliberate testing export.

One thing worth recording without grading it: the adapter's subscribeChanges collapses events down to sessionId | undefined, discarding metadata beyond the reason. That is the right boundary for what goals need today, but if goals ever need another session reason — a removal, say — the adapter is where that has to be reopened. Noting it as a known edge of the seam, not as a defect.

CI is terminal green on this head (test: completed / success), which is the head this approval is bound to.

Approving.

@chihumyum
chihumyumforce-pushed the refactor/goals-feature-slice branch 2 times, most recently from d38904b to cfce73eCompareAugust 23, 2026 07:53
@chihumyum

Copy link
Copy Markdown
ContributorAuthor

Rebased onto current upstream/main (729839ed8) and resolved the GoalDialog conflict in cfce73ee9.

The resolution preserves the newly merged reconnect reconciliation behavior: Goal arm outcomes still fence stale results, lock reconciled states, and prevent duplicate submission, while the bridge call remains behind the Goals service port. The reconciliation model and its tests now live inside the Goals feature boundary.

Verified after the final rebase:

  • npm run lint
  • npm run format:check
  • npm run astryx:surface-inventory
  • npm run build
  • npm run typecheck
  • npm --workspace @maka/desktop run test:dist — 1255 passed
  • npx knip --workspace apps/desktop

GitHub now reports the PR as mergeable. The new fork CI run is action_required and needs maintainer approval before jobs start.

Move Goal state, subscriptions, controls, dialog ownership, and view-model assembly behind a renderer feature boundary and Desktop adapter. Add fake services, lifecycle tests, and architecture guardrails without changing the preload contract or user behavior.
Refs apache#3439
Generated-by: Codex
Regenerate the checked-in surface inventory after moving the Goal dialog and adding the Goals feature service and host surfaces.
Refs apache#3439
Generated-by: Codex
@chihumyum
chihumyumforce-pushed the refactor/goals-feature-slice branch from cfce73e to 0ed2c53CompareAugust 23, 2026 09:10
@chihumyum

Copy link
Copy Markdown
ContributorAuthor

Rechecked against the latest upstream/main (047567c4b). Main had advanced by five commits and the PR had become DIRTY solely because the generated Astryx inventory conflicted again.

Rebased and regenerated the inventory in 0ed2c53c4. Verification:

  • npm run astryx:surface-inventory — 204 files, 1 exclusion
  • git diff --check upstream/main...HEAD
  • merge-tree probe against current main — clean

GitHub no longer reports a merge conflict. The current head workflow is run 32630272181, which is action_required with no jobs and needs maintainer approval to execute.

@jackwenerjackwener left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Incremental technical review of exact head 0ed2c53c4bddef7c97434ad111541ea7111c33d8, executed by the Kabi review agent on behalf of @WAWQAQ under the standing Kabi review/publisher authorization.

GO — no live P0–P3. APPROVE; no merge action.

This review covers the rebase-only delta that incorporated the newly merged Goal arm reconciliation contract. Comparing the pre-extraction implementation at current base 047567c4b with the moved feature code shows semantic parity: only armed closes the dialog; matching/different/null reconciled results and reconciliation_unavailable all lock the form, show the authoritative outcome, and prevent duplicate submission. interpretGoalArmOutcome is unchanged apart from its relative import.

The bridge authority remains singular: main.tsx creates one Desktop Goal service adapter, its bridge.goal.arm result is returned through the service and controller as Promise<GoalArmOutcome>, and GoalHost injects that exact function into GoalDialog. The Goals feature contains no window.maka.goal access and the old direct production path is absent.

Verification: focused Goals suites 18/18; Desktop main 1273/1274 on the first full run, with the sole unrelated shell-env timeout fixture passing 12/12 when rerun alone; Desktop preload/main/renderer/Storybook typechecks passed. Three discussion endpoints were reconciled after provisional sealing: two old-head reviews, no inline comments, and three author status comments; no live P0–P2.

Fresh action gate: OPEN, non-draft, MERGEABLE/CLEAN; exact-head hosted test is completed/success. This Agent-executed approval does not claim to satisfy any separate unresolved human-review wording.

@Astro-Han
Astro-Han merged commit 42cc510 into apache:mainAug 23, 2026
1 of 2 checks passed
@chihumyum
chihumyum deleted the refactor/goals-feature-slice branch August 23, 2026 16:19
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.

3 participants

@chihumyum@jackwener@Astro-Han
, '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(desktop): extract goals as a feature slice - #3531

Merged
Astro-Han merged 2 commits into
apache:mainfrom
chihumyum:refactor/goals-feature-slice
Aug 23, 2026
Merged

refactor(desktop): extract goals as a feature slice#3531
Astro-Han merged 2 commits into
apache:mainfrom
chihumyum:refactor/goals-feature-slice

Conversation

@chihumyum

Copy link
Copy Markdown
Contributor

Summary

  • Move Goal read state, subscriptions, controls, dialog ownership, and indicator assembly behind a renderer feature boundary.
  • Isolate Desktop bridge access behind a narrow GoalServices adapter and provider; keep AppShell limited to Session context plus host, commands, and selectors.
  • Add fake services and focused lifecycle, adapter, model, and architecture-boundary coverage.

Refs #3439

Verification

  • npm run lint
  • npm run format:check
  • npm run build
  • npm run typecheck
  • npm --workspace @maka/desktop run test:dist — 1198 passed
  • npx knip --workspace apps/desktop
  • npx knip --workspace packages/ui
  • npm --workspace @maka/desktop run build-storybook
  • npm --workspace @maka/desktop run smoke:storybook — 166 stories passed
  • npx playwright test --config e2e/playwright.config.ts from apps/desktop — 50 passed, 1 skipped

No screenshots are included because this changes no Goal copy, CSS, layout, IPC contract, or user-visible behavior.

Review focus

  • Session-switch fencing for stale Goal reads.
  • Goal-change event filtering and subscription disposal.
  • Dialog ownership of the Session captured when it opens.
  • Per-Session pause/resume re-entry protection.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex assisted with the feature extraction, implementation, tests, and verification.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@chihumyum
chihumyum marked this pull request as ready for review August 22, 2026 19:15

@Astro-HanAstro-Han 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.

Reviewed at head b29e3c4e. One blocking item, and it is a generated file rather than the code — the extraction itself came through clean.

[P1] The Astryx surface inventory wasn't regenerated, and that's what's failing test.

test is FAILURE on this exact head (job 97083453961), and I reproduced it locally: npm run astryx:surface-inventory exits 1 on this branch, consistently. Three moved files are on disk but absent from docs/astryx-surface-file-inventory.pathsapps/desktop/src/renderer/features/goals/ui/goal-dialog.tsx, plus services-context.tsx and goal-host.tsx in the same directory — while the pre-move apps/desktop/src/renderer/goal-dialog.tsx is still listed. docs/astryx-surface-file-inventory.md is likewise out of sync with the generator's output.

Fix is mechanical: run npm run astryx:surface-inventory:write and commit both regenerated files. Nothing about the runtime behaviour is at fault here — the gate is doing its job, the branch just moved surfaces without re-running it.


On the refactor itself: no P0–P3.

For a pure extraction the question is only ever whether behaviour changed under cover of moving things, so that is where I spent the time. use-goal-controller.ts ends up holding the active goal, session-switch clearing, the late-read sequence and disposed guards, the goal-change subscription, per-session control dedupe, and the dialog's session snapshot — and it stays a projection of Host events rather than becoming a second authority, which is the failure mode this kind of slice usually introduces. create-goal-services.ts is the single Desktop bridge adapter, and AppShell only reaches Goals through GoalHost and the controller's public API.

The deletion side checks out too, which is the part that makes an extraction actually reduce entropy rather than add a layer: use-session-goal.ts is gone, the old dialog's direct window.maka dependency is gone, and AppShell no longer carries goal control state. A repo-wide search finds no useSessionGoal and no surviving production entry to the old dialog path.

Verified: Goals focused tests 12/12; controller, model, adapter, and feature-boundary suites all pass; @maka/desktop builds and typechecks across renderer, preload, main, and Storybook; Biome clean on changed files. The full desktop main suite ran 1190 pass / 0 fail with 8 cancelled — the cancellations sit in pre-existing MCP OAuth pending tests and are not attributable to this branch, so I'm reporting it that way rather than calling the suite green.

Regenerate the inventory and this is ready for another look.

@chihumyum

Copy link
Copy Markdown
ContributorAuthor

Fixed in f9554a9af by regenerating both checked-in Astryx surface inventory files.

Local verification:

  • npm run astryx:surface-inventory:write
  • npm run astryx:surface-inventory — 203 files, 1 exclusion
  • git diff --check

The new CI run is currently action_required with no jobs, so it needs maintainer approval before GitHub will execute the workflow.

@Astro-HanAstro-Han 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.

Two independent lines on f9554a9af129f6bede8b7975c0a4bb9a2a0cc3be, from different models, neither able to see the other's conclusion. Both came back with nothing at P0–P3, and — more importantly for a refactor — both answered the question that actually matters here.

A refactor's failure mode isn't "didn't fix it", it's "changed behaviour in transit", and in a diff a relocation and a rewrite look identical. So both lines were asked to split -263 into what genuinely disappeared versus what is just move noise.

What disappeared (~150 lines):

  • use-session-goal.ts is gone as a file, and its authority — goal state, the change subscription, session-switch semantics — moved wholesale to the controller rather than being copied.
  • The indicator construction inlined in app-shell.tsx (~55 lines), plus runGoalControl, pendingGoalControlSessionIdsRef and goalDialogSessionId, all leave the shell. AppShell keeps two lines of wiring.

That is one ownership leaving one place and arriving in another, not a copy. Move noise (~110 lines) is the dialog relocating into features/goals/ui/ and isLiveGoal moving to model/live-goal.ts.

The controller being larger than the hook it replaces is explained rather than hand-waved: it absorbed the behaviour that used to live inline in the shell, so the two are not comparable line-for-line.

Semantic parity was checked point by point rather than asserted: subscription filtering (including the broadcast undefined case), session-switch ordering, the sequence-number race guard, control re-entrancy, dialog keying against the wrong session, and the GoalState type resolving to the same underlying type through a different path. One behavioural difference was found and it is an improvement: the indicator moves from an IIFE rebuilding a closure every render to a memo keyed on the active goal, so the reference is now stable.

No second implementation survives. We verified this at the gate independently: window.maka.goal has zero hits in production code on this head, use-session-goal.ts no longer exists in the tree, and the only remaining references to the old surface are stories pointing at the deliberate testing export.

One thing worth recording without grading it: the adapter's subscribeChanges collapses events down to sessionId | undefined, discarding metadata beyond the reason. That is the right boundary for what goals need today, but if goals ever need another session reason — a removal, say — the adapter is where that has to be reopened. Noting it as a known edge of the seam, not as a defect.

CI is terminal green on this head (test: completed / success), which is the head this approval is bound to.

Approving.

@chihumyum
chihumyumforce-pushed the refactor/goals-feature-slice branch 2 times, most recently from d38904b to cfce73eCompareAugust 23, 2026 07:53
@chihumyum

Copy link
Copy Markdown
ContributorAuthor

Rebased onto current upstream/main (729839ed8) and resolved the GoalDialog conflict in cfce73ee9.

The resolution preserves the newly merged reconnect reconciliation behavior: Goal arm outcomes still fence stale results, lock reconciled states, and prevent duplicate submission, while the bridge call remains behind the Goals service port. The reconciliation model and its tests now live inside the Goals feature boundary.

Verified after the final rebase:

  • npm run lint
  • npm run format:check
  • npm run astryx:surface-inventory
  • npm run build
  • npm run typecheck
  • npm --workspace @maka/desktop run test:dist — 1255 passed
  • npx knip --workspace apps/desktop

GitHub now reports the PR as mergeable. The new fork CI run is action_required and needs maintainer approval before jobs start.

Move Goal state, subscriptions, controls, dialog ownership, and view-model assembly behind a renderer feature boundary and Desktop adapter. Add fake services, lifecycle tests, and architecture guardrails without changing the preload contract or user behavior.
Refs apache#3439
Generated-by: Codex
Regenerate the checked-in surface inventory after moving the Goal dialog and adding the Goals feature service and host surfaces.
Refs apache#3439
Generated-by: Codex
@chihumyum
chihumyumforce-pushed the refactor/goals-feature-slice branch from cfce73e to 0ed2c53CompareAugust 23, 2026 09:10
@chihumyum

Copy link
Copy Markdown
ContributorAuthor

Rechecked against the latest upstream/main (047567c4b). Main had advanced by five commits and the PR had become DIRTY solely because the generated Astryx inventory conflicted again.

Rebased and regenerated the inventory in 0ed2c53c4. Verification:

  • npm run astryx:surface-inventory — 204 files, 1 exclusion
  • git diff --check upstream/main...HEAD
  • merge-tree probe against current main — clean

GitHub no longer reports a merge conflict. The current head workflow is run 32630272181, which is action_required with no jobs and needs maintainer approval to execute.

@jackwenerjackwener left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Incremental technical review of exact head 0ed2c53c4bddef7c97434ad111541ea7111c33d8, executed by the Kabi review agent on behalf of @WAWQAQ under the standing Kabi review/publisher authorization.

GO — no live P0–P3. APPROVE; no merge action.

This review covers the rebase-only delta that incorporated the newly merged Goal arm reconciliation contract. Comparing the pre-extraction implementation at current base 047567c4b with the moved feature code shows semantic parity: only armed closes the dialog; matching/different/null reconciled results and reconciliation_unavailable all lock the form, show the authoritative outcome, and prevent duplicate submission. interpretGoalArmOutcome is unchanged apart from its relative import.

The bridge authority remains singular: main.tsx creates one Desktop Goal service adapter, its bridge.goal.arm result is returned through the service and controller as Promise<GoalArmOutcome>, and GoalHost injects that exact function into GoalDialog. The Goals feature contains no window.maka.goal access and the old direct production path is absent.

Verification: focused Goals suites 18/18; Desktop main 1273/1274 on the first full run, with the sole unrelated shell-env timeout fixture passing 12/12 when rerun alone; Desktop preload/main/renderer/Storybook typechecks passed. Three discussion endpoints were reconciled after provisional sealing: two old-head reviews, no inline comments, and three author status comments; no live P0–P2.

Fresh action gate: OPEN, non-draft, MERGEABLE/CLEAN; exact-head hosted test is completed/success. This Agent-executed approval does not claim to satisfy any separate unresolved human-review wording.

@Astro-Han
Astro-Han merged commit 42cc510 into apache:mainAug 23, 2026
1 of 2 checks passed
@chihumyum
chihumyum deleted the refactor/goals-feature-slice branch August 23, 2026 16:19
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.

3 participants

@chihumyum@jackwener@Astro-Han
, '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(desktop): extract goals as a feature slice - #3531

Merged
Astro-Han merged 2 commits into
apache:mainfrom
chihumyum:refactor/goals-feature-slice
Aug 23, 2026
Merged

refactor(desktop): extract goals as a feature slice#3531
Astro-Han merged 2 commits into
apache:mainfrom
chihumyum:refactor/goals-feature-slice

Conversation

@chihumyum

Copy link
Copy Markdown
Contributor

Summary

  • Move Goal read state, subscriptions, controls, dialog ownership, and indicator assembly behind a renderer feature boundary.
  • Isolate Desktop bridge access behind a narrow GoalServices adapter and provider; keep AppShell limited to Session context plus host, commands, and selectors.
  • Add fake services and focused lifecycle, adapter, model, and architecture-boundary coverage.

Refs #3439

Verification

  • npm run lint
  • npm run format:check
  • npm run build
  • npm run typecheck
  • npm --workspace @maka/desktop run test:dist — 1198 passed
  • npx knip --workspace apps/desktop
  • npx knip --workspace packages/ui
  • npm --workspace @maka/desktop run build-storybook
  • npm --workspace @maka/desktop run smoke:storybook — 166 stories passed
  • npx playwright test --config e2e/playwright.config.ts from apps/desktop — 50 passed, 1 skipped

No screenshots are included because this changes no Goal copy, CSS, layout, IPC contract, or user-visible behavior.

Review focus

  • Session-switch fencing for stale Goal reads.
  • Goal-change event filtering and subscription disposal.
  • Dialog ownership of the Session captured when it opens.
  • Per-Session pause/resume re-entry protection.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex assisted with the feature extraction, implementation, tests, and verification.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@chihumyum
chihumyum marked this pull request as ready for review August 22, 2026 19:15

@Astro-HanAstro-Han 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.

Reviewed at head b29e3c4e. One blocking item, and it is a generated file rather than the code — the extraction itself came through clean.

[P1] The Astryx surface inventory wasn't regenerated, and that's what's failing test.

test is FAILURE on this exact head (job 97083453961), and I reproduced it locally: npm run astryx:surface-inventory exits 1 on this branch, consistently. Three moved files are on disk but absent from docs/astryx-surface-file-inventory.pathsapps/desktop/src/renderer/features/goals/ui/goal-dialog.tsx, plus services-context.tsx and goal-host.tsx in the same directory — while the pre-move apps/desktop/src/renderer/goal-dialog.tsx is still listed. docs/astryx-surface-file-inventory.md is likewise out of sync with the generator's output.

Fix is mechanical: run npm run astryx:surface-inventory:write and commit both regenerated files. Nothing about the runtime behaviour is at fault here — the gate is doing its job, the branch just moved surfaces without re-running it.


On the refactor itself: no P0–P3.

For a pure extraction the question is only ever whether behaviour changed under cover of moving things, so that is where I spent the time. use-goal-controller.ts ends up holding the active goal, session-switch clearing, the late-read sequence and disposed guards, the goal-change subscription, per-session control dedupe, and the dialog's session snapshot — and it stays a projection of Host events rather than becoming a second authority, which is the failure mode this kind of slice usually introduces. create-goal-services.ts is the single Desktop bridge adapter, and AppShell only reaches Goals through GoalHost and the controller's public API.

The deletion side checks out too, which is the part that makes an extraction actually reduce entropy rather than add a layer: use-session-goal.ts is gone, the old dialog's direct window.maka dependency is gone, and AppShell no longer carries goal control state. A repo-wide search finds no useSessionGoal and no surviving production entry to the old dialog path.

Verified: Goals focused tests 12/12; controller, model, adapter, and feature-boundary suites all pass; @maka/desktop builds and typechecks across renderer, preload, main, and Storybook; Biome clean on changed files. The full desktop main suite ran 1190 pass / 0 fail with 8 cancelled — the cancellations sit in pre-existing MCP OAuth pending tests and are not attributable to this branch, so I'm reporting it that way rather than calling the suite green.

Regenerate the inventory and this is ready for another look.

@chihumyum

Copy link
Copy Markdown
ContributorAuthor

Fixed in f9554a9af by regenerating both checked-in Astryx surface inventory files.

Local verification:

  • npm run astryx:surface-inventory:write
  • npm run astryx:surface-inventory — 203 files, 1 exclusion
  • git diff --check

The new CI run is currently action_required with no jobs, so it needs maintainer approval before GitHub will execute the workflow.

@Astro-HanAstro-Han 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.

Two independent lines on f9554a9af129f6bede8b7975c0a4bb9a2a0cc3be, from different models, neither able to see the other's conclusion. Both came back with nothing at P0–P3, and — more importantly for a refactor — both answered the question that actually matters here.

A refactor's failure mode isn't "didn't fix it", it's "changed behaviour in transit", and in a diff a relocation and a rewrite look identical. So both lines were asked to split -263 into what genuinely disappeared versus what is just move noise.

What disappeared (~150 lines):

  • use-session-goal.ts is gone as a file, and its authority — goal state, the change subscription, session-switch semantics — moved wholesale to the controller rather than being copied.
  • The indicator construction inlined in app-shell.tsx (~55 lines), plus runGoalControl, pendingGoalControlSessionIdsRef and goalDialogSessionId, all leave the shell. AppShell keeps two lines of wiring.

That is one ownership leaving one place and arriving in another, not a copy. Move noise (~110 lines) is the dialog relocating into features/goals/ui/ and isLiveGoal moving to model/live-goal.ts.

The controller being larger than the hook it replaces is explained rather than hand-waved: it absorbed the behaviour that used to live inline in the shell, so the two are not comparable line-for-line.

Semantic parity was checked point by point rather than asserted: subscription filtering (including the broadcast undefined case), session-switch ordering, the sequence-number race guard, control re-entrancy, dialog keying against the wrong session, and the GoalState type resolving to the same underlying type through a different path. One behavioural difference was found and it is an improvement: the indicator moves from an IIFE rebuilding a closure every render to a memo keyed on the active goal, so the reference is now stable.

No second implementation survives. We verified this at the gate independently: window.maka.goal has zero hits in production code on this head, use-session-goal.ts no longer exists in the tree, and the only remaining references to the old surface are stories pointing at the deliberate testing export.

One thing worth recording without grading it: the adapter's subscribeChanges collapses events down to sessionId | undefined, discarding metadata beyond the reason. That is the right boundary for what goals need today, but if goals ever need another session reason — a removal, say — the adapter is where that has to be reopened. Noting it as a known edge of the seam, not as a defect.

CI is terminal green on this head (test: completed / success), which is the head this approval is bound to.

Approving.

@chihumyum
chihumyumforce-pushed the refactor/goals-feature-slice branch 2 times, most recently from d38904b to cfce73eCompareAugust 23, 2026 07:53
@chihumyum

Copy link
Copy Markdown
ContributorAuthor

Rebased onto current upstream/main (729839ed8) and resolved the GoalDialog conflict in cfce73ee9.

The resolution preserves the newly merged reconnect reconciliation behavior: Goal arm outcomes still fence stale results, lock reconciled states, and prevent duplicate submission, while the bridge call remains behind the Goals service port. The reconciliation model and its tests now live inside the Goals feature boundary.

Verified after the final rebase:

  • npm run lint
  • npm run format:check
  • npm run astryx:surface-inventory
  • npm run build
  • npm run typecheck
  • npm --workspace @maka/desktop run test:dist — 1255 passed
  • npx knip --workspace apps/desktop

GitHub now reports the PR as mergeable. The new fork CI run is action_required and needs maintainer approval before jobs start.

Move Goal state, subscriptions, controls, dialog ownership, and view-model assembly behind a renderer feature boundary and Desktop adapter. Add fake services, lifecycle tests, and architecture guardrails without changing the preload contract or user behavior.
Refs apache#3439
Generated-by: Codex
Regenerate the checked-in surface inventory after moving the Goal dialog and adding the Goals feature service and host surfaces.
Refs apache#3439
Generated-by: Codex
@chihumyum
chihumyumforce-pushed the refactor/goals-feature-slice branch from cfce73e to 0ed2c53CompareAugust 23, 2026 09:10
@chihumyum

Copy link
Copy Markdown
ContributorAuthor

Rechecked against the latest upstream/main (047567c4b). Main had advanced by five commits and the PR had become DIRTY solely because the generated Astryx inventory conflicted again.

Rebased and regenerated the inventory in 0ed2c53c4. Verification:

  • npm run astryx:surface-inventory — 204 files, 1 exclusion
  • git diff --check upstream/main...HEAD
  • merge-tree probe against current main — clean

GitHub no longer reports a merge conflict. The current head workflow is run 32630272181, which is action_required with no jobs and needs maintainer approval to execute.

@jackwenerjackwener left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Incremental technical review of exact head 0ed2c53c4bddef7c97434ad111541ea7111c33d8, executed by the Kabi review agent on behalf of @WAWQAQ under the standing Kabi review/publisher authorization.

GO — no live P0–P3. APPROVE; no merge action.

This review covers the rebase-only delta that incorporated the newly merged Goal arm reconciliation contract. Comparing the pre-extraction implementation at current base 047567c4b with the moved feature code shows semantic parity: only armed closes the dialog; matching/different/null reconciled results and reconciliation_unavailable all lock the form, show the authoritative outcome, and prevent duplicate submission. interpretGoalArmOutcome is unchanged apart from its relative import.

The bridge authority remains singular: main.tsx creates one Desktop Goal service adapter, its bridge.goal.arm result is returned through the service and controller as Promise<GoalArmOutcome>, and GoalHost injects that exact function into GoalDialog. The Goals feature contains no window.maka.goal access and the old direct production path is absent.

Verification: focused Goals suites 18/18; Desktop main 1273/1274 on the first full run, with the sole unrelated shell-env timeout fixture passing 12/12 when rerun alone; Desktop preload/main/renderer/Storybook typechecks passed. Three discussion endpoints were reconciled after provisional sealing: two old-head reviews, no inline comments, and three author status comments; no live P0–P2.

Fresh action gate: OPEN, non-draft, MERGEABLE/CLEAN; exact-head hosted test is completed/success. This Agent-executed approval does not claim to satisfy any separate unresolved human-review wording.

@Astro-Han
Astro-Han merged commit 42cc510 into apache:mainAug 23, 2026
1 of 2 checks passed
@chihumyum
chihumyum deleted the refactor/goals-feature-slice branch August 23, 2026 16:19
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.

3 participants

@chihumyum@jackwener@Astro-Han
, '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(desktop): extract goals as a feature slice - #3531

Merged
Astro-Han merged 2 commits into
apache:mainfrom
chihumyum:refactor/goals-feature-slice
Aug 23, 2026
Merged

refactor(desktop): extract goals as a feature slice#3531
Astro-Han merged 2 commits into
apache:mainfrom
chihumyum:refactor/goals-feature-slice

Conversation

@chihumyum

Copy link
Copy Markdown
Contributor

Summary

  • Move Goal read state, subscriptions, controls, dialog ownership, and indicator assembly behind a renderer feature boundary.
  • Isolate Desktop bridge access behind a narrow GoalServices adapter and provider; keep AppShell limited to Session context plus host, commands, and selectors.
  • Add fake services and focused lifecycle, adapter, model, and architecture-boundary coverage.

Refs #3439

Verification

  • npm run lint
  • npm run format:check
  • npm run build
  • npm run typecheck
  • npm --workspace @maka/desktop run test:dist — 1198 passed
  • npx knip --workspace apps/desktop
  • npx knip --workspace packages/ui
  • npm --workspace @maka/desktop run build-storybook
  • npm --workspace @maka/desktop run smoke:storybook — 166 stories passed
  • npx playwright test --config e2e/playwright.config.ts from apps/desktop — 50 passed, 1 skipped

No screenshots are included because this changes no Goal copy, CSS, layout, IPC contract, or user-visible behavior.

Review focus

  • Session-switch fencing for stale Goal reads.
  • Goal-change event filtering and subscription disposal.
  • Dialog ownership of the Session captured when it opens.
  • Per-Session pause/resume re-entry protection.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex assisted with the feature extraction, implementation, tests, and verification.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@chihumyum
chihumyum marked this pull request as ready for review August 22, 2026 19:15

@Astro-HanAstro-Han 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.

Reviewed at head b29e3c4e. One blocking item, and it is a generated file rather than the code — the extraction itself came through clean.

[P1] The Astryx surface inventory wasn't regenerated, and that's what's failing test.

test is FAILURE on this exact head (job 97083453961), and I reproduced it locally: npm run astryx:surface-inventory exits 1 on this branch, consistently. Three moved files are on disk but absent from docs/astryx-surface-file-inventory.pathsapps/desktop/src/renderer/features/goals/ui/goal-dialog.tsx, plus services-context.tsx and goal-host.tsx in the same directory — while the pre-move apps/desktop/src/renderer/goal-dialog.tsx is still listed. docs/astryx-surface-file-inventory.md is likewise out of sync with the generator's output.

Fix is mechanical: run npm run astryx:surface-inventory:write and commit both regenerated files. Nothing about the runtime behaviour is at fault here — the gate is doing its job, the branch just moved surfaces without re-running it.


On the refactor itself: no P0–P3.

For a pure extraction the question is only ever whether behaviour changed under cover of moving things, so that is where I spent the time. use-goal-controller.ts ends up holding the active goal, session-switch clearing, the late-read sequence and disposed guards, the goal-change subscription, per-session control dedupe, and the dialog's session snapshot — and it stays a projection of Host events rather than becoming a second authority, which is the failure mode this kind of slice usually introduces. create-goal-services.ts is the single Desktop bridge adapter, and AppShell only reaches Goals through GoalHost and the controller's public API.

The deletion side checks out too, which is the part that makes an extraction actually reduce entropy rather than add a layer: use-session-goal.ts is gone, the old dialog's direct window.maka dependency is gone, and AppShell no longer carries goal control state. A repo-wide search finds no useSessionGoal and no surviving production entry to the old dialog path.

Verified: Goals focused tests 12/12; controller, model, adapter, and feature-boundary suites all pass; @maka/desktop builds and typechecks across renderer, preload, main, and Storybook; Biome clean on changed files. The full desktop main suite ran 1190 pass / 0 fail with 8 cancelled — the cancellations sit in pre-existing MCP OAuth pending tests and are not attributable to this branch, so I'm reporting it that way rather than calling the suite green.

Regenerate the inventory and this is ready for another look.

@chihumyum

Copy link
Copy Markdown
ContributorAuthor

Fixed in f9554a9af by regenerating both checked-in Astryx surface inventory files.

Local verification:

  • npm run astryx:surface-inventory:write
  • npm run astryx:surface-inventory — 203 files, 1 exclusion
  • git diff --check

The new CI run is currently action_required with no jobs, so it needs maintainer approval before GitHub will execute the workflow.

@Astro-HanAstro-Han 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.

Two independent lines on f9554a9af129f6bede8b7975c0a4bb9a2a0cc3be, from different models, neither able to see the other's conclusion. Both came back with nothing at P0–P3, and — more importantly for a refactor — both answered the question that actually matters here.

A refactor's failure mode isn't "didn't fix it", it's "changed behaviour in transit", and in a diff a relocation and a rewrite look identical. So both lines were asked to split -263 into what genuinely disappeared versus what is just move noise.

What disappeared (~150 lines):

  • use-session-goal.ts is gone as a file, and its authority — goal state, the change subscription, session-switch semantics — moved wholesale to the controller rather than being copied.
  • The indicator construction inlined in app-shell.tsx (~55 lines), plus runGoalControl, pendingGoalControlSessionIdsRef and goalDialogSessionId, all leave the shell. AppShell keeps two lines of wiring.

That is one ownership leaving one place and arriving in another, not a copy. Move noise (~110 lines) is the dialog relocating into features/goals/ui/ and isLiveGoal moving to model/live-goal.ts.

The controller being larger than the hook it replaces is explained rather than hand-waved: it absorbed the behaviour that used to live inline in the shell, so the two are not comparable line-for-line.

Semantic parity was checked point by point rather than asserted: subscription filtering (including the broadcast undefined case), session-switch ordering, the sequence-number race guard, control re-entrancy, dialog keying against the wrong session, and the GoalState type resolving to the same underlying type through a different path. One behavioural difference was found and it is an improvement: the indicator moves from an IIFE rebuilding a closure every render to a memo keyed on the active goal, so the reference is now stable.

No second implementation survives. We verified this at the gate independently: window.maka.goal has zero hits in production code on this head, use-session-goal.ts no longer exists in the tree, and the only remaining references to the old surface are stories pointing at the deliberate testing export.

One thing worth recording without grading it: the adapter's subscribeChanges collapses events down to sessionId | undefined, discarding metadata beyond the reason. That is the right boundary for what goals need today, but if goals ever need another session reason — a removal, say — the adapter is where that has to be reopened. Noting it as a known edge of the seam, not as a defect.

CI is terminal green on this head (test: completed / success), which is the head this approval is bound to.

Approving.

@chihumyum
chihumyumforce-pushed the refactor/goals-feature-slice branch 2 times, most recently from d38904b to cfce73eCompareAugust 23, 2026 07:53
@chihumyum

Copy link
Copy Markdown
ContributorAuthor

Rebased onto current upstream/main (729839ed8) and resolved the GoalDialog conflict in cfce73ee9.

The resolution preserves the newly merged reconnect reconciliation behavior: Goal arm outcomes still fence stale results, lock reconciled states, and prevent duplicate submission, while the bridge call remains behind the Goals service port. The reconciliation model and its tests now live inside the Goals feature boundary.

Verified after the final rebase:

  • npm run lint
  • npm run format:check
  • npm run astryx:surface-inventory
  • npm run build
  • npm run typecheck
  • npm --workspace @maka/desktop run test:dist — 1255 passed
  • npx knip --workspace apps/desktop

GitHub now reports the PR as mergeable. The new fork CI run is action_required and needs maintainer approval before jobs start.

Move Goal state, subscriptions, controls, dialog ownership, and view-model assembly behind a renderer feature boundary and Desktop adapter. Add fake services, lifecycle tests, and architecture guardrails without changing the preload contract or user behavior.
Refs apache#3439
Generated-by: Codex
Regenerate the checked-in surface inventory after moving the Goal dialog and adding the Goals feature service and host surfaces.
Refs apache#3439
Generated-by: Codex
@chihumyum
chihumyumforce-pushed the refactor/goals-feature-slice branch from cfce73e to 0ed2c53CompareAugust 23, 2026 09:10
@chihumyum

Copy link
Copy Markdown
ContributorAuthor

Rechecked against the latest upstream/main (047567c4b). Main had advanced by five commits and the PR had become DIRTY solely because the generated Astryx inventory conflicted again.

Rebased and regenerated the inventory in 0ed2c53c4. Verification:

  • npm run astryx:surface-inventory — 204 files, 1 exclusion
  • git diff --check upstream/main...HEAD
  • merge-tree probe against current main — clean

GitHub no longer reports a merge conflict. The current head workflow is run 32630272181, which is action_required with no jobs and needs maintainer approval to execute.

@jackwenerjackwener left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Incremental technical review of exact head 0ed2c53c4bddef7c97434ad111541ea7111c33d8, executed by the Kabi review agent on behalf of @WAWQAQ under the standing Kabi review/publisher authorization.

GO — no live P0–P3. APPROVE; no merge action.

This review covers the rebase-only delta that incorporated the newly merged Goal arm reconciliation contract. Comparing the pre-extraction implementation at current base 047567c4b with the moved feature code shows semantic parity: only armed closes the dialog; matching/different/null reconciled results and reconciliation_unavailable all lock the form, show the authoritative outcome, and prevent duplicate submission. interpretGoalArmOutcome is unchanged apart from its relative import.

The bridge authority remains singular: main.tsx creates one Desktop Goal service adapter, its bridge.goal.arm result is returned through the service and controller as Promise<GoalArmOutcome>, and GoalHost injects that exact function into GoalDialog. The Goals feature contains no window.maka.goal access and the old direct production path is absent.

Verification: focused Goals suites 18/18; Desktop main 1273/1274 on the first full run, with the sole unrelated shell-env timeout fixture passing 12/12 when rerun alone; Desktop preload/main/renderer/Storybook typechecks passed. Three discussion endpoints were reconciled after provisional sealing: two old-head reviews, no inline comments, and three author status comments; no live P0–P2.

Fresh action gate: OPEN, non-draft, MERGEABLE/CLEAN; exact-head hosted test is completed/success. This Agent-executed approval does not claim to satisfy any separate unresolved human-review wording.

@Astro-Han
Astro-Han merged commit 42cc510 into apache:mainAug 23, 2026
1 of 2 checks passed
@chihumyum
chihumyum deleted the refactor/goals-feature-slice branch August 23, 2026 16:19
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.

3 participants

@chihumyum@jackwener@Astro-Han
, '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(desktop): extract goals as a feature slice - #3531

Merged
Astro-Han merged 2 commits into
apache:mainfrom
chihumyum:refactor/goals-feature-slice
Aug 23, 2026
Merged

refactor(desktop): extract goals as a feature slice#3531
Astro-Han merged 2 commits into
apache:mainfrom
chihumyum:refactor/goals-feature-slice

Conversation

@chihumyum

Copy link
Copy Markdown
Contributor

Summary

  • Move Goal read state, subscriptions, controls, dialog ownership, and indicator assembly behind a renderer feature boundary.
  • Isolate Desktop bridge access behind a narrow GoalServices adapter and provider; keep AppShell limited to Session context plus host, commands, and selectors.
  • Add fake services and focused lifecycle, adapter, model, and architecture-boundary coverage.

Refs #3439

Verification

  • npm run lint
  • npm run format:check
  • npm run build
  • npm run typecheck
  • npm --workspace @maka/desktop run test:dist — 1198 passed
  • npx knip --workspace apps/desktop
  • npx knip --workspace packages/ui
  • npm --workspace @maka/desktop run build-storybook
  • npm --workspace @maka/desktop run smoke:storybook — 166 stories passed
  • npx playwright test --config e2e/playwright.config.ts from apps/desktop — 50 passed, 1 skipped

No screenshots are included because this changes no Goal copy, CSS, layout, IPC contract, or user-visible behavior.

Review focus

  • Session-switch fencing for stale Goal reads.
  • Goal-change event filtering and subscription disposal.
  • Dialog ownership of the Session captured when it opens.
  • Per-Session pause/resume re-entry protection.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex assisted with the feature extraction, implementation, tests, and verification.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@chihumyum
chihumyum marked this pull request as ready for review August 22, 2026 19:15

@Astro-HanAstro-Han 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.

Reviewed at head b29e3c4e. One blocking item, and it is a generated file rather than the code — the extraction itself came through clean.

[P1] The Astryx surface inventory wasn't regenerated, and that's what's failing test.

test is FAILURE on this exact head (job 97083453961), and I reproduced it locally: npm run astryx:surface-inventory exits 1 on this branch, consistently. Three moved files are on disk but absent from docs/astryx-surface-file-inventory.pathsapps/desktop/src/renderer/features/goals/ui/goal-dialog.tsx, plus services-context.tsx and goal-host.tsx in the same directory — while the pre-move apps/desktop/src/renderer/goal-dialog.tsx is still listed. docs/astryx-surface-file-inventory.md is likewise out of sync with the generator's output.

Fix is mechanical: run npm run astryx:surface-inventory:write and commit both regenerated files. Nothing about the runtime behaviour is at fault here — the gate is doing its job, the branch just moved surfaces without re-running it.


On the refactor itself: no P0–P3.

For a pure extraction the question is only ever whether behaviour changed under cover of moving things, so that is where I spent the time. use-goal-controller.ts ends up holding the active goal, session-switch clearing, the late-read sequence and disposed guards, the goal-change subscription, per-session control dedupe, and the dialog's session snapshot — and it stays a projection of Host events rather than becoming a second authority, which is the failure mode this kind of slice usually introduces. create-goal-services.ts is the single Desktop bridge adapter, and AppShell only reaches Goals through GoalHost and the controller's public API.

The deletion side checks out too, which is the part that makes an extraction actually reduce entropy rather than add a layer: use-session-goal.ts is gone, the old dialog's direct window.maka dependency is gone, and AppShell no longer carries goal control state. A repo-wide search finds no useSessionGoal and no surviving production entry to the old dialog path.

Verified: Goals focused tests 12/12; controller, model, adapter, and feature-boundary suites all pass; @maka/desktop builds and typechecks across renderer, preload, main, and Storybook; Biome clean on changed files. The full desktop main suite ran 1190 pass / 0 fail with 8 cancelled — the cancellations sit in pre-existing MCP OAuth pending tests and are not attributable to this branch, so I'm reporting it that way rather than calling the suite green.

Regenerate the inventory and this is ready for another look.

@chihumyum

Copy link
Copy Markdown
ContributorAuthor

Fixed in f9554a9af by regenerating both checked-in Astryx surface inventory files.

Local verification:

  • npm run astryx:surface-inventory:write
  • npm run astryx:surface-inventory — 203 files, 1 exclusion
  • git diff --check

The new CI run is currently action_required with no jobs, so it needs maintainer approval before GitHub will execute the workflow.

@Astro-HanAstro-Han 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.

Two independent lines on f9554a9af129f6bede8b7975c0a4bb9a2a0cc3be, from different models, neither able to see the other's conclusion. Both came back with nothing at P0–P3, and — more importantly for a refactor — both answered the question that actually matters here.

A refactor's failure mode isn't "didn't fix it", it's "changed behaviour in transit", and in a diff a relocation and a rewrite look identical. So both lines were asked to split -263 into what genuinely disappeared versus what is just move noise.

What disappeared (~150 lines):

  • use-session-goal.ts is gone as a file, and its authority — goal state, the change subscription, session-switch semantics — moved wholesale to the controller rather than being copied.
  • The indicator construction inlined in app-shell.tsx (~55 lines), plus runGoalControl, pendingGoalControlSessionIdsRef and goalDialogSessionId, all leave the shell. AppShell keeps two lines of wiring.

That is one ownership leaving one place and arriving in another, not a copy. Move noise (~110 lines) is the dialog relocating into features/goals/ui/ and isLiveGoal moving to model/live-goal.ts.

The controller being larger than the hook it replaces is explained rather than hand-waved: it absorbed the behaviour that used to live inline in the shell, so the two are not comparable line-for-line.

Semantic parity was checked point by point rather than asserted: subscription filtering (including the broadcast undefined case), session-switch ordering, the sequence-number race guard, control re-entrancy, dialog keying against the wrong session, and the GoalState type resolving to the same underlying type through a different path. One behavioural difference was found and it is an improvement: the indicator moves from an IIFE rebuilding a closure every render to a memo keyed on the active goal, so the reference is now stable.

No second implementation survives. We verified this at the gate independently: window.maka.goal has zero hits in production code on this head, use-session-goal.ts no longer exists in the tree, and the only remaining references to the old surface are stories pointing at the deliberate testing export.

One thing worth recording without grading it: the adapter's subscribeChanges collapses events down to sessionId | undefined, discarding metadata beyond the reason. That is the right boundary for what goals need today, but if goals ever need another session reason — a removal, say — the adapter is where that has to be reopened. Noting it as a known edge of the seam, not as a defect.

CI is terminal green on this head (test: completed / success), which is the head this approval is bound to.

Approving.

@chihumyum
chihumyumforce-pushed the refactor/goals-feature-slice branch 2 times, most recently from d38904b to cfce73eCompareAugust 23, 2026 07:53
@chihumyum

Copy link
Copy Markdown
ContributorAuthor

Rebased onto current upstream/main (729839ed8) and resolved the GoalDialog conflict in cfce73ee9.

The resolution preserves the newly merged reconnect reconciliation behavior: Goal arm outcomes still fence stale results, lock reconciled states, and prevent duplicate submission, while the bridge call remains behind the Goals service port. The reconciliation model and its tests now live inside the Goals feature boundary.

Verified after the final rebase:

  • npm run lint
  • npm run format:check
  • npm run astryx:surface-inventory
  • npm run build
  • npm run typecheck
  • npm --workspace @maka/desktop run test:dist — 1255 passed
  • npx knip --workspace apps/desktop

GitHub now reports the PR as mergeable. The new fork CI run is action_required and needs maintainer approval before jobs start.

Move Goal state, subscriptions, controls, dialog ownership, and view-model assembly behind a renderer feature boundary and Desktop adapter. Add fake services, lifecycle tests, and architecture guardrails without changing the preload contract or user behavior.
Refs apache#3439
Generated-by: Codex
Regenerate the checked-in surface inventory after moving the Goal dialog and adding the Goals feature service and host surfaces.
Refs apache#3439
Generated-by: Codex
@chihumyum
chihumyumforce-pushed the refactor/goals-feature-slice branch from cfce73e to 0ed2c53CompareAugust 23, 2026 09:10
@chihumyum

Copy link
Copy Markdown
ContributorAuthor

Rechecked against the latest upstream/main (047567c4b). Main had advanced by five commits and the PR had become DIRTY solely because the generated Astryx inventory conflicted again.

Rebased and regenerated the inventory in 0ed2c53c4. Verification:

  • npm run astryx:surface-inventory — 204 files, 1 exclusion
  • git diff --check upstream/main...HEAD
  • merge-tree probe against current main — clean

GitHub no longer reports a merge conflict. The current head workflow is run 32630272181, which is action_required with no jobs and needs maintainer approval to execute.

@jackwenerjackwener left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Incremental technical review of exact head 0ed2c53c4bddef7c97434ad111541ea7111c33d8, executed by the Kabi review agent on behalf of @WAWQAQ under the standing Kabi review/publisher authorization.

GO — no live P0–P3. APPROVE; no merge action.

This review covers the rebase-only delta that incorporated the newly merged Goal arm reconciliation contract. Comparing the pre-extraction implementation at current base 047567c4b with the moved feature code shows semantic parity: only armed closes the dialog; matching/different/null reconciled results and reconciliation_unavailable all lock the form, show the authoritative outcome, and prevent duplicate submission. interpretGoalArmOutcome is unchanged apart from its relative import.

The bridge authority remains singular: main.tsx creates one Desktop Goal service adapter, its bridge.goal.arm result is returned through the service and controller as Promise<GoalArmOutcome>, and GoalHost injects that exact function into GoalDialog. The Goals feature contains no window.maka.goal access and the old direct production path is absent.

Verification: focused Goals suites 18/18; Desktop main 1273/1274 on the first full run, with the sole unrelated shell-env timeout fixture passing 12/12 when rerun alone; Desktop preload/main/renderer/Storybook typechecks passed. Three discussion endpoints were reconciled after provisional sealing: two old-head reviews, no inline comments, and three author status comments; no live P0–P2.

Fresh action gate: OPEN, non-draft, MERGEABLE/CLEAN; exact-head hosted test is completed/success. This Agent-executed approval does not claim to satisfy any separate unresolved human-review wording.

@Astro-Han
Astro-Han merged commit 42cc510 into apache:mainAug 23, 2026
1 of 2 checks passed
@chihumyum
chihumyum deleted the refactor/goals-feature-slice branch August 23, 2026 16:19
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.

3 participants

@chihumyum@jackwener@Astro-Han