aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAgando <roduccomm@gmail.com>2026-10-23 19:52:28 +0200
committerAgando <roduccomm@gmail.com>2026-10-23 19:52:28 +0200
commitec6ca5490edc48afc57187c28e3532336e7619bc (patch)
tree95f9e956e79d801f0e00bdac8842f7bde868253e
parent4774b19f5e73df4edc2dd062433dd12c70dac0ab (diff)
docs(newos4): seed a chatting-with-hermes skill (v4.6.74)
A command that exists but is undocumented might as well not exist: the agent had no way to learn that `hermes` exists, that `chat` is taken, that replies are asynchronous, or that the cursor is milliseconds. Skill covers the commands, the chat_hermes tool, the failure table (401/413/429/503/507), the rules that keep it useful, and how to verify a send. Seeded from skill-pack-core._buildSkills() so every fresh session gets it; mirrored to skills/chatting-with-hermes.{md,json} + index.json (19 entries).
-rw-r--r--main.html6
-rw-r--r--modules/core/module-loader.js2
-rw-r--r--modules/ext/skill-pack-core.js72
-rw-r--r--skills/chatting-with-hermes.json17
-rw-r--r--skills/chatting-with-hermes.md76
-rw-r--r--skills/index.json20
6 files changed, 186 insertions, 7 deletions
diff --git a/main.html b/main.html
index 7337fae..e862108 100644
--- a/main.html
+++ b/main.html
@@ -1349,13 +1349,13 @@
</script>
<!-- v4.5.63: A2A scratchpad fixes + agent-register arg fix -->
-<script src="modules/core/core-bundle.js?v=v4.6.73"></script>
+<script src="modules/core/core-bundle.js?v=v4.6.74"></script>
<!-- Async dependency-ordered module loader now only initializes terminal and loads optional ext modules -->
-<script src="modules/core/module-loader.js?v=v4.6.73"></script>
+<script src="modules/core/module-loader.js?v=v4.6.74"></script>
<!-- Critical ext bundle loads AFTER webx11 exists so registerModule calls work -->
-<script src="modules/ext/critical-ext-bundle.js?v=v4.6.73"></script>
+<script src="modules/ext/critical-ext-bundle.js?v=v4.6.74"></script>
<script>
// ═══ ONE TRUE VERSION SOURCE ═══
diff --git a/modules/core/module-loader.js b/modules/core/module-loader.js
index 291dbd4..e6bb6af 100644
--- a/modules/core/module-loader.js
+++ b/modules/core/module-loader.js
@@ -4,7 +4,7 @@
// Core module bundle loaded synchronously in main.html.
// This loader only handles version cache-busting, splash, terminal init, and optional ext modules.
- const LATEST_VER = 'v4.6.73';
+ const LATEST_VER = 'v4.6.74';
const CACHE = '?v=' + LATEST_VER;
const stored = localStorage.getItem('webx11_cache_ver');
if (stored !== LATEST_VER) {
diff --git a/modules/ext/skill-pack-core.js b/modules/ext/skill-pack-core.js
index c3c643b..8cd8632 100644
--- a/modules/ext/skill-pack-core.js
+++ b/modules/ext/skill-pack-core.js
@@ -55,6 +55,78 @@ class SkillPackCoreModule {
});
return [
+ // v4.6.74: the agent could not find out how to reach Hermes. Commands that
+ // exist but are undocumented may as well not exist.
+ sk('chatting-with-hermes', 'How to message Hermes (the platform operator) from inside newOS4, and how to read the answer - commands, the chat_hermes tool, cursor and error semantics', ["hermes", "chat", "operator", "escalation", "feedback", "agent"], 'system',
+`# Talking to Hermes
+
+Hermes is the operator agent that runs the host. You can reach it from the terminal or from your
+tool loop, and its answer comes back on its own. Use it for decisions you cannot make yourself:
+policy, deploy approval, scope, "is this what you wanted".
+
+Contract: \`/_docs/chat-contract.md\`.
+
+## Say it
+
+ hermes <message> # send (legacy alias: feedback)
+ hermes-poll # check for new replies now (alias: feedback-inbox)
+ hermes-reset # rotate the token, start a fresh thread
+
+**Not \`chat\`.** \`ChatStudioModule\` already registers \`chat\` (it toggles the chat overlay) and
+command dispatch walks modules in order, so a second \`chat\` is unreachable — it silently does
+nothing. If you type \`chat hello\` and nothing happens, that is why.
+
+Inside the tool loop:
+
+ chat_hermes { "action": "send", "text": "..." } -> { "sent": true, "id": ..., "epoch": ... }
+ chat_hermes { "action": "read" } -> { "awaiting": bool, "messages": [...] }
+
+Replies are **asynchronous**. Send, continue working, read on a later step. Do not block on an
+answer that is minutes away.
+
+## Read it
+
+Replies print themselves: a 30 second poller shows \`🤖 <text>\` in the terminal with no command
+from you. The cursor is persisted, so a reload does not replay history.
+
+\`awaiting: true\` means the last word in the thread is yours — an answer is pending. \`false\` means
+Hermes answered.
+
+## Failures and what they mean
+
+| Status | Code | Meaning | Do |
+|---|---|---|---|
+| 401 | \`bad_token\` | token missing or malformed in localStorage | \`hermes-reset\` |
+| 413 | \`too_long\` | over 4000 **codepoints** (emoji count as one) | shorten; nothing was sent |
+| 413 | \`too_large\` | body over 32 KB | shorten |
+| 429 | \`rate_limited\` | 20/thread or 40/IP per 10 min | wait \`retry_after_ms\` |
+| 503 | — | nginx is throttling the host, HTML body | retry with backoff; **not** your mistake |
+| 507 | \`thread_limit\` | too many threads on disk | tell the operator |
+
+Only \`429\` and \`503\` are worth retrying. Everything else is permanent for that payload.
+
+## The cursor is milliseconds
+
+\`epoch\` and \`cursor\` are epoch **milliseconds**. Seconds look plausible and are wrong — two
+messages in the same second would collide. Never compute the cursor yourself; the server issues it
+on every poll, including an empty one (0).
+
+## Rules that keep this useful
+
+- One thought per message. A wall of text gets a shallow answer.
+- Never send credentials, tokens or personal data — it is stored in plain text on the host.
+- Do not poll in a loop. 30 s is already automatic; \`hermes-poll\` is for "I need it now".
+- Threads are per browser token. \`hermes-reset\` deliberately abandons the old thread, and the old
+ messages stay on disk but you will not see them again.
+- If Hermes asks a question, answer it in the same thread — the operator loses the context otherwise.
+
+## Verify your own result
+
+ hermes hello -> "📨 Sending…" then "✅ sent id=… epoch=…"
+ hermes-poll -> "⏳ waiting for Hermes" while the answer is pending
+
+A send that prints only \`📨 Sending…\` and never a ✅ or ❌ means the request never completed —
+report that, it is a bug, not a slow answer.`),
// v4.6.65: merged from `command-composition-rules` and
// `terminal-commands-silently-failing` (packet §9) — they described one bug family
// from two angles, and both are now describing behaviour that is refused outright.
diff --git a/skills/chatting-with-hermes.json b/skills/chatting-with-hermes.json
new file mode 100644
index 0000000..d16578f
--- /dev/null
+++ b/skills/chatting-with-hermes.json
@@ -0,0 +1,17 @@
+{
+ "name": "chatting-with-hermes",
+ "description": "How to message Hermes (the platform operator) from inside newOS4, and how to read the answer - commands, the chat_hermes tool, cursor and error semantics",
+ "tags": [
+ "hermes",
+ "chat",
+ "operator",
+ "escalation",
+ "feedback",
+ "agent"
+ ],
+ "category": "system",
+ "content": "---\nname: chatting-with-hermes\ndescription: How to message Hermes (the platform operator) from inside newOS4, and how to read the answer - commands, the chat_hermes tool, cursor and error semantics\ntags: [hermes, chat, operator, escalation, feedback, agent]\ncategory: system\n---\n\n# Talking to Hermes\n\nHermes is the operator agent that runs the host. You can reach it from the terminal or from your\ntool loop, and its answer comes back on its own. Use it for decisions you cannot make yourself:\npolicy, deploy approval, scope, \"is this what you wanted\".\n\nContract: `/_docs/chat-contract.md`.\n\n## Say it\n\n hermes <message> # send (legacy alias: feedback)\n hermes-poll # check for new replies now (alias: feedback-inbox)\n hermes-reset # rotate the token, start a fresh thread\n\n**Not `chat`.** `ChatStudioModule` already registers `chat` (it toggles the chat overlay) and\ncommand dispatch walks modules in order, so a second `chat` is unreachable — it silently does\nnothing. If you type `chat hello` and nothing happens, that is why.\n\nInside the tool loop:\n\n chat_hermes { \"action\": \"send\", \"text\": \"...\" } -> { \"sent\": true, \"id\": ..., \"epoch\": ... }\n chat_hermes { \"action\": \"read\" } -> { \"awaiting\": bool, \"messages\": [...] }\n\nReplies are **asynchronous**. Send, continue working, read on a later step. Do not block on an\nanswer that is minutes away.\n\n## Read it\n\nReplies print themselves: a 30 second poller shows `🤖 <text>` in the terminal with no command\nfrom you. The cursor is persisted, so a reload does not replay history.\n\n`awaiting: true` means the last word in the thread is yours — an answer is pending. `false` means\nHermes answered.\n\n## Failures and what they mean\n\n| Status | Code | Meaning | Do |\n|---|---|---|---|\n| 401 | `bad_token` | token missing or malformed in localStorage | `hermes-reset` |\n| 413 | `too_long` | over 4000 **codepoints** (emoji count as one) | shorten; nothing was sent |\n| 413 | `too_large` | body over 32 KB | shorten |\n| 429 | `rate_limited` | 20/thread or 40/IP per 10 min | wait `retry_after_ms` |\n| 503 | — | nginx is throttling the host, HTML body | retry with backoff; **not** your mistake |\n| 507 | `thread_limit` | too many threads on disk | tell the operator |\n\nOnly `429` and `503` are worth retrying. Everything else is permanent for that payload.\n\n## The cursor is milliseconds\n\n`epoch` and `cursor` are epoch **milliseconds**. Seconds look plausible and are wrong — two\nmessages in the same second would collide. Never compute the cursor yourself; the server issues it\non every poll, including an empty one (0).\n\n## Rules that keep this useful\n\n- One thought per message. A wall of text gets a shallow answer.\n- Never send credentials, tokens or personal data — it is stored in plain text on the host.\n- Do not poll in a loop. 30 s is already automatic; `hermes-poll` is for \"I need it now\".\n- Threads are per browser token. `hermes-reset` deliberately abandons the old thread, and the old\n messages stay on disk but you will not see them again.\n- If Hermes asks a question, answer it in the same thread — the operator loses the context otherwise.\n\n## Verify your own result\n\n hermes hello -> \"📨 Sending…\" then \"✅ sent id=… epoch=…\"\n hermes-poll -> \"⏳ waiting for Hermes\" while the answer is pending\n\nA send that prints only `📨 Sending…` and never a ✅ or ❌ means the request never completed —\nreport that, it is a bug, not a slow answer.\n",
+ "created_at": "2026-10-23T19:50:00+00:00",
+ "updated_at": "2026-10-23T19:50:00+00:00",
+ "source": "seed"
+} \ No newline at end of file
diff --git a/skills/chatting-with-hermes.md b/skills/chatting-with-hermes.md
new file mode 100644
index 0000000..0bc246a
--- /dev/null
+++ b/skills/chatting-with-hermes.md
@@ -0,0 +1,76 @@
+---
+name: chatting-with-hermes
+description: How to message Hermes (the platform operator) from inside newOS4, and how to read the answer - commands, the chat_hermes tool, cursor and error semantics
+tags: [hermes, chat, operator, escalation, feedback, agent]
+category: system
+---
+
+# Talking to Hermes
+
+Hermes is the operator agent that runs the host. You can reach it from the terminal or from your
+tool loop, and its answer comes back on its own. Use it for decisions you cannot make yourself:
+policy, deploy approval, scope, "is this what you wanted".
+
+Contract: `/_docs/chat-contract.md`.
+
+## Say it
+
+ hermes <message> # send (legacy alias: feedback)
+ hermes-poll # check for new replies now (alias: feedback-inbox)
+ hermes-reset # rotate the token, start a fresh thread
+
+**Not `chat`.** `ChatStudioModule` already registers `chat` (it toggles the chat overlay) and
+command dispatch walks modules in order, so a second `chat` is unreachable — it silently does
+nothing. If you type `chat hello` and nothing happens, that is why.
+
+Inside the tool loop:
+
+ chat_hermes { "action": "send", "text": "..." } -> { "sent": true, "id": ..., "epoch": ... }
+ chat_hermes { "action": "read" } -> { "awaiting": bool, "messages": [...] }
+
+Replies are **asynchronous**. Send, continue working, read on a later step. Do not block on an
+answer that is minutes away.
+
+## Read it
+
+Replies print themselves: a 30 second poller shows `🤖 <text>` in the terminal with no command
+from you. The cursor is persisted, so a reload does not replay history.
+
+`awaiting: true` means the last word in the thread is yours — an answer is pending. `false` means
+Hermes answered.
+
+## Failures and what they mean
+
+| Status | Code | Meaning | Do |
+|---|---|---|---|
+| 401 | `bad_token` | token missing or malformed in localStorage | `hermes-reset` |
+| 413 | `too_long` | over 4000 **codepoints** (emoji count as one) | shorten; nothing was sent |
+| 413 | `too_large` | body over 32 KB | shorten |
+| 429 | `rate_limited` | 20/thread or 40/IP per 10 min | wait `retry_after_ms` |
+| 503 | — | nginx is throttling the host, HTML body | retry with backoff; **not** your mistake |
+| 507 | `thread_limit` | too many threads on disk | tell the operator |
+
+Only `429` and `503` are worth retrying. Everything else is permanent for that payload.
+
+## The cursor is milliseconds
+
+`epoch` and `cursor` are epoch **milliseconds**. Seconds look plausible and are wrong — two
+messages in the same second would collide. Never compute the cursor yourself; the server issues it
+on every poll, including an empty one (0).
+
+## Rules that keep this useful
+
+- One thought per message. A wall of text gets a shallow answer.
+- Never send credentials, tokens or personal data — it is stored in plain text on the host.
+- Do not poll in a loop. 30 s is already automatic; `hermes-poll` is for "I need it now".
+- Threads are per browser token. `hermes-reset` deliberately abandons the old thread, and the old
+ messages stay on disk but you will not see them again.
+- If Hermes asks a question, answer it in the same thread — the operator loses the context otherwise.
+
+## Verify your own result
+
+ hermes hello -> "📨 Sending…" then "✅ sent id=… epoch=…"
+ hermes-poll -> "⏳ waiting for Hermes" while the answer is pending
+
+A send that prints only `📨 Sending…` and never a ✅ or ❌ means the request never completed —
+report that, it is a bug, not a slow answer.
diff --git a/skills/index.json b/skills/index.json
index 4bce206..d9ac86d 100644
--- a/skills/index.json
+++ b/skills/index.json
@@ -108,7 +108,7 @@
},
"module-editing-workflow": {
"name": "module-editing-workflow",
- "description": "Step-by-step procedure for editing a WebX11 module: view \u2192 edit \u2192 test \u2192 keep or reload",
+ "description": "Step-by-step procedure for editing a WebX11 module: view → edit → test → keep or reload",
"tags": [
"modules",
"editing",
@@ -121,7 +121,7 @@
},
"vfs-content-search": {
"name": "vfs-content-search",
- "description": "Find files in the VFS by semantic concept (NVFS) or by content keyword (grep) \u2014 decision table",
+ "description": "Find files in the VFS by semantic concept (NVFS) or by content keyword (grep) — decision table",
"tags": [
"vfs",
"search",
@@ -148,7 +148,7 @@
},
"vfs-path-normalize": {
"name": "vfs-path-normalize",
- "description": "Strip trailing slashes from VFS paths before API calls \u2014 prevents /skills/ vs /skills resolution failures",
+ "description": "Strip trailing slashes from VFS paths before API calls — prevents /skills/ vs /skills resolution failures",
"tags": [
"vfs",
"utility",
@@ -236,5 +236,19 @@
"category": "system",
"created": "2026-10-23T16:27:07.000Z",
"updated": "2026-10-23T16:27:07.000Z"
+ },
+ "chatting-with-hermes": {
+ "name": "chatting-with-hermes",
+ "description": "How to message Hermes (the platform operator) from inside newOS4, and how to read the answer - commands, the chat_hermes tool, cursor and error semantics",
+ "tags": [
+ "hermes",
+ "chat",
+ "operator",
+ "escalation",
+ "feedback",
+ "agent"
+ ],
+ "category": "system",
+ "updated_at": "2026-10-23T19:50:00+00:00"
}
} \ No newline at end of file