Skip to content

fix(dashboard): gate the legacy dashboard-report command on a config - #772

Merged
jeff-r2026 merged 2 commits into
Tencent:mainfrom
ydflow:fix/dashboard-report-legacy-gate
Sep 24, 2026
Merged

jeff-r2026 merged 2 commits into
Tencent:mainfrom
ydflow:fix/dashboard-report-legacy-gate

Conversation

@ydflow

@ydflow ydflow commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

What's the problem

The legacy teamai dashboard-report --stdin subcommand records dashboard events with no config check.

A current install writes only teamai hook-dispatch, and its dashboard-report handler is registered with requiresConfig — so when no config resolves for the hook's cwd, the dispatcher drops it. The old subcommand never got that gate. Hooks written by an earlier install still call it in every directory, so it kept appending to ~/.teamai/dashboard/events.jsonl for projects that never set up teamai — and since the event log is one machine-wide file whose events carry a cwd, those sessions were then attributed and reported by whichever scope pulled next.

This is the first half of #768; #771 covers the second half (the double-count and cross-project totals in teamai stats).

What's the fix

Apply the same gate teamai contribute-check was given in #748 — the other legacy command older installs still call. In dashboardReport(), after reading STDIN, resolve the config for the session's directory and return early when there is none:

const { resolveConfigForDir } = await import('./config.js');
if (!(await resolveConfigForDir(resolveHookCwd(hookData)))) {
  log.debug('dashboard-report: teamai is not set up here, skipping');
  return;
}

Two details worth calling out:

  • Asked about the session's cwd, not the process cwd. The payload is parsed with resolveHookCwd (the same helper parseHookEvent uses), so a host that sends cwd — or Cursor's workspace_roots — resolves the right project. A host that sends neither falls back to the directory the hook runs in, which is the semantics [bug] TeamAI hooks reach projects that never set it up: Stop nudge, and skill usage pushed to another team's stats #748 already established for contribute-check, so the two legacy commands behave alike.
  • No behaviour change for an installed team. The gate only short-circuits when nothing resolves; a malformed payload still falls through to parseHookEvent, which reports it as before.

Test plan

New src/__tests__/dashboard-report-gate.test.ts (3 tests), driving the real dashboardReport() with a Readable stand-in for STDIN — the same harness conversation-token-e2e.test.ts uses:

Test Before After
records nothing for a directory that never set up teamai events.jsonl gets 1 session_start no file, no events
still records for a directory teamai is set up in 1 session_start 1 session_start (unchanged)
records nothing when no cwd can be resolved 1 session_start no events

Verified as follows:

  • RED → GREEN — the two gated cases failed before the change (each showing the recorded session_start), the installed-team case passed both before and after, so the gate does not disturb the working path.
  • Rollback check — with the gate stashed, both gated cases go red again with the same recorded event, confirming the red comes from the code under test.
  • npx tsc --noEmit → exit 0.
  • Full-suite baseline comparison — the repo has pre-existing failures on Windows (a skill named gstack:tdd is seeded, and : is not legal in a Win32 filename). Clean HEAD: 105 failed / 4240 passed; with fix(stats): count each session once and keep other projects out #771 applied: 104/4241; with this change: 103 failed / 4242 passed — no new failures.
  • One pre-existing failure in hook-handlers.test.ts ("contribute-check handler withholds the reminder when the payload cwd exists but cannot be checked") reproduces on a clean HEAD with this change stashed, so it is not caused by this PR.

Notes for reviewers

A current install writes only `teamai hook-dispatch`, whose
dashboard-report handler declares `requiresConfig` and is dropped when
no config resolves for the hook's cwd. The legacy subcommand stayed
ungated, so a hook left behind by an earlier install kept recording
dashboard events for every directory it fired in — including projects
that never set up teamai, whose sessions were then reported by
whichever scope pulled next.

Apply the same gate `teamai contribute-check` was given in Tencent#748, asked
about the session's cwd (or, for a host that sends none, the directory
the hook runs in), so the two legacy commands behave alike.
Both suites drive `dashboardReport()` directly, so they bypass the
dispatcher and now hit the new config gate. Their payload cwd is a
fixture path that need not exist, and resolveConfigForDir then falls
back to the user scope — which nothing had seeded, so every hook call
returned early and no event was ever recorded.

Seed a user-scope config, which is what these pipelines already assume:
an installed team reporting its own sessions.
@jeff-r2026 jeff-r2026 self-assigned this Sep 24, 2026
@github-actions

Copy link
Copy Markdown

Findings

  • [P1 blocking] The PR description lacks the required real-CLI end-to-end verification. It reports direct Vitest calls to dashboardReport(), type-checking, and suite results, but no npm run build followed by an actual teamai dashboard-report --stdin CLI invocation. Add the commands and successful results to the Test Plan.

No additional code defects or rule violations found in the current diff. No earlier findings were provided to mark resolved.

@jeff-r2026
jeff-r2026 merged commit 34e65e9 into Tencent:main Sep 24, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants