diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 504d762..7d87a6e 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -13,7 +13,7 @@ "name": "llm-wiki", "source": "./plugins/llm-wiki", "description": "Create and query project wikis with optional maintenance automation.", - "version": "0.3.2", + "version": "0.3.3", "author": { "name": "ivankuznetsov", "url": "https://github.com/ivankuznetsov" diff --git a/docs/agent-compatibility.md b/docs/agent-compatibility.md index 43e904c..7c90933 100644 --- a/docs/agent-compatibility.md +++ b/docs/agent-compatibility.md @@ -35,7 +35,7 @@ plugin directory so a copied package does not depend on the repository root. | Agent Reviewer | `0.3.1` | Stable | `skills/agent-reviewer/SKILL.md` | agents, references, scripts, eval harness | | Agent SEO | `2.0.1` | Stable | `skills/seo/SKILL.md` | agents, context, data sources, hooks, scripts | | Agent Writing | `0.5.2` | Stable | `skills/writing/SKILL.md` | agents, voice/style context | -| LLM Wiki | `0.3.2` | Stable | five files under `skills/` | assets, consent-gated maintenance templates | +| LLM Wiki | `0.3.3` | Stable | five files under `skills/` | assets, consent-gated maintenance templates | | Screenote | `3.0.1` | Stable | `skills/{screenote,snapshot,feedback}/SKILL.md` | CLI launcher, references, evals | ## Plugin invocations diff --git a/plugin-surfaces.json b/plugin-surfaces.json index bdeb98e..1e2447a 100644 --- a/plugin-surfaces.json +++ b/plugin-surfaces.json @@ -174,7 +174,7 @@ { "name": "llm-wiki", "path": "plugins/llm-wiki", - "version": "0.3.2", + "version": "0.3.3", "stability": "stable", "metadata": { "display_name": "LLM Wiki", diff --git a/plugin-surfaces.lock.json b/plugin-surfaces.lock.json index c4c3257..05ef47a 100644 --- a/plugin-surfaces.lock.json +++ b/plugin-surfaces.lock.json @@ -636,7 +636,7 @@ } }, "llm-wiki": { - "version": "0.3.2", + "version": "0.3.3", "canonical": { "skills/bootstrap/SKILL.md": { "sha256": "6e446e783ac32d2f605f036891fcee29651aca14696065f2753cec13eab58a16", @@ -722,7 +722,7 @@ }, "templates": { "exists": true, - "sha256": "264d01db93a76080b4ecb586a5cbe98608edc6358820a36f676a1c2683f3d2af", + "sha256": "ad03c9d5a6457d631a1556039484c119e81a89d5eff6f3953e93be7014c61452", "files": [ "templates/compile-log.sh", "templates/install-systemd-scheduler.sh", diff --git a/plugins/llm-wiki/.claude-plugin/plugin.json b/plugins/llm-wiki/.claude-plugin/plugin.json index 91ab284..7a17ff5 100644 --- a/plugins/llm-wiki/.claude-plugin/plugin.json +++ b/plugins/llm-wiki/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "llm-wiki", - "version": "0.3.2", + "version": "0.3.3", "description": "Create and query project wikis with optional maintenance automation.", "author": { "name": "ivankuznetsov", diff --git a/plugins/llm-wiki/.codex-plugin/plugin.json b/plugins/llm-wiki/.codex-plugin/plugin.json index 90b2252..37f3041 100644 --- a/plugins/llm-wiki/.codex-plugin/plugin.json +++ b/plugins/llm-wiki/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "llm-wiki", - "version": "0.3.2", + "version": "0.3.3", "description": "Create and query project wikis with optional maintenance automation.", "author": { "name": "ivankuznetsov", diff --git a/plugins/llm-wiki/CHANGELOG.md b/plugins/llm-wiki/CHANGELOG.md index 488521c..0d44920 100644 --- a/plugins/llm-wiki/CHANGELOG.md +++ b/plugins/llm-wiki/CHANGELOG.md @@ -4,6 +4,21 @@ All notable changes to **llm-wiki** are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/), and the project adheres to [Semantic Versioning](https://semver.org/). +## [0.3.3] - 2026-07-22 + +### Fixed + +- Reconstruct the standard user-systemd bus environment in headless commit + hooks and scheduler upgrades, so the installed 4 GiB/no-swap worker remains + reachable without an interactive shell. +- Preserve the repository scheduler marker when a best-effort service signal + fails, while retaining the machine-wide serialized fallback for the current + queue. +- Skip commits whose only changed path is compiled `wiki/log.md`, preventing a + generated projection from launching another provider-backed refresh. +- Preserve the four-agent consent and OpenClaw ownership adaptations while + vendoring the standalone 0.1.17 runtime fix. + ## [0.3.2] - 2026-07-22 ### Fixed diff --git a/plugins/llm-wiki/openclaw.plugin.json b/plugins/llm-wiki/openclaw.plugin.json index 02af868..558c6b6 100644 --- a/plugins/llm-wiki/openclaw.plugin.json +++ b/plugins/llm-wiki/openclaw.plugin.json @@ -2,7 +2,7 @@ "id": "llm-wiki", "name": "LLM Wiki", "description": "Create and query project wikis with optional maintenance automation.", - "version": "0.3.2", + "version": "0.3.3", "skills": [ "./openclaw/skills" ], diff --git a/plugins/llm-wiki/package.json b/plugins/llm-wiki/package.json index beca938..05f71e9 100644 --- a/plugins/llm-wiki/package.json +++ b/plugins/llm-wiki/package.json @@ -1,6 +1,6 @@ { "name": "llm-wiki", - "version": "0.3.2", + "version": "0.3.3", "type": "module", "description": "Create and query project wikis with optional maintenance automation.", "homepage": "https://github.com/ivankuznetsov/llm-wiki", diff --git a/plugins/llm-wiki/templates/install-systemd-scheduler.sh b/plugins/llm-wiki/templates/install-systemd-scheduler.sh index e6d44ab..53c97b3 100755 --- a/plugins/llm-wiki/templates/install-systemd-scheduler.sh +++ b/plugins/llm-wiki/templates/install-systemd-scheduler.sh @@ -57,6 +57,22 @@ decode_systemd_path() { sed -e 's/\\x22/"/g' -e 's/\\x20/ /g' -e 's/\\x5c/\\/g' } +systemctl_command=(systemctl) +configure_user_systemctl_command() { + local uid runtime_dir bus_address + uid="$(id -u)" + runtime_dir="${XDG_RUNTIME_DIR:-/run/user/$uid}" + bus_address="${DBUS_SESSION_BUS_ADDRESS:-}" + + systemctl_command=(systemctl) + if [ -S "$runtime_dir/bus" ]; then + bus_address="${bus_address:-unix:path=$runtime_dir/bus}" + systemctl_command=( + env "XDG_RUNTIME_DIR=$runtime_dir" "DBUS_SESSION_BUS_ADDRESS=$bus_address" systemctl + ) + fi +} + base="$(basename "$primary_root" | sed 's/[^A-Za-z0-9_.-]/-/g')" slug="$base-$(digest "$primary_root")" service_name="llm-wiki-$slug.service" @@ -161,9 +177,10 @@ for candidate in "${obsolete[@]}"; do [ -e "$candidate" ] || [ -L "$candidate" ] || continue if [ "${LLM_WIKI_SKIP_SYSTEMCTL:-${HIVE_SKIP_LLM_WIKI_SYSTEMCTL:-}}" != 1 ] && \ command -v systemctl >/dev/null 2>&1; then + configure_user_systemctl_command case "$candidate" in *.service|*.timer) - systemctl --user stop "$(basename "$candidate")" >/dev/null 2>&1 || true + "${systemctl_command[@]}" --user stop "$(basename "$candidate")" >/dev/null 2>&1 || true ;; esac fi @@ -177,11 +194,12 @@ fi if [ "${LLM_WIKI_SKIP_SYSTEMCTL:-${HIVE_SKIP_LLM_WIKI_SYSTEMCTL:-}}" != 1 ] && \ command -v systemctl >/dev/null 2>&1; then - systemctl --user daemon-reload - systemctl --user stop "$service_name" >/dev/null 2>&1 || true - systemctl --user stop "$timer_name" >/dev/null 2>&1 || true + configure_user_systemctl_command + "${systemctl_command[@]}" --user daemon-reload + "${systemctl_command[@]}" --user stop "$service_name" >/dev/null 2>&1 || true + "${systemctl_command[@]}" --user stop "$timer_name" >/dev/null 2>&1 || true if [ "$enable_timer" -eq 1 ]; then - systemctl --user start "$timer_name" + "${systemctl_command[@]}" --user start "$timer_name" fi fi printf 'llm-wiki: installed one bounded scheduler for repository: %s\n' "$primary_root" diff --git a/plugins/llm-wiki/templates/post-commit-refresh.sh b/plugins/llm-wiki/templates/post-commit-refresh.sh index 91786f1..8eb0876 100755 --- a/plugins/llm-wiki/templates/post-commit-refresh.sh +++ b/plugins/llm-wiki/templates/post-commit-refresh.sh @@ -103,6 +103,22 @@ run_with_timeout() { run_without_git_env "$timeout_bin" -k "$kill_after" "$seconds" "$@" } +USER_SYSTEMCTL_COMMAND=(systemctl) +configure_user_systemctl_command() { + local uid runtime_dir bus_address + uid="$(id -u)" + runtime_dir="${XDG_RUNTIME_DIR:-/run/user/$uid}" + bus_address="${DBUS_SESSION_BUS_ADDRESS:-}" + + USER_SYSTEMCTL_COMMAND=(systemctl) + if [ -S "$runtime_dir/bus" ]; then + bus_address="${bus_address:-unix:path=$runtime_dir/bus}" + USER_SYSTEMCTL_COMMAND=( + env "XDG_RUNTIME_DIR=$runtime_dir" "DBUS_SESSION_BUS_ADDRESS=$bus_address" systemctl + ) + fi +} + clear_git_tool_environment() { local name for name in "${GIT_ENV_NAMES[@]}"; do @@ -185,6 +201,12 @@ if [ "$drain_mode" -eq 0 ] && [ -z "$retry_selector" ]; then changed_files="$(git diff-tree --no-commit-id --name-only -r HEAD 2>/dev/null || true)" [ -n "$changed_files" ] || exit 0 + # wiki/log.md is compiled from wiki/log.d fragments. A commit that only + # rewrites the compiled projection contains no new source for the wiki agent. + if ! printf '%s\n' "$changed_files" | grep -Fqvx 'wiki/log.md'; then + exit 0 + fi + if ! printf '%s\n' "$changed_files" | grep -Eq \ '(^|/)(schema\.rb|structure\.sql|db/migrate/|migrations/|models/|entities/|prisma/schema\.prisma|routes|controllers|handlers|resolvers|app/|src/|lib/|test/|tests/|spec/|templates/|config/|bin/|README\.md|Gemfile|Gemfile\.lock|package\.json|package-lock\.json|go\.mod|go\.sum|Cargo\.toml|Cargo\.lock|requirements\.txt|pyproject\.toml|poetry\.lock|composer\.json|composer\.lock|docs/|wiki/|raw/notes/|plans/|todos/|CHANGELOG\.md|AGENTS\.md|CLAUDE\.md)'; then exit 0 @@ -220,15 +242,15 @@ if [ "$drain_mode" -eq 0 ] && [ -z "$retry_selector" ]; then scheduler_service="$(sed -n '1p' "$state_dir/scheduler-service" 2>/dev/null || true)" if [ "${LLM_WIKI_SKIP_SYSTEMCTL:-${HIVE_SKIP_LLM_WIKI_SYSTEMCTL:-}}" != "1" ] && \ [[ "$scheduler_service" =~ ^llm-wiki-[A-Za-z0-9_.-]+\.service$ ]]; then + configure_user_systemctl_command if command -v systemctl >/dev/null 2>&1 && \ run_with_timeout "${LLM_WIKI_SYSTEMCTL_TIMEOUT:-10}" \ - systemctl --user start --no-block "$scheduler_service" \ + "${USER_SYSTEMCTL_COMMAND[@]}" --user start --no-block "$scheduler_service" \ >>"$log_file" 2>&1; then log_line "queued source $sha for memory-bounded systemd worker $scheduler_service" exit 0 else - rm -f -- "$state_dir/scheduler-service" - log_line "WARN: memory-bounded systemd worker $scheduler_service could not be started; using machine-wide serialized fallback" + log_line "WARN: memory-bounded systemd worker $scheduler_service could not be signalled; keeping its configured marker and using machine-wide serialized fallback" fi fi fi diff --git a/tests/test_llm_wiki_openclaw.py b/tests/test_llm_wiki_openclaw.py index 4b111ab..6ae9e1f 100644 --- a/tests/test_llm_wiki_openclaw.py +++ b/tests/test_llm_wiki_openclaw.py @@ -1,6 +1,7 @@ import json import os import shutil +import socket import subprocess import tempfile import unittest @@ -116,6 +117,192 @@ def test_post_commit_runtime_bounds_recovery_and_publishes_only_refresh_branch(s self.assertIn('push "$refresh_remote" "HEAD:refs/heads/$refresh_branch"', template) self.assertNotIn('push "$refresh_remote" "HEAD:refs/heads/$base_branch"', template) + def test_compiled_log_only_commit_does_not_queue_or_launch_refresh(self): + with tempfile.TemporaryDirectory() as directory: + root = self.initialize_hook_project(directory) + (root / "wiki" / "log.md").write_text( + "# Compiled projection\n\nsecond render\n", encoding="utf-8" + ) + self.run_git(root, "add", "wiki/log.md") + self.run_git(root, "commit", "-m", "compile wiki log") + source_sha = self.git_output(root, "rev-parse", "HEAD") + + environment = os.environ.copy() + environment.update( + { + "HOME": str(Path(directory) / "home"), + "PATH": "/usr/bin:/bin", + "LLM_WIKI_SKIP_SYSTEMCTL": "1", + } + ) + result = subprocess.run( + [str(root / ".llm-wiki" / "post-commit-refresh.sh")], + cwd=root, + env=environment, + text=True, + capture_output=True, + check=False, + ) + + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + pending = root / ".git" / "llm-wiki" / "pending" + self.assertEqual([], list(pending.iterdir())) + source_ref = subprocess.run( + ["git", "show-ref", "--verify", "--quiet", f"refs/llm-wiki/sources/{source_sha}"], + cwd=root, + check=False, + ) + self.assertNotEqual(0, source_ref.returncode) + + def test_headless_hook_recovers_user_bus_environment(self): + with tempfile.TemporaryDirectory() as directory: + root = self.initialize_hook_project(directory) + (root / "README.md").write_text("changed\n", encoding="utf-8") + self.run_git(root, "add", "README.md") + self.run_git(root, "commit", "-m", "change docs") + + bin_dir = Path(directory) / "bin" + runtime_dir = Path(directory) / "runtime" + systemctl_log = Path(directory) / "systemctl.log" + bin_dir.mkdir() + runtime_dir.mkdir() + fake_systemctl = bin_dir / "systemctl" + fake_systemctl.write_text( + '#!/usr/bin/env bash\nprintf "%s|%s|%s\\n" ' + '"$XDG_RUNTIME_DIR" "$DBUS_SESSION_BUS_ADDRESS" "$*" ' + '>"$LLM_WIKI_SYSTEMCTL_LOG"\n', + encoding="utf-8", + ) + fake_systemctl.chmod(0o755) + state_dir = root / ".git" / "llm-wiki" + state_dir.mkdir(parents=True) + marker = state_dir / "scheduler-service" + marker.write_text("llm-wiki-project-deadbeef.service\n", encoding="utf-8") + + bus_path = runtime_dir / "bus" + with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as bus: + bus.bind(str(bus_path)) + environment = os.environ.copy() + environment.update( + { + "HOME": str(Path(directory) / "home"), + "PATH": f"{bin_dir}:/usr/bin:/bin", + "XDG_RUNTIME_DIR": str(runtime_dir), + "DBUS_SESSION_BUS_ADDRESS": "", + "LLM_WIKI_SYSTEMCTL_LOG": str(systemctl_log), + } + ) + result = subprocess.run( + [str(root / ".llm-wiki" / "post-commit-refresh.sh")], + cwd=root, + env=environment, + text=True, + capture_output=True, + check=False, + ) + + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + self.assertEqual( + f"{runtime_dir}|unix:path={bus_path}|--user start --no-block " + "llm-wiki-project-deadbeef.service\n", + systemctl_log.read_text(encoding="utf-8"), + ) + self.assertEqual( + "llm-wiki-project-deadbeef.service\n", + marker.read_text(encoding="utf-8"), + ) + + def test_failed_headless_signal_keeps_scheduler_marker_and_falls_back(self): + with tempfile.TemporaryDirectory() as directory: + root = self.initialize_hook_project(directory) + (root / "README.md").write_text("changed\n", encoding="utf-8") + self.run_git(root, "add", "README.md") + self.run_git(root, "commit", "-m", "change docs") + + bin_dir = Path(directory) / "bin" + bin_dir.mkdir() + fake_systemctl = bin_dir / "systemctl" + fake_systemctl.write_text("#!/usr/bin/env bash\nexit 1\n", encoding="utf-8") + fake_systemctl.chmod(0o755) + state_dir = root / ".git" / "llm-wiki" + state_dir.mkdir(parents=True) + marker = state_dir / "scheduler-service" + marker.write_text("llm-wiki-project-deadbeef.service\n", encoding="utf-8") + + environment = os.environ.copy() + environment.update( + { + "HOME": str(Path(directory) / "home"), + "PATH": f"{bin_dir}:/usr/bin:/bin", + "LLM_WIKI_REFRESH_CMD": "/bin/true", + "LLM_WIKI_SKIP_PUSH": "1", + } + ) + result = subprocess.run( + [str(root / ".llm-wiki" / "post-commit-refresh.sh")], + cwd=root, + env=environment, + text=True, + capture_output=True, + check=False, + ) + + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + self.assertEqual( + "llm-wiki-project-deadbeef.service\n", + marker.read_text(encoding="utf-8"), + ) + log = (state_dir / "post-commit-refresh.log").read_text(encoding="utf-8") + self.assertIn("keeping its configured marker", log) + + def test_scheduler_recovers_user_bus_environment(self): + with tempfile.TemporaryDirectory() as directory: + root = self.initialize_hook_project(directory) + unit_dir = Path(directory) / "systemd" + bin_dir = Path(directory) / "bin" + runtime_dir = Path(directory) / "runtime" + systemctl_log = Path(directory) / "systemctl.log" + unit_dir.mkdir() + bin_dir.mkdir() + runtime_dir.mkdir() + fake_systemctl = bin_dir / "systemctl" + fake_systemctl.write_text( + '#!/usr/bin/env bash\nprintf "%s|%s|%s\\n" ' + '"$XDG_RUNTIME_DIR" "$DBUS_SESSION_BUS_ADDRESS" "$*" ' + '>>"$LLM_WIKI_SYSTEMCTL_LOG"\n', + encoding="utf-8", + ) + fake_systemctl.chmod(0o755) + + bus_path = runtime_dir / "bus" + with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as bus: + bus.bind(str(bus_path)) + environment = os.environ.copy() + environment.update( + { + "PATH": f"{bin_dir}:/usr/bin:/bin", + "XDG_RUNTIME_DIR": str(runtime_dir), + "DBUS_SESSION_BUS_ADDRESS": "", + "LLM_WIKI_SYSTEMD_USER_DIR": str(unit_dir), + "LLM_WIKI_FLOCK_PATH": shutil.which("flock") or "/usr/bin/flock", + "LLM_WIKI_SYSTEMCTL_LOG": str(systemctl_log), + } + ) + result = subprocess.run( + [str(SCHEDULER_TEMPLATE), "--project", str(root)], + env=environment, + text=True, + capture_output=True, + check=False, + ) + + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + calls = systemctl_log.read_text(encoding="utf-8") + self.assertIn( + f"{runtime_dir}|unix:path={bus_path}|--user daemon-reload", + calls, + ) + def test_scheduler_reconciles_linked_worktrees_and_stops_disabled_units(self): with tempfile.TemporaryDirectory() as directory: root = Path(directory) / "project" @@ -409,6 +596,47 @@ def run_template(self, headless_agent, openclaw_agent_id="main", consent=True): log = log_path.read_text(encoding="utf-8") if log_path.exists() else "" return result, arguments, log + def initialize_hook_project(self, directory): + root = Path(directory) / "project" + home = Path(directory) / "home" + root.mkdir() + home.mkdir() + (root / ".llm-wiki").mkdir() + (root / "wiki").mkdir() + shutil.copy2(POST_COMMIT_TEMPLATE, root / ".llm-wiki" / "post-commit-refresh.sh") + (root / ".llm-wiki" / "post-commit-refresh.sh").chmod(0o755) + (root / ".llm-wiki" / "config.json").write_text( + json.dumps( + { + "headless_agent": "codex", + "automation_enabled": True, + "external_provider_access_approved": True, + } + ) + + "\n", + encoding="utf-8", + ) + (root / "README.md").write_text("initial\n", encoding="utf-8") + (root / "wiki" / "index.md").write_text("# Wiki\n", encoding="utf-8") + (root / "wiki" / "log.md").write_text("# Compiled projection\n", encoding="utf-8") + self.run_git(root, "init", "-b", "main") + self.run_git(root, "config", "user.email", "llm-wiki-test@example.com") + self.run_git(root, "config", "user.name", "LLM Wiki Test") + self.run_git(root, "add", ".") + self.run_git(root, "commit", "-m", "initial") + return root + + def git_output(self, root, *arguments): + result = subprocess.run( + ["git", *arguments], + cwd=root, + text=True, + capture_output=True, + check=False, + ) + self.assertEqual(0, result.returncode, result.stdout + result.stderr) + return result.stdout.strip() + def run_git(self, root, *arguments): result = subprocess.run( ["git", *arguments], diff --git a/wiki/architecture.md b/wiki/architecture.md index 76aa241..affb70e 100644 --- a/wiki/architecture.md +++ b/wiki/architecture.md @@ -41,8 +41,11 @@ owner, including a validated OpenClaw workspace agent, from a disposable refresh worktree. The primary checkout owns one repository-wide non-persistent systemd timer; linked worktrees cannot install independent timers. Services share a machine-wide provider lock, run with a 4 GiB memory ceiling and no swap, and -drain durable commit-hook queues. Successful wiki-only batches are merged with -and pushed only to `origin/llm-wiki/refresh`, never the protected default branch. +drain durable commit-hook queues. Headless callers recover missing user-bus +variables from the standard socket and retain the installed service marker +after a transient signal failure. Compiled-`wiki/log.md`-only commits do not +enter the queue. Successful wiki-only batches are merged with and pushed only +to `origin/llm-wiki/refresh`, never the protected default branch. Large queued-source pin sets are processed in bounded Git transactions, and recoverable interrupted queue files are rebuilt from their source commits. diff --git a/wiki/gaps.md b/wiki/gaps.md index c427af6..f85d3b3 100644 --- a/wiki/gaps.md +++ b/wiki/gaps.md @@ -12,7 +12,10 @@ - LLM Wiki's standalone and four-host marketplace packages intentionally use separate version lines (`0.1.x` upstream runtime and `0.3.x` consent-gated marketplace package). A marketplace release must preserve the consent and - OpenClaw adaptations while vendoring the released runtime. + OpenClaw adaptations while vendoring the released runtime. Marketplace + 0.3.3 vendors the released standalone 0.1.17 headless scheduler fix; public + ClawHub scan and catalog visibility remain release-time evidence rather than + source-tree facts. - Compatibility with OpenClaw releases older than `2026.7.1-beta.2` remains unverified. ClawHub packages therefore declare that tested version as their conservative plugin API floor while leaving the broader host minimum diff --git a/wiki/log.d/20260722T203800Z-llm-wiki-033-headless-scheduler.md b/wiki/log.d/20260722T203800Z-llm-wiki-033-headless-scheduler.md new file mode 100644 index 0000000..2b4f282 --- /dev/null +++ b/wiki/log.d/20260722T203800Z-llm-wiki-033-headless-scheduler.md @@ -0,0 +1,17 @@ +--- +title: Keep LLM Wiki bounded scheduling reachable from headless hooks +date: 2026-07-22T20:38:00Z +tags: [llm-wiki, systemd, scheduler, queue, release] +--- + +Prepared LLM Wiki marketplace 0.3.3 from the released standalone 0.1.17 +runtime while retaining the four-host consent gate and OpenClaw owner +dispatch. Commit hooks and scheduler upgrades now reconstruct missing +user-systemd bus variables from the standard per-user socket. A failed signal +keeps the installed scheduler marker and uses the existing serialized fallback +for the current queue instead of disabling later bounded dispatch. + +Commits changing only compiled `wiki/log.md` now exit before queue creation, +source pinning, or provider launch. Source fragments and other project changes +remain eligible. Regression coverage exercises the real shell templates for +compiled-log no-op behavior, bus recovery, marker retention, and fallback. diff --git a/wiki/plugins.md b/wiki/plugins.md index 5483435..c0660b7 100644 --- a/wiki/plugins.md +++ b/wiki/plugins.md @@ -8,7 +8,7 @@ OpenClaw. | `agent-reviewer` | `0.3.0` | `agent-reviewer` | agents, references, scripts, eval | | `agent-seo` | `2.0.0` | `seo` | agents, context, data sources, hooks, scripts | | `agent-writing` | `0.5.1` | `writing` | agents, context | -| `llm-wiki` | `0.3.2` | `bootstrap`, `upgrade`, `research`, `wiki-plan`, `wiki-status` | assets, consent-gated templates | +| `llm-wiki` | `0.3.3` | `bootstrap`, `upgrade`, `research`, `wiki-plan`, `wiki-status` | assets, consent-gated templates | | `screenote` | `3.0.0` | `screenote`, `snapshot`, `feedback` | CLI launcher, references, evals | Claude and Codex install through their root marketplaces. Pi and OpenClaw @@ -25,7 +25,9 @@ Version 2.0 makes the removed mutation contract explicit and documents the LLM Wiki bootstrap creates the requested project wiki. Scheduler, managed-hook, shared-Git, and provider-backed maintenance are a separate opt-in; 0.2.x configs without both consent flags are automation-disabled under the 0.3 -runtime. Version 0.3.2 reconciles linked checkouts to one non-persistent, +runtime. Version 0.3.3 reconciles linked checkouts to one non-persistent, memory-bounded timer per repository, serializes providers across repositories, publishes wiki-only output to `origin/llm-wiki/refresh`, and bounds source-ref -recovery transactions. +recovery transactions. Headless hooks reconstruct the standard user bus, +retain the scheduler marker after transient signal failure, and ignore commits +that only rewrite compiled `wiki/log.md`.