GitHub check
256 KB of 597 KB loaded Download the full log (597 KB)
341 KB of earlier output not loaded
mentId &&
556 │ destinationProject.id === initialProjectId);
557 │ if (
558 │ !shareId ||
559 │ !draftKey ||
560 │ !destinationProject ||
561 │ !selectedProjectMatchesRoute ||
562 │ cancelledIncomingShareId === shareId
563 │ ) {
564 │ return;
565 │ }
566 │ const importKey = `${shareId}:${draftKey}`;
567 │ if (
568 │ startedShareImportKeyRef.current === importKey ||
569 │ cancellingShareImportKeyRef.current === importKey
570 │ ) {
571 │ return;
572 │ }
573 │
574 │ if (!incomingShare) {
575 │ if (isIncomingShareUnavailable && alertedUnavailableIncomingShareIdRef.current !== shareId) {
576 │ alertedUnavailableIncomingShareIdRef.current = shareId;
577 │ Dialog.alert(
578 │ "Shared content unavailable",
579 │ "The shared content is no longer in the inbox. You can continue editing this task draft.",
580 │ );
581 │ }
582 │ return;
583 │ }
584 │
585 │ if (
586 │ incomingShare.attachments.some((attachment) => attachment.type === "file") &&
587 │ selectedEnvironmentServerConfig === null
588 │ ) {
589 │ return;
590 │ }
591 │
592 │ if (alertedUnavailableIncomingShareIdRef.current === shareId) {
593 │ alertedUnavailableIncomingShareIdRef.current = null;
594 │ }
595 │ startedShareImportKeyRef.current = importKey;
596 │ const draftBackup =
597 │ shareImportDraftBackupRef.current.get(importKey) ?? getComposerDraftSnapshot(draftKey);
598 │ shareImportDraftBackupRef.current.set(importKey, draftBackup);
599 │ const importToken = Symbol(importKey);
600 │ let didReserveShare = false;
601 │ let didConsumeShare = false;
602 │ let needsDraftRestore = false;
603 │ activeShareImportTokenRef.current = importToken;
604 │ setImportingShareKey(importKey);
· ──────────┬─────────
· ╰── Avoid calling setState() directly within an effect
605 │ void (async () => {
╰────
help: Effects should synchronize React with external systems. Calling setState synchronously inside an effect starts another render and is usually unnecessary. Derive the value during render, initialize state directly, or update it from the event that caused the change. Use an effect only when synchronizing with an external system.
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/set-state-in-effect
⚠ react(exhaustive-effect-dependencies): Found extra effect dependencies
╭─[apps/mobile/src/features/threads/NewTaskDraftScreen.tsx:524:5]
523 │ props.initialProjectRef,
524 │ props.incomingShareId,
· ──────────┬──────────
· ╰── Unnecessary dependency `props.incomingShareId`
525 │ props.pendingTaskId,
╰────
help: Extra dependencies can cause an effect to fire more often than it should, resulting in performance problems such as excessive renders and side effects
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/exhaustive-deps
⚠ react(exhaustive-effect-dependencies): Found missing/extra effect dependencies
╭─[apps/mobile/src/features/threads/NewTaskDraftScreen.tsx:543:5]
542 │ loadedBranchesProjectKeyRef.current = projectKey;
543 │ flow.loadBranches();
· ──┬─
· ╰── Missing dependency `flow`
544 │ }, [flow.loadBranches, selectedProject]);
· ────────┬────────
· ╰── Overly precise dependency `flow.loadBranches`, use `flow` instead
545 │
╰────
help: Missing dependencies can cause an effect to fire less often than it should. Extra dependencies can cause an effect to fire more often than it should, resulting in performance problems such as excessive renders and side effects
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/exhaustive-deps
⚠ react(exhaustive-effect-dependencies): Found extra effect dependencies
╭─[apps/mobile/src/features/threads/NewTaskDraftScreen.tsx:766:5]
765 │ flow.draftKey,
766 │ hasImportedIncomingShare,
· ────────────┬───────────
· ╰── Unnecessary dependency `hasImportedIncomingShare`
767 │ incomingShare,
768 │ isIncomingShareInboxLoading,
· ─────────────┬─────────────
· ╰── Unnecessary dependency `isIncomingShareInboxLoading`
769 │ isIncomingShareUnavailable,
770 │ props.incomingShareId,
771 │ props.initialProjectRef?.environmentId,
772 │ props.initialProjectRef?.projectId,
773 │ releaseShareReservation,
774 │ reserveShare,
775 │ selectedEnvironmentServerConfig,
776 │ selectedProject,
777 │ shareImportAttempt,
· ─────────┬────────
· ╰── Unnecessary dependency `shareImportAttempt`
778 │ ]);
╰────
help: Extra dependencies can cause an effect to fire more often than it should, resulting in performance problems such as excessive renders and side effects
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/exhaustive-deps
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/features/diffs/nativeReviewDiffSurface.ts:277:39]
276 │
277 │ ╭─▶ return createElement(RawNativeView, {
278 │ │ ...nativeProps,
279 │ │ refreshEnabled: props.onPullToRefresh !== undefined,
280 │ │ ref: nativeRef,
281 │ ├─▶ });
· ╰──── Passing a ref to a function may read its value during render
282 │ }
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ eslint(no-unused-vars): Variable 'layerTest' is declared but never used. Unused variables should start with a '_'.
╭─[apps/server/src/telemetry/AnalyticsService.ts:340:7]
339 │
340 │ const layerTest = AnalyticsService.layerTest;
· ────┬────
· ╰── 'layerTest' is declared here
╰────
help: Consider removing this declaration.
⚠ react(exhaustive-effect-dependencies): Found extra effect dependencies
╭─[apps/mobile/src/features/files/SourceFileSurface.tsx:257:7]
256 │ return () => cancelAnimationFrame(frame);
257 │ }, [props.path, targetIndex]);
· ─────┬────
· ╰── Unnecessary dependency `props.path`
258 │
╰────
help: Extra dependencies can cause an effect to fire more often than it should, resulting in performance problems such as excessive renders and side effects
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/exhaustive-deps
⚠ react(no-array-index-key): Usage of Array index in keys is not allowed
╭─[apps/mobile/src/features/files/SourceFileSurface.tsx:293:23]
292 │ <SourceText
293 │ key={`${index}:${tokenIndex}`}
· ──────────────────────────────
294 │ style={{
╰────
help: Use a unique data-dependent key to avoid unnecessary rerenders
⚠ react(no-array-index-key): Usage of Array index in keys is not allowed
╭─[apps/mobile/src/features/files/SourceFileSurface.tsx:309:27]
308 │ return (
309 │ <SourceText key={index}>
· ───────────
310 │ {body}
╰────
help: Use a unique data-dependent key to avoid unnecessary rerenders
⚠ react(exhaustive-effect-dependencies): Found extra effect dependencies
╭─[apps/mobile/src/features/home/HomeScreen.tsx:533:25]
532 │ // range) the boundary string is identical and the chain would die.
533 │ }, [nextSnoozeWakeAt, snoozeWakeTick]);
· ───────┬──────
· ╰── Unnecessary dependency `snoozeWakeTick`
534 │ const v2SearchQuery = props.searchQuery.trim().toLocaleLowerCase();
╰────
help: Extra dependencies can cause an effect to fire more often than it should, resulting in performance problems such as excessive renders and side effects
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/exhaustive-deps
⚠ react(purity): Cannot call impure function during render
╭─[apps/mobile/src/features/home/HomeScreen.tsx:524:53]
523 │ if (Number.isNaN(wakeAtMs)) return;
524 │ const delayMs = Math.min(Math.max(0, wakeAtMs - Date.now()) + 50, 2_147_483_647);
· ─────┬────
· ╰── Cannot call impure function
525 │ const id = setTimeout(() => {
╰────
help: `Date.now` is an impure function. Calling an impure function can produce unstable results that update unpredictably when the component re-renders
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/purity
⚠ eslint(no-empty-pattern): Empty array binding pattern
╭─[apps/server/src/pullRequest/PullRequestService.test.ts:1526:12]
1525 │
1526 │ for (const [] of [
· ──
1527 │ ["github", "github.com"],
╰────
help: Passing non-iterable values (null, undefined, numbers, booleans, etc.) will result in a runtime error because these values are not iterable.
⚠ react(set-state-in-effect): Calling setState synchronously within an effect can trigger cascading renders
╭─[apps/mobile/src/features/files/FileTreeBrowser.tsx:155:5]
150 │
151 │ useEffect(() => {
· ────┬────
· ╰── This is the containing effect
152 │ if (!controlledSelectedPath) {
153 │ return;
154 │ }
155 │ setExpandedPaths((current) => {
· ────────┬───────
· ╰── Avoid calling setState() directly within an effect
156 │ const ancestors = ancestorPaths(controlledSelectedPath);
╰────
help: Effects should synchronize React with external systems. Calling setState synchronously inside an effect starts another render and is usually unnecessary. Derive the value during render, initialize state directly, or update it from the event that caused the change. Use an effect only when synchronizing with an external system.
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/set-state-in-effect
⚠ unicorn(prefer-array-find): Prefer `find` over filtering and accessing the first result.
╭─[apps/server/src/terminal/Manager.test.ts:731:31]
730 │ );
731 │ const snapshot = events.filter((event) => event.type === "snapshot").at(-1)?.snapshot;
· ──────
732 │ expect(snapshot?.history).toBe("aa😀\rEND");
╰────
help: Use `find(predicate)` instead of `filter(predicate)[0]` or similar patterns.
⚠ react(exhaustive-effect-dependencies): Found extra effect dependencies
╭─[apps/mobile/src/features/layout/AdaptiveWorkspaceLayout.tsx:155:7]
154 │ }
155 │ }, [wrappedRender]);
· ──────┬──────
· ╰── Unnecessary dependency `wrappedRender`
156 │
╰────
help: Extra dependencies can cause an effect to fire more often than it should, resulting in performance problems such as excessive renders and side effects
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/exhaustive-deps
⚠ react(jsx-no-constructed-context-values): The Context `value` prop should not be constructed.
╭─[apps/mobile/src/features/layout/AdaptiveWorkspaceLayout.tsx:800:42]
799 │ >
800 │ <AdaptiveWorkspaceContext.Provider value={contextValue}>
· ────────────────────
801 │ <WindowHingeContext value={windowHinge}>
╰────
help: Wrap the `value` prop in useMemo() or useCallback(), or use a constant value to prevent unnecessary re-renders.
Alternatively, move the value outside the render function if it doesn't depend on props or state.
⚠ react(immutability): This value cannot be modified
╭─[apps/mobile/src/features/layout/workspace-inspector-pane.tsx:42:5]
35 │
36 │ const inspectorProgress = useSharedValue(inspectorVisible ? 1 : 0);
· ────────┬────────
· ╰── `inspectorProgress` originates here
37 │ const { renderedInspectorWidth } = props;
38 │ const renderedContentWidth = useSharedValue(inspectorWidth ?? 0);
39 │
40 │ const onClosed = props.onClosed;
41 │ useEffect(() => {
42 │ inspectorProgress.value = withTiming(
· ────────┬────────
· ╰── `inspectorProgress` cannot be modified
43 │ inspectorVisible ? 1 : 0,
╰────
help: Modifying a value returned from a hook is not allowed. Consider moving the modification into the hook where the value is constructed
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/immutability
⚠ react(immutability): This value cannot be modified
╭─[apps/mobile/src/features/layout/workspace-inspector-pane.tsx:67:7]
37 │ const { renderedInspectorWidth } = props;
38 │ const renderedContentWidth = useSharedValue(inspectorWidth ?? 0);
· ──────────┬─────────
· ╰── `renderedContentWidth` originates here
39 │
40 │ const onClosed = props.onClosed;
41 │ useEffect(() => {
42 │ inspectorProgress.value = withTiming(
43 │ inspectorVisible ? 1 : 0,
44 │ WORKSPACE_PANE_TIMING,
45 │ (finished) => {
46 │ if (finished === true && !inspectorVisible && onClosed !== undefined) {
47 │ runOnJS(onClosed)();
48 │ }
49 │ },
50 │ );
51 │ const targetWidth = inspectorVisible ? (inspectorWidth ?? 0) : 0;
52 │ renderedInspectorWidth.set(
53 │ resizing ? targetWidth : withTiming(targetWidth, WORKSPACE_PANE_TIMING),
54 │ );
55 │ }, [
56 │ inspectorProgress,
57 │ inspectorVisible,
58 │ inspectorWidth,
59 │ onClosed,
60 │ renderedInspectorWidth,
61 │ resizing,
62 │ ]);
63 │
64 │ useEffect(() => {
65 │ const targetWidth = inspectorWidth ?? 0;
66 │ if (!inspectorVisible || resizing) {
67 │ renderedContentWidth.value = targetWidth;
· ──────────┬─────────
· ╰── `renderedContentWidth` cannot be modified
68 │ return;
╰────
help: Modifying a value returned from a hook is not allowed. Consider moving the modification into the hook where the value is constructed
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/immutability
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/features/home/thread-swipe-actions.tsx:494:27]
493 │ >
494 │ {props.children(close)}
· ──┬──
· ╰── Cannot access ref value during render
495 │ </ReanimatedSwipeable>
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(no-unstable-nested-components): Do not define components during render.
╭─[apps/mobile/src/Stack.tsx:1079:21]
1078 │ <Navigator
1079 │ screenLayout={(props) => <GuardedScreenLayout {...props} />}
· ─────────────────────────────────────────────
1080 │ screenOptions={({ route }) =>
╰────
help: Move this component definition out of the parent component `AdaptiveRootStack` and pass data as props. If you want to allow component creation in props, set `allowAsProps` option to true.
⚠ t3code(no-polling-loop-in-tests): Polling loop in a test. Spinning on `yieldNow`/`sleep` is scheduler- and load-dependent. Await the `Deferred`, `Queue.take`, `Stream` element, `drain()`, or `expect.poll` that marks the milestone.
╭─[apps/server/src/scheduledTasks/ScheduledTaskService.webhook.test.ts:521:13]
520 │ })).delivery;
521 │ ╭─▶ while (delivery.outcome === "accepted") {
522 │ │ yield* Effect.yieldNow;
523 │ │ delivery = (yield* service.getWebhookDelivery({
524 │ │ id: task.id,
525 │ │ deliveryId: deliveryId!,
526 │ │ })).delivery;
527 │ ╰─▶ }
528 │ assert.equal(delivery.outcome, "dispatch_failed");
╰────
⚠ eslint(no-unused-vars): Function 'describeSchedule' is declared but never used.
╭─[apps/server/src/scheduledTasks/Schedule.ts:79:10]
78 │
79 │ function describeSchedule(schedule: ScheduledTaskSchedule): string {
· ────────┬───────
· ╰── 'describeSchedule' is declared here
80 │ if (schedule.type === "webhook") return "On webhook";
╰────
help: Consider removing this declaration.
⚠ react(no-object-type-as-default-prop): Do not use an array literal as default prop value. Use a stable reference instead.
╭─[apps/web/src/components/settings/SettingInheritance.tsx:163:24]
162 │ keys,
163 │ overridingProjects = [],
· ──
164 │ onClearOverrides,
╰────
help: Default values are re-created on every render and break referential equality, causing unnecessary re-renders. Move the value out of the component or memoize it.
⚠ t3code(no-inline-schema-compile): Hoist Schema.decodeUnknownSync(...) to module scope: the compiled function is rebuilt on every call. Move it to a module-level const.
╭─[packages/contracts/src/auth.test.ts:17:12]
16 │ it("decodes legacy review credentials without offering them in new grants", () => {
17 │ expect(Schema.decodeUnknownSync(AuthEnvironmentScopes)(["review:write"])).toEqual([
· ────────────────────────
18 │ "review:write",
╰────
⚠ t3code(no-inline-schema-compile): Hoist Schema.decodeUnknownSync(...) to module scope: the compiled function is rebuilt on every call. Move it to a module-level const.
╭─[packages/contracts/src/auth.test.ts:20:18]
19 │ ]);
20 │ expect(() => Schema.decodeUnknownSync(AuthGrantScopes)(["review:write"])).toThrow();
· ────────────────────────
21 │ expect(AuthStandardClientScopes).not.toContain("review:write");
╰────
⚠ t3code(no-inline-schema-compile): Hoist Schema.decodeUnknownSync(...) to module scope: the compiled function is rebuilt on every call. Move it to a module-level const.
╭─[packages/contracts/src/auth.test.ts:58:21]
57 │ it("ignores unknown response permissions without falling back to broader scopes", () => {
58 │ const session = Schema.decodeUnknownSync(AuthSessionState)({
· ────────────────────────
59 │ authenticated: true,
╰────
⚠ t3code(no-inline-schema-compile): Hoist Schema.encodeUnknownSync(...) to module scope: both the inline schema literal and the compiled function are rebuilt on every call. Move the compiled function to a module-level const.
╭─[packages/contracts/src/baseSchemas.test.ts:39:9]
38 │ JSON.stringify(
39 │ Schema.encodeUnknownSync(Schema.toCodecJson(Named))([
· ────────────────────────
40 │ { name: "a" },
╰────
⚠ t3code(no-polling-loop-in-tests): Polling loop in a test. Spinning on `yieldNow`/`sleep` is scheduler- and load-dependent. Await the `Deferred`, `Queue.take`, `Stream` element, `drain()`, or `expect.poll` that marks the milestone.
╭─[apps/server/src/project/ProjectService.test.ts:94:3]
93 │ ) {
94 │ ╭─▶ for (let attempt = 0; attempt < 100; attempt += 1) {
95 │ │ const project = Option.getOrThrow(yield* service.getById(projectId));
96 │ │ if (predicate(project)) return project;
97 │ │ yield* Effect.yieldNow;
98 │ ╰─▶ }
99 │ return yield* Effect.die(`Project ${projectId} was not enriched in time.`);
╰────
⚠ react(purity): Cannot call impure function during render
╭─[apps/web/src/hooks/useThreadActions.ts:821:56]
820 │ const resolved = resolveThreadTarget(target);
821 │ if (resolved && !canSnooze(resolved.thread, { now: new Date().toISOString() })) {
· ─────┬────
· ╰── Cannot call impure function
822 │ return AsyncResult.failure(
╰────
help: `Date` is an impure function. Calling an impure function can produce unstable results that update unpredictably when the component re-renders
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/purity
⚠ react(purity): Cannot call impure function during render
╭─[apps/web/src/hooks/useThreadActions.ts:709:46]
708 │ const wokeAt = resolved
709 │ ? threadWokeAt(resolved.thread, { now: new Date().toISOString() })
· ─────┬────
· ╰── Cannot call impure function
710 │ : null;
╰────
help: `Date` is an impure function. Calling an impure function can produce unstable results that update unpredictably when the component re-renders
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/purity
⚠ react(exhaustive-effect-dependencies): Found extra effect dependencies
╭─[apps/mobile/src/state/thread-order.ts:29:7]
28 │ getPendingThreadOrder();
29 │ }, [nowMinute, snoozeWakeTick]);
· ────┬──── ───────┬──────
· │ ╰── Unnecessary dependency `snoozeWakeTick`
· ╰── Unnecessary dependency `nowMinute`
30 │ return pending;
╰────
help: Extra dependencies can cause an effect to fire more often than it should, resulting in performance problems such as excessive renders and side effects
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/exhaustive-deps
⚠ t3code(no-polling-loop-in-tests): Polling loop in a test. Spinning on `yieldNow`/`sleep` is scheduler- and load-dependent. Await the `Deferred`, `Queue.take`, `Stream` element, `drain()`, or `expect.poll` that marks the milestone.
╭─[apps/server/src/project/ProjectEnrichmentService.test.ts:28:3]
27 │ ) {
28 │ ╭─▶ for (let attempt = 0; attempt < 100; attempt += 1) {
29 │ │ const available = yield* service.peek(workspaceRoot);
30 │ │ if (predicate(available)) return available;
31 │ │ yield* Effect.yieldNow;
32 │ ╰─▶ }
33 │ return yield* Effect.die(`Project metadata for ${workspaceRoot} was not resolved in time.`);
╰────
⚠ eslint(no-unused-vars): Identifier 'Duration' is imported but never used.
╭─[packages/provider-pi/src/server/adapter.test.ts:24:13]
23 │ import * as Deferred from "effect/Deferred";
24 │ import * as Duration from "effect/Duration";
· ────┬───
· ╰── 'Duration' is imported here
25 │ import * as Effect from "effect/Effect";
╰────
help: Consider removing this import.
⚠ eslint(no-unused-vars): Type 'AuthSessionState' is imported but never used.
╭─[apps/web/src/components/settings/ProviderSettingsPanel.logic.ts:4:8]
3 │ AuthProvidersManageScope,
4 │ type AuthSessionState,
· ────────┬───────
· ╰── 'AuthSessionState' is imported here
5 │ type EnvironmentId,
╰────
help: Consider removing this import.
⚠ t3code(no-inline-schema-compile): Hoist Schema.encodeUnknownSync(...) to module scope: both the inline schema literal and the compiled function are rebuilt on every call. Move the compiled function to a module-level const.
╭─[packages/contracts/src/composerContext.test.ts:181:18]
180 │ it("sends a message without the records the wire cannot carry", () => {
181 │ const wire = Schema.encodeUnknownSync(Schema.toCodecJson(OrchestrationMessageContext))({
· ────────────────────────
182 │ version: 1,
╰────
⚠ eslint(no-unused-vars): Variable 'layer' is declared but never used. Unused variables should start with a '_'.
╭─[packages/provider-pi/src/server/adapter.ts:3405:7]
3404 │
3405 │ const layer: Layer.Layer<ProviderAdapter.ProviderAdapterV2, never, PiAdapterV2DriverEnv> =
· ──┬──
· ╰── 'layer' is declared here
3406 │ Layer.effect(
╰────
help: Consider removing this declaration.
⚠ unicorn(no-array-reverse): Use `Array#toReversed()` instead of `Array#reverse()`.
╭─[packages/shared/src/composerContextLegacySend.ts:19:45]
18 │ const occurrences = collectComposerContextReferences(text);
19 │ for (const occurrence of [...occurrences].reverse()) {
· ───────
20 │ const record = recordsById.get(occurrence.contextId);
╰────
help: `Array#reverse()` mutates the original array. Use `Array#toReversed()` to return a new reversed array without modifying the original.
⚠ unicorn(require-module-specifiers): Empty import specifier is not allowed
╭─[packages/contracts/src/rpc.ts:297:8]
296 │ } from "./device.ts";
297 │ import {} from "./previewAutomation.ts";
· ──
298 │ import {
╰────
help: Remove empty braces
⚠ eslint(no-unused-vars): Variable 'claudeCaps' is declared but never used. Unused variables should start with a '_'.
╭─[packages/shared/src/model.test.ts:36:7]
35 │
36 │ const claudeCaps: ModelCapabilities = createModelCapabilities({
· ─────┬────
· ╰── 'claudeCaps' is declared here
37 │ optionDescriptors: [
╰────
help: Consider removing this declaration.
⚠ t3code(no-polling-loop-in-tests): Polling loop in a test. Spinning on `yieldNow`/`sleep` is scheduler- and load-dependent. Await the `Deferred`, `Queue.take`, `Stream` element, `drain()`, or `expect.poll` that marks the milestone.
╭─[packages/shared/src/atomicWrite.test.ts:139:5]
138 │ Effect.gen(function* () {
139 │ ╭─▶ while (fiber.pollUnsafe() === undefined) {
140 │ │ yield* TestClock.adjust("100 millis");
141 │ │ // oxlint-disable-next-line t3code/no-real-time-wait-in-tests -- a macrotask boundary so the real stat I/O can finish; time moves only via TestClock
142 │ │ yield* Effect.promise(() => new Promise((resolve) => setImmediate(resolve)));
143 │ ╰─▶ }
144 │ return yield* Fiber.join(fiber);
╰────
⚠ unicorn(no-useless-fallback-in-spread): Empty fallbacks in spreads are unnecessary
╭─[apps/mobile/src/state/use-model-option-memory.ts:21:7]
20 │ [instanceId]: {
21 │ ...(state[instanceId] ?? {}),
· ────────────────────────────
22 │ [model]: options,
╰────
help: Spreading falsy values in object literals won't add any unexpected properties, so it's unnecessary to add an empty object as fallback.
⚠ eslint(no-unneeded-ternary): Unnecessary use of boolean literals in conditional expression
╭─[packages/shared/src/serverSettings.test.ts:35:7]
34 │ const fallback = fallbackTextGenerationModelSelection(providerInstances, (instanceId) =>
35 │ instanceId === configured ? true : false,
· ────────────────────────────────────────
36 │ );
╰────
help: Remove this ternary operator
⚠ unicorn(no-useless-fallback-in-spread): Empty fallbacks in spreads are unnecessary
╭─[apps/mobile/src/state/use-composer-drafts.ts:1022:15]
1021 │ instanceId,
1022 │ { ...(persisted.modelOptionMemory[instanceId] ?? {}), ...models },
· ──────────────────────────────────────────────────
1023 │ ]),
╰────
help: Spreading falsy values in object literals won't add any unexpected properties, so it's unnecessary to add an empty object as fallback.
⚠ t3code(no-polling-loop-in-tests): Polling loop in a test. Spinning on `yieldNow`/`sleep` is scheduler- and load-dependent. Await the `Deferred`, `Queue.take`, `Stream` element, `drain()`, or `expect.poll` that marks the milestone.
╭─[packages/client-runtime/src/connection/supervisor.test.ts:135:3]
134 │ let lastState = yield* SubscriptionRef.get(state);
135 │ ╭─▶ for (let iteration = 0; iteration < 100; iteration += 1) {
136 │ │ lastState = yield* SubscriptionRef.get(state);
137 │ │ if (predicate(lastState)) {
138 │ │ return lastState;
139 │ │ }
140 │ │ yield* Effect.yieldNow;
141 │ ╰─▶ }
142 │ return yield* Effect.die(
╰────
⚠ t3code(no-inline-schema-compile): Hoist Schema.decodeUnknownOption(...) to module scope: the compiled function is rebuilt on every call. Move it to a module-level const.
╭─[packages/shared/src/otelEnvironment.ts:146:14]
145 │ name,
146 │ (raw) => Schema.decodeUnknownOption(OtlpProtocol)(raw.toLowerCase()),
· ──────────────────────────
147 │ `${name} is not http/protobuf or http/json, ${NOT_EXPORTED}`,
╰────
⚠ react(exhaustive-effect-dependencies): Found extra effect dependencies
╭─[apps/mobile/src/state/use-thread-outbox-drain.ts:1315:5]
1314 │ queuedMessagesByThreadKey,
1315 │ retryTick,
· ────┬────
· ╰── Unnecessary dependency `retryTick`
1316 │ restoreQueuedMessage,
╰────
help: Extra dependencies can cause an effect to fire more often than it should, resulting in performance problems such as excessive renders and side effects
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/exhaustive-deps
⚠ typescript(no-extraneous-class): Unexpected class with only a constructor.
╭─[apps/desktop/src/preview/Manager.test.ts:158:18]
157 │ BrowserWindow: browserWindowConstructor,
158 │ ╭─▶ ClipboardItem: class {
159 │ │ constructor(data: Record<string, unknown>) {
160 │ │ clipboardItemConstructor(data);
161 │ │ }
162 │ ╰─▶ },
163 │ clipboard: {
╰────
help: Try replacing this class with a standalone function or deleting it entirely
⚠ react(set-state-in-effect): Calling setState synchronously within an effect can trigger cascading renders
╭─[apps/mobile/src/state/use-vcs-action-state.ts:86:5]
83 │ const [nowMs, setNowMs] = useState(() => Date.now());
84 │ useEffect(() => {
· ────┬────
· ╰── This is the containing effect
85 │ if (!actionState.isRunning) return;
86 │ setNowMs(Date.now());
· ────┬───
· ╰── Avoid calling setState() directly within an effect
87 │ const interval = setInterval(() => setNowMs(Date.now()), 1000);
╰────
help: Effects should synchronize React with external systems. Calling setState synchronously inside an effect starts another render and is usually unnecessary. Derive the value during render, initialize state directly, or update it from the event that caused the change. Use an effect only when synchronizing with an external system.
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/set-state-in-effect
⚠ t3code(no-polling-loop-in-tests): Polling loop in a test. Spinning on `yieldNow`/`sleep` is scheduler- and load-dependent. Await the `Deferred`, `Queue.take`, `Stream` element, `drain()`, or `expect.poll` that marks the milestone.
╭─[packages/client-runtime/src/state/shell-sync.test.ts:169:7]
168 │ });
169 │ ╭─▶ for (let index = 0; index < 100; index += 1) {
170 │ │ if ((yield* SubscriptionRef.get(shellState)).status === "synchronizing") break;
171 │ │ yield* Effect.yieldNow;
172 │ ╰─▶ }
173 │
╰────
⚠ t3code(no-polling-loop-in-tests): Polling loop in a test. Spinning on `yieldNow`/`sleep` is scheduler- and load-dependent. Await the `Deferred`, `Queue.take`, `Stream` element, `drain()`, or `expect.poll` that marks the milestone.
╭─[packages/client-runtime/src/state/shell-sync.test.ts:178:7]
177 │ yield* Deferred.succeed(releaseSave, undefined);
178 │ ╭─▶ for (let index = 0; index < 100; index += 1) {
179 │ │ if ((yield* Ref.get(saved)).length > 0) break;
180 │ │ yield* Effect.yieldNow;
181 │ ╰─▶ }
182 │
╰────
⚠ t3code(no-polling-loop-in-tests): Polling loop in a test. Spinning on `yieldNow`/`sleep` is scheduler- and load-dependent. Await the `Deferred`, `Queue.take`, `Stream` element, `drain()`, or `expect.poll` that marks the milestone.
╭─[packages/client-runtime/src/state/shell-sync.test.ts:307:7]
306 │ yield* Deferred.succeed(releaseUnenrichedSave, undefined);
307 │ ╭─▶ for (let index = 0; index < 100; index += 1) {
308 │ │ const values = yield* Ref.get(saved);
309 │ │ if (values.length > 0 && values.at(-1)?.projects[0]?.repositoryIdentity != null) {
310 │ │ break;
311 │ │ }
312 │ │ yield* Effect.yieldNow;
313 │ ╰─▶ }
314 │
╰────
⚠ eslint(no-empty-pattern): Empty object binding pattern
╭─[apps/server/src/provider/Drivers/CodexDriver.test.ts:466:14]
465 │
466 │ for (const {} of ["direct", "wrapper"] as const) {
· ──
467 │ }
╰────
help: Passing `null` or `undefined` will result in runtime error because `null` and `undefined` cannot be destructured.
⚠ react(purity): Cannot call impure function during render
╭─[apps/web/src/components/CommandPalette.tsx:1996:20]
1995 │ title: inferProjectTitleFromPath(destinationPath),
1996 │ createdAt: new Date().toISOString(),
· ─────┬────
· ╰── Cannot call impure function
1997 │ remoteUrl: addProjectCloneFlow.remoteUrl,
╰────
help: `Date` is an impure function. Calling an impure function can produce unstable results that update unpredictably when the component re-renders
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/purity
⚠ unicorn(prefer-add-event-listener): Prefer `addEventListener()` over their `on`-function counterparts.
╭─[apps/web/src/components/device/deviceHubApi.test.ts:12:14]
11 │ addEventListener(_type: string, listener: (event: { data: string }) => void) {
12 │ this.onmessage = listener;
· ─────────
13 │ }
╰────
help: `addEventListener()` can register multiple handlers and accepts options such as `{ once: true }`; assigning to `on<event>` replaces any previously registered handler.
⚠ typescript(no-this-alias): Unexpected aliasing of 'this' to local variable.
╭─[apps/web/src/components/device/deviceHubApi.test.ts:16:9]
15 │ constructor() {
16 │ source = this;
· ──────
17 │ }
╰────
help: Assigning a variable to this instead of properly using arrow lambdas may be a symptom of pre-ES2015 practices or not managing scope well.
⚠ eslint(no-unused-vars): Type 'Scope' is imported but never used.
╭─[apps/server/src/provider/ProviderAuthService.ts:15:18]
14 │ import * as Layer from "effect/Layer";
15 │ import type * as Scope from "effect/Scope";
· ──┬──
· ╰── 'Scope' is imported here
16 │ import * as Stream from "effect/Stream";
╰────
help: Consider removing this import.
⚠ oxc(no-accumulating-spread): Do not spread accumulators in loops
╭─[packages/client-runtime/src/state/shell.ts:189:5]
186 │ let waiting = yield* Ref.get(awaitingCompletion);
187 │ let next = initial;
· ──┬─
· ╰── From this accumulator
188 │ let receivedSnapshot = false;
189 │ for (const item of items) {
· ─┬─
· ╰── For this loop
190 │ if (item.kind === "synchronized") {
191 │ waiting = false;
192 │ if (Option.isSome(next.snapshot)) {
193 │ next = { ...next, status: "live", error: Option.none() };
· ───┬───
· ╰── From this spread
194 │ }
╰────
help: Consider using `Object.assign()` to mutate the accumulator instead.
note: Using spreads within accumulators leads to `O(n^2)` time complexity.
⚠ eslint(no-unused-vars): Parameter '_' is declared but never used.
╭─[packages/shared/src/qrCode.ts:458:44]
457 │ ): Array<byte> {
458 │ let result: Array<byte> = divisor.map((_) => 0);
· ┬
· ╰── '_' is declared here
459 │ for (const b of data) {
╰────
help: Consider removing this parameter.
⚠ eslint(no-unused-vars): Parameter 'stopSessions' is declared but never used. Unused parameters should start with a '_'.
╭─[apps/server/src/provider/AntigravityAuth.ts:285:20]
284 │ },
285 │ (effect, flow, stopSessions) =>
· ──────┬─────
· ╰── 'stopSessions' is declared here
286 │ effect.pipe(
╰────
help: Consider removing this parameter.
⚠ unicorn(no-useless-fallback-in-spread): Empty fallbacks in spreads are unnecessary
╭─[packages/shared/src/serverSettings.ts:346:9]
345 │ const entry: ProjectSettingsOverrides = {
346 │ ...(entries.get(projectId) ?? currentEntries[projectId] ?? {}),
· ──────────────────────────────────────────────────────────────
347 │ };
╰────
help: Spreading falsy values in object literals won't add any unexpected properties, so it's unnecessary to add an empty object as fallback.
⚠ oxc(no-accumulating-spread): Do not spread accumulators in Array.prototype.reduce()
╭─[packages/shared/src/serverSettings.ts:448:24]
447 │ const favorites =
448 │ setModelFavorites?.reduce((current, change) => {
· ───┬──
· ╰── For this reduce
449 │ const exists = current.some(
450 │ (favorite) => favorite.provider === change.provider && favorite.model === change.model,
451 │ );
452 │ return change.favorite
453 │ ? exists
454 │ ? current
455 │ : [...current, { provider: change.provider, model: change.model }]
· ─────┬────
· ╰── From this spread
456 │ : current.filter(
╰────
help: Consider using `Object.assign()` or `Array.prototype.push()` to mutate the accumulator instead.
note: Using spreads within accumulators leads to `O(n^2)` time complexity.
⚠ oxc(no-accumulating-spread): Do not spread accumulators in loops
╭─[packages/shared/src/serverSettings.ts:466:3]
464 │ null;
465 │ let nextModelPreferences = initialModelPreferences;
· ──────────┬─────────
· ╰── From this accumulator
466 │ for (const change of setModelsHidden ?? []) {
· ─┬─
· ╰── For this loop
467 │ const preferences = nextModelPreferences?.[change.provider] ?? {
468 │ hiddenModels: [],
469 │ modelOrder: [],
470 │ };
471 │ const hiddenModels = preferences.hiddenModels.filter((model) => model !== change.model);
472 │ if (change.hidden) hiddenModels.push(change.model);
473 │ nextModelPreferences = {
474 │ ...nextModelPreferences,
· ───────────┬───────────
· ╰── From this spread
475 │ [change.provider]: { ...preferences, hiddenModels },
╰────
help: Consider using `Object.assign()` to mutate the accumulator instead.
note: Using spreads within accumulators leads to `O(n^2)` time complexity.
⚠ t3code(no-inline-schema-compile): Hoist Schema.is(...) to module scope: both the inline schema literal and the compiled function are rebuilt on every call. Move the compiled function to a module-level const.
╭─[apps/server/src/provider/acp/AntigravityProtocol.ts:263:20]
262 │ ...(update._meta !== undefined
263 │ ? { _meta: Schema.is(Schema.Record(Schema.String, Schema.Json))(meta) ? meta : null }
· ─────────
264 │ : {}),
╰────
⚠ react(purity): Cannot call impure function during render
╭─[apps/web/src/components/CustomSnoozeDialog.tsx:140:58]
139 │ {...(weekStartsOn === undefined ? {} : { weekStartsOn })}
140 │ disabled={{ before: new Date(new Date().setHours(0, 0, 0, 0)) }}
· ─────┬────
· ╰── Cannot call impure function
141 │ onSelect={(selected) => {
╰────
help: `Date` is an impure function. Calling an impure function can produce unstable results that update unpredictably when the component re-renders
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/purity
⚠ t3code(no-inline-schema-compile): Hoist Schema.is(...) to module scope: the compiled function is rebuilt on every call. Move it to a module-level const.
╭─[packages/effect-codex-app-server/src/schema.test.ts:50:18]
49 │ for (const tool of ["sendMessage", "followupTask", "interruptAgent", "listAgents"]) {
50 │ assert.equal(Schema.is(CodexSchema.ServerNotification__CollabAgentTool)(tool), true);
· ─────────
51 │ assert.equal(Schema.is(CodexSchema.V2ThreadResumeResponse__CollabAgentTool)(tool), true);
╰────
⚠ t3code(no-inline-schema-compile): Hoist Schema.is(...) to module scope: the compiled function is rebuilt on every call. Move it to a module-level const.
╭─[packages/effect-codex-app-server/src/schema.test.ts:51:18]
50 │ assert.equal(Schema.is(CodexSchema.ServerNotification__CollabAgentTool)(tool), true);
51 │ assert.equal(Schema.is(CodexSchema.V2ThreadResumeResponse__CollabAgentTool)(tool), true);
· ─────────
52 │ }
╰────
⚠ t3code(no-inline-schema-compile): Hoist Schema.is(...) to module scope: the compiled function is rebuilt on every call. Move it to a module-level const.
╭─[packages/effect-codex-app-server/src/schema.test.ts:55:5]
54 │ assert.equal(
55 │ Schema.is(CodexSchema.ServerNotification__CollabAgentToolCallStatus)("interrupted"),
· ─────────
56 │ true,
╰────
⚠ t3code(no-inline-schema-compile): Hoist Schema.is(...) to module scope: the compiled function is rebuilt on every call. Move it to a module-level const.
╭─[packages/effect-codex-app-server/src/schema.test.ts:59:5]
58 │ assert.equal(
59 │ Schema.is(CodexSchema.V2ThreadResumeResponse__CollabAgentToolCallStatus)("interrupted"),
· ─────────
60 │ true,
╰────
⚠ t3code(no-inline-schema-compile): Hoist Schema.is(...) to module scope: the compiled function is rebuilt on every call. Move it to a module-level const.
╭─[packages/effect-codex-app-server/src/schema.test.ts:103:16]
102 │
103 │ assert.equal(Schema.is(CodexSchema.V2ThreadResumeResponse)(resumeResponse), true);
· ─────────
104 │ });
╰────
⚠ eslint(require-yield): This generator function does not have `yield`
╭─[packages/provider-acp/src/server/mcpOverAcpBridge.ts:81:78]
80 │
81 │ ╭─▶ export const makeAcpMcpOverAcpBridge = Effect.fn("AcpMcpOverAcpBridge.make")(function* (
82 │ │ options: AcpMcpOverAcpBridgeOptions,
83 │ │ ): Effect.fn.Return<AcpMcpOverAcpBridge> {
84 │ │ const fetchImplementation = options.fetchImplementation ?? fetch;
85 │ │ const connections = new Map<string, Connection>();
86 │ │
87 │ │ const connectionFor = (connectionId: string): Effect.Effect<Connection, AcpMcpOverAcpError> =>
88 │ │ Effect.suspend(() => {
89 │ │ const connection = connections.get(connectionId);
90 │ │ return connection === undefined
91 │ │ ? Effect.fail(new AcpMcpOverAcpError(`Unknown MCP-over-ACP connection "${connectionId}".`))
92 │ │ : Effect.succeed(connection);
93 │ │ });
94 │ │
95 │ │ const send = (
96 │ │ connection: Connection,
97 │ │ message: unknown,
98 │ │ ): Effect.Effect<ReadonlyArray<unknown>, AcpMcpOverAcpError> =>
99 │ │ connection.mutex.withPermits(1)(
100 │ │ Effect.gen(function* () {
101 │ │ const body = JSON.stringify(message);
102 │ │ if (Buffer.byteLength(body) > MAX_MESSAGE_BYTES) {
103 │ │ return yield* Effect.fail(new AcpMcpOverAcpError("MCP-over-ACP message exceeds 8 MiB."));
104 │ │ }
105 │ │ const response = yield* Effect.tryPromise({
106 │ │ try: (signal) =>
107 │ │ fetchImplementation(options.endpoint, {
108 │ │ method: "POST",
109 │ │ signal,
110 │ │ headers: {
111 │ │ "content-type": "application/json",
112 │ │ accept: "application/json, text/event-stream",
113 │ │ authorization: options.authorization,
114 │ │ ...(connection.sessionId === null
115 │ │ ? {}
116 │ │ : { "mcp-session-id": connection.sessionId }),
117 │ │ ...(connection.protocolVersion === null
118 │ │ ? {}
119 │ │ : { "mcp-protocol-version": connection.protocolVersion }),
120 │ │ },
121 │ │ body,
122 │ │ }),
123 │ │ catch: bridgeError,
124 │ │ });
125 │ │ connection.sessionId = response.headers.get("mcp-session-id") ?? connection.sessionId;
126 │ │ if (!response.ok) {
127 │ │ yield* Effect.promise(
128 │ │ () => response.body?.cancel().catch(() => undefined) ?? Promise.resolve(),
129 │ │ );
130 │ │ return yield* Effect.fail(
131 │ │ new AcpMcpOverAcpError(`T3 Code MCP endpoint responded with HTTP ${response.status}.`),
132 │ │ );
133 │ │ }
134 │ │ const payloads = [...(yield* Stream.runCollect(responsePayloads(response, bridgeError)))];
135 │ │ for (const payload of payloads) {
136 │ │ connection.protocolVersion = protocolVersionOf(payload) ?? connection.protocolVersion;
137 │ │ }
138 │ │ return payloads;
139 │ │ }).pipe(Effect.mapError(bridgeError)),
140 │ │ );
141 │ │
142 │ │ const disconnect = Effect.fn("mcpOverAcpBridge.disconnect")(function* (
143 │ │ request: AcpSchema.DisconnectMcpRequest,
144 │ │ ): Effect.fn.Return<AcpSchema.DisconnectMcpResponse, AcpMcpOverAcpError> {
145 │ │ const connection = yield* connectionFor(request.connectionId);
146 │ │ connections.delete(request.connectionId);
147 │ │ const sessionId = connection.sessionId;
148 │ │ if (sessionId !== null) {
149 │ │ const response = yield* Effect.tryPromise({
150 │ │ try: (signal) =>
151 │ │ fetchImplementation(options.endpoint, {
152 │ │ method: "DELETE",
153 │ │ signal,
154 │ │ headers: {
155 │ │ authorization: options.authorization,
156 │ │ "mcp-session-id": sessionId,
157 │ │ ...(connection.protocolVersion === null
158 │ │ ? {}
159 │ │ : { "mcp-protocol-version": connection.protocolVersion }),
160 │ │ },
161 │ │ }),
162 │ │ catch: bridgeError,
163 │ │ });
164 │ │ if (!response.ok && response.status !== 404) {
165 │ │ return yield* Effect.fail(
166 │ │ new AcpMcpOverAcpError(
167 │ │ `T3 Code MCP endpoint rejected disconnect with HTTP ${response.status}.`,
168 │ │ ),
169 │ │ );
170 │ │ }
171 │ │ yield* Effect.promise(
172 │ │ () => response.body?.cancel().catch(() => undefined) ?? Promise.resolve(),
173 │ │ );
174 │ │ }
175 │ │ return {};
176 │ │ });
177 │ │
178 │ │ return {
179 │ │ connect: Effect.fn("mcpOverAcpBridge.connect")(function* (request) {
180 │ │ if (request.serverId !== "t3-code") {
181 │ │ return yield* Effect.fail(
182 │ │ new AcpMcpOverAcpError(`Unknown ACP MCP server "${request.serverId}".`),
183 │ │ );
184 │ │ }
185 │ │ if (connections.size >= MAX_CONNECTIONS) {
186 │ │ return yield* Effect.fail(new AcpMcpOverAcpError("Too many MCP-over-ACP connections."));
187 │ │ }
188 │ │ const connectionId = yield* options.allocateConnectionId;
189 │ │ connections.set(connectionId, {
190 │ │ mutex: yield* Semaphore.make(1),
191 │ │ sessionId: null,
192 │ │ protocolVersion: null,
193 │ │ nextRequestId: 0,
194 │ │ });
195 │ │ return { connectionId };
196 │ │ }),
197 │ │ message: Effect.fn("mcpOverAcpBridge.message")(function* (request) {
198 │ │ const connection = yield* connectionFor(request.connectionId);
199 │ │ const id = ++connection.nextRequestId;
200 │ │ const payloads = yield* send(connection, {
201 │ │ jsonrpc: "2.0",
202 │ │ id,
203 │ │ method: request.method,
204 │ │ ...(request.params == null ? {} : { params: request.params }),
205 │ │ });
206 │ │ const response = payloads.find((payload) => asEnvelope(payload)?.id === id);
207 │ │ const envelope = asEnvelope(response);
208 │ │ if (envelope === null) {
209 │ │ return yield* Effect.fail(
210 │ │ new AcpMcpOverAcpError("MCP server did not return a matching response."),
211 │ │ );
212 │ │ }
213 │ │ if (envelope.error !== undefined) {
214 │ │ return yield* Effect.fail(new AcpMcpOverAcpError(errorMessage(envelope.error)));
215 │ │ }
216 │ │ return (envelope.result ?? null) as AcpSchema.MessageMcpResponse;
217 │ │ }),
218 │ │ notification: Effect.fn("mcpOverAcpBridge.notification")(function* (request) {
219 │ │ const connection = yield* connectionFor(request.connectionId);
220 │ │ yield* send(connection, {
221 │ │ jsonrpc: "2.0",
222 │ │ method: request.method,
223 │ │ ...(request.params == null ? {} : { params: request.params }),
224 │ │ });
225 │ │ }),
226 │ │ disconnect,
227 │ │ dispose: Effect.suspend(() =>
228 │ │ Effect.forEach(
229 │ │ [...connections.keys()],
230 │ │ (connectionId) => disconnect({ connectionId }).pipe(Effect.ignore),
231 │ │ { discard: true },
232 │ │ ),
233 │ │ ),
234 │ │ };
235 │ ╰─▶ });
╰────
help: Add a `yield` expression inside the generator body, or convert it to a regular function if iteration behavior is not needed.
⚠ react(no-array-index-key): Usage of Array index in keys is not allowed
╭─[apps/mobile/src/features/review/ReviewCommentCard.tsx:223:31]
222 │ ? snippetTokens.map((line, lineIndex) => (
223 │ <NativeText key={lineIndex}>
· ───────────────
224 │ {lineIndex > 0 ? "\n" : ""}
╰────
help: Use a unique data-dependent key to avoid unnecessary rerenders
⚠ react(no-array-index-key): Usage of Array index in keys is not allowed
╭─[apps/mobile/src/features/review/ReviewCommentCard.tsx:227:25]
226 │ <NativeText
227 │ key={tokenIndex}
· ────────────────
228 │ style={{
╰────
help: Use a unique data-dependent key to avoid unnecessary rerenders
⚠ eslint(no-unused-vars): Function 'summarizePayload' is declared but never used.
╭─[packages/provider-acp/src/server/nativeLogging.ts:22:10]
21 │
22 │ function summarizePayload(payload: unknown): Readonly<Record<string, unknown>> {
· ────────┬───────
· ╰── 'summarizePayload' is declared here
23 │ if (payload === null) return { valueType: "null" };
╰────
help: Consider removing this declaration.
⚠ eslint(no-unused-vars): Identifier 'Image' is imported but never used.
╭─[apps/mobile/src/native/T3ComposerEditor.native.tsx:17:10]
16 │ import type { NativeSyntheticEvent, ViewProps } from "react-native";
17 │ import { Image, Platform, StyleSheet } from "react-native";
· ──┬──
· ╰── 'Image' is imported here
18 │
╰────
help: Consider removing this import.
⚠ react(exhaustive-effect-dependencies): Found missing effect dependencies
╭─[apps/mobile/src/native/T3ComposerEditor.native.tsx:229:6]
225 │ nativeEventSnapshotsRef.current = pruneAcknowledgedComposerNativeEvents(
226 │ nativeEventSnapshotsRef.current,
· ───────────┬───────────
· ╰── Missing dependency `nativeEventSnapshotsRef`. Refs, setState functions, and other "stable" values generally do not need to be added as dependencies, but this variable may change over time to point to different values
227 │ mostRecentEventCount,
228 │ );
229 │ }, [acknowledgesLatestNativeEvent, mostRecentEventCount]);
· ──────────────────────────┬──────────────────────────
· ╰── This dependency list is missing values used by the callback
230 │ const assumedValue = props.value;
╰────
help: Missing dependencies can cause an effect to fire less often than it should
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/exhaustive-deps
⚠ react(exhaustive-effect-dependencies): Found missing/extra effect dependencies
╭─[apps/mobile/src/native/T3ComposerEditor.native.tsx:237:7]
236 │ nativeEventSnapshotsRef.current = assumeComposerControlledState(
237 │ nativeEventSnapshotsRef.current,
· ───────────┬───────────
· ╰── Missing dependency `nativeEventSnapshotsRef`. Refs, setState functions, and other "stable" values generally do not need to be added as dependencies, but this variable may change over time to point to different values
238 │ controlledEventCount,
239 │ assumedValue,
240 │ );
241 │ }, [assumedValue, controlledEventCount, isNativeEcho, controlledDocumentJson]);
· ───────────┬──────────
· ╰── Unnecessary dependency `controlledDocumentJson`
242 │ const acceptNativeEvent = useCallback(
╰────
help: Missing dependencies can cause an effect to fire less often than it should. Extra dependencies can cause an effect to fire more often than it should, resulting in performance problems such as excessive renders and side effects
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/exhaustive-deps
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/native/T3ComposerEditor.native.tsx:162:29]
161 │ const tokens = collectComposerInlineTokens(props.value, {
162 │ preserveTrailingFrom: confirmedTokensRef.current,
· ─────────────┬────────────
· ╰── Cannot access ref value during render
163 │ });
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/native/T3ComposerEditor.native.tsx:162:29]
161 │ const tokens = collectComposerInlineTokens(props.value, {
162 │ preserveTrailingFrom: confirmedTokensRef.current,
· ─────────────┬────────────
· ╰── Passing a ref to a function may read its value during render
163 │ });
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/native/T3ComposerEditor.native.tsx:164:23]
163 │ });
164 │ confirmedTokensRef.current = tokens;
· ─────────┬────────────┬───
· │ ╰── Cannot update ref value during render
· ╰── This value is a ref
165 │ return JSON.stringify(
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/native/T3ComposerEditor.native.tsx:206:5]
205 │ mostRecentEventCount,
206 │ nativeEventSnapshotsRef.current,
· ───────────────┬───────────────
· ╰── Passing a ref to a function may read its value during render
207 │ );
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/native/T3ComposerEditor.native.tsx:212:5]
211 │ mostRecentEventCount,
212 │ nativeEventSnapshotsRef.current,
· ───────────────┬───────────────
· ╰── Passing a ref to a function may read its value during render
213 │ );
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(memo-dependencies): Found missing memoization dependencies
╭─[apps/mobile/src/native/T3ComposerEditor.native.tsx:197:6]
161 │ const tokens = collectComposerInlineTokens(props.value, {
162 │ preserveTrailingFrom: confirmedTokensRef.current,
· ─────────┬────────
· ╰── Missing dependency `confirmedTokensRef`. Refs, setState functions, and other "stable" values generally do not need to be added as dependencies, but this variable may change over time to point to different values
163 │ });
164 │ confirmedTokensRef.current = tokens;
165 │ return JSON.stringify(
166 │ composerContextEditorTokens(props.value, tokens, skillLabels).map((token) => {
167 │ const record =
168 │ token.type === "context"
169 │ ? props.context?.records.find((record) => record.contextId === token.contextId)
170 │ : undefined;
171 │ const presentation = contextChipPresentation(
172 │ token.type === "context" ? token.kind : token.type,
173 │ record,
174 │ );
175 │ const icon = contextChipIcon(
176 │ presentation,
177 │ token.type === "mention" ? token.value : contextRecordFileName(record),
178 │ );
179 │ return {
180 │ type: token.type,
181 │ source: token.source,
182 │ start: token.start,
183 │ end: token.end,
184 │ accent: contextChipAccent(presentation.accent, theme, chipTextColor),
185 │ label:
186 │ token.type === "skill"
187 │ ? (skillLabels.get(token.value) ?? token.value)
188 │ : token.type === "context"
189 │ ? `${token.label}${props.context?.records.some((record) => record.contextId === token.contextId) ? "" : " · unavailable"}`
190 │ : basename(token.value),
191 │ detail: token.type === "context" ? composerChipSizeSuffix(record) : "",
192 │ iconUri: contextChipIconUri(icon),
193 │ tintsIcon: icon.kind === "chip",
194 │ };
195 │ }),
196 │ );
197 │ }, [props.value, props.context, skillLabels, theme, chipTextColor]);
· ───────────────────────────────┬───────────────────────────────
· ╰── This dependency list is missing values used by the callback
198 │ // Every render resolves against the snapshot history, so a render whose
╰────
help: Missing dependencies can cause a value to update less often than it should, resulting in stale UI
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/exhaustive-deps
⚠ react(memo-dependencies): Found missing memoization dependencies
╭─[apps/mobile/src/native/T3ComposerEditor.native.tsx:259:5]
251 │ mostRecentEventCountRef.current = acknowledgedEventCount;
252 │ nativeEventSnapshotsRef.current.push({
· ───────────┬───────────
· ╰── Missing dependency `nativeEventSnapshotsRef`. Refs, setState functions, and other "stable" values generally do not need to be added as dependencies, but this variable may change over time to point to different values
253 │ eventCount: acknowledgedEventCount,
254 │ value,
255 │ selection: nextSelection,
256 │ });
257 │ return acknowledgedEventCount;
258 │ },
259 │ [],
· ─┬
· ╰── This dependency list is missing values used by the callback
260 │ );
╰────
help: Missing dependencies can cause a value to update less often than it should, resulting in stale UI
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/exhaustive-deps
⚠ react(exhaustive-effect-dependencies): Found extra effect dependencies
╭─[apps/mobile/src/features/review/ReviewSheet.tsx:454:7]
453 │ showAuxiliaryPane("inspector");
454 │ }, [environmentId, showAuxiliaryPane, threadId]);
· ──────┬────── ────┬───
· │ ╰── Unnecessary dependency `threadId`
· ╰── Unnecessary dependency `environmentId`
455 │ const {
╰────
help: Extra dependencies can cause an effect to fire more often than it should, resulting in performance problems such as excessive renders and side effects
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/exhaustive-deps
⚠ react(static-components): Cannot create components during render
╭─[apps/mobile/src/features/review/ReviewSheet.tsx:725:20]
492 │ // same check.
493 │ const NativeReviewDiffView = resolveNativeReviewDiffView();
· ─────────────┬─────────────
· ╰── The component is created during render here
494 │ const nativeReviewDiffViewRef = useRef<NativeReviewDiffViewHandle>(null);
495 │ const showcasedReviewDrawRef = useRef<string | null>(null);
496 │ const [isPullRefreshing, setIsPullRefreshing] = useState(false);
497 │ const handlePullToRefresh = async () => {
498 │ setIsPullRefreshing(true);
499 │ await refreshSelectedSection();
500 │ setIsPullRefreshing(false);
501 │ };
502 │ const reviewFileNavigatorRef = useRef<ReviewFileNavigatorHandle>(null);
503 │ const reviewFiles = parsedDiff.kind === "files" ? parsedDiff.files : [];
504 │ const fileVisibility = useReviewFileVisibility({
505 │ threadKey: reviewCache.threadKey,
506 │ sectionId: selectedSection?.id ?? null,
507 │ files: reviewFiles,
508 │ cachedExpandedFileIds: selectedSection?.id
509 │ ? reviewCache.expandedFileIdsBySection[selectedSection.id]
510 │ : undefined,
511 │ cachedViewedFileIds: selectedSection?.id
512 │ ? reviewCache.viewedFileIdsBySection[selectedSection.id]
513 │ : undefined,
514 │ });
515 │ const { collapsedFileIds, toggleExpandedFile, toggleViewedFile, viewedFileIds } = fileVisibility;
516 │ const commentSelection = useReviewCommentSelectionController({
517 │ environmentId,
518 │ threadId,
519 │ selectedSection,
520 │ nativeReviewDiffData,
521 │ });
522 │ const nativeBridge = useNativeReviewDiffBridge({
523 │ threadKey: reviewCache.threadKey,
524 │ sectionId: selectedSection?.id ?? null,
525 │ diff: selectedSection?.diff,
526 │ data: nativeReviewDiffData,
527 │ collapsedFileIds,
528 │ viewedFileIds,
529 │ selectedRowIds: commentSelection.selectedRowIds,
530 │ canHighlight: parsedDiff.kind === "files",
531 │ });
532 │ const showcaseReviewKey =
533 │ SHOWCASE_ENABLED && parsedDiff.kind === "files" && selectedSection
534 │ ? `${reviewCache.threadKey}:${selectedSection.id}:${nativeBridge.tokensResetKey}:${nativeBridge.themeId}`
535 │ : null;
536 │ const handleNativeDebug = (event: NativeSyntheticEvent<Record<string, unknown>>) => {
537 │ nativeBridge.onDebug(event);
538 │ if (
539 │ showcaseReviewKey === null ||
540 │ showcasedReviewDrawRef.current === showcaseReviewKey ||
541 │ !isNativeReviewDiffDrawEvent(event.nativeEvent)
542 │ ) {
543 │ return;
544 │ }
545 │ showcasedReviewDrawRef.current = showcaseReviewKey;
546 │ reportShowcaseSceneRendered({ scene: "review", themeId: nativeBridge.themeId });
547 │ };
548 │
549 │ const handleSelectFile = async (fileId: string | null) => {
550 │ loadVisibleFile(fileId, true);
551 │ commentSelection.clearSelection();
552 │ if (fileId !== null && collapsedFileIds.includes(fileId)) {
553 │ toggleExpandedFile(fileId);
554 │ }
555 │ const nativeView = nativeReviewDiffViewRef.current;
556 │ if (!nativeView) return;
557 │ const result = await settlePromise(() =>
558 │ fileId === null ? nativeView.scrollToTop(true) : nativeView.scrollToFile(fileId, true),
559 │ );
560 │ if (AsyncResult.isFailure(result)) {
561 │ console.error("[review] Failed to navigate to diff file", squashAtomCommandFailure(result));
562 │ }
563 │ };
564 │ const handleVisibleFileChange = (
565 │ event: NativeSyntheticEvent<{ readonly fileId?: string | null }>,
566 │ ) => {
567 │ loadVisibleFile(event.nativeEvent.fileId ?? null);
568 │ reviewFileNavigatorRef.current?.setVisibleFile(event.nativeEvent.fileId ?? null);
569 │ };
570 │ const renderInspector = () => (
571 │ <ReviewFileNavigator
572 │ ref={reviewFileNavigatorRef}
573 │ files={nativeReviewDiffData.files}
574 │ headerInset={insets.top}
575 │ sectionId={selectedSection?.id ?? null}
576 │ onSelectFile={(fileId) => void handleSelectFile(fileId)}
577 │ />
578 │ );
579 │
580 │ const handleNativeToggleFile = (event: NativeSyntheticEvent<{ readonly fileId?: string }>) => {
581 │ const { fileId } = event.nativeEvent;
582 │ if (fileId) {
583 │ loadVisibleFile(fileId, true);
584 │ toggleExpandedFile(fileId);
585 │ }
586 │ };
587 │
588 │ const handleNativeToggleViewedFile = (
589 │ event: NativeSyntheticEvent<{ readonly fileId?: string }>,
590 │ ) => {
591 │ const { fileId } = event.nativeEvent;
592 │ if (fileId) {
593 │ toggleViewedFile(fileId);
594 │ }
595 │ };
596 │
597 │ const parsedDiffNotice =
598 │ parsedDiff.kind === "files" || parsedDiff.kind === "raw" ? parsedDiff.notice : null;
599 │ const hasCachedSelectedDiff = selectedSection?.diff != null;
600 │ const hasAnyCachedDiff = reviewSections.some((section) => section.diff != null);
601 │ const sectionMenu = buildReviewSectionMenu(reviewSections);
602 │ const { showConnectionNotice, showSectionToolbar } = resolveReviewAvailability({
603 │ hasEnvironmentPresentation: environment.isReady,
604 │ isEnvironmentConnected: isEnvironmentReady,
605 │ hasCachedSelectedDiff,
606 │ hasAnyCachedDiff,
607 │ });
608 │ const handleRetryEnvironment = () => {
609 │ void retryEnvironment(environmentId);
610 │ };
611 │ const handleReturnToThread = () => {
612 │ if (navigation.canGoBack()) {
613 │ navigation.goBack();
614 │ return;
615 │ }
616 │ navigation.navigate("Thread", {
617 │ environmentId: String(environmentId),
618 │ threadId: String(threadId),
619 │ });
620 │ };
621 │ const androidHeaderSubtitle = [
622 │ selectedSection?.title,
623 │ headerDiffSummary.additions,
624 │ headerDiffSummary.deletions,
625 │ ]
626 │ .filter((part): part is string => Boolean(part))
627 │ .join(" · ");
628 │
629 │ const showChangedFilesPane =
630 │ !showConnectionNotice &&
631 │ selectedSection !== null &&
632 │ parsedDiff.kind === "files" &&
633 │ NativeReviewDiffView !== null;
634 │ useRegisterWorkspaceInspector(showChangedFilesPane ? renderInspector : undefined);
635 │ const showChangedFilesToggle = panes.supportsAuxiliaryPane && showChangedFilesPane;
636 │
637 │ const listHeader = (() => {
638 │ const children: ReactElement[] = [];
639 │
640 │ if (error) {
641 │ children.push(
642 │ <View
643 │ key="review-error"
644 │ className={cn(
645 │ "bg-card px-4 py-3",
646 │ Platform.OS === "android" ? "m-2 rounded-[20px]" : "border-b border-border",
647 │ )}
648 │ >
649 │ <Text className="text-sm font-t3-bold text-foreground">Review unavailable</Text>
650 │ <Text className="text-xs leading-normal text-foreground-muted">{error}</Text>
651 │ </View>,
652 │ );
653 │ }
654 │
655 │ if (parsedDiffNotice) {
656 │ children.push(<ReviewNotice key="review-notice" notice={parsedDiffNotice} />);
657 │ }
658 │
659 │ if (children.length === 0) {
660 │ return null;
661 │ }
662 │
663 │ return <>{children}</>;
664 │ })();
665 │ const headerSubtitle = [
666 │ headerDiffSummary.additions,
667 │ headerDiffSummary.deletions,
668 │ pendingReviewCommentCount > 0
669 │ ? `${pendingReviewCommentCount} comment${pendingReviewCommentCount === 1 ? "" : "s"}`
670 │ : null,
671 │ ]
672 │ .filter(Boolean)
673 │ .join(" · ");
674 │ const headerTitleText = selectedSection?.title ?? "Review changes";
675 │
676 │ return (
677 │ <>
678 │ <ReviewHeader
679 │ environmentId={environmentId}
680 │ threadId={threadId}
681 │ title={headerTitleText}
682 │ subtitle={headerSubtitle}
683 │ androidSubtitle={androidHeaderSubtitle}
684 │ iconColor={headerIcon}
685 │ selectedThreadCwd={selectedThreadCwd}
686 │ sectionMenu={sectionMenu}
687 │ selectedSection={selectedSection}
688 │ showSectionToolbar={showSectionToolbar}
689 │ showChangedFilesToggle={showChangedFilesToggle}
690 │ onRefresh={handlePullToRefresh}
691 │ onSelectSection={selectSection}
692 │ onReturnToThread={handleReturnToThread}
693 │ />
694 │
695 │ <ScreenContent>
696 │ <View className="flex-1 bg-sheet android:bg-sheet-solid">
697 │ {showConnectionNotice ? (
698 │ <View className="flex-1" style={{ paddingTop: topContentInset }}>
699 │ <EnvironmentConnectionNotice
700 │ environmentLabel={environment.presentation?.entry.target.label ?? "Environment"}
701 │ connection={
702 │ environment.presentation?.connection ?? {
703 │ phase: "available",
704 │ error: null,
705 │ traceId: null,
706 │ }
707 │ }
708 │ resourceName="review"
709 │ onRetry={handleRetryEnvironment}
710 │ />
711 │ </View>
712 │ ) : selectedSection && parsedDiff.kind === "files" && NativeReviewDiffView ? (
713 │ <View
714 │ className="flex-1"
715 │ style={{
716 │ backgroundColor: nativeBridge.theme.background,
717 │ }}
718 │ >
719 │ <View
720 │ className="min-w-0 flex-1"
721 │ style={listHeader ? { paddingTop: topContentInset } : undefined}
722 │ >
723 │ {listHeader}
724 │ <View className="min-w-0 flex-1" collapsable={false}>
725 │ <NativeReviewDiffView
· ──────────┬─────────
· ╰── This component is created during render
726 │ collapsable={false}
╰────
help: Components created during render will reset their state each time they are created. Declare components outside of render
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/static-components
⚠ eslint(no-unused-vars): Function 'assertUserMessagesExclude' is declared but never used.
╭─[apps/server/src/orchestration-v2/testkit/fixtures/shared.ts:1398:10]
1397 │
1398 │ function assertUserMessagesExclude(
· ────────────┬────────────
· ╰── 'assertUserMessagesExclude' is declared here
1399 │ projection: OrchestrationV2ThreadProjection,
╰────
help: Consider removing this declaration.
⚠ react(exhaustive-effect-dependencies): Found missing effect dependencies
╭─[apps/mobile/src/native/T3ComposerEditor.ios.tsx:231:6]
227 │ nativeEventSnapshotsRef.current = pruneAcknowledgedComposerNativeEvents(
228 │ nativeEventSnapshotsRef.current,
· ───────────┬───────────
· ╰── Missing dependency `nativeEventSnapshotsRef`. Refs, setState functions, and other "stable" values generally do not need to be added as dependencies, but this variable may change over time to point to different values
229 │ mostRecentEventCount,
230 │ );
231 │ }, [acknowledgesLatestNativeEvent, mostRecentEventCount]);
· ──────────────────────────┬──────────────────────────
· ╰── This dependency list is missing values used by the callback
232 │ const assumedValue = props.value;
╰────
help: Missing dependencies can cause an effect to fire less often than it should
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/exhaustive-deps
⚠ react(exhaustive-effect-dependencies): Found missing/extra effect dependencies
╭─[apps/mobile/src/native/T3ComposerEditor.ios.tsx:239:7]
238 │ nativeEventSnapshotsRef.current = assumeComposerControlledState(
239 │ nativeEventSnapshotsRef.current,
· ───────────┬───────────
· ╰── Missing dependency `nativeEventSnapshotsRef`. Refs, setState functions, and other "stable" values generally do not need to be added as dependencies, but this variable may change over time to point to different values
240 │ controlledEventCount,
241 │ assumedValue,
242 │ );
243 │ }, [assumedValue, controlledEventCount, isNativeEcho, controlledDocumentJson]);
· ───────────┬──────────
· ╰── Unnecessary dependency `controlledDocumentJson`
244 │ const acceptNativeEvent = useCallback(
╰────
help: Missing dependencies can cause an effect to fire less often than it should. Extra dependencies can cause an effect to fire more often than it should, resulting in performance problems such as excessive renders and side effects
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/exhaustive-deps
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/native/T3ComposerEditor.ios.tsx:164:29]
163 │ const tokens = collectComposerInlineTokens(props.value, {
164 │ preserveTrailingFrom: confirmedTokensRef.current,
· ─────────────┬────────────
· ╰── Cannot access ref value during render
165 │ });
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/native/T3ComposerEditor.ios.tsx:164:29]
163 │ const tokens = collectComposerInlineTokens(props.value, {
164 │ preserveTrailingFrom: confirmedTokensRef.current,
· ─────────────┬────────────
· ╰── Passing a ref to a function may read its value during render
165 │ });
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/native/T3ComposerEditor.ios.tsx:166:23]
165 │ });
166 │ confirmedTokensRef.current = tokens;
· ─────────┬────────────┬───
· │ ╰── Cannot update ref value during render
· ╰── This value is a ref
167 │ return JSON.stringify(
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/native/T3ComposerEditor.ios.tsx:208:5]
207 │ mostRecentEventCount,
208 │ nativeEventSnapshotsRef.current,
· ───────────────┬───────────────
· ╰── Passing a ref to a function may read its value during render
209 │ );
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/native/T3ComposerEditor.ios.tsx:214:5]
213 │ mostRecentEventCount,
214 │ nativeEventSnapshotsRef.current,
· ───────────────┬───────────────
· ╰── Passing a ref to a function may read its value during render
215 │ );
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(memo-dependencies): Found missing memoization dependencies
╭─[apps/mobile/src/native/T3ComposerEditor.ios.tsx:199:6]
163 │ const tokens = collectComposerInlineTokens(props.value, {
164 │ preserveTrailingFrom: confirmedTokensRef.current,
· ─────────┬────────
· ╰── Missing dependency `confirmedTokensRef`. Refs, setState functions, and other "stable" values generally do not need to be added as dependencies, but this variable may change over time to point to different values
165 │ });
166 │ confirmedTokensRef.current = tokens;
167 │ return JSON.stringify(
168 │ composerContextEditorTokens(props.value, tokens, skillLabels).map((token) => {
169 │ const record =
170 │ token.type === "context"
171 │ ? props.context?.records.find((record) => record.contextId === token.contextId)
172 │ : undefined;
173 │ const presentation = contextChipPresentation(
174 │ token.type === "context" ? token.kind : token.type,
175 │ record,
176 │ );
177 │ const icon = contextChipIcon(
178 │ presentation,
179 │ token.type === "mention" ? token.value : contextRecordFileName(record),
180 │ );
181 │ return {
182 │ type: token.type,
183 │ source: token.source,
184 │ start: token.start,
185 │ end: token.end,
186 │ accent: contextChipAccent(presentation.accent, theme, chipTextColor),
187 │ label:
188 │ token.type === "skill"
189 │ ? (skillLabels.get(token.value) ?? token.value)
190 │ : token.type === "context"
191 │ ? `${token.label}${props.context?.records.some((record) => record.contextId === token.contextId) ? "" : " · unavailable"}`
192 │ : basename(token.value),
193 │ detail: token.type === "context" ? composerChipSizeSuffix(record) : "",
194 │ iconUri: contextChipIconUri(icon),
195 │ tintsIcon: icon.kind === "chip",
196 │ };
197 │ }),
198 │ );
199 │ }, [props.value, props.context, skillLabels, theme, chipTextColor]);
· ───────────────────────────────┬───────────────────────────────
· ╰── This dependency list is missing values used by the callback
200 │ // Every render resolves against the snapshot history, so a render whose
╰────
help: Missing dependencies can cause a value to update less often than it should, resulting in stale UI
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/exhaustive-deps
⚠ react(memo-dependencies): Found missing memoization dependencies
╭─[apps/mobile/src/native/T3ComposerEditor.ios.tsx:261:5]
253 │ mostRecentEventCountRef.current = acknowledgedEventCount;
254 │ nativeEventSnapshotsRef.current.push({
· ───────────┬───────────
· ╰── Missing dependency `nativeEventSnapshotsRef`. Refs, setState functions, and other "stable" values generally do not need to be added as dependencies, but this variable may change over time to point to different values
255 │ eventCount: acknowledgedEventCount,
256 │ value,
257 │ selection: nextSelection,
258 │ });
259 │ return acknowledgedEventCount;
260 │ },
261 │ [],
· ─┬
· ╰── This dependency list is missing values used by the callback
262 │ );
╰────
help: Missing dependencies can cause a value to update less often than it should, resulting in stale UI
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/exhaustive-deps
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/native/StackHeader.tsx:185:9]
184 │ "options",
185 │ latestOptionFunctionsRef.current,
· ────────────────┬───────────────
· ╰── Passing a ref to a function may read its value during render
186 │ optionFunctionWrappersRef.current,
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/native/StackHeader.tsx:186:9]
185 │ latestOptionFunctionsRef.current,
186 │ optionFunctionWrappersRef.current,
· ────────────────┬────────────────
· ╰── Passing a ref to a function may read its value during render
187 │ ) as NativeStackNavigationOptions)
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/features/voice-input/VoiceInputProvider.tsx:122:38]
121 │ const audioLevelsRef = useRef(Array<number>(VOICE_WAVEFORM_SAMPLE_COUNT).fill(0));
122 │ const audioLevels = useSharedValue(audioLevelsRef.current);
· ───────────┬──────────
· ╰── Cannot access ref value during render
123 │ const sessionRef = useRef<VoiceInputSession | null>(null);
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/features/voice-input/VoiceInputProvider.tsx:126:8]
125 │
126 │ if (!sessionRef.current || !recorderRef.current) {
· ─────────┬────────
· ╰── Cannot access ref value during render
127 │ const recorder = createLazyVoiceRecorder({
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/features/voice-input/VoiceInputProvider.tsx:126:7]
125 │
126 │ if (!sessionRef.current || !recorderRef.current) {
· ─────────┬─────────
· ╰── Cannot access ref value during render
127 │ const recorder = createLazyVoiceRecorder({
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/features/voice-input/VoiceInputProvider.tsx:126:31]
125 │
126 │ if (!sessionRef.current || !recorderRef.current) {
· ─────────┬─────────
· ╰── Cannot access ref value during render
127 │ const recorder = createLazyVoiceRecorder({
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/features/voice-input/VoiceInputProvider.tsx:126:30]
125 │
126 │ if (!sessionRef.current || !recorderRef.current) {
· ──────────┬─────────
· ╰── Cannot access ref value during render
127 │ const recorder = createLazyVoiceRecorder({
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/features/voice-input/VoiceInputProvider.tsx:127:46]
126 │ if (!sessionRef.current || !recorderRef.current) {
127 │ ╭─▶ const recorder = createLazyVoiceRecorder({
128 │ │ create: () => new AudioModule.AudioRecorder(VOICE_RECORDING_OPTIONS),
129 │ │ onStatus: (status: RecordingStatus) => {
130 │ │ sessionRef.current?.controller.handleRecorderStatus({
131 │ │ isFinished: status.isFinished,
132 │ │ hasError: status.hasError || status.mediaServicesDidReset === true,
133 │ │ error: status.error,
134 │ │ url: status.url,
135 │ │ });
136 │ │ },
137 │ │ // Read when recording starts so preference changes do not re-render every composer.
138 │ │ selectInput: (inputs) => {
139 │ │ const preferences = registry.get(mobilePreferencesAtom);
140 │ │ if (!AsyncResult.isSuccess(preferences)) return null;
141 │ │ const known = microphoneOrder(preferences.value.microphones);
142 │ │ const order = rememberMicrophones(known, inputs);
143 │ │ if (order !== known) {
144 │ │ registry.set(updateMobilePreferencesAtom, {
145 │ │ transform: (current) => ({
146 │ │ microphones: rememberMicrophones(microphoneOrder(current.microphones), inputs),
147 │ │ }),
148 │ │ });
149 │ │ }
150 │ │ return preferredMicrophoneInput(inputs, order);
151 │ │ },
152 │ ├─▶ });
· ╰──── Passing a ref to a function may read its value during render
153 │ recorderRef.current = recorder;
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/features/voice-input/VoiceInputProvider.tsx:153:16]
152 │ });
153 │ recorderRef.current = recorder;
· ─────┬─────────┬───
· │ ╰── Cannot update ref value during render
· ╰── This value is a ref
154 │ sessionRef.current = new VoiceInputSession({
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/features/voice-input/VoiceInputProvider.tsx:154:48]
153 │ recorderRef.current = recorder;
154 │ ╭─▶ sessionRef.current = new VoiceInputSession({
155 │ │ recorder,
156 │ │ getTranscriber: getLocalVoiceTranscriber,
157 │ │ requestPermission: async () => {
158 │ │ const permission = await requestRecordingPermissionsAsync();
159 │ │ return { granted: permission.granted, canAskAgain: permission.canAskAgain };
160 │ │ },
161 │ │ configureRecording: configureVoiceRecordingAudio,
162 │ │ releaseRecording: releaseVoiceRecordingAudio,
163 │ │ deleteRecording: (uri) => new File(uri).delete(),
164 │ │ onStateChange: (nextState) =>
165 │ │ setState({
166 │ │ state: nextState,
167 │ │ ownerKey: sessionRef.current?.ownerKey ?? null,
168 │ │ label: sessionRef.current?.label ?? null,
169 │ │ }),
170 │ ├─▶ });
· ╰──── Cannot access ref value during render
171 │ }
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/features/voice-input/VoiceInputProvider.tsx:154:15]
153 │ recorderRef.current = recorder;
154 │ sessionRef.current = new VoiceInputSession({
· ─────┬────────┬───
· │ ╰── Cannot update ref value during render
· ╰── This value is a ref
155 │ recorder,
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/features/voice-input/VoiceInputProvider.tsx:185:7]
184 │ return () => subscription.remove();
185 │ }, [controller]);
· ─────┬────
· ╰── Cannot access ref value during render
186 │
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/features/voice-input/VoiceInputProvider.tsx:185:6]
184 │ return () => subscription.remove();
185 │ }, [controller]);
· ──────┬─────
· ╰── Cannot access ref value during render
186 │
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/features/voice-input/VoiceInputProvider.tsx:192:6]
191 │ },
192 │ [controller, recorder],
· ─────┬────
· ╰── Cannot access ref value during render
193 │ );
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/features/voice-input/VoiceInputProvider.tsx:175:20]
174 │ const controller = session.controller;
175 │ const recorder = recorderRef.current;
· ─────────┬─────────
· ╰── Cannot access ref value during render
176 │
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/features/voice-input/VoiceInputProvider.tsx:192:5]
191 │ },
192 │ [controller, recorder],
· ───────────┬──────────
· ╰── Cannot access ref value during render
193 │ );
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/features/voice-input/VoiceInputProvider.tsx:246:20]
245 │ return () => clearInterval(intervalId);
246 │ }, [audioLevels, controller, recorder, state.phase]);
· ─────┬────
· ╰── Cannot access ref value during render
247 │
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/features/voice-input/VoiceInputProvider.tsx:246:6]
245 │ return () => clearInterval(intervalId);
246 │ }, [audioLevels, controller, recorder, state.phase]);
· ────────────────────────┬───────────────────────
· ╰── Cannot access ref value during render
247 │
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/features/voice-input/VoiceInputProvider.tsx:261:5]
260 │ setOwnerFocused,
261 │ session,
· ───┬───
· ╰── Cannot access ref value during render
262 │ stop,
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/features/voice-input/VoiceInputProvider.tsx:251:10]
250 │
251 │ ╭─▶ return {
252 │ │ isAvailable: getLocalVoiceTranscriber() !== null || getNativeShowcaseScene() !== null,
253 │ │ state,
254 │ │ audioLevels,
255 │ │ elapsedSeconds,
256 │ │ isBusy: voiceInputBlocksSubmission(state),
257 │ │ ownerKey,
258 │ │ label,
259 │ │ focusedOwners,
260 │ │ setOwnerFocused,
261 │ │ session,
262 │ │ stop,
263 │ │ cancel,
264 │ ├─▶ };
· ╰──── Cannot access ref value during render
265 │ }
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ react(immutability): This value cannot be modified
╭─[apps/mobile/src/features/voice-input/VoiceInputProvider.tsx:212:7]
121 │ const audioLevelsRef = useRef(Array<number>(VOICE_WAVEFORM_SAMPLE_COUNT).fill(0));
122 │ const audioLevels = useSharedValue(audioLevelsRef.current);
· ─────┬─────
· ╰── `audioLevels` originates here
123 │ const sessionRef = useRef<VoiceInputSession | null>(null);
124 │ const recorderRef = useRef<LazyVoiceRecorder<RecorderState> | null>(null);
125 │
126 │ if (!sessionRef.current || !recorderRef.current) {
127 │ const recorder = createLazyVoiceRecorder({
128 │ create: () => new AudioModule.AudioRecorder(VOICE_RECORDING_OPTIONS),
129 │ onStatus: (status: RecordingStatus) => {
130 │ sessionRef.current?.controller.handleRecorderStatus({
131 │ isFinished: status.isFinished,
132 │ hasError: status.hasError || status.mediaServicesDidReset === true,
133 │ error: status.error,
134 │ url: status.url,
135 │ });
136 │ },
137 │ // Read when recording starts so preference changes do not re-render every composer.
138 │ selectInput: (inputs) => {
139 │ const preferences = registry.get(mobilePreferencesAtom);
140 │ if (!AsyncResult.isSuccess(preferences)) return null;
141 │ const known = microphoneOrder(preferences.value.microphones);
142 │ const order = rememberMicrophones(known, inputs);
143 │ if (order !== known) {
144 │ registry.set(updateMobilePreferencesAtom, {
145 │ transform: (current) => ({
146 │ microphones: rememberMicrophones(microphoneOrder(current.microphones), inputs),
147 │ }),
148 │ });
149 │ }
150 │ return preferredMicrophoneInput(inputs, order);
151 │ },
152 │ });
153 │ recorderRef.current = recorder;
154 │ sessionRef.current = new VoiceInputSession({
155 │ recorder,
156 │ getTranscriber: getLocalVoiceTranscriber,
157 │ requestPermission: async () => {
158 │ const permission = await requestRecordingPermissionsAsync();
159 │ return { granted: permission.granted, canAskAgain: permission.canAskAgain };
160 │ },
161 │ configureRecording: configureVoiceRecordingAudio,
162 │ releaseRecording: releaseVoiceRecordingAudio,
163 │ deleteRecording: (uri) => new File(uri).delete(),
164 │ onStateChange: (nextState) =>
165 │ setState({
166 │ state: nextState,
167 │ ownerKey: sessionRef.current?.ownerKey ?? null,
168 │ label: sessionRef.current?.label ?? null,
169 │ }),
170 │ });
171 │ }
172 │
173 │ const session = sessionRef.current;
174 │ const controller = session.controller;
175 │ const recorder = recorderRef.current;
176 │
177 │ useEffect(() => {
178 │ const subscription = AppState.addEventListener("change", (nextState) => {
179 │ // iOS reports `inactive` while its permission dialog is open. Only the
180 │ // real background state cancels preparation; recorder status handles
181 │ // calls and route interruptions during capture.
182 │ if (nextState === "background") controller.appMovedToBackground();
183 │ });
184 │ return () => subscription.remove();
185 │ }, [controller]);
186 │
187 │ useEffect(
188 │ () => () => {
189 │ controller.dispose();
190 │ recorder.release();
191 │ },
192 │ [controller, recorder],
193 │ );
194 │
195 │ useEffect(() => {
196 │ if (state.phase !== "recording") return;
197 │
198 │ const tag = `voice-input:${keepAwakeId}:${++keepAwakeSessionRef.current}`;
199 │ const activation = activateKeepAwakeAsync(tag);
200 │ void activation.catch(() => {});
201 │ return () => {
202 │ // Release after activation settles, even if the recording ends immediately.
203 │ void activation.then(() => deactivateKeepAwake(tag)).catch(() => {});
204 │ };
205 │ }, [keepAwakeId, state.phase]);
206 │
207 │ useEffect(() => {
208 │ if (state.phase !== "preparing" && state.phase !== "recording") return;
209 │
210 │ if (audioLevelsRef.current.some((level) => level !== 0)) {
211 │ audioLevelsRef.current = Array<number>(VOICE_WAVEFORM_SAMPLE_COUNT).fill(0);
212 │ audioLevels.value = audioLevelsRef.current;
· ─────┬─────
· ╰── `audioLevels` cannot be modified
213 │ }
╰────
help: Modifying a value returned from a hook is not allowed. Consider moving the modification into the hook where the value is constructed
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/immutability
⚠ react(immutability): Cannot modify local variables after render completes
╭─[apps/mobile/src/features/voice-input/VoiceInputProvider.tsx:212:7]
206 │
207 │ useEffect(() => {
· ───┬───
· ╰── This function may (indirectly) reassign or modify `audioLevels` after render
208 │ if (state.phase !== "preparing" && state.phase !== "recording") return;
209 │
210 │ if (audioLevelsRef.current.some((level) => level !== 0)) {
211 │ audioLevelsRef.current = Array<number>(VOICE_WAVEFORM_SAMPLE_COUNT).fill(0);
212 │ audioLevels.value = audioLevelsRef.current;
· ─────┬─────
· ╰── This modifies `audioLevels`
213 │ }
╰────
help: This argument is a function which may reassign or mutate `audioLevels` after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/immutability
⚠ unicorn(prefer-array-find): Prefer `find` over filtering and accessing the first result.
╭─[packages/client-runtime/src/operations/projects.ts:228:51]
227 │ ): string {
228 │ const folderName = workspaceRoot.split(/[\\/]/).filter(Boolean).at(-1) ?? "";
· ──────
229 │ return target.owner ? `${target.owner}/${folderName}` : folderName;
╰────
help: Use `find(predicate)` instead of `filter(predicate)[0]` or similar patterns.
⚠ react(immutability): This value cannot be modified
╭─[apps/mobile/src/features/voice-input/ComposerDictationControl.tsx:93:5]
90 │ }) {
91 │ const rotation = useSharedValue(props.hidden ? 1 : 0);
· ────┬───
· ╰── `rotation` originates here
92 │ useLayoutEffect(() => {
93 │ rotation.value = withTiming(props.hidden ? 1 : 0, TOOLBAR_FLIP_TIMING);
· ────┬───
· ╰── `rotation` cannot be modified
94 │ }, [props.hidden, rotation]);
╰────
help: Modifying a value returned from a hook is not allowed. Consider moving the modification into the hook where the value is constructed
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/immutability
⚠ react(immutability): This value cannot be modified
╭─[apps/mobile/src/features/voice-input/ComposerDictationControl.tsx:269:5]
266 │ const variant = props.variant ?? "plain";
267 │ const loadingVisibility = useSharedValue(props.loading ? 1 : 0);
· ────────┬────────
· ╰── `loadingVisibility` originates here
268 │ useLayoutEffect(() => {
269 │ loadingVisibility.value = withTiming(props.loading ? 1 : 0, DICTATION_TIMING);
· ────────┬────────
· ╰── `loadingVisibility` cannot be modified
270 │ }, [loadingVisibility, props.loading]);
╰────
help: Modifying a value returned from a hook is not allowed. Consider moving the modification into the hook where the value is constructed
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/immutability
⚠ react(immutability): This value cannot be modified
╭─[apps/mobile/src/features/voice-input/ComposerDictationControl.tsx:328:5]
325 │ }) {
326 │ const recordingVisibility = useSharedValue(props.phase === "recording" ? 1 : 0);
· ─────────┬─────────
· ╰── `recordingVisibility` originates here
327 │ useLayoutEffect(() => {
328 │ recordingVisibility.value = withTiming(props.phase === "recording" ? 1 : 0, DICTATION_TIMING);
· ─────────┬─────────
· ╰── `recordingVisibility` cannot be modified
329 │ }, [props.phase, recordingVisibility]);
╰────
help: Modifying a value returned from a hook is not allowed. Consider moving the modification into the hook where the value is constructed
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/immutability
⚠ react(immutability): This value cannot be modified
╭─[apps/mobile/src/features/voice-input/GlobalVoiceInputControl.tsx:68:5]
65 │ const [expanded, setExpanded] = useState(false);
66 │ const progress = useSharedValue(0);
· ────┬───
· ╰── `progress` originates here
67 │ useEffect(() => {
68 │ progress.value = withTiming(expanded ? 1 : 0, MORPH_TIMING);
· ────┬───
· ╰── `progress` cannot be modified
69 │ }, [expanded, progress]);
╰────
help: Modifying a value returned from a hook is not allowed. Consider moving the modification into the hook where the value is constructed
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/immutability
⚠ react(refs): Cannot access refs during render
╭─[apps/mobile/src/features/voice-input/useVoiceInputController.ts:27:14]
26 │ const latestInput = useRef(input);
27 │ latestInput.current = input;
· ─────┬─────────┬───
· │ ╰── Cannot update ref value during render
· ╰── This value is a ref
28 │ const mounted = useRef(true);
╰────
help: React refs are values that are not needed for rendering. Refs should only be accessed outside of render, such as in event handlers or effects. Accessing a ref value (the `current` property) during render can cause your component not to update as expected
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/refs
⚠ unicorn(prefer-set-has): should be a `Set`, and use `.has()` to check existence or non-existence.
╭─[apps/web/src/components/pullRequest/pullRequestList.logic.ts:265:9]
264 │ ): boolean {
265 │ const labels = entry.labels.map((label) => label.name.trim().toLowerCase());
· ─────────────────────────────────────────────────────────────────────
266 │ const holds = (label: string) => labels.includes(label.trim().toLowerCase());
╰────
help: Switch to `Set`
⚠ react(set-state-in-effect): Calling setState synchronously within an effect can trigger cascading renders
╭─[apps/mobile/src/features/review/useNativeReviewDiffHighlighting.ts:60:5]
55 │
56 │ useEffect(() => {
· ────┬────
· ╰── This is the containing effect
57 │ scheduler.reset();
58 │ highlightedRowIdsRef.current = new Set();
59 │ visibleChunkIndexRef.current = 0;
60 │ setVisibleRange({ firstRowIndex: 0, lastRowIndex: 80 });
· ───────┬───────
· ╰── Avoid calling setState() directly within an effect
61 │ setTokensPatchJson(createEmptyTokenPatch(resetKey));
╰────
help: Effects should synchronize React with external systems. Calling setState synchronously inside an effect starts another render and is usually unnecessary. Derive the value during render, initialize state directly, or update it from the event that caused the change. Use an effect only when synchronizing with an external system.
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/set-state-in-effect
⚠ react(exhaustive-effect-dependencies): Found extra effect dependencies
╭─[apps/mobile/src/features/review/useNativeReviewDiffHighlighting.ts:63:7]
62 │ return () => scheduler.cancel();
63 │ }, [enabled, resetKey, rows.length, scheduler]);
· ───┬─── ─────┬─────
· │ ╰── Unnecessary dependency `rows.length`
· ╰── Unnecessary dependency `enabled`
64 │
╰────
help: Extra dependencies can cause an effect to fire more often than it should, resulting in performance problems such as excessive renders and side effects
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/exhaustive-deps
⚠ react(no-array-index-key): Usage of Array index in keys is not allowed
╭─[apps/web/src/components/pullRequest/PullRequestSummaryTab.tsx:814:17]
813 │ <div
814 │ key={`${index}:${check.name}:${check.url ?? ""}`}
· ─────────────────────────────────────────────────
815 │ className="group flex items-center gap-2 rounded-md pr-1 hover:bg-accent/60"
╰────
help: Use a unique data-dependent key to avoid unnecessary rerenders
⚠ react(set-state-in-effect): Calling setState synchronously within an effect can trigger cascading renders
╭─[apps/mobile/src/features/review/useReviewCommentSelectionController.ts:107:5]
104 │
105 │ useEffect(() => {
· ────┬────
· ╰── This is the containing effect
106 │ clearReviewCommentTarget();
107 │ setPendingNativeCommentSelection(null);
· ────────────────┬───────────────
· ╰── Avoid calling setState() directly within an effect
108 │ }, [selectedSection?.id]);
╰────
help: Effects should synchronize React with external systems. Calling setState synchronously inside an effect starts another render and is usually unnecessary. Derive the value during render, initialize state directly, or update it from the event that caused the change. Use an effect only when synchronizing with an external system.
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/set-state-in-effect
⚠ react(set-state-in-effect): Calling setState synchronously within an effect can trigger cascading renders
╭─[apps/mobile/src/features/review/useReviewCommentSelectionController.ts:112:7]
109 │
110 │ useEffect(() => {
· ────┬────
· ╰── This is the containing effect
111 │ if (activeCommentTarget === null) {
112 │ setPendingNativeCommentSelection(null);
· ────────────────┬───────────────
· ╰── Avoid calling setState() directly within an effect
113 │ }
╰────
help: Effects should synchronize React with external systems. Calling setState synchronously inside an effect starts another render and is usually unnecessary. Derive the value during render, initialize state directly, or update it from the event that caused the change. Use an effect only when synchronizing with an external system.
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/set-state-in-effect
⚠ react(exhaustive-effect-dependencies): Found extra effect dependencies
╭─[apps/mobile/src/features/review/useReviewCommentSelectionController.ts:108:7]
107 │ setPendingNativeCommentSelection(null);
108 │ }, [selectedSection?.id]);
· ─────────┬─────────
· ╰── Unnecessary dependency `selectedSection?.id`
109 │
╰────
help: Extra dependencies can cause an effect to fire more often than it should, resulting in performance problems such as excessive renders and side effects
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/exhaustive-deps
⚠ react(no-array-index-key): Usage of Array index in keys is not allowed
╭─[apps/web/src/components/pullRequest/PullRequestChecksPopover.tsx:88:15]
87 │ <li
88 │ key={`${index}:${check.name}`}
· ──────────────────────────────
89 │ className="col-span-full grid grid-cols-subgrid items-center text-xs"
╰────
help: Use a unique data-dependent key to avoid unnecessary rerenders
⚠ react(set-state-in-effect): Calling setState synchronously within an effect can trigger cascading renders
╭─[apps/mobile/src/features/review/ReviewCommentComposerSheet.tsx:103:7]
100 │
101 │ useEffect(() => {
· ────┬────
· ╰── This is the containing effect
102 │ if (!target || selectedLines.length === 0) {
103 │ setHighlightedLinesById({});
· ───────────┬───────────
· ╰── Avoid calling setState() directly within an effect
104 │ return;
╰────
help: Effects should synchronize React with external systems. Calling setState synchronously inside an effect starts another render and is usually unnecessary. Derive the value during render, initialize state directly, or update it from the event that caused the change. Use an effect only when synchronizing with an external system.
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/set-state-in-effect
⚠ t3code(no-inline-schema-compile): Hoist Schema.decodeUnknownEffect(...) to module scope: both the inline schema literal and the compiled function are rebuilt on every call. Move the compiled function to a module-level const.
╭─[packages/effect-acp/src/errors.test.ts:129:28]
128 │ const secret = "acp-summary-secret";
129 │ const cause = yield* Schema.decodeUnknownEffect(
· ──────────────────────────
130 │ Schema.Struct({
╰────
⚠ react(no-object-type-as-default-prop): Do not use an array literal as default prop value. Use a stable reference instead.
╭─[apps/web/src/components/pullRequest/PullRequestListFilters.tsx:473:19]
472 │ onFilters,
473 │ authorOptions = [],
· ──
474 │ labelOptions = [],
╰────
help: Default values are re-created on every render and break referential equality, causing unnecessary re-renders. Move the value out of the component or memoize it.
⚠ react(no-object-type-as-default-prop): Do not use an array literal as default prop value. Use a stable reference instead.
╭─[apps/web/src/components/pullRequest/PullRequestListFilters.tsx:474:18]
473 │ authorOptions = [],
474 │ labelOptions = [],
· ──
475 │ optionScope,
╰────
help: Default values are re-created on every render and break referential equality, causing unnecessary re-renders. Move the value out of the component or memoize it.
⚠ t3code(no-inline-schema-compile): Hoist Schema.decodeUnknownEffect(...) to module scope: both the inline schema literal and the compiled function are rebuilt on every call. Move the compiled function to a module-level const.
╭─[packages/effect-acp/src/protocol.test.ts:500:31]
499 │
500 │ const response = yield* Schema.decodeUnknownEffect(
· ──────────────────────────
501 │ Schema.fromJsonString(JsonRpcErrorResponse),
╰────
⚠ t3code(no-inline-schema-compile): Hoist Schema.decodeUnknownEffect(...) to module scope: the compiled function is rebuilt on every call. Move it to a module-level const.
╭─[packages/effect-acp/src/client.ts:1269:11]
1268 │ extNotificationHandlers.set(CLIENT_METHODS.mcp_message, (params) =>
1269 │ Schema.decodeUnknownEffect(AcpSchemaV2.MessageMcpNotification)(params).pipe(
· ──────────────────────────
1270 │ Effect.mapError(() => AcpError.AcpRequestError.invalidParams()),
╰────
⚠ t3code(no-inline-schema-compile): Hoist Schema.is(...) to module scope: the compiled function is rebuilt on every call. Move it to a module-level const.
╭─[packages/effect-acp/src/schema.test.ts:18:12]
17 │ const command = { name: "plan", description: "Make a plan", input: { hint: "Task" } };
18 │ expect(Schema.is(V1.AvailableCommand)(command)).toBe(true);
· ─────────
19 │ expect(
╰────
⚠ t3code(no-inline-schema-compile): Hoist Schema.is(...) to module scope: the compiled function is rebuilt on every call. Move it to a module-level const.
╭─[packages/effect-acp/src/schema.test.ts:20:7]
19 │ expect(
20 │ Schema.is(V2.AvailableCommand)({ ...command, input: { type: "text", hint: "Task" } }),
· ─────────
21 │ ).toBe(true);
╰────
⚠ eslint(no-unused-vars): Variable 'layer' is declared but never used. Unused variables should start with a '_'.
╭─[packages/provider-opencode/src/server/adapter.ts:3755:7]
3754 │
3755 │ const layer: Layer.Layer<ProviderAdapter.ProviderAdapterV2, never, OpenCodeAdapterV2DriverEnv> =
· ──┬──
· ╰── 'layer' is declared here
3756 │ Layer.effect(
╰────
help: Consider removing this declaration.
⚠ eslint(no-unused-vars): Variable 'useDragRegion' is declared but never used. Unused variables should start with a '_'.
╭─[apps/web/src/components/preview/PreviewPanelShell.tsx:61:9]
60 │ ) {
61 │ const useDragRegion = isElectron && props.mode !== "sheet" && props.mode !== "embedded";
· ──────┬──────
· ╰── 'useDragRegion' is declared here
62 │ const isInline = props.mode === "inline";
╰────
help: Consider removing this declaration.
⚠ react(set-state-in-effect): Calling setState synchronously within an effect can trigger cascading renders
╭─[apps/mobile/src/features/pull-requests/PullRequestRouteScreen.tsx:329:7]
324 │ };
325 │ useEffect(() => {
· ────┬────
· ╰── This is the containing effect
326 │ if (!guidesEnabled && section === "guide") {
327 │ requestedSection.current = "overview";
328 │ currentScrollOffset.current = scrollOffsets.current.overview ?? -insets.top;
329 │ setSection("overview");
· ─────┬────
· ╰── Avoid calling setState() directly within an effect
330 │ }
╰────
help: Effects should synchronize React with external systems. Calling setState synchronously inside an effect starts another render and is usually unnecessary. Derive the value during render, initialize state directly, or update it from the event that caused the change. Use an effect only when synchronizing with an external system.
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/set-state-in-effect
⚠ react(exhaustive-effect-dependencies): Found missing effect dependencies
╭─[apps/mobile/src/features/pull-requests/PullRequestRouteScreen.tsx:331:6]
326 │ if (!guidesEnabled && section === "guide") {
327 │ requestedSection.current = "overview";
· ────────┬───────
· ╰── Missing dependency `requestedSection`. Refs, setState functions, and other "stable" values generally do not need to be added as dependencies, but this variable may change over time to point to different values
328 │ currentScrollOffset.current = scrollOffsets.current.overview ?? -insets.top;
· ─────────┬───────── ──────┬──────
· │ ╰── Missing dependency `scrollOffsets`. Refs, setState functions, and other "stable" values generally do not need to be added as dependencies, but this variable may change over time to point to different values
· ╰── Missing dependency `currentScrollOffset`. Refs, setState functions, and other "stable" values generally do not need to be added as dependencies, but this variable may change over time to point to different values
329 │ setSection("overview");
330 │ }
331 │ }, [guidesEnabled, section, insets.top]);
· ──────────────────┬─────────────────
· ╰── This dependency list is missing values used by the callback
332 │ const tabContent = activityContent;
╰────
help: Missing dependencies can cause an effect to fire less often than it should
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/exhaustive-deps
⚠ react(exhaustive-effect-dependencies): Found missing effect dependencies
╭─[apps/mobile/src/features/pull-requests/PullRequestRouteScreen.tsx:868:6]
851 │ if (
852 │ lastSelection.current.path === route.params.path &&
· ──────┬──────
· ╰── Missing dependency `lastSelection`. Refs, setState functions, and other "stable" values generally do not need to be added as dependencies, but this variable may change over time to point to different values
853 │ lastSelection.current.id === route.params.fileSelectionId
854 │ )
855 │ return;
856 │ lastSelection.current = { path: route.params.path, id: route.params.fileSelectionId };
857 │ if (route.params.focus) navigation.setParams({ focus: undefined });
858 │ setJumpPath(route.params.path);
859 │ setSelectedRowId(null);
860 │ jumpStarted.current = false;
861 │ const file = data.files.find((entry) => entry.path === route.params.path);
862 │ if (!file || !nativeView.current) return;
· ─────┬────
· ╰── Missing dependency `nativeView`. Refs, setState functions, and other "stable" values generally do not need to be added as dependencies, but this variable may change over time to point to different values
863 │ setCollapsedIds((ids) => ids.filter((id) => id !== file.id));
864 │ jumpStarted.current = true;
865 │ void nativeView.current.scrollToFile(file.id, false).catch(() => {
866 │ jumpStarted.current = false;
867 │ });
868 │ }, [route.params.path, route.params.fileSelectionId, route.params.focus, data.files, navigation]);
· ──────────────────────────────────────────────┬──────────────────────────────────────────────
· ╰── This dependency list is missing values used by the callback
869 │ const appliedFilter = useRef(filter.hideTestFiles);
╰────
help: Missing dependencies can cause an effect to fire less often than it should
note: React Compiler skipped optimizing this component or hook. Additional guidance: https://react.dev/reference/eslint-plugin-react-hooks/lints/exhaustive-deps
⚠ eslint(no-unused-vars): Variable 'layer' is declared but never used. Unused variables should start with a '_'.
╭─[packages/provider-grok/src/server/adapter.ts:408:7]
407 │
408 │ const layer: Layer.Layer<
· ──┬──
· ╰── 'layer' is declared here
409 │ ProviderAdapter.ProviderAdapterV2,
╰────
help: Consider removing this declaration.
⚠ eslint(no-unused-vars): Function 'promptResponseHasMissingXAiStopReason' is declared but never used.
╭─[packages/provider-grok/src/server/xaiAcpExtension.ts:1620:10]
1619 │
1620 │ function promptResponseHasMissingXAiStopReason(response: EffectAcpSchema.PromptResponse): boolean {
· ──────────────────┬──────────────────
· ╰── 'promptResponseHasMissingXAiStopReason' is declared here
1621 │ const meta = response._meta;
╰────
help: Consider removing this declaration.
Found 0 errors and 362 warnings in 5420 files (5.4s, 8 threads)
Post job cleanup.
Cache hit occurred on the primary key electron-Linux-X64-854e11ddd491bd4f350eebb67a74265df119376a3984c8e153cfe5fc8ced6309, not saving cache.
Post job cleanup.
##[start-action display=Cache full pnpm store;id=__706d9fd2-a58c-44a0-9bd8-944ab8abb637.__actions_cache]
Post job cleanup.
Cache hit occurred on the primary key pnpm-full-v1-Linux-X64-8600a8d4a7fcc9519d421cef0c77201c793c5d8afbbef2897636b5b9305a9b7d, not saving cache.
##[end-action id=__706d9fd2-a58c-44a0-9bd8-944ab8abb637.__actions_cache;outcome=success;conclusion=success;duration_ms=101]
##[start-action display=Cache Vite+;id=__706d9fd2-a58c-44a0-9bd8-944ab8abb637.vp_cache]
Post job cleanup.
Cache hit occurred on the primary key vite-plus-home-v2-Linux-X64-1.3.0-node26.12.1-pnpm@12.14.0, not saving cache.
##[end-action id=__706d9fd2-a58c-44a0-9bd8-944ab8abb637.vp_cache;outcome=success;conclusion=success;duration_ms=69]
Post job cleanup.
[command]/usr/local/bin/git version
git version 2.55.0
Temporarily overriding HOME='/home/runner/_work/_temp/f8f446e9-534e-4729-8c61-30812c7ed679' before making global git config changes
Adding repository directory to the temporary git global config as a safe directory
[command]/usr/local/bin/git config --global --add safe.directory /home/runner/_work/t3code/t3code
Removing SSH command configuration
[command]/usr/local/bin/git config --local --name-only --get-regexp core\.sshCommand
[command]/usr/local/bin/git submodule foreach --recursive sh -c "git config --local --name-only --get-regexp 'core\.sshCommand' && git config --local --unset-all 'core.sshCommand' || :"
fatal: No url found for submodule path '.repos/alchemy-effect/submodules/distilled' in .gitmodules
Warning: The process '/usr/local/bin/git' failed with exit code 128
A job completed hook has been configured by the self-hosted runner administrator
▸ Run '/job_completed.sh'
shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
env:
BLACKSMITH_RUNNER_MESSAGE_WAIT_MS: 152
BLACKSMITH_RUNNER_ACQUIRE_JOB_MS: 360
BLACKSMITH_CHECK_RUN_ID: 120851488754
BLACKSMITH_JOB_DISPLAY_NAME: Lint
GITHUB_ACTIONS_CACHE_MODE: write
Docker container cache not activated, skipping hash computation.
No active SSH sessions detected. Proceeding with shutdown immediately.
Cleaning up orphan processes