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
|
## Project
|
||||||
|
|
||||||
|
|
@ -64,6 +64,6 @@ The core product principle is: agents publish content, not files. The server own
|
||||||
- Artifact view: `GET /a/{id}`
|
- Artifact view: `GET /a/{id}`
|
||||||
- Development token: `Authorization: Bearer dev-token`
|
- 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",
|
"$schema": "https://opencode.ai/config.json",
|
||||||
"instructions": ["AGENTS.md"],
|
"instructions": ["CLAUDE.md"],
|
||||||
"permission": "allow"
|
"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.
|
- Webhooks or "latest artifact" endpoints for chaining agents.
|
||||||
- Retention/archival policies per persona.
|
- Retention/archival policies per persona.
|
||||||
- Multi-user reader auth with per-persona visibility.
|
- 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
|
## 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