aboutsummaryrefslogtreecommitdiff
path: root/course/chapters
diff options
context:
space:
mode:
authorAgando <roduccomm@gmail.com>2026-10-18 14:05:18 +0200
committerAgando <roduccomm@gmail.com>2026-10-18 14:05:18 +0200
commit88ad8ed2fbbda61920b11a79df29acb58928b5af (patch)
tree7fd3df420ed78e59ccdc7861c7408347b207cfb5 /course/chapters
parent005a1ad651383cca9793f24213de3a22c2474967 (diff)
newOS4: interactive AI course (terminal module, portal, atlas, telemetry, daily maintenance+cron) + free store card
Diffstat (limited to 'course/chapters')
-rw-r--r--course/chapters/01-orientation.json132
-rw-r--r--course/chapters/02-architecture.json131
-rw-r--r--course/chapters/03-commands.json119
-rw-r--r--course/chapters/04-ai.json128
-rw-r--r--course/chapters/05-modules.json115
-rw-r--r--course/chapters/06-files-cloud.json132
-rw-r--r--course/chapters/07-automation.json134
-rw-r--r--course/chapters/08-build.json117
8 files changed, 1008 insertions, 0 deletions
diff --git a/course/chapters/01-orientation.json b/course/chapters/01-orientation.json
new file mode 100644
index 0000000..165e140
--- /dev/null
+++ b/course/chapters/01-orientation.json
@@ -0,0 +1,132 @@
+{
+ "id": "01-orientation",
+ "title": "Orientation β€” what newOS4 is",
+ "icon": "πŸš€",
+ "level": "beginner",
+ "lessons": [
+ {
+ "id": "1.1",
+ "title": "A terminal in your browser",
+ "objective": "Understand what newOS4 is and run your first three commands.",
+ "minutes": 6,
+ "commands": [
+ "help",
+ "status",
+ "ls"
+ ],
+ "blocks": [
+ {
+ "type": "text",
+ "text": "newOS4 is a terminal-centric browser OS. Every command runs in your tab, files live in a virtual filesystem (VFS), and modules add commands at runtime."
+ },
+ {
+ "type": "cmd",
+ "text": "help"
+ },
+ {
+ "type": "text",
+ "text": "`help` lists every registered command grouped by the module that owns it."
+ },
+ {
+ "type": "cmd",
+ "text": "status"
+ },
+ {
+ "type": "cmd",
+ "text": "ls"
+ },
+ {
+ "type": "tip",
+ "text": "The VFS survives reloads. Create a file with `touch notes.txt`, then run `ls`."
+ }
+ ],
+ "exercise": {
+ "instruction": "Run `status` and read the loaded-modules line.",
+ "accept": [
+ "status"
+ ],
+ "check": {
+ "type": "command"
+ },
+ "hint": "Type: status"
+ },
+ "quiz": {
+ "q": "Where do files live in newOS4?",
+ "options": [
+ "On the web server",
+ "In the browser VFS",
+ "In a SQL database"
+ ],
+ "answer": 1
+ },
+ "sources": [
+ "modules/core/terminal.js",
+ "modules/core/virtual-fs.js"
+ ]
+ },
+ {
+ "id": "1.2",
+ "title": "Finding your way around",
+ "objective": "Navigate the virtual filesystem and create your first file.",
+ "minutes": 8,
+ "commands": [
+ "pwd",
+ "cd",
+ "tree",
+ "cat",
+ "touch"
+ ],
+ "blocks": [
+ {
+ "type": "text",
+ "text": "The VFS is a tree rooted at `/`. `pwd` prints where you are, `cd` moves, `tree` shows the branch, `cat` prints a file."
+ },
+ {
+ "type": "cmd",
+ "text": "pwd"
+ },
+ {
+ "type": "cmd",
+ "text": "tree"
+ },
+ {
+ "type": "warn",
+ "text": "`echo \"text\" > file` is NOT supported by the VFS. Use `touch`, the editor (`edit <file>`), or `webx11.fs.writeFile()` in the console."
+ },
+ {
+ "type": "cmd",
+ "text": "touch hello.txt"
+ },
+ {
+ "type": "cmd",
+ "text": "ls"
+ }
+ ],
+ "exercise": {
+ "instruction": "From the root, create `hello.txt` and list it.",
+ "accept": [
+ "touch hello.txt",
+ "ls"
+ ],
+ "check": {
+ "type": "file",
+ "path": "/hello.txt"
+ },
+ "hint": "Type: touch hello.txt β€” then ls"
+ },
+ "quiz": {
+ "q": "Which command prints the current directory?",
+ "options": [
+ "ls",
+ "pwd",
+ "cd"
+ ],
+ "answer": 1
+ },
+ "sources": [
+ "modules/core/module-fs.js",
+ "modules/core/virtual-fs.js"
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/course/chapters/02-architecture.json b/course/chapters/02-architecture.json
new file mode 100644
index 0000000..7dee513
--- /dev/null
+++ b/course/chapters/02-architecture.json
@@ -0,0 +1,131 @@
+{
+ "id": "02-architecture",
+ "title": "Architecture without the mystery",
+ "icon": "πŸ—",
+ "level": "beginner",
+ "lessons": [
+ {
+ "id": "2.1",
+ "title": "Terminal, modules, commands",
+ "objective": "See how the terminal, module manager and command registry fit together.",
+ "minutes": 9,
+ "commands": [
+ "modules",
+ "status",
+ "help"
+ ],
+ "blocks": [
+ {
+ "type": "text",
+ "text": "`terminal.js` parses input and dispatches a command to the module that registered it. Each module owns a `commands` map and contributes help strings."
+ },
+ {
+ "type": "cmd",
+ "text": "modules"
+ },
+ {
+ "type": "text",
+ "text": "The module manager lists every loaded module and its command count."
+ },
+ {
+ "type": "cmd",
+ "text": "status"
+ },
+ {
+ "type": "text",
+ "text": "`status` shows files, modules and network state in one place."
+ },
+ {
+ "type": "cmd",
+ "text": "check"
+ },
+ {
+ "type": "tip",
+ "text": "A command that exists in `help` but fails at runtime usually has an unmet module requirement that `check` reports."
+ }
+ ],
+ "exercise": {
+ "instruction": "List the loaded modules.",
+ "accept": [
+ "modules",
+ "status"
+ ],
+ "check": {
+ "type": "command"
+ },
+ "hint": "Type: modules"
+ },
+ "quiz": {
+ "q": "Who executes a command after you press Enter?",
+ "options": [
+ "nginx",
+ "the module that registered it",
+ "the browser cache"
+ ],
+ "answer": 1
+ },
+ "sources": [
+ "modules/core/terminal.js",
+ "modules/core/module-manager.js",
+ "modules/core/module-system.js"
+ ]
+ },
+ {
+ "id": "2.2",
+ "title": "VFS and the three loading tiers",
+ "objective": "Understand where files live and why a module edit sometimes needs a rebuild and sometimes does not.",
+ "minutes": 10,
+ "commands": [
+ "status",
+ "help",
+ "load-local"
+ ],
+ "blocks": [
+ {
+ "type": "text",
+ "text": "Files live in `virtual-fs.js` (in-memory + localStorage persistence). Directories are nodes; `readFile()` returns `null` for a missing path."
+ },
+ {
+ "type": "text",
+ "text": "Modules ship in three tiers:"
+ },
+ {
+ "type": "table",
+ "text": "core-bundle.js β€” core modules (requires rebuild) | critical-ext-bundle.js β€” editor, shell, alias, finder, filemgr, diff, busybox (requires rebuild) | individually loaded ext modules β€” cache-busted by LATEST_VER (no rebuild)"
+ },
+ {
+ "type": "cmd",
+ "text": "status"
+ },
+ {
+ "type": "warn",
+ "text": "Individually loaded modules are cached with `?v=<webx11_cache_ver>`. Without bumping `LATEST_VER`, users keep the old file."
+ }
+ ],
+ "exercise": {
+ "instruction": "Run `status` and find the VFS size line.",
+ "accept": [
+ "status"
+ ],
+ "check": {
+ "type": "command"
+ },
+ "hint": "Type: status"
+ },
+ "quiz": {
+ "q": "Which tier needs `rebuild-bundles.py` after an edit?",
+ "options": [
+ "core-bundle.js",
+ "webdav.js",
+ "course.js"
+ ],
+ "answer": 0
+ },
+ "sources": [
+ "modules/core/virtual-fs.js",
+ "modules/core/module-loader.js",
+ "scripts/rebuild-bundles.py"
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/course/chapters/03-commands.json b/course/chapters/03-commands.json
new file mode 100644
index 0000000..10807cb
--- /dev/null
+++ b/course/chapters/03-commands.json
@@ -0,0 +1,119 @@
+{
+ "id": "03-commands",
+ "title": "Command mastery",
+ "icon": "⌨",
+ "level": "beginner",
+ "lessons": [
+ {
+ "id": "3.1",
+ "title": "Find any command fast",
+ "objective": "Use help, commands and check to discover what exists before guessing.",
+ "minutes": 7,
+ "commands": [
+ "help",
+ "status"
+ ],
+ "blocks": [
+ {
+ "type": "text",
+ "text": "`help` groups all 344 commands by the module that owns them."
+ },
+ {
+ "type": "cmd",
+ "text": "help"
+ },
+ {
+ "type": "cmd",
+ "text": "help webdav-push"
+ },
+ {
+ "type": "tip",
+ "text": "`check` shows module requirements β€” the fastest way to explain a command that is listed but not working."
+ }
+ ],
+ "exercise": {
+ "instruction": "Open the help for `webdav-push`.",
+ "accept": [
+ "help webdav-push"
+ ],
+ "check": {
+ "type": "command"
+ },
+ "hint": "Type: help webdav-push"
+ },
+ "quiz": {
+ "q": "Which command shows usage for one command?",
+ "options": [
+ "help <cmd>",
+ "status",
+ "ls"
+ ],
+ "answer": 0
+ },
+ "sources": [
+ "modules/core/module-system.js",
+ "modules/core/module-manager.js"
+ ]
+ },
+ {
+ "id": "3.2",
+ "title": "Pipes, grep, sed, tail",
+ "objective": "Combine commands and understand the two semantics that bite: per-line sed and tail -f deltas.",
+ "minutes": 12,
+ "commands": [
+ "grep",
+ "sed",
+ "tail",
+ "sort",
+ "head"
+ ],
+ "blocks": [
+ {
+ "type": "text",
+ "text": "Pipes feed one command into the next. `grep` filters lines, `sed` substitutes text, `tail` prints the end of a file."
+ },
+ {
+ "type": "cmd",
+ "text": "ls | grep txt"
+ },
+ {
+ "type": "warn",
+ "text": "`sed s/x/y/` substitutes the first match per LINE, not per file. `sed -i` is flagged destructive and needs confirmation."
+ },
+ {
+ "type": "text",
+ "text": "`tail -f` is interactive and stops with Ctrl+C. AI-initiated commands get a bounded read instead."
+ },
+ {
+ "type": "cmd",
+ "text": "tail hello.txt"
+ }
+ ],
+ "exercise": {
+ "instruction": "Search the current listing for `txt`.",
+ "accept": [
+ "ls | grep txt",
+ "grep txt"
+ ],
+ "check": {
+ "type": "command"
+ },
+ "hint": "Type: ls | grep txt"
+ },
+ "quiz": {
+ "q": "`sed s/a/b/` replaces…",
+ "options": [
+ "every match in the file",
+ "the first match on each line",
+ "only the last line"
+ ],
+ "answer": 1
+ },
+ "sources": [
+ "modules/core/module-fs.js",
+ "modules/ext/shell.js",
+ "modules/core/terminal.js"
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/course/chapters/04-ai.json b/course/chapters/04-ai.json
new file mode 100644
index 0000000..3552c53
--- /dev/null
+++ b/course/chapters/04-ai.json
@@ -0,0 +1,128 @@
+{
+ "id": "04-ai",
+ "title": "The AI assistant",
+ "icon": "πŸ€–",
+ "level": "intermediate",
+ "lessons": [
+ {
+ "id": "4.1",
+ "title": "Ask, and let it use tools",
+ "objective": "Use the AI assistant and understand the confirmation boundary.",
+ "minutes": 9,
+ "commands": [
+ "ai",
+ "ask",
+ "ai-config",
+ "ai-model"
+ ],
+ "blocks": [
+ {
+ "type": "text",
+ "text": "`ai` and `ask` open the tool-calling assistant. It can read files, run safe commands and search the web."
+ },
+ {
+ "type": "cmd",
+ "text": "ai what can you do?"
+ },
+ {
+ "type": "text",
+ "text": "Destructive actions (writes, `sed -i`, deletes) require confirmation. AI-initiated commands run with a loop guard so they cannot recurse."
+ },
+ {
+ "type": "cmd",
+ "text": "ai-model"
+ },
+ {
+ "type": "cmd",
+ "text": "ai-config"
+ }
+ ],
+ "exercise": {
+ "instruction": "Ask the AI a short question.",
+ "accept": [
+ "ai *",
+ "ask *"
+ ],
+ "check": {
+ "type": "command"
+ },
+ "hint": "Type: ai \"hello\""
+ },
+ "quiz": {
+ "q": "What happens when the AI wants a destructive command?",
+ "options": [
+ "runs silently",
+ "asks for confirmation",
+ "restarts the terminal"
+ ],
+ "answer": 1
+ },
+ "sources": [
+ "modules/core/module-aiassist.js",
+ "modules/core/ollama-manager.js"
+ ]
+ },
+ {
+ "id": "4.2",
+ "title": "Context, memory and skills",
+ "objective": "Inspect and clear context, then browse the skill library the AI retrieves from.",
+ "minutes": 8,
+ "commands": [
+ "ai-context",
+ "ai-clear",
+ "skill-list",
+ "skill-validate",
+ "learn-skill"
+ ],
+ "blocks": [
+ {
+ "type": "text",
+ "text": "The assistant keeps recent context. `ai-context` shows it; `ai-clear` resets it without touching your files."
+ },
+ {
+ "type": "cmd",
+ "text": "ai-context"
+ },
+ {
+ "type": "cmd",
+ "text": "skill-list"
+ },
+ {
+ "type": "text",
+ "text": "Skills are markdown entries in `/skills/` indexed by `/skills/index.json`; `load_skills` retrieves them by query."
+ },
+ {
+ "type": "cmd",
+ "text": "skill-validate course-01-orientation"
+ },
+ {
+ "type": "tip",
+ "text": "This course installs its chapters as `course-*` skills, so the AI can teach what you are reading."
+ }
+ ],
+ "exercise": {
+ "instruction": "List the installed skills.",
+ "accept": [
+ "skill-list"
+ ],
+ "check": {
+ "type": "command"
+ },
+ "hint": "Type: skill-list"
+ },
+ "quiz": {
+ "q": "Where does the skill index live?",
+ "options": [
+ "/skills/index.json",
+ "/etc/skills",
+ "localStorage only"
+ ],
+ "answer": 0
+ },
+ "sources": [
+ "modules/ext/skill-pack-core.js",
+ "modules/core/module-aiassist.js"
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/course/chapters/05-modules.json b/course/chapters/05-modules.json
new file mode 100644
index 0000000..4b68f42
--- /dev/null
+++ b/course/chapters/05-modules.json
@@ -0,0 +1,115 @@
+{
+ "id": "05-modules",
+ "title": "Modules & packages",
+ "icon": "🧩",
+ "level": "intermediate",
+ "lessons": [
+ {
+ "id": "5.1",
+ "title": "Browse and install modules",
+ "objective": "See what is loaded and install from the WebX11 package index.",
+ "minutes": 8,
+ "commands": [
+ "modules",
+ "wpm",
+ "load-local"
+ ],
+ "blocks": [
+ {
+ "type": "text",
+ "text": "`wpm` is the package manager for terminal modules: list the index, install a module from `packages.json` or a URL."
+ },
+ {
+ "type": "cmd",
+ "text": "wpm list"
+ },
+ {
+ "type": "cmd",
+ "text": "modules"
+ },
+ {
+ "type": "text",
+ "text": "Every ext module in the default build auto-loads. There is no separate β€œneeds loadmod” tier."
+ },
+ {
+ "type": "cmd",
+ "text": "load-local modules/ext/calc.js"
+ }
+ ],
+ "exercise": {
+ "instruction": "List available packages.",
+ "accept": [
+ "wpm list"
+ ],
+ "check": {
+ "type": "command"
+ },
+ "hint": "Type: wpm list"
+ },
+ "quiz": {
+ "q": "What does wpm install?",
+ "options": [
+ "terminal modules",
+ "system packages",
+ "browser extensions"
+ ],
+ "answer": 0
+ },
+ "sources": [
+ "modules/ext/wpm.js",
+ "packages.json",
+ "modules/core/module-loader.js"
+ ]
+ },
+ {
+ "id": "5.2",
+ "title": "Module anatomy (a complete mini module)",
+ "objective": "Read the contract every module follows: class, commands map, help info, registration.",
+ "minutes": 12,
+ "commands": [
+ "load-local"
+ ],
+ "blocks": [
+ {
+ "type": "text",
+ "text": "A module is a class with `commands`, `registerCommands()`, `getHelpInfo()` and optionally `init(terminal)`. The module manager injects `terminal` before calling `registerCommands()`."
+ },
+ {
+ "type": "code",
+ "text": "class HelloModule {\n constructor(){ this.commands = {}; }\n getHelpInfo(){ return { hello: 'hello β€” print a greeting' }; }\n registerCommands(){ this.commands['hello'] = () => this.terminal.print('hello newOS4'); }\n}"
+ },
+ {
+ "type": "tip",
+ "text": "Tier-3 modules register at the end with `webx11.moduleManager.registerModule(new HelloModule(), url)`."
+ },
+ {
+ "type": "cmd",
+ "text": "modules"
+ }
+ ],
+ "exercise": {
+ "instruction": "Open the module list and find a module you have not used.",
+ "accept": [
+ "modules"
+ ],
+ "check": {
+ "type": "command"
+ },
+ "hint": "Type: modules"
+ },
+ "quiz": {
+ "q": "What does the module manager inject before registerCommands()?",
+ "options": [
+ "the terminal",
+ "the database",
+ "nothing"
+ ],
+ "answer": 0
+ },
+ "sources": [
+ "modules/core/module-manager.js",
+ "modules/ext/kanban.js"
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/course/chapters/06-files-cloud.json b/course/chapters/06-files-cloud.json
new file mode 100644
index 0000000..697a5f5
--- /dev/null
+++ b/course/chapters/06-files-cloud.json
@@ -0,0 +1,132 @@
+{
+ "id": "06-files-cloud",
+ "title": "Files, editor, WebDAV",
+ "icon": "☁",
+ "level": "intermediate",
+ "lessons": [
+ {
+ "id": "6.1",
+ "title": "Edit and compare files",
+ "objective": "Use the editor and diff tools on the VFS.",
+ "minutes": 9,
+ "commands": [
+ "edit",
+ "diff",
+ "find",
+ "files"
+ ],
+ "blocks": [
+ {
+ "type": "text",
+ "text": "`edit` opens the VFS editor. `diff` compares two files. `find` searches names; `filemgr` opens the visual browser."
+ },
+ {
+ "type": "cmd",
+ "text": "edit hello.txt"
+ },
+ {
+ "type": "cmd",
+ "text": "find hello"
+ },
+ {
+ "type": "cmd",
+ "text": "diff hello.txt hello.txt"
+ },
+ {
+ "type": "tip",
+ "text": "The editor calls the tutorial/file-saved hook, so exercise progress can be detected from a save."
+ },
+ {
+ "type": "cmd",
+ "text": "files"
+ }
+ ],
+ "exercise": {
+ "instruction": "Search for your file by name.",
+ "accept": [
+ "find hello",
+ "find hello.txt"
+ ],
+ "check": {
+ "type": "command"
+ },
+ "hint": "Type: find hello"
+ },
+ "quiz": {
+ "q": "Which command opens the visual file manager?",
+ "options": [
+ "filemgr",
+ "ls",
+ "cat"
+ ],
+ "answer": 0
+ },
+ "sources": [
+ "modules/ext/editor.js",
+ "modules/ext/diff.js",
+ "modules/ext/filemgr.js"
+ ]
+ },
+ {
+ "id": "6.2",
+ "title": "Cloud sync and login",
+ "objective": "Understand WebDAV auth, the space token, and the 401 self-heal path.",
+ "minutes": 14,
+ "commands": [
+ "webdav-login",
+ "webdav-config",
+ "webdav-status",
+ "webdav-push",
+ "webdav-backup"
+ ],
+ "blocks": [
+ {
+ "type": "text",
+ "text": "WebDAV syncs your VFS to your space. The module holds a SPACE token, not your personal token; it refreshes on 401."
+ },
+ {
+ "type": "cmd",
+ "text": "webdav-status"
+ },
+ {
+ "type": "cmd",
+ "text": "webdav-login"
+ },
+ {
+ "type": "warn",
+ "text": "Sessions do not cross browser contexts. If a push 401s, run `webdav-login` in THIS browser, then retry."
+ },
+ {
+ "type": "cmd",
+ "text": "webdav-push"
+ },
+ {
+ "type": "cmd",
+ "text": "webdav-backup"
+ }
+ ],
+ "exercise": {
+ "instruction": "Check the WebDAV status.",
+ "accept": [
+ "webdav-status"
+ ],
+ "check": {
+ "type": "command"
+ },
+ "hint": "Type: webdav-status"
+ },
+ "quiz": {
+ "q": "A 401 push usually means…",
+ "options": [
+ "the file is too big",
+ "no session/token in this browser context",
+ "WebDAV is disabled"
+ ],
+ "answer": 1
+ },
+ "sources": [
+ "modules/ext/webdav.js"
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/course/chapters/07-automation.json b/course/chapters/07-automation.json
new file mode 100644
index 0000000..3345fc2
--- /dev/null
+++ b/course/chapters/07-automation.json
@@ -0,0 +1,134 @@
+{
+ "id": "07-automation",
+ "title": "Automation",
+ "icon": "βš™",
+ "level": "advanced",
+ "lessons": [
+ {
+ "id": "7.1",
+ "title": "Schedule commands with cron",
+ "objective": "Run a command on an interval and manage the schedule.",
+ "minutes": 8,
+ "commands": [
+ "cron-every",
+ "cron-list",
+ "cron-stop",
+ "cron-clear"
+ ],
+ "blocks": [
+ {
+ "type": "text",
+ "text": "`cron-every` schedules a command inside the terminal (minimum 5 seconds). Jobs live only while the tab is open."
+ },
+ {
+ "type": "cmd",
+ "text": "cron-every 60 echo hello"
+ },
+ {
+ "type": "cmd",
+ "text": "cron-list"
+ },
+ {
+ "type": "cmd",
+ "text": "cron-stop 1"
+ },
+ {
+ "type": "cmd",
+ "text": "cron-clear"
+ },
+ {
+ "type": "tip",
+ "text": "For server-side schedules use Hermes cron; the terminal scheduler is per-tab."
+ }
+ ],
+ "exercise": {
+ "instruction": "List active cron jobs.",
+ "accept": [
+ "cron-list"
+ ],
+ "check": {
+ "type": "command"
+ },
+ "hint": "Type: cron-list"
+ },
+ "quiz": {
+ "q": "How long does a terminal cron job live?",
+ "options": [
+ "forever on the server",
+ "while the tab is open",
+ "until reboot"
+ ],
+ "answer": 1
+ },
+ "sources": [
+ "modules/ext/cron.js"
+ ]
+ },
+ {
+ "id": "7.2",
+ "title": "Kanban and checkpoints",
+ "objective": "Track work on a board and snapshot the VFS before risky changes.",
+ "minutes": 8,
+ "commands": [
+ "kanban",
+ "checkpoint",
+ "checkpoint-list",
+ "rollback"
+ ],
+ "blocks": [
+ {
+ "type": "text",
+ "text": "`kanban` is a local board with todo/doing/done columns. `checkpoint` snapshots the VFS; `rollback` restores it."
+ },
+ {
+ "type": "cmd",
+ "text": "kanban add \"Try the course\""
+ },
+ {
+ "type": "cmd",
+ "text": "kanban list"
+ },
+ {
+ "type": "cmd",
+ "text": "checkpoint before-project"
+ },
+ {
+ "type": "cmd",
+ "text": "checkpoint-list"
+ },
+ {
+ "type": "cmd",
+ "text": "rollback before-project"
+ },
+ {
+ "type": "warn",
+ "text": "`rollback` replaces current VFS state β€” checkpoint before experiments."
+ }
+ ],
+ "exercise": {
+ "instruction": "Create a checkpoint.",
+ "accept": [
+ "checkpoint *",
+ "checkpoint"
+ ],
+ "check": {
+ "type": "command"
+ },
+ "hint": "Type: checkpoint my-test"
+ },
+ "quiz": {
+ "q": "What does checkpoint do?",
+ "options": [
+ "snapshots the VFS",
+ "deletes files",
+ "pushes to WebDAV"
+ ],
+ "answer": 0
+ },
+ "sources": [
+ "modules/ext/kanban.js",
+ "modules/core/module-fs.js"
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/course/chapters/08-build.json b/course/chapters/08-build.json
new file mode 100644
index 0000000..48a60bd
--- /dev/null
+++ b/course/chapters/08-build.json
@@ -0,0 +1,117 @@
+{
+ "id": "08-build",
+ "title": "Build & extend",
+ "icon": "πŸ”§",
+ "level": "advanced",
+ "lessons": [
+ {
+ "id": "8.1",
+ "title": "Add a command safely",
+ "objective": "Follow the edit β†’ syntax β†’ test β†’ rebuild β†’ version-bump loop.",
+ "minutes": 12,
+ "commands": [
+ "load-local",
+ "status",
+ "help"
+ ],
+ "blocks": [
+ {
+ "type": "text",
+ "text": "Edit the source, run `node --check`, run the relevant test harness, rebuild bundles for tiers 1–2, then bump BOTH `main.html` and `LATEST_VER`."
+ },
+ {
+ "type": "cmd",
+ "text": "status"
+ },
+ {
+ "type": "cmd",
+ "text": "help load-local"
+ },
+ {
+ "type": "warn",
+ "text": "Editing a tier-3 module without bumping `LATEST_VER` means users keep the stale cached file indefinitely."
+ }
+ ],
+ "exercise": {
+ "instruction": "Run the built-in test suite.",
+ "accept": [
+ "status"
+ ],
+ "check": {
+ "type": "command"
+ },
+ "hint": "Type: test auto"
+ },
+ "quiz": {
+ "q": "Which two places carry the version?",
+ "options": [
+ "main.html and LATEST_VER",
+ "package.json only",
+ "localStorage"
+ ],
+ "answer": 0
+ },
+ "sources": [
+ "scripts/rebuild-bundles.py",
+ "modules/core/module-loader.js"
+ ]
+ },
+ {
+ "id": "8.2",
+ "title": "Debug and observe",
+ "objective": "Use the debug panel, console and health checks when something breaks.",
+ "minutes": 8,
+ "commands": [
+ "debug",
+ "health-check",
+ "js"
+ ],
+ "blocks": [
+ {
+ "type": "text",
+ "text": "`debug` toggles the runtime debug panel; `console` opens a JS console in the terminal; `health-check` audits VFS, modules, logs and skills."
+ },
+ {
+ "type": "cmd",
+ "text": "health-check"
+ },
+ {
+ "type": "cmd",
+ "text": "debug"
+ },
+ {
+ "type": "tip",
+ "text": "Errors are posted to `/spaces/newos4/api/debug/ingest.php` and clustered in the debug dashboard."
+ },
+ {
+ "type": "cmd",
+ "text": "js 1+1"
+ }
+ ],
+ "exercise": {
+ "instruction": "Run a health check.",
+ "accept": [
+ "health-check"
+ ],
+ "check": {
+ "type": "command"
+ },
+ "hint": "Type: health-check"
+ },
+ "quiz": {
+ "q": "Where do runtime errors get ingested?",
+ "options": [
+ "/api/debug/ingest.php",
+ "/dev/null",
+ "localStorage"
+ ],
+ "answer": 0
+ },
+ "sources": [
+ "modules/ext/debug-panel.js",
+ "modules/core/module-debug-supervisor.js",
+ "api/debug/ingest.php"
+ ]
+ }
+ ]
+} \ No newline at end of file