localagentbrowser 1.52__tar.gz → 1.57__tar.gz

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.
Files changed (26) hide show
  1. {localagentbrowser-1.52 → localagentbrowser-1.57}/CHANGELOG.md +90 -1
  2. {localagentbrowser-1.52 → localagentbrowser-1.57}/MANIFEST.in +2 -1
  3. {localagentbrowser-1.52/localagentbrowser.egg-info → localagentbrowser-1.57}/PKG-INFO +99 -21
  4. {localagentbrowser-1.52 → localagentbrowser-1.57}/README.md +98 -20
  5. {localagentbrowser-1.52 → localagentbrowser-1.57}/agent_browser.py +426 -42
  6. {localagentbrowser-1.52 → localagentbrowser-1.57/localagentbrowser.egg-info}/PKG-INFO +99 -21
  7. {localagentbrowser-1.52 → localagentbrowser-1.57}/localagentbrowser.egg-info/SOURCES.txt +5 -1
  8. {localagentbrowser-1.52 → localagentbrowser-1.57}/pyproject.toml +1 -1
  9. localagentbrowser-1.57/tests/test_checklist.py +251 -0
  10. {localagentbrowser-1.52 → localagentbrowser-1.57}/tests/test_decisions.py +38 -5
  11. {localagentbrowser-1.52 → localagentbrowser-1.57}/tests/test_journal.py +6 -0
  12. {localagentbrowser-1.52 → localagentbrowser-1.57}/tests/test_main_loop.py +47 -10
  13. {localagentbrowser-1.52 → localagentbrowser-1.57}/tests/test_model_turns.py +9 -1
  14. localagentbrowser-1.57/tests/test_regression.py +112 -0
  15. localagentbrowser-1.57/tools/live_test.py +68 -0
  16. localagentbrowser-1.57/tools/regression.py +402 -0
  17. {localagentbrowser-1.52 → localagentbrowser-1.57}/LICENSE +0 -0
  18. {localagentbrowser-1.52 → localagentbrowser-1.57}/localagentbrowser.egg-info/dependency_links.txt +0 -0
  19. {localagentbrowser-1.52 → localagentbrowser-1.57}/localagentbrowser.egg-info/entry_points.txt +0 -0
  20. {localagentbrowser-1.52 → localagentbrowser-1.57}/localagentbrowser.egg-info/requires.txt +0 -0
  21. {localagentbrowser-1.52 → localagentbrowser-1.57}/localagentbrowser.egg-info/top_level.txt +0 -0
  22. {localagentbrowser-1.52 → localagentbrowser-1.57}/setup.cfg +0 -0
  23. {localagentbrowser-1.52 → localagentbrowser-1.57}/tests/conftest.py +0 -0
  24. {localagentbrowser-1.52 → localagentbrowser-1.57}/tests/fakes.py +0 -0
  25. {localagentbrowser-1.52 → localagentbrowser-1.57}/tests/test_duplicates.py +0 -0
  26. {localagentbrowser-1.52 → localagentbrowser-1.57}/tests/test_page_text.py +0 -0
@@ -1,9 +1,98 @@
1
1
  # Changelog
2
2
 
3
- Every version of `agent_browser.py`, newest first. Each version is also a tagged commit (`v1.11` … `v1.28`).
3
+ Every version of `agent_browser.py`, newest first. Each released version is also a tagged commit (`v1.11` … `v1.57`); 1.54 to 1.56 were internal steps
4
+ measured on the regression suite and released as part of 1.57 (see
5
+ [docs/regression-history.md](docs/regression-history.md)).
4
6
  Timings are from live runs on the development machine (Intel i5-9500, 6 cores, no GPU, Qwen2.5-7B-Instruct
5
7
  Q4_K_M in LM Studio), where reading the prompt takes about 90% of every model call.
6
8
 
9
+ ## [1.57] - 2026-10-19
10
+ Released together with the internal steps 1.54, 1.55 and 1.56, each of which was measured on the regression suite
11
+ but not released on its own. [docs/regression-history.md](docs/regression-history.md) has every step's results,
12
+ task by task, and what each one showed.
13
+ ### Added
14
+ - Coverage check before finishing. The 1.53 suite left two problems open: an explanation finished from one overview
15
+ paragraph that the model said covered every item (no oxygen or water), and a list named WPS Office as
16
+ "free, open-source". Before a FINISH goes through, each checklist item is now checked against the full findings
17
+ in a short call of its own, with the item last so the instructions are read once (about 1-3 minutes for a
18
+ checklist). The code checks the verdict rather than taking it on trust: an item nothing was copied for counts as
19
+ unanswered; an item asking for a number of things gets "only 1 of 3 found" when fewer are named; for such items,
20
+ each thing named must be shown to meet the item's conditions in words copied from a finding about that thing; and
21
+ a claim that something is missing is dropped when every word of it is already in the findings. With gaps, the
22
+ FINISH is sent back once, naming the next step for a condition ("SEARCH for 'OnlyOffice free and open-source' to
23
+ check it, or replace it"), and the next turn starts from a fresh prompt. Finishing with nothing recorded is sent
24
+ back too.
25
+ - What no finding answers is reported by the code. Checked once more just before the final result, checklist items
26
+ nothing answers and things not shown to meet a condition are left out of what the final result is asked to write
27
+ and added after it ("Not found in the pages read", "Left out, not shown to meet the conditions in the pages read").
28
+ The final result had filled a gap from the model's own knowledge (a care routine for repotted plants).
29
+ - The first turn asks for one short search for the whole objective, keeping its conditions: with the checklist, the
30
+ first search had gone after the first item only, and the documentation task had dropped "official". Two system
31
+ prompt rules say the same for later searches.
32
+ ### Changed
33
+ - A DISCOVER refused as not on the page now quotes the page sentence closest to it (chosen by the refused text and
34
+ the objective), to record instead, or names what the parts shown never mention ("Japan, Navajo"); it is no longer
35
+ wrapped in "Do NOT choose DISCOVER again ... choose a different action", which outweighed the quoted sentence.
36
+ Replayed on the saved runs: the page's real aftercare line was recorded 6 times out of 6 (0 of 3 before), a refusal
37
+ where the real steps came on the next part still led to READ_MORE 6 of 6, and an owl case read on 5 of 6.
38
+ - The final result gives as many items as asked for without ever repeating one, and says how many were not found:
39
+ a list run had listed LibreOffice three times.
40
+ - Opinion items are shown in the checklist as "written by you at FINISH, not found on a page": shown as having no
41
+ discoveries yet, an owl task kept collecting cultures after it had the three asked for.
42
+ - Fundraising banners and other site notices are hidden like cookie banners: Wikipedia's filled the whole first part
43
+ of an article.
44
+ - Regression suite: the core how-to is now "make cold brew coffee at home" (`howto-coldbrew`), since the repotting
45
+ task went to the same guide in three runs and that guide has no section on care in the first two weeks; repotting
46
+ stays as an extra task under its old id. The summary flags a task that fails again on the same site as before. The
47
+ documentation task has 45 minutes, like the others.
48
+ ### Fixed
49
+ - The not-on-page check refused the real Kilimanjaro answer as unseen because the banner hid the article (above).
50
+ - Numbered headings ("#### 1. Setup") were flagged as numbers missing from the findings (1.53).
51
+
52
+ Regression runs, finished out of 7 (model minutes): 1.53 5 (200), 1.54 4 (239), 1.54 with fixes 5 (225), 1.55 5
53
+ (233), 1.56 4 (272), 1.57 4 (270). Across these runs the result quality rose where the checks fired: the
54
+ explanation went from thin to complete and cited, the comparison stopped inventing features, the list stopped naming
55
+ WPS Office as open source, and every documentation finding since 1.55 is from python.org. What is not better: about
56
+ half of the coverage check's send-backs were for gaps that were not real, and each costs 8-10 minutes on this
57
+ hardware (a fresh prompt reads 3,000-4,000 tokens), so finishes were lost: on 1.57, a list of three correct
58
+ open-source suites sent back because no words showed them to be "free", and a comparison sent back for "official
59
+ documentation" it was not asked for. The next step is to send the agent back only for gaps the code verifies.
60
+ Also still open: on the documentation task the Windows line repeats the create command instead of the activate
61
+ one (1.56 and 1.57), and on 1.57 the opinion task ran out of time on a page that covered two of the three
62
+ cultures asked for.
63
+
64
+ ## [1.53] - 2026-10-17
65
+ ### Added
66
+ - Regression suite (`tools/regression.py`): seven objectives, one of each kind of task tested so far, run one
67
+ after the other with a time limit each and scored the same way (finished or not, turns, model time, checklist
68
+ progress, checks fired, and word checks for missing answers, missed conditions, uncited paragraphs, numbers
69
+ missing from the findings and a missing opinion), with a comparison to an earlier run. Single runs had been
70
+ flattering: on 1.52 the suite finished only 2 of 7 tasks within their limits, including tasks earlier single
71
+ runs had finished. Refused actions in the journal now name the check that refused them, so the suite can count
72
+ each check, and the live test runner times every model call and saves the model's full replies.
73
+ - Objective checklist. The 1.52 suite showed the main failure: every check asked the model to split the
74
+ objective into parts again, from memory, and the split drifted. On the list task it blocked its own FINISH
75
+ over "migration strategies", which the objective never asked for (an idea from a page it had read), and never
76
+ looked for a third suite; on the comparison it added "data types" and never covered "many simultaneous users".
77
+ Now one short call at the start splits the objective into a fixed checklist; asked on its own, the model split
78
+ all seven test objectives cleanly and kept their conditions. Each DISCOVER names the items it serves
79
+ (`checklist_items` in the reply), the checklist with its discoveries is in fresh prompts and in the note after
80
+ each discovery, the finish, progress and objective checks go through its items ("do not add other parts"),
81
+ the read-on check names the items still open, the final result covers every item or says it was not found,
82
+ and the report lists the checklist. The split call uses the same system prompt as turn 1, so LM Studio's cache
83
+ of it still applies there (without that, turn 1 took 128 s instead of about 40).
84
+ ### Fixed
85
+ - The report flagged the numbers of numbered headings ("#### 1. Setup") as numbers missing from the findings.
86
+
87
+ Regression run against 1.52 (model minutes in brackets): 5 of 7 tasks finished instead of 2, and the total model
88
+ time fell from 254 to 200 minutes. The list (30.1, was a 45-minute time limit), comparison (39.0, every part
89
+ covered), explanation (12.9, was 60 without finishing) and opinion (38.1) tasks now finish; the factual question
90
+ still does (13.6, was 11.9). What is not better: the list names WPS Office, which is not open source; the
91
+ explanation finished from a single overview paragraph that the model claimed covered all four items, without
92
+ oxygen or water; the how-to found the materials and steps but not the aftercare before its time limit; and the
93
+ documentation task now went to python.org, as asked, but worked through the items one search at a time and hit
94
+ its 30-minute limit before the last one (it had finished in 15 minutes on 1.52, from a tutorial site).
95
+
7
96
  ## [1.52] - 2026-10-16
8
97
  ### Changed
9
98
  - The note after each DISCOVER also says to work on parts of the objective that are not covered yet before
@@ -1,3 +1,4 @@
1
- # Files the source package needs beyond the defaults, so its tests can run
1
+ # Files the source package needs beyond the defaults, so its tests (and the tools they test) can run
2
2
  include CHANGELOG.md
3
3
  recursive-include tests *.py
4
+ recursive-include tools *.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: localagentbrowser
3
- Version: 1.52
3
+ Version: 1.57
4
4
  Summary: An autonomous web agent driven by a local LLM (LM Studio) and Playwright. Runs entirely on your own machine.
5
5
  Author: SnowFX
6
6
  License-Expression: MIT
@@ -56,8 +56,8 @@ and tuned to work well with a **small 7B model on a CPU, no GPU required**.
56
56
  - ⚡ **Built for slow hardware.** It reuses LM Studio's prompt cache, so most turns process only what changed.
57
57
  - 📝 **A readable report every time.** `research_report.md` holds the final result and every finding with its
58
58
  source, written however the run ends; `research_log.txt` keeps every action and reason.
59
- - ✅ **Tested.** 112 tests on Linux and Windows, Python 3.10–3.13, run in about a second with no model or browser,
60
- plus live runs on seven different kinds of task (see [results](#results-on-different-kinds-of-tasks)).
59
+ - ✅ **Tested.** 165 tests on Linux and Windows, Python 3.10–3.13, run in a few seconds with no model or browser,
60
+ plus a [regression suite](#regression-suite) of live runs on seven different kinds of task.
61
61
 
62
62
  📖 **The story behind it:** [Teaching a 7B model on a CPU to finish what it starts](https://dev.to/snowfxxx/teaching-a-7b-model-on-a-cpu-to-finish-what-it-starts-1amc),
63
63
  six lessons from 30 versions of keeping a small local model on track.
@@ -193,7 +193,25 @@ does not generalise; the [changelog](https://github.com/SnowFXXX/LocalAgentBrows
193
193
  | List of items | Three free, open-source alternatives to Microsoft Office and what each is best at | 1.46, 1.51 | LibreOffice and OnlyOffice with their strengths, cited, in 18 turns (49 min); the third, FreeOffice, is free but not open source, and LibreOffice was recorded four times in different words; on 1.51: LibreOffice, OnlyOffice and Apache OpenOffice, all open source, in 7 turns (16 min) |
194
194
  | Step-by-step how-to | Make a sourdough starter, with quantities and what to do each day | 1.36–1.37 | A clear plan in 7 turns (19 min), but it invented the first water amount; 1.37 stops guessing and flags unsupported numbers, and the agent then went looking for the missing details |
195
195
  | Step-by-step how-to | Repot a houseplant: what you need, the steps, and care for the first two weeks | 1.43–1.44, 1.51 | 1.43 recorded six steps it wrote itself before reading the part that had them; 1.44 recorded the guide's real steps but took 68 min and its result left one out. 1.51: every step from the page, in 7 turns (29 min), and it says that no care instructions beyond the first watering were found |
196
- | Explanation of a topic | How photosynthesis works: inputs and outputs, both stages and where each takes place | 1.41–1.42 | A complete, cited explanation in 18 turns (45 min); 1.41 read four parts of a relevant page without recording them and had not finished after 49 min |
196
+ | Explanation of a topic | How photosynthesis works: inputs and outputs, both stages and where each takes place | 1.41–1.42, 1.52 | A complete, cited explanation in 18 turns (45 min); 1.41 read four parts of a relevant page without recording them and had not finished after 49 min. 1.52 recorded both stages and where each takes place, but did not finish within 65 min: it read the history sections of a long encyclopedia article twice and never recorded the inputs and outputs |
197
+
198
+ ### Regression suite
199
+
200
+ Since 1.53, every change is measured on the same seven objectives, one of each kind above, run one after the other
201
+ with a time limit each (`tools/regression.py`, see [Testing](#testing)). Single runs vary with the pages a search
202
+ turns up, so the suite compares versions on all seven at once. 1.54 to 1.56 were internal steps measured this way
203
+ and released together as 1.57; [docs/regression-history.md](https://github.com/SnowFXXX/LocalAgentBrowser/blob/main/docs/regression-history.md)
204
+ has every step's results and what each one showed.
205
+
206
+ | Task | 1.52 | 1.53 (objective checklist) | 1.57 (coverage check) |
207
+ |---|---|---|---|
208
+ | Factual question | Finished, 12 min | Finished, 14 min | Finished, 13 min |
209
+ | List of three office suites | Time limit | Finished, 30 min; but WPS Office is not open source | Time limit: three correct open-source suites by turn 7, sent back because no words showed them to be "free" |
210
+ | Comparison and recommendation | Time limit | Finished, 39 min | Time limit, after a send-back for "official documentation", which the objective does not ask for |
211
+ | How-to (cold brew from 1.55; repotting before) | Time limit | Time limit | Finished, 36 min; but "how long it keeps" answered with the steeping time |
212
+ | Explanation (photosynthesis) | Time limit | Finished, 13 min, but thin: no oxygen or water | Finished, 59 min: inputs, outputs and both stages, cited |
213
+ | Opinion (owls) | Time limit | Finished, 38 min | Time limit: its first page covered two of the three cultures asked for |
214
+ | Documentation (venv, official docs) | Finished, 15 min, from a tutorial site | Time limit (30 min) | Finished, 37 min, all from python.org; but the Windows line repeats the create command instead of the activate one |
197
215
 
198
216
  ## How it works
199
217
 
@@ -232,7 +250,22 @@ flowchart LR
232
250
  - **Findings must match the page.** A finding that shares too few word pairs with the page text shown so far
233
251
  (or has a sentence that does) is sent back once, asking for only what the page says in its own words, and
234
252
  one far from anything on the page is refused outright. A small model will otherwise "complete" a list from
235
- its own knowledge when a page says "follow these 6 steps" and the steps come later.
253
+ its own knowledge when a page says "follow these 6 steps" and the steps come later. The refusal points the way:
254
+ it quotes the one page sentence closest to what the model wrote, to record instead, or names what the parts
255
+ shown never mention ("Japan, Navajo"), so the model reads on.
256
+ - **An objective checklist.** At the start, one short model call splits the objective into a fixed checklist of
257
+ what the result must contain, keeping conditions like "free, open-source" or "three". Each finding names the
258
+ items it serves, the checklist with its findings is in every prompt, and every check goes through these items
259
+ instead of asking the model to split the objective again from memory, which drifted: it once blocked its own
260
+ finish over "migration strategies", which the objective never asked for. Opinion items are shown as written
261
+ at FINISH, not as gaps to fill, and the first search covers the whole objective in one short query, keeping
262
+ its conditions ("official python documentation venv").
263
+ - **A coverage check before finishing.** Each checklist item is checked against the findings in a short call of
264
+ its own, and the code checks the verdict instead of taking it on trust: an item nothing was copied for, fewer
265
+ things than asked for ("only 1 of 3 found"), and things not shown, in words copied from a finding about them,
266
+ to meet a condition such as "open-source". A claim that something is missing is dropped when every word of it is
267
+ already in the findings. With gaps, the FINISH is sent back once, with the next step named ("SEARCH for
268
+ 'OnlyOffice free and open-source' to check it, or replace it"), and the next turn starts from a fresh prompt.
236
269
  - **Numbered findings.** Findings are numbered in the prompt and listed with every check, and the model names
237
270
  the finding that covers each part of the objective ("covered by [2]") instead of just saying "covered".
238
271
  - **Knowing when it's done.** After every new finding the model is asked whether the objective is now fully
@@ -244,12 +277,16 @@ flowchart LR
244
277
  A part that cannot be found after several tries can be reported as missing instead of blocking for good.
245
278
  - **Writing is a separate step.** When the agent finishes, one more model call writes the final result from
246
279
  only the objective and the recorded findings, under a short list of rules: no guessing or outside knowledge,
247
- cite findings by number, give exactly as many items as asked for, and add a "My view:" paragraph only when
248
- the objective asks for an opinion. A small model writes far better when that is its only job, and every
249
- claim stays traceable to a recorded finding. The report flags any number in the final result that appears
250
- in none of the findings, the most harmful kind of slip in a how-to.
280
+ cite findings by number, give as many items as asked for (never repeating one, and saying how many were not
281
+ found), and add a "My view:" paragraph only when the objective asks for an opinion. A small model writes far
282
+ better when that is its only job, and every claim stays traceable to a recorded finding. What no finding
283
+ answers is not left to the model: those checklist items, and things not shown to meet a condition, are left out
284
+ of what it is asked to write, and the code adds them after the result as "Not found in the pages read" and
285
+ "Left out, not shown to meet the conditions". The report flags any number in the final result that appears in
286
+ none of the findings, the most harmful kind of slip in a how-to.
251
287
  - **Error pages are recognised.** A page answering 404, 403 and so on counts as a failed visit, not content.
252
- - **Readable pages.** Navigation menus, footers and cookie banners are hidden; code blocks and tables are
288
+ - **Readable pages.** Navigation menus, footers, cookie banners and site notices such as fundraising banners are
289
+ hidden; code blocks and tables are
253
290
  never split between parts; links already shown are not repeated. Long pages come with an outline of the
254
291
  headings in each part, marking the parts already read, so the agent can jump to the part it needs instead of
255
292
  reading in order.
@@ -282,11 +319,13 @@ Measured on an Intel i5-9500 (6 cores, no GPU) with Qwen2.5-7B-Instruct Q4_K_M a
282
319
  | Follow-up on the same page (finding recorded, cheap retry) | 35–60 s |
283
320
  | Next part of a page, or a new page appended | 100–280 s |
284
321
  | First turn of a run | 45–110 s |
285
- | Fresh prompt after the context budget is reached | 160–380 s (longest with long pages) |
322
+ | Fresh prompt (context budget reached, or after a coverage send-back) | 160–540 s (longest with long pages) |
323
+ | Coverage check before finishing (all checklist items) | about 1–3 min |
286
324
  | Writing the final result (once, at the end) | 50–190 s, depending on how much was found |
287
325
 
288
- Whole runs from the results table: a factual question in about 12 minutes of model time, a list of three items
289
- in 24, a comparison in 33. A GPU or a smaller model will be much faster.
326
+ Whole runs vary with the pages a search turns up. In the regression runs since 1.53, a factual question took 13 to
327
+ 19 minutes of model time; the list, comparison, how-to, opinion and documentation tasks 21 to 44 when they finished;
328
+ and the explanation 13 to 59. A GPU or a smaller model will be much faster.
290
329
 
291
330
  ## FAQ
292
331
 
@@ -321,9 +360,19 @@ turn that brings in a new page takes a few minutes. See [Performance](#performan
321
360
  research, an opinion from several sources, a factual question, a comparison, a how-to, a list and an
322
361
  explanation of a topic. Each one
323
362
  exposed something that did not generalise and was fixed; other kinds of tasks may expose more.
324
- - **Reading without recording.** The model used to read long pages part by part without recording the
325
- relevant parts. Since 1.42 it must say what a part contains before reading on, which fixed this on an
326
- explanation task; it is still the area most likely to need more work on other pages.
363
+ - **Judging whether a finding covers an item is the weakest area.** The model's verdict is unreliable both ways:
364
+ on 1.53 the explanation finished from one overview paragraph without oxygen or water, and in the regression runs
365
+ since 1.54 about half of the coverage check's send-backs were for gaps that were not real ("missing official
366
+ documentation" on a comparison that did not ask for it, "H2O, O2" already recorded). The code now verifies what
367
+ it can (an item nothing answers, a count, word-for-word proof of a condition), but each wrong send-back still
368
+ costs a finish on this hardware, since a send-back costs 8–10 minutes.
369
+ - **Conditions in the objective.** A small model tends to drop conditions such as "open source" or "using the
370
+ official documentation": a list of open-source office suites once included FreeOffice (free but not open
371
+ source), and a task that asked for the official Python documentation used a tutorial site. The objective
372
+ checklist keeps the conditions in view (the documentation task uses python.org since 1.55), and a thing not
373
+ shown in the findings to meet a condition is left out of the result and listed after it. The check is strict:
374
+ on 1.57 it sent back three correct open-source suites because no words showed them to be "free". Check the
375
+ result against any conditions you set.
327
376
  - **A small model's judgement is the ceiling.** It sometimes drifts to loosely related pages, prefers
328
377
  secondary sources or stays with one source too long, and results vary with the first pages a search turns
329
378
  up; every finding is in `research_report.md` regardless.
@@ -332,8 +381,9 @@ turn that brings in a new page takes a few minutes. See [Performance](#performan
332
381
  minutes, but with thin findings and without naming what it could not find, so check the result against the
333
382
  objective.
334
383
  - **Check the citations.** The final result is told to use only recorded findings, but a 7B model sometimes
335
- puts the wrong number on a citation, adds a line no finding supports or leaves out a step, so verify a
336
- claim against the listed findings before relying on it.
384
+ puts the wrong number on a citation, adds a line no finding supports, leaves out a step or misreads a part of
385
+ the question (on 1.57 it answered "how long it keeps in the fridge" with the steeping time), so verify a claim
386
+ against the listed findings before relying on it.
337
387
  - **Some sites refuse automated browsers** (HTTP 403). The agent respects that and does not try to disguise
338
388
  itself; it moves on to other sources.
339
389
  - **Reading only.** The agent searches, opens pages and reads them. It does not click, fill in forms or sign in.
@@ -348,6 +398,15 @@ turn that brings in a new page takes a few minutes. See [Performance](#performan
348
398
  - [x] Finish as soon as the objective is covered (1.35)
349
399
  - [x] Get the model to weigh each part of a long page before reading on (1.42)
350
400
  - [ ] Let very strict objectives end with the gaps named instead of searching indefinitely (they finish since 1.50; naming the gaps is still open)
401
+ - [x] Measure every change on a regression suite of seven kinds of task (1.53)
402
+ - [x] Keep a fixed checklist of the objective's parts instead of re-splitting it at every check (1.53)
403
+ - [ ] Check that a finding really covers its checklist item, including conditions like "open source" (partly, since
404
+ 1.57: a coverage check before finishing, with what the code can verify)
405
+ - [ ] Send the agent back only for gaps the code verifies, and let the model's other verdicts only shape the final
406
+ result (the next step after 1.57)
407
+ - [ ] Rewind dead ends: save the conversation before an expensive step such as reading a long page, and if it
408
+ leads nowhere, return to that point with a short note instead of carrying the unused page text in every later
409
+ prompt (LM Studio reuses its cache up to the saved point)
351
410
  - [ ] Try more kinds of objectives (seven so far) and adjust the rules that don't generalise
352
411
  - [ ] Make fresh prompts (the slowest kind of turn) cheaper still (31% cheaper since 1.34)
353
412
  - [ ] Interacting with pages (clicking, forms) for tasks beyond reading
@@ -356,7 +415,7 @@ Ideas and requests are welcome in [issues](https://github.com/SnowFXXX/LocalAgen
356
415
 
357
416
  ## Testing
358
417
 
359
- The test suite runs in about a second and needs neither LM Studio nor a browser: the model and the website
418
+ The test suite runs in a few seconds and needs neither LM Studio nor a browser: the model and the website
360
419
  are replaced by scripted fakes, including an end-to-end run of the main loop.
361
420
 
362
421
  ```bash
@@ -372,6 +431,23 @@ call:
372
431
  python tools/live_test.py "Your objective here" --minutes 25
373
432
  ```
374
433
 
434
+ To measure a change on all seven kinds of task (about four hours on a CPU), compared with an earlier run:
435
+
436
+ ```bash
437
+ python tools/regression.py --baseline regression_runs/<earlier run>/summary.json
438
+ ```
439
+
440
+ Each run gets a folder in `regression_runs/` with every task's report, journal, console output and prompt
441
+ trace, and a `summary.md` that is updated after each task: whether it finished, turns, model time, how many
442
+ checklist items got findings, which checks fired, and problems found by simple word checks (missing answers,
443
+ missed conditions such as a non-open-source item, uncited paragraphs, numbers missing from the findings, a
444
+ missing opinion). It also flags a task that fails again on the same site as in the earlier run: one site that
445
+ cannot answer part of an objective can decide a task whatever the agent does (the repotting how-to went to the same
446
+ guide in three runs, which is why the core how-to is now the cold brew one). `--suite all` adds six more tasks,
447
+ including the earlier how-to, `--only` runs some of them, and `--rescore` scores an earlier run again without the
448
+ model. Every step since 1.53 and its results are in
449
+ [docs/regression-history.md](https://github.com/SnowFXXX/LocalAgentBrowser/blob/main/docs/regression-history.md).
450
+
375
451
  ## Contributing
376
452
 
377
453
  Contributions are welcome! See [CONTRIBUTING.md](https://github.com/SnowFXXX/LocalAgentBrowser/blob/main/CONTRIBUTING.md) for setup and guidelines, and please follow
@@ -379,8 +455,10 @@ the [Code of Conduct](https://github.com/SnowFXXX/LocalAgentBrowser/blob/main/CO
379
455
 
380
456
  ## Project history
381
457
 
382
- Every version is a tagged commit, and [CHANGELOG.md](https://github.com/SnowFXXX/LocalAgentBrowser/blob/main/CHANGELOG.md) describes what changed in each one and
383
- why, with the measurements behind the decisions.
458
+ Every released version is a tagged commit, and [CHANGELOG.md](https://github.com/SnowFXXX/LocalAgentBrowser/blob/main/CHANGELOG.md) describes what changed in each one and
459
+ why, with the measurements behind the decisions. Versions 1.54 to 1.56 were internal steps, each measured on the
460
+ regression suite and released together as 1.57; their results are in
461
+ [docs/regression-history.md](https://github.com/SnowFXXX/LocalAgentBrowser/blob/main/docs/regression-history.md).
384
462
 
385
463
  ## Acknowledgements
386
464
 
@@ -24,8 +24,8 @@ and tuned to work well with a **small 7B model on a CPU, no GPU required**.
24
24
  - ⚡ **Built for slow hardware.** It reuses LM Studio's prompt cache, so most turns process only what changed.
25
25
  - 📝 **A readable report every time.** `research_report.md` holds the final result and every finding with its
26
26
  source, written however the run ends; `research_log.txt` keeps every action and reason.
27
- - ✅ **Tested.** 112 tests on Linux and Windows, Python 3.10–3.13, run in about a second with no model or browser,
28
- plus live runs on seven different kinds of task (see [results](#results-on-different-kinds-of-tasks)).
27
+ - ✅ **Tested.** 165 tests on Linux and Windows, Python 3.10–3.13, run in a few seconds with no model or browser,
28
+ plus a [regression suite](#regression-suite) of live runs on seven different kinds of task.
29
29
 
30
30
  📖 **The story behind it:** [Teaching a 7B model on a CPU to finish what it starts](https://dev.to/snowfxxx/teaching-a-7b-model-on-a-cpu-to-finish-what-it-starts-1amc),
31
31
  six lessons from 30 versions of keeping a small local model on track.
@@ -161,7 +161,25 @@ does not generalise; the [changelog](https://github.com/SnowFXXX/LocalAgentBrows
161
161
  | List of items | Three free, open-source alternatives to Microsoft Office and what each is best at | 1.46, 1.51 | LibreOffice and OnlyOffice with their strengths, cited, in 18 turns (49 min); the third, FreeOffice, is free but not open source, and LibreOffice was recorded four times in different words; on 1.51: LibreOffice, OnlyOffice and Apache OpenOffice, all open source, in 7 turns (16 min) |
162
162
  | Step-by-step how-to | Make a sourdough starter, with quantities and what to do each day | 1.36–1.37 | A clear plan in 7 turns (19 min), but it invented the first water amount; 1.37 stops guessing and flags unsupported numbers, and the agent then went looking for the missing details |
163
163
  | Step-by-step how-to | Repot a houseplant: what you need, the steps, and care for the first two weeks | 1.43–1.44, 1.51 | 1.43 recorded six steps it wrote itself before reading the part that had them; 1.44 recorded the guide's real steps but took 68 min and its result left one out. 1.51: every step from the page, in 7 turns (29 min), and it says that no care instructions beyond the first watering were found |
164
- | Explanation of a topic | How photosynthesis works: inputs and outputs, both stages and where each takes place | 1.41–1.42 | A complete, cited explanation in 18 turns (45 min); 1.41 read four parts of a relevant page without recording them and had not finished after 49 min |
164
+ | Explanation of a topic | How photosynthesis works: inputs and outputs, both stages and where each takes place | 1.41–1.42, 1.52 | A complete, cited explanation in 18 turns (45 min); 1.41 read four parts of a relevant page without recording them and had not finished after 49 min. 1.52 recorded both stages and where each takes place, but did not finish within 65 min: it read the history sections of a long encyclopedia article twice and never recorded the inputs and outputs |
165
+
166
+ ### Regression suite
167
+
168
+ Since 1.53, every change is measured on the same seven objectives, one of each kind above, run one after the other
169
+ with a time limit each (`tools/regression.py`, see [Testing](#testing)). Single runs vary with the pages a search
170
+ turns up, so the suite compares versions on all seven at once. 1.54 to 1.56 were internal steps measured this way
171
+ and released together as 1.57; [docs/regression-history.md](https://github.com/SnowFXXX/LocalAgentBrowser/blob/main/docs/regression-history.md)
172
+ has every step's results and what each one showed.
173
+
174
+ | Task | 1.52 | 1.53 (objective checklist) | 1.57 (coverage check) |
175
+ |---|---|---|---|
176
+ | Factual question | Finished, 12 min | Finished, 14 min | Finished, 13 min |
177
+ | List of three office suites | Time limit | Finished, 30 min; but WPS Office is not open source | Time limit: three correct open-source suites by turn 7, sent back because no words showed them to be "free" |
178
+ | Comparison and recommendation | Time limit | Finished, 39 min | Time limit, after a send-back for "official documentation", which the objective does not ask for |
179
+ | How-to (cold brew from 1.55; repotting before) | Time limit | Time limit | Finished, 36 min; but "how long it keeps" answered with the steeping time |
180
+ | Explanation (photosynthesis) | Time limit | Finished, 13 min, but thin: no oxygen or water | Finished, 59 min: inputs, outputs and both stages, cited |
181
+ | Opinion (owls) | Time limit | Finished, 38 min | Time limit: its first page covered two of the three cultures asked for |
182
+ | Documentation (venv, official docs) | Finished, 15 min, from a tutorial site | Time limit (30 min) | Finished, 37 min, all from python.org; but the Windows line repeats the create command instead of the activate one |
165
183
 
166
184
  ## How it works
167
185
 
@@ -200,7 +218,22 @@ flowchart LR
200
218
  - **Findings must match the page.** A finding that shares too few word pairs with the page text shown so far
201
219
  (or has a sentence that does) is sent back once, asking for only what the page says in its own words, and
202
220
  one far from anything on the page is refused outright. A small model will otherwise "complete" a list from
203
- its own knowledge when a page says "follow these 6 steps" and the steps come later.
221
+ its own knowledge when a page says "follow these 6 steps" and the steps come later. The refusal points the way:
222
+ it quotes the one page sentence closest to what the model wrote, to record instead, or names what the parts
223
+ shown never mention ("Japan, Navajo"), so the model reads on.
224
+ - **An objective checklist.** At the start, one short model call splits the objective into a fixed checklist of
225
+ what the result must contain, keeping conditions like "free, open-source" or "three". Each finding names the
226
+ items it serves, the checklist with its findings is in every prompt, and every check goes through these items
227
+ instead of asking the model to split the objective again from memory, which drifted: it once blocked its own
228
+ finish over "migration strategies", which the objective never asked for. Opinion items are shown as written
229
+ at FINISH, not as gaps to fill, and the first search covers the whole objective in one short query, keeping
230
+ its conditions ("official python documentation venv").
231
+ - **A coverage check before finishing.** Each checklist item is checked against the findings in a short call of
232
+ its own, and the code checks the verdict instead of taking it on trust: an item nothing was copied for, fewer
233
+ things than asked for ("only 1 of 3 found"), and things not shown, in words copied from a finding about them,
234
+ to meet a condition such as "open-source". A claim that something is missing is dropped when every word of it is
235
+ already in the findings. With gaps, the FINISH is sent back once, with the next step named ("SEARCH for
236
+ 'OnlyOffice free and open-source' to check it, or replace it"), and the next turn starts from a fresh prompt.
204
237
  - **Numbered findings.** Findings are numbered in the prompt and listed with every check, and the model names
205
238
  the finding that covers each part of the objective ("covered by [2]") instead of just saying "covered".
206
239
  - **Knowing when it's done.** After every new finding the model is asked whether the objective is now fully
@@ -212,12 +245,16 @@ flowchart LR
212
245
  A part that cannot be found after several tries can be reported as missing instead of blocking for good.
213
246
  - **Writing is a separate step.** When the agent finishes, one more model call writes the final result from
214
247
  only the objective and the recorded findings, under a short list of rules: no guessing or outside knowledge,
215
- cite findings by number, give exactly as many items as asked for, and add a "My view:" paragraph only when
216
- the objective asks for an opinion. A small model writes far better when that is its only job, and every
217
- claim stays traceable to a recorded finding. The report flags any number in the final result that appears
218
- in none of the findings, the most harmful kind of slip in a how-to.
248
+ cite findings by number, give as many items as asked for (never repeating one, and saying how many were not
249
+ found), and add a "My view:" paragraph only when the objective asks for an opinion. A small model writes far
250
+ better when that is its only job, and every claim stays traceable to a recorded finding. What no finding
251
+ answers is not left to the model: those checklist items, and things not shown to meet a condition, are left out
252
+ of what it is asked to write, and the code adds them after the result as "Not found in the pages read" and
253
+ "Left out, not shown to meet the conditions". The report flags any number in the final result that appears in
254
+ none of the findings, the most harmful kind of slip in a how-to.
219
255
  - **Error pages are recognised.** A page answering 404, 403 and so on counts as a failed visit, not content.
220
- - **Readable pages.** Navigation menus, footers and cookie banners are hidden; code blocks and tables are
256
+ - **Readable pages.** Navigation menus, footers, cookie banners and site notices such as fundraising banners are
257
+ hidden; code blocks and tables are
221
258
  never split between parts; links already shown are not repeated. Long pages come with an outline of the
222
259
  headings in each part, marking the parts already read, so the agent can jump to the part it needs instead of
223
260
  reading in order.
@@ -250,11 +287,13 @@ Measured on an Intel i5-9500 (6 cores, no GPU) with Qwen2.5-7B-Instruct Q4_K_M a
250
287
  | Follow-up on the same page (finding recorded, cheap retry) | 35–60 s |
251
288
  | Next part of a page, or a new page appended | 100–280 s |
252
289
  | First turn of a run | 45–110 s |
253
- | Fresh prompt after the context budget is reached | 160–380 s (longest with long pages) |
290
+ | Fresh prompt (context budget reached, or after a coverage send-back) | 160–540 s (longest with long pages) |
291
+ | Coverage check before finishing (all checklist items) | about 1–3 min |
254
292
  | Writing the final result (once, at the end) | 50–190 s, depending on how much was found |
255
293
 
256
- Whole runs from the results table: a factual question in about 12 minutes of model time, a list of three items
257
- in 24, a comparison in 33. A GPU or a smaller model will be much faster.
294
+ Whole runs vary with the pages a search turns up. In the regression runs since 1.53, a factual question took 13 to
295
+ 19 minutes of model time; the list, comparison, how-to, opinion and documentation tasks 21 to 44 when they finished;
296
+ and the explanation 13 to 59. A GPU or a smaller model will be much faster.
258
297
 
259
298
  ## FAQ
260
299
 
@@ -289,9 +328,19 @@ turn that brings in a new page takes a few minutes. See [Performance](#performan
289
328
  research, an opinion from several sources, a factual question, a comparison, a how-to, a list and an
290
329
  explanation of a topic. Each one
291
330
  exposed something that did not generalise and was fixed; other kinds of tasks may expose more.
292
- - **Reading without recording.** The model used to read long pages part by part without recording the
293
- relevant parts. Since 1.42 it must say what a part contains before reading on, which fixed this on an
294
- explanation task; it is still the area most likely to need more work on other pages.
331
+ - **Judging whether a finding covers an item is the weakest area.** The model's verdict is unreliable both ways:
332
+ on 1.53 the explanation finished from one overview paragraph without oxygen or water, and in the regression runs
333
+ since 1.54 about half of the coverage check's send-backs were for gaps that were not real ("missing official
334
+ documentation" on a comparison that did not ask for it, "H2O, O2" already recorded). The code now verifies what
335
+ it can (an item nothing answers, a count, word-for-word proof of a condition), but each wrong send-back still
336
+ costs a finish on this hardware, since a send-back costs 8–10 minutes.
337
+ - **Conditions in the objective.** A small model tends to drop conditions such as "open source" or "using the
338
+ official documentation": a list of open-source office suites once included FreeOffice (free but not open
339
+ source), and a task that asked for the official Python documentation used a tutorial site. The objective
340
+ checklist keeps the conditions in view (the documentation task uses python.org since 1.55), and a thing not
341
+ shown in the findings to meet a condition is left out of the result and listed after it. The check is strict:
342
+ on 1.57 it sent back three correct open-source suites because no words showed them to be "free". Check the
343
+ result against any conditions you set.
295
344
  - **A small model's judgement is the ceiling.** It sometimes drifts to loosely related pages, prefers
296
345
  secondary sources or stays with one source too long, and results vary with the first pages a search turns
297
346
  up; every finding is in `research_report.md` regardless.
@@ -300,8 +349,9 @@ turn that brings in a new page takes a few minutes. See [Performance](#performan
300
349
  minutes, but with thin findings and without naming what it could not find, so check the result against the
301
350
  objective.
302
351
  - **Check the citations.** The final result is told to use only recorded findings, but a 7B model sometimes
303
- puts the wrong number on a citation, adds a line no finding supports or leaves out a step, so verify a
304
- claim against the listed findings before relying on it.
352
+ puts the wrong number on a citation, adds a line no finding supports, leaves out a step or misreads a part of
353
+ the question (on 1.57 it answered "how long it keeps in the fridge" with the steeping time), so verify a claim
354
+ against the listed findings before relying on it.
305
355
  - **Some sites refuse automated browsers** (HTTP 403). The agent respects that and does not try to disguise
306
356
  itself; it moves on to other sources.
307
357
  - **Reading only.** The agent searches, opens pages and reads them. It does not click, fill in forms or sign in.
@@ -316,6 +366,15 @@ turn that brings in a new page takes a few minutes. See [Performance](#performan
316
366
  - [x] Finish as soon as the objective is covered (1.35)
317
367
  - [x] Get the model to weigh each part of a long page before reading on (1.42)
318
368
  - [ ] Let very strict objectives end with the gaps named instead of searching indefinitely (they finish since 1.50; naming the gaps is still open)
369
+ - [x] Measure every change on a regression suite of seven kinds of task (1.53)
370
+ - [x] Keep a fixed checklist of the objective's parts instead of re-splitting it at every check (1.53)
371
+ - [ ] Check that a finding really covers its checklist item, including conditions like "open source" (partly, since
372
+ 1.57: a coverage check before finishing, with what the code can verify)
373
+ - [ ] Send the agent back only for gaps the code verifies, and let the model's other verdicts only shape the final
374
+ result (the next step after 1.57)
375
+ - [ ] Rewind dead ends: save the conversation before an expensive step such as reading a long page, and if it
376
+ leads nowhere, return to that point with a short note instead of carrying the unused page text in every later
377
+ prompt (LM Studio reuses its cache up to the saved point)
319
378
  - [ ] Try more kinds of objectives (seven so far) and adjust the rules that don't generalise
320
379
  - [ ] Make fresh prompts (the slowest kind of turn) cheaper still (31% cheaper since 1.34)
321
380
  - [ ] Interacting with pages (clicking, forms) for tasks beyond reading
@@ -324,7 +383,7 @@ Ideas and requests are welcome in [issues](https://github.com/SnowFXXX/LocalAgen
324
383
 
325
384
  ## Testing
326
385
 
327
- The test suite runs in about a second and needs neither LM Studio nor a browser: the model and the website
386
+ The test suite runs in a few seconds and needs neither LM Studio nor a browser: the model and the website
328
387
  are replaced by scripted fakes, including an end-to-end run of the main loop.
329
388
 
330
389
  ```bash
@@ -340,6 +399,23 @@ call:
340
399
  python tools/live_test.py "Your objective here" --minutes 25
341
400
  ```
342
401
 
402
+ To measure a change on all seven kinds of task (about four hours on a CPU), compared with an earlier run:
403
+
404
+ ```bash
405
+ python tools/regression.py --baseline regression_runs/<earlier run>/summary.json
406
+ ```
407
+
408
+ Each run gets a folder in `regression_runs/` with every task's report, journal, console output and prompt
409
+ trace, and a `summary.md` that is updated after each task: whether it finished, turns, model time, how many
410
+ checklist items got findings, which checks fired, and problems found by simple word checks (missing answers,
411
+ missed conditions such as a non-open-source item, uncited paragraphs, numbers missing from the findings, a
412
+ missing opinion). It also flags a task that fails again on the same site as in the earlier run: one site that
413
+ cannot answer part of an objective can decide a task whatever the agent does (the repotting how-to went to the same
414
+ guide in three runs, which is why the core how-to is now the cold brew one). `--suite all` adds six more tasks,
415
+ including the earlier how-to, `--only` runs some of them, and `--rescore` scores an earlier run again without the
416
+ model. Every step since 1.53 and its results are in
417
+ [docs/regression-history.md](https://github.com/SnowFXXX/LocalAgentBrowser/blob/main/docs/regression-history.md).
418
+
343
419
  ## Contributing
344
420
 
345
421
  Contributions are welcome! See [CONTRIBUTING.md](https://github.com/SnowFXXX/LocalAgentBrowser/blob/main/CONTRIBUTING.md) for setup and guidelines, and please follow
@@ -347,8 +423,10 @@ the [Code of Conduct](https://github.com/SnowFXXX/LocalAgentBrowser/blob/main/CO
347
423
 
348
424
  ## Project history
349
425
 
350
- Every version is a tagged commit, and [CHANGELOG.md](https://github.com/SnowFXXX/LocalAgentBrowser/blob/main/CHANGELOG.md) describes what changed in each one and
351
- why, with the measurements behind the decisions.
426
+ Every released version is a tagged commit, and [CHANGELOG.md](https://github.com/SnowFXXX/LocalAgentBrowser/blob/main/CHANGELOG.md) describes what changed in each one and
427
+ why, with the measurements behind the decisions. Versions 1.54 to 1.56 were internal steps, each measured on the
428
+ regression suite and released together as 1.57; their results are in
429
+ [docs/regression-history.md](https://github.com/SnowFXXX/LocalAgentBrowser/blob/main/docs/regression-history.md).
352
430
 
353
431
  ## Acknowledgements
354
432