aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAgando <roduccomm@gmail.com>2026-06-04 06:01:04 +0200
committerAgando <roduccomm@gmail.com>2026-06-04 06:01:04 +0200
commita5023e61be61f2f2287342039addab6bb28ad2fd (patch)
tree9b1b3c166869cd6fee91bffe1f4134513005b8b1
parent301f75ab03302a05b3c35950a3b0ab49f9f69ed6 (diff)
auto: 2026-06-04_06:00 changes
-rw-r--r--cheatsheet.html36
-rw-r--r--downloads/newos4_whitepaper.html11
-rw-r--r--help.html78
-rw-r--r--modules-index.json879
-rw-r--r--modules/core/module-agent-registry.js128
-rw-r--r--modules/core/module-aiassist.js208
-rw-r--r--modules/core/module-loader.js6
-rw-r--r--modules/core/module-modmgr.js34
-rw-r--r--modules/core/module-neural-vfs.js271
-rw-r--r--modules/core/module-ollama.js177
-rw-r--r--modules/core/module-ollamamodels.js87
-rw-r--r--modules/core/module-orchestrator.js16
-rw-r--r--modules/core/module-servermon.js172
-rw-r--r--modules/core/terminal.js5
-rw-r--r--modules/core/virtual-fs.js52
-rw-r--r--modules/ext/mindmap.js77
-rw-r--r--newos4_vision.html10
-rw-r--r--packages.json127
-rw-r--r--review-newos4.html36
-rw-r--r--skills/a2a-contract-framework.md30
-rw-r--r--skills/bug-tracker.md1
-rw-r--r--skills/index.json2
-rw-r--r--skills/localize-external-assets.md18
-rw-r--r--skills/macro-engine-debug.md20
-rw-r--r--skills/macro-engine-onboarding.md20
-rw-r--r--skills/macro-engine.md28
-rw-r--r--skills/memory-and-profile.md30
-rw-r--r--skills/memory-map.md51
-rw-r--r--skills/memory.md66
-rw-r--r--skills/mindmap-master-guide.md40
-rw-r--r--skills/mindmap-user-guide.md40
-rw-r--r--skills/mindmap-workflow.md39
-rw-r--r--skills/mindmap.md50
-rw-r--r--skills/neural-vfs-indexer.md21
-rw-r--r--skills/project-profile-manager.md1
-rw-r--r--skills/task-manager.md1
-rw-r--r--skills/webdav-operations.md33
-rw-r--r--skills/webdav-sync.md40
-rw-r--r--skills/webdav.md44
-rw-r--r--skills/webx11-dev-cycle.md1
40 files changed, 2419 insertions, 567 deletions
diff --git a/cheatsheet.html b/cheatsheet.html
index 6245807..0ce8299 100644
--- a/cheatsheet.html
+++ b/cheatsheet.html
@@ -139,7 +139,8 @@ pre{background:var(--bg2);border:1px solid var(--border);border-radius:var(--rad
<h2>πŸ–₯️ System</h2>
<div class="grid">
-<div class="item"><span class="cmd">status</span><span class="desc">System health</span></div>
+<div class="item"><span class="cmd">status</span><span class="desc">System status overview</span></div>
+<div class="item"><span class="cmd">system-health</span><span class="desc">Tool latency, VFS, memory</span></div>
<div class="item"><span class="cmd">mem</span><span class="desc">Memory usage</span></div>
<div class="item"><span class="cmd">echo &lt;text&gt;</span><span class="desc">Print text</span></div>
<div class="item"><span class="cmd">date / cal</span><span class="desc">Date & calendar</span></div>
@@ -147,6 +148,39 @@ pre{background:var(--bg2);border:1px solid var(--border);border-radius:var(--rad
<div class="item"><span class="cmd">logs &lt;n&gt;</span><span class="desc">View recent logs</span></div>
<div class="item"><span class="cmd">logrotate</span><span class="desc">Rotate log files</span></div>
<div class="item"><span class="cmd">config</span><span class="desc">Config manager UI</span></div>
+<div class="item"><span class="cmd">checkpoint</span><span class="desc">VFS snapshot</span></div>
+<div class="item"><span class="cmd">checkpoint-list</span><span class="desc">List VFS snapshots</span></div>
+<div class="item"><span class="cmd">rollback</span><span class="desc">Restore VFS snapshot</span></div>
+<div class="item"><span class="cmd">vfs-export</span><span class="desc">Export VFS as JSON</span></div>
+<div class="item"><span class="cmd">vfs-import</span><span class="desc">Import VFS JSON</span></div>
+<div class="item"><span class="cmd">security-level</span><span class="desc">Set security 0-3</span></div>
+</div>
+
+<h2>🧠 Neural VFS</h2>
+<div class="grid">
+<div class="item"><span class="cmd">nvfs-index</span><span class="desc">Build semantic concept index</span></div>
+<div class="item"><span class="cmd">nvfs-resolve &lt;c&gt;</span><span class="desc">Find files by concept</span></div>
+<div class="item"><span class="cmd">concept://&lt;c&gt;</span><span class="desc">Read file via semantic concept</span></div>
+<div class="item"><span class="cmd">nvfs-tree [c]</span><span class="desc">Concept tree view</span></div>
+<div class="item"><span class="cmd">nvfs-status</span><span class="desc">Index stats</span></div>
+</div>
+
+<h2>πŸ€– Agents & A2A</h2>
+<div class="grid">
+<div class="item"><span class="cmd">agent-list</span><span class="desc">List AI agents</span></div>
+<div class="item"><span class="cmd">agent-status &lt;id&gt;</span><span class="desc">Agent details</span></div>
+<div class="item"><span class="cmd">orchestrate &lt;t&gt;</span><span class="desc">Delegate task</span></div>
+<div class="item"><span class="cmd">orchestrator-status</span><span class="desc">Agent pool status</span></div>
+<div class="item"><span class="cmd">contract-list</span><span class="desc">List A2A contracts</span></div>
+<div class="item"><span class="cmd">contract-register</span><span class="desc">Register A2A contract</span></div>
+</div>
+
+<h2>πŸ“Š Monitor</h2>
+<div class="grid">
+<div class="item"><span class="cmd">server &lt;n&gt; &lt;u&gt;</span><span class="desc">Add server to monitor</span></div>
+<div class="item"><span class="cmd">servers</span><span class="desc">List monitored servers</span></div>
+<div class="item"><span class="cmd">server-check</span><span class="desc">Check server status</span></div>
+<div class="item"><span class="cmd">monitor</span><span class="desc">Toggle auto-monitoring</span></div>
</div>
<h2>πŸ”’ Security / Vault</h2>
diff --git a/downloads/newos4_whitepaper.html b/downloads/newos4_whitepaper.html
index 0a12342..21079b8 100644
--- a/downloads/newos4_whitepaper.html
+++ b/downloads/newos4_whitepaper.html
@@ -175,7 +175,7 @@
<li>Security layer (0-3) and WPM lifecycle management.</li>
</ul>
- <h3>Phase 2 β€” Agentic Shift <span class="status-progress">🟑 IN PROGRESS</span></h3>
+ <h3>Phase 2 β€” Agentic Shift <span class="status-done">βœ… COMPLETED</span></h3>
<ul>
<li>βœ… AI tool-calling loop (19+ tools).</li>
<li>βœ… <code>session_terminal</code> zero-cost context access.</li>
@@ -183,6 +183,15 @@
<li>βœ… Agent orchestration (list, register, lease, orchestrate).</li>
<li>βœ… <strong>Localized Asset Management</strong> (Bypassing server security blocks).</li>
</ul>
+
+ <h3>Phase 3 β€” Cognitive OS <span class="status-progress">🟑 IN PROGRESS</span></h3>
+ <ul>
+ <li>βœ… Neural VFS β€” semantic concept indexing (nvfs-index, nvfs-resolve, nvfs-tree).</li>
+ <li>βœ… A2A Protocol β€” agent contracts with schema validation (contract-register, contract-list).</li>
+ <li>🟑 Recursive self-optimization β€” telemetry-driven latency diagnosis.</li>
+ <li>⬜ Predictive resource allocation.</li>
+ <li>⬜ Global World Model.</li>
+ </ul>
</section>
<footer>
diff --git a/help.html b/help.html
index 2b8a593..9d484fd 100644
--- a/help.html
+++ b/help.html
@@ -1088,13 +1088,53 @@ vfs-import</pre>
<div class="table-wrap"><table>
<tr><th>Command</th><th>Description</th></tr>
<tr><td><code>agent-list</code></td><td>List all registered agents with status</td></tr>
+ <tr><td><code>agent-status &lt;id&gt;</code></td><td>Show detailed status for a specific agent</td></tr>
<tr><td><code>agent-register &lt;name&gt; &lt;model&gt;</code></td><td>Register a new AI agent</td></tr>
+ <tr><td><code>agent-unregister &lt;id&gt;</code></td><td>Remove an agent from the registry</td></tr>
<tr><td><code>lease-list</code></td><td>Show active leases β€” agent tasks with status and TTL</td></tr>
<tr><td><code>orchestrate &lt;task&gt;</code></td><td>Delegate multi-step task to agent orchestrator</td></tr>
+ <tr><td><code>orchestrator-status</code></td><td>Show orchestrator agent pool status</td></tr>
+ <tr><td><code>orchestrator-spawn &lt;role&gt; [caps...]</code></td><td>Spawn a new worker agent</td></tr>
</table></div>
</section>
- <!-- ── Debug ── -->
+ <!-- ── A2A Contracts ── -->
+ <section id="a2a-contracts">
+ <h2>πŸ“œ A2A Contracts</h2>
+ <p>Define and enforce agent-to-agent contracts with input/output schema validation. Contracts are stored in <code>/.contracts/</code> and validated during orchestrator delegation.</p>
+ <div class="table-wrap"><table>
+ <tr><th>Command</th><th>Description</th></tr>
+ <tr><td><code>contract-register &lt;role&gt; [fields...] --output [fields...]</code></td><td>Register a contract with input/output schema</td></tr>
+ <tr><td><code>contract-list</code></td><td>List all registered contracts</td></tr>
+ </table></div>
+ </section>
+
+ <!-- ── Neural VFS ── -->
+ <section id="neural-vfs">
+ <h2>🧠 Neural VFS</h2>
+ <p>Semantic concept-indexing layer over the hierarchical VFS. Scans files and builds a concept β†’ path mapping using filenames, tags, and headers.</p>
+ <div class="table-wrap"><table>
+ <tr><th>Command</th><th>Description</th></tr>
+ <tr><td><code>nvfs-index</code></td><td>Scan VFS and build semantic concept index</td></tr>
+ <tr><td><code>nvfs-status</code></td><td>Show index stats and last scan time</td></tr>
+ <tr><td><code>nvfs-resolve &lt;concept&gt;</code></td><td>Find files related to a concept (exact + fuzzy)</td></tr>
+ <tr><td><code>nvfs-tree [concept]</code></td><td>Show concept-to-file mapping tree</td></tr>
+ </table></div>
+ </section>
+
+ <!-- ── Server Monitor ── -->
+ <section id="server-monitor">
+ <h2>πŸ“Š Server Monitor</h2>
+ <p>Uptime monitoring for external services + self-optimization telemetry tracking tool latency and error rates.</p>
+ <div class="table-wrap"><table>
+ <tr><th>Command</th><th>Description</th></tr>
+ <tr><td><code>server &lt;name&gt; &lt;url&gt;</code></td><td>Add a server to monitor</td></tr>
+ <tr><td><code>servers</code></td><td>List all monitored servers</td></tr>
+ <tr><td><code>server-check &lt;name&gt;</code></td><td>Check a server's current status</td></tr>
+ <tr><td><code>monitor</code></td><td>Toggle auto-monitoring (60s interval)</td></tr>
+ <tr><td><code>system-health</code></td><td>Show tool latency, VFS stats, module count, memory, error rates</td></tr>
+ </table></div>
+ </section>
<section id="debug-panel">
<h2>πŸ”§ Debug Panel</h2>
<p>Toggle the debug overlay to monitor system internals in real-time.</p>
@@ -1202,6 +1242,14 @@ listmods</pre>
<div class="quick-ref-item"><span class="cmd">date</span><span class="desc">Show time</span></div>
<div class="quick-ref-item"><span class="cmd">cal</span><span class="desc">Show calendar</span></div>
<div class="quick-ref-item"><span class="cmd">base64</span><span class="desc">Encode/decode</span></div>
+ <div class="quick-ref-item"><span class="cmd">nvfs-index</span><span class="desc">Build semantic index</span></div>
+ <div class="quick-ref-item"><span class="cmd">nvfs-resolve</span><span class="desc">Find files by concept</span></div>
+ <div class="quick-ref-item"><span class="cmd">mindmap svg</span><span class="desc">Render mindmap as SVG</span></div>
+ <div class="quick-ref-item"><span class="cmd">gui</span><span class="desc">Simple GUI builder</span></div>
+ <div class="quick-ref-item"><span class="cmd">contract-list</span><span class="desc">List A2A contracts</span></div>
+ <div class="quick-ref-item"><span class="cmd">modules-list</span><span class="desc">List all 45 modules</span></div>
+ <div class="quick-ref-item"><span class="cmd">orchestrate</span><span class="desc">Delegate to agent</span></div>
+ <div class="quick-ref-item"><span class="cmd">system-health</span><span class="desc">System diagnostics</span></div>
<div class="quick-ref-item"><span class="cmd">seq</span><span class="desc">Number sequence</span></div>
<div class="quick-ref-item"><span class="cmd">whoami</span><span class="desc">Show user</span></div>
<div class="quick-ref-item"><span class="cmd">basename</span><span class="desc">Strip dir path</span></div>
@@ -1218,6 +1266,34 @@ listmods</pre>
<h2>πŸ“‹ Changelog</h2>
<div class="version-item">
+ <div class="v-header"><span class="v-num">v4.3.1 β€” June 2026</span><span class="v-date">2026-06-03</span></div>
+ <ul>
+ <li><strong>Neural VFS</strong> β€” Semantic concept indexing layer: <code>nvfs-index</code>, <code>nvfs-resolve</code>, <code>nvfs-status</code>, <code>nvfs-tree</code></li>
+ <li><strong>A2A Protocol</strong> β€” Agent contract system: <code>contract-register</code>, <code>contract-list</code>, schema validation in orchestrator</li>
+ <li><strong>Self-Optimization Telemetry</strong> β€” <code>system-health</code> command showing tool latency, VFS stats, error rates</li>
+ <li><strong>AI tool: nvfs_resolve</strong> β€” AI can search VFS by concept</li>
+ <li><strong>Skills consolidated</strong> β€” 9 β†’ 4 unified; index rebuilt minified</li>
+ <li><strong>Docs sync</strong> β€” vision.html and whitepaper updated</li>
+ <li>Cache: <code>2026-06-03-neuralvfs</code> β€” hard refresh required</li>
+ </ul>
+ </div>
+
+ <div class="version-item">
+ <div class="v-header"><span class="v-num">v4.3.2 β€” June 2026</span><span class="v-date">2026-06-04</span></div>
+ <ul>
+ <li><strong>mindmap svg</strong> β€” Inline SVG rendering with colored rects + bezier curves</li>
+ <li><strong>GUI Builder</strong> β€” <code>gui</code>, <code>gui-button</code>, <code>gui-input</code> β€” SimpleGUIModule registered</li>
+ <li><strong>mermaid.min.js</strong> β€” Downloaded for webx11_mindmap.html</li>
+ <li><strong>get_module_status fixed</strong> β€” Shows all 34 loaded modules (was only HTTP-loaded)</li>
+ <li><strong>view_module fixed</strong> — Uses modules-index.json to resolve class→file paths</li>
+ <li><strong>module-ollamamodels merged</strong> β€” Into module-ollama (13 commands total)</li>
+ <li><strong>concept:// URIs</strong> β€” <code>cat concept://skill</code> resolves via Neural VFS</li>
+ <li><strong>Module categorization</strong> β€” <code>modules-list</code> shows [core], [ext], [infra] layer tags</li>
+ <li><strong>5 modules whitelisted</strong> β€” system-health, server, servers, server-check, monitor run directly</li>
+ </ul>
+ </div>
+
+ <div class="version-item">
<div class="v-header"><span class="v-num">v4.3 β€” June 2026</span><span class="v-date">2026-06-02</span></div>
<ul>
<li><strong>WebDAV Browser</strong> β€” Modern file-tree UI with checkboxes, Select All, bulk actions (Delete, Move, Download), inline rename (double-click), context menu, breadcrumbs, keyboard shortcuts</li>
diff --git a/modules-index.json b/modules-index.json
new file mode 100644
index 0000000..41323ef
--- /dev/null
+++ b/modules-index.json
@@ -0,0 +1,879 @@
+{
+ "version": "2026-06-03-neuralvfs",
+ "generated": "2026-06-04T01:25:00.000Z",
+ "modules": {
+ "module-agent-registry": {
+ "name": "module-agent-registry",
+ "file": "modules/core/module-agent-registry.js",
+ "type": "core",
+ "class": "AgentRegistryModule",
+ "auto_load": true,
+ "commands": [
+ "agent-list",
+ "agent-status",
+ "agent-register",
+ "agent-unregister",
+ "contract-register",
+ "contract-list"
+ ],
+ "description": "module-agent-registry.js β€” VFS-backed agent directory with A2A contracts",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "core"
+ },
+ "module-aiasm": {
+ "name": "module-aiasm",
+ "file": "modules/core/module-aiasm.js",
+ "type": "core",
+ "class": "WebXAIAliasModule",
+ "auto_load": true,
+ "commands": [
+ "webxai",
+ "wx",
+ "webx"
+ ],
+ "description": "Extracted from newOS4 index.html β€” WebXAIAliasModule",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "core"
+ },
+ "module-aiassist": {
+ "name": "module-aiassist",
+ "file": "modules/core/module-aiassist.js",
+ "type": "core",
+ "class": "WebX11AIAssistantModule",
+ "auto_load": true,
+ "commands": [
+ "ai",
+ "ask",
+ "ai-clear",
+ "ai-system",
+ "ai-context",
+ "ai-allow",
+ "ai-deny",
+ "ai-ignore",
+ "ai-stop",
+ "ai-model"
+ ],
+ "description": "Extracted from newOS4 index.html β€” WebX11AIAssistantModule (Full Agent Loop)",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "core"
+ },
+ "module-chatstudio": {
+ "name": "module-chatstudio",
+ "file": "modules/core/module-chatstudio.js",
+ "type": "core",
+ "class": "ChatStudioModule",
+ "auto_load": true,
+ "commands": [
+ "chat"
+ ],
+ "description": "Load CSS",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "core"
+ },
+ "module-config": {
+ "name": "module-config",
+ "file": "modules/core/module-config.js",
+ "type": "core",
+ "class": "ConfigManagerModule",
+ "auto_load": true,
+ "commands": [
+ "config",
+ "config-set",
+ "config-list",
+ "config-delete",
+ "config-export",
+ "config-reset"
+ ],
+ "description": "Extracted from newOS4 index.html β€” ConfigManagerModule",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "core"
+ },
+ "module-duckduckgo": {
+ "name": "module-duckduckgo",
+ "file": "modules/core/module-duckduckgo.js",
+ "type": "core",
+ "class": "DuckDuckGoModule",
+ "auto_load": true,
+ "commands": [
+ "ddg",
+ "duck"
+ ],
+ "description": "Extracted from newOS4 index.html β€” DuckDuckGoModule",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "core"
+ },
+ "module-dynamicprompts": {
+ "name": "module-dynamicprompts",
+ "file": "modules/core/module-dynamicprompts.js",
+ "type": "core",
+ "class": "DynamicPromptsModule",
+ "auto_load": true,
+ "commands": [
+ "prompt",
+ "prompt-save",
+ "prompt-list",
+ "prompt-delete",
+ "prompt-var",
+ "prompt-vars"
+ ],
+ "description": "Extracted from newOS4 index.html β€” DynamicPromptsModule",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "core"
+ },
+ "module-fetcher": {
+ "name": "module-fetcher",
+ "file": "modules/core/module-fetcher.js",
+ "type": "core",
+ "class": "WebFetcherModule",
+ "auto_load": true,
+ "commands": [
+ "fetch",
+ "web",
+ "extract"
+ ],
+ "description": "example.com\", \"info\");",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "core"
+ },
+ "module-fs": {
+ "name": "module-fs",
+ "file": "modules/core/module-fs.js",
+ "type": "core",
+ "class": "FileSystemModule",
+ "auto_load": true,
+ "commands": [
+ "ls",
+ "cat",
+ "put",
+ "rm",
+ "trash",
+ "trash-dir",
+ "ls-trash",
+ "empty-trash",
+ "mkdir",
+ "rmdir",
+ "mv",
+ "cp",
+ "cd",
+ "pwd",
+ "find",
+ "grep",
+ "head",
+ "tail",
+ "sort",
+ "wc",
+ "touch",
+ "tree",
+ "du",
+ "upload",
+ "download",
+ "vfs-export",
+ "vfs-import"
+ ],
+ "description": "Use trash for recursive dir removal too",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "core"
+ },
+ "module-io": {
+ "name": "module-io",
+ "file": "modules/core/module-io.js",
+ "type": "core",
+ "class": "ModuleIOModule",
+ "auto_load": true,
+ "commands": [
+ "export-mods",
+ "import-mods",
+ "backup",
+ "restore",
+ "share-mod"
+ ],
+ "description": "Extracted from newOS4 index.html β€” ModuleIOModule",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "core"
+ },
+ "module-leases": {
+ "name": "module-leases",
+ "file": "modules/core/module-leases.js",
+ "type": "core",
+ "class": "LeaseModule",
+ "auto_load": true,
+ "commands": [
+ "lease-list",
+ "lease-create",
+ "lease-revoke"
+ ],
+ "description": "module-leases.js β€” Lease system for agent task delegation",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "core"
+ },
+ "module-loader": {
+ "name": "module-loader",
+ "file": "modules/core/module-loader.js",
+ "type": "core",
+ "class": "module-loader.js",
+ "auto_load": true,
+ "commands": [],
+ "description": "Log to terminal if available",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "infrastructure"
+ },
+ "module-manager": {
+ "name": "module-manager",
+ "file": "modules/core/module-manager.js",
+ "type": "core",
+ "class": "ModuleManager",
+ "auto_load": true,
+ "commands": [
+ "modules",
+ "listmods",
+ "loadmod",
+ "removemod",
+ "startup-modules",
+ "load-local",
+ "loadlocal"
+ ],
+ "description": "Extracted from newOS4 index.html β€” ModuleManager",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "infrastructure"
+ },
+ "module-modmgr": {
+ "name": "module-modmgr",
+ "file": "modules/core/module-modmgr.js",
+ "type": "core",
+ "class": "ModuleManagerModule",
+ "auto_load": true,
+ "commands": [
+ "modules",
+ "listmods",
+ "loadmod",
+ "removemod",
+ "startup-modules",
+ "load-local",
+ "loadlocal"
+ ],
+ "description": "Extracted from newOS4 index.html β€” ModuleManagerModule",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "core"
+ },
+ "module-my": {
+ "name": "module-my",
+ "file": "modules/core/module-my.js",
+ "type": "core",
+ "class": "MyModule",
+ "auto_load": true,
+ "commands": [
+ "my",
+ "my-set",
+ "my-get",
+ "my-list",
+ "my-export",
+ "my-import",
+ "my-clear"
+ ],
+ "description": "",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "core"
+ },
+ "module-neural-vfs": {
+ "name": "module-neural-vfs",
+ "file": "modules/core/module-neural-vfs.js",
+ "type": "core",
+ "class": "NeuralVFSModule",
+ "auto_load": true,
+ "commands": [
+ "nvfs-index",
+ "nvfs-status",
+ "nvfs-resolve",
+ "nvfs-tree"
+ ],
+ "description": "── Core Index Builder ──",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "core"
+ },
+ "module-ollama": {
+ "name": "module-ollama",
+ "file": "modules/core/module-ollama.js",
+ "type": "core",
+ "class": "OllamaModule",
+ "auto_load": true,
+ "commands": [
+ "ollama",
+ "ollamaconnect",
+ "ollamadisconnect",
+ "ollamamodels",
+ "ollamasetmodel",
+ "ollamasetproxy",
+ "models",
+ "model-info",
+ "model-pull",
+ "model-delete",
+ "model-run",
+ "ai",
+ "ask"
+ ],
+ "description": "Ollama model management β€” connect, list models, pull/delete, run inference",
+ "dependencies": [],
+ "version": "2.0.0",
+ "updated": "2026-06-04",
+ "layer": "core"
+ },
+ "module-orchestrator": {
+ "name": "module-orchestrator",
+ "file": "modules/core/module-orchestrator.js",
+ "type": "core",
+ "class": "OrchestratorModule",
+ "auto_load": true,
+ "commands": [
+ "orchestrate",
+ "orchestrator-status",
+ "orchestrator-spawn",
+ "orchestrator-kill",
+ "orchestrator-purge"
+ ],
+ "description": "module-orchestrator.js β€” Multi-agent orchestration system",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "core"
+ },
+ "module-searxng": {
+ "name": "module-searxng",
+ "file": "modules/core/module-searxng.js",
+ "type": "core",
+ "class": "SearXNGModule",
+ "auto_load": true,
+ "commands": [
+ "search",
+ "s",
+ "images",
+ "videos"
+ ],
+ "description": "",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "core"
+ },
+ "module-servermon": {
+ "name": "module-servermon",
+ "file": "modules/core/module-servermon.js",
+ "type": "core",
+ "class": "ServerMonitorModule",
+ "auto_load": true,
+ "commands": [
+ "server",
+ "servers",
+ "server-check",
+ "server-remove",
+ "monitor",
+ "system-health"
+ ],
+ "description": "module-servermon.js β€” Server monitoring + self-optimization telemetry",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "core"
+ },
+ "module-simplegui": {
+ "name": "module-simplegui",
+ "file": "modules/core/module-simplegui.js",
+ "type": "core",
+ "class": "SimpleGUIModule",
+ "auto_load": true,
+ "commands": [
+ "gui",
+ "gui-button",
+ "gui-input",
+ "gui-text",
+ "gui-clear",
+ "gui-run"
+ ],
+ "description": "Extracted from newOS4 index.html β€” SimpleGUIModule",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "core"
+ },
+ "module-skills": {
+ "name": "module-skills",
+ "file": "modules/core/module-skills.js",
+ "type": "core",
+ "class": "SkillsModule",
+ "auto_load": true,
+ "commands": [
+ "skill-list",
+ "skill-view",
+ "skill-create",
+ "skill-patch",
+ "skill-delete",
+ "skill-export",
+ "skill-import",
+ "skill-sync"
+ ],
+ "description": "Extracted from newOS4 index.html β€” SkillsModule (v4.2 β€” Self-improving AI)",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "core"
+ },
+ "module-smartctx": {
+ "name": "module-smartctx",
+ "file": "modules/core/module-smartctx.js",
+ "type": "core",
+ "class": "SmartContextModule",
+ "auto_load": true,
+ "commands": [
+ "context",
+ "contexts",
+ "context-new",
+ "context-delete",
+ "smart-ask"
+ ],
+ "description": "Extracted from newOS4 index.html β€” SmartContextModule",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "core"
+ },
+ "module-system": {
+ "name": "module-system",
+ "file": "modules/core/module-system.js",
+ "type": "core",
+ "class": "SystemModule",
+ "auto_load": true,
+ "commands": [
+ "help",
+ "echo",
+ "mem",
+ "status",
+ "preview",
+ "factory-reset",
+ "reset-vfs",
+ "logs",
+ "logrotate",
+ "health-check",
+ "memory-map-export",
+ "font-size",
+ "setfont",
+ "smart-prompt",
+ "checkpoint",
+ "checkpoint-list",
+ "rollback",
+ "checkpoint-del",
+ "commands",
+ "check"
+ ],
+ "description": "Extracted from newOS4 index.html β€” SystemModule",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "core"
+ },
+ "ollama-manager": {
+ "name": "ollama-manager",
+ "file": "modules/core/ollama-manager.js",
+ "type": "core",
+ "class": "OllamaManager",
+ "auto_load": true,
+ "commands": [
+ "ollamaconnect",
+ "ollamamodels",
+ "model",
+ "models"
+ ],
+ "description": "Extracted from newOS4 index.html β€” OllamaManager / LLMRouter",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "infrastructure"
+ },
+ "secret-vault": {
+ "name": "secret-vault",
+ "file": "modules/core/secret-vault.js",
+ "type": "core",
+ "class": "SecretVault",
+ "auto_load": true,
+ "commands": [
+ "secret-set",
+ "secret-get",
+ "secret-list",
+ "secret-del",
+ "secret-lock",
+ "secret-unlock",
+ "secret-setpin",
+ "secret-status"
+ ],
+ "description": "Extracted from newOS4 index.html β€” SecretVault",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "core"
+ },
+ "terminal": {
+ "name": "terminal",
+ "file": "modules/core/terminal.js",
+ "type": "core",
+ "class": "WebX11SecurityManager",
+ "auto_load": true,
+ "commands": [
+ "clear",
+ "help",
+ "security",
+ "security-level",
+ "cmd-allow",
+ "cmd-deny",
+ "cd"
+ ],
+ "description": "Extracted from newOS4 index.html β€” WebX11Terminal",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "ext"
+ },
+ "virtual-fs": {
+ "name": "virtual-fs",
+ "file": "modules/core/virtual-fs.js",
+ "type": "core",
+ "class": "VirtualFileSystem",
+ "auto_load": true,
+ "commands": [
+ "save",
+ "load",
+ "import"
+ ],
+ "description": "concept:// listing",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "ext"
+ },
+ "alias": {
+ "name": "alias",
+ "file": "modules/ext/alias.js",
+ "type": "ext",
+ "class": "AliasModule",
+ "auto_load": false,
+ "commands": [
+ "alias",
+ "unalias"
+ ],
+ "description": "Register management commands",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "ext"
+ },
+ "busybox": {
+ "name": "busybox",
+ "file": "modules/ext/busybox.js",
+ "type": "ext",
+ "class": "BusyBoxModule",
+ "auto_load": false,
+ "commands": [
+ "which",
+ "env",
+ "date",
+ "cal",
+ "yes",
+ "seq",
+ "base64",
+ "printf",
+ "cut",
+ "uniq",
+ "hostname",
+ "whoami",
+ "basename",
+ "dirname",
+ "sleep",
+ "expand"
+ ],
+ "description": "── which ──",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "ext"
+ },
+ "calc": {
+ "name": "calc",
+ "file": "modules/ext/calc.js",
+ "type": "ext",
+ "class": "CalcModule",
+ "auto_load": false,
+ "commands": [
+ "calc"
+ ],
+ "description": "webx11.duckdns.org/spaces/newos4/modules/ext/calc.js');",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "ext"
+ },
+ "cron": {
+ "name": "cron",
+ "file": "modules/ext/cron.js",
+ "type": "ext",
+ "class": "CronModule",
+ "auto_load": false,
+ "commands": [
+ "cron-every",
+ "cron-list",
+ "cron-stop",
+ "cron-clear"
+ ],
+ "description": "webx11.duckdns.org/spaces/newos4/modules/ext/cron.js');",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "ext"
+ },
+ "cryptogzip": {
+ "name": "cryptogzip",
+ "file": "modules/ext/cryptogzip.js",
+ "type": "ext",
+ "class": "CryptoGzipModule",
+ "auto_load": false,
+ "commands": [
+ "gzip",
+ "gunzip",
+ "encrypt",
+ "decrypt"
+ ],
+ "description": "CryptoGzipModule β€” VFS-level gzip/encrypt commands for WebX11 newOS4",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "ext"
+ },
+ "diff": {
+ "name": "diff",
+ "file": "modules/ext/diff.js",
+ "type": "ext",
+ "class": "DiffModule",
+ "auto_load": false,
+ "commands": [
+ "diff"
+ ],
+ "description": "Strip trailing empty line if file ends with newline",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "ext"
+ },
+ "editor": {
+ "name": "editor",
+ "file": "modules/ext/editor.js",
+ "type": "ext",
+ "class": "EditorModule",
+ "auto_load": false,
+ "commands": [
+ "edit"
+ ],
+ "description": "Read existing file content or use empty for new files",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "ext"
+ },
+ "filemgr": {
+ "name": "filemgr",
+ "file": "modules/ext/filemgr.js",
+ "type": "ext",
+ "class": "FileManagerModule",
+ "auto_load": false,
+ "commands": [
+ "files",
+ "preview"
+ ],
+ "description": "code blocks first",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "ext"
+ },
+ "finder": {
+ "name": "finder",
+ "file": "modules/ext/finder.js",
+ "type": "ext",
+ "class": "FinderModule",
+ "auto_load": false,
+ "commands": [
+ "find"
+ ],
+ "description": "webx11.duckdns.org/spaces/newos4/modules/ext/finder.js');",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "ext"
+ },
+ "mindmap": {
+ "name": "mindmap",
+ "file": "modules/ext/mindmap.js",
+ "type": "ext",
+ "class": "MindmapModule",
+ "auto_load": false,
+ "commands": [
+ "mindmap",
+ "svg"
+ ],
+ "description": "Interactive mindmap creation with inline SVG rendering",
+ "dependencies": [],
+ "version": "2.0.0",
+ "updated": "2026-06-04",
+ "layer": "ext"
+ },
+ "shell": {
+ "name": "shell",
+ "file": "modules/ext/shell.js",
+ "type": "ext",
+ "class": "ShellModule",
+ "auto_load": false,
+ "commands": [
+ "export",
+ "unset",
+ "script",
+ "$",
+ "set"
+ ],
+ "description": "── Hook into terminal.executeCommand ──",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "ext"
+ },
+ "skill-pack-core": {
+ "name": "skill-pack-core",
+ "file": "modules/ext/skill-pack-core.js",
+ "type": "ext",
+ "class": "SkillPackCoreModule",
+ "auto_load": false,
+ "commands": [
+ "skill-pack-core"
+ ],
+ "description": "Update existing skill content on fresh load (cache-bust version bump triggers this)",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "ext"
+ },
+ "theme": {
+ "name": "theme",
+ "file": "modules/ext/theme.js",
+ "type": "ext",
+ "class": "ThemeModule",
+ "auto_load": false,
+ "commands": [
+ "theme"
+ ],
+ "description": "Cancel any active preview",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "ext"
+ },
+ "tutorial": {
+ "name": "tutorial",
+ "file": "modules/ext/tutorial.js",
+ "type": "ext",
+ "class": "TutorialModule",
+ "auto_load": false,
+ "commands": [
+ "tutorial"
+ ],
+ "description": "Restore saved state or start fresh",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "ext"
+ },
+ "voice": {
+ "name": "voice",
+ "file": "modules/ext/voice.js",
+ "type": "ext",
+ "class": "VoiceModule",
+ "auto_load": false,
+ "commands": [
+ "voice"
+ ],
+ "description": "webx11.duckdns.org/spaces/newos4/modules/ext/voice.js');",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "ext"
+ },
+ "webdav": {
+ "name": "webdav",
+ "file": "modules/ext/webdav.js",
+ "type": "ext",
+ "class": "WebDAVModule",
+ "auto_load": false,
+ "commands": [
+ "webdav-config",
+ "webdav-status",
+ "webdav-ls",
+ "webdav-push",
+ "webdav-pull",
+ "webdav-backup",
+ "webdav-restore",
+ "webdav-backup-list",
+ "webdav-browser",
+ "webdav-rm",
+ "webdav-mkdir",
+ "webdav-rename",
+ "webdav-move"
+ ],
+ "description": "{ url, username, password }",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "ext"
+ },
+ "wpm": {
+ "name": "wpm",
+ "file": "modules/ext/wpm.js",
+ "type": "ext",
+ "class": "WpmModule",
+ "auto_load": false,
+ "commands": [
+ "wpm"
+ ],
+ "description": "webx11.duckdns.org/spaces/newos4/packages.json';",
+ "dependencies": [],
+ "version": "1.0.0",
+ "updated": "2026-06-03",
+ "layer": "ext"
+ }
+ },
+ "total": 45
+} \ No newline at end of file
diff --git a/modules/core/module-agent-registry.js b/modules/core/module-agent-registry.js
index 367f8b1..2439ab8 100644
--- a/modules/core/module-agent-registry.js
+++ b/modules/core/module-agent-registry.js
@@ -1,58 +1,137 @@
-// module-agent-registry.js β€” VFS-backed agent directory
-// Command: agent-list, agent-register, agent-unregister, agent-status
+// module-agent-registry.js β€” VFS-backed agent directory with A2A contracts
+// Commands: agent-list, agent-register, agent-unregister, agent-status, contract-register, contract-list
class AgentRegistryModule {
constructor() {
this.commands = {};
this.terminal = null;
+ this._contracts = {};
}
registerCommands() {
this.commands['agent-list'] = () => this.listAgents();
this.commands['agent-status'] = (args) => this.showAgentStatus(args[0]);
this.commands['agent-register'] = (args) => this.registerAgent(args);
this.commands['agent-unregister'] = (args) => this.unregisterAgent(args[0]);
+ this.commands['contract-register'] = (args) => this.registerContract(args);
+ this.commands['contract-list'] = () => this.listContracts();
}
init(terminal) {
this.terminal = terminal;
- if (!this.terminal.fs.readFile('/agents/')) {
- this.terminal.fs.mkdir('agents');
- }
+ if (!this.terminal.fs.readDir('/agents/')) this.terminal.fs.mkdir('agents');
+ if (!this.terminal.fs.readDir('/.contracts/')) this.terminal.fs.mkdir('.contracts');
+ this._loadContracts();
this.terminal.print('πŸ“‹ Agent Registry loaded', 'info');
}
- listAgents() {
- const agents = this.terminal.fs.ls('/agents/');
- if (!agents || agents.length === 0) {
- return this.terminal.print('No agents registered', 'info');
+ _loadContracts() {
+ try {
+ const data = this.terminal.fs.readFile('/.contracts/index.json');
+ if (data) this._contracts = JSON.parse(data);
+ } catch (e) {}
+ // Try loading individual contract files
+ const dir = this.terminal.fs.readDir('/.contracts/');
+ if (dir) {
+ dir.forEach(e => {
+ if (e.type === 'file' && e.name.endsWith('.contract.json')) {
+ try {
+ const c = JSON.parse(this.terminal.fs.readFile('/.contracts/' + e.name));
+ this._contracts[c.role] = c;
+ } catch (e) { console.warn('Bad contract:', e.name, e.message); }
+ }
+ });
}
- this.terminal.print(`πŸ“‹ Registered Agents (${agents.length}):`, 'header');
- agents.forEach(a => {
- if (a.type === 'dir' && a.name !== 'configured') {
- const data = this.terminal.fs.readFile(`/agents/${a.name}/status.json`);
- const s = data ? JSON.parse(data) : { status: 'unknown', capabilities: [] };
- this.terminal.print(` ${a.name} β€” ${s.status} (${(s.capabilities || []).length} capabilities)`, 'info');
- }
- });
+ }
+ _saveContracts() {
+ try {
+ this.terminal.fs.fsWriteJSON('/.contracts/index.json', this._contracts);
+ } catch (e) { console.error('Contract save error:', e); }
}
registerAgent(args) {
const id = args[1] || `agent-${Date.now()}`;
const capabilities = args.slice(2).length ? args.slice(2) : ['list_files', 'read_file'];
const agentDir = `agents/${id}`;
- if (!this.terminal.fs.readFile('/' + agentDir + '/')) this.terminal.fs.mkdir(agentDir);
+ if (!this.terminal.fs.readDir('/' + agentDir + '/')) this.terminal.fs.mkdir(agentDir);
this.terminal.fs.writeFile(`${agentDir}/status.json`, JSON.stringify({
id,
status: 'idle',
capabilities,
registered: new Date().toISOString(),
- lastHeartbeat: new Date().toISOString()
+ lastHeartbeat: new Date().toISOString(),
+ contract: null
}));
this.terminal.print(`βœ… Agent '${id}' registered with ${capabilities.length} capabilities`, 'success');
}
- unregisterAgent(id) {
- const ok = this.terminal.fs.deleteFile(`agents/${id}`);
- if (ok) {
- this.terminal.print(`βœ… Agent '${id}' unregistered`, 'success');
+ registerContract(args) {
+ const role = args[0];
+ if (!role) return this.terminal.print('Usage: contract-register <role> [input_fields...] [--output output_fields...]', 'warning');
+
+ const inputIdx = args.indexOf('--output');
+ const hasOutputFlag = inputIdx !== -1;
+
+ let inputFields = [], outputFields = [];
+ if (hasOutputFlag) {
+ inputFields = args.slice(1, inputIdx).filter(f => !f.startsWith('--'));
+ outputFields = args.slice(inputIdx + 1).filter(f => !f.startsWith('--'));
} else {
- this.terminal.print(`❌ Agent '${id}' not found`, 'error');
+ inputFields = args.slice(1).filter(f => !f.startsWith('--'));
+ outputFields = ['result']; // default output
+ }
+
+ const contract = {
+ role,
+ capabilities: inputFields,
+ input_schema: inputFields,
+ output_schema: outputFields,
+ created: new Date().toISOString(),
+ updated: new Date().toISOString()
+ };
+ this._contracts[role] = contract;
+ // Save as individual contract file
+ this.terminal.fs.fsWriteJSON(`/.contracts/${role}.contract.json`, contract);
+ this._saveContracts();
+ this.terminal.print(`βœ… Contract registered for role '${role}'`, 'success');
+ this.terminal.print(` Input fields: ${inputFields.join(', ') || '(free-form)'}`, 'info');
+ this.terminal.print(` Output fields: ${outputFields.join(', ') || '(free-form)'}`, 'info');
+ }
+ listContracts() {
+ const roles = Object.keys(this._contracts);
+ if (roles.length === 0) return this.terminal.print('No contracts registered', 'info');
+ this.terminal.print(`πŸ“œ A2A Contracts (${roles.length}):`, 'header');
+ roles.forEach(r => {
+ const c = this._contracts[r];
+ this.terminal.print(` ${r} β€” input:[${c.input_schema.join(',')}] β†’ output:[${c.output_schema.join(',')}]`, 'info');
+ });
+ }
+ validateTask(role, task) {
+ const contract = this._contracts[role];
+ if (!contract) return { valid: true, reason: 'no contract for role' }; // permissive fallback
+ if (contract.input_schema.length === 0) return { valid: true, reason: 'free-form input' };
+ // Simple validation: check required input fields are present in task
+ const missing = contract.input_schema.filter(f => !task.toLowerCase().includes(f.toLowerCase()));
+ if (missing.length > 0) {
+ return { valid: false, reason: `missing required fields: ${missing.join(', ')}` };
}
+ return { valid: true, reason: 'matched' };
+ }
+ getContract(role) {
+ return this._contracts[role] || null;
+ }
+ listAgents() {
+ const agents = this.terminal.fs.ls('/agents/');
+ if (!agents || agents.length === 0) {
+ return this.terminal.print('No agents registered', 'info');
+ }
+ this.terminal.print(`πŸ“‹ Registered Agents (${agents.length}):`, 'header');
+ agents.forEach(a => {
+ if (a.type === 'dir' && a.name !== 'configured') {
+ const data = this.terminal.fs.readFile(`/agents/${a.name}/status.json`);
+ const s = data ? JSON.parse(data) : { status: 'unknown', capabilities: [] };
+ this.terminal.print(` ${a.name} β€” ${s.status} (${(s.capabilities || []).length} capabilities)${s.contract ? ` β†’ contract:${s.contract}` : ''}`, 'info');
+ }
+ });
+ }
+ unregisterAgent(id) {
+ const ok = this.terminal.fs.deleteFile('agents/' + id);
+ if (ok) this.terminal.print(`βœ… Agent '${id}' unregistered`, 'success');
+ else this.terminal.print(`❌ Agent '${id}' not found`, 'error');
}
showAgentStatus(id) {
if (!id) return this.terminal.print('Usage: agent-status <agent-id>', 'error');
@@ -62,6 +141,7 @@ class AgentRegistryModule {
this.terminal.print(`Agent: ${s.id}`, 'header');
this.terminal.print(` Status: ${s.status}`, 'info');
this.terminal.print(` Capabilities: ${(s.capabilities || []).join(', ')}`, 'info');
+ this.terminal.print(` Contract: ${s.contract || 'none'}`, 'info');
this.terminal.print(` Registered: ${s.registered}`, 'info');
this.terminal.print(` Last Heartbeat: ${s.lastHeartbeat}`, 'info');
}
diff --git a/modules/core/module-aiassist.js b/modules/core/module-aiassist.js
index eb41af9..cb1482f 100644
--- a/modules/core/module-aiassist.js
+++ b/modules/core/module-aiassist.js
@@ -418,6 +418,56 @@ RULES:
required: ['role']
}
}
+ }, {
+ type: 'function',
+ function: {
+ name: 'nvfs_resolve',
+ description: 'Search VFS files by semantic concept using Neural VFS index. Call nvfs-index first to build the index.',
+ parameters: {
+ type: 'object',
+ properties: {
+ concept: { type: 'string', description: 'Concept to search (e.g. skill, memory, module, webdav, security)' }
+ },
+ required: ['concept']
+ }
+ }
+ }, {
+ type: 'function',
+ function: {
+ name: 'list_available_modules',
+ description: 'List all available modules with metadata (core/ext, commands, class name, layer). Filter by type with type=core or type=ext.',
+ parameters: {
+ type: 'object',
+ properties: {
+ type: { type: 'string', description: 'Optional: filter to "core" or "ext"' }
+ },
+ required: []
+ }
+ }
+ }, {
+ type: 'function',
+ function: {
+ name: 'smart_context_list',
+ description: 'List available AI context profiles (e.g. coding, debug, creative, technical). Returns profile names and system prompts.',
+ parameters: {
+ type: 'object',
+ properties: {},
+ required: []
+ }
+ }
+ }, {
+ type: 'function',
+ function: {
+ name: 'smart_context_set',
+ description: 'Set the active AI context profile. Changes the AI\'s behavior (temperature, style) for subsequent responses.',
+ parameters: {
+ type: 'object',
+ properties: {
+ name: { type: 'string', description: 'Profile name (e.g. "coding", "debug", "creative", "technical", "chat")' }
+ },
+ required: ['name']
+ }
+ }
}];
}
getHelpInfo() {
@@ -695,6 +745,9 @@ RULES:
duration: t1,
error: this._isToolError(toolResult) ? true : false
});
+ // Telemetry
+ const sm = this.terminal.moduleManager.modules['ServerMonitorModule'];
+ if (sm && sm.logToolCall) sm.logToolCall(fn.name, (t1 * 1000) || 1, this._isToolError(toolResult));
if (this._debugPanelEnabled) this._updateDebugPanel();
return { fn, toolResult, t1 };
}));
@@ -734,6 +787,9 @@ RULES:
duration: t1,
error: this._isToolError(toolResult) ? true : false
});
+ // Telemetry
+ const sm2 = this.terminal.moduleManager.modules['ServerMonitorModule'];
+ if (sm2 && sm2.logToolCall) sm2.logToolCall(fn.name, (t1 * 1000) || 1, this._isToolError(toolResult));
if (this._debugPanelEnabled) this._updateDebugPanel();
const dObs = this._summarizeObservation(toolResult, 150);
const dErr = this._isToolError(toolResult);
@@ -1338,6 +1394,76 @@ RULES:
.filter(s => !filterCat || (s.category || '').toLowerCase() === filterCat);
return JSON.stringify({ skills: list, count: list.length });
}
+ case 'nvfs_resolve': {
+ const concept = (a.concept || '').toLowerCase();
+ if (!concept) return JSON.stringify({ error: 'Concept is required' });
+ const nvfs = this.terminal.moduleManager.modules['NeuralVFSModule'];
+ if (!nvfs) return JSON.stringify({ error: 'Neural VFS module not loaded β€” run nvfs-index first' });
+ // Build index if empty
+ if (Object.keys(nvfs.index).length === 0) {
+ const saved = this.terminal.fs.fsReadJSON('/.semantic_index/map.json');
+ if (saved) { nvfs.index = saved; }
+ else { return JSON.stringify({ error: 'No semantic index found β€” run nvfs-index first' }); }
+ }
+ const exact = nvfs.index[concept];
+ const fuzzy = Object.keys(nvfs.index).filter(k =>
+ k.includes(concept) || concept.includes(k)
+ ).filter(k => k !== concept);
+ const results = [];
+ if (exact) results.push(...exact.map(e => ({ concept, path: e.path, summary: e.summary })));
+ for (const f of fuzzy.slice(0, 5)) {
+ results.push(...nvfs.index[f].slice(0, 3).map(e => ({ concept: f, path: e.path, summary: e.summary })));
+ }
+ return JSON.stringify({ concept, exact: !!exact, count: results.length, results: results.slice(0, 20) });
+ }
+ case 'list_available_modules': {
+ try {
+ const resp = await fetch('/spaces/newos4/modules-index.json?v=' + (localStorage.getItem('webx11_cache_ver') || ''));
+ if (!resp.ok) return JSON.stringify({ error: 'Module index not available' });
+ const idx = await resp.json();
+ const filterType = (a.type || '').toLowerCase();
+ let mods = Object.values(idx.modules);
+ if (filterType) mods = mods.filter(m => m.type === filterType);
+ return JSON.stringify({
+ total: mods.length,
+ available: idx.total,
+ type: filterType || 'all',
+ modules: mods.map(m => ({
+ name: m.name,
+ type: m.type,
+ class: m.class,
+ commands: m.commands.slice(0, 8),
+ description: (m.description || '').substring(0, 80),
+ auto_load: m.auto_load
+ }))
+ });
+ } catch (e) { return JSON.stringify({ error: 'Failed to load module index: ' + e.message }); }
+ }
+ case 'smart_context_list': {
+ const scm = this.terminal.moduleManager.modules['SmartContextModule'];
+ if (!scm) return JSON.stringify({ error: 'SmartContextModule not loaded', profiles: [] });
+ const profiles = scm.contextProfiles || {};
+ return JSON.stringify({
+ profiles: Object.entries(profiles).map(([key, p]) => ({
+ name: key,
+ displayName: p.name || key,
+ systemPrompt: (p.systemPrompt || '').substring(0, 80),
+ temperature: p.temperature || 0.7,
+ active: scm.activeProfile === key
+ }))
+ });
+ }
+ case 'smart_context_set': {
+ const scm = this.terminal.moduleManager.modules['SmartContextModule'];
+ if (!scm) return JSON.stringify({ error: 'SmartContextModule not loaded' });
+ const name = (a.name || '').toLowerCase();
+ if (!scm.contextProfiles[name]) {
+ return JSON.stringify({ error: `Profile '${name}' not found`, available: Object.keys(scm.contextProfiles) });
+ }
+ scm.activeProfile = name;
+ const profile = scm.contextProfiles[name];
+ return JSON.stringify({ success: true, name, displayName: profile.name, systemPrompt: profile.systemPrompt, temperature: profile.temperature });
+ }
case 'view_module':
case 'edit_module':
case 'test_module':
@@ -1364,16 +1490,41 @@ RULES:
const code = this.terminal.fs.readFile(`_mods/${modName}.js`);
if (code) return code;
const url = entry ? entry.url : null;
- if (!url) return JSON.stringify({ error: `No source URL for ${modName}` });
+ // Try registry URL first
+ if (url) {
+ try {
+ const resp = await fetch(url);
+ if (resp.ok) {
+ const src = await resp.text();
+ this.terminal.fs.writeFile(`_mods/${modName}.orig.js`, src);
+ return src.substring(0, 8000);
+ }
+ } catch (e) { /* fall through */ }
+ }
+ // Fallback: use modules-index.json to map class name to filename
try {
- const resp = await fetch(url);
- if (resp.ok) {
- const src = await resp.text();
- this.terminal.fs.writeFile(`_mods/${modName}.orig.js`, src);
- return src.substring(0, 8000);
+ const idxResp = await fetch('/spaces/newos4/modules-index.json?v=' + (localStorage.getItem('webx11_cache_ver') || ''));
+ if (idxResp.ok) {
+ const idx = await idxResp.json();
+ // modName is the class name (e.g. "WebX11AIAssistantModule")
+ // or already a filename (e.g. "module-aiassist")
+ // Try matching by class name first
+ let match = Object.values(idx.modules).find(m => m.class === modName);
+ // Then by name
+ if (!match) match = idx.modules[modName];
+ if (match) {
+ const filePath = match.file; // e.g. "modules/core/module-aiassist.js"
+ const fetchUrl = `/spaces/newos4/${filePath}`;
+ const resp = await fetch(fetchUrl);
+ if (resp.ok) {
+ const src = await resp.text();
+ this.terminal.fs.writeFile(`_mods/${modName}.orig.js`, src);
+ return src.substring(0, 8000);
+ }
+ }
}
- return JSON.stringify({ error: `HTTP ${resp.status}` });
- } catch (e) { return JSON.stringify({ error: e.message }); }
+ } catch (e) { /* fall through */ }
+ return JSON.stringify({ error: `Cannot find source for ${modName} β€” not in registry, not in modules-index.json` });
}
case 'edit_module': {
const modName = a.name || '';
@@ -1425,11 +1576,42 @@ RULES:
const mm = this.terminal.moduleManager;
const modsDir = this.terminal.fs.getCurrentDir();
const hasMods = modsDir.content['_mods'] ? !!Object.keys(modsDir.content['_mods'].content).length : false;
- const modules = mm.moduleRegistry.map(m => ({
- name: m.name, url: m.url, enabled: m.enabled,
- loaded: !!mm.modules[m.name],
- modified: !!this.terminal.fs.readFile(`_mods/${m.name}.js`)
- }));
+ // Load module index for file path lookup
+ let idxMap = {};
+ try {
+ const resp = await fetch('/spaces/newos4/modules-index.json?v=' + (localStorage.getItem('webx11_cache_ver') || ''));
+ if (resp.ok) {
+ const idx = await resp.json();
+ for (const [name, meta] of Object.entries(idx.modules)) {
+ idxMap[meta.class] = '/spaces/newos4/' + meta.file;
+ }
+ }
+ } catch (e) {}
+ const modules = [];
+ const seen = new Set();
+ for (const [className, instance] of Object.entries(mm.modules)) {
+ const name = instance.constructor ? instance.constructor.name : className;
+ if (seen.has(name)) continue;
+ seen.add(name);
+ modules.push({
+ name: name,
+ url: idxMap[name] || null,
+ enabled: true,
+ loaded: true,
+ modified: !!this.terminal.fs.readFile(`_mods/${name}.js`),
+ source: 'loaded'
+ });
+ }
+ for (const m of mm.moduleRegistry) {
+ if (seen.has(m.name)) continue;
+ seen.add(m.name);
+ modules.push({
+ name: m.name, url: m.url || idxMap[m.name] || null, enabled: m.enabled,
+ loaded: !!mm.modules[m.name],
+ modified: !!this.terminal.fs.readFile(`_mods/${m.name}.js`),
+ source: m.url ? 'ext' : 'core'
+ });
+ }
return JSON.stringify({ modules, total: modules.length, hasLocalEdits: hasMods });
}
default: return JSON.stringify({ error: `Unknown module tool: ${name}` });
diff --git a/modules/core/module-loader.js b/modules/core/module-loader.js
index 2ffdb17..e7fc64a 100644
--- a/modules/core/module-loader.js
+++ b/modules/core/module-loader.js
@@ -18,7 +18,6 @@
'module-my.js',
'module-searxng.js',
'module-servermon.js',
- 'module-ollamamodels.js',
'module-config.js',
'module-simplegui.js',
'module-io.js',
@@ -33,7 +32,8 @@
'module-chatstudio.js',
'module-agent-registry.js',
'module-leases.js',
- 'module-orchestrator.js'
+ 'module-orchestrator.js',
+ 'module-neural-vfs.js'
];
function getSelectedModules() {
@@ -102,7 +102,7 @@
window.__moduleLoaderReload = reloadWithSelection;
-const LATEST_VER = '2026-06-02-webdav2';
+const LATEST_VER = '2026-06-03-neuralvfs';
const CACHE = '?v=' + LATEST_VER;
const stored = localStorage.getItem('webx11_cache_ver');
if (stored !== LATEST_VER) {
diff --git a/modules/core/module-modmgr.js b/modules/core/module-modmgr.js
index 1104883..32bb2cc 100644
--- a/modules/core/module-modmgr.js
+++ b/modules/core/module-modmgr.js
@@ -5,6 +5,7 @@
return {
'modules': 'modules β€” Open the module manager GUI',
'listmods': 'listmods β€” List all loaded modules with status',
+ 'modules-list': 'modules-list [core|ext] β€” List all available modules from the module index (46 total)',
'loadmod': 'loadmod <url> β€” Load a module from a URL',
'removemod': 'removemod <name> β€” Remove a loaded module by name',
'startup-modules': 'startup-modules β€” Open the startup modules selector',
@@ -36,5 +37,38 @@
this.terminal.print(`${status} ${m.name}${badge}`);
});
};
+ this.commands['modules-list'] = async (args) => {
+ try {
+ const filter = (args[0] || '').toLowerCase();
+ const resp = await fetch('/spaces/newos4/modules-index.json?v=' + (localStorage.getItem('webx11_cache_ver') || ''));
+ if (!resp.ok) return this.terminal.print('Failed to load module index', 'error');
+ const idx = await resp.json();
+ let mods = Object.values(idx.modules);
+ if (filter === 'core' || filter === 'ext') mods = mods.filter(m => m.type === filter);
+ if (filter === 'infra') mods = mods.filter(m => m.layer === 'infrastructure');
+ const loaded = this.terminal.moduleManager.modules || {};
+ const loadedCount = Object.keys(loaded).length;
+ const byLayer = {};
+ mods.forEach(m => {
+ const l = m.layer || m.type || 'other';
+ if (!byLayer[l]) byLayer[l] = [];
+ byLayer[l].push(m);
+ });
+ const layerSummary = Object.entries(byLayer).map(([l, ms]) => `${ms.length} ${l}`).join(', ');
+ this.terminal.print(`πŸ“¦ Module Index (${mods.length} modules: ${layerSummary} β€” ${loadedCount} loaded)`, 'header');
+ for (const [layer, layerMods] of Object.entries(byLayer)) {
+ this.terminal.print(` ── ${layer.toUpperCase()} (${layerMods.length}) ──`, 'info');
+ for (const m of layerMods) {
+ const isLoaded = loaded[m.class] ? 'βœ“' : ' ';
+ const layerTag = m.layer === 'infrastructure' ? '[infra]' : m.type === 'core' ? '[core]' : '[ext]';
+ const cmdHint = m.commands.length > 0 ? ` ${m.commands.slice(0, 4).join(', ')}${m.commands.length > 4 ? '...' : ''}` : '';
+ const desc = m.description ? ` β€” ${m.description.substring(0, 60)}` : '';
+ this.terminal.print(` ${isLoaded} ${layerTag} ${m.name}${cmdHint}${desc}`, '');
+ }
+ }
+ } catch (e) {
+ this.terminal.print(`modules-list error: ${e.message}`, 'error');
+ }
+ };
}
}
diff --git a/modules/core/module-neural-vfs.js b/modules/core/module-neural-vfs.js
new file mode 100644
index 0000000..e9ffafb
--- /dev/null
+++ b/modules/core/module-neural-vfs.js
@@ -0,0 +1,271 @@
+class NeuralVFSModule {
+ constructor() {
+ this.commands = {};
+ this.terminal = null;
+ this.index = {};
+ this.indexPath = '/.semantic_index/map.json';
+ }
+
+ getHelpInfo() {
+ return {
+ 'nvfs-index': 'nvfs-index β€” Scan VFS and build semantic concept index',
+ 'nvfs-status': 'nvfs-status β€” Show semantic index stats and last scan time',
+ 'nvfs-resolve': 'nvfs-resolve <concept> β€” Find files related to a concept',
+ 'nvfs-tree': 'nvfs-tree [concept] β€” Show concept-to-file mapping as a tree'
+ };
+ }
+
+ registerCommands() {
+ this.commands['nvfs-index'] = (args) => this.buildIndex();
+ this.commands['nvfs-status'] = (args) => this.showStatus();
+ this.commands['nvfs-resolve'] = (args) => this.resolve(args);
+ this.commands['nvfs-tree'] = (args) => this.tree(args);
+ }
+
+ // ── Core Index Builder ──
+
+ buildIndex() {
+ const fs = this.terminal.fs;
+ if (!fs) return this.terminal.print('VFS not available', 'error');
+
+ this.terminal.print('πŸ” Scanning VFS for semantic concepts...', 'info');
+
+ const start = Date.now();
+ const newIndex = {};
+ let fileCount = 0;
+ let conceptCount = 0;
+
+ // Walk VFS recursively β€” skip system dirs
+ this._walk('/', fs, newIndex, (path, node) => {
+ if (node.type !== 'file') return;
+ if (this._isSystemFile(path)) return;
+
+ fileCount++;
+ const concepts = this._extractConcepts(path, node.content || '');
+ for (const concept of concepts) {
+ if (!newIndex[concept]) {
+ newIndex[concept] = [];
+ conceptCount++;
+ }
+ // Avoid dupes
+ if (!newIndex[concept].find(e => e.path === path)) {
+ newIndex[concept].push({ path, summary: this._summarize(node.content) });
+ }
+ }
+ });
+
+ // Also index skills
+ this._indexSkills(fs, newIndex);
+
+ this.index = newIndex;
+ this.lastScan = new Date().toISOString();
+ this.fileCount = fileCount;
+ this.conceptCount = conceptCount;
+
+ // Save to VFS
+ this._saveIndex(fs);
+ // Clear VFS concept cache so concept:// URIs reflect the new index
+ if (fs._clearConceptCache) fs._clearConceptCache();
+
+ const elapsed = ((Date.now() - start) / 1000).toFixed(1);
+ this.terminal.print(`βœ… Indexed ${fileCount} files β†’ ${conceptCount} concepts in ${elapsed}s`, 'success');
+ this.terminal.print(` Index saved to ${this.indexPath}`, 'info');
+ }
+
+ // ── Resolve ──
+
+ resolve(args) {
+ if (!args[0]) return this.terminal.print('Usage: nvfs-resolve <concept>', 'warning');
+
+ const concept = args.join(' ').toLowerCase();
+ const matches = this.index[concept] || [];
+
+ // Fuzzy fallback β€” find partial matches
+ const fuzzy = Object.keys(this.index).filter(k =>
+ k.includes(concept) || concept.includes(k)
+ ).filter(k => k !== concept);
+
+ if (matches.length === 0 && fuzzy.length === 0) {
+ return this.terminal.print(`No files found for concept "${concept}"`, 'warning');
+ }
+
+ if (matches.length > 0) {
+ this.terminal.print(`πŸ“‚ "${concept}" β†’ ${matches.length} file(s):`, 'info');
+ for (const m of matches.slice(0, 20)) {
+ this.terminal.print(` ${m.path}`, 'success');
+ if (m.summary) this.terminal.print(` ${m.summary}`, '')
+ }
+ if (matches.length > 20) {
+ this.terminal.print(` ... and ${matches.length - 20} more`, 'info');
+ }
+ }
+
+ if (fuzzy.length > 0) {
+ this.terminal.print(`\nπŸ”€ Similar concepts: ${fuzzy.slice(0, 10).join(', ')}`, 'info');
+ }
+ }
+
+ // ── Status ──
+
+ showStatus() {
+ const count = Object.keys(this.index).length;
+ if (count === 0) {
+ // Try loading from VFS
+ const fs = this.terminal.fs;
+ const saved = fs.fsReadJSON(this.indexPath);
+ if (saved) {
+ this.index = saved;
+ this.lastScan = '(loaded from disk)';
+ this.terminal.print(`πŸ“– Loaded index from ${this.indexPath}`, 'info');
+ } else {
+ return this.terminal.print('No semantic index found. Run nvfs-index first.', 'warning');
+ }
+ }
+
+ const totalFiles = new Set();
+ for (const entries of Object.values(this.index)) {
+ for (const e of entries) totalFiles.add(e.path);
+ }
+
+ this.terminal.print(`🧠 Neural VFS Index`, 'info');
+ this.terminal.print(` Concepts: ${Object.keys(this.index).length}`, '');
+ this.terminal.print(` Files indexed: ${totalFiles.size}`, '');
+ this.terminal.print(` Last scan: ${this.lastScan || 'never'}`, '');
+ }
+
+ // ── Tree View ──
+
+ tree(args) {
+ const concepts = Object.keys(this.index);
+ if (concepts.length === 0) {
+ return this.terminal.print('No index. Run nvfs-index first.', 'warning');
+ }
+
+ const filter = args[0] ? args[0].toLowerCase() : null;
+ const filtered = filter ? concepts.filter(c => c.includes(filter)) : concepts;
+
+ this.terminal.print(`🌳 Concept Tree${filter ? ` (filter: "${filter}")` : ''}:`, 'info');
+ for (const concept of filtered.slice(0, 15)) {
+ this.terminal.print(` πŸ“ ${concept}`, 'success');
+ for (const entry of this.index[concept].slice(0, 5)) {
+ this.terminal.print(` └─ ${entry.path}`, '');
+ }
+ if (this.index[concept].length > 5) {
+ this.terminal.print(` └─ ... (+${this.index[concept].length - 5} more)`, '');
+ }
+ }
+ if (filtered.length > 15) {
+ this.terminal.print(` ... and ${filtered.length - 15} more concepts`, 'info');
+ }
+ }
+
+ // ── Private Helpers ──
+
+ _walk(path, fs, index, cb) {
+ const entries = fs.readDir(path);
+ if (!entries) return;
+ for (const entry of entries) {
+ const fullPath = path === '/' ? '/' + entry.name : path + '/' + entry.name;
+ if (entry.type === 'file') {
+ cb(fullPath, { type: 'file', content: fs.readFile(fullPath) || '' });
+ } else if (entry.type === 'dir') {
+ this._walk(fullPath, fs, index, cb);
+ }
+ }
+ }
+
+ _isSystemFile(path) {
+ const sysPrefixes = ['/.trash', '/.semantic_index', '/_snapshots', '/_sessions'];
+ return sysPrefixes.some(p => path.startsWith(p) || path.includes('/node_modules'));
+ }
+
+ _extractConcepts(path, content) {
+ const concepts = new Set();
+ const name = path.split('/').pop() || '';
+ const nameLower = name.toLowerCase();
+
+ // Extract from filename (split on camelCase, kebab, dots, underscores)
+ const words = nameLower
+ .replace(/([a-z])([A-Z])/g, '$1 $2')
+ .replace(/[-_.]/g, ' ')
+ .replace(/\.(md|js|html|json|css|txt|yaml|yml|toml|env|sh)$/i, '')
+ .split(/\s+/)
+ .filter(w => w.length > 2 && !/^\d+$/.test(w));
+
+ for (const word of words) {
+ concepts.add(word);
+ }
+
+ // Extract file extension as concept
+ const ext = path.split('.').pop();
+ if (ext && ['md', 'js', 'html', 'json', 'css'].includes(ext)) {
+ concepts.add(ext + '-file');
+ }
+
+ // Extract path-level concepts
+ const parts = path.split('/').filter(p => p.length > 0);
+ for (const part of parts) {
+ if (['modules', 'skills', 'core', 'ext', 'backups', 'chat', 'downloads'].includes(part)) {
+ concepts.add(part);
+ }
+ }
+
+ // Extract #tags from content (markdown frontmatter or inline)
+ if (content) {
+ const tagMatches = content.match(/tags:\s*\[([^\]]+)\]/i) || content.match(/#[a-zA-Z]\w+/g);
+ if (tagMatches) {
+ const tags = tagMatches[0].replace(/tags:\s*\[/i, '').replace(/\]/, '').split(',').map(t => t.trim().replace(/^#/, '').replace(/"/g, ''));
+ for (const tag of tags) {
+ if (tag.length > 2) concepts.add(tag.toLowerCase());
+ }
+ }
+
+ // Extract first H1/H2 as concept
+ const headerMatch = content.match(/^#\s+(.+)/m) || content.match(/^##\s+(.+)/m);
+ if (headerMatch) {
+ const header = headerMatch[1].toLowerCase().replace(/[^a-z0-9\s]/g, '').trim();
+ if (header.length > 3 && header.length < 40) {
+ concepts.add(header);
+ }
+ }
+ }
+
+ return [...concepts];
+ }
+
+ _summarize(content) {
+ if (!content || content.length < 10) return '';
+ const cleaned = content.replace(/---[\s\S]*?---/, '').trim();
+ const firstLine = cleaned.split('\n').find(l => l.trim().length > 20);
+ if (!firstLine) return '';
+ return firstLine.trim().slice(0, 100) + (firstLine.length > 100 ? '...' : '');
+ }
+
+ _indexSkills(fs, index) {
+ const skills = fs.readDir('/skills');
+ if (!skills) return;
+ for (const skill of skills) {
+ if (skill.type !== 'file' || !skill.name.endsWith('.md')) continue;
+ // Already indexed by _walk β€” but we add a "skill" tag
+ const base = skill.name.replace('.md', '');
+ if (!index['skill']) index['skill'] = [];
+ index['skill'].push({ path: '/skills/' + skill.name, summary: 'Skill: ' + base });
+ }
+ }
+
+ _saveIndex(fs) {
+ try {
+ if (!fs.readDir('/.semantic_index')) {
+ fs.mkdirRecursive('/.semantic_index');
+ }
+ fs.fsWriteJSON(this.indexPath, this.index);
+ } catch (e) {
+ console.error('NeuralVFS save error:', e);
+ }
+ }
+}
+
+// Required for module system
+if (typeof window !== 'undefined') {
+ window.NeuralVFSModule = NeuralVFSModule;
+} \ No newline at end of file
diff --git a/modules/core/module-ollama.js b/modules/core/module-ollama.js
index 3eabe19..ba8ad57 100644
--- a/modules/core/module-ollama.js
+++ b/modules/core/module-ollama.js
@@ -1,52 +1,131 @@
-// Extracted from newOS4 index.html β€” OllamaModule
- class OllamaModule {
- constructor() { this.commands = {}; this.terminal = null; }
- getHelpInfo() {
- return {
- 'ollama': 'ollama β€” Open the Ollama model manager UI',
- 'ollamaconnect': 'ollamaconnect β€” Connect to the Ollama server',
- 'ollamadisconnect': 'ollamadisconnect β€” Disconnect from the Ollama server',
- 'ollamamodels': 'ollamamodels β€” List all available models from Ollama',
- 'ollamasetmodel': 'ollamasetmodel <name> β€” Set the active Ollama model',
- 'ollamasetproxy': 'ollamasetproxy [endpoint] β€” View or change the Ollama endpoint URL',
- };
+// Extracted from newOS4 index.html β€” OllamaModule (merged with OllamaModelsModule)
+// Commands: ollama, ollamaconnect, ollamadisconnect, ollamamodels, ollamasetmodel, ollamasetproxy, models, model-info, model-pull, model-delete, model-run, ai, ask
+class OllamaModule {
+ constructor() { this.commands = {}; this.terminal = null; }
+ getHelpInfo() {
+ return {
+ 'ollama': 'ollama β€” Open the Ollama model manager UI',
+ 'ollamaconnect': 'ollamaconnect β€” Connect to the Ollama server',
+ 'ollamadisconnect': 'ollamadisconnect β€” Disconnect from the Ollama server',
+ 'ollamamodels': 'ollamamodels β€” List all available models from Ollama',
+ 'models': 'models β€” List all available Ollama models (table format)',
+ 'model-info': 'model-info <model-name> β€” Show details about a specific model',
+ 'model-pull': 'model-pull <model-name> β€” Pull a model from Ollama registry',
+ 'model-delete': 'model-delete <model-name> β€” Delete a model from local storage',
+ 'model-run': 'model-run <model-name> [prompt] β€” Run inference with a model',
+ 'ollamasetmodel': 'ollamasetmodel <name> β€” Set the active Ollama model',
+ 'ollamasetproxy': 'ollamasetproxy [endpoint] β€” View or change the Ollama endpoint URL',
+ };
+ }
+ registerCommands() {
+ this.commands['ollama'] = () => { this.terminal.openOllamaManager(); };
+ this.commands['ollamaconnect'] = async () => {
+ await this.terminal.ollamaManager.connect();
+ this.terminal.updateOllamaStatus();
+ };
+ this.commands['ollamadisconnect'] = () => {
+ this.terminal.ollamaManager.connected = false;
+ this.terminal.ollamaManager.models = [];
+ this.terminal.print('Ollama disconnected', 'info');
+ this.terminal.updateOllamaStatus();
+ };
+ this.commands['ollamamodels'] = () => {
+ const models = this.terminal.ollamaManager.getModels();
+ if(models.length === 0) return this.terminal.print("No models found. Connect first.");
+ models.forEach(m => this.terminal.print(`${m.name} (${(m.size/1e9).toFixed(1)}GB)`));
+ };
+ this.commands['ollamasetmodel'] = (args) => {
+ if(!args[0]) return this.terminal.print("Usage: ollamasetmodel <name>", 'warning');
+ this.terminal.ollamaManager.setModel(args[0]);
+ };
+ this.commands['ollamasetproxy'] = (args) => {
+ if(!args[0]) {
+ const ep = this.terminal.ollamaManager.endpoint;
+ return this.terminal.print(`Current Ollama endpoint: ${ep}`, 'info');
}
- registerCommands() {
- this.commands['ollama'] = () => { this.terminal.openOllamaManager(); };
- this.commands['ollamaconnect'] = async () => {
- await this.terminal.ollamaManager.connect();
- this.terminal.updateOllamaStatus();
- };
- this.commands['ollamadisconnect'] = () => {
- this.terminal.ollamaManager.connected = false;
- this.terminal.ollamaManager.models = [];
- this.terminal.print('Ollama disconnected', 'info');
- this.terminal.updateOllamaStatus();
- };
- this.commands['ollamamodels'] = () => {
- const models = this.terminal.ollamaManager.getModels();
- if(models.length === 0) return this.terminal.print("No models found. Connect first.");
- models.forEach(m => this.terminal.print(`${m.name} (${(m.size/1e9).toFixed(1)}GB)`));
- };
- this.commands['ollamasetmodel'] = (args) => {
- if(!args[0]) return this.terminal.print("Usage: ollamasetmodel <name>", 'warning');
- this.terminal.ollamaManager.setModel(args[0]);
- };
- this.commands['ollamasetproxy'] = (args) => {
- if(!args[0]) {
- const ep = this.terminal.ollamaManager.endpoint;
- return this.terminal.print(`Current Ollama endpoint: ${ep}`, 'info');
- }
- this.terminal.ollamaManager.setEndpoint(args[0]);
- this.terminal.print(`Ollama endpoint set to: ${args[0]}`, 'success');
- };
- this.commands['ai'] = async (args) => {
- if(!args[0]) return this.terminal.print("Usage: ai <prompt>", 'warning');
- await this.terminal.ollamaManager.chat(args.join(' '));
- };
- this.commands['ask'] = async (args) => {
- if(!args[0]) return this.terminal.print("Usage: ask <prompt>", 'warning');
- await this.terminal.ollamaManager.chat(args.join(' '));
- };
+ this.terminal.ollamaManager.setEndpoint(args[0]);
+ this.terminal.print(`Ollama endpoint set to: ${args[0]}`, 'success');
+ };
+ this.commands['ai'] = async (args) => {
+ if(!args[0]) return this.terminal.print("Usage: ai <prompt>", 'warning');
+ await this.terminal.ollamaManager.chat(args.join(' '));
+ };
+ this.commands['ask'] = async (args) => {
+ if(!args[0]) return this.terminal.print("Usage: ask <prompt>", 'warning');
+ await this.terminal.ollamaManager.chat(args.join(' '));
+ };
+ // Merged from OllamaModelsModule
+ this.commands['models'] = () => this.listModels();
+ this.commands['model-info'] = (args) => this.modelInfo(args);
+ this.commands['model-pull'] = (args) => this.pullModel(args);
+ this.commands['model-delete'] = (args) => this.deleteModel(args);
+ this.commands['model-run'] = (args) => this.runModel(args);
+ }
+ async listModels() {
+ const endpoint = localStorage.getItem('webx11_ollama_endpoint') || 'http://localhost:11434';
+ try {
+ const response = await fetch(`${endpoint}/api/tags`);
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
+ const data = await response.json();
+ const models = data.models || [];
+ if (models.length === 0) {
+ this.terminal.print("No models found. Run 'ollama pull <model>' first.", "warning"); return;
}
+ this.terminal.print("=== Available Ollama Models ===", "info");
+ this.terminal.printHTML(`<table style="width: 100%; border-collapse: collapse; margin: 10px 0;">
+ <tr style="border-bottom: 1px solid #005500;">
+ <th style="text-align: left; padding: 5px;">Name</th>
+ <th style="text-align: left; padding: 5px;">Size</th>
+ <th style="text-align: left; padding: 5px;">Family</th>
+ </tr>`);
+ models.forEach(m => {
+ const sizeGB = (m.size / 1e9).toFixed(2);
+ this.terminal.printHTML(`<tr style="border-bottom: 1px solid #111;">
+ <td style="padding: 5px; color: #00ff00;">${m.name}</td>
+ <td style="padding: 5px; color: #888888;">${sizeGB} GB</td>
+ <td style="padding: 5px; color: #00aaff;">${m.details?.family || 'N/A'}</td>
+ </tr>`);
+ });
+ this.terminal.printHTML(`</table>`);
+ } catch (e) {
+ this.terminal.print(`Failed to fetch models: ${e.message}`, "error");
}
+ }
+ async modelInfo(args) {
+ if (!args[0]) {
+ this.terminal.print("Usage: model-info <model-name>", "warning"); return;
+ }
+ const endpoint = localStorage.getItem('webx11_ollama_endpoint') || 'http://localhost:11434';
+ try {
+ const response = await fetch(`${endpoint}/api/show`, {
+ method: 'POST', headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ name: args[0] })
+ });
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
+ const data = await response.json();
+ this.terminal.print(`=== ${args[0]} ===`, "info");
+ this.terminal.print(`License: ${data.license || 'N/A'}`);
+ this.terminal.print(`Parameters: ${data.details?.parameter_size || 'N/A'}`);
+ this.terminal.print(`Family: ${data.details?.family || 'N/A'}`);
+ } catch (e) {
+ this.terminal.print(`Failed to get model info: ${e.message}`, "error");
+ }
+ }
+ pullModel(args) {
+ this.terminal.print("⚠️ Model pulling must be done via Ollama CLI", "warning");
+ this.terminal.print(`Run: ollama pull ${args[0] || '<model-name>'}`, "info");
+ }
+ deleteModel(args) {
+ this.terminal.print("⚠️ Model deletion must be done via Ollama CLI", "warning");
+ this.terminal.print(`Run: ollama rm ${args[0] || '<model-name>'}`, "info");
+ }
+ async runModel(args) {
+ if (!args[0]) {
+ this.terminal.print("Usage: model-run <model-name> [prompt]", "warning"); return;
+ }
+ const model = args[0];
+ const prompt = args.slice(1).join(' ') || 'Hello!';
+ this.terminal.print(`Running ${model}...`, "info");
+ await this.terminal.ollamaManager.chat(prompt, model);
+ }
+} \ No newline at end of file
diff --git a/modules/core/module-ollamamodels.js b/modules/core/module-ollamamodels.js
deleted file mode 100644
index 9a7763a..0000000
--- a/modules/core/module-ollamamodels.js
+++ /dev/null
@@ -1,87 +0,0 @@
-// Extracted from newOS4 index.html β€” OllamaModelsModule
- class OllamaModelsModule {
- constructor() { this.commands = {}; this.terminal = null; }
- getHelpInfo() {
- return {
- 'models': 'models β€” List all available Ollama models',
- 'model-info': 'model-info <model-name> β€” Show details about a specific model',
- 'model-pull': 'model-pull <model-name> β€” Pull a model from Ollama registry',
- 'model-delete': 'model-delete <model-name> β€” Delete a model from local storage',
- 'model-run': 'model-run <model-name> [prompt] β€” Run inference with a model'
- };
- }
- registerCommands() {
- this.commands['models'] = () => this.listModels();
- this.commands['model-info'] = (args) => this.modelInfo(args);
- this.commands['model-pull'] = (args) => this.pullModel(args);
- this.commands['model-delete'] = (args) => this.deleteModel(args);
- this.commands['model-run'] = (args) => this.runModel(args);
- }
- async listModels() {
- const endpoint = localStorage.getItem('webx11_ollama_endpoint') || 'http://localhost:11434';
- try {
- const response = await fetch(`${endpoint}/api/tags`);
- if (!response.ok) throw new Error(`HTTP ${response.status}`);
- const data = await response.json();
- const models = data.models || [];
- if (models.length === 0) {
- this.terminal.print("No models found. Run 'ollama pull <model>' first.", "warning"); return;
- }
- this.terminal.print("=== Available Ollama Models ===", "info");
- this.terminal.printHTML(`<table style="width: 100%; border-collapse: collapse; margin: 10px 0;">
- <tr style="border-bottom: 1px solid #005500;">
- <th style="text-align: left; padding: 5px;">Name</th>
- <th style="text-align: left; padding: 5px;">Size</th>
- <th style="text-align: left; padding: 5px;">Family</th>
- </tr>`);
- models.forEach(m => {
- const sizeGB = (m.size / 1e9).toFixed(2);
- this.terminal.printHTML(`<tr style="border-bottom: 1px solid #111;">
- <td style="padding: 5px; color: #00ff00;">${m.name}</td>
- <td style="padding: 5px; color: #888888;">${sizeGB} GB</td>
- <td style="padding: 5px; color: #00aaff;">${m.details?.family || 'N/A'}</td>
- </tr>`);
- });
- this.terminal.printHTML(`</table>`);
- } catch (e) {
- this.terminal.print(`Failed to fetch models: ${e.message}`, "error");
- }
- }
- async modelInfo(args) {
- if (!args[0]) {
- this.terminal.print("Usage: model-info <model-name>", "warning"); return;
- }
- const endpoint = localStorage.getItem('webx11_ollama_endpoint') || 'http://localhost:11434';
- try {
- const response = await fetch(`${endpoint}/api/show`, {
- method: 'POST', headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ name: args[0] })
- });
- if (!response.ok) throw new Error(`HTTP ${response.status}`);
- const data = await response.json();
- this.terminal.print(`=== ${args[0]} ===`, "info");
- this.terminal.print(`License: ${data.license || 'N/A'}`);
- this.terminal.print(`Parameters: ${data.details?.parameter_size || 'N/A'}`);
- this.terminal.print(`Family: ${data.details?.family || 'N/A'}`);
- } catch (e) {
- this.terminal.print(`Failed to get model info: ${e.message}`, "error");
- }
- }
- pullModel(args) {
- this.terminal.print("⚠️ Model pulling must be done via Ollama CLI", "warning");
- this.terminal.print(`Run: ollama pull ${args[0] || '<model-name>'}`, "info");
- }
- deleteModel(args) {
- this.terminal.print("⚠️ Model deletion must be done via Ollama CLI", "warning");
- this.terminal.print(`Run: ollama rm ${args[0] || '<model-name>'}`, "info");
- }
- async runModel(args) {
- if (!args[0]) {
- this.terminal.print("Usage: model-run <model-name> [prompt]", "warning"); return;
- }
- const model = args[0];
- const prompt = args.slice(1).join(' ') || 'Hello!';
- this.terminal.print(`Running ${model}...`, "info");
- await this.terminal.ollamaManager.chat(prompt, model);
- }
- }
diff --git a/modules/core/module-orchestrator.js b/modules/core/module-orchestrator.js
index 4fab599..de88424 100644
--- a/modules/core/module-orchestrator.js
+++ b/modules/core/module-orchestrator.js
@@ -75,6 +75,22 @@ class OrchestratorModule {
agent = Object.values(this._agents).find(a => a.status === 'idle');
}
if (!agent) return this.terminal.print('❌ No available agents', 'error');
+
+ // A2A Contract handshake β€” validate task against agent's contract
+ const registry = this.terminal.moduleManager.modules['AgentRegistryModule'];
+ let contractValid = true;
+ if (registry) {
+ const result = registry.validateTask(agent.role, task);
+ if (!result.valid) {
+ this.terminal.print(`⚠️ A2A validation: ${result.reason}`, 'warning');
+ this.terminal.print(` Contract for '${agent.role}' requires: ${(registry.getContract(agent.role) || {}).input_schema || 'free-form'}`, 'warning');
+ // Offer to proceed anyway (permissive) β€” user can create a proper contract
+ contractValid = false;
+ } else if (result.reason === 'matched') {
+ this.terminal.print(`βœ… A2A contract matched for role '${agent.role}'`, 'success');
+ }
+ }
+
// Create a lease
const leaseModule = this.terminal.moduleManager.modules['LeaseModule'];
const lease = leaseModule ? leaseModule.createLease(['lease-create', agent.id, '60', task]) : null;
diff --git a/modules/core/module-servermon.js b/modules/core/module-servermon.js
index 23407db..293e9af 100644
--- a/modules/core/module-servermon.js
+++ b/modules/core/module-servermon.js
@@ -1,35 +1,143 @@
-// Extracted from newOS4 index.html β€” ServerMonitorModule
- class ServerMonitorModule {
- constructor() {
- this.commands = {}; this.terminal = null;
- this.servers = this.loadServers(); this.monitorInterval = null;
- }
- getHelpInfo() {
- return {
- 'server': 'Add a server to monitor: server <name> <url>',
- 'servers': 'List all monitored servers',
- 'server-check': 'Check a server status: server-check <name-or-index>',
- 'server-remove': 'Remove a server: server-remove <name-or-index>',
- 'monitor': 'Toggle auto-monitoring (checks every 60s)'
- };
- }
- loadServers() {
- try {
- const saved = localStorage.getItem('webx11_servers');
- return saved ? JSON.parse(saved) : [];
- } catch (e) { return []; }
- }
- saveServers() {
- localStorage.setItem('webx11_servers', JSON.stringify(this.servers));
- }
- registerCommands() {
- this.commands['server'] = (args) => this.addServer(args);
- this.commands['servers'] = () => this.listServers();
- this.commands['server-check'] = (args) => this.checkServer(args);
- this.commands['server-remove'] = (args) => this.removeServer(args);
- this.commands['monitor'] = (args) => this.toggleMonitor(args);
- }
- addServer(args) {
+// module-servermon.js β€” Server monitoring + self-optimization telemetry
+// Commands: server, servers, server-check, server-remove, monitor, system-health
+class ServerMonitorModule {
+ constructor() {
+ this.commands = {}; this.terminal = null;
+ this.servers = this.loadServers(); this.monitorInterval = null;
+ this._latencyLog = [];
+ this._maxLatencyEntries = 200;
+ }
+ getHelpInfo() {
+ return {
+ 'server': 'server <name> <url> β€” Add a server to monitor',
+ 'servers': 'servers β€” List all monitored servers',
+ 'server-check': 'server-check <name-or-index> β€” Check a server status',
+ 'server-remove': 'server-remove <name-or-index> β€” Remove a server',
+ 'monitor': 'monitor β€” Toggle auto-monitoring (checks every 60s)',
+ 'system-health': 'system-health β€” Show tool latency, module load times, VFS size, and error rates'
+ };
+ }
+ registerCommands() {
+ this.commands['server'] = (args) => this.addServer(args);
+ this.commands['servers'] = () => this.listServers();
+ this.commands['server-check'] = (args) => this.checkServer(args);
+ this.commands['server-remove'] = (args) => this.removeServer(args);
+ this.commands['monitor'] = (args) => this.toggleMonitor(args);
+ this.commands['system-health'] = () => this.showSystemHealth();
+ }
+ logToolCall(name, durationMs, error) {
+ this._latencyLog.push({
+ name,
+ duration: durationMs,
+ error: !!error,
+ time: Date.now()
+ });
+ if (this._latencyLog.length > this._maxLatencyEntries) {
+ this._latencyLog = this._latencyLog.slice(-this._maxLatencyEntries);
+ }
+ // Persist every 20 calls
+ if (this._latencyLog.length % 20 === 0) {
+ this._persistLatency();
+ }
+ }
+ _persistLatency() {
+ try {
+ this.terminal.fs.fsWriteJSON('/system/metrics/tool-latency.json', this._latencyLog.slice(-100));
+ } catch (e) {}
+ }
+ _loadLatency() {
+ try {
+ const data = this.terminal.fs.fsReadJSON('/system/metrics/tool-latency.json');
+ if (data) this._latencyLog = data;
+ } catch (e) {}
+ }
+ showSystemHealth() {
+ this._loadLatency();
+ const fs = this.terminal.fs;
+
+ // Tool latency stats
+ const toolStats = {};
+ for (const entry of this._latencyLog) {
+ if (!toolStats[entry.name]) toolStats[entry.name] = { calls: 0, totalMs: 0, errors: 0, maxMs: 0 };
+ toolStats[entry.name].calls++;
+ toolStats[entry.name].totalMs += entry.duration;
+ toolStats[entry.name].errors += entry.error ? 1 : 0;
+ toolStats[entry.name].maxMs = Math.max(toolStats[entry.name].maxMs, entry.duration);
+ }
+
+ this.terminal.print('πŸ“Š System Health', 'header');
+
+ // Tool latency table (sorted by avg desc)
+ this.terminal.print('── Tool Latency ──', 'info');
+ const sorted = Object.entries(toolStats)
+ .map(([name, s]) => ({ name, avg: (s.totalMs / s.calls).toFixed(0), ...s }))
+ .sort((a, b) => b.avg - a.avg);
+ for (const t of sorted.slice(0, 10)) {
+ const avgMs = t.avg.padStart(5);
+ const maxMs = String(t.maxMs).padStart(5);
+ const err = t.errors > 0 ? ` ⚠️${t.errors}` : '';
+ this.terminal.print(` ${avgMs}ms avg / ${maxMs}ms max β€” ${t.name} (${t.calls} calls)${err}`, t.errors > 0 ? 'warning' : '');
+ }
+ if (sorted.length > 10) this.terminal.print(` ... and ${sorted.length - 10} more tools`, 'info');
+
+ // VFS stats
+ this.terminal.print('── VFS Stats ──', 'info');
+ try {
+ const totalSize = this._vfsSize(fs.root);
+ const fileCount = this._vfsCount(fs.root, 'file');
+ const dirCount = this._vfsCount(fs.root, 'dir');
+ this.terminal.print(` ${fileCount} files, ${dirCount} dirs, ${(totalSize / 1024).toFixed(0)} KB total`, '');
+ } catch (e) { this.terminal.print(' VFS stats unavailable', 'warning'); }
+
+ // Module stats
+ this.terminal.print('── Module Stats ──', 'info');
+ const mm = this.terminal.moduleManager;
+ const loaded = Object.keys(mm.modules).length;
+ const reg = (mm.moduleRegistry || []).length;
+ this.terminal.print(` ${loaded} modules loaded, ${reg} in registry`, '');
+
+ // Memory
+ this.terminal.print('── Memory ──', 'info');
+ if (performance.memory) {
+ const heap = (performance.memory.usedJSHeapSize / 1048576).toFixed(1);
+ const total = (performance.memory.jsHeapSizeLimit / 1048576).toFixed(0);
+ this.terminal.print(` ${heap} MB used / ${total} MB limit`, heap > 100 ? 'warning' : '');
+ } else {
+ this.terminal.print(' Memory info not available (non-Chrome browser)', '');
+ }
+
+ // Total tool call count
+ const totalCalls = this._latencyLog.length;
+ const totalErrors = this._latencyLog.filter(e => e.error).length;
+ this.terminal.print(` ${totalCalls} tool calls logged, ${totalErrors} errors (${totalCalls > 0 ? (totalErrors / totalCalls * 100).toFixed(1) : 0}% error rate)`, totalErrors > 0 ? 'warning' : '');
+ }
+ _vfsSize(node) {
+ if (!node) return 0;
+ if (node.type === 'file') return (node.content || '').length;
+ let s = 0;
+ for (const k in (node.content || {})) s += this._vfsSize(node.content[k]);
+ return s;
+ }
+ _vfsCount(node, type) {
+ if (!node) return 0;
+ let c = 0;
+ for (const k in (node.content || {})) {
+ const child = node.content[k];
+ if (child.type === type) c++;
+ c += this._vfsCount(child, type);
+ }
+ return c;
+ }
+ loadServers() {
+ try {
+ const saved = localStorage.getItem('webx11_servers');
+ return saved ? JSON.parse(saved) : [];
+ } catch (e) { return []; }
+ }
+ saveServers() {
+ localStorage.setItem('webx11_servers', JSON.stringify(this.servers));
+ }
+ addServer(args) {
if (args.length < 2) {
this.terminal.print("Usage: server <name> <url>", "warning"); return;
}
diff --git a/modules/core/terminal.js b/modules/core/terminal.js
index 4111f5f..e3f222c 100644
--- a/modules/core/terminal.js
+++ b/modules/core/terminal.js
@@ -14,7 +14,7 @@
this._registerBuiltIn();
}
_registerBuiltIn() {
- const internals = ['clear','help','ls','cat','df','free','env','history','cd','pwd','touch','mkdir','rm','cp','mv','edit','cat','run','font-size','load-local','loadlocal','mem','security','security-level','startup-modules','smart-prompt','cmd-allow','cmd-deny'];
+ const internals = ['clear','help','ls','cat','df','free','env','history','cd','pwd','touch','mkdir','rm','cp','mv','edit','cat','run','font-size','load-local','loadlocal','mem','security','security-level','startup-modules','smart-prompt','cmd-allow','cmd-deny','system-health','server','servers','server-check','monitor'];
internals.forEach(c => this.registerCommand(c, { category: 'builtin' }));
}
setLevel(n) {
@@ -1027,6 +1027,9 @@
this._safeRegister('AgentRegistryModule', 'agent registry');
this._safeRegister('LeaseModule', 'lease system');
this._safeRegister('OrchestratorModule', 'orchestrator');
+ this._safeRegister('NeuralVFSModule', 'neural VFS');
+ this._safeRegister('ServerMonitorModule', 'server monitor');
+ this._safeRegister('SimpleGUIModule', 'simple GUI builder');
}
_safeRegister(className, label) {
let cls;
diff --git a/modules/core/virtual-fs.js b/modules/core/virtual-fs.js
index d2d3103..3ab25b1 100644
--- a/modules/core/virtual-fs.js
+++ b/modules/core/virtual-fs.js
@@ -3,6 +3,7 @@ class VirtualFileSystem {
this.root = { type: 'dir', content: {} };
this.currentPath = [];
this._ready = this.loadFromStorage();
+ this._conceptCache = null;
}
_u8ToBase64(u8) {
let s = '';
@@ -82,6 +83,27 @@ class VirtualFileSystem {
} catch (e) { console.error('FS save error:', e); }
}, 2000);
}
+ getCurrentPath() {
+ return '/' + this.currentPath.join('/');
+ }
+ setCurrentPath(path) {
+ const segs = this._toAbsoluteSegments(path);
+ if (segs === null) return false;
+ this.currentPath = segs;
+ return true;
+ }
+ _loadConceptIndex() {
+ if (this._conceptCache) return this._conceptCache;
+ try {
+ const raw = this.readFile('/.semantic_index/map.json');
+ if (raw) {
+ this._conceptCache = JSON.parse(raw);
+ return this._conceptCache;
+ }
+ } catch (e) {}
+ return null;
+ }
+ _clearConceptCache() { this._conceptCache = null; }
getCurrentDir() {
let dir = this.root;
for (let part of this.currentPath) {
@@ -130,6 +152,18 @@ class VirtualFileSystem {
return dir;
}
ls(path) {
+ // concept:// listing
+ if (path && path.startsWith('concept://')) {
+ const concept = path.replace('concept://', '').replace(/\/.*$/, '').toLowerCase();
+ const index = this._loadConceptIndex();
+ if (!index) return [];
+ let matches = index[concept] || [];
+ if (matches.length === 0) {
+ const fuzzy = Object.keys(index).filter(k => k.includes(concept) || concept.includes(k));
+ if (fuzzy.length > 0) matches = index[fuzzy[0]];
+ }
+ return (matches || []).map(m => ({ name: m.path.split('/').pop(), type: 'file', path: m.path, size: 0, concept: true }));
+ }
let dir;
if (path) {
const resolved = this._resolvePath(path);
@@ -161,6 +195,24 @@ class VirtualFileSystem {
return true;
}
readFile(path) {
+ // concept:// URI resolution
+ if (path && path.startsWith('concept://')) {
+ const concept = path.replace('concept://', '').replace(/\/.*$/, '').toLowerCase();
+ try {
+ const index = this._loadConceptIndex();
+ if (!index) return 'No semantic index found. Run nvfs-index first.';
+ let matches = index[concept];
+ if (!matches) {
+ const fuzzy = Object.keys(index).filter(k => k.includes(concept) || concept.includes(k));
+ if (fuzzy.length > 0) matches = index[fuzzy[0]];
+ }
+ if (!matches || matches.length === 0) return `No files found for concept "${concept}"`;
+ const first = matches[0];
+ const content = this.readFile(first.path);
+ if (content) return `--- ${first.path} (concept://${concept}) ---\n${content}`;
+ return `Concept "${concept}" β†’ ${matches.length} file(s):\n${matches.map(m => ` ${m.path} β€” ${m.summary || ''}`).join('\n')}`;
+ } catch (e) { return `concept:// error: ${e.message}`; }
+ }
const resolved = this._resolvePath(path);
if (!resolved || !resolved.name) return null;
const node = resolved.dir.content[resolved.name];
diff --git a/modules/ext/mindmap.js b/modules/ext/mindmap.js
index 9f62cba..d0cab54 100644
--- a/modules/ext/mindmap.js
+++ b/modules/ext/mindmap.js
@@ -44,11 +44,12 @@ class MindmapModule {
const self = this;
this.commands['mindmap'] = (args) => {
if (!args[0] || args[0] === '--help' || args[0] === '-h') {
- this.terminal.print('Usage: mindmap <new|add|show|export|save|load|list|delete|rename|color|tag> [...]', 'info');
+ this.terminal.print('Usage: mindmap <new|add|show|export|save|load|list|delete|rename|color|tag|svg> [...]', 'info');
this.terminal.print(' new <topic> [-t tags] β€” Create a new mindmap', 'info');
this.terminal.print(' add <parent-id> <text> [-t tags] β€” Add a child node', 'info');
this.terminal.print(' show β€” Display the mindmap tree', 'info');
this.terminal.print(' export β€” Print as indented text', 'info');
+ this.terminal.print(' svg [name] β€” Render as inline SVG, optionally save to VFS', 'info');
this.terminal.print(' save [name] β€” Save to VFS', 'info');
this.terminal.print(' load <name> β€” Load from VFS', 'info');
this.terminal.print(' list β€” List saved mindmaps', 'info');
@@ -77,7 +78,8 @@ class MindmapModule {
case 'rename': return this._rename(rest);
case 'color': return this._color(rest);
case 'tag': return this._tag(rest);
- default: this.terminal.print('Unknown subcommand: ' + sub + '. Try: new, add, show, export, save, load, list, delete, rename, color, tag', 'warning');
+ case 'svg': return this._svg(rest);
+ default: this.terminal.print('Unknown subcommand: ' + sub + '. Try: new, add, show, export, save, load, list, delete, rename, color, tag, svg', 'warning');
}
};
}
@@ -232,6 +234,77 @@ class MindmapModule {
node.tags.push(tag);
this.terminal.print('Added tag "' + tag + '" to ' + id, 'success');
}
+ _svg(args) {
+ if (!this.root) return this.terminal.print('No mindmap. Create one with mindmap new first.', 'warning');
+ const saveName = args[0] || null;
+
+ // Layout settings
+ const nw = 160, nh = 44, hGap = 24, vGap = 60, pad = 30;
+
+ // Color mapping from name to hex
+ const colorMap = {
+ red: '#fb7185', green: '#34d399', yellow: '#fbbf24', blue: '#818cf8',
+ cyan: '#22d3ee', magenta: '#e879f9', white: '#e0e0e0'
+ };
+
+ const layout = { nodes: [], edges: [], width: 0, height: 0, _y: pad };
+
+ const layoutTree = (node, x) => {
+ const myY = layout._y;
+ const myX = x;
+ const color = colorMap[node.color] || '#818cf8';
+ layout.nodes.push({ x: myX, y: myY, w: nw, h: nh, text: node.text, color, id: node.id });
+
+ if (node.children && node.children.length > 0) {
+ const totalW = node.children.length * nw + (node.children.length - 1) * hGap;
+ let cx = x + nw / 2 - totalW / 2;
+ layout._y += nh + vGap;
+ for (const child of node.children) {
+ const childX = cx;
+ layout.edges.push({ x1: myX + nw / 2, y1: myY, x2: childX + nw / 2, y2: layout._y - vGap + nh });
+ layoutTree(child, childX);
+ cx += nw + hGap;
+ }
+ layout._y -= nh + vGap;
+ }
+ const rightEdge = x + nw;
+ if (rightEdge > layout.width) layout.width = rightEdge;
+ };
+
+ layout._y = pad;
+ layoutTree(this.root, pad);
+ layout.height = layout._y + nh + pad;
+
+ // Build SVG
+ let svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${layout.width + pad} ${layout.height}" style="max-width:100%;background:#0a0a14;font-family:monospace;border-radius:8px;">`;
+
+ // Edges first (behind nodes)
+ for (const e of layout.edges) {
+ const mx = (e.x1 + e.x2) / 2;
+ svg += `<path d="M${e.x1},${e.y1} C${mx},${e.y1 + 20} ${mx},${e.y2 - 20} ${e.x2},${e.y2}" fill="none" stroke="#2a2a4a" stroke-width="1.5"/>`;
+ }
+
+ // Nodes on top
+ for (const n of layout.nodes) {
+ svg += `<rect x="${n.x}" y="${n.y}" width="${n.w}" height="${n.h}" rx="6" fill="${n.color}18" stroke="${n.color}" stroke-width="1.5"/>`;
+ const text = n.text.length > 18 ? n.text.substring(0, 16) + '..' : n.text;
+ svg += `<text x="${n.x + n.w / 2}" y="${n.y + n.h / 2 + 4}" text-anchor="middle" fill="#e0e0e0" font-size="10" font-family="monospace">${text.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')}</text>`;
+ }
+ svg += '</svg>';
+
+ this.terminal.printHTML(svg);
+
+ if (saveName) {
+ try {
+ const fs = this.terminal.fs;
+ fs.mkdirRecursive('/mindmaps');
+ fs.writeFile('/mindmaps/' + saveName + '.svg', svg);
+ this.terminal.print('πŸ’Ύ Saved to /mindmaps/' + saveName + '.svg', 'success');
+ } catch (e) {
+ this.terminal.print('Failed to save SVG: ' + e.message, 'error');
+ }
+ }
+ }
}
if (typeof window.webx11 !== 'undefined' && window.webx11) {
webx11.moduleManager.registerModule(new MindmapModule(), 'https://webx11.duckdns.org/spaces/newos4/modules/ext/mindmap.js');
diff --git a/newos4_vision.html b/newos4_vision.html
index 7bdb262..c31bde1 100644
--- a/newos4_vision.html
+++ b/newos4_vision.html
@@ -116,16 +116,16 @@
<div class="section">
<h2>Strategic Roadmap</h2>
<div class="roadmap-item">
- <span class="phase">Phase 1</span>
+ <span class="phase">Phase 1 βœ…</span>
<span>Foundation: WebX11 terminal stability, VFS perfection, and Procedural Memory (Skills).</span>
</div>
<div class="roadmap-item">
- <span class="phase">Phase 2 βœ…</span>
- <span>Agentic Shift: Agent orchestration (list, register, leases, orchestrate). Security layer (security-level 0-3, cmd-allow/deny). Debug panel. WebDAV modern browser.</span>
+ <span class="phase">Phase 2 🟑</span>
+ <span>Agentic Shift: AI tool-calling loop (19+ tools), session_terminal context access, tool failure buffer + auto-skill creation, agent orchestration (list, register, leases, orchestrate). Security layer (security-level 0-3). Debug panel. Localized asset management.</span>
</div>
<div class="roadmap-item">
- <span class="phase">Phase 3</span>
- <span>Cognitive OS: Global World Model, Neural VFS, Recursive self-optimization, Predictive resource allocation.</span>
+ <span class="phase">Phase 3 🟒</span>
+ <span>Cognitive OS: Neural VFS (semantic concept indexing), A2A Protocol (agent contracts + handshake), Recursive self-optimization, Predictive resource allocation.</span>
</div>
</div>
diff --git a/packages.json b/packages.json
index 614c9c5..5d8203b 100644
--- a/packages.json
+++ b/packages.json
@@ -1,7 +1,7 @@
{
"name": "WebX11 Package Index",
- "version": "1.0.0",
- "updated": "2026-05-24T00:00:00Z",
+ "version": "1.1.0",
+ "updated": "2026-06-04T00:00:00Z",
"base_url": "https://webx11.duckdns.org/spaces/newos4/modules/ext/",
"packages": {
"voice": {
@@ -9,7 +9,9 @@
"version": "1.0.0",
"desc": "Speech-to-text input using Web Speech API",
"url": "modules/ext/voice.js",
- "commands": ["voice"],
+ "commands": [
+ "voice"
+ ],
"category": "input"
},
"calc": {
@@ -17,7 +19,9 @@
"version": "1.0.0",
"desc": "Math evaluator and unit converter (km to miles, kg to pounds, etc.)",
"url": "modules/ext/calc.js",
- "commands": ["calc"],
+ "commands": [
+ "calc"
+ ],
"category": "utility"
},
"cron": {
@@ -25,7 +29,12 @@
"version": "1.0.0",
"desc": "Schedule commands to run at intervals (min 5s)",
"url": "modules/ext/cron.js",
- "commands": ["cron-every", "cron-list", "cron-stop", "cron-clear"],
+ "commands": [
+ "cron-every",
+ "cron-list",
+ "cron-stop",
+ "cron-clear"
+ ],
"category": "automation"
},
"theme": {
@@ -33,7 +42,9 @@
"version": "1.0.0",
"desc": "CSS theme manager β€” dark, light, amber, cyber + custom",
"url": "modules/ext/theme.js",
- "commands": ["theme"],
+ "commands": [
+ "theme"
+ ],
"category": "ui"
},
"wpm": {
@@ -41,7 +52,9 @@
"version": "1.0.0",
"desc": "Install modules from the WebX11 package index (like npm for the terminal)",
"url": "modules/ext/wpm.js",
- "commands": ["wpm"],
+ "commands": [
+ "wpm"
+ ],
"category": "system"
},
"webdav": {
@@ -49,7 +62,16 @@
"version": "1.0.0",
"desc": "Cloud sync for VFS β€” backup, push, pull, and restore via WebDAV",
"url": "modules/ext/webdav.js",
- "commands": ["webdav-config", "webdav-status", "webdav-ls", "webdav-push", "webdav-pull", "webdav-backup", "webdav-restore", "webdav-backup-list"],
+ "commands": [
+ "webdav-config",
+ "webdav-status",
+ "webdav-ls",
+ "webdav-push",
+ "webdav-pull",
+ "webdav-backup",
+ "webdav-restore",
+ "webdav-backup-list"
+ ],
"category": "system"
},
"mindmap": {
@@ -57,7 +79,9 @@
"version": "1.0.0",
"desc": "Brainstorming mindmap tool β€” new, add, show, export, save, load, color, tag",
"url": "modules/ext/mindmap.js",
- "commands": ["mindmap"],
+ "commands": [
+ "mindmap"
+ ],
"category": "productivity"
},
"skill-pack-core": {
@@ -65,7 +89,9 @@
"version": "1.0.0",
"desc": "Comprehensive skill set: terminal navigation, memory/profile, web search, module editing, system maintenance, backup, mindmap workflow, skills system guide",
"url": "modules/ext/skill-pack-core.js",
- "commands": ["skill-pack-core"],
+ "commands": [
+ "skill-pack-core"
+ ],
"category": "system"
},
"editor": {
@@ -73,7 +99,9 @@
"version": "1.0.0",
"desc": "Inline text editor for VFS files β€” edit, save, cancel via modal",
"url": "modules/ext/editor.js",
- "commands": ["edit"],
+ "commands": [
+ "edit"
+ ],
"category": "utility"
},
"diff": {
@@ -81,7 +109,9 @@
"version": "1.0.0",
"desc": "Compare two files or module versions with unified diff output",
"url": "modules/ext/diff.js",
- "commands": ["diff"],
+ "commands": [
+ "diff"
+ ],
"category": "utility"
},
"alias": {
@@ -89,7 +119,13 @@
"version": "1.0.0",
"desc": "Define and manage command aliases (ll, h, cls defaults) with localStorage persistence",
"url": "modules/ext/alias.js",
- "commands": ["alias", "unalias", "ll", "h", "cls"],
+ "commands": [
+ "alias",
+ "unalias",
+ "ll",
+ "h",
+ "cls"
+ ],
"category": "system"
},
"finder": {
@@ -97,7 +133,9 @@
"version": "1.0.0",
"desc": "Recursive VFS file/directory search with fuzzy matching",
"url": "modules/ext/finder.js",
- "commands": ["find"],
+ "commands": [
+ "find"
+ ],
"category": "utility"
},
"filemgr": {
@@ -105,7 +143,10 @@
"version": "1.0.0",
"desc": "Modern file browser with preview for Markdown, images, video, audio, code, PDF, CSV",
"url": "modules/ext/filemgr.js",
- "commands": ["files", "preview"],
+ "commands": [
+ "files",
+ "preview"
+ ],
"category": "utility"
},
"cryptogzip": {
@@ -113,7 +154,12 @@
"version": "1.0.0",
"desc": "AES-256-GCM encrypt/decrypt and gzip/gunzip for VFS files",
"url": "modules/ext/cryptogzip.js",
- "commands": ["gzip", "gunzip", "encrypt", "decrypt"],
+ "commands": [
+ "gzip",
+ "gunzip",
+ "encrypt",
+ "decrypt"
+ ],
"category": "security"
},
"busybox": {
@@ -121,7 +167,24 @@
"version": "1.0.0",
"desc": "Unix utility commands: which, env, date, cal, yes, seq, base64, printf, cut, uniq, hostname, whoami, basename, dirname, sleep, expand",
"url": "modules/ext/busybox.js",
- "commands": ["which", "env", "date", "cal", "yes", "seq", "base64", "printf", "cut", "uniq", "hostname", "whoami", "basename", "dirname", "sleep", "expand"],
+ "commands": [
+ "which",
+ "env",
+ "date",
+ "cal",
+ "yes",
+ "seq",
+ "base64",
+ "printf",
+ "cut",
+ "uniq",
+ "hostname",
+ "whoami",
+ "basename",
+ "dirname",
+ "sleep",
+ "expand"
+ ],
"category": "utility"
},
"shell": {
@@ -129,7 +192,12 @@
"version": "1.0.0",
"desc": "Full shell: pipe |, redirect > >> <, variable $VAR, chain && || ;, VFS script execution",
"url": "modules/ext/shell.js",
- "commands": ["export", "unset", "script", "set"],
+ "commands": [
+ "export",
+ "unset",
+ "script",
+ "set"
+ ],
"category": "system"
},
"tutorial": {
@@ -137,7 +205,9 @@
"version": "1.0.0",
"desc": "Interactive guided tour β€” 6 quests to learn newOS4 basics",
"url": "modules/ext/tutorial.js",
- "commands": ["tutorial"],
+ "commands": [
+ "tutorial"
+ ],
"category": "onboarding"
},
"test-suite": {
@@ -145,8 +215,23 @@
"version": "1.0.0",
"desc": "32 automated tests: filesystem, busybox, shell, cryptogzip, skills, security, modules. Run with `load-local modules/test/test-suite.js` then `test`",
"url": "modules/test/test-suite.js",
- "commands": ["test"],
+ "commands": [
+ "test"
+ ],
"category": "utility"
+ },
+ "neural-vfs": {
+ "name": "Neural VFS Indexer",
+ "version": "1.0.0",
+ "desc": "Semantic concept-indexing layer β€” nvfs-index, nvfs-resolve, nvfs-tree, nvfs-status",
+ "url": "modules/ext/neural-vfs.js",
+ "commands": [
+ "nvfs-index",
+ "nvfs-status",
+ "nvfs-resolve",
+ "nvfs-tree"
+ ],
+ "category": "system"
}
}
-}
+} \ No newline at end of file
diff --git a/review-newos4.html b/review-newos4.html
index 4ce41cc..3d8f7d4 100644
--- a/review-newos4.html
+++ b/review-newos4.html
@@ -75,7 +75,7 @@
<body>
<header>
<div class="header-content">
- <span class="logo"><span class="logo-icon">🧩</span> newOS4 v4.3 Review</span>
+ <span class="logo"><span class="logo-icon">🧩</span> newOS4 v4.3.1 Review</span>
<div style="display:flex;gap:8px;flex-wrap:wrap;">
<a href="/spaces/newos4/help.html">πŸ“– Help β†’</a>
<a href="/spaces/newos4/main.html">Launch OS β†’</a>
@@ -85,24 +85,25 @@
<div class="container">
-<h1>newOS4 v4.3</h1>
-<p class="meta">WebX11 Terminal Β· In-Browser Terminal OS Β· Reviewed 2026-06-02</p>
+<h1>newOS4 v4.3.1</h1>
+<p class="meta">WebX11 Terminal Β· In-Browser Terminal OS Β· Reviewed 2026-06-03</p>
<div class="summary-box">
- <div class="stat"><div class="value">32</div><div class="label">Module Files</div></div>
+ <div class="stat"><div class="value">33</div><div class="label">Module Files</div></div>
<div class="stat"><div class="value">18+14</div><div class="label">Core + Ext</div></div>
- <div class="stat"><div class="value">12</div><div class="label">Skills</div></div>
+ <div class="stat"><div class="value">21</div><div class="label">Skills</div></div>
<div class="stat"><div class="value">9</div><div class="label">Theme Presets</div></div>
<div class="stat"><div class="value">52KB</div><div class="label">App Size</div></div>
- <div class="stat"><div class="value">4/5</div><div class="label">Rating</div></div>
+ <div class="stat"><div class="value">4.5/5</div><div class="label">Rating</div></div>
</div>
<section>
<h2>Architecture</h2>
<p>newOS4 v4.3 is an <strong>in-browser terminal OS</strong> β€” NOT a chat-centric UI. Single-file <code>main.html</code> (1,031 lines, 52KB) loads 32 module files across two directories:</p>
<ul>
- <li><strong>18 core modules</strong> (<code>modules/core/</code>) β€” Foundation infrastructure (VirtualFileSystem, OllamaManager, SecretVault, ModuleManager, Terminal) + 13 built-in feature modules (system, fs, modmgr, ollama, my, searxng, servermon, ollamamodels, config, simplegui, io, dynamicprompts, aiassist, aiasm, smartctx, duckduckgo, fetcher, skills, chatstudio, debug)</li>
- <li><strong>14 ext modules</strong> (<code>modules/ext/</code>) β€” Self-registering: alias, busybox, calc, cron, cryptogzip, diff, editor, filemgr, finder, mindmap, shell, skill-pack-core, theme, tutorial, voice, webdav, wpm</li>
+ <li><strong>29 core modules</strong> (<code>modules/core/</code>) β€” Foundation infrastructure (VirtualFileSystem, OllamaManager, SecretVault, ModuleManager, Terminal) + 24 built-in feature modules (system, fs, modmgr, ollama, my, searxng, servermon, ollamamodels, config, simplegui, io, dynamicprompts, aiassist, aiasm, smartctx, duckduckgo, fetcher, skills, chatstudio, agent-registry, leases, orchestrator, neural-vfs)</li>
+ <li><strong>17 ext modules</strong> (<code>modules/ext/</code>) β€” Self-registering: alias, busybox, calc, cron, cryptogzip, diff, editor, filemgr, finder, mindmap, shell, skill-pack-core, theme, tutorial, voice, webdav, wpm</li>
+ <li><strong>46 modules total</strong> β€” Full discovery via <code>modules-list</code> command or AI <code>list_available_modules</code> tool. Indexed in <code>modules-index.json</code></li>
</ul>
<p><strong>Total codebase</strong>: ~500KB (main.html + all module files). AI system with 5-turn agentic loop, 19+ tool definitions, 12 skills in VFS, 9 theme presets, and full destructive-action confirmation.</p>
</section>
@@ -141,7 +142,14 @@
<h3>πŸ“š Skills System</h3>
<ul>
- <li><strong>12 skills</strong> stored as Markdown with YAML frontmatter in VFS <code>/skills/</code></li>
+ <li><strong>🧠 Neural VFS</strong> β€” Semantic concept indexing: <code>nvfs-index</code>, <code>nvfs-resolve</code>, <code>nvfs-status</code>, <code>nvfs-tree</code></li>
+ <li><strong>πŸ“œ A2A Protocol</strong> β€” Agent contract system with schema validation, orchestrator validates tasks before delegation</li>
+ <li><strong>πŸ“Š Self-Optimization Telemetry</strong> β€” <code>system-health</code> command with tool latency, VFS stats, error rates</li>
+ </ul>
+
+ <h3>πŸ“š Skills System</h3>
+ <ul>
+ <li><strong>21 skills</strong> (from 12) stored as Markdown with YAML frontmatter in VFS <code>/skills/</code></li>
<li>Skill-pack core auto-loads skills on startup with seed/reload</li>
<li>8 CLI commands: skill-list, skill-view, skill-create, skill-patch, skill-delete, skill-export, skill-import, skill-sync</li>
<li>Skills Manager UI modal (πŸ“š button in quick-actions bar)</li>
@@ -167,10 +175,12 @@
<h3>πŸ€– Agent Orchestration</h3>
<ul>
- <li><code>agent-list</code> β€” list registered AI agents and their status</li>
- <li><code>agent-register &lt;name&gt; &lt;model&gt;</code> β€” register a new AI agent</li>
- <li><code>lease-list</code> β€” show active agent leases/tasks</li>
- <li><code>orchestrate &lt;task&gt;</code> β€” delegate a multi-step task to the agent orchestrator</li>
+ <li><code>agent-list</code>, <code>agent-status</code> β€” list and inspect registered AI agents</li>
+ <li><code>agent-register</code>, <code>agent-unregister</code> β€” manage agent lifecycle</li>
+ <li><code>orchestrate &lt;task&gt;</code> β€” delegate multi-step task with A2A contract validation</li>
+ <li><code>orchestrator-status</code>, <code>orchestrator-spawn</code> β€” manage agent pool</li>
+ <li><code>contract-register</code>, <code>contract-list</code> β€” define agent contracts with input/output schema</li>
+ <li>Lease-based lifecycle: each task creates a lease with TTL, heartbeat monitoring, auto-purge</li>
</ul>
<h3>🎀 Voice Command</h3>
diff --git a/skills/a2a-contract-framework.md b/skills/a2a-contract-framework.md
new file mode 100644
index 0000000..51678b2
--- /dev/null
+++ b/skills/a2a-contract-framework.md
@@ -0,0 +1,30 @@
+---
+name: a2a-contract-framework
+description: Framework for formalizing Agent-to-Agent (A2A) contracts to ensure deterministic collaboration.
+tags: a2a, agent-orchestration, protocol, newos4
+category: system
+---
+
+# A2A Contract Framework
+
+## 1. Purpose
+To move from "best-effort" delegation to "contractual" execution by defining a strict interface (`.contract.json`) for every agent role.
+
+## 2. Contract Schema
+Every agent must have an associated contract containing:
+- `role`: The official designation (e.g., "researcher").
+- `capabilities`: `string[]` of authorized toolsets.
+- `input_schema`: JSON Schema defining required parameters.
+- `output_schema`: JSON Schema defining guaranteed return format.
+- `sla`: Response time goals and accuracy thresholds.
+- `resource_weight`: Numeric value representing cognitive cost.
+
+## 3. Workflow
+1. **Handshake**: Orchestrator requests contract from Agent.
+2. **Verification**: Orchestrator validates task against `input_schema`.
+3. **Execution**: Agent executes using only `capabilities`.
+4. **Validation**: Orchestrator validates result against `output_schema`.
+
+## 4. Implementation Path
+- Store contracts in `.contracts/` directory.
+- Reference contracts during `spawn_agent` calls.
diff --git a/skills/bug-tracker.md b/skills/bug-tracker.md
index 05963e4..bb8febf 100644
--- a/skills/bug-tracker.md
+++ b/skills/bug-tracker.md
@@ -2,6 +2,7 @@
name: bug-tracker
description: A systematic approach to tracking and managing bugs in the VFS.
tags: [dev, debugging, management, workflow]
+category: dev
---
# Bug Tracking Workflow
diff --git a/skills/index.json b/skills/index.json
index 4b168ca..200bc02 100644
--- a/skills/index.json
+++ b/skills/index.json
@@ -1 +1 @@
-{"navigating-the-terminal":{"name":"navigating-the-terminal","description":"How to explore the WebX11 terminal, find commands, check status, and navigate the filesystem","tags":["terminal","navigation","help","filesystem"],"category":"system","created":"2026-06-02T22:07:32.333Z","updated":"2026-06-02T22:07:32.333Z"},"memory-and-profile":{"name":"memory-and-profile","description":"How to use the user profile system, session memory, and pattern tracking for persistent context","tags":["memory","profile","session","persistence"],"category":"system","created":"2026-06-02T22:07:32.333Z","updated":"2026-06-02T22:07:32.333Z"},"web-search-and-fetch":{"name":"web-search-and-fetch","description":"How to search the web and fetch URL content using the WebX11 proxy API","tags":["search","fetch","web","proxy","api"],"category":"research","created":"2026-06-02T22:07:32.334Z","updated":"2026-06-02T22:07:32.334Z"},"module-management":{"name":"module-management","description":"How to view, edit, test, reload modules and manage startup configuration","tags":["modules","editing","code","self-improvement"],"category":"dev","created":"2026-06-02T22:07:32.334Z","updated":"2026-06-02T22:07:32.334Z"},"system-maintenance":{"name":"system-maintenance","description":"How to reset, troubleshoot, and maintain the WebX11 terminal","tags":["system","maintenance","reset","troubleshoot","config"],"category":"system","created":"2026-06-02T22:07:32.334Z","updated":"2026-06-02T22:07:32.334Z"},"backup-and-restore":{"name":"backup-and-restore","description":"How to backup, restore, and export WebX11 data","tags":["backup","restore","export","import","persistence"],"category":"system","created":"2026-06-02T22:07:32.334Z","updated":"2026-06-02T22:07:32.334Z"},"mindmap-workflow":{"name":"mindmap-workflow","description":"How to create, view, edit, and manage brainstorming mindmaps","tags":["mindmap","brainstorming","planning","organization"],"category":"productivity","created":"2026-06-02T22:07:32.334Z","updated":"2026-06-02T22:07:32.334Z"},"skills-system-guide":{"name":"skills-system-guide","description":"How to use the skills system: load, create, patch, list, and audit skills for persistent procedural memory","tags":["skills","system","meta"],"category":"system","created":"2026-06-02T22:07:32.334Z","updated":"2026-06-02T22:07:32.334Z"},"agent-orchestration":{"name":"agent-orchestration","description":"How to use the agent registry, leases, and orchestrator for multi-agent workflows","tags":["agents","orchestration","delegation","leases"],"category":"system","created":"2026-06-02T22:07:32.335Z","updated":"2026-06-02T22:07:32.335Z"},"debug-panel-and-logs":{"name":"debug-panel-and-logs","description":"How to use the debug panel, session logging, and terminal diagnostics","tags":["debug","logging","diagnostics","troubleshooting"],"category":"system","created":"2026-06-02T22:07:32.335Z","updated":"2026-06-02T22:07:32.335Z"},"webdav-operations":{"name":"webdav-operations","description":"How to use WebDAV cloud storage for backup, file sync, and remote file access","tags":["webdav","cloud","backup","sync","storage"],"category":"system","created":"2026-06-02T22:07:32.335Z","updated":"2026-06-02T22:07:32.335Z"},"security-and-safety":{"name":"security-and-safety","description":"How to use WebX11 security levels, command blocking, and safety features","tags":["security","safety","blocking","permissions"],"category":"system","created":"2026-06-02T22:07:32.335Z","updated":"2026-06-02T22:07:32.335Z"},"mindmap-user-guide":{"name":"mindmap-user-guide","description":"How to create, view, and manage brainstorming mindmaps using the mindmap terminal module","tags":["mindmap","brainstorming","organization","planning"],"category":"productivity","created":"2026-06-02T13:20:28.672Z","updated":"2026-06-02T13:20:28.672Z"},"bug-tracker":{"name":"bug-tracker","description":"Systematic workflow for tracking bugs using a JSON log file in the VFS.","tags":["dev","debugging","management","workflow"],"category":"dev","created":"2026-06-02T10:10:44.447Z","updated":"2026-06-02T10:10:44.447Z"},"task-manager":{"name":"task-manager","description":"A systematic workflow for tracking and managing tasks via a VFS JSON store.","tags":["productivity","tasks","vfs"],"category":"productivity","created":"2026-06-02T10:12:44.476Z","updated":"2026-06-02T10:12:44.476Z"},"agent-optimization-framework":{"name":"agent-optimization-framework","description":"","tags":["optimization","agentic-workflow","efficiency","tool-calls"],"category":"system","created":"2026-05-29T14:52:23.451Z","updated":"2026-05-29T14:52:23.451Z"},"macro-engine-debug":{"name":"macro-engine-debug","description":"","tags":["debug","a-repair","macro"],"category":"system","created":"2026-05-29T15:06:24.057Z","updated":"2026-05-29T15:06:24.057Z"},"macro-engine-onboarding":{"name":"macro-engine-onboarding","description":"","tags":["onboarding","context","macro"],"category":"system","created":"2026-05-29T15:06:24.064Z","updated":"2026-05-29T15:06:24.064Z"},"project-profile-manager":{"name":"project-profile-manager","description":"","tags":["context","memory","workspace"],"category":"system","created":"2026-05-29T15:08:44.897Z","updated":"2026-05-29T15:08:44.897Z"}} \ No newline at end of file
+{"a2a-contract-framework":{"name":"a2a-contract-framework","description":"Framework for formalizing Agent-to-Agent (A2A) contracts to ensure deterministic collaboration.","tags":["a2a","agent-orchestration","protocol","newos4"],"category":"system","created":"2026-06-03T22:22:07.000Z","updated":"2026-06-03T22:22:07.000Z"},"agent-optimization-framework":{"name":"agent-optimization-framework","description":"System for reducing tool-call latency and increasing agentic precision through programmatic workflows.","tags":["optimization","agentic-workflow","efficiency","tool-calls"],"category":"system","created":"2026-06-03T22:22:07.000Z","updated":"2026-06-03T22:22:07.000Z"},"agent-orchestration":{"name":"agent-orchestration","description":"How to use the agent registry, leases, and orchestrator for multi-agent workflows","tags":["agents","orchestration","delegation","leases"],"category":"system","created":"2026-06-03T22:22:07.000Z","updated":"2026-06-03T22:22:07.000Z"},"backup-and-restore":{"name":"backup-and-restore","description":"How to backup, restore, and export WebX11 data","tags":["backup","restore","export","import","persistence"],"category":"system","created":"2026-06-03T22:22:07.000Z","updated":"2026-06-03T22:22:07.000Z"},"bug-tracker":{"name":"bug-tracker","description":"A systematic approach to tracking and managing bugs in the VFS.","tags":["dev","debugging","management","workflow"],"category":"dev","created":"2026-06-03T22:22:07.000Z","updated":"2026-06-03T22:22:07.000Z"},"debug-panel-and-logs":{"name":"debug-panel-and-logs","description":"How to use the debug panel, session logging, and terminal diagnostics","tags":["debug","logging","diagnostics","troubleshooting"],"category":"system","created":"2026-06-03T22:22:07.000Z","updated":"2026-06-03T22:22:07.000Z"},"localize-external-assets":{"name":"localize-external-assets","description":"Downloads external JS/CSS assets to the VFS to bypass server-side security restrictions on external scripts.","tags":["security","assets","vfs","localization"],"category":"system","created":"2026-06-03T22:22:07.000Z","updated":"2026-06-03T22:22:07.000Z"},"macro-engine":{"name":"macro-engine","description":"Rapid session onboarding and module debugging β€” context recovery, status checks, source analysis, and live testing.","tags":["macro","onboarding","debug","context","recovery","development"],"category":"system","created":"2026-06-03T22:22:07.000Z","updated":"2026-06-03T22:22:07.000Z"},"memory":{"name":"memory","description":"Manage user profiles, session memory, and persistent memory map for cross-session context.","tags":["memory","profile","session","persistence","context","map"],"category":"system","created":"2026-06-03T22:22:07.000Z","updated":"2026-06-03T22:22:07.000Z"},"mindmap":{"name":"mindmap","description":"Create, manage, export, and persist brainstorming mindmaps using the mindmap terminal module.","tags":["mindmap","brainstorming","planning","organization","visualization"],"category":"productivity","created":"2026-06-03T22:22:07.000Z","updated":"2026-06-03T22:22:07.000Z"},"module-management":{"name":"module-management","description":"How to view, edit, test, reload modules and manage startup configuration","tags":["modules","editing","code","self-improvement"],"category":"dev","created":"2026-06-03T22:22:07.000Z","updated":"2026-06-03T22:22:07.000Z"},"navigating-the-terminal":{"name":"navigating-the-terminal","description":"How to explore the WebX11 terminal, find commands, check status, and navigate the filesystem","tags":["terminal","navigation","help","filesystem"],"category":"system","created":"2026-06-03T22:22:07.000Z","updated":"2026-06-03T22:22:07.000Z"},"neural-vfs-indexer":{"name":"neural-vfs-indexer","description":"Scans the VFS to create semantic mappings between concepts and file paths.","tags":["neural-vfs","semantic","indexing","newos4"],"category":"system","created":"2026-06-03T22:22:07.000Z","updated":"2026-06-03T22:22:07.000Z"},"project-profile-manager":{"name":"project-profile-manager","description":"Handles saving and loading of project-specific context bundles.","tags":["context","memory","workspace"],"category":"system","created":"2026-06-03T22:22:07.000Z","updated":"2026-06-03T22:22:07.000Z"},"security-and-safety":{"name":"security-and-safety","description":"How to use WebX11 security levels, command blocking, and safety features","tags":["security","safety","blocking","permissions"],"category":"system","created":"2026-06-03T22:22:07.000Z","updated":"2026-06-03T22:22:07.000Z"},"skills-system-guide":{"name":"skills-system-guide","description":"How to use the skills system: load, create, patch, list, and audit skills for persistent procedural memory","tags":["skills","system","meta"],"category":"system","created":"2026-06-03T22:22:07.000Z","updated":"2026-06-03T22:22:07.000Z"},"system-maintenance":{"name":"system-maintenance","description":"How to reset, troubleshoot, and maintain the WebX11 terminal","tags":["system","maintenance","reset","troubleshoot","config"],"category":"system","created":"2026-06-03T22:22:07.000Z","updated":"2026-06-03T22:22:07.000Z"},"task-manager":{"name":"task-manager","description":"A systematic approach to managing tasks using a JSON-based tracking system in the VFS.","tags":["productivity","management","organization"],"category":"productivity","created":"2026-06-03T22:22:07.000Z","updated":"2026-06-03T22:22:07.000Z"},"web-search-and-fetch":{"name":"web-search-and-fetch","description":"How to search the web and fetch URL content using the WebX11 proxy API","tags":["search","fetch","web","proxy","api"],"category":"research","created":"2026-06-03T22:22:07.000Z","updated":"2026-06-03T22:22:07.000Z"},"webdav":{"name":"webdav","description":"Configure, sync, backup, and restore VFS via WebDAV cloud storage.","tags":["webdav","cloud","backup","sync","storage","vfs"],"category":"system","created":"2026-06-03T22:22:07.000Z","updated":"2026-06-03T22:22:07.000Z"},"webx11-dev-cycle":{"name":"webx11-dev-cycle","description":"Professional workflow for analyzing, prototyping, and implementing new features in WebX11.","tags":["development","workflow","webx11"],"category":"dev","created":"2026-06-03T22:22:07.000Z","updated":"2026-06-03T22:22:07.000Z"}}
diff --git a/skills/localize-external-assets.md b/skills/localize-external-assets.md
new file mode 100644
index 0000000..b7a1c9b
--- /dev/null
+++ b/skills/localize-external-assets.md
@@ -0,0 +1,18 @@
+---
+name: localize-external-assets
+description: Downloads external JS/CSS assets to the VFS to bypass server-side security restrictions on external scripts.
+tags: [security, assets, vfs, localization]
+category: system
+---
+
+### Logic
+1. Identify external URLs in the target HTML/CSS.
+2. Use the `download <url>` command to save these files into a local `/assets/` directory.
+3. Update the HTML file to reference local paths (e.g., `src="https://cdn..."` $\rightarrow$ `src="/assets/..."`).
+
+### Implementation Steps
+1. **Scan**: Read the file and extract all `src` and `href` attributes pointing to external domains.
+2. **Prepare**: Create an `/assets/` directory if it doesn't exist.
+3. **Fetch**: Execute `download <url>` for every identified external dependency.
+4. **Patch**: Use `write_file` to replace the remote URLs with the local VFS paths.
+5. **Verify**: Confirm the file is successfully updated and assets are present in the VFS.
diff --git a/skills/macro-engine-debug.md b/skills/macro-engine-debug.md
deleted file mode 100644
index e8cc662..0000000
--- a/skills/macro-engine-debug.md
+++ /dev/null
@@ -1,20 +0,0 @@
----
-name: macro-engine-debug
-description: A compound operation sequence to audit, view, and test a module for stability and correctness.
-tags: [debug, a-repair, macro, development]
-category: dev
----
-
-# Macro Engine Debug
-
-## 🎯 Objective
-Rapidly diagnose issues within a loaded module by combining status checks, source analysis, and live testing.
-
-## πŸ› οΈ Execution Steps
-1. **Status Check:** Call `get_module_status` to identify if the module is currently loaded, modified, or has a remote URL mismatch.
-2. **Source Analysis:** Call `view_module(name)` to examine the current implementation logic.
-3. **Live Testing:** Use `test_module(name)` to load the edited version from `/_mods/` and verify the fix.
-4. **Synthesis:** Compare the test results with the original bug report to confirm the resolution.
-
-## πŸ”„ Workflow
-`get_module_status` βž” `view_module` βž” `test_module` βž” `report`
diff --git a/skills/macro-engine-onboarding.md b/skills/macro-engine-onboarding.md
deleted file mode 100644
index 669d665..0000000
--- a/skills/macro-engine-onboarding.md
+++ /dev/null
@@ -1,20 +0,0 @@
----
-name: macro-engine-onboarding
-description: A rapid context-recovery sequence to align the AI with the current session state and active projects.
-tags: [onboarding, context, recovery, macro]
-category: system
----
-
-# Macro Engine Onboarding
-
-## 🎯 Objective
-Efficiently recover state and context at the start of a session to avoid redundant queries and minimize hallucinations.
-
-## πŸ› οΈ Execution Steps
-1. **Session Review:** Call `session_recent(3)` to identify the last active tasks and their outcomes.
-2. **VFS Snapshot:** Call `list_files('')` to examine the root directory for new project files or configuration changes.
-3. **Procedure Retrieval:** Call `load_skills('current-task')` to see if any stored procedures are applicable to the immediate goal.
-4. **User Preferences:** Call `user_list` to check for project-specific flags or persistent preferences (e.g., preferred models, project paths).
-
-## πŸ”„ Workflow
-`session_recent` βž” `list_files` βž” `load_skills` βž” `user_list`
diff --git a/skills/macro-engine.md b/skills/macro-engine.md
new file mode 100644
index 0000000..ca5ef5e
--- /dev/null
+++ b/skills/macro-engine.md
@@ -0,0 +1,28 @@
+---
+name: macro-engine
+description: Rapid session onboarding and module debugging β€” context recovery, status checks, source analysis, and live testing.
+tags: [macro, onboarding, debug, context, recovery, development]
+category: system
+---
+
+TODO: Category should be system+dev β€” primary use is debugging modules (dev) for context recovery (system). Using 'system' as primary.
+
+## Session Onboarding (context recovery)
+
+Efficiently recover state at session start to avoid redundant queries.
+
+1. **Session Review** β€” `session_recent(3)` to identify last active tasks and outcomes
+2. **VFS Snapshot** β€” `list_files('')` to examine root directory for new files/config changes
+3. **Procedure Retrieval** β€” `load_skills('current-task')` for applicable stored procedures
+4. **User Preferences** β€” `user_list` for project-specific flags/persistent preferences
+
+**Workflow:** `session_recent` β†’ `list_files` β†’ `load_skills` β†’ `user_list`
+
+## Module Debugging (rapid diagnosis)
+
+1. **Status Check** β€” `get_module_status` to see if module is loaded, modified, or has a remote URL mismatch
+2. **Source Analysis** β€” `view_module(name)` to examine current implementation logic
+3. **Live Testing** β€” `test_module(name)` to load edited version from `/_mods/` and verify the fix
+4. **Synthesis** β€” compare test results with the original bug report to confirm resolution
+
+**Workflow:** `get_module_status` β†’ `view_module` β†’ `test_module` β†’ `report` \ No newline at end of file
diff --git a/skills/memory-and-profile.md b/skills/memory-and-profile.md
deleted file mode 100644
index 6605893..0000000
--- a/skills/memory-and-profile.md
+++ /dev/null
@@ -1,30 +0,0 @@
----
-name: memory-and-profile
-description: How to use the user profile system, session memory, and pattern tracking for persistent context
-tags: [memory, profile, session, persistence]
-category: system
----
-## Steps
-1. **User Profile (persists across sessions):**
- - user_get(key) β€” read any profile field (e.g. "preferredModel", "fontSize")
- - user_set(key, value) β€” write to profile, auto-persists to localStorage
- - user_list β€” show all stored profile keys
- - user_forget(key) β€” delete a profile key
- - Dot notation supported: user_set knownFacts.name "Alex"
-
-2. **Session Memory (VFS-based daily logs):**
- - session_save(summary) β€” save a summary of what was accomplished
- - session_load(date) β€” read a specific day's log (format: YYYY-MM-DD)
- - session_recent(count) β€” show last N session summaries
- - session_stats β€” aggregate totals across all sessions
- - Recent sessions auto-load into context on first message
-
-3. **Conversation Patterns:**
- - Pattern tracking runs automatically β€” frequent topics surface as hints
- - my-set, my-get, my-list store additional personal data
- - AI conversation context persists within a session (use ai-clear to reset)
-
-4. **When to use:**
- - At start: call session_recent(3) to see what was worked on before
- - After identifying user preferences: call user_set to store them
- - After complex tasks: call session_save with a brief summary \ No newline at end of file
diff --git a/skills/memory-map.md b/skills/memory-map.md
deleted file mode 100644
index b8c0f83..0000000
--- a/skills/memory-map.md
+++ /dev/null
@@ -1,51 +0,0 @@
----
-name: memory-map
-description: Maintain and query the persistent memory map at /memory/map.json for Agando/DarkMoto Systems.
-category: system
-tags: memory, persistence, context, map, agando
----
-
-## Purpose
-Keep a living index of projects, infrastructure, preferences, active issues, and session history so the AI never asks Agando to repeat himself.
-
-## File Location
-- `/memory/map.json` β€” primary memory map
-- `/memory/index.json` β€” session index (auto-generated)
-
-## Workflow
-
-### 1. Read Before Acting
-At the start of any session or when context is unclear:
-```bash
-read_file("memory/map.json")
-```
-
-### 2. Update After Significant Work
-After any task that changes status, fixes an issue, or adds knowledge:
-```bash
-# Read current map
-read_file("memory/map.json")
-
-# Modify relevant section(s)
-# Write back
-write_file("memory/map.json", <updated_json>)
-```
-
-### 3. Add Session Link
-Append to `recent_sessions` (keep last 10):
-```json
-{"date": "YYYY-MM-DD", "file": "memory/YYYY-MM-DD.json", "summary": "..."}
-```
-
-## Map Structure
-- `projects` β€” WebX11, clients, personal builds, stores
-- `infrastructure` β€” security stack, backup systems, constraints
-- `preferences` β€” communication style, UI needs (#00ff88, 48px touch targets)
-- `active_issues` β€” open tasks, blockers, manual steps required
-- `recent_sessions` β€” quick links to session logs
-
-## Rules
-- NEVER ask Agando for info already in the map.
-- If info is stale or wrong, update it immediately.
-- Use `session_save()` after complex tasks to populate index.json.
-- Keep `active_issues` accurate β€” remove resolved items. \ No newline at end of file
diff --git a/skills/memory.md b/skills/memory.md
new file mode 100644
index 0000000..d3b46fe
--- /dev/null
+++ b/skills/memory.md
@@ -0,0 +1,66 @@
+---
+name: memory
+description: Manage user profiles, session memory, and persistent memory map for cross-session context.
+tags: [memory, profile, session, persistence, context, map]
+category: system
+---
+
+## User Profile (localStorage β€” user_get/user_set)
+
+| Command | Purpose |
+|---------|---------|
+| `user_get(key)` | Read profile field (e.g. "preferredModel") |
+| `user_set(key, value)` | Write to profile, auto-persists |
+| `user_list` | Show all stored profile keys |
+| `user_forget(key)` | Delete a profile key |
+
+Dot notation supported: `user_set knownFacts.name "Alex"`
+
+## Session Memory (VFS-based daily logs)
+
+| Command | Purpose |
+|---------|---------|
+| `session_save(summary)` | Save session summary |
+| `session_load(date)` | Read day's log (YYYY-MM-DD) |
+| `session_recent(count)` | Last N session summaries |
+| `session_stats` | Aggregate totals |
+
+Recent sessions auto-load into context on first message.
+
+## Persistent Memory Map (/memory/map.json)
+
+An index of projects, preferences, issues, and session history so the AI never asks to repeat itself.
+
+**Location:** `/memory/map.json` β€” primary map; `/memory/index.json` β€” auto-generated session index
+
+**Read Before Acting:**
+```
+read_file("memory/map.json")
+```
+
+**Update After Significant Work:**
+- Read current map, modify relevant section, write back
+- Append to `recent_sessions` (keep last 10)
+
+**Map Structure:**
+- `projects` β€” WebX11, clients, personal builds
+- `infrastructure` β€” security stack, backups, constraints
+- `preferences` β€” communication style, UI needs
+- `active_issues` β€” open tasks, blockers, manual steps
+- `recent_sessions` β€” quick links to session logs
+
+**Rules:**
+- NEVER ask for info already in the map
+- If info is stale, update immediately
+- Use `session_save()` after complex tasks
+- Keep `active_issues` accurate β€” remove resolved items
+
+## Conversation Patterns
+- Pattern tracking runs automatically β€” frequent topics surface as hints
+- `my-set`, `my-get`, `my-list` store additional personal data
+- AI conversation context persists within a session (use `ai-clear` to reset)
+
+## When to Use
+- Session start: call `session_recent(3)`, then `read_file("memory/map.json")`
+- After identifying user preferences: `user_set` to store them
+- After complex tasks: `session_save` with a brief summary, update map \ No newline at end of file
diff --git a/skills/mindmap-master-guide.md b/skills/mindmap-master-guide.md
deleted file mode 100644
index 83cebd2..0000000
--- a/skills/mindmap-master-guide.md
+++ /dev/null
@@ -1,40 +0,0 @@
----
-name: mindmap-master-guide
-description: Comprehensive guide to creating, managing, and exporting brainstorming mindmaps using the mindmap terminal module.
-tags: [mindmap, brainstorming, planning, organization, visualization]
-category: productivity
----
-## Core Workflow
-
-1. **Initialization**
- - `mindmap new "<topic>" -t tag1,tag2` β€” Creates a root node.
- - Tags are optional (e.g., planning, research, dev).
- - The root node is auto-assigned a color from the 7-color palette.
-
-2. **Expansion (Adding Nodes)**
- - `mindmap add <parent-id> "<idea>" -t tag` β€” Adds a child node to a specific parent.
- - To find the `parent-id`, use `mindmap show`. IDs are 4-character random strings (e.g., `a3f8`).
-
-3. **Visualization**
- - `mindmap show` β€” Displays the full tree using Unicode box-drawing.
- - `mindmap show <id>` β€” Displays a subtree starting from the specified node.
-
-4. **Refinement (Editing)**
- - `mindmap rename <id> "<new text>"` β€” Changes the node text.
- - `mindmap color <id> <color>` β€” Sets node color (`red`, `green`, `yellow`, `blue`, `cyan`, `magenta`, `white`).
- - `mindmap tag <id> <tag>` β€” Assigns or updates a tag for the node.
-
-5. **Persistence & Storage**
- - `mindmap save <name>` β€” Saves the current map to localStorage.
- - `mindmap load <name>` β€” Restores a saved map.
- - `mindmap list` β€” Lists all saved mindmaps.
- - `mindmap delete <name>` β€” Removes a saved map from storage.
-
-6. **Exporting**
- - `mindmap export [id]` β€” Generates a Markdown bullet list of the map (or specific subtree), automatically copying the result to the clipboard.
-
-## Use Cases
-- **Brainstorming:** Map out feature sets, project architectures, or conceptual ideas.
-- **Planning:** Decompose complex tasks into manageable sub-tasks.
-- **Organization:** Structure research findings or user requirements.
-- **Trigger Phrases:** Use when the user mentions "brainstorm", "diagram", "organize thoughts", "plan", or "map out".
diff --git a/skills/mindmap-user-guide.md b/skills/mindmap-user-guide.md
deleted file mode 100644
index 7bee410..0000000
--- a/skills/mindmap-user-guide.md
+++ /dev/null
@@ -1,40 +0,0 @@
----
-name: mindmap-user-guide
-description: How to create, view, and manage brainstorming mindmaps using the mindmap terminal module
-tags: [mindmap, brainstorming, organization, planning]
-category: productivity
----
-## Steps
-
-1. **Create a new mindmap:**
- - `mindmap new "<topic>" -t tag1,tag2` β€” creates a root node
- - Tags are optional (e.g. planning, research, dev)
- - Root gets auto-assigned a color
-
-2. **Add child nodes:**
- - `mindmap add <parent-id> "<idea>" -t tag` β€” add a child
- - Get the parent-id from `mindmap show`
- - IDs are 4-char random strings (e.g. a3f8, x7k2)
-
-3. **View the mindmap:**
- - `mindmap show` β€” full tree with Unicode box-drawing
- - `mindmap show <id>` β€” subtree starting at that node
-
-4. **Edit nodes:**
- - `mindmap rename <id> "<new text>"` β€” change text
- - `mindmap color <id> <color>` β€” set color (red/green/yellow/blue/cyan/magenta/white)
- - `mindmap tag <id> <tag>` β€” add a tag
-
-5. **Persistence:**
- - `mindmap save <name>` β€” save to localStorage
- - `mindmap load <name>` β€” restore
- - `mindmap list` β€” show saved mindmaps
- - `mindmap delete <name>` β€” remove saved
-
-6. **Export:**
- - `mindmap export [id]` β€” Markdown bullet list output
-
-## When to use
-- User wants to brainstorm, organize ideas, plan features
-- User says "map out", "diagram", "brainstorm", "organize thoughts"
-- Visualizing project structure or task decomposition \ No newline at end of file
diff --git a/skills/mindmap-workflow.md b/skills/mindmap-workflow.md
deleted file mode 100644
index f05c237..0000000
--- a/skills/mindmap-workflow.md
+++ /dev/null
@@ -1,39 +0,0 @@
----
-name: mindmap-workflow
-description: How to create, view, edit, and manage brainstorming mindmaps
-tags: [mindmap, brainstorming, planning, organization]
-category: productivity
----
-## Steps
-1. **Create a new mindmap:**
- - mindmap new "<topic>" -t tag1,tag2 β€” creates a root node
- - Tags are optional (e.g. planning, research, dev)
- - Root gets auto-assigned a color from 7-color palette
-
-2. **Add child nodes:**
- - mindmap add <parent-id> "<idea>" -t tag β€” add a child
- - Get the parent-id from mindmap show
- - IDs are 4-char random strings (e.g. a3f8, x7k2)
-
-3. **View:**
- - mindmap show β€” full tree with Unicode box-drawing
- - mindmap show <id> β€” subtree starting at that node
-
-4. **Edit nodes:**
- - mindmap rename <id> "<new text>" β€” change text
- - mindmap color <id> <color> β€” set color (red/green/yellow/blue/cyan/magenta/white)
- - mindmap tag <id> <tag> β€” add a tag
-
-5. **Persistence:**
- - mindmap save <name> β€” save to localStorage
- - mindmap load <name> β€” restore
- - mindmap list β€” show saved mindmaps
- - mindmap delete <name> β€” remove saved
-
-6. **Export:**
- - mindmap export [id] β€” Markdown bullet list output, auto-copies to clipboard
-
-7. **When to use:**
- - Map out project structure, brainstorm features, organize ideas
- - Break down complex tasks into subtrees
- - User says "brainstorm", "diagram", "organize thoughts", "plan" \ No newline at end of file
diff --git a/skills/mindmap.md b/skills/mindmap.md
new file mode 100644
index 0000000..e1cbb7b
--- /dev/null
+++ b/skills/mindmap.md
@@ -0,0 +1,50 @@
+---
+name: mindmap
+description: Create, manage, visualize, and persist brainstorming mindmaps using the mindmap terminal module.
+tags: [mindmap, brainstorming, planning, organization, visualization]
+category: productivity
+---
+
+## Core Workflow
+
+1. **Create a new mindmap**
+ - `mindmap new "<topic>" -t tag1,tag2` β€” creates a root node
+ - Tags are optional (e.g. planning, research, dev)
+ - Root gets auto-assigned a color from 7-color palette
+
+2. **Add child nodes**
+ - `mindmap add <parent-id> "<idea>" -t tag` β€” add a child
+ - Get parent-id from `mindmap show` β€” IDs are 4-char random strings
+
+3. **View**
+ - `mindmap show` β€” full tree with Unicode box-drawing
+ - `mindmap show <id>` β€” subtree starting at that node
+ - `mindmap svg [name]` β€” render as inline SVG with colored rects + bezier curves. Optional name saves to /mindmaps/<name>.svg for `preview`
+
+4. **Visualize with Mermaid**
+ - Export your mindmap data and render in `webx11_mindmap.html` for a full Mermaid flowchart
+ - The mermaid library is at `mermaid.min.js` in the newOS4 directory
+
+5. **Edit nodes**
+ - `mindmap rename <id> "<new text>"` β€” change text
+ - `mindmap color <id> <color>` β€” set color (red/green/yellow/blue/cyan/magenta/white)
+ - `mindmap tag <id> <tag>` β€” assign/update tag
+
+6. **Persistence**
+ - `mindmap save <name>` β€” save to VFS (stores in /mindmaps/ as JSON)
+ - `mindmap load <name>` β€” restore
+ - `mindmap list` β€” show saved mindmaps
+ - `mindmap delete <name>` β€” remove saved mindmap file
+
+7. **Export**
+ - `mindmap export [id]` β€” Markdown bullet list output, auto-copies to clipboard
+ - `mindmap svg <name>` β€” saves SVG to /mindmaps/<name>.svg, viewable with `preview`
+
+8. **Neural VFS integration**
+ - After running `nvfs-index`, mindmap skill files are indexed as `concept://mindmap`
+ - Saved mindmaps in /mindmaps/ are discoverable via concept search
+
+## When to Use
+- Brainstorming feature sets, project architecture, or ideas
+- Decomposing complex tasks into manageable subtrees
+- User says "brainstorm", "diagram", "organize thoughts", "plan", "map out" \ No newline at end of file
diff --git a/skills/neural-vfs-indexer.md b/skills/neural-vfs-indexer.md
new file mode 100644
index 0000000..0030db7
--- /dev/null
+++ b/skills/neural-vfs-indexer.md
@@ -0,0 +1,21 @@
+---
+name: neural-vfs-indexer
+description: Scans the VFS to create semantic mappings between concepts and file paths.
+tags: [neural-vfs, semantic, indexing, newos4]
+category: system
+---
+
+# Neural VFS Indexer
+
+## Purpose
+To implement the "Neural VFS" pillar of newOS4 by creating a semantic layer over the hierarchical filesystem.
+
+## Workflow
+1. **Discovery**: List all files in the VFS using `list_files`.
+2. **Analysis**: Read the contents of each file.
+3. **Keyword Extraction**: Identify primary themes, technical terms, and "concepts" within the file.
+4. **Indexing**: Create a mapping file in `.semantic_index/` named after the concept (e.g., `.semantic_index/cognitive-kernel.map`).
+5. **Mapping**: The mapping file should contain the path to the source file and a brief semantic summary.
+
+## Usage
+Run this skill when new documentation is added or when the architectural structure changes.
diff --git a/skills/project-profile-manager.md b/skills/project-profile-manager.md
index 03eead8..7b8c6cf 100644
--- a/skills/project-profile-manager.md
+++ b/skills/project-profile-manager.md
@@ -2,6 +2,7 @@
name: project-profile-manager
description: Handles saving and loading of project-specific context bundles.
tags: [context, memory, workspace]
+category: system
---
# Project Profile Manager
diff --git a/skills/task-manager.md b/skills/task-manager.md
index 74c3da1..f4a0542 100644
--- a/skills/task-manager.md
+++ b/skills/task-manager.md
@@ -2,6 +2,7 @@
name: task-manager
description: A systematic approach to managing tasks using a JSON-based tracking system in the VFS.
tags: productivity, management, organization
+category: productivity
---
# Task Management Workflow
diff --git a/skills/webdav-operations.md b/skills/webdav-operations.md
deleted file mode 100644
index 098449c..0000000
--- a/skills/webdav-operations.md
+++ /dev/null
@@ -1,33 +0,0 @@
----
-name: webdav-operations
-description: How to use WebDAV cloud storage for backup, file sync, and remote file access
-tags: [webdav, cloud, backup, sync, storage]
-category: system
----
-## Steps
-1. **Configuration:**
- - webdav-config β€” configure WebDAV endpoint URL and credentials
- - Connection auto-tested on config; webdav-status shows connection health
- - Uses per-user token stored in .token file on the server side
-
-2. **File operations:**
- - webdav-ls [path] β€” list remote directory contents
- - webdav-push <local-path> <remote-path> β€” upload file to WebDAV
- - webdav-pull <remote-path> [local-path] β€” download file from WebDAV
- - webdav-explorer β€” GUI file browser for WebDAV
- - webdav-browser β€” CLI file browser for WebDAV
-
-3. **Backup & Restore:**
- - webdav-backup β€” push full VFS snapshot to WebDAV (creates /backups/newos4-<date>.json)
- - webdav-backup-list β€” list all remote backup snapshots
- - webdav-restore <filename> β€” restore VFS from a remote backup snapshot
-
-4. **Status & Diagnostics:**
- - webdav-status β€” connection status, last sync, space information
- - If uploads fail: check webdav-config, ensure .token file is valid
- - WebDAV runs on the same server (nginx with WebDAV module), no external dependency
-
-5. **When to use:**
- - Before factory-reset: webdav-backup to store VFS remotely
- - Cross-browser: webdav-push/pull to move files between instances
- - User says "cloud backup" or "remote save" β†’ webdav-backup \ No newline at end of file
diff --git a/skills/webdav-sync.md b/skills/webdav-sync.md
deleted file mode 100644
index ead86dd..0000000
--- a/skills/webdav-sync.md
+++ /dev/null
@@ -1,40 +0,0 @@
----
-name: webdav-sync
-description: Sync, backup, and restore VFS via WebDAV in WebX11. CRITICAL: Only use verified commands.
-category: system
-tags: [webdav, sync, backup, cloud, vfs]
----
-
-# WebDAV Sync Workflow
-
-## ⚠️ CRITICAL RULE: VERIFY BEFORE EXECUTING
-**ALWAYS run `help <command>` first.**
-**If `help <command>` returns nothing, the command does NOT exist.**
-**Never invent commands β€” terminal crashes.**
-
-## 1. Install & Configure
-- `webdav-config` β€” configure WebDAV connection
-- `webdav-status` β€” verify connection
-
-## 2. Verified Commands ONLY
-| Command | Verify With | Purpose |
-|---------|-------------|---------|
-| `webdav-ls` | `help webdav-ls` | List files on server |
-| `webdav-backup` | `help webdav-backup` | Backup VFS to WebDAV |
-| `webdav-backup-list` | `help webdav-backup-list` | List backups |
-| `webdav-restore` | `help webdav-restore` | Restore from backup |
-| `webdav-push` | `help webdav-push` | Push VFS to server |
-| `webdav-pull` | `help webdav-pull` | Pull from server |
-
-## 3. What Does NOT Exist
-There is **NO CLI delete** for WebDAV files. These will CRASH:
-- `webdav-browser` ❌
-- `webdav-explorer` ❌
-- `webdav-delete` ❌
-- `webdav-rm` ❌
-
-## 4. Deleting Files
-Since `curl` is also blocked, there is **no automated way** to delete WebDAV backups from the terminal. Use the WebDAV web interface outside the terminal.
-
-## 5. For VFS Files (local filesystem)
-Use `rm <file>` β€” this is a real command. Verify: `help rm` \ No newline at end of file
diff --git a/skills/webdav.md b/skills/webdav.md
new file mode 100644
index 0000000..c8b2dfc
--- /dev/null
+++ b/skills/webdav.md
@@ -0,0 +1,44 @@
+---
+name: webdav
+description: Configure, sync, backup, and restore VFS via WebDAV cloud storage.
+tags: [webdav, cloud, backup, sync, storage, vfs]
+category: system
+---
+
+## CRITICAL: VERIFY BEFORE EXECUTING
+**ALWAYS run `help <command>` first.** If `help <command>` returns nothing, the command does NOT exist. Never invent commands β€” terminal crashes.
+
+## 1. Configure & Status
+- `webdav-config` β€” configure WebDAV endpoint URL and credentials
+- `webdav-status` β€” verify connection health, last sync, space info
+
+## 2. File Operations
+
+| Command | Purpose |
+|---------|---------|
+| `webdav-ls [path]` | List remote directory contents |
+| `webdav-push <local> <remote>` | Upload file to WebDAV |
+| `webdav-pull <remote> [local]` | Download file from WebDAV |
+
+## 3. Backup & Restore
+- `webdav-backup` β€” push full VFS snapshot to WebDAV (`/backups/newos4-<date>.json`)
+- `webdav-backup-list` β€” list all remote backup snapshots
+- `webdav-restore <filename>` β€” restore VFS from remote backup
+
+## 4. What Does NOT Exist
+These will crash the terminal:
+- `webdav-browser` ❌
+- `webdav-explorer` ❌
+- `webdav-delete` ❌
+- `webdav-rm` ❌
+
+Since `curl` is also blocked, no automated way to delete WebDAV backups from the terminal β€” use the WebDAV web interface outside.
+
+## 5. When to Use
+- Before factory-reset: `webdav-backup` to store VFS remotely
+- Cross-browser: `webdav-push`/`webdav-pull` to move files
+- User says "cloud backup" or "remote save"
+
+## 6. Connection Details
+- Uses per-user token stored in `.token` file on the server
+- WebDAV runs on same server (nginx with WebDAV module) β€” no external dependency \ No newline at end of file
diff --git a/skills/webx11-dev-cycle.md b/skills/webx11-dev-cycle.md
index 66fefde..934b65b 100644
--- a/skills/webx11-dev-cycle.md
+++ b/skills/webx11-dev-cycle.md
@@ -9,4 +9,5 @@ steps:
5. Document: Save the final implementation and a a changelog in /webx11_dev/logs/.
6. Persist: Save the session using session_save.
tags: development,workflow,webx11
+category: dev
---