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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/quality-gates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
- ".github/workflows/quality-gates.yml"
- "lefthook.yml"
- "package/ego-browser/**"
- "skills/ego-browser/SKILL.md"
- "skills/ego-browser/learnings/**"
push:
branches:
Expand All @@ -15,6 +16,7 @@ on:
- ".github/workflows/quality-gates.yml"
- "lefthook.yml"
- "package/ego-browser/**"
- "skills/ego-browser/SKILL.md"
- "skills/ego-browser/learnings/**"

jobs:
Expand Down Expand Up @@ -72,4 +74,3 @@ jobs:
- name: Validate site skills
working-directory: package/ego-browser
run: npm run validate:site-skills

41 changes: 41 additions & 0 deletions package/ego-browser/src/legacy-skill-guard.test.mjs
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import test from "node:test";
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";

import {
LEGACY_GLOBAL_HELPERS,
LEGACY_TASK_SPACE_REPLACEMENTS,
STALE_SKILL_PREFIX,
installLegacySkillGuards,
} from "../dist/src/legacy-skill-guard.js";
import { resetSink } from "../dist/src/output-sink.js";

const SKILL_URL = new URL(
"../../../skills/ego-browser/SKILL.md",
import.meta.url,
);

const EXPECTED_TASK_SPACE_REPLACEMENTS = {
listTaskSpaces: "taskSpaces.list()",
switchTaskSpace: "taskSpaces.switch(nameOrId)",
Expand Down Expand Up @@ -65,3 +73,36 @@ test("legacy skill guards cover only the removed task-space global surface", ()
}
resetSink();
});

test("the current skill examples do not call removed global helpers", () => {
const skill = readFileSync(fileURLToPath(SKILL_URL), "utf8");
const examples = executableCodeBlocks(skill);

assert.notEqual(examples, "", "SKILL.md must contain executable examples");

for (const helper of LEGACY_GLOBAL_HELPERS) {
const unqualifiedCall = new RegExp(
`(?<![\\w.])${escapeRegExp(helper)}(?=\\s*\\()`,
"g",
);
assert.doesNotMatch(
examples,
unqualifiedCall,
`SKILL.md must use the current facade instead of ${helper}(...)`,
);
}
});

function executableCodeBlocks(markdown) {
return [
...markdown.matchAll(
/```(?:bash|js|javascript|ts|typescript)\n([\s\S]*?)```/g,
),
]
.map((match) => match[1])
.join("\n");
}

function escapeRegExp(value) {
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
2 changes: 1 addition & 1 deletion package/ego-browser/src/legacy-skill-guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ type InstallTarget = Record<string, unknown>;
* Globals removed when the agent-facing API moved to Playwright-style facades.
* Keep this list as the single cleanup source for both embedded and direct-CLI runs.
*/
const LEGACY_GLOBAL_HELPERS = [
export const LEGACY_GLOBAL_HELPERS = [
"click",
"dblclick",
"hover",
Expand Down
4 changes: 2 additions & 2 deletions skills/ego-browser/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ EOF

## Runtime map

- `page`: navigation and state (`goto`, `reload`, `url`, `title`, `info`), semantic locators, waits, `snapshot`, `screenshot`, `screencast`, `evaluate`, `keyboard`, `mouse`, downloads, and event draining.
- `page.locator(selector)`: chaining and filtering; `first` / `nth` / `last`; click, hover, `dragTo`, `scrollIntoViewIfNeeded`, form, keyboard, upload, state-read, collection, element-evaluate, screenshot, and wait methods.
- `page`: navigation and state (`goto`, `reload`, `url`, `title`, `info`), semantic locators, waits, `snapshot`, `screenshot`, `screencast`, `evaluate`, keyboard (`press`, `down`, `up`, `insertText`, `type`), mouse, downloads, and event draining.
- `page.locator(selector)`: chaining and filtering; `first` / `nth` / `last`; click, hover, `dragTo`, `scrollIntoViewIfNeeded`, form, keyboard (`press`, `pressSequentially`), upload, state-read, collection, element-evaluate, screenshot, and wait methods.
- `browser`: `listTabs`, `currentTab`, `switchTab`, `openOrReuseTab`, `closeTab`, `ensureRealTab`, `iframeTarget`.
- `taskSpaces`: `list`, `switch`, `new`, `useOrCreate`, `claim`, `complete`, `handOff`, `takeOver`, `waitForAgentControl`.
- `fetch.server` performs Node-side requests; `fetch.browser` performs requests in the current page origin. Use `cdp` only as an escape hatch.
Expand Down