<feed xmlns='http://www.w3.org/2005/Atom'>
<title>newos4/modules/core/module-world-model.js, branch main</title>
<subtitle>newOS4 - the browser terminal that runs WebX11 user spaces</subtitle>
<id>https://newos.webx11.duckdns.org/newos4/atom?h=main</id>
<link rel='self' href='https://newos.webx11.duckdns.org/newos4/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://newos.webx11.duckdns.org/newos4/'/>
<updated>2026-10-23T19:35:02+00:00</updated>
<entry>
<title>fix(newos4): the virtual /sys entry leaked into listings, trees and counts (v4.6.88-90)</title>
<updated>2026-10-23T19:35:02+00:00</updated>
<author>
<name>Agando</name>
<email>roduccomm@gmail.com</email>
</author>
<published>2026-10-23T19:35:02+00:00</published>
<link rel='alternate' type='text/html' href='https://newos.webx11.duckdns.org/newos4/commit/?id=d5b6e6f12c8c3c4551050f8fc7d19fb78d6b581b'/>
<id>urn:sha1:d5b6e6f12c8c3c4551050f8fc7d19fb78d6b581b</id>
<content type='text'>
One phantom entry, three symptoms:
- ls() injected 'sys' whenever it was called without a path, so 'cd _agents; ls' advertised a
  sys directory that does not exist, and list_files('_agents/sys') answered 'Directory not
  found' — the reported false negative. Injection is now gated on dir === root.
- tree() pushed the same virtual name into the walk and dereferenced it, throwing mid-output on
  every root listing. Guarded.
- _gatherFileInfo() walked into /sys and counted a synthetic subtree: 146 files / 114 dirs for a
  44-file / 15-dir store. Virtual entries are skipped.

Verified: root still lists sys; _agents and skills do not; tree('') completes; world model total
(44) equals an independent walk of fs.root (44), agree: true.
</content>
</entry>
<entry>
<title>fix(newos4): world_model_query default path parses again (v4.6.83-84)</title>
<updated>2026-10-23T19:22:30+00:00</updated>
<author>
<name>Agando</name>
<email>roduccomm@gmail.com</email>
</author>
<published>2026-10-23T19:22:30+00:00</published>
<link rel='alternate' type='text/html' href='https://newos.webx11.duckdns.org/newos4/commit/?id=cdba58ccda05d10dd02f9dcb447f624377744b21'/>
<id>urn:sha1:cdba58ccda05d10dd02f9dcb447f624377744b21</id>
<content type='text'>
_modelDigest() returned JSON.stringify(...) cut at 4000 chars plus '…(digest truncated)'. The
tool then did JSON.parse() on it, so the default detail threw 'Unexpected end of JSON input'
every single call; detail:'full' worked only because it returned the object untouched.

The digest now returns an OBJECT (_modelSnapshot) and shrinks by reducing list lengths, then by
dropping whole sections with an explicit 'omitted' list. The string form is generated at the
edge and is always valid JSON.

Verified: default call -&gt; no error, 13-key snapshot, facts answered; caps 400/1200/4000 all under
cap and parseable; the residual floor at cap 200 is identity fields only.
</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=5a7230121afc75ad96f1ed32ac90791a98fabce2'/>
<id>urn:sha1:5a7230121afc75ad96f1ed32ac90791a98fabce2</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): unmeasured skills are untracked, world-model writes verified, skill audit</title>
<updated>2026-10-23T12:39:45+00:00</updated>
<author>
<name>Agando</name>
<email>roduccomm@gmail.com</email>
</author>
<published>2026-10-23T12:39:45+00:00</published>
<link rel='alternate' type='text/html' href='https://newos.webx11.duckdns.org/newos4/commit/?id=fa6eca3eda89e88b01f58bc01ef60f3e7e5473fb'/>
<id>urn:sha1:fa6eca3eda89e88b01f58bc01ef60f3e7e5473fb</id>
<content type='text'>
External review packet (os4-external-review-v4.6.51.html) triaged against the code:
2 findings confirmed and fixed, 4 could not be reproduced and were recorded as such.

- module-memory-graph.js: getStaleSkills() treated a missing lastUsed as 999 days
  unused, so skill-audit recommended archiving every skill (22 of 22). Skills with no
  usage telemetry are now collected by getUntrackedSkills() and never counted stale.
  Live: "Stale: 0" + "Untracked: 22 (no usage telemetry — NOT stale)".
- module-world-model.js: _saveToVFS() ignored fsWriteJSON()'s return value and promoted
  whatever a truthy read returned. Now write -&gt; read-back -&gt; byte compare -&gt; promote,
  with every return checked. Regression test modules/test/test-world-model-save.js
  (red on the old code: promoted=true with errs=[]; green now).
- scripts/newos4-skill-audit.py: 5 mechanical probes (version x3, read_file paging +
  context budget, selection symbols, required scripts, extKeys) + skill presence;
  exits non-zero on drift. 7/7 pass today. Weekly job cb6bc2a16216 runs it Mondays.

Not reproduced (recorded in admin/docs/newos4-external-review-verification-2026-10-23.md):
world_model_query empty-payload throw (live call returns JSON), pipes-as-command-names,
ls skills empty (23 entries via fs.readDir), ~66 agent dirs (4 live).
</content>
</entry>
<entry>
<title>feat(newos4): world-model-ask answers with the LLM, grounded in the model (v4.6.50)</title>
<updated>2026-10-21T22:46:05+00:00</updated>
<author>
<name>Agando</name>
<email>roduccomm@gmail.com</email>
</author>
<published>2026-10-21T22:46:05+00:00</published>
<link rel='alternate' type='text/html' href='https://newos.webx11.duckdns.org/newos4/commit/?id=70b9a2f8cc2b249362ca4893fdbb6703c0ea7b8a'/>
<id>urn:sha1:70b9a2f8cc2b249362ca4893fdbb6703c0ea7b8a</id>
<content type='text'>
`world-model-ask` was a 10-keyword lookup: any real question returned
"Unknown query. Try: modules, skills, ...". The documented example
("what changed since yesterday") compared nothing — it restated the current
snapshot.

- _modelDigest(): whitelisted snapshot (measured 942-965 chars on fixtures,
  ~3.3 KB live) + recent error sample + changesSinceLastSnapshot
- _buildAskPrompt(): "answer only from this JSON, never invent numbers, name the
  command that would produce missing data"
- ask(): connects Ollama on demand, answers via chat(), falls back to the facts
  path with a visible warning; --facts keeps the instant lookup
- _diffSincePrev(): keeps one previous snapshot in /system/world-model.prev.json
  so "what changed" is a real diff (files 136 -&gt; 140)
- world_model_query tool returns the snapshot (digest or detail:full) instead of
  ten canned strings; no nested LLM call inside a tool call
- help text now says what it does; node test modules/test/test-world-model-ask.js
  (11 assertions, runs the real class)

Verified live v4.6.50: facts "Loaded 46 modules" | LLM "The snapshot does not
contain information regarding the cause of memory growth ... use
world-model-refresh" | diff "files 136 -&gt; 140" | tool snapshot 3,334 bytes.
</content>
</entry>
<entry>
<title>auto: 2026-07-09_06:00 changes</title>
<updated>2026-07-09T04:00:32+00:00</updated>
<author>
<name>Agando</name>
<email>roduccomm@gmail.com</email>
</author>
<published>2026-07-09T04:00:32+00:00</published>
<link rel='alternate' type='text/html' href='https://newos.webx11.duckdns.org/newos4/commit/?id=2538c91876455fe96febf441fc8dde20f2606023'/>
<id>urn:sha1:2538c91876455fe96febf441fc8dde20f2606023</id>
<content type='text'>
</content>
</entry>
<entry>
<title>auto: 2026-06-17_06:01 changes</title>
<updated>2026-06-17T04:01:20+00:00</updated>
<author>
<name>Agando</name>
<email>roduccomm@gmail.com</email>
</author>
<published>2026-06-17T04:01:20+00:00</published>
<link rel='alternate' type='text/html' href='https://newos.webx11.duckdns.org/newos4/commit/?id=cebacc27a48168e666679018f8e27156d12d4527'/>
<id>urn:sha1:cebacc27a48168e666679018f8e27156d12d4527</id>
<content type='text'>
</content>
</entry>
<entry>
<title>auto: 2026-06-06_06:00 changes</title>
<updated>2026-06-06T04:00:27+00:00</updated>
<author>
<name>Agando</name>
<email>roduccomm@gmail.com</email>
</author>
<published>2026-06-06T04:00:27+00:00</published>
<link rel='alternate' type='text/html' href='https://newos.webx11.duckdns.org/newos4/commit/?id=ccc7d9956559d2195e20345e7a794662b52cd403'/>
<id>urn:sha1:ccc7d9956559d2195e20345e7a794662b52cd403</id>
<content type='text'>
</content>
</entry>
<entry>
<title>auto: 2026-06-05_18:01 changes</title>
<updated>2026-06-05T16:01:01+00:00</updated>
<author>
<name>Agando</name>
<email>roduccomm@gmail.com</email>
</author>
<published>2026-06-05T16:01:01+00:00</published>
<link rel='alternate' type='text/html' href='https://newos.webx11.duckdns.org/newos4/commit/?id=b538577cd0a4292e4cd4ca1c9f9829fc7e133caa'/>
<id>urn:sha1:b538577cd0a4292e4cd4ca1c9f9829fc7e133caa</id>
<content type='text'>
</content>
</entry>
</feed>
