chore: bootstrap projax scaffolding + PRD
Copy the design PRD, .claude config, .m config, .mcp.json, and AGENTS.md symlink from m's main working tree so the worker has the full project context before starting Phase 1 implementation.
This commit is contained in:
16
.claude/CLAUDE.md
Normal file
16
.claude/CLAUDE.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# projax Project Instructions
|
||||
|
||||
<!-- Add your project-specific instructions for AI tools here -->
|
||||
<!-- This file is used by Claude Code, Cursor, Windsurf, and other AI assistants -->
|
||||
|
||||
## Project Overview
|
||||
|
||||
Describe your project here.
|
||||
|
||||
## Code Style & Conventions
|
||||
|
||||
Document your coding conventions.
|
||||
|
||||
## Architecture
|
||||
|
||||
Describe key architectural decisions.
|
||||
14
.claude/agents/coder.md
Normal file
14
.claude/agents/coder.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Coder Agent
|
||||
|
||||
Implementation-focused agent for writing and refactoring code.
|
||||
|
||||
## Instructions
|
||||
|
||||
- Follow existing patterns in the codebase
|
||||
- Write minimal, focused code
|
||||
- Run tests after changes
|
||||
- Commit incrementally with descriptive messages
|
||||
|
||||
## Tools
|
||||
|
||||
All tools available.
|
||||
14
.claude/agents/researcher.md
Normal file
14
.claude/agents/researcher.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Researcher Agent
|
||||
|
||||
Exploration and information gathering agent.
|
||||
|
||||
## Instructions
|
||||
|
||||
- Search broadly, then narrow down
|
||||
- Document findings in structured format
|
||||
- Cite sources and file paths
|
||||
- Summarize key insights, don't dump raw data
|
||||
|
||||
## Tools
|
||||
|
||||
Read-only tools preferred. Use Bash only for non-destructive commands.
|
||||
14
.claude/agents/reviewer.md
Normal file
14
.claude/agents/reviewer.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Reviewer Agent
|
||||
|
||||
Code review agent for checking quality and correctness.
|
||||
|
||||
## Instructions
|
||||
|
||||
- Check for bugs, security issues, and style violations
|
||||
- Verify test coverage for changes
|
||||
- Suggest improvements concisely
|
||||
- Focus on correctness over style preferences
|
||||
|
||||
## Tools
|
||||
|
||||
Read-only tools. No file modifications.
|
||||
1
.claude/skills/mai-clone
Symbolic link
1
.claude/skills/mai-clone
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-clone
|
||||
1
.claude/skills/mai-coder
Symbolic link
1
.claude/skills/mai-coder
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-coder
|
||||
1
.claude/skills/mai-commit
Symbolic link
1
.claude/skills/mai-commit
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-commit
|
||||
1
.claude/skills/mai-consultant
Symbolic link
1
.claude/skills/mai-consultant
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-consultant
|
||||
1
.claude/skills/mai-debrief
Symbolic link
1
.claude/skills/mai-debrief
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-debrief
|
||||
1
.claude/skills/mai-enemy
Symbolic link
1
.claude/skills/mai-enemy
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-enemy
|
||||
1
.claude/skills/mai-excalidraw
Symbolic link
1
.claude/skills/mai-excalidraw
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-excalidraw
|
||||
1
.claude/skills/mai-fixer
Symbolic link
1
.claude/skills/mai-fixer
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-fixer
|
||||
1
.claude/skills/mai-gitster
Symbolic link
1
.claude/skills/mai-gitster
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-gitster
|
||||
1
.claude/skills/mai-head
Symbolic link
1
.claude/skills/mai-head
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-head
|
||||
1
.claude/skills/mai-init
Symbolic link
1
.claude/skills/mai-init
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-init
|
||||
1
.claude/skills/mai-inventor
Symbolic link
1
.claude/skills/mai-inventor
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-inventor
|
||||
1
.claude/skills/mai-lead
Symbolic link
1
.claude/skills/mai-lead
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-lead
|
||||
1
.claude/skills/mai-maister
Symbolic link
1
.claude/skills/mai-maister
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-maister
|
||||
1
.claude/skills/mai-member
Symbolic link
1
.claude/skills/mai-member
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-member
|
||||
1
.claude/skills/mai-researcher
Symbolic link
1
.claude/skills/mai-researcher
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-researcher
|
||||
1
.claude/skills/mai-think
Symbolic link
1
.claude/skills/mai-think
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-think
|
||||
1
.claude/skills/mai-web
Symbolic link
1
.claude/skills/mai-web
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/m/.mai/skills/mai-web
|
||||
4
.m/.gitignore
vendored
Normal file
4
.m/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
workers.json
|
||||
spawn.lock
|
||||
session.yaml
|
||||
config.reference.yaml
|
||||
171
.m/config.yaml
Normal file
171
.m/config.yaml
Normal file
@@ -0,0 +1,171 @@
|
||||
# Project-specific mai configuration
|
||||
# Auto-generated by 'mai init' — run 'mai setup' to customize
|
||||
|
||||
provider: claude
|
||||
providers:
|
||||
claude:
|
||||
api_key: ""
|
||||
model: claude-sonnet-4-20250514
|
||||
base_url: https://api.anthropic.com/v1
|
||||
ollama:
|
||||
host: http://localhost:11434
|
||||
model: llama3.2
|
||||
memory:
|
||||
enabled: true
|
||||
backend: ""
|
||||
path: ""
|
||||
url: postgres://mai_memory.your-tenant-id:maiMem6034supa@100.99.98.201:6543/postgres?sslmode=disable
|
||||
group_id: ""
|
||||
cache_ttl: 5m0s
|
||||
auto_load: true
|
||||
embedding_url: ""
|
||||
embedding_model: ""
|
||||
gitea:
|
||||
url: https://mgit.msbls.de
|
||||
repo: m/projax
|
||||
token: ""
|
||||
sync:
|
||||
enabled: false
|
||||
interval: 0s
|
||||
repos: []
|
||||
auto_queue: false
|
||||
api:
|
||||
api_key: ""
|
||||
basic_auth:
|
||||
username: ""
|
||||
password: ""
|
||||
public_endpoints:
|
||||
- /api/health
|
||||
ui:
|
||||
theme: default
|
||||
show_sidebar: true
|
||||
animation: true
|
||||
persona: true
|
||||
avatar_pack: ""
|
||||
worker:
|
||||
names: []
|
||||
name_scheme: role
|
||||
default_level: standard
|
||||
auto_discard: false
|
||||
max_workers: 5
|
||||
persistent: true
|
||||
head:
|
||||
name: ""
|
||||
capacity:
|
||||
global:
|
||||
max_workers: 5
|
||||
max_heads: 3
|
||||
per_worker:
|
||||
max_tasks_lifetime: 0
|
||||
max_concurrent: 1
|
||||
max_context_tokens: 0
|
||||
per_head:
|
||||
max_workers: 10
|
||||
resources:
|
||||
max_memory_mb: 0
|
||||
max_cpu_percent: 0
|
||||
queue:
|
||||
max_pending: 100
|
||||
stale_task_days: 30
|
||||
workforce:
|
||||
timeouts:
|
||||
task_default: 0s
|
||||
task_max: 0s
|
||||
idle_before_warn: 10m0s
|
||||
idle_before_kill: 30m0s
|
||||
quality_check: 2m0s
|
||||
context:
|
||||
max_tokens_per_worker: 0
|
||||
max_tokens_global: 0
|
||||
warn_threshold: 0.8
|
||||
truncate_strategy: oldest
|
||||
delegation:
|
||||
strategy: skill_match
|
||||
preferred_role: coder
|
||||
auto_delegate: false
|
||||
max_depth: 3
|
||||
allowed_roles:
|
||||
- coder
|
||||
- researcher
|
||||
- fixer
|
||||
peppy:
|
||||
enabled: false
|
||||
style: calm
|
||||
interval: 5m0s
|
||||
emoji: false
|
||||
nudges: true
|
||||
nudge_main: false
|
||||
custom_prompt: ""
|
||||
stall_threshold: 0s
|
||||
restart_enabled: false
|
||||
max_shifts: 0
|
||||
crash_detection: false
|
||||
max_crash_retries: 0
|
||||
quality_gates:
|
||||
enabled: true
|
||||
checks: []
|
||||
preflight:
|
||||
enabled: false
|
||||
type: ""
|
||||
root: ""
|
||||
checks: []
|
||||
guardrails:
|
||||
enabled: false
|
||||
use_defaults: true
|
||||
output:
|
||||
coder_checks: []
|
||||
researcher_checks: []
|
||||
fixer_checks: []
|
||||
custom_checks: {}
|
||||
global_checks: []
|
||||
tools:
|
||||
role_rules: {}
|
||||
deny_patterns: []
|
||||
allow_patterns: []
|
||||
schemas:
|
||||
report_schemas: {}
|
||||
deliverable_schemas: {}
|
||||
modes:
|
||||
yolo: false
|
||||
self_improvement: false
|
||||
autonomous: false
|
||||
verbose: false
|
||||
improve_interval: 0s
|
||||
predict_interval: 0s
|
||||
layouts:
|
||||
head: ""
|
||||
worker: ""
|
||||
roles: {}
|
||||
dog:
|
||||
name: buddy
|
||||
supabase:
|
||||
url: ""
|
||||
role_key: ""
|
||||
anon_key: ""
|
||||
schema: mai
|
||||
storage:
|
||||
backend: ""
|
||||
postgres:
|
||||
url: ""
|
||||
max_conns: 0
|
||||
min_conns: 0
|
||||
max_conn_lifetime: 0s
|
||||
idle:
|
||||
behavior: wait
|
||||
auto_hire: false
|
||||
prompt: ""
|
||||
git:
|
||||
worktrees:
|
||||
enabled: true
|
||||
delete_branch: false
|
||||
dir: .worktrees
|
||||
phase:
|
||||
enabled: false
|
||||
current: ""
|
||||
allowed_roles: {}
|
||||
goal: ""
|
||||
skills: {}
|
||||
editor: nvim
|
||||
log_level: info
|
||||
project_detection: true
|
||||
tone: professional
|
||||
11
.mcp.json
Normal file
11
.mcp.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"supabase": {
|
||||
"type": "http",
|
||||
"url": "http://100.99.98.201:8000/mcp",
|
||||
"headers": {
|
||||
"Authorization": "Basic ${SUPABASE_AUTH}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
250
docs/design.md
Normal file
250
docs/design.md
Normal file
@@ -0,0 +1,250 @@
|
||||
# projax — PRD
|
||||
|
||||
**Status:** v1 draft, 2026-05-15
|
||||
**Authors:** m, head (dialogue)
|
||||
**Scope:** Phase-1 build sufficient to live with the system; phases 2–3 listed but deferred.
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
projax is m's personal data backbone for self-management — areas of life, projects within them, and aggregated views over tasks that live elsewhere. It subsumes (over time) the scattered state currently held in `mai.projects`, CalDAV task lists, Gitea issues, and mBrian topic hubs. No interface is canonical; each is a view.
|
||||
|
||||
**Meta-requirement: flexibility.** m's self-model evolves. Identity is by UUID; everything human-readable is renameable. The data model leans on jsonb + array-typed kinds so future re-categorization doesn't require a migration.
|
||||
|
||||
## 2. Model
|
||||
|
||||
### 2.1 Two kinds, freely nestable
|
||||
|
||||
```
|
||||
area ─┐
|
||||
├─ project ─┐
|
||||
│ ├─ project ─┐ (sub-projects allowed, any depth)
|
||||
│ │ └─ …
|
||||
└─ task (external ref)
|
||||
```
|
||||
|
||||
- **Area** — a container without start/end. Long-running domain of life. Areas live at the root (`parent_id = NULL`). Examples: `dev`, `sports`, `home`, `work`, `health`, `finances`, `social`.
|
||||
- **Project** — a bounded effort with (usually) a start and an end. Lives under an area, or under another project. Sub-projects nest to arbitrary depth (`home.spring-clean.bathroom.tiles` is fine if that's how m thinks). Examples: `home.spring-clean`, `dev.prjx`, `sports.giro-okt`.
|
||||
- **Task** — atomic work item. **Lives outside projax** (CalDAV todos, Gitea issues, `mai.tasks`). projax references and aggregates them; it does not own them.
|
||||
|
||||
Areas and projects share one table (`projax.items`) distinguished by the `kind` array column. The tree (`parent_id`) is unconstrained on depth; the only structural rules are:
|
||||
|
||||
- An area's `parent_id` must be `NULL` (areas are roots).
|
||||
- A project's `parent_id` must point to an area or another project (no project at root).
|
||||
- No cycles (enforced by the path trigger).
|
||||
|
||||
Tasks are referenced via `projax.item_links`.
|
||||
|
||||
### 2.2 Identity & naming
|
||||
|
||||
- `id uuid` — canonical, immutable.
|
||||
- `slug text` — local-only segment (no dots). Renameable freely. Examples: `prjx`, `spring-clean`, `upc.deadlines` would be split as parent slug `upc` + child slug `deadlines`.
|
||||
- `path text` — full dot-joined path computed from parent walk. Cached column maintained by trigger; not the source of truth.
|
||||
- Slug convention: lowercase, vowel-elided where natural (`prjx`, `mai`, `mbrn` if m wishes), kebab-allowed for multi-word leaves (`spring-clean`).
|
||||
- Aliases: `aliases text[]` keeps old slugs searchable after rename.
|
||||
|
||||
### 2.3 Lifecycle (thin)
|
||||
|
||||
For projects only — areas don't have lifecycle.
|
||||
|
||||
```
|
||||
active → done → archived
|
||||
```
|
||||
|
||||
That's it. Free-text in `content_md` covers the nuance ("waiting on Brian," "paused until June"). No rich state machine; m flagged richer schemes as rot-prone.
|
||||
|
||||
### 2.4 Relationships
|
||||
|
||||
- **Tree** (parent/child within projax): `items.parent_id uuid` self-FK. Areas have `parent_id = NULL`. Projects point at their area or another project. Arbitrary nesting depth.
|
||||
- **External refs** (`projax.item_links`): each row links an `item_id` to a typed external resource — caldav-todo, gitea-issue, mai-task, mai-project, mbrian-node, etc. Used both for aggregating tasks and for soft cross-references.
|
||||
|
||||
## 3. Schema (Postgres, msupabase, schema `projax`)
|
||||
|
||||
```sql
|
||||
create schema if not exists projax;
|
||||
|
||||
create table projax.items (
|
||||
id uuid primary key default gen_random_uuid(),
|
||||
kind text[] not null default '{}', -- ['area'] or ['project'] (multi-tag allowed for future)
|
||||
title text not null,
|
||||
slug text not null, -- local segment, no dots
|
||||
path text not null, -- computed, e.g. 'home.spring-clean'
|
||||
parent_id uuid references projax.items(id) on delete restrict,
|
||||
content_md text default '',
|
||||
aliases text[] default '{}',
|
||||
metadata jsonb not null default '{}'::jsonb,
|
||||
status text not null default 'active', -- active | done | archived (projects only)
|
||||
pinned boolean not null default false,
|
||||
archived boolean not null default false,
|
||||
start_time timestamptz,
|
||||
end_time timestamptz,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now(),
|
||||
deleted_at timestamptz,
|
||||
unique (parent_id, slug)
|
||||
);
|
||||
|
||||
create index items_path_idx on projax.items (path);
|
||||
create index items_kind_idx on projax.items using gin (kind);
|
||||
create index items_parent_idx on projax.items (parent_id);
|
||||
|
||||
create table projax.item_links (
|
||||
id uuid primary key default gen_random_uuid(),
|
||||
item_id uuid not null references projax.items(id) on delete cascade,
|
||||
ref_type text not null, -- 'caldav-todo' | 'gitea-issue' | 'mai-task' | 'mai-project' | 'mbrian-node' | 'url' | ...
|
||||
ref_id text not null, -- opaque external identifier
|
||||
rel text not null default 'contains', -- 'contains' | 'related' | 'blocked-by' | 'derived-from'
|
||||
note text,
|
||||
metadata jsonb not null default '{}'::jsonb,
|
||||
created_at timestamptz not null default now(),
|
||||
unique (item_id, ref_type, ref_id, rel)
|
||||
);
|
||||
|
||||
create index item_links_item_idx on projax.item_links (item_id);
|
||||
create index item_links_ref_idx on projax.item_links (ref_type, ref_id);
|
||||
```
|
||||
|
||||
### 3.1 The `path` trigger
|
||||
|
||||
`path` is maintained by trigger on insert/update: walks `parent_id` to the root, joins slugs with `.`. Recomputed for the subtree when a parent is renamed or re-parented. Keeps queries cheap.
|
||||
|
||||
### 3.2 The mai.projects adapter view
|
||||
|
||||
mai.projects stays untouched. projax surfaces it in the unified item stream via a read-only view:
|
||||
|
||||
```sql
|
||||
create or replace view projax.items_unified as
|
||||
select
|
||||
id,
|
||||
kind,
|
||||
title,
|
||||
slug,
|
||||
path,
|
||||
parent_id,
|
||||
content_md,
|
||||
status,
|
||||
pinned,
|
||||
archived,
|
||||
start_time,
|
||||
end_time,
|
||||
'projax'::text as source,
|
||||
created_at,
|
||||
updated_at
|
||||
from projax.items
|
||||
where deleted_at is null
|
||||
|
||||
union all
|
||||
|
||||
select
|
||||
('00000000-0000-0000-0000-' || substr(md5(p.id), 1, 12))::uuid as id, -- deterministic placeholder
|
||||
array['project']::text[] as kind,
|
||||
p.name as title,
|
||||
p.id as slug,
|
||||
'mai.' || p.id as path,
|
||||
null::uuid as parent_id,
|
||||
coalesce(p.goal, '') as content_md,
|
||||
case p.status
|
||||
when 'active' then 'active'
|
||||
when 'sleeping' then 'archived'
|
||||
when 'archived' then 'archived'
|
||||
else 'active'
|
||||
end as status,
|
||||
false as pinned,
|
||||
(p.status = 'archived') as archived,
|
||||
null::timestamptz as start_time,
|
||||
null::timestamptz as end_time,
|
||||
'mai.projects'::text as source,
|
||||
p.created_at,
|
||||
p.updated_at
|
||||
from mai.projects p;
|
||||
```
|
||||
|
||||
UI reads `items_unified`. Writes target `projax.items` only. Once m wants to fully migrate, the `mai.projects` half is dropped from the view and rows are copied across with real UUIDs + proper parent assignment.
|
||||
|
||||
### 3.3 Classification overlay
|
||||
|
||||
For each mai.projects row, m can later promote it into projax-native (assigning area parent, real slug, kind tweak). Until promoted it appears as a top-level orphan project tagged `source=mai.projects`. An admin page surfaces the unmapped set and lets m one-click classify.
|
||||
|
||||
## 4. Interfaces
|
||||
|
||||
### 4.1 Phase 1 — MVP (this build)
|
||||
|
||||
**Web frontend at `https://projax.msbls.de`**, single binary, served by the same Go process that talks to msupabase.
|
||||
|
||||
Pages:
|
||||
|
||||
1. **Tree view** (`/`) — collapsible tree of areas → projects, reads `items_unified`. Status badges, search bar (slug, title, alias, content_md).
|
||||
2. **Item detail** (`/i/{path}`) — full editor for projax-native items (title, slug, parent, kind, status, start/end, content_md). Read-only view for mai.projects-sourced rows with a "Promote to projax" button.
|
||||
3. **New item** (`/new?parent={path}`) — small form, prefilled with parent.
|
||||
4. **Classify orphans** (`/admin/classify`) — list of unmapped mai.projects rows, inline assign-to-area control.
|
||||
|
||||
Auth: shared msupabase login (matches flexsiebels precedent), single-user m.
|
||||
|
||||
### 4.2 Phase 2 — task aggregation
|
||||
|
||||
- **CalDAV ingest** — read-only mirror of m's CalDAV todo lists into `item_links` with `ref_type=caldav-todo`. Per-area mapping (e.g. `home` aggregates from CalDAV list "Home"). Background sync, no writeback initially.
|
||||
- **Gitea ingest** — read-only mirror of issues on linked repos. `mai.projects.repo` field is a hint; per-item override possible.
|
||||
|
||||
### 4.3 Phase 3 — visualization & integrations
|
||||
|
||||
- **Excalidraw view** — visual roadmap, dependencies, area-overview boards. Generated from items_unified.
|
||||
- **MCP** — `mcp__projax__*` so otto and other workers can read/write projax. Pattern follows mcp__mai__.
|
||||
- **Otto-PWA integration** — read-mostly surface for m's day-to-day. Defer until projax has lived long enough to know what otto actually needs.
|
||||
|
||||
## 5. Tech stack
|
||||
|
||||
- **Backend**: Go single binary. `pgx` for Postgres. HTMX-driven HTML rendered server-side (Go `html/template`). No frontend build step. Static assets bundled with `embed`. Matches m's dotfile-stated preferences.
|
||||
- **Database**: msupabase, schema `projax` (new). View `projax.items_unified` reads across `projax.*` + `mai.projects`. RLS off for v1 (single-user).
|
||||
- **Hosting**: Dokploy on mlake, domain `projax.msbls.de`. Tailscale-only network (no public exposure).
|
||||
- **Repo**: `m/projax` (already exists). Branch strategy per project CLAUDE.md (main + short-lived feat/fix branches, no dev branch initially).
|
||||
|
||||
Alternative considered: SvelteKit + Bun (matches flexsiebels). Rejected for v1 — CRUD admin scale doesn't justify the build chain.
|
||||
|
||||
## 6. Migration plan
|
||||
|
||||
Three phases, smallest viable each:
|
||||
|
||||
**1a — Schema + seed**: create `projax.items`, `projax.item_links`, path trigger. Seed the seven day-one areas (`dev`, `sports`, `home`, `work`, `health`, `finances`, `social`) as `kind=['area']`, `parent_id=null`.
|
||||
|
||||
**1b — Adapter view**: deploy `items_unified`. All 28 mai.projects rows now visible in the tree as top-level orphans.
|
||||
|
||||
**1c — Classification UI**: the `/admin/classify` page so m can drag mai.projects rows under areas. Drag = create a projax-native item with `kind=['project']` + `parent_id` set + `item_links` row pointing at the mai.projects row. mai.projects untouched; the projax row owns area assignment + projax metadata.
|
||||
|
||||
After 1c, m can use the system. Test rows in mai.projects either stay as orphans (ignored) or get a `source-filter` to hide them.
|
||||
|
||||
## 7. Out of scope
|
||||
|
||||
- Multi-user (single-tenant, m only)
|
||||
- Mobile-first responsive (desktop browser is enough)
|
||||
- Public exposure (Tailscale only)
|
||||
- Generic SaaS instincts (admin panels, billing, audit logs)
|
||||
- CLI surface (m has explicitly opted out)
|
||||
- Bidirectional CalDAV/Gitea sync in v1 (read-only first)
|
||||
- Real-time collaboration features
|
||||
|
||||
## 8. Open questions (post-PRD)
|
||||
|
||||
- **Path-trigger correctness** under cycle attempts: enforce acyclicity via check in trigger.
|
||||
- **`mai.projects` test row hiding**: drop them from the view via name pattern, or surface them with a "test" tag?
|
||||
- **Classification promotion semantics**: when a mai.projects row is promoted, does the projax item replace it in the unified view, or do both still appear? Default: projax wins, view filters out adapted mai rows.
|
||||
- **Auth**: re-use flexsiebels Supabase auth, or simpler shared-secret cookie? msupabase auth is heavier than v1 needs.
|
||||
- **mBrian topic-hub linkage**: do we auto-suggest mbrian topic links when an item is created with a matching slug? Defer to phase 3.
|
||||
|
||||
## 9. Phase-1 deliverable checklist
|
||||
|
||||
- [ ] `projax.items` + `projax.item_links` migrations in `db/migrations/`
|
||||
- [ ] Path trigger + tests
|
||||
- [ ] `projax.items_unified` view
|
||||
- [ ] Go binary: HTTP server, pgx pool, html/template + HTMX, embed static
|
||||
- [ ] Pages: tree, detail, new, classify
|
||||
- [ ] Auth: msupabase session cookie OR shared-secret (decide in 1a)
|
||||
- [ ] Dockerfile + Dokploy config for `projax.msbls.de`
|
||||
- [ ] Seed migration for the seven day-one areas
|
||||
- [ ] README + run instructions
|
||||
|
||||
## 10. References
|
||||
|
||||
- Project CLAUDE.md (this repo) — purpose, constraints, gated worker flow
|
||||
- `~/.claude/CLAUDE.md` — global conventions (memory, channel routing, git strategy)
|
||||
- `mai.projects` schema (msupabase) — current state being adapted
|
||||
- mBrian `nodes`/`edges` schema — terminology source
|
||||
- otto session 2026-05-15 — inventory motivating this project
|
||||
Reference in New Issue
Block a user