Enable strict typed ESLint rules

This commit is contained in:
murashit 2026-06-25 08:39:57 +09:00
parent 498632cd7d
commit 6fb9e60dea
7 changed files with 14 additions and 17 deletions

View file

@ -14,7 +14,7 @@ Use this as the normal edit loop. `npm run format` applies Biome formatting and
Use focused scripts for tight loops: `npm run typecheck`, `npm run test`, `npm run build`, or the targeted `npm run check:*` scripts. CI and release preflight run the same `npm run check` command as local development.
Biome owns formatting, import organization, general JavaScript/TypeScript/JSON/CSS linting, GritQL source-shape plugins, GritQL import-boundary restrictions, and GritQL CSS source policy. Biome warnings fail `npm run check`; info diagnostics stay advisory, including accessibility while Obsidian-specific UI semantics are reviewed rule by rule. The CSS usage script still checks dead authored classes. ESLint remains for typed unsafe-any checks, Obsidian plugin policy, and Codex Panel responsibility-boundary rules that need TypeScript type information.
Biome owns formatting, import organization, general JavaScript/TypeScript/JSON/CSS linting, GritQL source-shape plugins, GritQL import-boundary restrictions, and GritQL CSS source policy. Biome warnings fail `npm run check`; info diagnostics stay advisory, including accessibility while Obsidian-specific UI semantics are reviewed rule by rule. The CSS usage script still checks dead authored classes. ESLint remains for typed strict TypeScript checks, Obsidian plugin policy, and Codex Panel responsibility-boundary rules that need TypeScript type information. The typed strict preset is used with `@typescript-eslint/require-await` disabled because Obsidian and panel-owned async-shaped boundaries sometimes return already-complete work.
## Generated and Loaded Files

View file

@ -4,12 +4,7 @@ import ts from "typescript";
import tseslint from "typescript-eslint";
const sourceTypeScriptFiles = ["src/**/*.{ts,tsx}"];
const unsafeAnyTypeScriptRules = {
"@typescript-eslint/no-unsafe-argument": "error",
"@typescript-eslint/no-unsafe-assignment": "error",
"@typescript-eslint/no-unsafe-call": "error",
"@typescript-eslint/no-unsafe-member-access": "error",
};
const strictTypeCheckedTypeScriptRules = Object.assign({}, ...tseslint.configs.strictTypeChecked.map((config) => config.rules ?? {}));
const codexPanelRuleIds = {
chatStateDirectMutation: "codex-panel/no-chat-state-direct-mutation",
imperativeDom: "codex-panel/no-imperative-dom",
@ -133,7 +128,10 @@ export default defineConfig([
setTimeout: "readonly",
},
},
rules: unsafeAnyTypeScriptRules,
rules: {
...strictTypeCheckedTypeScriptRules,
"@typescript-eslint/require-await": "off",
},
},
{
files: sourceTypeScriptFiles,

View file

@ -7,8 +7,7 @@ export async function withShortLivedAppServerClient<T>(
operation: (client: AppServerClient) => Promise<T>,
options: AppServerClientAccessOptions = {},
): Promise<T> {
let client!: AppServerClient;
client = new AppServerClient(codexPath, cwd, {
const client = new AppServerClient(codexPath, cwd, {
onNotification: () => undefined,
onServerRequest: (request) => {
client.rejectServerRequest(

View file

@ -68,7 +68,6 @@ export async function runEphemeralStructuredTurn(options: RunEphemeralStructured
throwIfAborted(options.signal, options.abortMessage);
let state = createEphemeralStructuredTurnState();
const timers = options.timers ?? DEFAULT_EPHEMERAL_STRUCTURED_TURN_TIMERS;
let timeout: ReturnType<Window["setTimeout"]> | undefined;
let handleNotification: (notification: ServerNotification) => void = () => undefined;
let operationAbortError: Error | null = null;
const operationAbort = new AbortController();
@ -84,7 +83,7 @@ export async function runEphemeralStructuredTurn(options: RunEphemeralStructured
() => operationAbortError ?? ephemeralStructuredTurnAbortError(options.abortMessage),
);
timeout = timers.setTimeout(() => {
const timeout = timers.setTimeout(() => {
if (state.lifecycle.kind === "completed") return;
state = completeEphemeralStructuredTurnState(state);
abortOperation(new Error(options.timedOutMessage));
@ -99,9 +98,8 @@ export async function runEphemeralStructuredTurn(options: RunEphemeralStructured
};
});
let client!: EphemeralStructuredTurnRuntimeCapableClient;
const clientFactory = options.clientFactory ?? ((codexPath, cwd, handlers) => new AppServerClient(codexPath, cwd, handlers));
client = clientFactory(options.codexPath, options.cwd, {
const client = clientFactory(options.codexPath, options.cwd, {
onNotification: (notification) => {
handleNotification(notification);
},

View file

@ -32,7 +32,7 @@ export async function exportArchivedThreadMarkdown(
now = new Date(),
): Promise<ArchiveExportResult> {
const context = templateContext(thread, now);
const normalizePath = destination.normalizePath;
const normalizePath = (path: string): string => destination.normalizePath(path);
const folder = folderPathFromTemplate(settings.archiveExportFolderTemplate, context, normalizePath);
const filename = filenameFromTemplate(settings.archiveExportFilenameTemplate, context, normalizePath);
await ensureFolder(destination, folder);

View file

@ -468,7 +468,8 @@ export function shouldSuppressLifecycleItem(item: TurnItem): boolean {
return item.type === "agentMessage" || item.type === "userMessage";
}
function ignoredUnsupportedTurnItem(_item: never): null {
function ignoredUnsupportedTurnItem(item: never): null {
void item;
return null;
}

View file

@ -199,7 +199,8 @@ function autoReviewToggleMessage(state: AutoReviewState): string {
return state === "enabled" ? "Auto-review on for subsequent turns." : "Auto-review off for subsequent turns.";
}
function collaborationModeWarningMessage(_warning: NonNullable<PendingRuntimeSettingsPatch["collaborationModeWarning"]>): string {
function collaborationModeWarningMessage(warning: NonNullable<PendingRuntimeSettingsPatch["collaborationModeWarning"]>): string {
void warning;
return "No effective model is available. Sending without a mode override.";
}