525KB binary, zero external dependencies. Replaces start.sh as launchd target.
- Pre-start port cleanup (kills orphans holding 3111)
- Signal forwarding (SIGTERM/SIGINT/SIGHUP → bun child)
- Crash recovery with exponential backoff (1s→30s max)
- Health checks every 30s, auto-restart after 3 consecutive failures
- Inngest function registry PUT sync after startup
- Secret loading via `secrets` CLI
- TOML config at ~/.config/worker-supervisor.toml
Tested: bun crash → auto-restart in 1s, SIGTERM → clean forwarding,
launchd restart → no orphans, no EADDRINUSE.
Root cause: Colima internally shells to limactl (/opt/homebrew/bin/limactl)
but launchd's default PATH is /usr/bin:/bin:/usr/sbin:/sbin — no homebrew.
Both com.joel.colima and k8s-reboot-heal.sh failed silently for 6 days
(since Feb 21), leaving the entire k8s cluster unrecoverable from any
restart or crash without manual intervention.
Fixes:
- com.joel.colima.plist: add EnvironmentVariables with PATH
- k8s-reboot-heal.sh: export PATH at script top (belt-and-suspenders)
- k8s-reboot-heal.sh: add kubectl uncordon (node was SchedulingDisabled)
- k8s skill: document PATH requirement as resilience rule #6 and #7
- operations.md: document PATH requirement, uncordon step, sticky
shutdown state after unclean Talos container stop
New Inngest function: skill-garden
- Daily cron (6am PT) + on-demand via skill-garden/check event
- Structural checks: broken symlinks, non-canonical REAL DIRs,
missing frontmatter, orphan skills
- Pattern-based staleness: greps for k3d, k3s, qdrant, old paths
- Monthly LLM deep review (1st of month): compares skill content
against current AGENTS.md via pi inference
- Gateway notification when issues found, zero noise on clean days
New skill: skill-review
- Codifies the review process: canonical contract, structural
checks, fix procedures, stale pattern registry
- Documents the automated garden triggers and output
Updated skills:
- joelclaw: full rewrite v2.0.0 — Talos/k8s v1.35.0, 110+ functions,
all CLI commands (subscribe, gateway, otel, recall, discover, etc.),
current pod list, ADR-0155/0156 references
- sync-system-bus: v2.0.0 — publish script as primary method,
ADR-0156 restart safety, current gotcha table
timeouts.start = queued-before-execution timeout
timeouts.finish = total execution time timeout
Was using wrong one, causing 5m default to kill codex runs.
Implements the CLI surface for feed subscription management:
- subscribe list: show all monitored subscriptions from Redis
- subscribe add <url>: add with auto-type-detection, --name, --type, --interval, --filter
- subscribe remove <id>: remove by ID with not-found error handling
- subscribe check [--id]: trigger Inngest check for one or all subscriptions
- subscribe summary: health overview with stale detection and type breakdown
All commands return HATEOAS JSON envelopes per cli-design skill.
Duplicate detection on add with fix suggestion.
Lazy Redis connection (same pattern as gateway commands).
Inngest events for check: subscription/check.requested, subscription/check-feeds.requested
CFP-2 made getPost/getAllPosts async for Convex reads, but Next.js 16
with PPR rejects uncached async data access outside <Suspense>.
ALL article pages failed prerender with 'Uncached data was accessed
outside of <Suspense>'.
CFP-2 and CFP-3 need to land together — Convex reads require
'use cache' boundaries first.
retries: 0 made worker restarts fatal — Inngest couldn't retry
the step on the new worker. With retries: 2, the 1s restart window
is covered by Inngest's built-in retry backoff.
ADR-0156 rewritten: blue/green port swap > drain-then-restart.
Inngest is step-level stateless — we don't need to wait for runs,
just for the current in-flight step.
- Replace manual interfaces with Zod schemas (PrdSchema, StorySchema)
- Runtime parse with safeParse — fails fast with actionable error messages
- StorySchema.transform normalizes acceptance/acceptance_criteria
- Lists available story IDs on not-found error
- Add zod dep to system-bus
- story-pipeline.ts: implement → prove → judge per story
- Event type agent/story.start registered in client
- PRD with 6 stories: seed, read, cache, feedback, inngest, revision
- Concurrency limit 1 (one story at a time)
- Max 3 attempts per story before blocking
Typesense auto-embedding requires the embedding field in query_by
for vector_query with empty array [] to work. Without it:
'Vector query could not find any embedded fields.'
Other callers (observe.ts, context-prefetch.ts) already had this
correct. Only nightly-maintenance was broken.
Probes stat /Volumes/nas-nvme and /Volumes/three-body with 5s
timeout. Stale or missing mounts surface as degraded in gateway
alerts before backup jobs fail silently.
Ref: ADR-0088 addendum (2026-02-27)
- /api/search now serves HATEOAS envelope for agents AND web UI
- Search dialog reads from .result.hits (envelope-aware)
- Updated /api discovery and layout comment
- Removed /api/agent/ directory