Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1134,6 +1134,13 @@ jobs:
- name: Type check
run: pnpm typecheck

# Still advisory, and the reason is measured rather than habitual: this
# step runs `eslint src --max-warnings 0`, and desktop currently reports
# 0 errors but **4 `react-hooks/exhaustive-deps` warnings** (missing `t` /
# `tApp` in useMemo dependency arrays). Fixing those means changing
# memoization dependencies, which is a behaviour change, not a lint
# cleanup — so it needs its own reviewed slice. Removing
# continue-on-error before that would hard-fail every desktop PR (#2274).
- name: Lint
continue-on-error: true
run: pnpm lint --max-warnings 0
Expand Down Expand Up @@ -1252,8 +1259,12 @@ jobs:
- name: Install
run: pnpm install --frozen-lockfile

# #2274: was `continue-on-error: true`, i.e. structurally incapable of
# failing — which is how six `no-explicit-any` errors lived on master
# unnoticed (all the same hand-copied `options?: any` translate signature).
# They are fixed in this PR, so the step is a real gate now: web's lint
# script is `eslint src --max-warnings 0` and reports 0 problems.
- name: Lint Web
continue-on-error: true
run: pnpm lint

- name: Build Web
Expand Down Expand Up @@ -1319,8 +1330,10 @@ jobs:
- name: Type check (mobile)
run: pnpm --filter agenthub-mobile-rn typecheck

# #2274: was `continue-on-error: true` (advisory). The exact CI command
# reports 0 errors / 1 react-hooks warning, and the mobile lint script does
# not pass --max-warnings, so this is a real gate now.
- name: Lint (mobile rules)
continue-on-error: true
run: pnpm --filter agenthub-mobile-rn lint

# ── Hardened: Test with coverage reporting ──
Expand Down
21 changes: 18 additions & 3 deletions app/web/src/api/agentQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ export function mapHubAgentProfileToAgentInfo(profile: AgentProfile): AgentInfo
};
}

export function agentConfigToCreateAgentProfileRequest(agent: AgentConfig, t?: (key: string, options?: any) => string): CreateAgentProfileRequest {
export function agentConfigToCreateAgentProfileRequest(agent: AgentConfig, t?: (key: string) => string): CreateAgentProfileRequest {
const model = splitModelLabel(agent.model);
const description = persistableAgentDescription(agent.role);
const reasoningEffort = reasoningEffortFromMode(agent.mode);
Expand Down Expand Up @@ -265,7 +265,7 @@ export function agentConfigToCreateAgentProfileRequest(agent: AgentConfig, t?: (
};
}

export function agentConfigToUpdateAgentProfileRequest(agent: AgentConfig, t?: (key: string, options?: any) => string): UpdateAgentProfileRequest {
export function agentConfigToUpdateAgentProfileRequest(agent: AgentConfig, t?: (key: string) => string): UpdateAgentProfileRequest {
const model = splitModelLabel(agent.model);
const description = persistableAgentDescription(agent.role);
const runtimeID = optionalRuntimeInput(agent.engine);
Expand Down Expand Up @@ -295,7 +295,22 @@ export function agentConfigToUpdateAgentProfileRequest(agent: AgentConfig, t?: (
};
}

export function createDefaultAgentProfileRequest(index: number, t?: (key: string, options?: any) => string): CreateAgentProfileRequest {
export function createDefaultAgentProfileRequest(
index: number,
// The only web mapper callback that actually interpolates — it calls
// t('agents.newDefault', { index }) — so it is the only one that keeps an
// options bag, and it is typed rather than `any` (which is what
// `eslint --max-warnings 0` in the web lint gate rejects).
//
// The other five web copies of this signature declared the same parameter and
// never passed anything, so they dropped it. Do not "re-symmetrise" this with
// desktop: desktop's six copies keep `options?: any` on purpose, because their
// callers hand in i18next's own `TFunction`, which is only assignable to a
// callback whose options parameter is `any` — narrowing it there fails
// typecheck with TS2345 at App.tsx:265 (measured, not guessed). desktop's
// eslint config does not enable no-explicit-any, so nothing flags it.
t?: (key: string, options?: Record<string, unknown>) => string,
): CreateAgentProfileRequest {
return {
name: t?.('agents.newDefault', { index }) ?? `新 Agent ${index}`,
runtime_id: 'codex',
Expand Down
2 changes: 1 addition & 1 deletion app/web/src/platform/webPlatformMapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export function resolveWebWorkbenchAgents(
return mapped.length > 0 ? mapped : webAgents;
}

type WebTranslate = (key: string, options?: any) => string;
type WebTranslate = (key: string) => string;

export function hubSessionToWorkbenchConversation(session: Session, t?: WebTranslate): WorkbenchConversation | null {
const id = session.id ?? session.session_id;
Expand Down
2 changes: 1 addition & 1 deletion app/web/src/platform/webWorkbenchProjects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export interface ParsedProjectThreadMessageContent {
} | undefined;
}

type WebTranslate = (key: string, options?: any) => string;
type WebTranslate = (key: string) => string;

export function workspaceProjectToProjectInfo(
project: WorkspaceProject,
Expand Down
2 changes: 1 addition & 1 deletion app/web/src/platform/webWorkbenchProjectsPort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { projectDraftToHubRequest } from './webWorkbenchProjects';
* (#1546). Wraps the HubClient transport; the shared UI only ever sees the
* narrow `WorkbenchProjectsPort` contract.
*/
type WebTranslate = (key: string, options?: any) => string;
type WebTranslate = (key: string) => string;

export function createWebWorkbenchProjectsPort(t?: WebTranslate): WorkbenchProjectsPort {
const hubClient = createHubClient({ getToken: getAccessToken });
Expand Down
22 changes: 2 additions & 20 deletions scripts/verify/quality-debt-baseline.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,12 @@
{
"location": "frontend-desktop: Lint",
"kind": "continue-on-error",
"reason": "desktop eslint advisory while Wave 9-10 design-system refactor settles (#1575)",
"issue": 1575,
"reason": "desktop eslint advisory for a measured reason, not a habitual one (#2278): the CI step runs `pnpm lint --max-warnings 0` and desktop currently reports 0 errors but 4 `react-hooks/exhaustive-deps` warnings (useMemo dependency arrays missing `t` / `tApp` in useDesktopWorkbenchModel.ts) => exit 1. Fixing them changes memoization dependencies, i.e. a behaviour change that needs its own reviewed slice; flipping the gate before that would hard-fail every desktop PR. The two sibling soft gates (frontend-web Lint Web, frontend-mobile Lint (mobile rules)) were retired by #2278 and are tracked in #2251.",
"issue": 2251,
"owner": "desktop-owners",
"introduced_at": "2026-08-11",
"review_by": "2026-10-01"
},
{
"location": "frontend-web: Lint Web",
"kind": "continue-on-error",
"reason": "web eslint advisory while Wave 9-10 design-system refactor settles (#1581)",
"issue": 1581,
"owner": "web-owners",
"introduced_at": "2026-08-11",
"review_by": "2026-10-01"
},
{
"location": "frontend-mobile: Lint (mobile rules)",
"kind": "continue-on-error",
"reason": "mobile eslint advisory while Wave 9-10 design-system refactor settles (#1575)",
"issue": 1573,
"owner": "mobile-owners",
"introduced_at": "2026-08-11",
"review_by": "2026-10-01"
},
{
"location": "validate: Verify i18n callsites ratchet (#1612)",
"kind": "continue-on-error",
Expand Down
Loading