Review 4: Evolution from Git

1,244 commits across 60 days, from ChatCLI v0.9 to 9.11.0, and how long each rule took to get its test. Updated on 24 October 2026.

Method and limits

Facts are verified with git log, git show, and git log -S against AGENTS.md; dates and version tags come directly from repository commits. Interpretations are explicitly highlighted as such. Most commits feature descriptive commit messages referencing specific task IDs, enabling clear tracing of key design decisions.

This review inspects the historical lag between writing a rule in AGENTS.md and introducing the automated test that enforces it, corroborating the real-world value of the 9.0.0 lesson.

1. Figures

  • 1,244 commits between 26 August and 24 October 2026, with activity on 57 of those 60 days; the peaks are still the early ones: 74 (02/09) and 65 (29/08).
  • 238 commits since the 9.2.3 review (924aef6, 16/10), over 9 consecutive days, peaking at 51 on 23/10; in that time 39 milestones closed (M5 to M43) and nine minor versions shipped, from 9.3.0 to 9.11.0.
  • Of those 238 commits, 212 list Claude Opus 5.5 as co-author; earlier, Claude Opus 5, Fable 5.1 and Antigravity (Gemini 3.8 Flash) also took part.
  • The suite went from 864 cases in 9.2.3 to 702 in 9.11.0 while covering more features: milestones M24, M32 and M41 pruned trivial, duplicate or absence tests.

2. Evolution phases

Origins and initial growth (26 August – 16 September)

ChatCLI v0.9 emerges (39fed30), featuring multi-chat and voice recognition (later removed in cbc4cb1). Introduction of AgentCore and first MCP integration (969526e). The project is renamed to ZeroChat (ad107f4). Orama lexical RAG engine arrives and the first AGENTS.md is drafted on 02/09 (481c9c6, d37ff35). SVG vector icons, custom modal dialogs, and WebLLM (e20a70c, 11/09).

Backend and hardening (17 September – 4 October)

Frontend bundling step eliminated; zerochat.py unified in version 7.0.0 (f58544f). PyPI package release and backend modularization into py/ (b3db5f0). HMAC signature for tool calls (c51d0a8). ChatState domain slices with tests (2059455) and 0600 token permissions. First audited release with version 8.12.4 (aff1019).

8.12 series (4 – 9 October)

From 8.12.5 to 8.12.16: closure of audit findings with tests against empty catch blocks and untranslated literals, branch summaries, persistent project mode, and its memory protocol.

Towards 9.0.0 and the great cleanup (9 – 12 October)

Unbounded agent loop with loop detection (38ef6f9). Modern run_command and check_command tools replace legacy shell execution (514591d). Read-only subagents (ba21510). Forwarding reasoning traces across tool steps (a3e41b6). Removal of legacy compatibility layers (c1c66af, 8d769f7) and strict hygiene rules (f785a3f). Release of 9.0.0 (d2ab109) followed by 17 refactoring passes deleting 16,500 lines across js/, css/, and py/.

Closure of the 9.1.0 audit (13 October)

Review 9.1.0 closed all ten findings with automated tests in 14a7fab: persistence boundary protection (test_persistence_boundary.js), closed HTML sink whitelist (test_html_sinks.js), provider inheritance (test_providers.js), and help page consistency (test_help_pages.js).

9.1 to 9.2 series: Document maturity, multimodality and optimization (13 – 16 October)

A period of expanding capabilities while actively shedding technical debt:

  • Office document ingestion and native parsing: Milestone M4 supported DOCX, PPTX, XLSX, and ODS in chat and RAG. Subsequently, milestone M17 (ee7e732) replaced the heavy ExcelJS dependency with an in-house lightweight native XLSX parser in js/office-parser.js, cutting ~1 MB from vendor bundles and eliminating complicated external licenses.
  • Multimodal web vision (M19): Builtin download_image tool (88ede9e) allowing multimodal models to directly fetch, validate, and analyze web images with anti-SSRF protections.
  • In-chat document generation (M13): Interactive generation of HTML, SVG, and CSV documents in chat (c9b0b0c), with secure Blob previews and CSV table exports.
  • Project memory automation (M9): Creation of task.py (37ba6a0, cca1c87) to atomically record tasks, architectural decisions, and milestone states in .zerochat/, preventing memory desynchronization.
  • Test suite optimization (M5): Domain-based test suite consolidation (ccf7bec), timer acceleration, and withTestApp harness (468bf8b), reaching 864 tests running in seconds.
  • Documentation colocation and rules: Slimmed down AGENTS.md (93766e5) by relocating subsystem contracts into colocated README.md files and capping tasks at ~300 lines.

9.3 to 9.5 series: own web transport and test pruning (16 – 17 October)

Public proxies are removed and web transport becomes the local server or, without it, Jina Reader, with DuckDuckGo search (M21, M23, M27; b15e953, 029b4c8). The external diff viewer arrives in the file-write cards (9.4.0, M20, 7541dca). happy-dom is removed and trivial or duplicate tests are pruned, with written criteria for keeping or deleting them (M24, 62682d7). The post-9.2.3 review is fixed in M26 (ca8ce1d).

9.6 series: unattended runs, profiles and Playwright (17 – 19 October)

zerochat --prompt runs a prompt in the interface and returns the answer in the terminal, with profile, export and hidden window (M18, from a4b9bbd). Connection profiles become configuration profiles, with the MCP services they start and the model's browser (M29). Playwright MCP gains its own engines, installed from Settings, and a mode with the user's browser (M3, 94ed197, 5b6a5b6).

9.7 and 9.8 series: scoped audits and live state (20 – 21 October)

Two scoped audits between minor versions close with their tasks (M30, M31) and the tests added since 9.2.0 are reviewed (M32). The local server becomes the single source of state that changes during a session: external services, commands and Playwright arrive in the heartbeat (M33, b92e9d7). The most complex frontend hotspots are simplified (M34, M35).

9.9 and 9.10 series: structure and reconnection (22 – 23 October)

PDF reader bounded by each stream (M36), guided diff viewer setup (M37), bilingual home page with a generated sitemap (M28, ba04ab0), model-view-controller separation in the dialogs (M38), interface logic tested without a browser (M39), automatic reconnection to the local server (M40, 7120ce7) and a suite that runs in half the time (M41). For using the home server from Android through an SSH tunnel, zerochat --print-url arrives; 9.11 replaces it with sign-in.

9.11 series: one way to connect (24 October)

Transport with the local server becomes POST-only, without an SSE channel (4e39189). The daily token also expires while the server runs (2476077) and, when it is missing or expired, the page asks for the user name and password of the system account (fb8dd4b). Settings › Connection unifies the local server, the SSH tunnel and the reverse proxy (6407dc1, 3f12d81). The design decisions were recorded before starting (M42-D10 to D17).

3. Rules and tests over time

RuleIn AGENTS.mdTest addedLagWhat the test found upon arrival
Dialogs with ChatDialogs09/09 (11a0389)09/09 (c87f69b)0 daysZero defects; test existed from day one
ChatState domain slices07/09 (3481a07)03/10 (2059455)26 daysDirect mutations on the ui slice
Explicit error handling (frontend)07/09 (3481a07)04/10 (cf7aca4)27 days116 empty catch blocks
Visible text with ChatI18n06/09 (66a1967)04/10 (46b6228)28 days10 untranslated string literals
Explicit error handling (backend)07/09 (3481a07)12/10 (72deff7)35 daysSilent generic catches across 7 files
Styles using tokens.css tokens06/09 (66a1967)12/10 (26abb4c)36 daysLiteral color values and var() fallbacks across 58 files
No fallbacks, legacy compatibility, or test exports11/10 (f785a3f)11/10 (f785a3f)0 days (after 46 d)The great 9.0.0 cleanup (16,500 lines removed)
mount() with delegated listeners12/10 (98f07af)13/10 (9ff0df4)1 dayDuplicate listener attachments in MCP panel
Injected chat messages in English08/09 (cfdab94)13/10 (631f2d3)35 daysOne system profile description in Spanish
External data kept out of innerHTML13/10 (29a1af3)13/10 (29a1af3)0 daysMarkup injection in SVG attributes in render_chart
Bilingual synchronized help pages13/10 (975a723)13/10 (975a723)0 daysAPI key help pages missing language switcher
Memory automation and sentinel (task.py)14/10 (37ba6a0)14/10 (cca1c87)0 daysPrevents desynchronization in milestone plans
Single source of truth and exact N/N+1 limits15/10 (b4aad8a)15/10 (976ab59)0 daysRow loss at the 500-row cap in ODS tables
No production code used only by tests17/10 (2b663f0)17/10 (2b663f0)0 daysParameters and injections that only existed for tests
Sitemap and unique titles and descriptions22/10 (ba04ab0)22/10 (ba04ab0)0 daysBorn with the bilingual home page and the generated sitemap
One source also between JavaScript and Python15/10 (b4aad8a)24/10 (f2e7224)9 daysEngines, browsers and the extension token, now in a fixture both suites check

Interpretation: the lag between writing a rule and having its test was historically the main source of technical debt. Since the 9.x series almost every rule arrives with its test in the same commit; the recent exception, one source between JavaScript and Python, took 9 days because until M42 there was no fixture shared by both suites.

4. What history teaches

  • Code improves by trimming dependencies: Replacing ExcelJS with a focused, native XLSX parser showed that simplifying architecture yields better maintainability than piling on vendor libraries.
  • Tests must consolidate around domains: Reorganizing test suites in milestone M5 demonstrated that consolidating suites and removing synthetic delays increases test coverage (from 756 to 864 tests) while speeding up execution.
  • Scoping tasks preserves control: Capping tasks at ~300 lines and creating shared bases before rolling out multiple format variants stops sister implementations from diverging.
  • Fewer tests can cover more: from 9.2.3 to 9.11.0 the suite dropped from 864 to 702 cases while features grew, because each behavior is now tested once, at the lowest level that observes it.
  • Decide before coding: in M42 the remote connection design was discussed and recorded as decisions before the first line of code; the seven tasks were then completed without redoing any.

Interpretation: 9.11.0 changes the local server's network surface more than any earlier version, and does so with the same discipline: every decision recorded and every new behavior with its test.

5. Summary timeline

DateVersionCommitKey milestone
26/08v0.939fed30ChatCLI creation
02/09v5.3d37ff35First AGENTS.md
09/09v6.5.411a0389Custom dialogs guarded by automated test
11/09v6.6.0e20a70cIn-browser WebLLM integration
17/09v7.0.0f58544fEnd of client bundle; unification in zerochat.py
04/10v8.12.4aff1019Audited release
11/10v9.0.0d2ab109Great cleanup; unbounded agent and subagents
12/109.1.0a0393c3Baseline of the 9.1.0 review
13/109.1.014a7fabTotal closure of the 10 infrastructure findings
14/10v9.1.237ba6a0Project memory automation with task.py
15/10v9.1.58e449f8Office document support (Word, Excel, PowerPoint, ODS)
15/10v9.1.61177deeNative XLSX reader and removal of ExcelJS
15/10v9.2.002710d7Bump to 9.2.0 with unified backend and office support
16/10v9.2.12df3888In-chat document generation and table CSV export (M13)
16/10v9.2.2233ae57download_image tool and multimodal web vision (M19)
16/10v9.2.3924aef6Test suite consolidation (M5) and previous review
17/10v9.3.0b15e953No public proxies; unified web transport
17/10v9.4.08ce5e82External diff viewer
17/10v9.5.009e2fcfWeb transport hardened after the 9.2.3 review
19/10v9.6.007fc781Unattended runs, configuration profiles and Playwright engines
20/10v9.7.0957220aFixes from the scoped audits
21/10v9.8.0d93491aLive local server state in the heartbeat
22/10v9.9.04de3d1fBilingual home page, PDF stream bounds and visible Playwright browser window
22/10v9.10.0b8dea66zerochat --print-url for the tablet (removed in 9.11) and tool signatures with ±30 s clock skew
24/10v9.11.0170ee03Sign-in with the system account and Settings › Connection; reviewed version

Authorship

  • Review and drafting: Claude Opus 5.5 in Claude Code, from the Git history up to commit 170ee03; the phases up to 9.2.3 come from the previous review, by Antigravity (Gemini 3.8 Flash).