Commit Graph

21 Commits

Author SHA1 Message Date
73696bc58c use native Claude Code installer (curl | bash), check prerequisites in birth
- install-cli.sh: suggest curl -sL https://claude.ai/install.sh | bash
- birth.sh: check colony, colony-agent, claude are in PATH before starting
- Fail fast with clear error messages if anything is missing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 08:27:32 +02:00
0f000c70c9 fix: codex birth review — shell injection, root prevention, dream user
Critical fixes:
- Quoted heredoc prevents shell injection in CLAUDE.md generation
- Block reserved system usernames (root, daemon, bin, etc.)
- Dream service runs as agent user, not root
- systemd ExecStartPre/Post handles worker stop/start (root via +)
- dream.rs no longer calls systemctl directly

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 23:21:02 +02:00
39ba317e5e birth script + POST /api/users endpoint
- scripts/birth.sh: create agent (user, soul, memory, config, systemd)
- POST /api/users: register new users (for agent birth)
- colony-agent birth delegates to birth.sh via sudo
- Soul template with self-discovery, evolution log, birth instruction
- systemd units: worker service + dream timer per agent
- MemoryMax=4G on worker to prevent OOM

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 23:11:08 +02:00
d47905a68f fix: codex review — safe ack, dream stops worker, graceful errors
Worker:
- Only ack inbox items if Claude succeeds (prevents losing work on crash)
- Graceful error if colony not in PATH (no panic)
- Check colony inbox exit code before parsing
- Per-agent prompt path (/tmp/colony-{name}-prompt.md)

Dream:
- Stops worker service before dreaming (prevents file races)
- Restarts worker after dream completes
- Posts error message if dream fails
- Uses COLONY_AGENT env var for service name

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 23:03:28 +02:00
67c81fc518 colony-agent: implement worker loop + dream cycle
Worker:
- run_pulse(): check inbox → heartbeat → HEARTBEAT_OK or invoke Claude
- run_worker_loop(): forever loop with 30s/10s sleep
- Builds prompt from inbox items + heartbeat.md
- Invokes claude --dangerously-skip-permissions with context
- Acks inbox items after Claude completes
- Added 'pulse' command for one-shot testing

Dream:
- Checks memory.md line count (skip if < 50)
- Posts "dreaming..." to #general
- Invokes Claude to consolidate, prune, evolve
- Posts "back from dreaming" when done

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 22:53:49 +02:00
5c59b598c6 fix: codex review — scope ack to user, deduplicate inbox entries
- ack_inbox now requires ?user= and only acks items owned by that user
- Reports actual rows_affected instead of input count
- populate_inbox uses HashSet to prevent duplicate entries
- @alice @alice no longer creates two inbox items
- @alice @agents for an agent named alice only creates one item

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 22:51:48 +02:00
87b6e264c6 fix: graceful error on inbox parse failure instead of panic
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 22:49:54 +02:00
dd536c0949 colony-agent skeleton: worker, dream, birth, status commands (stubs)
Phase 2 crate scaffolded with clap CLI. All commands are stubs
that exit with "not yet implemented". Ready for implementation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 22:48:50 +02:00
321adfb9e9 Colony CLI: inbox + ack commands
- colony inbox [--json] — show unacked inbox items
- colony ack <id> [--all] [--quiet] — ack items
- Client methods: get_inbox(), ack_inbox()
- AckRequest gets Serialize derive for CLI use

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 22:44:21 +02:00
2127bf4ef0 backend: inbox table + endpoints, mention-triggered inbox population
- Migration: inbox table with user_id, message_id, trigger, acked_at
- GET /api/inbox?user= — returns unacked inbox items with full message + channel
- POST /api/inbox/ack — ack items by ID array
- post_message now calls populate_inbox() to create entries for @mentions
- Handles @agents (all agents) and @apes (all apes) broadcasts
- parse_mentions made public for reuse

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 22:42:45 +02:00
5d2bd5600e Colony CLI v1: init, whoami, channels, read, post, create-channel
Working commands against live apes.unslope.com:
- colony init --api-url X --user Y
- colony whoami [--json]
- colony channels [--json]
- colony read <channel> [--since N] [--json]
- colony post <channel> "msg" [--type X] [--json] [--quiet]
- colony create-channel <name> [--json]

All with --json support, proper exit codes, channel name resolution.
Reuses colony-types for no split brain. Added Serialize to request types.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 22:38:49 +02:00
5ba82869d3 fix: CLI spec contradictions from codex AX audit
- Fix paths: relative to agent home dir, not hardcoded /home/agent
- Add worker/dream coordination: dream pauses worker to prevent file races
- Watch registration via .colony.toml (server reads agent config)
- Remove remaining old mentions API reference (use inbox instead)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 22:32:32 +02:00
18a091abe4 docs: scout's soul — first agent identity template
Personality: curious, honest, show-don't-tell
Behavior: watches #general + #research, proactive, max 5 messages/pulse
Values: apes don't do tasks, be useful not noisy, escalate to @apes
Voice: lowercase, casual, direct, no LLM slop

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 22:20:29 +02:00
ca2e604b4e restore/undo for deleted messages — backend + UI
- POST /api/channels/{id}/messages/{msg_id}/restore — undeletes a message
- Any user can restore (not just the deleter)
- Broadcasts restored message via WebSocket
- UI: "undo" button in floating pill on deleted messages
- API: restoreMessage() in api.ts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 22:08:52 +02:00
1830b520a6 delete messages + fix layout overflow
- DELETE /api/channels/{id}/messages/{msg_id} — soft delete, own only
- Broadcasts WsEvent::Delete to subscribers
- UI: "Del" button on hover for own messages (turns red)
- Fix layout: h-full + overflow-hidden on flex containers
- ScrollArea gets min-h-0 to properly constrain in flex
- Messages no longer push compose past viewport

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 21:19:44 +02:00
8ce8ebc9b8 add @mentions — parsed server-side, rendered as highlighted spans
- Backend: parse_mentions() extracts @username from content
- Message API response includes mentions: string[] field
- Frontend: renderContent() highlights @mentions in hot orange
- Works with alphanumeric + hyphens + underscores

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 20:56:45 +02:00
17cca7b077 S5: WebSocket real-time — per-channel broadcast, auto-reconnect
Backend:
- AppState with per-channel broadcast::Sender map
- WS handler: auth via first message, keepalive pings, broadcast forwarding
- post_message broadcasts WsEvent::Message to all subscribers

Frontend:
- useChannelSocket hook: connects, auths, appends messages, auto-reconnects
- Removed 3s polling — WebSocket is primary, initial load via REST
- Deduplication on WS messages (sender also fetches after post)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 20:29:07 +02:00
3a2f414e47 fix: eprintln for Docker logs, include migrations in stub build
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 19:42:44 +02:00
f8420496b2 S3+S4: user param auth, static file serving, Docker deploy config
- replace hardcoded benji with ?user= query param
- add GET /api/users and GET /api/me?user= endpoints
- serve frontend static files via tower-http ServeDir
- add multi-stage Dockerfile (Rust + Vite → single image)
- add docker-compose.yml + Caddyfile for apes.unslope.com
- frontend: getCurrentUsername() from URL param → localStorage
- sidebar shows current user

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 19:18:06 +02:00
b48232ca03 fix: all 5 high-severity bugs from codex review
- use sqlx migrate!() instead of broken split(';') — triggers now work
- seq via AUTOINCREMENT — no race conditions, monotonic ordering
- replace ?since= with ?after_seq= — cursor-based, no timestamp format issues
- replace all unwrap() with typed errors (404, 409, 400, 500)
- reply_to same-channel enforced in route handler
- add biome for frontend linting

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 19:07:12 +02:00
e940afde52 S1: Colony backend skeleton — Axum + SQLite, channels + messages CRUD
Monorepo structure:
- crates/colony-types: API types (serde + ts-rs), separate from DB models
- crates/colony: Axum server, SQLite via sqlx, migrations

Working endpoints:
- GET /api/health
- GET/POST /api/channels
- GET /api/channels/{id}
- GET /api/channels/{id}/messages (?since=, ?type=, ?user_id=)
- POST /api/channels/{id}/messages (with type + metadata)

Data model includes:
- seq monotonic ordering, soft delete, same-channel reply constraint
- Seeded users (benji, neeraj) and #general channel

Also: codex-review skill, .gitignore

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 18:54:43 +02:00