mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-30 16:20:35 +02:00
chore(desktop): add navigation boundary lint rule (MUL-4741 Phase 2 prereq)
The tab Coordinator protocol requires that application code never navigates directly (invariant 1: a Router location change without a Coordinator token is a protocol error). Enforce it statically: - renderer app code may not import useNavigate/Navigate from react-router-dom nor call router.navigate; src/platform is exempt - the five known legacy sites (the RFC §8.1 migration checklist, cross-validated: the rule fires on exactly those and nothing else) carry inline eslint-disable directives tagged MUL-4741 — the Phase 2 migration removes them one by one, and this rule holding with zero disables is the machine check that the migration is complete Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -41,4 +41,39 @@ export default [
|
||||
"no-restricted-syntax": "off",
|
||||
},
|
||||
},
|
||||
// Navigation boundary (MUL-4741): the tab Coordinator must be the only
|
||||
// navigation initiator — a Router location change without a Coordinator
|
||||
// token is a protocol error. Application code must not navigate directly;
|
||||
// it goes through the navigation adapter / Coordinator in src/platform.
|
||||
// Remaining legacy sites carry an inline eslint-disable tagged MUL-4741;
|
||||
// the Phase 2 migration removes them one by one, and this rule holding
|
||||
// with zero disables is the machine check that the migration is complete.
|
||||
{
|
||||
files: ["src/renderer/src/**/*.{ts,tsx}"],
|
||||
ignores: ["src/renderer/src/platform/**", "src/renderer/src/**/*.test.*"],
|
||||
rules: {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
paths: [
|
||||
{
|
||||
name: "react-router-dom",
|
||||
importNames: ["useNavigate", "Navigate"],
|
||||
message:
|
||||
"Direct navigation from application code breaks the Coordinator protocol (MUL-4741). Use the navigation adapter from src/platform instead.",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
selector:
|
||||
"CallExpression[callee.object.name='router'][callee.property.name='navigate']",
|
||||
message:
|
||||
"Direct router.navigate from application code breaks the Coordinator protocol (MUL-4741). Route it through the navigation adapter in src/platform.",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useMemo } from "react";
|
||||
// eslint-disable-next-line no-restricted-imports -- MUL-4741 Phase 2: error recovery moves to the Coordinator; remove with §8.1
|
||||
import { useLocation, useNavigate, useRouteError } from "react-router-dom";
|
||||
import { AlertTriangle, RotateCw, Send, X } from "lucide-react";
|
||||
import { Button } from "@multica/ui/components/ui/button";
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useEffect } from "react";
|
||||
// eslint-disable-next-line no-restricted-imports -- MUL-4741 Phase 2: workspace redirect + login bounce move to the Coordinator; remove with §8.1
|
||||
import { Outlet, useNavigate, useParams } from "react-router-dom";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { WorkspaceSlugProvider, paths } from "@multica/core/paths";
|
||||
|
||||
@@ -27,12 +27,14 @@ export function useTabHistory() {
|
||||
const goBack = useCallback(() => {
|
||||
if (!router || historyIndex <= 0) return;
|
||||
popDirectionHints.set(router, "back");
|
||||
// eslint-disable-next-line no-restricted-syntax -- MUL-4741 Phase 2: shell back/forward moves to the Coordinator (invariant 1); remove with §8.1
|
||||
router.navigate(-1);
|
||||
}, [router, historyIndex]);
|
||||
|
||||
const goForward = useCallback(() => {
|
||||
if (!router || historyIndex >= historyLength - 1) return;
|
||||
popDirectionHints.set(router, "forward");
|
||||
// eslint-disable-next-line no-restricted-syntax -- MUL-4741 Phase 2: shell back/forward moves to the Coordinator (invariant 1); remove with §8.1
|
||||
router.navigate(1);
|
||||
}, [router, historyIndex, historyLength]);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useEffect } from "react";
|
||||
import {
|
||||
createMemoryRouter,
|
||||
// eslint-disable-next-line no-restricted-imports -- MUL-4741 Phase 2: index redirect moves to the Coordinator; remove with §8.1
|
||||
Navigate,
|
||||
Outlet,
|
||||
useMatches,
|
||||
|
||||
Reference in New Issue
Block a user