chore(e2e): trim narration and self-justifying comments; drop a stale one

An audit of the comments added since the feature base flagged a batch of
justification openers ("Not a copy-paste", "Live entry not dead weight"),
"there's a test for it" cross-refs, and how-we-found-it war-stories. Cut the
narration and keep the load-bearing fact in each. One was actively wrong:
playwright.config.ts still described the `maxDiffPixelRatio` anti-aliasing
budget that 5cec81b replaced with an absolute `maxDiffPixels` — removed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Sergey Kozyrenko
2026-07-25 12:12:46 +07:00
co-authored by Claude Opus 4.8
parent 9649e7f313
commit a7c0c19b53
16 changed files with 26 additions and 46 deletions
-1
View File
@@ -14,7 +14,6 @@ on:
- "v[0-9]+.[0-9]+.[0-9]+"
workflow_dispatch:
# A PR's synchronize pushes supersede each other; keep only the latest run per ref.
concurrency:
group: ci-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
+4 -8
View File
@@ -7,15 +7,11 @@ const owns = (dir: string, file: string): boolean => file === dir || file.starts
/**
* Maps a set of changed repo files to the manifest routes they touch, by
* prefix-matching each change against a route's owning source dirs. This is the
* substrate for selective runs and for scoping the exploratory agent to the
* changed surface. Pure — the CLI and the vitest unit test both drive it.
* prefix-matching each change against a route's owning source dirs.
*
* - no frontend change → no routes (a backend-only diff; the caller falls back
* to the full suite, and schema-compat covers the backend contract);
* - a frontend change owned by no route → all routes (shared infra: the e2e
* engine, config, src/lib, a provider used everywhere) — conservative on
* purpose, since over-running is safe and under-running hides a regression;
* - no frontend change → no routes (the caller falls back to the full suite);
* - a frontend change owned by no route → all routes (shared infra: e2e engine,
* config, src/lib, an everywhere-provider) — over-run rather than under-run;
* - otherwise → the routes whose `sources` the changes fall under.
*
* Paths are repo-relative (`frontend/...`); `sources` are `frontend/`-relative.
+2 -3
View File
@@ -12,9 +12,8 @@ const errorsTest = base.extend<{ pageErrorLog: PageErrorLog }>({
await use(log);
// Asserted here rather than left to the spec: a spec that never destructured this
// fixture collected nothing, so opting in was the same as opting out. Console errors
// stay with `expectCleanPage` — several specs drive genuine 4xx paths that log one.
// Auto (not opt-in): a spec that never destructured this fixture would assert nothing.
// Console errors stay with `expectCleanPage` — several specs drive 4xx paths that log one.
baseExpect(log.pageErrors, 'no uncaught page errors').toEqual([]);
},
{ auto: true },
+1 -4
View File
@@ -35,8 +35,6 @@ export const RULES = [
match: /get_number/,
toolCalls: [{ args: { value: 1 }, name: 'get_number' }],
},
// The task reporter summarizes the finished task and only accepts the
// report_result tool.
{
label: 'task-report',
match: /report_result|TASK EXECUTION EVALUATOR AND REPORTER/,
@@ -51,8 +49,7 @@ export const RULES = [
},
],
},
// The refiner re-plans between subtasks and only accepts subtask_patch;
// an empty operations list means "plan unchanged".
// An empty operations list means "plan unchanged".
{
label: 'subtask-refine',
match: /subtask_patch/,
+2 -3
View File
@@ -18,9 +18,8 @@ const flows: ResultOf<typeof FlowsDocument> = { flows: [] };
const flowTemplates: ResultOf<typeof FlowTemplatesDocument> = { flowTemplates: [] };
// Live entry, not dead weight: after a websocket reconnect the app re-requests
// resources on the wire with {recursive:true} (removing this red-lights the
// reconnect spec on the 501 gate).
// After a websocket reconnect the app re-requests resources on the wire with {recursive:true};
// removing this entry red-lights the reconnect spec on the 501 gate.
const resources: ResultOf<typeof ResourcesDocument> = { resources: [] };
const providers: ResultOf<typeof ProvidersDocument> = { providers: [] };
+2 -2
View File
@@ -181,8 +181,8 @@ export const flowsCassette = (override: Cassette = {}): Cassette =>
{
frames: [
...FLOW_A_STREAMED_IDS.map((id) => addedFrame(makeMessage(id, '5'), 80)),
// Not a copy-paste: a resubscribe replays what the refetch already
// delivered, and the sentinel after it proves the replay was received.
// A resubscribe replays what the refetch already delivered; the sentinel
// after it proves the replay was received.
{
...addedFrame(makeMessage(FLOW_A_RECONNECT_ID, '5'), 0),
whenFlag: REPLAY_FLAG,
+1 -1
View File
@@ -54,7 +54,7 @@ export const handleWsConnection = (
case 'connection_init': {
// Ack immediately; a frame sent before the ack is a graphql-ws protocol
// violation that closes the socket. Ack-first ordering is pinned by the unit test.
// violation that closes the socket.
send({ type: 'connection_ack' });
break;
}
+3 -7
View File
@@ -45,14 +45,10 @@ if ((tier === 'stand' || tier === 'local') && !TIERS[tier].baseURL) {
}
export default defineConfig<BackendOptions>({
// A colour change must move enough pixels to fail. The baselines and the run both
// render in the pinned container (the host path is blocked above), so there is no
// host-vs-CI rasterisation noise to absorb — tighten the per-pixel threshold below
// Playwright's default 0.2 so a one-step palette shift is caught, with a small
// maxDiffPixelRatio for anti-aliasing at glyph edges. cross/contrast.spec.ts still
// measures colour numerically as the belt-and-suspenders check.
// Absolute, not a ratio: 1% of a 1280x720 baseline is 9,216 pixels, more than any one foreground
// token covers, so a token could change hue with every baseline still matching.
// token covers, so a token could change hue with every baseline still matching. Baselines and
// run both render in the pinned container (the host path is blocked above), so 200px absorbs the
// glyph anti-aliasing without host-vs-CI noise.
expect: {
toHaveScreenshot: { maxDiffPixels: 200, threshold: 0.02 },
},
+1 -2
View File
@@ -56,8 +56,7 @@ const SANCTIONED_VARIANTS = [
* its path; a tab panel by `${path} [${tab}]`. Exact strings: they waive one node, not a rule.
*/
const ACCEPTED: Record<string, string[]> = {
// file-manager.tsx expand-all control; changing it moves pixels, so it goes with the design pass.
// Same control renders in the flow Files tab, so it is waived there under the same rationale.
// file-manager.tsx expand-all control, on /resources and embedded in the flow Files tab.
'/resources': ['button: hover:text-blue-400'],
[`${routes.flow('5')} [Files]`]: ['button: hover:text-blue-400'],
};
@@ -72,7 +72,6 @@ test.describe('resources', { tag: '@coverage' }, () => {
await page.goto('/resources');
await expect(page.getByText('No resources yet')).toBeVisible();
// The CTA, not just the title — the empty state's whole point is the upload affordance.
// Scope to the drop zone (its hint is unique) so the toolbar's Upload button is excluded.
const dropZone = page.locator('div').filter({ hasText: 'Up to 300 MB per file' }).last();
@@ -69,9 +69,9 @@ test.describe('flow subscriptions', { tag: ['@flows', '@smoke'] }, () => {
});
/**
* Not a duplicate of the round trip above: leaving via `/flows` unmounts FlowProvider (app.tsx
* wraps only `flows/:flowId`), so stream A is already closed there. Only the pager keeps the
* provider mounted and merely swaps the subscription variables.
* Leaving via `/flows` unmounts FlowProvider (app.tsx wraps only `flows/:flowId`), so stream A is
* already closed there. Only the pager keeps the provider mounted and merely swaps the subscription
* variables the one path where a superseded stream can still write into the flow on screen.
*/
test.describe('flow subscriptions across a pager switch', { tag: '@flows' }, () => {
test.use({ cassette: pagerStreamsCassette() });
+2 -2
View File
@@ -4,8 +4,8 @@ import { readTerminalBuffer } from '../../helpers/terminal.ts';
test.describe('real backend flow run', { tag: '@real' }, () => {
test('runs a flow end-to-end through the mock LLM', async ({ page }) => {
// Above the sum of the step timeouts below (60+30+90+90+90+60 = 420s); at 240s a legitimately
// slow-but-passing real run was killed mid-step with a generic timeout, masking the real state.
// Above the sum of the step timeouts below (60+30+90+90+90+60 = 420s), so a slow-but-passing
// run is not killed mid-step with a generic timeout that masks the real state.
test.setTimeout(450_000);
const pageErrors: string[] = [];
+2 -3
View File
@@ -23,9 +23,8 @@ compose() {
# sandboxes for any flow id starting with 9.
remove_e2e_sandboxes() {
docker ps -aq --filter 'name=^/?pentagi-terminal-9[0-9]{4,}$' | xargs -r docker rm -f
# Each sandbox also gets a `<container>-data` volume, created on the socket
# outside the compose project — removing the container leaves it behind, so
# every Tier-2 run used to add one more dangling volume.
# Each sandbox also gets a `<container>-data` volume, created on the socket outside the compose
# project — removing the container leaves it behind, so it needs its own cleanup.
docker volume ls -q --filter 'name=^pentagi-terminal-9[0-9]{4,}-data$' | xargs -r docker volume rm
}
@@ -159,8 +159,6 @@ describe('SettingsProvider create-form type guards', () => {
expect(navigate).not.toHaveBeenCalled();
});
// The seeding effect re-runs on every settingsProviders refetch (a fresh `data` reference under
// cache-and-network); keepDirtyValues is what stops that reset from wiping an in-flight edit.
it('preserves an in-flight edit across a background refetch', () => {
state.providerId = 'edit-1';
const { rerender } = render(<SettingsProvider />);
@@ -171,7 +169,6 @@ describe('SettingsProvider create-form type guards', () => {
fireEvent.change(nameInput, { target: { value: 'My Unsaved Edit' } });
// A refetch delivers a new `data` object with the same server content, re-firing the effect.
queryResult.data = { settingsProviders };
rerender(<SettingsProvider />);
@@ -1205,7 +1205,7 @@ function SettingsProvider() {
},
// The seeding effect re-runs on every settingsProviders refetch (cache-and-network +
// replaceWithIncoming gives a fresh `data`); without this a background refetch landing
// mid-edit silently wipes the unsaved form. Matches settings-prompt and template.
// mid-edit silently wipes the unsaved form.
resetOptions: { keepDirtyValues: true },
schema: formSchema,
});
+2 -2
View File
@@ -39,8 +39,8 @@ import { Log } from '@/lib/log';
/**
* Under `errorPolicy:'all'` a partial not-found error surfaces alongside a flow that loaded fine, so
* the not-found disjunct gates on `!flowData?.flow` mirroring `flowLoadError` and the toast below.
* Without the gate that partial error redirects the user off a flow that rendered correctly.
* the not-found disjunct gates on `!flowData?.flow`. Without the gate that partial error redirects
* the user off a flow that rendered correctly.
*/
export const deriveFlowMissing = (
flowData: null | undefined | { flow: unknown },