localagentbrowser 1.53__tar.gz → 1.61__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 (27) hide show
  1. {localagentbrowser-1.53 → localagentbrowser-1.61}/CHANGELOG.md +97 -1
  2. {localagentbrowser-1.53/localagentbrowser.egg-info → localagentbrowser-1.61}/PKG-INFO +76 -41
  3. {localagentbrowser-1.53 → localagentbrowser-1.61}/README.md +75 -40
  4. {localagentbrowser-1.53 → localagentbrowser-1.61}/agent_browser.py +443 -21
  5. {localagentbrowser-1.53 → localagentbrowser-1.61/localagentbrowser.egg-info}/PKG-INFO +76 -41
  6. {localagentbrowser-1.53 → localagentbrowser-1.61}/pyproject.toml +1 -1
  7. localagentbrowser-1.61/tests/test_checklist.py +346 -0
  8. {localagentbrowser-1.53 → localagentbrowser-1.61}/tests/test_decisions.py +38 -5
  9. {localagentbrowser-1.53 → localagentbrowser-1.61}/tests/test_journal.py +7 -0
  10. {localagentbrowser-1.53 → localagentbrowser-1.61}/tests/test_main_loop.py +26 -4
  11. {localagentbrowser-1.53 → localagentbrowser-1.61}/tests/test_model_turns.py +9 -1
  12. {localagentbrowser-1.53 → localagentbrowser-1.61}/tests/test_page_text.py +16 -2
  13. {localagentbrowser-1.53 → localagentbrowser-1.61}/tests/test_regression.py +14 -0
  14. {localagentbrowser-1.53 → localagentbrowser-1.61}/tools/regression.py +22 -3
  15. localagentbrowser-1.53/tests/test_checklist.py +0 -90
  16. {localagentbrowser-1.53 → localagentbrowser-1.61}/LICENSE +0 -0
  17. {localagentbrowser-1.53 → localagentbrowser-1.61}/MANIFEST.in +0 -0
  18. {localagentbrowser-1.53 → localagentbrowser-1.61}/localagentbrowser.egg-info/SOURCES.txt +0 -0
  19. {localagentbrowser-1.53 → localagentbrowser-1.61}/localagentbrowser.egg-info/dependency_links.txt +0 -0
  20. {localagentbrowser-1.53 → localagentbrowser-1.61}/localagentbrowser.egg-info/entry_points.txt +0 -0
  21. {localagentbrowser-1.53 → localagentbrowser-1.61}/localagentbrowser.egg-info/requires.txt +0 -0
  22. {localagentbrowser-1.53 → localagentbrowser-1.61}/localagentbrowser.egg-info/top_level.txt +0 -0
  23. {localagentbrowser-1.53 → localagentbrowser-1.61}/setup.cfg +0 -0
  24. {localagentbrowser-1.53 → localagentbrowser-1.61}/tests/conftest.py +0 -0
  25. {localagentbrowser-1.53 → localagentbrowser-1.61}/tests/fakes.py +0 -0
  26. {localagentbrowser-1.53 → localagentbrowser-1.61}/tests/test_duplicates.py +0 -0
  27. {localagentbrowser-1.53 → localagentbrowser-1.61}/tools/live_test.py +0 -0
@@ -1,9 +1,105 @@
1
1
  # Changelog
2
2
 
3
- Every version of `agent_browser.py`, newest first. Each version is also a tagged commit (`v1.11` … `v1.53`).
3
+ Every version of `agent_browser.py`, newest first. Each released version is also a tagged commit (`v1.11` … `v1.61`); 1.54 to 1.56 and 1.58 to 1.60 were internal steps
4
+ measured on the regression suite and released as part of 1.57 and 1.61 (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.61] - 2026-10-21
10
+ Released together with the internal steps 1.58, 1.59 and 1.60, each measured on the regression suite
11
+ ([docs/regression-history.md](docs/regression-history.md) has every step's results, task by task).
12
+ ### Added
13
+ - An outline pointer for long pages. On a page long enough to have an outline, the read-on check looks for an unread
14
+ part whose label names a word of an item with nothing recorded yet ("Administration" for "setup and
15
+ administration"), and a plain READ_MORE then reads that part instead of the next one. Told only to use the
16
+ outline, the model went on to the next part 6 times out of 6 on a 10-part comparison page; with the code making
17
+ the jump, it reaches the part every time. Words that say what the whole page is about are ignored (the page title's
18
+ words, words every item shares), as are item verbs and parts that start inside code; hyphenated words stay whole.
19
+ On 1.61 the comparison finished for the first time since 1.56, from that page's Administration part.
20
+ - "Every item has the discoveries it asks for: choose FINISH now" in the note after a discovery, when each item has
21
+ at least what it asks for. When that holds, the read-on check also asks for FINISH instead of offering to read on
22
+ (replayed: read on 6 of 6 before, FINISH 9 of 9 after).
23
+ ### Changed
24
+ - The agent is sent back before finishing only for gaps the code verifies: an item nothing was copied for, fewer
25
+ things than the item asks for, or nothing recorded. The model's other verdicts are logged "(not sent back)" and
26
+ only shape the final result. About half of the send-backs for those verdicts had been wrong, costing finishes.
27
+ - Every item that asks for a number is counted, not only items with a condition: an owl task finished with two
28
+ tribes for "at least three cultures". Amounts of time or measure ("the first two weeks") are not counts.
29
+ - A thing not shown to meet a condition stays in the result, marked where it is first named ("**OnlyOffice** (not
30
+ shown in the pages read to be free and open-source)"), instead of being left out: leaving such things out dropped
31
+ correct answers along with wrong ones.
32
+ - A description named by the coverage check as one of a list's things is ignored (it had made two office suites
33
+ count as three).
34
+ - Smaller fresh prompts: refusal reasons in the journal are cut to 120 characters, pages list 8 links instead of 15
35
+ (those with a few words of text first; in four suites the agent opened 39 pages, none from page links), and links
36
+ whose text is HTML are skipped. Fresh prompts are about 2,500 tokens instead of 3,500-4,900.
37
+ - Regression suite: the scorer accepts a forbidden item when the result marks it with the caveat.
38
+ ### Fixed
39
+ - When several things shared a caveat, only the first was marked: the identical note next to it counted for all.
40
+
41
+ Regression runs, finished out of 7 (model minutes): 1.58 5 (214), 1.59 5 (209.5), 1.60 6 (170.6), 1.61 6 (222.1).
42
+ What is still open: a fresh prompt (when a conversation reaches its token budget) does not carry the advice to
43
+ finish, and on 1.61 the documentation task read on after one with all four items found; nothing checks that a
44
+ recipe's steps reach their end (on 1.60 cold brew stopped after step 2). Measured and not used: checking a
45
+ discovery's link to its item by shared words (most links without a shared word are right), and a 16,384-token
46
+ context, which would halve the fresh prompts but needs more memory than the default aims for.
47
+
48
+ ## [1.57] - 2026-10-19
49
+ Released together with the internal steps 1.54, 1.55 and 1.56, each of which was measured on the regression suite
50
+ but not released on its own. [docs/regression-history.md](docs/regression-history.md) has every step's results,
51
+ task by task, and what each one showed.
52
+ ### Added
53
+ - Coverage check before finishing. The 1.53 suite left two problems open: an explanation finished from one overview
54
+ paragraph that the model said covered every item (no oxygen or water), and a list named WPS Office as
55
+ "free, open-source". Before a FINISH goes through, each checklist item is now checked against the full findings
56
+ in a short call of its own, with the item last so the instructions are read once (about 1-3 minutes for a
57
+ checklist). The code checks the verdict rather than taking it on trust: an item nothing was copied for counts as
58
+ unanswered; an item asking for a number of things gets "only 1 of 3 found" when fewer are named; for such items,
59
+ each thing named must be shown to meet the item's conditions in words copied from a finding about that thing; and
60
+ a claim that something is missing is dropped when every word of it is already in the findings. With gaps, the
61
+ FINISH is sent back once, naming the next step for a condition ("SEARCH for 'OnlyOffice free and open-source' to
62
+ check it, or replace it"), and the next turn starts from a fresh prompt. Finishing with nothing recorded is sent
63
+ back too.
64
+ - What no finding answers is reported by the code. Checked once more just before the final result, checklist items
65
+ nothing answers and things not shown to meet a condition are left out of what the final result is asked to write
66
+ and added after it ("Not found in the pages read", "Left out, not shown to meet the conditions in the pages read").
67
+ The final result had filled a gap from the model's own knowledge (a care routine for repotted plants).
68
+ - The first turn asks for one short search for the whole objective, keeping its conditions: with the checklist, the
69
+ first search had gone after the first item only, and the documentation task had dropped "official". Two system
70
+ prompt rules say the same for later searches.
71
+ ### Changed
72
+ - A DISCOVER refused as not on the page now quotes the page sentence closest to it (chosen by the refused text and
73
+ the objective), to record instead, or names what the parts shown never mention ("Japan, Navajo"); it is no longer
74
+ wrapped in "Do NOT choose DISCOVER again ... choose a different action", which outweighed the quoted sentence.
75
+ Replayed on the saved runs: the page's real aftercare line was recorded 6 times out of 6 (0 of 3 before), a refusal
76
+ 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.
77
+ - The final result gives as many items as asked for without ever repeating one, and says how many were not found:
78
+ a list run had listed LibreOffice three times.
79
+ - Opinion items are shown in the checklist as "written by you at FINISH, not found on a page": shown as having no
80
+ discoveries yet, an owl task kept collecting cultures after it had the three asked for.
81
+ - Fundraising banners and other site notices are hidden like cookie banners: Wikipedia's filled the whole first part
82
+ of an article.
83
+ - Regression suite: the core how-to is now "make cold brew coffee at home" (`howto-coldbrew`), since the repotting
84
+ task went to the same guide in three runs and that guide has no section on care in the first two weeks; repotting
85
+ stays as an extra task under its old id. The summary flags a task that fails again on the same site as before. The
86
+ documentation task has 45 minutes, like the others.
87
+ ### Fixed
88
+ - The not-on-page check refused the real Kilimanjaro answer as unseen because the banner hid the article (above).
89
+ - Numbered headings ("#### 1. Setup") were flagged as numbers missing from the findings (1.53).
90
+
91
+ 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
92
+ (233), 1.56 4 (272), 1.57 4 (270). Across these runs the result quality rose where the checks fired: the
93
+ explanation went from thin to complete and cited, the comparison stopped inventing features, the list stopped naming
94
+ WPS Office as open source, and every documentation finding since 1.55 is from python.org. What is not better: about
95
+ half of the coverage check's send-backs were for gaps that were not real, and each costs 8-10 minutes on this
96
+ hardware (a fresh prompt reads 3,000-4,000 tokens), so finishes were lost: on 1.57, a list of three correct
97
+ open-source suites sent back because no words showed them to be "free", and a comparison sent back for "official
98
+ documentation" it was not asked for. The next step is to send the agent back only for gaps the code verifies.
99
+ Also still open: on the documentation task the Windows line repeats the create command instead of the activate
100
+ 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
101
+ cultures asked for.
102
+
7
103
  ## [1.53] - 2026-10-17
8
104
  ### Added
9
105
  - Regression suite (`tools/regression.py`): seven objectives, one of each kind of task tested so far, run one
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: localagentbrowser
3
- Version: 1.53
3
+ Version: 1.61
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,7 +56,7 @@ 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.** 136 tests on Linux and Windows, Python 3.10–3.13, run in about a second with no model or browser,
59
+ - ✅ **Tested.** 165 tests on Linux and Windows, Python 3.10–3.13, run in a few seconds with no model or browser,
60
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),
@@ -199,17 +199,19 @@ does not generalise; the [changelog](https://github.com/SnowFXXX/LocalAgentBrows
199
199
 
200
200
  Since 1.53, every change is measured on the same seven objectives, one of each kind above, run one after the other
201
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:
203
-
204
- | Task | 1.52 | 1.53 (objective checklist) |
205
- |---|---|---|
206
- | Factual question | Finished, 12 min | Finished, 14 min |
207
- | List of three office suites | Time limit (45 min) | Finished, 30 min; but one of the three (WPS Office) is not open source |
208
- | Comparison and recommendation | Time limit (45 min) | Finished, 39 min, every part covered |
209
- | How-to (repotting) | Time limit (45 min) | Time limit (45 min); materials and steps found, aftercare not |
210
- | Explanation (photosynthesis) | Time limit (60 min) | Finished, 13 min, but thin: one finding, no oxygen or water |
211
- | Opinion (owls) | Time limit (45 min) | Finished, 38 min, four cultures and an opinion |
212
- | Documentation (venv, official docs) | Finished, 15 min, from a tutorial site | Time limit (30 min); create and activate found, from python.org |
202
+ turns up, so the suite compares versions on all seven at once. 1.54 to 1.56 and 1.58 to 1.60 were internal steps
203
+ measured this way and released with 1.57 and 1.61; [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) | 1.61 (verified send-backs, outline pointer) |
207
+ |---|---|---|---|---|
208
+ | Factual question | Finished, 12 min | Finished, 14 min | Finished, 13 min | Finished, 17 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" | Finished, 21 min: LibreOffice, WPS Office and OnlyOffice, each marked "not shown in the pages read to be free and open-source" |
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 | Finished, 26 min, setup and administration from the part of a long page the outline pointer chose |
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 | Finished, 33 min: every step, the 16-hour steep and the shelf life, cited |
212
+ | Explanation (photosynthesis) | Time limit | Finished, 13 min, but thin: no oxygen or water | Finished, 59 min: inputs, outputs and both stages, cited | Finished, 39 min |
213
+ | Opinion (owls) | Time limit | Finished, 38 min | Time limit: its first page covered two of the three cultures asked for | Finished, 42 min: four cultures, cited, with a view |
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 | Time limit: all four items found from python.org, then it read on |
213
215
 
214
216
  ## How it works
215
217
 
@@ -248,12 +250,22 @@ flowchart LR
248
250
  - **Findings must match the page.** A finding that shares too few word pairs with the page text shown so far
249
251
  (or has a sentence that does) is sent back once, asking for only what the page says in its own words, and
250
252
  one far from anything on the page is refused outright. A small model will otherwise "complete" a list from
251
- 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.
252
256
  - **An objective checklist.** At the start, one short model call splits the objective into a fixed checklist of
253
257
  what the result must contain, keeping conditions like "free, open-source" or "three". Each finding names the
254
258
  items it serves, the checklist with its findings is in every prompt, and every check goes through these items
255
259
  instead of asking the model to split the objective again from memory, which drifted: it once blocked its own
256
- finish over "migration strategies", which the objective never asked for.
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.
257
269
  - **Numbered findings.** Findings are numbered in the prompt and listed with every check, and the model names
258
270
  the finding that covers each part of the objective ("covered by [2]") instead of just saying "covered".
259
271
  - **Knowing when it's done.** After every new finding the model is asked whether the objective is now fully
@@ -265,12 +277,16 @@ flowchart LR
265
277
  A part that cannot be found after several tries can be reported as missing instead of blocking for good.
266
278
  - **Writing is a separate step.** When the agent finishes, one more model call writes the final result from
267
279
  only the objective and the recorded findings, under a short list of rules: no guessing or outside knowledge,
268
- cite findings by number, give exactly as many items as asked for, and add a "My view:" paragraph only when
269
- the objective asks for an opinion. A small model writes far better when that is its only job, and every
270
- claim stays traceable to a recorded finding. The report flags any number in the final result that appears
271
- 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.
272
287
  - **Error pages are recognised.** A page answering 404, 403 and so on counts as a failed visit, not content.
273
- - **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
274
290
  never split between parts; links already shown are not repeated. Long pages come with an outline of the
275
291
  headings in each part, marking the parts already read, so the agent can jump to the part it needs instead of
276
292
  reading in order.
@@ -303,12 +319,13 @@ Measured on an Intel i5-9500 (6 cores, no GPU) with Qwen2.5-7B-Instruct Q4_K_M a
303
319
  | Follow-up on the same page (finding recorded, cheap retry) | 35–60 s |
304
320
  | Next part of a page, or a new page appended | 100–280 s |
305
321
  | First turn of a run | 45–110 s |
306
- | 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 |
307
324
  | Writing the final result (once, at the end) | 50–190 s, depending on how much was found |
308
325
 
309
- Whole runs vary with the pages a search turns up. In the results table, a factual question takes about 12
310
- minutes of model time, a list of three items 16 to 49, a comparison 25 to 38 and an explanation 45 or more. A
311
- 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 9 to
327
+ 19 minutes of model time; the list, comparison, how-to, opinion and documentation tasks 17 to 44 when they finished;
328
+ and the explanation 13 to 59. A whole suite of seven tasks took 171 to 272 minutes. A GPU or a smaller model will be much faster.
312
329
 
313
330
  ## FAQ
314
331
 
@@ -343,18 +360,21 @@ turn that brings in a new page takes a few minutes. See [Performance](#performan
343
360
  research, an opinion from several sources, a factual question, a comparison, a how-to, a list and an
344
361
  explanation of a topic. Each one
345
362
  exposed something that did not generalise and was fixed; other kinds of tasks may expose more.
346
- - **Reading long pages and knowing when it has enough.** The model used to read long pages part by part
347
- without recording the relevant parts; since 1.42 it must say what a part contains before reading on. On 1.52
348
- the explanation task still lost about 20 minutes reading unrelated sections of a long article and did not
349
- finish. On 1.53, with the objective checklist, it finished in 13 minutes, but from a single overview paragraph
350
- that left out oxygen and water: the model can now claim one finding covers every item. Judging whether a
351
- finding really covers an item is the weakest area.
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). Since 1.58 the agent is sent
367
+ back only for what the code verifies (an item nothing answers, fewer things than asked for); the model's other
368
+ verdicts only shape the final result, so a thin answer can still pass (on 1.61 the comparison's "many
369
+ simultaneous users" part is short).
352
370
  - **Conditions in the objective.** A small model tends to drop conditions such as "open source" or "using the
353
371
  official documentation": a list of open-source office suites once included FreeOffice (free but not open
354
372
  source), and a task that asked for the official Python documentation used a tutorial site. The objective
355
- checklist keeps the conditions in view (the documentation task went to python.org on 1.53), but on the same
356
- run the list task still named WPS Office, which is not open source. Check the result against any conditions
357
- you set.
373
+ checklist keeps the conditions in view (the documentation task uses python.org since 1.55), and a thing not
374
+ shown in the findings to meet a condition is marked where it is named ("not shown in the pages read to be free
375
+ and open-source"). The mark says what the pages read did not show, not that the thing fails the condition: on
376
+ 1.61 it marked LibreOffice and OnlyOffice, which are open source, as well as WPS Office, which is not. Check the
377
+ result against any conditions you set.
358
378
  - **A small model's judgement is the ceiling.** It sometimes drifts to loosely related pages, prefers
359
379
  secondary sources or stays with one source too long, and results vary with the first pages a search turns
360
380
  up; every finding is in `research_report.md` regardless.
@@ -363,8 +383,9 @@ turn that brings in a new page takes a few minutes. See [Performance](#performan
363
383
  minutes, but with thin findings and without naming what it could not find, so check the result against the
364
384
  objective.
365
385
  - **Check the citations.** The final result is told to use only recorded findings, but a 7B model sometimes
366
- puts the wrong number on a citation, adds a line no finding supports or leaves out a step, so verify a
367
- claim against the listed findings before relying on it.
386
+ puts the wrong number on a citation, adds a line no finding supports, leaves out a step or misreads a part of
387
+ the question (on 1.57 it answered "how long it keeps in the fridge" with the steeping time), so verify a claim
388
+ against the listed findings before relying on it.
368
389
  - **Some sites refuse automated browsers** (HTTP 403). The agent respects that and does not try to disguise
369
390
  itself; it moves on to other sources.
370
391
  - **Reading only.** The agent searches, opens pages and reads them. It does not click, fill in forms or sign in.
@@ -381,7 +402,15 @@ turn that brings in a new page takes a few minutes. See [Performance](#performan
381
402
  - [ ] Let very strict objectives end with the gaps named instead of searching indefinitely (they finish since 1.50; naming the gaps is still open)
382
403
  - [x] Measure every change on a regression suite of seven kinds of task (1.53)
383
404
  - [x] Keep a fixed checklist of the objective's parts instead of re-splitting it at every check (1.53)
384
- - [ ] Check that a finding really covers its checklist item, including conditions like "open source"
405
+ - [ ] Check that a finding really covers its checklist item, including conditions like "open source" (partly, since
406
+ 1.57: a coverage check before finishing, with what the code can verify)
407
+ - [x] Send the agent back only for gaps the code verifies, and let the model's other verdicts only shape the final
408
+ result (1.58, released in 1.61)
409
+ - [x] Point the agent to the part of a long page whose outline names an item it still needs (1.61)
410
+ - [ ] Keep the advice to finish when a conversation starts over from a fresh prompt (the next step after 1.61)
411
+ - [ ] Rewind dead ends: save the conversation before an expensive step such as reading a long page, and if it
412
+ leads nowhere, return to that point with a short note instead of carrying the unused page text in every later
413
+ prompt (LM Studio reuses its cache up to the saved point)
385
414
  - [ ] Try more kinds of objectives (seven so far) and adjust the rules that don't generalise
386
415
  - [ ] Make fresh prompts (the slowest kind of turn) cheaper still (31% cheaper since 1.34)
387
416
  - [ ] Interacting with pages (clicking, forms) for tasks beyond reading
@@ -390,7 +419,7 @@ Ideas and requests are welcome in [issues](https://github.com/SnowFXXX/LocalAgen
390
419
 
391
420
  ## Testing
392
421
 
393
- The test suite runs in about a second and needs neither LM Studio nor a browser: the model and the website
422
+ The test suite runs in a few seconds and needs neither LM Studio nor a browser: the model and the website
394
423
  are replaced by scripted fakes, including an end-to-end run of the main loop.
395
424
 
396
425
  ```bash
@@ -416,8 +445,12 @@ Each run gets a folder in `regression_runs/` with every task's report, journal,
416
445
  trace, and a `summary.md` that is updated after each task: whether it finished, turns, model time, how many
417
446
  checklist items got findings, which checks fired, and problems found by simple word checks (missing answers,
418
447
  missed conditions such as a non-open-source item, uncited paragraphs, numbers missing from the findings, a
419
- missing opinion). `--suite all` adds five more tasks, `--only` runs some of them, and `--rescore` scores an
420
- earlier run again without the model.
448
+ missing opinion). It also flags a task that fails again on the same site as in the earlier run: one site that
449
+ cannot answer part of an objective can decide a task whatever the agent does (the repotting how-to went to the same
450
+ guide in three runs, which is why the core how-to is now the cold brew one). `--suite all` adds six more tasks,
451
+ including the earlier how-to, `--only` runs some of them, and `--rescore` scores an earlier run again without the
452
+ model. Every step since 1.53 and its results are in
453
+ [docs/regression-history.md](https://github.com/SnowFXXX/LocalAgentBrowser/blob/main/docs/regression-history.md).
421
454
 
422
455
  ## Contributing
423
456
 
@@ -426,8 +459,10 @@ the [Code of Conduct](https://github.com/SnowFXXX/LocalAgentBrowser/blob/main/CO
426
459
 
427
460
  ## Project history
428
461
 
429
- 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
430
- why, with the measurements behind the decisions.
462
+ 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
463
+ why, with the measurements behind the decisions. Versions 1.54 to 1.56 and 1.58 to 1.60 were internal steps, each
464
+ measured on the regression suite and released with 1.57 and 1.61; their results are in
465
+ [docs/regression-history.md](https://github.com/SnowFXXX/LocalAgentBrowser/blob/main/docs/regression-history.md).
431
466
 
432
467
  ## Acknowledgements
433
468
 
@@ -24,7 +24,7 @@ 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.** 136 tests on Linux and Windows, Python 3.10–3.13, run in about a second with no model or browser,
27
+ - ✅ **Tested.** 165 tests on Linux and Windows, Python 3.10–3.13, run in a few seconds with no model or browser,
28
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),
@@ -167,17 +167,19 @@ does not generalise; the [changelog](https://github.com/SnowFXXX/LocalAgentBrows
167
167
 
168
168
  Since 1.53, every change is measured on the same seven objectives, one of each kind above, run one after the other
169
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:
171
-
172
- | Task | 1.52 | 1.53 (objective checklist) |
173
- |---|---|---|
174
- | Factual question | Finished, 12 min | Finished, 14 min |
175
- | List of three office suites | Time limit (45 min) | Finished, 30 min; but one of the three (WPS Office) is not open source |
176
- | Comparison and recommendation | Time limit (45 min) | Finished, 39 min, every part covered |
177
- | How-to (repotting) | Time limit (45 min) | Time limit (45 min); materials and steps found, aftercare not |
178
- | Explanation (photosynthesis) | Time limit (60 min) | Finished, 13 min, but thin: one finding, no oxygen or water |
179
- | Opinion (owls) | Time limit (45 min) | Finished, 38 min, four cultures and an opinion |
180
- | Documentation (venv, official docs) | Finished, 15 min, from a tutorial site | Time limit (30 min); create and activate found, from python.org |
170
+ turns up, so the suite compares versions on all seven at once. 1.54 to 1.56 and 1.58 to 1.60 were internal steps
171
+ measured this way and released with 1.57 and 1.61; [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) | 1.61 (verified send-backs, outline pointer) |
175
+ |---|---|---|---|---|
176
+ | Factual question | Finished, 12 min | Finished, 14 min | Finished, 13 min | Finished, 17 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" | Finished, 21 min: LibreOffice, WPS Office and OnlyOffice, each marked "not shown in the pages read to be free and open-source" |
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 | Finished, 26 min, setup and administration from the part of a long page the outline pointer chose |
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 | Finished, 33 min: every step, the 16-hour steep and the shelf life, cited |
180
+ | Explanation (photosynthesis) | Time limit | Finished, 13 min, but thin: no oxygen or water | Finished, 59 min: inputs, outputs and both stages, cited | Finished, 39 min |
181
+ | Opinion (owls) | Time limit | Finished, 38 min | Time limit: its first page covered two of the three cultures asked for | Finished, 42 min: four cultures, cited, with a view |
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 | Time limit: all four items found from python.org, then it read on |
181
183
 
182
184
  ## How it works
183
185
 
@@ -216,12 +218,22 @@ flowchart LR
216
218
  - **Findings must match the page.** A finding that shares too few word pairs with the page text shown so far
217
219
  (or has a sentence that does) is sent back once, asking for only what the page says in its own words, and
218
220
  one far from anything on the page is refused outright. A small model will otherwise "complete" a list from
219
- 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.
220
224
  - **An objective checklist.** At the start, one short model call splits the objective into a fixed checklist of
221
225
  what the result must contain, keeping conditions like "free, open-source" or "three". Each finding names the
222
226
  items it serves, the checklist with its findings is in every prompt, and every check goes through these items
223
227
  instead of asking the model to split the objective again from memory, which drifted: it once blocked its own
224
- finish over "migration strategies", which the objective never asked for.
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.
225
237
  - **Numbered findings.** Findings are numbered in the prompt and listed with every check, and the model names
226
238
  the finding that covers each part of the objective ("covered by [2]") instead of just saying "covered".
227
239
  - **Knowing when it's done.** After every new finding the model is asked whether the objective is now fully
@@ -233,12 +245,16 @@ flowchart LR
233
245
  A part that cannot be found after several tries can be reported as missing instead of blocking for good.
234
246
  - **Writing is a separate step.** When the agent finishes, one more model call writes the final result from
235
247
  only the objective and the recorded findings, under a short list of rules: no guessing or outside knowledge,
236
- cite findings by number, give exactly as many items as asked for, and add a "My view:" paragraph only when
237
- the objective asks for an opinion. A small model writes far better when that is its only job, and every
238
- claim stays traceable to a recorded finding. The report flags any number in the final result that appears
239
- 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.
240
255
  - **Error pages are recognised.** A page answering 404, 403 and so on counts as a failed visit, not content.
241
- - **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
242
258
  never split between parts; links already shown are not repeated. Long pages come with an outline of the
243
259
  headings in each part, marking the parts already read, so the agent can jump to the part it needs instead of
244
260
  reading in order.
@@ -271,12 +287,13 @@ Measured on an Intel i5-9500 (6 cores, no GPU) with Qwen2.5-7B-Instruct Q4_K_M a
271
287
  | Follow-up on the same page (finding recorded, cheap retry) | 35–60 s |
272
288
  | Next part of a page, or a new page appended | 100–280 s |
273
289
  | First turn of a run | 45–110 s |
274
- | 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 |
275
292
  | Writing the final result (once, at the end) | 50–190 s, depending on how much was found |
276
293
 
277
- Whole runs vary with the pages a search turns up. In the results table, a factual question takes about 12
278
- minutes of model time, a list of three items 16 to 49, a comparison 25 to 38 and an explanation 45 or more. A
279
- 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 9 to
295
+ 19 minutes of model time; the list, comparison, how-to, opinion and documentation tasks 17 to 44 when they finished;
296
+ and the explanation 13 to 59. A whole suite of seven tasks took 171 to 272 minutes. A GPU or a smaller model will be much faster.
280
297
 
281
298
  ## FAQ
282
299
 
@@ -311,18 +328,21 @@ turn that brings in a new page takes a few minutes. See [Performance](#performan
311
328
  research, an opinion from several sources, a factual question, a comparison, a how-to, a list and an
312
329
  explanation of a topic. Each one
313
330
  exposed something that did not generalise and was fixed; other kinds of tasks may expose more.
314
- - **Reading long pages and knowing when it has enough.** The model used to read long pages part by part
315
- without recording the relevant parts; since 1.42 it must say what a part contains before reading on. On 1.52
316
- the explanation task still lost about 20 minutes reading unrelated sections of a long article and did not
317
- finish. On 1.53, with the objective checklist, it finished in 13 minutes, but from a single overview paragraph
318
- that left out oxygen and water: the model can now claim one finding covers every item. Judging whether a
319
- finding really covers an item is the weakest area.
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). Since 1.58 the agent is sent
335
+ back only for what the code verifies (an item nothing answers, fewer things than asked for); the model's other
336
+ verdicts only shape the final result, so a thin answer can still pass (on 1.61 the comparison's "many
337
+ simultaneous users" part is short).
320
338
  - **Conditions in the objective.** A small model tends to drop conditions such as "open source" or "using the
321
339
  official documentation": a list of open-source office suites once included FreeOffice (free but not open
322
340
  source), and a task that asked for the official Python documentation used a tutorial site. The objective
323
- checklist keeps the conditions in view (the documentation task went to python.org on 1.53), but on the same
324
- run the list task still named WPS Office, which is not open source. Check the result against any conditions
325
- you set.
341
+ checklist keeps the conditions in view (the documentation task uses python.org since 1.55), and a thing not
342
+ shown in the findings to meet a condition is marked where it is named ("not shown in the pages read to be free
343
+ and open-source"). The mark says what the pages read did not show, not that the thing fails the condition: on
344
+ 1.61 it marked LibreOffice and OnlyOffice, which are open source, as well as WPS Office, which is not. Check the
345
+ result against any conditions you set.
326
346
  - **A small model's judgement is the ceiling.** It sometimes drifts to loosely related pages, prefers
327
347
  secondary sources or stays with one source too long, and results vary with the first pages a search turns
328
348
  up; every finding is in `research_report.md` regardless.
@@ -331,8 +351,9 @@ turn that brings in a new page takes a few minutes. See [Performance](#performan
331
351
  minutes, but with thin findings and without naming what it could not find, so check the result against the
332
352
  objective.
333
353
  - **Check the citations.** The final result is told to use only recorded findings, but a 7B model sometimes
334
- puts the wrong number on a citation, adds a line no finding supports or leaves out a step, so verify a
335
- claim against the listed findings before relying on it.
354
+ puts the wrong number on a citation, adds a line no finding supports, leaves out a step or misreads a part of
355
+ the question (on 1.57 it answered "how long it keeps in the fridge" with the steeping time), so verify a claim
356
+ against the listed findings before relying on it.
336
357
  - **Some sites refuse automated browsers** (HTTP 403). The agent respects that and does not try to disguise
337
358
  itself; it moves on to other sources.
338
359
  - **Reading only.** The agent searches, opens pages and reads them. It does not click, fill in forms or sign in.
@@ -349,7 +370,15 @@ turn that brings in a new page takes a few minutes. See [Performance](#performan
349
370
  - [ ] Let very strict objectives end with the gaps named instead of searching indefinitely (they finish since 1.50; naming the gaps is still open)
350
371
  - [x] Measure every change on a regression suite of seven kinds of task (1.53)
351
372
  - [x] Keep a fixed checklist of the objective's parts instead of re-splitting it at every check (1.53)
352
- - [ ] Check that a finding really covers its checklist item, including conditions like "open source"
373
+ - [ ] Check that a finding really covers its checklist item, including conditions like "open source" (partly, since
374
+ 1.57: a coverage check before finishing, with what the code can verify)
375
+ - [x] Send the agent back only for gaps the code verifies, and let the model's other verdicts only shape the final
376
+ result (1.58, released in 1.61)
377
+ - [x] Point the agent to the part of a long page whose outline names an item it still needs (1.61)
378
+ - [ ] Keep the advice to finish when a conversation starts over from a fresh prompt (the next step after 1.61)
379
+ - [ ] Rewind dead ends: save the conversation before an expensive step such as reading a long page, and if it
380
+ leads nowhere, return to that point with a short note instead of carrying the unused page text in every later
381
+ prompt (LM Studio reuses its cache up to the saved point)
353
382
  - [ ] Try more kinds of objectives (seven so far) and adjust the rules that don't generalise
354
383
  - [ ] Make fresh prompts (the slowest kind of turn) cheaper still (31% cheaper since 1.34)
355
384
  - [ ] Interacting with pages (clicking, forms) for tasks beyond reading
@@ -358,7 +387,7 @@ Ideas and requests are welcome in [issues](https://github.com/SnowFXXX/LocalAgen
358
387
 
359
388
  ## Testing
360
389
 
361
- The test suite runs in about a second and needs neither LM Studio nor a browser: the model and the website
390
+ The test suite runs in a few seconds and needs neither LM Studio nor a browser: the model and the website
362
391
  are replaced by scripted fakes, including an end-to-end run of the main loop.
363
392
 
364
393
  ```bash
@@ -384,8 +413,12 @@ Each run gets a folder in `regression_runs/` with every task's report, journal,
384
413
  trace, and a `summary.md` that is updated after each task: whether it finished, turns, model time, how many
385
414
  checklist items got findings, which checks fired, and problems found by simple word checks (missing answers,
386
415
  missed conditions such as a non-open-source item, uncited paragraphs, numbers missing from the findings, a
387
- missing opinion). `--suite all` adds five more tasks, `--only` runs some of them, and `--rescore` scores an
388
- earlier run again without the model.
416
+ missing opinion). It also flags a task that fails again on the same site as in the earlier run: one site that
417
+ cannot answer part of an objective can decide a task whatever the agent does (the repotting how-to went to the same
418
+ guide in three runs, which is why the core how-to is now the cold brew one). `--suite all` adds six more tasks,
419
+ including the earlier how-to, `--only` runs some of them, and `--rescore` scores an earlier run again without the
420
+ model. Every step since 1.53 and its results are in
421
+ [docs/regression-history.md](https://github.com/SnowFXXX/LocalAgentBrowser/blob/main/docs/regression-history.md).
389
422
 
390
423
  ## Contributing
391
424
 
@@ -394,8 +427,10 @@ the [Code of Conduct](https://github.com/SnowFXXX/LocalAgentBrowser/blob/main/CO
394
427
 
395
428
  ## Project history
396
429
 
397
- 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
398
- why, with the measurements behind the decisions.
430
+ 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
431
+ why, with the measurements behind the decisions. Versions 1.54 to 1.56 and 1.58 to 1.60 were internal steps, each
432
+ measured on the regression suite and released with 1.57 and 1.61; their results are in
433
+ [docs/regression-history.md](https://github.com/SnowFXXX/LocalAgentBrowser/blob/main/docs/regression-history.md).
399
434
 
400
435
  ## Acknowledgements
401
436