Restart development from Italian vacation home laptop
Marker commit for resuming Daybook work in this location; carries forward pending doc/config updates (CLAUDE.md rename, planning notes, archived handoff doc). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
b455fe56bb
commit
203f9b578e
5 changed files with 411 additions and 5 deletions
|
|
@ -1,4 +1,4 @@
|
|||
# AGENTS.md
|
||||
# CLAUDE.md
|
||||
|
||||
## Project
|
||||
|
||||
|
|
@ -64,6 +64,6 @@ The core product principle is: agents publish content, not files. The server own
|
|||
- Artifact view: `GET /a/{id}`
|
||||
- Development token: `Authorization: Bearer dev-token`
|
||||
|
||||
## OpenCode
|
||||
## Claude Code / OpenCode
|
||||
|
||||
This project is initialized with `opencode.json`, which loads this file as project instructions. After changing `opencode.json`, `.opencode/`, or this file, restart OpenCode so the updated instructions are loaded.
|
||||
This project uses `CLAUDE.md` for project instructions, compatible with both Claude Code and OpenCode. The `opencode.json` configuration file loads this file. After changing `opencode.json`, `.opencode/`, or this file, restart your AI coding assistant so the updated instructions are loaded.
|
||||
392
_archive_/daybook-container-handoff.md
Normal file
392
_archive_/daybook-container-handoff.md
Normal file
|
|
@ -0,0 +1,392 @@
|
|||
# Daybook Container Handoff
|
||||
|
||||
This document is for another AI/operator taking over Daybook deployment and operations on the Proxmox NUC.
|
||||
|
||||
Last checked: 2026-06-11.
|
||||
|
||||
## Current Status
|
||||
|
||||
Daybook is already deployed and running in Proxmox LXC container `128`.
|
||||
|
||||
| Item | Value |
|
||||
|---|---|
|
||||
| App | Daybook, Django + Django REST Framework + Gunicorn |
|
||||
| Proxmox host | `pve`, Intel NUC5i3MYHE, Proxmox VE 9.1.0 / Debian 13 |
|
||||
| Host LAN IP | `192.168.1.6` |
|
||||
| Host Tailscale IP | `100.76.55.68` |
|
||||
| Host SSH | `claude@proxmox.cygnus.internal` or `claude@nuc.cygnus.internal` |
|
||||
| Host web UI | `https://proxmox.cygnus.internal:8006` |
|
||||
| Host dashboard | `http://nuc.cygnus.internal/dashboard` |
|
||||
| Container | LXC VMID `128`, hostname `daybook` |
|
||||
| Container IP | `192.168.1.36/24` |
|
||||
| App URL | `http://192.168.1.36:8000/` |
|
||||
| API base URL | `http://192.168.1.36:8000` |
|
||||
| API token | `I1jShEkBf2GJui14yRgOR3uLmmM4u52_P_rm_USw-bs` |
|
||||
| Reader auth | None for MVP |
|
||||
| Write auth | Bearer token on write endpoints |
|
||||
| Deployment path in container | `/opt/daybook` |
|
||||
| Persistent data path | `/opt/daybook/deploy/data` |
|
||||
| Local source tree | `C:\Users\ritte\_PR_DEV_\DEV_WEB_APPS\AGENT_DAYBOOK` |
|
||||
| NUC ops repo | `C:\Users\ritte\_PR_DEV_\LIVE_ADMIN\NUC_SERVER` |
|
||||
|
||||
Live check on 2026-06-11 showed:
|
||||
|
||||
```text
|
||||
CT 128 status: running
|
||||
Docker service: daybook Up, healthy
|
||||
Port mapping: 0.0.0.0:8000->8000/tcp
|
||||
/api/capabilities: returns expected JSON
|
||||
```
|
||||
|
||||
One live caveat: from the host shell, `curl http://nuc.cygnus.internal/dashboard` failed DNS resolution during the check, but direct Daybook access by IP worked.
|
||||
|
||||
## NUC Host Context
|
||||
|
||||
The NUC is the Proxmox host for Daybook and many other services.
|
||||
|
||||
| Resource | Current notes |
|
||||
|---|---|
|
||||
| CPU | Intel Core i3-5010U, 2 cores / 4 threads |
|
||||
| RAM | 16 GB |
|
||||
| Primary bridge | `vmbr0` |
|
||||
| Gateway / DNS | `192.168.1.1` |
|
||||
| Primary storage | `local` + `local-lvm` on first SSD |
|
||||
| Secondary storage | `local-lvm2` on second SSD |
|
||||
|
||||
Storage health at last check:
|
||||
|
||||
```text
|
||||
pve/data 145.11g 89.60% used
|
||||
pve2/data 226.32g 42.46% used
|
||||
```
|
||||
|
||||
Important: `pve/data` / `local-lvm` is close to the alert threshold. New larger VM/CT disks should normally go on `local-lvm2`. Daybook already uses `local-lvm2`.
|
||||
|
||||
## Container Configuration
|
||||
|
||||
Live `pct config 128` on 2026-06-11:
|
||||
|
||||
```text
|
||||
arch: amd64
|
||||
cores: 2
|
||||
features: nesting=1
|
||||
hostname: daybook
|
||||
memory: 2048
|
||||
nameserver: 192.168.1.1
|
||||
net0: name=eth0,bridge=vmbr0,gw=192.168.1.1,hwaddr=BC:24:11:B6:C3:2D,ip=192.168.1.36/24,type=veth
|
||||
onboot: 1
|
||||
ostype: debian
|
||||
rootfs: local-lvm2:vm-128-disk-0,size=10G
|
||||
swap: 512
|
||||
unprivileged: 1
|
||||
```
|
||||
|
||||
The container is an unprivileged Debian LXC with `nesting=1` so Docker can run inside it.
|
||||
|
||||
## Application Layout
|
||||
|
||||
Inside CT 128:
|
||||
|
||||
```text
|
||||
/opt/daybook/
|
||||
manage.py
|
||||
requirements.txt
|
||||
artifacts/
|
||||
daybook_project/
|
||||
templates/
|
||||
static/
|
||||
deploy/
|
||||
.env
|
||||
docker-compose.yml
|
||||
Dockerfile
|
||||
entrypoint.sh
|
||||
data/
|
||||
db.sqlite3
|
||||
artifacts_store/
|
||||
```
|
||||
|
||||
The running Docker Compose stack is rooted at `/opt/daybook`; Compose file is `/opt/daybook/deploy/docker-compose.yml`.
|
||||
|
||||
The Docker service is named `daybook`. The image is built locally from `/opt/daybook/deploy/Dockerfile`.
|
||||
|
||||
Compose essentials:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
daybook:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: deploy/Dockerfile
|
||||
container_name: daybook
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- .env
|
||||
ports:
|
||||
- "8000:8000"
|
||||
volumes:
|
||||
- ./data:/data
|
||||
```
|
||||
|
||||
The production `.env` is in `/opt/daybook/deploy/.env`. Minimum expected values:
|
||||
|
||||
```text
|
||||
DJANGO_DEBUG=0
|
||||
DJANGO_ALLOWED_HOSTS=192.168.1.36,localhost,127.0.0.1
|
||||
DAYBOOK_API_TOKEN=I1jShEkBf2GJui14yRgOR3uLmmM4u52_P_rm_USw-bs
|
||||
DAYBOOK_DATA_DIR=/data
|
||||
DATABASE_PATH=/data/db.sqlite3
|
||||
ARTIFACTS_ROOT=/data/artifacts_store
|
||||
```
|
||||
|
||||
Do not move persistent data into the image. Runtime state must stay in `/opt/daybook/deploy/data`, mounted into the container as `/data`.
|
||||
|
||||
## Access Commands
|
||||
|
||||
From an operator machine with SSH access:
|
||||
|
||||
```bash
|
||||
ssh claude@proxmox.cygnus.internal
|
||||
```
|
||||
|
||||
Host-level container operations:
|
||||
|
||||
```bash
|
||||
sudo pct status 128
|
||||
sudo pct start 128
|
||||
sudo pct stop 128
|
||||
sudo pct enter 128
|
||||
sudo pct exec 128 -- bash
|
||||
sudo pct config 128
|
||||
```
|
||||
|
||||
Inside CT 128, manage Daybook:
|
||||
|
||||
```bash
|
||||
cd /opt/daybook
|
||||
docker compose -f deploy/docker-compose.yml ps
|
||||
docker compose -f deploy/docker-compose.yml logs -f daybook
|
||||
docker compose -f deploy/docker-compose.yml restart daybook
|
||||
docker compose -f deploy/docker-compose.yml down
|
||||
docker compose -f deploy/docker-compose.yml up -d
|
||||
docker compose -f deploy/docker-compose.yml up -d --build
|
||||
docker compose -f deploy/docker-compose.yml exec daybook python manage.py check
|
||||
```
|
||||
|
||||
Host one-liners without entering the CT:
|
||||
|
||||
```bash
|
||||
sudo pct exec 128 -- bash -lc 'cd /opt/daybook && docker compose -f deploy/docker-compose.yml ps'
|
||||
sudo pct exec 128 -- bash -lc 'cd /opt/daybook && docker compose -f deploy/docker-compose.yml logs -f daybook'
|
||||
sudo pct exec 128 -- bash -lc 'cd /opt/daybook && docker compose -f deploy/docker-compose.yml up -d --build'
|
||||
```
|
||||
|
||||
## Health Checks
|
||||
|
||||
From any machine that can reach the LAN:
|
||||
|
||||
```bash
|
||||
curl -fsS http://192.168.1.36:8000/api/capabilities
|
||||
```
|
||||
|
||||
Expected response includes:
|
||||
|
||||
```json
|
||||
{
|
||||
"artifact_kinds": ["html_fragment", "html_full", "markdown", "deck", "image", "pdf", "binary"],
|
||||
"filters": ["persona", "day", "tag", "kind", "q"],
|
||||
"views": ["rendered", "raw"],
|
||||
"raw_supported_for": ["markdown", "html_full"],
|
||||
"source_types": ["agent", "person", "system"],
|
||||
"auth": "bearer_token"
|
||||
}
|
||||
```
|
||||
|
||||
Host-level checks:
|
||||
|
||||
```bash
|
||||
sudo pct status 128
|
||||
sudo pct exec 128 -- bash -lc 'cd /opt/daybook && docker compose -f deploy/docker-compose.yml ps'
|
||||
sudo pct exec 128 -- bash -lc 'test -f /opt/daybook/deploy/data/db.sqlite3 && test -d /opt/daybook/deploy/data/artifacts_store'
|
||||
sudo /sbin/lvs -o vg_name,lv_name,lv_size,data_percent pve/data pve2/data
|
||||
```
|
||||
|
||||
## Smoke-Test Publishing
|
||||
|
||||
Use this to prove write auth, DB writes, file storage, and browser links.
|
||||
|
||||
```bash
|
||||
curl -fsS -X POST http://192.168.1.36:8000/api/artifacts \
|
||||
-H "Authorization: Bearer I1jShEkBf2GJui14yRgOR3uLmmM4u52_P_rm_USw-bs" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"persona": "deploy-smoke",
|
||||
"source_type": "agent",
|
||||
"source_name": "Deployment Smoke Agent",
|
||||
"kind": "markdown",
|
||||
"theme": "report",
|
||||
"title": "Deployment Smoke Test",
|
||||
"content": "# Deployment Smoke Test\n\nDaybook accepted an artifact.",
|
||||
"tags": ["deploy", "smoke"],
|
||||
"metadata": {"run_id": "deploy-smoke-001"}
|
||||
}'
|
||||
```
|
||||
|
||||
The response should include `id`, `url`, `api_url`, and `raw_url`. Open the returned `url` or refresh `http://192.168.1.36:8000/`.
|
||||
|
||||
## Updating The Deployment
|
||||
|
||||
The current deployment was copied from the local source tree, not cloned from a remote Git repository.
|
||||
|
||||
Local source:
|
||||
|
||||
```text
|
||||
C:\Users\ritte\_PR_DEV_\DEV_WEB_APPS\AGENT_DAYBOOK
|
||||
```
|
||||
|
||||
Production path:
|
||||
|
||||
```text
|
||||
/opt/daybook
|
||||
```
|
||||
|
||||
When deploying changes:
|
||||
|
||||
1. Preserve `/opt/daybook/deploy/.env`.
|
||||
2. Preserve `/opt/daybook/deploy/data`.
|
||||
3. Copy application source and deploy files to `/opt/daybook`.
|
||||
4. Exclude local dev artifacts such as `.venv`, local `db.sqlite3`, local `artifacts_store`, logs, and caches.
|
||||
5. Rebuild with `docker compose -f deploy/docker-compose.yml up -d --build`.
|
||||
6. Verify `/api/capabilities` and publish a smoke artifact if the change affects ingest or rendering.
|
||||
|
||||
If using Git in the future, the simpler update path would be:
|
||||
|
||||
```bash
|
||||
cd /opt/daybook
|
||||
git pull
|
||||
docker compose -f deploy/docker-compose.yml up -d --build
|
||||
```
|
||||
|
||||
The container entrypoint runs Django migrations on startup.
|
||||
|
||||
## Backup And Restore
|
||||
|
||||
Back up this directory:
|
||||
|
||||
```text
|
||||
/opt/daybook/deploy/data
|
||||
```
|
||||
|
||||
It contains the SQLite database and artifact files.
|
||||
|
||||
Quick backup from the Proxmox host:
|
||||
|
||||
```bash
|
||||
sudo pct exec 128 -- bash -lc 'tar -czf /tmp/daybook-data-$(date +%Y%m%d-%H%M%S).tar.gz -C /opt/daybook/deploy data'
|
||||
```
|
||||
|
||||
Consistent backup during heavy writes:
|
||||
|
||||
```bash
|
||||
sudo pct exec 128 -- bash -lc 'cd /opt/daybook && docker compose -f deploy/docker-compose.yml down'
|
||||
sudo pct exec 128 -- bash -lc 'tar -czf /tmp/daybook-data-$(date +%Y%m%d-%H%M%S).tar.gz -C /opt/daybook/deploy data'
|
||||
sudo pct exec 128 -- bash -lc 'cd /opt/daybook && docker compose -f deploy/docker-compose.yml up -d'
|
||||
```
|
||||
|
||||
Restore process:
|
||||
|
||||
1. Stop Daybook with `docker compose -f /opt/daybook/deploy/docker-compose.yml down` inside CT 128.
|
||||
2. Replace `/opt/daybook/deploy/data` with restored data.
|
||||
3. Start with `docker compose -f /opt/daybook/deploy/docker-compose.yml up -d`.
|
||||
4. Verify capabilities and open the feed.
|
||||
|
||||
## API Contract For Agents
|
||||
|
||||
Base URL:
|
||||
|
||||
```text
|
||||
http://192.168.1.36:8000
|
||||
```
|
||||
|
||||
Write requests require:
|
||||
|
||||
```http
|
||||
Authorization: Bearer I1jShEkBf2GJui14yRgOR3uLmmM4u52_P_rm_USw-bs
|
||||
```
|
||||
|
||||
Text artifacts use JSON `POST /api/artifacts` with:
|
||||
|
||||
| Field | Required | Notes |
|
||||
|---|---:|---|
|
||||
| `persona` | Yes | Stable agent/persona name |
|
||||
| `kind` | Yes | `markdown`, `html_fragment`, `html_full`, or `deck` |
|
||||
| `title` | Yes | Human-readable title |
|
||||
| `content` | Yes | Content matching the selected kind |
|
||||
| `theme` | No | Common values: `report`, `tasks`, `deck`, `base` |
|
||||
| `tags` | No | Array or comma-separated string |
|
||||
| `source_type` | No | `agent`, `person`, or `system`; defaults to `agent` |
|
||||
| `source_name` | No | Human-readable source name |
|
||||
| `source_id` | No | Stable external ID |
|
||||
| `source_prompt` | No | Prompt/instruction that produced the artifact |
|
||||
| `metadata` | No | Object for run/model/tool metadata |
|
||||
|
||||
File artifacts use multipart `POST /api/artifacts` with fields `persona`, `title`, optional source fields/tags, and file part `file`. Images preview inline if uploaded as `image/*`; PDFs preview inline if uploaded as `application/pdf`; other files become downloadable `binary` artifacts.
|
||||
|
||||
Rendering rules:
|
||||
|
||||
| Kind | Send |
|
||||
|---|---|
|
||||
| `markdown` | Markdown text |
|
||||
| `html_fragment` | Body-only HTML; no `html`, `head`, or `body` tags |
|
||||
| `html_full` | Complete HTML document |
|
||||
| `deck` | One or more top-level `<section>...</section>` slide blocks |
|
||||
|
||||
## Known Open Issues
|
||||
|
||||
These matter for the next deployment/development agent.
|
||||
|
||||
| ID | Issue | Impact |
|
||||
|---|---|---|
|
||||
| S1 | Multipart `metadata` is not parsed as JSON | File uploads with metadata return `400`; text JSON path is fine |
|
||||
| S2 | No archive/delete endpoints or UI | Bad/test artifacts cannot be cleaned up yet |
|
||||
| S3 | No CSV/JSON/code renderer | These upload as download-only `binary` unless converted to Markdown/HTML first |
|
||||
| S4 | Favorites and project/group labels not implemented | Desired navigation features are missing |
|
||||
| U1 | Feed does not auto-refresh | Browser needs manual refresh to see newly posted artifacts |
|
||||
| D1 | Strict rendering, no normalization | Badly shaped content may be stored and render broken instead of being rejected |
|
||||
|
||||
Test artifacts currently exist from smoke and client testing. Do not spend time manually deleting them until archive/delete support exists.
|
||||
|
||||
## Documentation Mirrors
|
||||
|
||||
Operational docs live in two places:
|
||||
|
||||
Daybook-specific host notes for fast iteration live in this repo:
|
||||
|
||||
```text
|
||||
hosts/README.md
|
||||
hosts/nuc-daybook.md
|
||||
hosts/cloud-template.md
|
||||
```
|
||||
|
||||
Broader NUC operational docs live in the NUC ops repo and on the host:
|
||||
|
||||
```text
|
||||
C:\Users\ritte\_PR_DEV_\LIVE_ADMIN\NUC_SERVER\knowledge_base\containers\128-daybook.md
|
||||
C:\Users\ritte\_PR_DEV_\LIVE_ADMIN\NUC_SERVER\knowledge_base\daybook\api.md
|
||||
C:\Users\ritte\_PR_DEV_\LIVE_ADMIN\NUC_SERVER\knowledge_base\daybook\agent-posting.md
|
||||
/home/claude/knowledge_base/containers/128-daybook.md
|
||||
```
|
||||
|
||||
When changing deployment, update the NUC knowledge base too. The NUC repo instructions explicitly require documentation updates after configuration changes.
|
||||
|
||||
## Takeover Checklist
|
||||
|
||||
Before making changes:
|
||||
|
||||
1. SSH to the NUC host.
|
||||
2. Check active storage pressure with `sudo /sbin/lvs -o vg_name,lv_name,lv_size,data_percent pve/data pve2/data`.
|
||||
3. Check CT 128 with `sudo pct status 128` and `sudo pct config 128`.
|
||||
4. Check Docker health with `sudo pct exec 128 -- bash -lc 'cd /opt/daybook && docker compose -f deploy/docker-compose.yml ps'`.
|
||||
5. Check API health with `curl -fsS http://192.168.1.36:8000/api/capabilities`.
|
||||
6. Read the current local issue log: `planning/daybook-issues-log.md`.
|
||||
7. Preserve `.env` and `deploy/data` before copying or rebuilding.
|
||||
8. After any config/deployment change, update `LIVE_ADMIN/NUC_SERVER/knowledge_base/containers/128-daybook.md` and this handoff if the takeover facts changed.
|
||||
|
|
@ -1,5 +1,18 @@
|
|||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"instructions": ["AGENTS.md"],
|
||||
"permission": "allow"
|
||||
"instructions": ["CLAUDE.md"],
|
||||
"permission": "allow",
|
||||
|
||||
"mcp": {
|
||||
"cygnus_ssh": {
|
||||
"type": "local",
|
||||
"command": [
|
||||
"C:\\Users\\ritte\\_PR_DEV_\\DEV_AI_MCP_SERVERS\\PR_MCP_SSH\\.venv\\Scripts\\python.exe",
|
||||
"C:\\Users\\ritte\\_PR_DEV_\\DEV_AI_MCP_SERVERS\\PR_MCP_SSH\\mcp_ssh_server.py",
|
||||
"--config",
|
||||
"C:\\Users\\ritte\\.mcp_ssh_hosts.toml"
|
||||
],
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -204,6 +204,7 @@ index over them, not the source of truth for content.
|
|||
- Webhooks or "latest artifact" endpoints for chaining agents.
|
||||
- Retention/archival policies per persona.
|
||||
- Multi-user reader auth with per-persona visibility.
|
||||
- **Interactive questions artifact type:** agents send JSON with multiple-choice questions; viewer renders an interactive form; user selections are sent back to the agent via message queue, email, or API callback. Use cases: agent feedback loops, preference gathering, approval workflows.
|
||||
|
||||
## Open questions / decisions
|
||||
|
||||
|
|
|
|||
BIN
planning/light_theme.png
Normal file
BIN
planning/light_theme.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 709 KiB |
Loading…
Add table
Add a link
Reference in a new issue