refactor: fix and tighten mechanical lint rules

- no-useless-escape: drop needless backslashes in character classes and
  URL/path regexes (gh-cli, store, task, modelFilter, useFileMention,
  RoutineEditor, ScheduleForm).
- no-case-declarations: wrap case bodies in ProjectOverview and
  SettingsModal with block scopes.
- prefer-const: convert a never-reassigned slug binding in agent-import;
  annotate legitimate forward-declared let bindings in dashboard.ts that
  callbacks close over before assignment.
- no-fallthrough: add missing break after settings-subcommand error.
- no-empty-interface/no-empty-object-type: convert ProjectManifest from
  empty interface extension to a type alias.
- no-unused-expressions: replace `x && x.method()` short-circuits in
  TerminalModal with optional chaining.

Then ratchet these rules from warn → error so regressions are blocked.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-04-23 17:54:18 -07:00
parent 3f9a65fd56
commit 94e752d606
15 changed files with 35 additions and 35 deletions

View File

@@ -108,12 +108,13 @@ export function ProjectOverview({
case "name":
comparison = a.project.name.localeCompare(b.project.name);
break;
case "activity":
case "activity": {
const aTime = a.project.lastActivityAt || a.health?.lastActivityAt || a.project.updatedAt;
const bTime = b.project.lastActivityAt || b.health?.lastActivityAt || b.project.updatedAt;
comparison = new Date(bTime).getTime() - new Date(aTime).getTime();
break;
case "status":
}
case "status": {
const statusOrder: Record<ProjectStatus, number> = {
errored: 0,
initializing: 1,
@@ -122,6 +123,7 @@ export function ProjectOverview({
};
comparison = statusOrder[a.project.status] - statusOrder[b.project.status];
break;
}
}
return sortDirection === "asc" ? comparison : -comparison;

View File

@@ -52,7 +52,7 @@ function isLikelyCron(expr: string): boolean {
const parts = expr.trim().split(/\s+/);
if (parts.length !== 5) return false;
// Each field should contain digits, *, /, -, or ,
return parts.every((p) => /^[\d*,/\-]+$/.test(p));
return parts.every((p) => /^[\d*,/-]+$/.test(p));
}
/**

View File

@@ -43,7 +43,7 @@ function isLikelyCron(expr: string): boolean {
const parts = expr.trim().split(/\s+/);
if (parts.length !== 5) return false;
// Each field should contain digits, *, /, -, or ,
return parts.every((p) => /^[\d*,/\-]+$/.test(p));
return parts.every((p) => /^[\d*,/-]+$/.test(p));
}
/**

View File

@@ -3024,7 +3024,7 @@ export function SettingsModal({
);
case "pi-extensions":
return <PiExtensionsManager addToast={addToast} projectId={projectId} />;
case "authentication":
case "authentication": {
// CLI-backed providers (currently just claude-cli) render their own
// compact card with Enable/Disable + Test actions — bypassing the
// OAuth/API-key rendering below. Filter them out of the standard
@@ -3231,6 +3231,7 @@ export function SettingsModal({
)}
</>
);
}
}
};

View File

@@ -610,7 +610,7 @@ export function TerminalModal({ isOpen, onClose, initialCommand, projectId }: Te
if (xtermRef.current) {
const currentSize = xtermRef.current.options.fontSize || 14;
xtermRef.current.options.fontSize = Math.min(currentSize + 1, 32);
fitAddonRef.current && (fitAddonRef.current as InstanceType<typeof FitAddon>).fit();
(fitAddonRef.current as InstanceType<typeof FitAddon> | null)?.fit();
}
return;
}
@@ -621,7 +621,7 @@ export function TerminalModal({ isOpen, onClose, initialCommand, projectId }: Te
if (xtermRef.current) {
const currentSize = xtermRef.current.options.fontSize || 14;
xtermRef.current.options.fontSize = Math.max(currentSize - 1, 8);
fitAddonRef.current && (fitAddonRef.current as InstanceType<typeof FitAddon>).fit();
(fitAddonRef.current as InstanceType<typeof FitAddon> | null)?.fit();
}
return;
}
@@ -631,7 +631,7 @@ export function TerminalModal({ isOpen, onClose, initialCommand, projectId }: Te
e.preventDefault();
if (xtermRef.current) {
xtermRef.current.options.fontSize = 14;
fitAddonRef.current && (fitAddonRef.current as InstanceType<typeof FitAddon>).fit();
(fitAddonRef.current as InstanceType<typeof FitAddon> | null)?.fit();
}
return;
}

View File

@@ -71,7 +71,7 @@ export function useFileMention(options: UseFileMentionOptions = {}): UseFileMent
}
// Path characters: alphanumeric, /, _, -, .
const isPathChar = (char: string): boolean => /[a-zA-Z0-9/_.\-]/.test(char);
const isPathChar = (char: string): boolean => /[a-zA-Z0-9/_.-]/.test(char);
// Find # by scanning backwards from cursor
// Skip over path chars (they're part of the mention text)

View File

@@ -8,7 +8,7 @@ import type { ModelInfo } from "../api";
* Preserves spaces (which serve as field/word boundaries) and alphanumeric chars.
*/
function normalize(s: string): string {
return s.toLowerCase().replace(/[-_.\/]/g, "");
return s.toLowerCase().replace(/[-_./]/g, "");
}
/**