<feed xmlns='http://www.w3.org/2005/Atom'>
<title>newos4/modules/core/module-system.js, branch v4.6.168</title>
<subtitle>newOS4 - the browser terminal that runs WebX11 user spaces</subtitle>
<id>https://newos.webx11.duckdns.org/newos4/atom?h=v4.6.168</id>
<link rel='self' href='https://newos.webx11.duckdns.org/newos4/atom?h=v4.6.168'/>
<link rel='alternate' type='text/html' href='https://newos.webx11.duckdns.org/newos4/'/>
<updated>2026-11-12T15:39:12+00:00</updated>
<entry>
<title>fix(newos4): honest size/network measurements + checkpoint and phantom-delete fixes (v4.6.160)</title>
<updated>2026-11-12T15:39:12+00:00</updated>
<author>
<name>Hermes SysOp</name>
<email>sysop@webx11.duckdns.org</email>
</author>
<published>2026-11-12T15:39:12+00:00</published>
<link rel='alternate' type='text/html' href='https://newos.webx11.duckdns.org/newos4/commit/?id=228ad621e2631487e74acdf9bf58e797f60ab745'/>
<id>urn:sha1:228ad621e2631487e74acdf9bf58e797f60ab745</id>
<content type='text'>
Applies the three 2026-11-09 patches after review, and fixes two more
navigator.onLine lies found while verifying them. Each patch was checked
against the live code first; one of its claims did not survive.

1. virtual-fs — phantom deletes and checkpoint bloat
   - deleteCheckpoint('nope') returned true and printed "Deleted checkpoint"
     for a name that did not exist: _resolvePath() validates intermediate
     segments only, so the leaf was never checked. New _requireLeaf() refuses
     a resolved path whose leaf is absent, and deleteCheckpoint uses it.
   - CHECKPOINT SIZE: checkpoint() cloned the whole root minus
     _snapshots/_sessions/.trash, so _mods (module originals) and
     .semantic_index were duplicated into EVERY checkpoint — measured
     2,101,686 bytes for a 2 MiB _mods. Both are now excluded on write and
     preserved across rollback (without the keep-list change a rollback would
     delete the live module originals). Measured after: 185 bytes.
   - Claim corrected: the patch also claimed deleteFile() reported success on
     a phantom path. It did not — live code already required
     `node &amp;&amp; node.type === 'file'` and returned false. The guard is kept as
     defence-in-depth, and the test asserts the real behaviour rather than the
     claimed one.

2. module-fs — vfs-size reported ~2x the real size
   - It measured JSON.stringify(root).length: UTF-16 code units PLUS every
     structural character of the serialisation. A 1046-byte tree printed as
     1961; anything under ~5 KB printed as "0.00 MB".
   - Every number is now stored bytes (UTF-8 of file content): one measure()
     walk for the total, the per-file table, the top-directory table and the
     system dirs, so the rows add up to the total. The patch's arithmetic was
     still off in seven places, all fixed here: a UTF-16 fallback that
     reintroduced the bug when Blob was missing, a top-5 table that could
     never sum to the total (now top 10 + an aggregated remainder row), the
     top-dirs table dropping files stored at root (now a "/(root files)" row),
     a 2-decimal MB total that printed 0.00 for small VFS, three duplicate
     hand-rolled walks, readDir() used for dir sizes, and "1 files".

3. module-system — status/doctor no longer trust navigator.onLine
   - status printed "Network: Offline" from navigator.onLine, which an
     Android WebView reports false while fully connected.
   - doctor now awaits a real HEAD probe (AbortController, 4 s): only
     'reachable' is healthy, a throw is HIGH "Network: unreachable", a non-ok
     answer is MEDIUM and names the status (405 to HEAD is not "offline").
   - THE PATCH'S THRESHOLDS COULD NEVER FIRE: it compared localStorage bytes
     against navigator.storage.estimate().quota, which is the whole-origin
     quota (GBs, mostly Cache Storage), while localStorage has its own ~5 MB
     cap — a 4.5 MB localStorage reported "All systems healthy" against a
     2 GB quota. Now: localStorage measured as (key+value)*2 UTF-16 bytes with
     HIGH &gt; 4 MiB / MEDIUM &gt; 3 MiB, VFS measured in UTF-8 bytes with
     HIGH &gt; 3 MiB and &gt; 80% of the measured localStorage bytes. The origin
     quota appears only in one informational line and decides no severity.
   - Also removed navigator.onLine from version, bug-report and bug (a grep
     for it is now 0 in the module), and added a "Measured:" line so a clean
     report still shows what was measured.

4. terminal.js / module-servermon.js — the same lie, where the user looks
   - The status bar printed "❌ Offline" in red from navigator.onLine; on a
     WebView that is false while online. It now shows "📶 Network?" with a
     title pointing at `doctor` unless the browser claims online.
   - `net` test line now reads "Browser reports: offline (unreliable)" as a
     warning instead of a red failure — the real verdict comes from the
     probes that follow.

Verified: 40/40 node tests (3 new files: 36 + 53 + 34 assertions, each proven
red against the pre-patch code; the doctor test runs against the PATCH's
threshold logic and shows the 4.5 MB case staying silent). An independent
orchestrator probe re-derived all of it: phantom delete false, 2 MB _mods
absent from the checkpoint and preserved through rollback, vfs-size exact
bytes for ASCII/é/☃ nested trees, 4.5 MB localStorage HIGH despite a 2 GB
quota, failing probe unreachable, status never claiming Online/Offline.
Served bytes identical for core-bundle.js / main.html / module-system.js /
virtual-fs.js. Live Chromium on v4.6.160: vfs-size "85.8 KB (87880 bytes)
across 40 files", doctor "Measured: VFS 0.08 MB UTF-8 · localStorage 0.07 MB
UTF-16 in 14 keys", a stubbed failing probe reports HIGH unreachable, the
status bar reads "📶 Network?" when the browser lies, deleteCheckpoint on a
missing name returns false, and the console has 0 warnings and 0 JS errors.
</content>
</entry>
<entry>
<title>fix(newos4): help names the owner of an undocumented command; loop lessons leave /skills</title>
<updated>2026-10-27T14:23:38+00:00</updated>
<author>
<name>Agando</name>
<email>roduccomm@gmail.com</email>
</author>
<published>2026-10-27T14:23:38+00:00</published>
<link rel='alternate' type='text/html' href='https://newos.webx11.duckdns.org/newos4/commit/?id=5c7178fbe1120c6843f87928a6f2c4ca470e92a8'/>
<id>urn:sha1:5c7178fbe1120c6843f87928a6f2c4ca470e92a8</id>
<content type='text'>
Two board items plus the context-window close-out.

- MAINT-019 (module-system.js): `help &lt;cmd&gt;` answered "No help available for X" for a command
  that is registered but has no help line, which reads as if the command does not exist. It now
  says "X — registered by &lt;Module&gt;, which publishes no help line for it. Try: help". A command
  that genuinely does not exist still gets the old message.
- MAINT-020 (module-aiassist.js): auto-generated loop lessons were written into /skills with
  their own index entries, so `skill list` filled up with system noise. Lessons now live in
  /lessons with /lessons/index.json; the reader still falls back to legacy loop-lesson-* entries
  in /skills for one release, and the one-time migration deletes them from the skills index.

Verification: test-help-and-lessons.js (10 asserts, includes a lint-style guard that no lesson is
written into /skills). Suite 14/14 files green; maintain --fix "node tests 14/14 pass",
"help coverage 362/362". Live on v4.6.108: `help agent-register` -&gt; "registered by
AgentRegistryModule, which publishes no help line for it"; `help a2a-prune` unchanged;
`help nope-not-real` still "No help available".

MAINT-001 close-out (no code change here): history is capped at 20 messages with a "[context trim]"
marker (first trim at turn 11 in a 60-turn probe), token compression took 80 msgs/8080 tok to
17/2625, and since v4.6.107 one turn's tool bodies are clipped to 6 000 chars each and elided past
24 000 with the newest 4 kept verbatim. Residual, recorded on the board: maxContextTokens is never
sent to the server as num_ctx, so the real window is whatever the endpoint defaults to.

MAINT-018 close-out: not reproducible. Live probes on v4.6.107/108 — `sed -n '1,3p' /probe.txt`
prints lines 1-3, `sed -n "2,4p"` prints 2-4, `grep 'line4'` matches, and the same commands inside
`script /q.sh` print correctly. The "Command not found: for;" symptom belongs to the line-by-line
script runner, which is MAINT-021 and stays open.
</content>
</entry>
<entry>
<title>fix(newos4): print the checkpoint name actually saved (auto)</title>
<updated>2026-10-27T07:32:39+00:00</updated>
<author>
<name>Agando</name>
<email>roduccomm@gmail.com</email>
</author>
<published>2026-10-27T07:31:56+00:00</published>
<link rel='alternate' type='text/html' href='https://newos.webx11.duckdns.org/newos4/commit/?id=1f7b33ce2f213217f5a162d9171f5897a1154194'/>
<id>urn:sha1:1f7b33ce2f213217f5a162d9171f5897a1154194</id>
<content type='text'>
Task 2 + ship of plan 2026-10-27_061724-newos4-checkpoint-name-mismatch.md.

module-system.js `checkpoint` read the clock a second time for the printed
name, so the name in "✅ Checkpoint created: &lt;name&gt;" differed from the name on
disk by &gt;=1ms whenever no explicit name was given. It now prints the value
returned by fs.checkpoint(). try/catch and error strings unchanged.

Bundles rebuilt (rebuild-bundles.py); LATEST_VER in module-loader.js and all
three ?v= tags in main.html (core-bundle, module-loader, critical-ext-bundle)
bumped v4.6.101 -&gt; v4.6.102.

Verification:
  $ node --check modules/core/module-system.js
  SYNTAX OK
  $ node --check modules/core/core-bundle.js
  BUNDLE SYNTAX OK
  $ node modules/test/test-vfs-checkpoint.js   (x5)
  test-vfs-checkpoint: 10 passed, 0 failed
  $ curl -s https://webx11.duckdns.org/spaces/newos4/main.html | grep -o 'core-bundle.js?v=[^"]*'
  core-bundle.js?v=v4.6.102
  $ python3 scripts/newos4-maintain.py
  PASS: version v4.6.102 x3 in main.html (expect 3) ... maintenance result: OK
  $ python3 scripts/newos4-skill-audit.py
  skill audit: 7/7 pass
</content>
</entry>
<entry>
<title>fix(newos4): one error counter for errors/dashboard/world-model (v4.6.61)</title>
<updated>2026-10-23T16:15:05+00:00</updated>
<author>
<name>Agando</name>
<email>roduccomm@gmail.com</email>
</author>
<published>2026-10-23T16:15:05+00:00</published>
<link rel='alternate' type='text/html' href='https://newos.webx11.duckdns.org/newos4/commit/?id=d100ad3c57f4a18dacb2cbc11cfdc5590f20cf08'/>
<id>urn:sha1:d100ad3c57f4a18dacb2cbc11cfdc5590f20cf08</id>
<content type='text'>
Packet 2 (three surfaces, three answers). Measured first: `errors` scanned
/logs/current.log for [ERROR] lines, but that file only ever receives explicit
terminal.log('ERROR', ...) calls -- exactly one call site in the whole app -- so it
read 0. The dashboard added DebugSupervisor._errorDB plus failed tool calls (18),
and the world model read the debug DB alone (11).

- terminal.countErrors() / countLogErrors(): the single counter, exposed on the one
  object all three surfaces already hold
- `errors` prints the canonical total with its breakdown, the entry list (hash,
  count, severity, message), and reports the log scan separately as a mirror
- dashboard health.errors and health.errorBreakdown derive from it
- world model telemetry.recentErrors derives from it, plus errorsBySource
- terminal.log('ERROR', ...) now also records into DebugSupervisor, so the log is a
  human-readable mirror of one store instead of a second store almost nobody wrote

Verified live on v4.6.61: with a seeded debug entry + failed tool call, all three
report 2; a single log('ERROR') call moves debug 1-&gt;2 and the total by exactly 1
(the mirror line is counted once, in the log, and reported separately).
</content>
</entry>
<entry>
<title>fix(newos4): empty-pipeline crash, stacks in reports, frame in digest + dashboard (v4.6.55)</title>
<updated>2026-10-23T13:55:51+00:00</updated>
<author>
<name>Agando</name>
<email>roduccomm@gmail.com</email>
</author>
<published>2026-10-23T13:55:51+00:00</published>
<link rel='alternate' type='text/html' href='https://newos.webx11.duckdns.org/newos4/commit/?id=ef7e4d4d64c294240542c74d8ad2f99b7ef641f2'/>
<id>urn:sha1:ef7e4d4d64c294240542c74d8ad2f99b7ef641f2</id>
<content type='text'>
Root cause: splitPipe() splits on every '|', so `help |`, `| wc -l`, `a || b` produced a stage with
no argv and executePipeChain() called parts[0].toLowerCase() on undefined — 989 occurrences, first
filed 2026-10-20, unfixable from the report because bug reports dropped the stack that named
executePipeChain:3955. Same unguarded read existed in _classify().

- terminal.js: _classify() returns an inert classification for empty argv; executePipeChain()
  parses each stage once, filters stages with no argv (so the last real stage stays final), warns
  only when the whole pipeline is empty. Last-stage test now compares against the filtered length.
- module-system.js: `bug` diagnostics include the stack (10 frames, 1200 chars); auto-filed reports
  carry it too — they are the majority of the inbox and were previously message-only.
- report.php: per-stack 2 KB cap; fingerprint pinned to message/source/count so adding `stack`
  cannot break dedupe against reports filed before today.
- ingest.php: first_frame() parsed once on ingest, stored as `frame` on each signature.
- newos4-triage.py: FRAME| line with the first application frame.
- dashboard.php: frame under each Top Errors row.
- modules/test/test-pipe-guard.js: ordering tripwire (guard must precede the parts[0] read).

Verified: test RED exit=1 -&gt; GREEN exit=0; browser matrix on v4.6.55 (help |, | wc -l,
echo hi || echo bye, ls | | wc -l, |) -&gt; 0 new error signatures, "|" warns;
auto-filed report now carries stack (RPT-...f3e31124, archived after the probe);
frame = modules/core/core-bundle.js:3955:42; maintain OK; skill audit 7/7.
</content>
</entry>
<entry>
<title>newOS4 v4.6.40: review fixes (bug diagnostics, trash tree, dir paste, stale capture, preview)</title>
<updated>2026-10-18T15:19:14+00:00</updated>
<author>
<name>Agando</name>
<email>roduccomm@gmail.com</email>
</author>
<published>2026-10-18T15:19:14+00:00</published>
<link rel='alternate' type='text/html' href='https://newos.webx11.duckdns.org/newos4/commit/?id=240e22bc2e4f6b67b032c0a317e456958520fe90'/>
<id>urn:sha1:240e22bc2e4f6b67b032c0a317e456958520fe90</id>
<content type='text'>
</content>
</entry>
<entry>
<title>newOS4 v4.6.37: bug-report pipeline (report.php, bug command, HTML generator, telemetry-loop fix)</title>
<updated>2026-10-18T15:01:52+00:00</updated>
<author>
<name>Agando</name>
<email>roduccomm@gmail.com</email>
</author>
<published>2026-10-18T15:01:52+00:00</published>
<link rel='alternate' type='text/html' href='https://newos.webx11.duckdns.org/newos4/commit/?id=d7a1198aa7ac77cbe9d3f0c844245dd08a8ccd12'/>
<id>urn:sha1:d7a1198aa7ac77cbe9d3f0c844245dd08a8ccd12</id>
<content type='text'>
</content>
</entry>
<entry>
<title>auto: 2026-06-18_06:00 changes</title>
<updated>2026-06-18T04:00:40+00:00</updated>
<author>
<name>Agando</name>
<email>roduccomm@gmail.com</email>
</author>
<published>2026-06-18T04:00:40+00:00</published>
<link rel='alternate' type='text/html' href='https://newos.webx11.duckdns.org/newos4/commit/?id=fba6df22dae297c89fa0df065628dddded66c69c'/>
<id>urn:sha1:fba6df22dae297c89fa0df065628dddded66c69c</id>
<content type='text'>
</content>
</entry>
<entry>
<title>auto: 2026-06-14_06:00 changes</title>
<updated>2026-06-14T04:00:14+00:00</updated>
<author>
<name>Agando</name>
<email>roduccomm@gmail.com</email>
</author>
<published>2026-06-14T04:00:14+00:00</published>
<link rel='alternate' type='text/html' href='https://newos.webx11.duckdns.org/newos4/commit/?id=3dda77c60c19ebe810ac86e35a5c510c737b7b39'/>
<id>urn:sha1:3dda77c60c19ebe810ac86e35a5c510c737b7b39</id>
<content type='text'>
</content>
</entry>
<entry>
<title>auto: 2026-06-13_18:00 changes</title>
<updated>2026-06-13T16:00:58+00:00</updated>
<author>
<name>Agando</name>
<email>roduccomm@gmail.com</email>
</author>
<published>2026-06-13T16:00:58+00:00</published>
<link rel='alternate' type='text/html' href='https://newos.webx11.duckdns.org/newos4/commit/?id=de713efd619360e29b9bfc4b99d30d2a86b96caf'/>
<id>urn:sha1:de713efd619360e29b9bfc4b99d30d2a86b96caf</id>
<content type='text'>
</content>
</entry>
</feed>
