fix: pre-public audit — critical install regression + 7 blockers
Some checks are pending
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / preflight (push) Waiting to run
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / vps-smoke (push) Waiting to run
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:frustration-matrix,kei-frustration-loop,kei-skill-importer,kei-projects-index,kei-projects-watcher,kei-gdrive-import,kei-leak-matrix,kei-skills,kei-gateway,kei-cron-scheduler,kei-export-trajectories,kei-backend-daytona,kei-d… (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-compute-baremetal,kei-compute-vultr,kei-compute-linode,kei-compute-digitalocean,kei-svc-systemd,kei-llm-bridge-mlx name:hosted-sleep-compute]) (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-diff,kei-scheduler,kei-watch,kei-prune,kei-discover,kei-brain-view,kei-hibernate,kei-ledger-sign,kei-fork name:wave13-15]) (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-git-gitea,kei-git-forgejo,kei-git-gitlab,kei-git-bitbucket,kei-memory-sled,kei-memory-redis,kei-memory-postgres,kei-memory-sqlite,kei-auth-google,kei-auth-apple,kei-auth-magiclink,kei-auth-webauthn,kei-notify-slack,kei-n… (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-ledger,kei-migrate,kei-changelog,kei-memory,kei-store,kei-conflict-scan,kei-refactor-engine,kei-graph-check,kei-shared,kei-dna-index,kei-pet name:core]) (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-machine-probe,kei-llm-ollama,kei-llm-llamacpp,kei-llm-mlx,kei-llm-router,kei-model name:llm-stack]) (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:kei-router,kei-sage,kei-task,kei-chat-store,kei-crossdomain,kei-search-core,kei-content-store,kei-social-store,kei-curator,kei-auth,kei-artifact name:mcp-lbm]) (push) Blocked by required conditions
CI (Forgejo Actions — self-hosted runner on Mac, host mode) / rust-primitives (map[crates:keisei,kei-forge,kei-runtime,kei-runtime-core,kei-atom-discovery,kei-agent-runtime,kei-capability,kei-provision,kei-entity-store,kei-pipe,kei-cache,kei-spawn,kei-replay name:atom-substrate]) (push) Blocked by required conditions

CRITICAL: lib-hooks.sh had an apostrophe ("user's") inside the jq
program's bash single-quote, closing the quote and producing a parse
error so EVERY install aborted at source time (install.sh:71). Caught
by a full minimal e2e (rc=2 then rc=0 after fix). Reworded the jq
comment to drop the apostrophe.

Audit blockers fixed:
- MANIFEST: drop cortex-ui (no such primitive) from 4 profiles + block;
  lib-menu desc no longer references it. Profile resolution verified clean.
- lib-dev-hub-forgejo / -zoekt: source lib-launchd.sh (register_launchd
  was undefined, so full-hub dev-hub install would fail at runtime).
- kei-message: portable 16-digit id. BSD date prints literal "N" for %N;
  fall back to /dev/urandom. Verified numeric in both code paths.
- bootstrap non-TTY default cortex to minimal (matches install.sh; avoids
  divergent curl-bash vs direct-install behaviour and 105-crate surprise).
- install.sh stamps ~/.claude/.kei-profile; bin/kei reads it (splash
  showed "profile: ?" before, since .installed holds only primitive names).
- README hook count 38 to 54 (real: ls hooks star dot sh).
- web-install warns before it discards local edits in the managed clone.

Verified: 106 shell files bash -n clean; minimal e2e rc=0 (38 agents,
57 hooks, 69 skills, profile stamped, mailbox present).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
KeiSei84 2026-05-24 10:48:06 +08:00
parent c347f329aa
commit 3aff00290f
11 changed files with 41 additions and 25 deletions

View file

@ -8,8 +8,8 @@ OpenClaw / Kimi from the same source-of-truth.
**Apache 2.0** — explicit patent grant + retaliation clause. 105 Rust
crates [REAL: `grep -E '^\s*"[a-z-]+",' _primitives/_rust/Cargo.toml | wc -l`],
68 skills [REAL: `ls skills/ | wc -l`], 38 hooks
[REAL: `grep -c '"command":' settings-snippet.json`], 38 agent manifests
68 skills [REAL: `ls skills/ | wc -l`], 54 hooks
[REAL: `ls hooks/*.sh | wc -l`], 38 agent manifests
[REAL: `ls _manifests/*.toml | wc -l`], 85 substrate blocks
[REAL: `find _blocks/ -name '*.md' | wc -l`], 18 capability atoms
[REAL: `find _capabilities/ -mindepth 2 -maxdepth 2 -type d | wc -l`],
@ -83,7 +83,7 @@ The web installer (`web-install.sh` in this repo, served at
repo and delegates to `bootstrap.sh` — single source of truth, no
duplicated install logic.
38 agents + 68 skills + 38 hooks + nightly consolidation wired in
38 agents + 68 skills + 54 hooks + nightly consolidation wired in
~60 seconds. Twelve install profiles (`outcome-only`, `minimal`,
`core`, `frontend`, `ops`, `dev`, `mcp`, `cortex`, `local-mirror`,
`dashboard`, `full-hub`, `full`) defined in

View file

@ -34,10 +34,10 @@ buddy = ["kei-buddy", "kei-telegram-webhook", "kei-shared", "kei-chat-store",
# previous one — `dashboard` extends `local-mirror`, `full-hub` extends
# `dashboard`. Native macOS arm64 (brew + launchd plists). See
# `install/lib-dev-hub-*.sh` for the install logic per component.
local-mirror = ["kei-cortex", "cortex-ui", "kei-pet", "kei-shared", "kei-ledger", "kei-memory", "frustration-matrix", "kei-skill-importer", "kei-router", "kei-dna-index", "kei-atom-discovery", "dev-hub-forgejo", "dev-hub-forgejo-runner"]
dashboard = ["kei-cortex", "cortex-ui", "kei-pet", "kei-shared", "kei-ledger", "kei-memory", "frustration-matrix", "kei-skill-importer", "kei-router", "kei-dna-index", "kei-atom-discovery", "dev-hub-forgejo", "dev-hub-forgejo-runner", "kei-projects-index", "kei-projects-watcher", "dev-hub-datasette"]
full-hub = ["kei-cortex", "cortex-ui", "kei-pet", "kei-shared", "kei-ledger", "kei-memory", "frustration-matrix", "kei-skill-importer", "kei-router", "kei-dna-index", "kei-atom-discovery", "dev-hub-forgejo", "dev-hub-forgejo-runner", "kei-projects-index", "kei-projects-watcher", "dev-hub-datasette", "dev-hub-zoekt", "dev-hub-mdbook", "dev-hub-restic", "dev-hub-gdrive-import"]
full = ["tomd", "kei-doctor", "kei-ledger", "kei-migrate", "kei-changelog", "ssh-check", "firewall-diff", "mock-render", "visual-diff", "tokens-sync", "design-scrape", "live-preview", "figma-tokens", "frontend-inspect", "screenshot-decode", "provision-hetzner", "provision-vultr", "harden-base", "metrics-scrape", "log-ship", "kei-ci-lint", "kei-docs-scaffold", "kei-memory", "kei-conflict-scan", "kei-refactor-engine", "kei-graph-check", "kei-store", "kei-router", "kei-sage", "kei-task", "kei-chat-store", "kei-crossdomain", "kei-search-core", "kei-content-store", "kei-social-store", "kei-curator", "kei-auth", "kei-artifact", "keisei", "kei-agent-runtime", "kei-capability", "kei-provision", "kei-entity-store", "kei-pipe", "kei-cache", "kei-spawn", "kei-replay", "kei-cortex", "cortex-ui", "kei-pet", "kei-shared", "frustration-matrix", "kei-skill-importer", "kei-projects-index", "kei-projects-watcher", "dev-hub-forgejo", "dev-hub-forgejo-runner", "dev-hub-datasette", "dev-hub-zoekt", "dev-hub-mdbook", "dev-hub-restic", "dev-hub-gdrive-import"]
local-mirror = ["kei-cortex", "kei-pet", "kei-shared", "kei-ledger", "kei-memory", "frustration-matrix", "kei-skill-importer", "kei-router", "kei-dna-index", "kei-atom-discovery", "dev-hub-forgejo", "dev-hub-forgejo-runner"]
dashboard = ["kei-cortex", "kei-pet", "kei-shared", "kei-ledger", "kei-memory", "frustration-matrix", "kei-skill-importer", "kei-router", "kei-dna-index", "kei-atom-discovery", "dev-hub-forgejo", "dev-hub-forgejo-runner", "kei-projects-index", "kei-projects-watcher", "dev-hub-datasette"]
full-hub = ["kei-cortex", "kei-pet", "kei-shared", "kei-ledger", "kei-memory", "frustration-matrix", "kei-skill-importer", "kei-router", "kei-dna-index", "kei-atom-discovery", "dev-hub-forgejo", "dev-hub-forgejo-runner", "kei-projects-index", "kei-projects-watcher", "dev-hub-datasette", "dev-hub-zoekt", "dev-hub-mdbook", "dev-hub-restic", "dev-hub-gdrive-import"]
full = ["tomd", "kei-doctor", "kei-ledger", "kei-migrate", "kei-changelog", "ssh-check", "firewall-diff", "mock-render", "visual-diff", "tokens-sync", "design-scrape", "live-preview", "figma-tokens", "frontend-inspect", "screenshot-decode", "provision-hetzner", "provision-vultr", "harden-base", "metrics-scrape", "log-ship", "kei-ci-lint", "kei-docs-scaffold", "kei-memory", "kei-conflict-scan", "kei-refactor-engine", "kei-graph-check", "kei-store", "kei-router", "kei-sage", "kei-task", "kei-chat-store", "kei-crossdomain", "kei-search-core", "kei-content-store", "kei-social-store", "kei-curator", "kei-auth", "kei-artifact", "keisei", "kei-agent-runtime", "kei-capability", "kei-provision", "kei-entity-store", "kei-pipe", "kei-cache", "kei-spawn", "kei-replay", "kei-cortex", "kei-pet", "kei-shared", "frustration-matrix", "kei-skill-importer", "kei-projects-index", "kei-projects-watcher", "dev-hub-forgejo", "dev-hub-forgejo-runner", "dev-hub-datasette", "dev-hub-zoekt", "dev-hub-mdbook", "dev-hub-restic", "dev-hub-gdrive-import"]
# --- shell primitives (13) -------------------------------------------------
@ -357,12 +357,6 @@ crate = "kei-cortex"
deps = ["python3 (>=3.9, for whisper_worker.py subprocess)", "pip install -r scripts/requirements.txt", "ffmpeg (on PATH, faster-whisper audio demux)"]
desc = "Local HTTP daemon exposing chat/TTS/STT/portrait endpoints — backs cortex-ui browser app"
[primitive.cortex-ui]
kind = "node"
path = "_ts_packages/packages/cortex-ui"
deps = ["node>=18", "pnpm"]
desc = "Svelte 5 + Vite 5 web UI for kei-cortex daemon (chat panel, Live2D pet renderer, portrait uploader)"
[primitive.frustration-matrix]
kind = "rust"
crate = "frustration-matrix"

10
bin/kei
View file

@ -62,12 +62,10 @@ agent_count() {
# Profile from .installed marker file
profile_name() {
local f="${AGENTS_DIR}/_primitives/.installed"
if [ -f "$f" ]; then
grep -E "^profile" "$f" 2>/dev/null | head -1 | awk -F= '{gsub(/[ "]/,"",$2); print $2}' || echo "?"
else
echo "?"
fi
# install.sh stamps the chosen profile here; .installed only holds primitive
# names (so the old `grep ^profile .installed` always returned "?").
local f="$HOME/.claude/.kei-profile"
if [ -f "$f" ]; then head -1 "$f"; else echo "?"; fi
}
# Last Phase B sleep timestamp

View file

@ -51,7 +51,11 @@ prompt_profile() {
# Interactive iff stdin is a terminal. NOT stdout: web-install.sh tees stdout
# to a logfile (pipe), so -t 1 is false even in an interactive curl|bash.
# Prompts print to the terminal via tee; the menu reads from stdin.
if [ ! -t 0 ]; then PROFILE="cortex"; return 0; fi
# Non-interactive (CI / piped, no controlling terminal) → minimal: fast,
# no 105-crate compile, can't half-fail. Matches install.sh's own default
# (was "cortex" here → divergent install vs direct install.sh). Opt up with
# --profile=cortex/full-hub.
if [ ! -t 0 ]; then PROFILE="minimal"; return 0; fi
cat <<'WIZARD'
╔═══════════════════════════════════════════════════════════════════╗

View file

@ -147,6 +147,9 @@ case "$PROFILE" in
;;
esac
say "profile: $PROFILE"
# Stamp the chosen profile so `kei` splash + tools can show it (bin/kei reads this).
mkdir -p "$HOME_DIR/.claude" 2>/dev/null || true
printf '%s\n' "$PROFILE" > "$HOME_DIR/.claude/.kei-profile" 2>/dev/null || true
# --- resolve profile -> primitive list (UNCONDITIONAL, SSoT) -------------
# Must run BEFORE any reader of PROFILE_PRIMS: the --no-execute plan block

View file

@ -160,6 +160,8 @@ _dhf_bootstrap_admin_user() {
# Public — install entry point. Called from install.sh primitives phase.
install_dev_hub_forgejo() {
say "[dev-hub-forgejo] install starting"
# shellcheck source=./lib-launchd.sh
. "$KIT_DIR/install/lib-launchd.sh" # install_service / detect_brew_prefix (was unsourced → command not found)
_dhf_check_brew || return 1
_dhf_brew_install || return 1
_dhf_ensure_data_dir || return 1

View file

@ -128,6 +128,8 @@ _dhz_print_banner() {
# Public — install entry point. Called from install.sh primitives phase.
install_dev_hub_zoekt() {
say "[dev-hub-zoekt] install starting"
# shellcheck source=./lib-launchd.sh
. "$KIT_DIR/install/lib-launchd.sh" # install_service / detect_brew_prefix (was unsourced → command not found)
_dhz_check_brew || return 1
_dhz_check_go_runtime
_dhz_brew_install || return 1

View file

@ -60,9 +60,9 @@ _jq_merge_hooks() {
| reduce ($add.hooks | keys[]) as $phase ($orig;
.hooks[$phase] = (
((.hooks[$phase] // []) + ($add.hooks[$phase] // []))
# Normalize null/absent matcher "" (Claude Code /doctor rejects null;
# user's pre-kit hooks often have no matcher field). Before group_by so
# null + "" collapse into one group.
# Normalize null/absent matcher to "" (Claude Code /doctor rejects null;
# pre-kit user hooks often have no matcher field) before group_by so
# null and "" collapse into one group.
| map(.matcher //= "")
| group_by(.matcher)
| map(

View file

@ -37,7 +37,7 @@ menu_whiptail_profile() {
"ops" "+ 9 infra tools — provision, ssh-check, firewall-diff" OFF \
"dev" "+ 17 dev tools — kei-migrate, kei-memory, deep-sleep" OFF \
"mcp" "+ 10 MCP tools — kei-router, kei-sage, kei-auth, kei-pet" OFF \
"cortex" "+ 11 cortex stack — kei-cortex daemon + cortex-ui" OFF \
"cortex" "+ 11 cortex stack — kei-cortex daemon + UI primitives" OFF \
"full" "+ all 62 primitives (~5 min, 380 MB)" OFF \
"local-mirror" "dev hub: cortex + Forgejo + CI runner (+ 13 prims)" OFF \
"dashboard" "local-mirror + projects-index + Datasette (+ 16 prims)" OFF \

View file

@ -37,7 +37,13 @@ case "$cmd" in
done
body="${body# }"
[ -n "$body" ] || { echo "usage: kei message send [--to <name|all>] <text>" >&2; exit 1; }
id="$(date +%s)$(date +%N 2>/dev/null | cut -c1-6 || printf '000000')"
# Sub-second component: GNU `date +%N` where available; on stock macOS (BSD
# date) %N is unsupported and prints literal "N" → fall back to /dev/urandom.
# Result id = epoch(10) + 6 digits = 16-digit integer, safely < 2^53.
ns="$(date +%N 2>/dev/null)"
case "$ns" in *[!0-9]*|'') ns="$(od -An -N4 -tu4 /dev/urandom 2>/dev/null | tr -dc 0-9)" ;; esac
sub="$(printf '%s000000' "$ns" | cut -c1-6)"
id="$(date +%s)${sub}"
jq -cn --argjson id "$id" --arg ts "$(date -u +%FT%TZ)" \
--arg from "$me" --arg to "$to" --arg body "$body" \
'{id:$id, ts:$ts, from:$from, to:$to, body:$body}' >> "$LOG"

View file

@ -78,6 +78,13 @@ mkdir -p "$(dirname "$KEISEI_ROOT")"
if [ -d "$KEISEI_ROOT/.git" ]; then
say "pulling $KEISEI_REF in $KEISEI_ROOT"
git -C "$KEISEI_ROOT" fetch --depth=1 origin "$KEISEI_REF"
# reset --hard discards ANY local edits in this managed clone. It's a managed
# dir (don't hand-edit it — change the repo + push instead), but warn loudly
# so a manual tweak isn't lost silently.
if ! git -C "$KEISEI_ROOT" diff --quiet 2>/dev/null \
|| ! git -C "$KEISEI_ROOT" diff --cached --quiet 2>/dev/null; then
say " ⚠ local changes in $KEISEI_ROOT will be DISCARDED by reset --hard"
fi
git -C "$KEISEI_ROOT" reset --hard "origin/$KEISEI_REF"
else
say "cloning $KEISEI_REPO ($KEISEI_REF) → $KEISEI_ROOT"