@capagents/forgeqe 1.1.5 → 1.1.6

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 CHANGED
@@ -405,7 +405,7 @@ The chat gets a short summary and a card with both paths as links, and **Open th
405
405
  **The start screen.** Before your first request, the screen is one column under the logo:
406
406
 
407
407
  ```
408
- playwright-csharp-pom-framework · .NET · Azure DevOps · azure/gpt-5.4
408
+ playwright-csharp-pom-framework · .NET · Azure DevOps
409
409
 
410
410
  ┃ Describe what you want to test…
411
411
  ✦ Refine ctrl+r ⌕ Search ctrl+p ? shortcuts ctrl+c close
@@ -417,9 +417,10 @@ The chat gets a short summary and a card with both paths as links, and **Open th
417
417
  ▤ Report QI-Payments pipeline status report 18 min ago open
418
418
  ✓ Run Search hotels in Mumbai on booking.com 2 days ago open rerun
419
419
  Setup ▰▰▰▱▱ 3 of 5 · Domain and Notifications are not set up ▸ how to set up
420
+ ● Tip Press Tab to switch LLM profile azure/gpt-5.4 (default) · ForgeQE
420
421
  ```
421
422
 
422
- - The line under the logo is what ForgeQE works with here: the folder, what it is built with (from its files, such as a `.sln` or `playwright.config.ts`), the systems that are set up, and the model.
423
+ - The line under the logo is what ForgeQE works with here: the folder, what it is built with (from its files, such as a `.sln` or `playwright.config.ts`), the systems that are set up. The model and its profile are in the footer, the status line on every screen; Tab switches the profile.
423
424
  - The prompt starts five rows high and grows with a long request, up to nearly half the screen, before it scrolls; the sections below give way, last first, to make room.
424
425
  - **Start with** offers up to four things to ask, from the capabilities that work in this setup, each with an example in the words of your setup. Click one, or press Alt-1 to Alt-4, to put it in the prompt to adjust and send.
425
426
  - In a folder without `forgeqe.yaml`, or without a live model, the line under the logo says so and **Get started** takes its place: **Set up ForgeQE in this folder** (runs `/init`), **Add a model**, and **Sign in to Azure DevOps or Jira** (runs `/auth`). Start ForgeQE in your test project's folder to work with its settings.
@@ -443,26 +444,29 @@ The chat gets a short summary and a card with both paths as links, and **Open th
443
444
  ⏺ No classic releases exist in any of the seven projects.
444
445
  …
445
446
 
446
- ⠹ Thinking… (24s · 57.4K tokens · esc to interrupt)
447
+ ⠹ Acting in the browser (step 3)… (24s · step 3/40 · 57.4K tokens · esc to interrupt)
447
448
  ╭──────────────────────────────────────────────────────────╮
448
449
  │ > Ask ForgeQE… (/ for commands, @ to reference a run…) │
449
450
  ╰──────────────────────────────────────────────────────────╯
450
451
  ✦ Refine ctrl+r ⌕ Search ctrl+p ▦ Panels ctrl+o ctrl+c close
451
- ~/playwright-csharp-pom-framework azure/gpt-5.4 · 57.4K tokens · ForgeQE
452
+ ~/playwright-csharp-pom-framework azure/gpt-5.4 (default) · 57.4K tokens · ForgeQE
452
453
  ```
453
454
 
454
455
  - `>` is what you asked. `⏺` starts each reply, tool call, browser run, test case, and result; calls in a row sit together, with the arguments dimmed. What came of a call is indented under it after `⎿`: the agent's notes, each browser step and its actions (✓ or ✗), and a result's details.
455
- - While a request runs, one line above the input says what is happening, for how long, and with how many tokens. The footer is the status line: the model and what the session used. Prices are not shown in the conversation; reports and `forgeqe models` have them.
456
+ - While a request runs, one line above the input says what is happening, for how long, how far a browser run or suite has got, and with how many tokens. The footer is the status line, and the one place for the folder, the model and its profile, and what the session used.
457
+ - PgUp and PgDn scroll the conversation from the prompt (the mouse wheel works too); PgDn back at the end follows new lines again.
458
+ - A long request you sent (a refined one, a pasted spec) shows its first lines and *… 27 more lines, sent in full*. Prices are not shown in the conversation; reports and `forgeqe models` have them.
456
459
  - A result that made nothing (a run that only looked something up) adds no card.
457
460
 
458
- **The panels.** **▦ Panels** (Ctrl-O) opens the session, plan, activity, files, context, and tokens panels beside the conversation on a terminal 120 columns wide or more, or in its place on a narrower one; Ctrl-O again, or **✕ Close**, closes them:
461
+ **The panels.** **▦ Panels** (Ctrl-O) splits the screen in half on a terminal 120 columns wide or more: the **Activities** column on the right, and the conversation with the files, context, and tokens panels on the left. On a narrower terminal the panels take the conversation's place. Ctrl-O again, or **✕ Close**, closes them.
459
462
 
460
- - the status line, with who is working, for how long, a progress bar for the plan or a suite's cases, and **■ Stop**;
461
- - **Plan**: the agent's to-do list, then each browser step or suite case with ✓, ✗ and why, ◐ running;
462
- - **Activity**: every tool call, browser step, and the agents' reasoning;
463
- - **Files**: each file read ◉, written ✚, or edited ✎, newest first;
464
- - **Context**: how full the model's context window is, and the skills, product knowledge, domain, and MCP servers in it;
465
- - **Tokens**: total, input, output, cached.
463
+ The Activities column shows what the agents do as they do it:
464
+
465
+ - the status line: who is working, a progress bar for the plan or a suite's cases, for how long, and **■ Stop**; under it, the whole width, what is happening now (*Agent: Azure DevOps API · QI-Payments/_apis/build/builds…*);
466
+ - **Plan**: the agent's own task list as soon as it writes one, then each browser step or suite case: ○ pending, ◐ in progress, ✓ done, ✗ failed and why. ForgeQE's agent writes a plan for any request of three steps or more and updates it as it goes;
467
+ - **Activity**: **Now** (the task in progress) and **Next** (the next task), then every tool call, browser step, and note. A call shows ◐ the moment it starts and becomes ✓ or ✗ in the same row when it ends, so a long API query or test run is never invisible. Reads and searches that the conversation leaves out at the brief detail level are listed here. A call takes one row and a note up to three; focus the panel to scroll through everything or filter it.
468
+
469
+ Over the conversation: **Files** (each file read ◉, written ✚, or edited ✎, newest first), **Context** (how full the model's context window is, and the skills, product knowledge, domain, and MCP servers in it), and **Tokens** (total, input, output, cached). When that half is under 80 columns they fold into one line: *Files 4 (1 changed) · Context 26% · Skills 2 · 52.9K tokens*.
466
470
 
467
471
  **Buttons.** Under the input: **✦ Refine** (Ctrl-R; it fills in once there is text to refine), **⌕ Search** (Ctrl-P, the command palette), and **▦ Panels** (Ctrl-O); while a request runs, **■ Stop** (Esc) takes Refine's place. With the panels open, **▦ Focus panels** (Shift-Tab) and **✕ Close** (Ctrl-O) are in their status line. On a narrow terminal, **◧ Details** (Ctrl-O) and **⇄ Profile** (Tab) are under the input. Each is clickable.
468
472
 
@@ -502,7 +506,7 @@ Summary: Show the deployed build in each environment, and why each deployment fa
502
506
 
503
507
  Refine is one model session of its own, separate from the conversation: a few model steps (usually two) and read-only tool calls, typically 15K–25K tokens and 20–30 seconds. The panel title shows what it cost and how much of the request keeps the ASD-STE100 rules (*✦ Refined request · STE 100% · 20.8K tokens · 21s*), and its tokens count in the session total in the footer.
504
508
 
505
- A read-only agent writes it. It starts knowing every capability and whether it works in this setup, and the domain; it checks names and ids in the systems that are set up (work items, test plans, pipelines, sprints, recent runs). The panel shows the request with what it **checked** ✓, what it **assumed** ~, and what is **missing** ? (for example "Which story? Give the work item id"); a capability that is not set up shows as missing too. Enter sends it, `e` puts it in the prompt to edit, Esc keeps yours. Refine never runs anything, writes files, or changes a work item; it never invents an id, URL, project, or file.
509
+ A read-only agent writes it. It starts knowing every capability and whether it works in this setup, and the domain; it checks names and ids in the systems that are set up (work items, test plans, pipelines, sprints, recent runs). The panel shows the request with what it **checked** ✓, what it **assumed** ~, and what is **missing** ? (for example "Which story? Give the work item id"); a capability that is not set up shows as missing too. What is missing comes first, and the title counts it (*✦ Refined request · 2 to answer*). A refined request longer than the screen scrolls inside the panel with ↑/↓ and PgUp/PgDn (the border says so); the title and the **Use refined**, **Edit**, and **Keep mine** buttons stay on screen. ←/→ or Tab picks one, Enter does it; `e` puts the request in the prompt to edit, Esc keeps yours. Refine never runs anything, writes files, or changes a work item; it never invents an id, URL, project, or file.
506
510
 
507
511
  **Next steps.** When a request finishes, up to three suggestions appear above the prompt: from what it produced (*Open the report*, *Write a test for this run*, *Why did it fail?*, *Rerun the cases that failed*) and from the agent's answer, which suggests the follow-ups you are likely to want (*Write a release report*, *Show the failed CD logs*). Click one or press Alt-1 to Alt-3; suggestions that start work are put in the prompt first, to adjust and send.
508
512
 
@@ -511,6 +515,7 @@ A read-only agent writes it. It starts knowing every capability and whether it w
511
515
  | Enter | Send the message or command |
512
516
  | Tab | Next LLM profile from `llms.json`; the conversation carries over to the new model. While `/` or `@` suggestions show, completes the selected one |
513
517
  | Shift-Tab | Move between the chat and the Plan, Activity, and Files panels |
518
+ | PgUp / PgDn | Scroll the conversation |
514
519
  | Ctrl-P | Command palette |
515
520
  | Ctrl-R | Refine the request in the prompt |
516
521
  | Ctrl-O | Open or close the panels (beside the conversation, or in its place on a narrow terminal) |
@@ -632,7 +637,7 @@ What happens after the run passes:
632
637
  4. It writes the test from the handoff and the replay script: steps that worked are ported with their locators, steps that failed are fixed first. Every locator, including those for assertions, comes from the replay script, the page snapshots, page memory, or a check on the page; steps where the browser agent ran JavaScript to look around are left out. It does not walk the flow again or build tests to explore. Once a step fails (in the replay, or in its test), ForgeQE switches on its live browser: a Chrome that Playwright drives, set up like ForgeQE's, where it looks at the failing step's page one tool call per action (open, snapshot, click, type, wait, screenshot, run JavaScript, console errors, failed requests). Until then the live browser tools are off, so no tokens go into looking at pages that work. The live browser needs Node.js (`npx`), and Microsoft's Playwright MCP server is downloaded on first use; with `live_browser: false`, or without `npx`, it looks with a small throwaway script instead. When its browser gets a different page than ForgeQE's did (an error, a challenge, a control that will not open), it compares the two browsers (user agent, `navigator.webdriver`, headless, failed requests and CORS errors, headers the framework adds, console errors) and fixes the difference in the repo's browser configuration. It never judges the site with `curl` or `webfetch`.
633
638
  5. Scribe does not run the test itself: it may build or compile, then reports the test file and the command that runs only that test, and ForgeQE runs it. If one command it runs fails `stall_after` times in a row within its work (the same build again and again, say), ForgeQE stops that turn and sends the command and its last output back, asking it to change approach. If the same command stalls again, the job stops as a failure with that output in the notes.
634
639
  6. ForgeQE runs that command (with `CI=1`) and checks the exit code, and it watches the processes the command starts for a browser launched by Playwright, Puppeteer, Selenium, or Cypress. On a failure it sends the command, exit code, and output back to Scribe. The output is kept short so the error is never cut off: the page dump Playwright puts into a failed assertion ("Aria snapshot:", often thousands of lines) is taken out and saved as `<run>/test-runs/attempt-N-page.aria.yml`, then the start (where the first error and its stack trace are) and the end (the summary) are sent; the full output is in `<run>/test-runs/attempt-N.log`, and the prompt names both files. A command that exits 0 without starting a browser also goes back: the test must drive the app in a browser. If the repo's browser runs on another machine (Selenium Grid, a cloud service, a container), the agent says where and the check is skipped.
635
- 7. A passing test then goes to a separate reviewer agent, which can read files and `git diff` but not change anything. It checks the change against the goal and the test rules: every part of the goal done through the page and asserted, generic page objects with data in the test, no values or URLs copied from the run, browser settings in the repo's configuration, no leftover files. The changed files come inline in its prompt, so it reads nothing again, and it does not ask to replace locators or texts that came from the replay or the checks, since those matched the live site. It judges only what this job changed: ForgeQE records the working tree before the job, so your uncommitted edits, your untracked files, and ForgeQE's own files (`.forgeqe/`, `forgeqe.yaml`, `llms.json`) are never part of the review. It gets the outlines of the classes the changed code uses, the repo's browser settings, and the same `code_*` tools, so it checks reuse and settings without reading those files. The code graph also tells it what the job added that it can check in the code: a new member that locates an element an existing member already locates (to reuse instead), and new XPath or position-based locators. If it finds problems, they go back to Scribe as the next attempt.
640
+ 7. A passing test then goes to a separate reviewer agent, which can read files and `git diff` but not change anything. It checks the change against the goal and the test rules: every part of the goal done through the page and asserted, generic page objects with data in the test, no values or URLs copied from the run, browser settings in the repo's configuration, no leftover files. The changed files come inline in its prompt, so it reads nothing again, and it does not ask to replace locators or texts that came from the replay or the checks, since those matched the live site. It judges only what this job changed: ForgeQE records the working tree before the job, so your uncommitted edits, your untracked files, and ForgeQE's own files (`.forgeqe/`, `forgeqe.yaml`, `llms.json`) are never part of the review. It checks the diff of every file that existed before the job: removing or rewriting an existing test, even a commented-out one, is a correctness problem. Credentials come from the environment, except a public demo login that the application itself shows to anyone (such as the logins on saucedemo.com's sign-in page), which may stay in the repo's test data. It gets the outlines of the classes the changed code uses, the repo's browser settings, and the same `code_*` tools, so it checks reuse and settings without reading those files. The code graph also tells it what the job added that it can check in the code: a new member that locates an element an existing member already locates (to reuse instead), and new XPath or position-based locators. If it finds problems, they go back to Scribe as the next attempt.
636
641
 
637
642
  Scribe cannot edit ForgeQE's files or run folders, and cannot run `git clean`, `git reset --hard`, `git stash`, `git restore`, or `git checkout -- <path>`. If it still removes a file that existed before the job, or reverts your uncommitted edits, ForgeQE puts the file back after that attempt and tells the agent.
638
643
  8. The job is done when ForgeQE's run passes with a browser and the reviewer approves. It stops as a failure after `max_attempts` attempts, when the job passes `code.max_tokens`, when the reviewer rejects a passing test twice, if the review cannot finish, when the test fails the same way three times in a row (the same output apart from numbers such as timings and line numbers; the second time, Scribe is told its change did not change the failure and to look at the failing step before changing code), or straight away on an auth, API, or context-limit error from the model.
@@ -664,7 +664,7 @@ Add a GitHub Actions workflow that runs tests/cases.yaml on every PR, and make i
664
664
  <p>The text is the agent's own result. Failed runs show <code>✗ Task failed</code> with the reason, and stopped runs show <code>■ Run stopped</code>. <code>forgeqe run</code> prints the same summary at the end.</p>
665
665
  </div>
666
666
  <section class="doc sub" id="doc-how_to_use-the-screen"><h4>The screen</h4><div class="prose"><p><strong>The start screen.</strong> Before your first request, the screen is one column under the logo:</p>
667
- <pre><code> playwright-csharp-pom-framework · .NET · Azure DevOps · azure/gpt-5.4
667
+ <pre><code> playwright-csharp-pom-framework · .NET · Azure DevOps
668
668
 
669
669
  ┃ Describe what you want to test…
670
670
  ✦ Refine ctrl+r ⌕ Search ctrl+p ? shortcuts ctrl+c close
@@ -676,9 +676,10 @@ Add a GitHub Actions workflow that runs tests/cases.yaml on every PR, and make i
676
676
  ▤ Report QI-Payments pipeline status report 18 min ago open
677
677
  ✓ Run Search hotels in Mumbai on booking.com 2 days ago open rerun
678
678
  Setup ▰▰▰▱▱ 3 of 5 · Domain and Notifications are not set up ▸ how to set up
679
+ ● Tip Press Tab to switch LLM profile azure/gpt-5.4 (default) · ForgeQE
679
680
  </code></pre>
680
681
  <ul>
681
- <li>The line under the logo is what ForgeQE works with here: the folder, what it is built with (from its files, such as a <code>.sln</code> or <code>playwright.config.ts</code>), the systems that are set up, and the model.</li>
682
+ <li>The line under the logo is what ForgeQE works with here: the folder, what it is built with (from its files, such as a <code>.sln</code> or <code>playwright.config.ts</code>), the systems that are set up. The model and its profile are in the footer, the status line on every screen; Tab switches the profile.</li>
682
683
  <li>The prompt starts five rows high and grows with a long request, up to nearly half the screen, before it scrolls; the sections below give way, last first, to make room.</li>
683
684
  <li><strong>Start with</strong> offers up to four things to ask, from the capabilities that work in this setup, each with an example in the words of your setup. Click one, or press Alt-1 to Alt-4, to put it in the prompt to adjust and send.</li>
684
685
  <li>In a folder without <code>forgeqe.yaml</code>, or without a live model, the line under the logo says so and <strong>Get started</strong> takes its place: <strong>Set up ForgeQE in this folder</strong> (runs <code>/init</code>), <strong>Add a model</strong>, and <strong>Sign in to Azure DevOps or Jira</strong> (runs <code>/auth</code>). Start ForgeQE in your test project's folder to work with its settings.</li>
@@ -700,27 +701,28 @@ Add a GitHub Actions workflow that runs tests/cases.yaml on every PR, and make i
700
701
  ⏺ No classic releases exist in any of the seven projects.
701
702
  …
702
703
 
703
- ⠹ Thinking… (24s · 57.4K tokens · esc to interrupt)
704
+ ⠹ Acting in the browser (step 3)… (24s · step 3/40 · 57.4K tokens · esc to interrupt)
704
705
  ╭──────────────────────────────────────────────────────────╮
705
706
  │ &gt; Ask ForgeQE… (/ for commands, @ to reference a run…) │
706
707
  ╰──────────────────────────────────────────────────────────╯
707
708
  ✦ Refine ctrl+r ⌕ Search ctrl+p ▦ Panels ctrl+o ctrl+c close
708
- ~/playwright-csharp-pom-framework azure/gpt-5.4 · 57.4K tokens · ForgeQE
709
+ ~/playwright-csharp-pom-framework azure/gpt-5.4 (default) · 57.4K tokens · ForgeQE
709
710
  </code></pre>
710
711
  <ul>
711
712
  <li><code>&gt;</code> is what you asked. <code>⏺</code> starts each reply, tool call, browser run, test case, and result; calls in a row sit together, with the arguments dimmed. What came of a call is indented under it after <code>⎿</code>: the agent's notes, each browser step and its actions (✓ or ✗), and a result's details.</li>
712
- <li>While a request runs, one line above the input says what is happening, for how long, and with how many tokens. The footer is the status line: the model and what the session used. Prices are not shown in the conversation; reports and <code>forgeqe models</code> have them.</li>
713
+ <li>While a request runs, one line above the input says what is happening, for how long, how far a browser run or suite has got, and with how many tokens. The footer is the status line, and the one place for the folder, the model and its profile, and what the session used.</li>
714
+ <li>PgUp and PgDn scroll the conversation from the prompt (the mouse wheel works too); PgDn back at the end follows new lines again.</li>
715
+ <li>A long request you sent (a refined one, a pasted spec) shows its first lines and <em>… 27 more lines, sent in full</em>. Prices are not shown in the conversation; reports and <code>forgeqe models</code> have them.</li>
713
716
  <li>A result that made nothing (a run that only looked something up) adds no card.</li>
714
717
  </ul>
715
- <p><strong>The panels.</strong> <strong>▦ Panels</strong> (Ctrl-O) opens the session, plan, activity, files, context, and tokens panels beside the conversation on a terminal 120 columns wide or more, or in its place on a narrower one; Ctrl-O again, or <strong>✕ Close</strong>, closes them:</p>
718
+ <p><strong>The panels.</strong> <strong>▦ Panels</strong> (Ctrl-O) splits the screen in half on a terminal 120 columns wide or more: the <strong>Activities</strong> column on the right, and the conversation with the files, context, and tokens panels on the left. On a narrower terminal the panels take the conversation's place. Ctrl-O again, or <strong>✕ Close</strong>, closes them.</p>
719
+ <p>The Activities column shows what the agents do as they do it:</p>
716
720
  <ul>
717
- <li>the status line, with who is working, for how long, a progress bar for the plan or a suite's cases, and <strong>■ Stop</strong>;</li>
718
- <li><strong>Plan</strong>: the agent's to-do list, then each browser step or suite case with ✓, ✗ and why, ◐ running;</li>
719
- <li><strong>Activity</strong>: every tool call, browser step, and the agents' reasoning;</li>
720
- <li><strong>Files</strong>: each file read ◉, written ✚, or edited ✎, newest first;</li>
721
- <li><strong>Context</strong>: how full the model's context window is, and the skills, product knowledge, domain, and MCP servers in it;</li>
722
- <li><strong>Tokens</strong>: total, input, output, cached.</li>
721
+ <li>the status line: who is working, a progress bar for the plan or a suite's cases, for how long, and <strong>■ Stop</strong>; under it, the whole width, what is happening now (<em>Agent: Azure DevOps API · QI-Payments/_apis/build/builds…</em>);</li>
722
+ <li><strong>Plan</strong>: the agent's own task list as soon as it writes one, then each browser step or suite case: ○ pending, ◐ in progress, ✓ done, ✗ failed and why. ForgeQE's agent writes a plan for any request of three steps or more and updates it as it goes;</li>
723
+ <li><strong>Activity</strong>: <strong>Now</strong> (the task in progress) and <strong>Next</strong> (the next task), then every tool call, browser step, and note. A call shows ◐ the moment it starts and becomes ✓ or ✗ in the same row when it ends, so a long API query or test run is never invisible. Reads and searches that the conversation leaves out at the brief detail level are listed here. A call takes one row and a note up to three; focus the panel to scroll through everything or filter it.</li>
723
724
  </ul>
725
+ <p>Over the conversation: <strong>Files</strong> (each file read ◉, written ✚, or edited ✎, newest first), <strong>Context</strong> (how full the model's context window is, and the skills, product knowledge, domain, and MCP servers in it), and <strong>Tokens</strong> (total, input, output, cached). When that half is under 80 columns they fold into one line: <em>Files 4 (1 changed) · Context 26% · Skills 2 · 52.9K tokens</em>.</p>
724
726
  <p><strong>Buttons.</strong> Under the input: <strong>✦ Refine</strong> (Ctrl-R; it fills in once there is text to refine), <strong>⌕ Search</strong> (Ctrl-P, the command palette), and <strong>▦ Panels</strong> (Ctrl-O); while a request runs, <strong>■ Stop</strong> (Esc) takes Refine's place. With the panels open, <strong>▦ Focus panels</strong> (Shift-Tab) and <strong>✕ Close</strong> (Ctrl-O) are in their status line. On a narrow terminal, <strong>◧ Details</strong> (Ctrl-O) and <strong>⇄ Profile</strong> (Tab) are under the input. Each is clickable.</p>
725
727
  <p><strong>Replies.</strong> The agent's answers lead with the answer, then short headed sections; lists keep their bullets in a column, so a wrapped line stays under its text instead of running back to the margin.</p>
726
728
  <p><strong>Moving between panels.</strong> With the panels open, Shift-Tab (or a click) moves the keys from the prompt to Plan, Activity, then Files; the focused panel's border lights up and shows its keys. Esc, or typing, goes back to the prompt.</p>
@@ -752,7 +754,7 @@ Output format: One section for each project, with a line for each environment: t
752
754
  Summary: Show the deployed build in each environment, and why each deployment failed.
753
755
  </code></pre>
754
756
  <p>Refine is one model session of its own, separate from the conversation: a few model steps (usually two) and read-only tool calls, typically 15K–25K tokens and 20–30 seconds. The panel title shows what it cost and how much of the request keeps the ASD-STE100 rules (<em>✦ Refined request · STE 100% · 20.8K tokens · 21s</em>), and its tokens count in the session total in the footer.</p>
755
- <p>A read-only agent writes it. It starts knowing every capability and whether it works in this setup, and the domain; it checks names and ids in the systems that are set up (work items, test plans, pipelines, sprints, recent runs). The panel shows the request with what it <strong>checked</strong> ✓, what it <strong>assumed</strong> ~, and what is <strong>missing</strong> ? (for example &quot;Which story? Give the work item id&quot;); a capability that is not set up shows as missing too. Enter sends it, <code>e</code> puts it in the prompt to edit, Esc keeps yours. Refine never runs anything, writes files, or changes a work item; it never invents an id, URL, project, or file.</p>
757
+ <p>A read-only agent writes it. It starts knowing every capability and whether it works in this setup, and the domain; it checks names and ids in the systems that are set up (work items, test plans, pipelines, sprints, recent runs). The panel shows the request with what it <strong>checked</strong> ✓, what it <strong>assumed</strong> ~, and what is <strong>missing</strong> ? (for example &quot;Which story? Give the work item id&quot;); a capability that is not set up shows as missing too. What is missing comes first, and the title counts it (<em>✦ Refined request · 2 to answer</em>). A refined request longer than the screen scrolls inside the panel with ↑/↓ and PgUp/PgDn (the border says so); the title and the <strong>Use refined</strong>, <strong>Edit</strong>, and <strong>Keep mine</strong> buttons stay on screen. ←/→ or Tab picks one, Enter does it; <code>e</code> puts the request in the prompt to edit, Esc keeps yours. Refine never runs anything, writes files, or changes a work item; it never invents an id, URL, project, or file.</p>
756
758
  <p><strong>Next steps.</strong> When a request finishes, up to three suggestions appear above the prompt: from what it produced (<em>Open the report</em>, <em>Write a test for this run</em>, <em>Why did it fail?</em>, <em>Rerun the cases that failed</em>) and from the agent's answer, which suggests the follow-ups you are likely to want (<em>Write a release report</em>, <em>Show the failed CD logs</em>). Click one or press Alt-1 to Alt-3; suggestions that start work are put in the prompt first, to adjust and send.</p>
757
759
  <div class="tbl"><table>
758
760
  <thead>
@@ -762,6 +764,7 @@ Summary: Show the deployed build in each environment, and why each deployment fa
762
764
  <tr><td>Enter</td><td>Send the message or command</td></tr>
763
765
  <tr><td>Tab</td><td>Next LLM profile from <code>llms.json</code>; the conversation carries over to the new model. While <code>/</code> or <code>@</code> suggestions show, completes the selected one</td></tr>
764
766
  <tr><td>Shift-Tab</td><td>Move between the chat and the Plan, Activity, and Files panels</td></tr>
767
+ <tr><td>PgUp / PgDn</td><td>Scroll the conversation</td></tr>
765
768
  <tr><td>Ctrl-P</td><td>Command palette</td></tr>
766
769
  <tr><td>Ctrl-R</td><td>Refine the request in the prompt</td></tr>
767
770
  <tr><td>Ctrl-O</td><td>Open or close the panels (beside the conversation, or in its place on a narrow terminal)</td></tr>
@@ -1299,7 +1302,7 @@ Acceptance criteria:
1299
1302
  <p>ForgeQE runs that command (with <code>CI=1</code>) and checks the exit code, and it watches the processes the command starts for a browser launched by Playwright, Puppeteer, Selenium, or Cypress. On a failure it sends the command, exit code, and output back to Scribe. The output is kept short so the error is never cut off: the page dump Playwright puts into a failed assertion (&quot;Aria snapshot:&quot;, often thousands of lines) is taken out and saved as <code>&lt;run&gt;/test-runs/attempt-N-page.aria.yml</code>, then the start (where the first error and its stack trace are) and the end (the summary) are sent; the full output is in <code>&lt;run&gt;/test-runs/attempt-N.log</code>, and the prompt names both files. A command that exits 0 without starting a browser also goes back: the test must drive the app in a browser. If the repo's browser runs on another machine (Selenium Grid, a cloud service, a container), the agent says where and the check is skipped.</p>
1300
1303
  </li>
1301
1304
  <li>
1302
- <p>A passing test then goes to a separate reviewer agent, which can read files and <code>git diff</code> but not change anything. It checks the change against the goal and the test rules: every part of the goal done through the page and asserted, generic page objects with data in the test, no values or URLs copied from the run, browser settings in the repo's configuration, no leftover files. The changed files come inline in its prompt, so it reads nothing again, and it does not ask to replace locators or texts that came from the replay or the checks, since those matched the live site. It judges only what this job changed: ForgeQE records the working tree before the job, so your uncommitted edits, your untracked files, and ForgeQE's own files (<code>.forgeqe/</code>, <code>forgeqe.yaml</code>, <code>llms.json</code>) are never part of the review. It gets the outlines of the classes the changed code uses, the repo's browser settings, and the same <code>code_*</code> tools, so it checks reuse and settings without reading those files. The code graph also tells it what the job added that it can check in the code: a new member that locates an element an existing member already locates (to reuse instead), and new XPath or position-based locators. If it finds problems, they go back to Scribe as the next attempt.</p>
1305
+ <p>A passing test then goes to a separate reviewer agent, which can read files and <code>git diff</code> but not change anything. It checks the change against the goal and the test rules: every part of the goal done through the page and asserted, generic page objects with data in the test, no values or URLs copied from the run, browser settings in the repo's configuration, no leftover files. The changed files come inline in its prompt, so it reads nothing again, and it does not ask to replace locators or texts that came from the replay or the checks, since those matched the live site. It judges only what this job changed: ForgeQE records the working tree before the job, so your uncommitted edits, your untracked files, and ForgeQE's own files (<code>.forgeqe/</code>, <code>forgeqe.yaml</code>, <code>llms.json</code>) are never part of the review. It checks the diff of every file that existed before the job: removing or rewriting an existing test, even a commented-out one, is a correctness problem. Credentials come from the environment, except a public demo login that the application itself shows to anyone (such as the logins on saucedemo.com's sign-in page), which may stay in the repo's test data. It gets the outlines of the classes the changed code uses, the repo's browser settings, and the same <code>code_*</code> tools, so it checks reuse and settings without reading those files. The code graph also tells it what the job added that it can check in the code: a new member that locates an element an existing member already locates (to reuse instead), and new XPath or position-based locators. If it finds problems, they go back to Scribe as the next attempt.</p>
1303
1306
  <p>Scribe cannot edit ForgeQE's files or run folders, and cannot run <code>git clean</code>, <code>git reset --hard</code>, <code>git stash</code>, <code>git restore</code>, or <code>git checkout -- &lt;path&gt;</code>. If it still removes a file that existed before the job, or reverts your uncommitted edits, ForgeQE puts the file back after that attempt and tells the agent.</p>
1304
1307
  </li>
1305
1308
  <li>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capagents/forgeqe",
3
- "version": "1.1.5",
3
+ "version": "1.1.6",
4
4
  "description": "ForgeQE: a browser agent CLI that runs goals and test cases in local Chrome or Chromium, or BrowserStack and TestMu AI/LambdaTest when configured, and turns passing runs into tests in your repo",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/prompts/brain.md CHANGED
@@ -112,6 +112,7 @@ Read data from Azure DevOps, Jira, Xray, Confluence, and other systems in this s
112
112
  - You MUST stay in the working directory. You MAY also read the run and memory folders of ForgeQE.
113
113
  - A status alone is not an answer. When a result is "failed", empty, or "none found", you MUST give the cause and the next action that fixes it.
114
114
  - You MUST NOT promise a thing that the capability list does not say.
115
+ - When a request needs three steps or more, you MUST write your plan with todowrite before the first step. Each task is one short sentence. Keep one task in_progress. Mark a task completed immediately when it is done, and write the list again when the plan changes. The user sees this plan while you work.
115
116
 
116
117
  ### Deciding
117
118
  - You MUST select the source from what the user says and from the configured systems below.
@@ -60,6 +60,7 @@ Code:
60
60
  - You MUST use and extend the page objects, fixtures, helpers, test data, and configuration of the repository, in its style.
61
61
  - When the repository has no test setup, you MUST add Playwright Test with TypeScript in the standard layout.
62
62
  - You MUST NOT put secrets in the code. You MUST read them from the environment variables that the handoff names.
63
+ - A public demo login is the one exception: a user name and password that the application itself shows to anyone, such as the logins on the sign-in page of a demo site (saucedemo.com). Such a login MAY follow the convention of the repository for test data. The page snapshots of the run show whether the application publishes it.
63
64
  - You MAY change all that the test needs, including the configuration and the dependencies.
64
65
 
65
66
  Running:
@@ -18,7 +18,7 @@ A test is approved only when all these conditions are true:
18
18
  - It does the steps of the verified run through the controls of the page, with the values that the goal names.
19
19
  - It has an assertion for each result that the goal tells it to check. When the browser agent listed checks, use them.
20
20
  - It follows the test rules below. Page objects are generic, the data is in the test, and the assertions are true on each run.
21
- - It does not copy live values (prices, counts) or URLs from the run. It reads secrets from the environment. It does not read ForgeQE files.
21
+ - It does not copy live values (prices, counts) or URLs from the run. It reads secrets from the environment, except a public demo login (below). It does not read ForgeQE files.
22
22
  - Changes to the browser and the framework are in the configuration or the shared setup. They apply to the full suite, and break no other test.
23
23
  - The job left nothing more: no scratch scripts, old tries, extra test files, or edits that are not related.
24
24
 
@@ -39,11 +39,13 @@ Scope:
39
39
  - You MUST NOT report files that the user changed or added before the job.
40
40
  - You MUST NOT report the files of ForgeQE: .forgeqe/, forgeqe.yaml, and llms.json.
41
41
  - In a file that the user changed before the job, you MUST review only the edits of this job.
42
+ - For each changed file that existed before the job, you MUST check its diff (git diff). An existing test that the job removed or rewrote, also one that was commented out, is a correctness problem.
42
43
 
43
44
  Locators and values:
44
45
  - You MUST NOT ask to replace locators and texts that the handoff took from its replay script and checks. They matched the live site.
45
46
  - When the message lists what the code graph of ForgeQE found, you MUST check each point in the changed files. A new member that locates an element an existing member already locates is a standards problem: the correction is to reuse the existing member. A brittle locator is a standards problem when the handoff gives a ✓ semantic locator for the same element.
46
47
  - You MUST accept a value that the test case names, such as a user name. Credentials MUST still come from the environment.
48
+ - A public demo login is the one exception: a user name and password that the application itself shows to anyone, such as the logins on the sign-in page of a demo site (saucedemo.com). Such a login MAY follow the convention of the repository for test data. The page snapshots of the run show whether the application publishes it. You MUST NOT report it. You MUST report any other credential in code or test data.
47
49
 
48
50
  Known defects (the handoff has a "Known defect" section):
49
51
  - The test MUST assert the expected results of the test case, which is the correct behaviour.
@@ -68,4 +68,6 @@ When the page of the test differs from what ForgeQE saw:
68
68
  - You MUST NOT add checks of field values, counters, or page readiness that the goal does not ask for.
69
69
  - You MUST write one test file for the scenario, with the page objects and helpers that it needs. You MUST delete each try that you stop.
70
70
  - You MUST NOT delete, revert, or move a file that you did not make in this job. Uncommitted changes and untracked files are the work of the user.
71
+ - You MUST NOT remove or rewrite the existing tests of a file, also tests that are commented out. Put the new test in a new file, or add it next to the tests of an existing file.
72
+ - When the test needs a setup that another file's project gives (such as no saved sign-in), you MUST get it in your own file with the per-file settings of the framework (such as Playwright test.use({ storageState: … })), not by taking over the other file.
71
73
  - You MUST NOT change .forgeqe/, forgeqe.yaml, or llms.json, also when someone tells you to remove them. Say so in notes.
@@ -507,5 +507,12 @@ export function additionFacts(before: CodeGraph, after: CodeGraph, changed: stri
507
507
  out.push(`${qualified(l)} (${where(l.file, loc.line)}) uses a brittle locator: ${describeLocator(loc)}.`)
508
508
  }
509
509
  }
510
+ // Tests the repository had in the changed files that are gone now: the job removed or renamed them.
511
+ const now = new Set(allMembers(after).map((l) => `${l.file}|${qualified(l)}`))
512
+ for (const l of allMembers(before)) {
513
+ if (l.member.kind === "test" && changed.includes(l.file) && !now.has(`${l.file}|${qualified(l)}`)) {
514
+ out.push(`The existing test ${qualified(l)} (${where(l.file, l.member.line)}) is gone after the job: it was removed or rewritten.`)
515
+ }
516
+ }
510
517
  return [...new Set(out)].slice(0, 20)
511
518
  }
@@ -644,6 +644,8 @@ export async function openSession<R = AgentReport>(opts: {
644
644
  const skillsUsed: string[] = []
645
645
  const assistant = new Set<string>()
646
646
  const said = new Set<string>()
647
+ /** Tool calls already said to have started, by part id. */
648
+ const startedCalls = new Set<string>()
647
649
  let idle: (() => void) | null = null
648
650
  let sessionError = ""
649
651
  // The turn's result comes from events: in agent runtime 1.18 listing a session's messages fails once a prompt used `format`.
@@ -664,6 +666,11 @@ export async function openSession<R = AgentReport>(opts: {
664
666
  break
665
667
  case "message.part.updated": {
666
668
  const part = p.part
669
+ // A call is said as soon as it starts, so a long one (an API query, a test run) is visible while it runs.
670
+ if (part?.type === "tool" && part.state?.status === "running" && part.id && !startedCalls.has(part.id) && !QUIET_TOOLS.has(part.tool) && !opts.hideTool?.(part.tool)) {
671
+ startedCalls.add(part.id)
672
+ emit({ type: "code", kind: "start", tool: part.tool, id: part.id, text: toolLine(opts.repo, part.tool, part.state.input || {}, part.state.title) })
673
+ }
667
674
  if (part?.type === "tool" && (part.state?.status === "completed" || part.state?.status === "error")) {
668
675
  if (part.tool === "StructuredOutput" && part.state.status === "completed" && !turn.structured) {
669
676
  turn.structured = part.state.input || null
@@ -687,7 +694,7 @@ export async function openSession<R = AgentReport>(opts: {
687
694
  const ok = part.state.status === "completed"
688
695
  const file = toolFile(opts.repo, part.tool, input)
689
696
  const skill = part.tool === "skill" && ok ? String(input.name || "") : ""
690
- emit({ type: "code", kind: "tool", ok, tool: part.tool, ...(file ? { file } : {}), ...(skill ? { skill } : {}), text: ok ? line : `${line}: ${clip(toolError(String(part.state.error || "")) || "failed", 120)}` })
697
+ emit({ type: "code", kind: "tool", ok, tool: part.tool, ...(part.id ? { id: part.id } : {}), ...(file ? { file } : {}), ...(skill ? { skill } : {}), text: ok ? line : `${line}: ${clip(toolError(String(part.state.error || "")) || "failed", 120)}` })
691
698
  } else if (part?.type === "text" && part.time?.end && assistant.has(part.messageID) && !said.has(part.id)) {
692
699
  said.add(part.id)
693
700
  const text = String(part.text || "").trim()
package/src/mcp/server.ts CHANGED
@@ -62,9 +62,11 @@ export function createMcpServer(opts: McpServerOptions) {
62
62
  base.emit?.(e)
63
63
  }
64
64
  : undefined
65
+ const callId = `${tool.name}-${String(id)}-${started}`
65
66
  const said = (ok: boolean) => {
66
- if (tool.line && emit) emit({ type: "call", text: tool.line(params.arguments || {}), ok })
67
+ if (tool.line && emit) emit({ type: "call", text: tool.line(params.arguments || {}), ok, id: callId })
67
68
  }
69
+ if (tool.line && emit) emit({ type: "call-start", text: tool.line(params.arguments || {}), id: callId })
68
70
  let out: unknown
69
71
  try {
70
72
  out = await tool.run(params.arguments || {}, { ...base, emit, signal: controller.signal })
package/src/mcp/tools.ts CHANGED
@@ -102,7 +102,9 @@ export type ToolEvent =
102
102
  /** write_report saved a report: its page and its Markdown. */
103
103
  | { type: "report"; title: string; html: string; markdown: string }
104
104
  /** A finished call of a tool that has no card of its own, as one line: "Azure DevOps API · QI-Claims/_apis/build/builds (top 5)". */
105
- | { type: "call"; text: string; ok: boolean }
105
+ | { type: "call"; text: string; ok: boolean; id?: string }
106
+ /** The same call as it starts, so a long one is visible while it runs; its `call` with the same `id` follows. */
107
+ | { type: "call-start"; text: string; id: string }
106
108
 
107
109
  const API_LABEL: Record<string, string> = { azure_devops: "Azure DevOps", jira: "Jira", xray: "Xray", confluence: "Confluence" }
108
110