@capagents/forgeqe 2.3.15 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/HOW_TO_USE.md +9 -2
- package/README.md +2 -0
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/dist/forgeqe.js +1099 -1038
- package/dist/web/THIRD_PARTY_NOTICES.md +2542 -0
- package/dist/web/assets/ApiTests-CSSed9hU.js +2 -0
- package/dist/web/assets/Chat-CFfiv7wI.js +2 -0
- package/dist/web/assets/Data-Qolfhsd7.js +4 -0
- package/dist/web/assets/Features-BM48eq6x.js +1 -0
- package/dist/web/assets/Jobs-BjVNQUaK.js +3 -0
- package/dist/web/assets/Quality-F0sKErYg.js +1 -0
- package/dist/web/assets/Record-CkwV9gN8.js +1 -0
- package/dist/web/assets/Regression-DKaNfFu1.js +2 -0
- package/dist/web/assets/Reports-o_82URX6.js +3 -0
- package/dist/web/assets/Response-YL9AIB8R.js +8 -0
- package/dist/web/assets/Runs-Dp-DzyW1.js +2 -0
- package/dist/web/assets/circle-dashed-DbpKfamm.js +1 -0
- package/dist/web/assets/context-engine-BIWf1ZIT.svg +1 -0
- package/dist/web/assets/dm-sans-latin-400-normal-BwCSEQnW.woff +0 -0
- package/dist/web/assets/dm-sans-latin-400-normal-CW0RaeGs.woff2 +0 -0
- package/dist/web/assets/dm-sans-latin-500-normal-B9HHJjqV.woff2 +0 -0
- package/dist/web/assets/dm-sans-latin-500-normal-Dr3UlScf.woff +0 -0
- package/dist/web/assets/dm-sans-latin-600-normal-Aqo67rzb.woff2 +0 -0
- package/dist/web/assets/dm-sans-latin-600-normal-BmdmIIQ2.woff +0 -0
- package/dist/web/assets/dm-sans-latin-ext-400-normal-BjWJ59Pq.woff +0 -0
- package/dist/web/assets/dm-sans-latin-ext-400-normal-BtiwyxMk.woff2 +0 -0
- package/dist/web/assets/dm-sans-latin-ext-500-normal-BJfUCQsA.woff2 +0 -0
- package/dist/web/assets/dm-sans-latin-ext-500-normal-DR84L5F-.woff +0 -0
- package/dist/web/assets/dm-sans-latin-ext-600-normal-4vooXBpG.woff2 +0 -0
- package/dist/web/assets/dm-sans-latin-ext-600-normal-DRtaDpgU.woff +0 -0
- package/dist/web/assets/external-link-pvVHJFAZ.js +1 -0
- package/dist/web/assets/file-chart-column-increasing-b-Yh6rmz.js +1 -0
- package/dist/web/assets/index-Bkx3fVbr.js +21 -0
- package/dist/web/assets/index-DSEYuBEd.css +2 -0
- package/dist/web/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
- package/dist/web/assets/jetbrains-mono-cyrillic-500-normal-DJqRU3vO.woff +0 -0
- package/dist/web/assets/jetbrains-mono-cyrillic-500-normal-DmUKJPL_.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
- package/dist/web/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-greek-500-normal-D7SFKleX.woff +0 -0
- package/dist/web/assets/jetbrains-mono-greek-500-normal-JpySY46c.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
- package/dist/web/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff +0 -0
- package/dist/web/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
- package/dist/web/assets/jetbrains-mono-latin-ext-500-normal-Cut-4mMH.woff2 +0 -0
- package/dist/web/assets/jetbrains-mono-latin-ext-500-normal-ckzbgY84.woff +0 -0
- package/dist/web/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
- package/dist/web/assets/jetbrains-mono-vietnamese-500-normal-DNRqzVM1.woff +0 -0
- package/dist/web/assets/knowledge-base-CMsi5KtZ.svg +1 -0
- package/dist/web/assets/markdown-GKy06efH.js +10 -0
- package/dist/web/assets/model-CGrmjuJz.svg +1 -0
- package/dist/web/assets/report-mkgMJOFK.svg +1 -0
- package/dist/web/assets/rotate-ccw-BL6YOAPy.js +1 -0
- package/dist/web/assets/rule-DycAnn4u.svg +1 -0
- package/dist/web/assets/search-YLg3uzAx.js +1 -0
- package/dist/web/assets/status-CL_clA0J.js +3 -0
- package/dist/web/assets/sticky-note-DIQ2FWMw.js +1 -0
- package/dist/web/assets/terminal-BdTFlGZR.js +1 -0
- package/dist/web/assets/timer-NLZ0XmVl.js +1 -0
- package/dist/web/assets/trace-YEplLreO.svg +1 -0
- package/dist/web/assets/trash-DIUJbRpw.js +1 -0
- package/dist/web/index.html +15 -0
- package/docs/ARCHITECTURE.md +4 -1
- package/docs/user-guide.html +10 -2
- package/forgeqe.example.yaml +37 -0
- package/package.json +3 -3
- package/prompts/test-agent.md +2 -0
- package/py/forgeqe_engine/capture.py +33 -7
- package/py/forgeqe_engine/logins.py +5 -0
- package/py/forgeqe_engine/memory.py +80 -4
- package/py/forgeqe_engine/service.py +41 -5
- package/py/forgeqe_engine/userlike.py +150 -0
- package/py/forgeqe_mobile/hyperexecute.py +1 -1
package/HOW_TO_USE.md
CHANGED
|
@@ -513,11 +513,17 @@ A card says which it did and why (*Extending PracticeTests.Flow · covers 12 of
|
|
|
513
513
|
|
|
514
514
|
**The same flow asked again.** When a session writes tests and you ask for a flow an earlier job already wrote a test for, ForgeQE runs that test first, before any browser run. If it passes in a real browser, that is the answer: no browser run, no Scribe, and no new test file, in the seconds the test takes (*✓ Existing test passed · 19s · no browser run or new test needed*). If it fails, the flow runs in the browser and Scribe updates that test instead of writing another. ForgeQE's agent rewords a goal a little each time, so goals count as the same flow when they share their content words (endings, case, and phrasing aside) and the new goal keeps everything the earlier one checked; the same steps with a different final check, a shorter flow, or another site are a new flow. The agent also compares the earlier goal with your request and runs fresh when you ask for a check the earlier test does not have. Ask for "a fresh run" or "a new test" to skip the reuse.
|
|
515
515
|
|
|
516
|
-
**
|
|
516
|
+
**The run as a test would do it.** The browser agent works through the same page a test meets, and the handoff tells Scribe everything it did on the way:
|
|
517
|
+
- A click on an element something covers (a confirmation after Add to cart, a pop-up) fails and names what covers it, so the agent closes it as a user would and that step is in the flow; the step after says what covered it, and "What covered the page before a click" lists them. The engine library would otherwise click the element from JavaScript, which a test cannot do. What it still does from a script (a click, typing to the page) is named on its step.
|
|
518
|
+
- Locators are the ones Playwright finds: no link role for an `<a>` without `href` (Chrome calls it a link, Playwright does not), icon-font characters kept out of names (a name with one becomes a `role_pattern`), and a control that repeats on every row or card gets a locator scoped to its row (`#product-1 a.cart_quantity_delete`).
|
|
519
|
+
- An element in a frame says which frame, and the replay reaches it through `frameLocator`. Advertisements (Google's full-page ads, ad frames) are marked, left out of the replay, and "Ads on these pages" says to block the ad hosts in the test instead of closing them.
|
|
520
|
+
- A suite case runs from the state its test starts from: without the saved logins' sessions, so the agent signs in as the test will (`suite.restore_sessions: true` keeps them; a login with no username and password to sign in with keeps its session, the only way in) and from the case's own start page (its URL, first step, description, or preconditions). When a run did start with saved sessions, "State the run started with" says so.
|
|
521
|
+
|
|
522
|
+
**When the flow cannot be reproduced.** If ForgeQE's own replay of the run could not reach the run's final page and Scribe's test fails too, Scribe is told where the replay stopped and what was open on the page, since that is usually a pop-up, consent banner or ad the browser agent closed, or state its browser already had (signed in, items in a cart), and gets another attempt to handle it. The job stops, saying which replayed step failed and why, only when the test then fails the same way again, instead of spending its remaining attempts on a flow no script can repeat as recorded.
|
|
517
523
|
|
|
518
524
|
**Why a test failed.** When ForgeQE's run of Scribe's test fails, the ✗ line and the next attempt say why in the test's own words: dotnet test's Error Message, pytest's `E` lines, or the error with its Expected and Received values (Playwright, Jest, JUnit), not the runner's summary line.
|
|
519
525
|
|
|
520
|
-
**Keeping Scribe's cost down.** ForgeQE reads the repository's test setup itself before Scribe starts (stack, settings files and their browser values, the test id attribute, base classes, page objects and their methods, one test command) and hands it over, so Scribe does not discover it with dozens of file reads. Each attempt after the first starts a fresh session from a summary of the job (handoff, files changed, what each attempt did, the latest failure), so later attempts cost about what the first did. `code.max_attempts` (default 3) and `code.max_tokens` (default 1,500,000; `0` turns it off) cap a job, and the token budget is checked during an attempt too, so one long attempt is stopped when the total passes it. The reviewer sorts its issues into correctness (the test does not test what the goal says, or not reliably) and coding standards (test data or credentials in a page object, naming, hard waits, leftovers). Coding standards never fail a test that works: it is accepted, and the coding agent gets one more round (not counted in `max_attempts`) to fix them; if that round breaks the test, ForgeQE puts back the version that passed and lists the standards issues in the notes (`code.tidy: false` skips the round). A test the reviewer rejects twice for correctness stops the job with its issues, since that usually means the test case and the page disagree. Under each step, the handoff shows that step's part of the page (its section and neighbours, from the replay's page snapshot) instead of whole snapshots. When a test fails, ForgeQE shows the failing element on the test's page at the failure and on the replay's page, so most failures are fixed without opening a browser. Scribe's live browser is switched on only when the same failure repeats, and it does not send a page snapshot after every click or keystroke. `code.max_steps` (default 50) caps the tool calls in one of Scribe's turns. `code.review_profile` runs the reviewer on a cheaper llms.json profile.
|
|
526
|
+
**Keeping Scribe's cost down.** ForgeQE reads the repository's test setup itself before Scribe starts (stack, settings files and their browser values, the test id attribute, base classes, page objects and their methods, one test command) and hands it over, so Scribe does not discover it with dozens of file reads. Each attempt after the first starts a fresh session from a summary of the job (handoff, files changed, what each attempt did, the latest failure), so later attempts cost about what the first did. The summary has a "Tried already, and did not work" list: for each failed attempt, what Scribe said it did (it reports each change in `tried`), how it failed, the locator the test was waiting for and the element that covered it and took the click, both read from the test's output, and whether an earlier attempt already failed on that locator. Scribe must not try those again in the same form and must say what it does differently. `forgeqe heal` keeps the same list across its attempts. `code.max_attempts` (default 3) and `code.max_tokens` (default 1,500,000; `0` turns it off) cap a job, and the token budget is checked during an attempt too, so one long attempt is stopped when the total passes it. The reviewer sorts its issues into correctness (the test does not test what the goal says, or not reliably) and coding standards (test data or credentials in a page object, naming, hard waits, leftovers). Coding standards never fail a test that works: it is accepted, and the coding agent gets one more round (not counted in `max_attempts`) to fix them; if that round breaks the test, ForgeQE puts back the version that passed and lists the standards issues in the notes (`code.tidy: false` skips the round). A test the reviewer rejects twice for correctness stops the job with its issues, since that usually means the test case and the page disagree. When a test passed and the reviewer sent it back, and the changes for the review then break it (or the attempts or the token budget run out first), ForgeQE puts back the version that passed: the result is passed but not approved, with the reviewer's issues in the notes, so you get a working test to finish instead of none. Under each step, the handoff shows that step's part of the page (its section and neighbours, from the replay's page snapshot) instead of whole snapshots. When a test fails, ForgeQE shows the failing element on the test's page at the failure and on the replay's page, so most failures are fixed without opening a browser. Scribe's live browser is switched on only when the same failure repeats, and it does not send a page snapshot after every click or keystroke. `code.max_steps` (default 50) caps the tool calls in one of Scribe's turns. `code.review_profile` runs the reviewer on a cheaper llms.json profile.
|
|
521
527
|
|
|
522
528
|
**Scribe's rulebook: the same mistake once.** When a job passes after a failed test run or a reviewer's change, Scribe's report gives up to three one-line rules that would have avoided the mistake ("Wait for the cart badge with toHaveText before clicking Checkout; it updates after a request"). ForgeQE keeps them in `.forgeqe/scribe-rules.json` in the repository, and every attempt of later jobs, and every healing session, starts with them. A lesson from a job that did not pass, or that passed at once, is not kept: only a fix that worked becomes a rule. The book stays small, since it is sent with each model call: at most 15 rules of one line each; a lesson learned again is merged into its rule (shown as "learned 3 times") instead of added; when it is full, the rule confirmed least and longest ago goes, and a rule not learned again for 180 days expires. The rules are the coding agent's own words, so a rule with a link, something like a token, a destructive command, or wording that tells an agent to drop its instructions is refused, and the agents are told they are hints that never override their instructions or the team's guardrails. Commit the file to share the rules with the team and see each change in review; edit or delete a rule there (the agents cannot change `.forgeqe`). ForgeQE says each new rule as it learns it (`Learned for next time: …`). `code.rulebook: false` turns it off.
|
|
523
529
|
|
|
@@ -1498,6 +1504,7 @@ forgeqe suite cases.yaml --no-code --no-write-back --out .forgeqe/reports/smoke
|
|
|
1498
1504
|
suite:
|
|
1499
1505
|
parallel: 1 # browsers at once
|
|
1500
1506
|
code: true # with a repo set, passed cases go to Scribe
|
|
1507
|
+
restore_sessions: false # true: each case starts signed in from the saved logins' sessions
|
|
1501
1508
|
out_dir: ./.forgeqe/reports/suites
|
|
1502
1509
|
```
|
|
1503
1510
|
|
package/README.md
CHANGED
|
@@ -27,6 +27,8 @@ Everything else is downloaded on first use into `~/.forgeqe/tools` (`%USERPROFIL
|
|
|
27
27
|
|
|
28
28
|
`forgeqe setup` does all of this up front; otherwise the first command that needs a piece fetches it. Upgrading is `forgeqe update`: it updates every `forgeqe` on PATH (bun, npm and pip installs) and waits while the registries catch up with a new release. A release that pins a newer Bun, agent runtime, uv or engine library downloads it on the next run and removes the old one. Deleting `~/.forgeqe` removes everything ForgeQE downloaded. Behind a proxy, set `HTTPS_PROXY`. The npm launcher's Bun download also needs `NODE_USE_ENV_PROXY=1` (Node 24+); on older Node, use the pip launcher or install Bun yourself.
|
|
29
29
|
|
|
30
|
+
**Coming from WebPilot** (`@capagents/webpilot`, ForgeQE's name before the rename): remove it first with `npm uninstall -g @capagents/webpilot`. npm refuses to install ForgeQE while the old package owns the `webpilot` command (`EEXIST ... npm\webpilot`). Your settings, sign-ins, `WEBPILOT_*` variables and `webpilot.yaml` files keep working. The npm package installs only the `forgeqe` command; the pip launcher still installs `webpilot` too. Install with `-g`, not with `npm install @capagents/forgeqe` inside a folder: `npx forgeqe` runs that folder copy, and `forgeqe update` does not change it (it prints how to replace it).
|
|
31
|
+
|
|
30
32
|
From this repo:
|
|
31
33
|
|
|
32
34
|
```bash
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
ForgeQE contains and installs the open source software below. Each is the work of its own authors and is used under its own licence, which is reproduced here as that licence asks. These notices are generated from the installed packages by `bun scripts/gen-notices.ts`; do not edit.
|
|
4
4
|
|
|
5
|
-
Most of these libraries are inside `dist/forgeqe.js`, the bundle ForgeQE ships; `@opentui/core` and its platform builds are installed beside it. axe-core (MPL-2.0) is shipped unmodified as `dist/vendor/axe.min.js`; its source is at the address given with it.
|
|
5
|
+
Most of these libraries are inside `dist/forgeqe.js`, the bundle ForgeQE ships; `@opentui/core` and its platform builds are installed beside it. axe-core (MPL-2.0) is shipped unmodified as `dist/vendor/axe.min.js`; its source is at the address given with it. The web app (`dist/web`) credits the libraries inside it in `dist/web/THIRD_PARTY_NOTICES.md`.
|
|
6
6
|
|
|
7
7
|
## Packages
|
|
8
8
|
|