Skip to content

feat: scoped tiers#75

Open
NisargIO wants to merge 2 commits intomainfrom
feat/scoped-tiers
Open

feat: scoped tiers#75
NisargIO wants to merge 2 commits intomainfrom
feat/scoped-tiers

Conversation

@NisargIO
Copy link
Copy Markdown
Member

@NisargIO NisargIO commented Apr 3, 2026

Summary by cubic

Adds scoped test tiers (quick, standard, thorough) to control test depth from the CLI and writes structured run results to .expect/runs for easy consumption by external agents. Also adds an auth-redirect warning when a page opens to a login/auth screen.

  • New Features

    • --scope <tier> CLI flag (quick, standard, thorough; default standard), validated and passed through to the supervisor.
    • Tier-aware system and execution prompts in @expect/shared/prompts (focused checks in quick, audits and cross-browser in thorough).
    • Persist run results to .expect/runs/{planId}.json with status, durations, step results, and artifacts; keeps last 20 runs; path is printed in non-JSON mode.
    • Auth redirect warning in the browser MCP open tool when the app redirects to an auth page; suggests marking auth-blocked steps.
    • Step durations and summaries included in CI output.
  • Refactors

    • Introduced ScopeTier in @expect/shared/models; executor and CLI accept and forward it.
    • Added NodeServices layer in the CLI to enable filesystem effects for result writing.
    • Unified result-building and output writing in headless and execution flows.
    • Added EXPECT_RUNS_DIR and EXPECT_RUNS_MAX_KEPT constants in @expect/supervisor; updated tests for new tier behavior.
    • Bumped packages/expect-skill to v2.3.0 and expanded docs for scope tiers and .expect/runs result files.

Written for commit 95ce694. Summary will update on new commits.

…ution reporting

- Added `scope` option to CLI for specifying test depth: quick, standard, or thorough.
- Updated `runHeadless` and related functions to handle new scope tier logic.
- Enhanced execution reporting to include detailed step results and durations.
- Implemented auth redirect warning in the browser MCP server.
- Introduced new constants for run management in the supervisor module.
@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Apr 3, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
expect Ready Ready Preview, Comment Apr 3, 2026 7:12am

@NisargIO NisargIO requested a review from skoshx April 3, 2026 03:07
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 3, 2026

Open in StackBlitz

npm i https://pkg.pr.new/expect-cli@75

commit: 95ce694

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 11 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/cli/src/index.tsx">

<violation number="1" location="apps/cli/src/index.tsx:71">
P2: `--scope` is exposed as a global option, but it only affects the headless execution path. In interactive runs it is ignored, so users can pass `--scope quick` and still get default behavior.</violation>
</file>

<file name="apps/cli/src/data/execution-atom.ts">

<violation number="1" location="apps/cli/src/data/execution-atom.ts:210">
P2: `finalExecuted.id ?? crypto.randomUUID()` does not handle empty-string ids, so runs with `id: ""` all write to the same `.expect/runs/.json` file.</violation>
</file>

<file name="apps/cli/src/utils/run-test.ts">

<violation number="1" location="apps/cli/src/utils/run-test.ts:405">
P2: Use a truthy fallback for `finalExecuted.id` so empty-string IDs don’t collapse to `.expect/runs/.json` and overwrite previous run results.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

)
.option("-t, --target <target>", "what to test: unstaged, branch, or changes", "changes")
.option(
"-s, --scope <tier>",
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: --scope is exposed as a global option, but it only affects the headless execution path. In interactive runs it is ignored, so users can pass --scope quick and still get default behavior.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/cli/src/index.tsx, line 71:

<comment>`--scope` is exposed as a global option, but it only affects the headless execution path. In interactive runs it is ignored, so users can pass `--scope quick` and still get default behavior.</comment>

<file context>
@@ -63,6 +67,11 @@ const program = new Command()
   )
   .option("-t, --target <target>", "what to test: unstaged, branch, or changes", "changes")
+  .option(
+    "-s, --scope <tier>",
+    "test depth: quick (one check, ~30s), standard (primary + follow-ups), thorough (full audit)",
+    "standard",
</file context>
Fix with Cubic

summary: `${summaryParts.join(", ")} out of ${report.steps.length} step${report.steps.length === 1 ? "" : "s"}`,
});

yield* writeRunResult(finalExecuted.id ?? crypto.randomUUID(), resultOutput);
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: finalExecuted.id ?? crypto.randomUUID() does not handle empty-string ids, so runs with id: "" all write to the same .expect/runs/.json file.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/cli/src/data/execution-atom.ts, line 210:

<comment>`finalExecuted.id ?? crypto.randomUUID()` does not handle empty-string ids, so runs with `id: ""` all write to the same `.expect/runs/.json` file.</comment>

<file context>
@@ -175,6 +179,36 @@ const executeCore = (input: ExecuteInput) =>
+      summary: `${summaryParts.join(", ")} out of ${report.steps.length} step${report.steps.length === 1 ? "" : "s"}`,
+    });
+
+    yield* writeRunResult(finalExecuted.id ?? crypto.randomUUID(), resultOutput);
+
     return {
</file context>
Suggested change
yield* writeRunResult(finalExecuted.id ?? crypto.randomUUID(), resultOutput);
yield* writeRunResult(finalExecuted.id && finalExecuted.id.length > 0 ? finalExecuted.id : crypto.randomUUID(), resultOutput);
Fix with Cubic

});

const runResultPath = yield* writeRunResult(
finalExecuted.id ?? crypto.randomUUID(),
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Use a truthy fallback for finalExecuted.id so empty-string IDs don’t collapse to .expect/runs/.json and overwrite previous run results.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/cli/src/utils/run-test.ts, line 405:

<comment>Use a truthy fallback for `finalExecuted.id` so empty-string IDs don’t collapse to `.expect/runs/.json` and overwrite previous run results.</comment>

<file context>
@@ -366,39 +369,47 @@ export const runHeadless = (options: HeadlessRunOptions) =>
+          });
+
+          const runResultPath = yield* writeRunResult(
+            finalExecuted.id ?? crypto.randomUUID(),
+            resultOutput,
+          );
</file context>
Suggested change
finalExecuted.id ?? crypto.randomUUID(),
finalExecuted.id || crypto.randomUUID(),
Fix with Cubic

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 3, 2026

Test Results

✅ Website Test: passed

9 passed, 0 failed out of 10 steps — 172s

Step Status Duration
Homepage loads — hero section and install commands visible ✅ passed 15s
View demo — navigates to /replay?demo=true and player loads ✅ passed 7s
Replay controls — play/pause, speed selector, step list ✅ passed 38s
Copy button — clipboard contains the install command text ✅ passed 15s
Theme toggle — dark mode changes background, light mode restores it ✅ passed 16s
Footer links — GitHub and X have correct hrefs and target="_blank" ✅ passed 5s
Legal pages — /terms, /privacy, /security each load with text content ✅ passed 20s
Mobile viewport 375×812 — no horizontal scrollbar, key content visible ✅ passed 22s
Accessibility audit — check for critical/serious WCAG violations ⬜ not-run
Console errors check — verify no JS errors on homepage ✅ passed 30s

Session Recording

https://github.com/millionco/expect/releases/download/ci-pr-75/f7e45ab0-21ed-4004-849a-2e6fc0b023c9.webm


Workflow run #219 | 📎 Download all recordings

// agents (Cursor, Claude Code, Codex) can read a single file instead of
// polling terminal output. Each run gets a unique planId (UUID), enabling
// parallel agent sessions without file conflicts.

Copy link
Copy Markdown
Contributor

@vercel vercel bot Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Constants EXPECT_STATE_DIR, EXPECT_RUNS_DIR, and EXPECT_RUNS_MAX_KEPT are duplicated in write-run-result.ts instead of being imported from supervisor

Fix on Vercel

yes?: boolean;
agent?: AgentBackend;
target?: Target;
scope?: ScopeTier;
Copy link
Copy Markdown
Contributor

@vercel vercel bot Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CommanderOpts interface declares scope/target/output/agent with literal union types (ScopeTier, Target, OutputFormat, AgentBackend), but Commander provides raw strings for all options, making the type annotation misleading about type safety.

Fix on Vercel

});

const totalDurationMs = getTotalElapsedMs(report.steps) || durationMs;
const summaryParts = [`${passedCount} passed`, `${failedCount} failed`];
Copy link
Copy Markdown
Contributor

@vercel vercel bot Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The summary construction in execution-atom.ts is missing the skipped count, resulting in inconsistent output compared to run-test.ts

Fix on Vercel

…ers and execution results

- Bumped version from 2.2.0 to 2.3.0.
- Added detailed documentation on scope tiers for testing depth: quick, standard, and thorough.
- Included instructions for reading structured run result files from `.expect/runs/{planId}.json`.
Copy link
Copy Markdown
Contributor

@vercel vercel bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Suggestion:

The --scope option is accepted globally but silently ignored in interactive mode (when users run expect without --yes or --message), making the option appear to work when it doesn't

Fix on Vercel

summary: `${summaryParts.join(", ")} out of ${report.steps.length} step${report.steps.length === 1 ? "" : "s"}`,
});

yield* writeRunResult(finalExecuted.id ?? crypto.randomUUID(), resultOutput);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using the ?? operator doesn't properly handle empty-string IDs, causing multiple runs to overwrite the same file

Fix on Vercel

});

const runResultPath = yield* writeRunResult(
finalExecuted.id ?? crypto.randomUUID(),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The nullish coalescing operator (??) doesn't treat empty strings as falsy, causing empty-string IDs to be used instead of generating UUIDs

Fix on Vercel

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.

1 participant