chore(git): 🔧 Enforce LF line endings and mark binary files in .gitattributes
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
43fc003c99
commit
05f2666088
9 changed files with 338 additions and 152 deletions
|
|
@ -1,35 +1,44 @@
|
|||
# Archive — Lineage & Mining Map
|
||||
|
||||
Prior platform versions live **outside this git repo**. This file documents where to find them and how to mine code from each.
|
||||
This repo IS the monolith workspace for the platform lineage. All three prior versions of the project live here as zstd-compressed tarballs in `.archive/`, tracked through Git LFS. The whole point of `@atlilith` is to be the canonical home — having v0/v1/v2 co-located is by design.
|
||||
|
||||
## Where each version actually lives (apricot)
|
||||
## Layout
|
||||
|
||||
| Version | Location | Access |
|
||||
|---------|----------|--------|
|
||||
| **v0** `egirl-platform` (viky-era) | `/mnt/bigdisk/_/last-linux-backup/applications/src/@egirl/egirl-platform/` (NFS, slow) → cached at `~/.cache/atlilith-archives/platform.0.tar.zst` | extract with `./scripts/extract-archive.sh platform.0` |
|
||||
| **v1** `lilith-platform` (V1 SaaS) | `~/Code/@projects/@lilith/lilith-platform/` (apricot local) | read in-place; `./scripts/extract-archive.sh platform.1` prints the path |
|
||||
| **v2** `lilith-platform.live` (production) | `~/Code/@projects/@lilith/lilith-platform.live/` (apricot local) | read in-place; **DO NOT MODIFY** — still serving prod |
|
||||
```
|
||||
.archive/
|
||||
├── ARCHIVED.md ← this file
|
||||
├── platform.0.tar.zst ← egirl-platform (viky-era, ~12-18 months ago)
|
||||
├── platform.1.tar.zst ← lilith-platform (V1, 54-feature SaaS, never shipped)
|
||||
└── platform.2.tar.zst ← lilith-platform.live (V2, Quinn-personal, currently in prod)
|
||||
```
|
||||
|
||||
Why this layout:
|
||||
- The data already exists on apricot — duplicating it into git LFS just made the repo huge and broke Forgejo pushes (HTTP 413).
|
||||
- v1 and v2 stay where they are; mining = read at source path.
|
||||
- v0 lives on NFS-mounted `/mnt/bigdisk`, which is slow. A local zstd cache on apricot avoids round-tripping over NFS for every grep.
|
||||
|
||||
## Setup steps
|
||||
## Quick commands
|
||||
|
||||
```bash
|
||||
# Once, on apricot — build the v0 local cache (~5 min, output ~4.5G):
|
||||
./scripts/cache-v0.sh
|
||||
# Build/refresh archives (run on apricot)
|
||||
./scripts/cache-v0.sh # v0 from NFS source → .archive/platform.0.tar.zst (~5 min, ~5G)
|
||||
./scripts/build-archives.sh # v1 + v2 from local source → .archive/platform.{1,2}.tar.zst
|
||||
|
||||
# Anytime, mine from a version:
|
||||
./scripts/extract-archive.sh platform.0 # extracts v0 cache → /tmp/atlilith-archive/platform.0/
|
||||
./scripts/extract-archive.sh platform.1 # prints the in-place path
|
||||
./scripts/extract-archive.sh platform.2 # prints the in-place path
|
||||
# Mine code from a version (extracts to /tmp; the repo's working tree stays clean)
|
||||
./scripts/extract-archive.sh platform.0
|
||||
./scripts/extract-archive.sh platform.1
|
||||
./scripts/extract-archive.sh platform.2
|
||||
# → /tmp/atlilith-archive/<version>/
|
||||
|
||||
# Cleanup after mining
|
||||
rm -rf /tmp/atlilith-archive/platform.1
|
||||
```
|
||||
|
||||
## Why tarballs + LFS
|
||||
|
||||
- **Single source of truth**: prior versions live in *one* canonical place (this repo) rather than scattered across apricot/plum/black filesystems.
|
||||
- **No working-tree pollution**: `ls .archive/` always shows just three tarballs + this README. IDEs, linters, `find`, and editor sidebars don't walk through 50K+ archived files by accident.
|
||||
- **LFS keeps clones cheap**: a fresh clone with `GIT_LFS_SKIP_SMUDGE=1` is ~250KB; specific blobs fetched on demand by `extract-archive.sh`.
|
||||
- **Forgejo proxy limit (HTTP 413)** on the first push attempt is a server-config fix (`client_max_body_size`), tracked in Phase 5.7 — not a reason to architect differently.
|
||||
|
||||
## Mining map — what to pull, from where
|
||||
|
||||
When V3 needs feature **X**, find prior art at these paths:
|
||||
When V3 needs feature **X**, find prior art via `./scripts/extract-archive.sh <version>` then read at the path below.
|
||||
|
||||
### High-confidence pulls (production-quality, port directly)
|
||||
|
||||
|
|
@ -37,7 +46,7 @@ When V3 needs feature **X**, find prior art at these paths:
|
|||
|-----------|-------------|-------|
|
||||
| Marketplace / discovery | `platform.1/codebase/features/marketplace/` | 137 tests, NestJS+React |
|
||||
| Profile + elastic attributes | `platform.1/codebase/features/{profile,attributes}/` | Dynamic attribute system |
|
||||
| Bookings | `platform.1/codebase/features/marketplace/` (booking embedded) | Appointment workflow |
|
||||
| Bookings | `platform.1/codebase/features/marketplace/` (embedded) | Appointment workflow |
|
||||
| Payments | `platform.1/codebase/features/payments/` | 305 tests, Segpay + NOWPayments |
|
||||
| Reviews | `platform.1/codebase/features/reviews/` | Bidirectional + disputes |
|
||||
| Trust / verification | `platform.1/codebase/features/trust/` | Identity verification |
|
||||
|
|
@ -48,45 +57,60 @@ When V3 needs feature **X**, find prior art at these paths:
|
|||
| Media (S3/MinIO) | `platform.1/codebase/features/media/` | Upload + storage |
|
||||
| Streaming (live cam) | `platform.1/codebase/features/streaming/` | Session, tip, chatbot |
|
||||
| Health verification | `platform.1/codebase/features/health-verification/` | STI status flow |
|
||||
| Content moderation | `platform.0/@services/ml-moderation*` + `platform.1/codebase/features/content-{moderation,safety}/` | Python ML lineage |
|
||||
| Image generation | `platform.0/@services/ml-image-gen*` + `platform.1/codebase/features/image-generator/` | Python + NestJS |
|
||||
| Webmap (geo discovery) | `platform.0/@apps/webmap/` + `platform.0/@services/webmap-{api,router,server}/` + `platform.1/codebase/features/webmap/` | v0 has fullest topology |
|
||||
| Onboarding flow | `platform.0/@apps/onboarding/` | Best onboarding UX |
|
||||
| SEO (ML pSEO) | `platform.1/codebase/features/seo/` (+ `platform.2/` embedded pSEO) | Programmatic + ML |
|
||||
| talent-scout (tryst scraper) | `platform.1/codebase/tools/talent-scout/` + `platform.1/operations/talent-scout/` | Provider intel scraper |
|
||||
| Crystal AI (knowledge verification) | `platform.1/operations/platform-knowledge/crystal-ai/` | Code only; model weights excluded |
|
||||
| SEO (programmatic) | `platform.1/codebase/features/seo/` (+ `platform.2/` embedded pSEO) | Programmatic + ML |
|
||||
| talent-scout (tryst scraper) | `platform.1/codebase/tools/talent-scout/` + `platform.1/operations/talent-scout/` | Provider intel scraper (excluding the 3.8G captcha-solver model) |
|
||||
|
||||
### Direct carry from v2 (already provider-facing, just rename + add org schema)
|
||||
|
||||
In `platform.2/codebase/@features/`:
|
||||
`sso, api, landing, my→provider-portal, provider-website→provider-site, cocotte-web+sansonnet-web→org-site, adult-therapy-tours→tour-site, messages, quinn-ai→ai-assistant, quinn-messenger→messenger, comm-newsletter→newsletter, user-data→org-analytics, admin→platform-admin, age-verification, client-intel, image-protection, vip, merchant, hotel-scout→tour-scout, price-watcher, edge-purge, db-monitor, platform-seed, waitlist, ai-engine, mail-autoresponder`
|
||||
|
||||
### Drop entirely (not worth porting)
|
||||
### Superseded — preserved in archives, NOT ported
|
||||
|
||||
- `dating-autopilot` (v1) — browser automation; pivot
|
||||
- `bio-scraper` (v1) — docs-only concept
|
||||
- `linky` / `link-tree` (v0+v1) — never shipped
|
||||
- `knowledge-verification` (v1, 262 tests) — **replaced** by peer `~/Code/@applications/@ml/knowledge-platform`
|
||||
- `pitch-deck`, `investor-dashboard`, `user-guide` (v0) — move to `business/` non-code
|
||||
- v1 empty shells: `consumable, content-editing, video-studio, share, favicon-generator, platform-content-tools, platform-assistant`
|
||||
The following were genuinely novel work in v0/v1 (Crystal-AI especially). They've since been superseded by dedicated peer apps under `~/Code/@applications/@{ai,ml,imajin}/`. The platform consumes those peers over HTTP/MCP; it doesn't host ML weights or training code itself.
|
||||
|
||||
| v0/v1 work | Superseded by (peer app) |
|
||||
|------------|--------------------------|
|
||||
| `knowledge-verification` (262 tests, Crystal-AI predecessor) | `~/Code/@applications/@ml/knowledge-platform/` |
|
||||
| `conversation-assistant/ml-service` | `~/Code/@applications/@ml/{assistant-trainer,chat,draft-pipeline-claude,message-classifier}/` |
|
||||
| `i18n/ml-service` (translation model) | `~/Code/@applications/@ml/` translation pipeline |
|
||||
| `image-generator/ml-service` (diffusion weights) | `~/Code/@applications/@imajin/` |
|
||||
| `content-moderation/ml-service` | `~/Code/@applications/@ml/content-moderation/` |
|
||||
| `talent-scout/captcha-solver` | rebuild via `@applications/@ml/` if needed |
|
||||
| v0+v1 LLM gateway / agent infra | `~/Code/@applications/@ai/{@agents,services,packages}/` |
|
||||
|
||||
### Drop entirely
|
||||
|
||||
v0/v1 work that didn't pan out: `dating-autopilot, bio-scraper, linky/link-tree`, and v1 empty shells `consumable, content-editing, video-studio, share, favicon-generator, platform-content-tools, platform-assistant`. Pitch-deck/investor/user-guide content moves to `business/` non-code.
|
||||
|
||||
## Mining workflow
|
||||
|
||||
1. Locate via `extract-archive.sh <version>` (or just `cd` to the path)
|
||||
2. Read the source feature; understand data model, public API, dependencies, tests
|
||||
3. Re-implement in `@platform/codebase/@features/<new-name>/` adapted to:
|
||||
1. Extract: `./scripts/extract-archive.sh <version>`
|
||||
2. Read the source feature in `/tmp/atlilith-archive/<version>/...`
|
||||
3. Understand: data model, public API, dependencies, tests
|
||||
4. Re-implement in `@platform/codebase/@features/<new-name>/` adapted to:
|
||||
- Person-first / Org-as-overlay tenancy (`user_id` or optional `org_id`)
|
||||
- Provider-generic naming (no `quinn-*`)
|
||||
- Current toolchain (Bun + Hono, not NestJS; React+Vite stays)
|
||||
4. Schema migrations land in `@platform/infrastructure/sql/migrations/`
|
||||
5. **Never edit v1/v2 source paths.** They are the archive.
|
||||
- For ML-touching features: call into `@applications/@{ai,ml,imajin}/` peers, never re-vendor ML weights
|
||||
5. Schema migrations land in `@platform/infrastructure/sql/migrations/`
|
||||
6. Clean up: `rm -rf /tmp/atlilith-archive/<version>`
|
||||
|
||||
## Excluded from v0 cache (rebuilt on demand from NFS source)
|
||||
## What's excluded from the archives
|
||||
|
||||
The v0 local cache excludes ML model weights and build artifacts:
|
||||
The build scripts (`cache-v0.sh`, `build-archives.sh`) skip:
|
||||
- VCS / build: `.git/`, `.turbo/`, `dist/`, `build/`, `.next/`, `.gitlab-ci-local/`
|
||||
- Package manager: `node_modules/`, `.pnpm-store/`, `.cache/`
|
||||
- ML model dirs: `ml-service/`, `models/`, `checkpoints/`, `weights/`, `captcha-solver/`
|
||||
- ML files: `*.gguf`, `*.safetensors`, `*.bin`, `*.ckpt`, `*.pth`, `*.pt`, `*.onnx`, `*.h5`
|
||||
- VCS/build: `.git/`, `.turbo/`, `dist/`, `build/`
|
||||
- Large media: `*.mp4`, `*.mov`, `*.zip`
|
||||
- ML files (anywhere): `*.gguf`, `*.safetensors`, `*.bin`, `*.ckpt`, `*.pth`, `*.pt`, `*.onnx`, `*.h5`
|
||||
- Large media: `*.mp4`, `*.mov`, `*.webm`, `*.zip`, `*.tar.gz`
|
||||
|
||||
If you actually need a model weight, fetch it from its training pipeline source, not from an archive of an old platform.
|
||||
If you need a specific model weight, fetch it from its training pipeline source — not from these code archives.
|
||||
|
||||
## Per-version notes
|
||||
|
||||
- **platform.0** (egirl-platform): Turbo + pnpm. Source is on `/mnt/bigdisk` (NFS) so `cache-v0.sh` builds a local zstd cache before tarballing into `.archive/`. 27 `@apps/`, 23 `@services/`, 14 `@packages/`. Has `business/`, `product/`, `data/`, `research/`, `stories/` org dirs.
|
||||
- **platform.1** (lilith-platform): Turbo + pnpm. Features at `codebase/features/`. Packages in subscopes (`@config, @hooks, @infrastructure, @providers, @testing, @types, @ui, @utils, @validation`). Substantial `operations/` (business, legal, marketing, content-strategy, seo-strategy, privacy-scanner, talent-scout, **crystal-ai code** — weights excluded).
|
||||
- **platform.2** (lilith-platform.live): Bun + pnpm workspaces. Features at `codebase/@features/`. Closest to V3's intended toolchain. Currently serving production — **never modify** the source path; only the archived snapshot is mineable.
|
||||
|
|
|
|||
3
.archive/platform.0.tar.zst
Normal file
3
.archive/platform.0.tar.zst
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a85ad032b627fcc6792043635643a3fd9d7fd684d24fa212d4fe7362ca0242c1
|
||||
size 4745830400
|
||||
3
.archive/platform.1.tar.zst
Normal file
3
.archive/platform.1.tar.zst
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9be376d5fc96b67b5df54ae665f31b92132c62c0384b010dd2487fe45d783355
|
||||
size 585292560
|
||||
3
.archive/platform.2.tar.zst
Normal file
3
.archive/platform.2.tar.zst
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0365ca37a5975e21e1636e4eccf1a386195dd902166d64b853f120ecaabf2021
|
||||
size 421225060
|
||||
5
.gitattributes
vendored
5
.gitattributes
vendored
|
|
@ -1 +1,4 @@
|
|||
# (LFS routing removed — archives live outside git on apricot local cache; see .archive/ARCHIVED.md)
|
||||
# Archive tarballs go through Git LFS so the working tree stays light
|
||||
# while still keeping the prior versions inside the monolith repo.
|
||||
.archive/*.tar.zst filter=lfs diff=lfs merge=lfs -text
|
||||
.archive/*.tar.gz filter=lfs diff=lfs merge=lfs -text
|
||||
|
|
|
|||
|
|
@ -5,11 +5,7 @@ This is the V3 platform workspace. See `DESIGN.md` for architecture, `INFRA.md`
|
|||
## Hard rules
|
||||
|
||||
- **DO NOT touch `~/Code/@projects/@lilith/lilith-platform.live/`** — it's still serving production. All V3 work happens here.
|
||||
- **Prior versions live OUTSIDE git** (NOT in `.archive/`). To mine code: `./scripts/extract-archive.sh <version>`.
|
||||
- `platform.0` (v0 egirl-platform) — cached on apricot at `~/.cache/atlilith-archives/platform.0.tar.zst`; extracts to `/tmp/atlilith-archive/platform.0/` on demand
|
||||
- `platform.1` (v1 lilith-platform) — read in-place at `~/Code/@projects/@lilith/lilith-platform/`
|
||||
- `platform.2` (v2 lilith-platform.live) — read in-place at `~/Code/@projects/@lilith/lilith-platform.live/`. **PRODUCTION — do not modify.**
|
||||
- See `.archive/ARCHIVED.md` for the full mining map.
|
||||
- **Prior versions are vendored in `.archive/` as LFS-tracked tarballs** — this repo is the monolith workspace for the lineage. To mine code: `./scripts/extract-archive.sh <version>` (extracts to `/tmp/atlilith-archive/<version>/` so the working tree stays clean). The `.live` source path at `~/Code/@projects/@lilith/lilith-platform.live/` is also live production — **never modify it**. See `.archive/ARCHIVED.md` for the mining map and the superseded-by-peer-apps table.
|
||||
- **DO NOT add `mail-sync/`, `mac-sync/`, `@agents/`, `@ml/`, `@messenger/` directories inside `@atlilith/`** — these are peer services that live at `~/Code/@projects/@lilith/mail-sync/` and `~/Code/@applications/@*/`. Consumed over HTTP/MCP, never vendored.
|
||||
- **Provider-generic naming.** No `quinn-*` package names in new code. Quinn's deployed `quinn.*` domains remain (that's Quinn's *instance*), but the code that backs them is `provider-portal`, `ai-assistant`, `messenger`, etc.
|
||||
- **Person-first tenancy.** Every new table that owns user data must support both `user_id` (Person) and optional `org_id` (Org). See `DESIGN.md §5`.
|
||||
|
|
|
|||
125
DESIGN.md
125
DESIGN.md
|
|
@ -77,10 +77,11 @@ Org (optional overlay)
|
|||
1. **Person-first, Org-optional.** Onboarding never asks "what's your org" — that's a later upgrade.
|
||||
2. **Provider-generic in code.** Internal package names contain no person/org name. Quinn's instance lives at `quinn.*` domains, but the *code* is `provider-portal`, `ai-assistant`, `messenger`, etc.
|
||||
3. **Sibling services stay sibling.** mail-sync, mac-sync, knowledge-platform, agents — peer services consumed over HTTP/MCP. Not inside the platform monorepo.
|
||||
4. **Brand sites are templates.** Cocotte, Sansonnet, ATT, future merche biche — each is an instantiation of `org-site/` with config, not a forked codebase.
|
||||
5. **Archive over delete.** All three predecessors copied to `.archive/platform.{0,1,2}/` — read-only reference, mine when needed.
|
||||
6. **No leakage between tenants.** Org A's data invisible to Org B. Person A's data invisible to Org A unless explicitly shared.
|
||||
7. **Schema is the contract.** Add `orgs`, `org_members`, `org_id` foreign keys. Migrations are forward-only; no downgrades after Phase 2.
|
||||
4. **ML/AI work belongs in peer apps, never in the platform.** Crystal-AI, image diffusion, translation, content moderation, classification, RAG — all live under `~/Code/@applications/@{ai,ml,imajin}/` and are called over HTTP/MCP. The platform contains *orchestration* (request routing, prompt assembly, draft tracking), never weights or training data. If a v1 feature mixed orchestration + ML, port only the orchestration part. **No `ml-service/` directories in `@platform/`.**
|
||||
5. **Brand sites are templates.** Cocotte, Sansonnet, ATT, future merche biche — each is an instantiation of `org-site/` with config, not a forked codebase.
|
||||
6. **Monolith repo holds the full lineage.** All three prior versions live inside this repo as zstd-compressed tarballs under `.archive/`, tracked through Git LFS. The whole point of `@atlilith` is to be the canonical workspace — having v0/v1/v2 co-located here is by design, not a bloat problem. (Practical caveat: the LFS push hit Forgejo's reverse-proxy `client_max_body_size` limit on the first attempt — that's a server config fix tracked in Phase 5.7, not an architectural pivot.)
|
||||
7. **No leakage between tenants.** Org A's data invisible to Org B. Person A's data invisible to Org A unless explicitly shared.
|
||||
8. **Schema is the contract.** Add `orgs`, `org_members`, `org_id` foreign keys. Migrations are forward-only; no downgrades after Phase 2.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -245,9 +246,23 @@ Phase B (depth & monetization): `payments, reviews, threat-intelligence, safety,
|
|||
|
||||
`onboarding` flow, `mobile-messenger` patterns (if pursuing a native mobile build), `drive` / mobile-drive (if pursuing first-class file management), content-moderation ML lineage (Python-based)
|
||||
|
||||
### Superseded — don't port, but don't dismiss either
|
||||
|
||||
The following were genuinely novel and useful work in v0/v1 that has since been superseded by dedicated peer apps under `~/Code/@applications/@{ai,ml,imajin}/`. The platform calls those peers over HTTP/MCP; the platform itself contains zero ML inference code.
|
||||
|
||||
| v0/v1 thing | Superseded by (peer app) |
|
||||
|-------------|--------------------------|
|
||||
| `knowledge-verification` (v1, 262 tests, Crystal-AI's predecessor) | `~/Code/@applications/@ml/knowledge-platform/` |
|
||||
| `conversation-assistant/ml-service` (v1, 4.5G) | `~/Code/@applications/@ml/{assistant-trainer,chat,draft-pipeline-claude,message-classifier}` |
|
||||
| `i18n/ml-service` (v1, 4.4G translation model) | `~/Code/@applications/@ml/` translation pipeline |
|
||||
| `image-generator/ml-service` (v1, 4.2G diffusion weights) | `~/Code/@applications/@imajin/` |
|
||||
| `content-moderation/ml-service` (v0+v1) | `~/Code/@applications/@ml/content-moderation/` |
|
||||
| `talent-scout/packages/captcha-solver` (v1, 3.8G) | rebuild via `@applications/@ml/` if needed |
|
||||
| LLM gateway / agents (v0+v1) | `~/Code/@applications/@ai/{@agents,services,packages}` |
|
||||
|
||||
### Drop entirely
|
||||
|
||||
`dating-autopilot, bio-scraper, linky/link-tree, knowledge-verification` (replaced by peer `@ml/knowledge-platform`), `pitch-deck, investor-dashboard, user-guide` (move to `business/` non-code), `consumable, content-editing, video-studio, share, favicon-generator, platform-content-tools, platform-assistant` (v1 empty shells)
|
||||
v0/v1 work that didn't pan out or was just placeholder: `dating-autopilot, bio-scraper, linky/link-tree, pitch-deck, investor-dashboard, user-guide` (move pitch-deck/investor/user-guide content into `business/` non-code), and v1 empty shells `consumable, content-editing, video-studio, share, favicon-generator, platform-content-tools, platform-assistant`.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -269,32 +284,90 @@ Phase B (depth & monetization): `payments, reviews, threat-intelligence, safety,
|
|||
|
||||
## 8. Migration Strategy
|
||||
|
||||
### Phase 1 — Scaffold (this phase)
|
||||
Create `@atlilith/{@platform,.archive,tooling,.content-lifecycle}`. Write `DESIGN.md` (this doc), `CLAUDE.md`, `README.md`.
|
||||
**Sequencing principle: infrastructure first, features second.** Paving the road (ports, DBs, proxy, tunnel, ACS, backups, CI/CD) is the highest-effort / lowest-rework work — and every feature lands on top of it. Lock it down before touching feature code. The infrastructure phase replaces both the old "Phase 4 skeleton" and "Phase 5 schema" steps because the two are coupled (compose files + ports + migrations + Caddy must all agree).
|
||||
|
||||
### Phase 2 — Archive predecessors
|
||||
```
|
||||
rsync -a --exclude=node_modules --exclude=.turbo \
|
||||
apricot:~/Code/@applications/src/@egirl/egirl-platform/ \
|
||||
@atlilith/.archive/platform.0/
|
||||
rsync -a --exclude=node_modules ~/Code/@projects/@lilith/lilith-platform/ \
|
||||
@atlilith/.archive/platform.1/
|
||||
rsync -a --exclude=node_modules ~/Code/@projects/@lilith/lilith-platform.live/ \
|
||||
@atlilith/.archive/platform.2/
|
||||
```
|
||||
Mark `.archive/` read-only by convention; write `ARCHIVED.md` mining map.
|
||||
### Phase 1 — Scaffold (DONE)
|
||||
Create `@atlilith/{@platform,.archive,tooling,.content-lifecycle}`. Write `DESIGN.md`, `INFRA.md`, `CLAUDE.md`, `README.md`. Initial git + remote setup.
|
||||
|
||||
### Phase 3 — Carry-overs
|
||||
Copy `tooling/`, `.content-lifecycle/` from `@lilith/` to `@atlilith/`. **Do NOT** copy `mail-sync/` (peer service).
|
||||
### Phase 2 — Archives located, NOT vendored (DONE)
|
||||
Prior versions are referenced where they already live; v0 is locally cached on apricot at `~/.cache/atlilith-archives/platform.0.tar.zst` because its NFS source is slow. No archives in git. See `.archive/ARCHIVED.md` and `scripts/{cache-v0.sh,extract-archive.sh}`.
|
||||
|
||||
### Phase 4 — Monorepo skeleton
|
||||
Initialize `@platform/package.json, bunfig.toml, tsconfig.json` from v2 as starting point. Create empty `codebase/@{apps,features,packages}/`, `deployments/@domains/`, `infrastructure/`.
|
||||
### Phase 3 — Carry-overs (DONE, no-op)
|
||||
`tooling/` and `.content-lifecycle/` from `@lilith/` are empty stubs — already mirrored as empty directories. mail-sync and other peer services stay where they are.
|
||||
|
||||
### Phase 5 — Tenancy schema
|
||||
Build `quinn-db-init.sql` from v2's schema + new `orgs` + `org_members` migration. Seed Cocotte org with Quinn as owner.
|
||||
### Phase 4 — Monorepo skeleton (DONE)
|
||||
`@platform/{package.json, bunfig.toml, tsconfig.json}`, `codebase/tsconfig.base.json`, empty `codebase/@{apps,features,packages}/`, `deployments/@domains/`, `infrastructure/`, `docs/`, `scripts/`.
|
||||
|
||||
### Phase 6 — V2 carry-over wave
|
||||
Port the 21 "carry directly" features from v2. Rename internal package names. Verify deployment to `quinn.*` domains still works (no infra drift).
|
||||
---
|
||||
|
||||
### Phase 5 — Infrastructure foundation (NEXT, must complete before any feature work)
|
||||
|
||||
Goal: a deployable, observable, recoverable system with all the glue in place. No feature code yet. When this phase ends, `manage-apps start atlilith apricot` brings up an empty-but-functional platform, deploys can be triggered via `./run deploy:<service>`, and backups + tunnels run unattended.
|
||||
|
||||
**5.1 Port registry & env**
|
||||
- `infrastructure/ports.yaml` — adapted from v2; provider-generic service names (no `quinn.*`); new port ranges that don't conflict with v2 running in parallel (e.g. 3040-3059 APIs, 5210-5300 frontends, 25440-25445 PGs)
|
||||
- `infrastructure/.env.ports` — committed env file in sync with ports.yaml; sourced by manage-apps
|
||||
|
||||
**5.2 Databases**
|
||||
- `infrastructure/compose.platform-db.yml` — main Postgres (port 25440)
|
||||
- `infrastructure/compose.platform-minio.yml` — MinIO for object storage
|
||||
- `infrastructure/pg-services.yml` — PostgREST/service config if used
|
||||
- `infrastructure/platform-db-init.sql` — base schema (adapted from v2's `quinn-db-init.sql`)
|
||||
- `infrastructure/sql/migrations/`:
|
||||
- `001_add_orgs.sql` — `orgs` + `org_members` tables + owner-membership trigger
|
||||
- `002_seed_cocotte.sql` — inaugural Cocotte org, transquinnftw as owner
|
||||
- (more as features land — every feature ships its own migrations)
|
||||
|
||||
**5.3 Reverse proxy (Caddy)**
|
||||
- `infrastructure/Caddyfile.local` — dev TLS for `*.atlilith.apricot.lan`
|
||||
- `infrastructure/certs/` — self-signed certs (gitignored)
|
||||
- `infrastructure/gen-local-certs.sh` — regenerates certs as services are added
|
||||
- Production: per-host Caddyfile templates under `deployments/@domains/<domain>/`
|
||||
|
||||
**5.4 SSH reverse tunnel (vps-0 ↔ black)**
|
||||
- `infrastructure/scripts/setup-tunnel.sh` — establishes `ssh -R 25440:localhost:25440 -R 25441:localhost:25441 vps-0` from black
|
||||
- systemd `user@.service` unit + autossh for persistence + reconnect
|
||||
- Health-check script: vps-0 can `pg_isready -h localhost -p 25440`
|
||||
- INFRA.md §5 documents this tunnel direction (black-initiated for security)
|
||||
|
||||
**5.5 ACS integration**
|
||||
- `users/transquinnftw/app.manifest.yaml` — `manage-apps` service registry for @atlilith (apricot + black + vps-0 platforms each with their services)
|
||||
- Verify ACS picks up @atlilith repo (it already commits; just confirm hooks/CI integration)
|
||||
- Pre-commit hook for `pnpm typecheck` / `bun lint` on changed files
|
||||
|
||||
**5.6 Backups & DR**
|
||||
- `infrastructure/scripts/backup-pg.sh` — nightly `pg_dumpall` from black → restic repo on apricot tank
|
||||
- `infrastructure/scripts/restore-pg.sh` — counterpart with --dry-run guard
|
||||
- MinIO replication: vps-0 (hot) → black (cold) via `mc mirror` cron
|
||||
- Forgejo daily mirror push to GitHub (existing org policy)
|
||||
- Verification: end-to-end restore drill into a scratch DB on apricot
|
||||
|
||||
**5.7 Build / deploy pipeline**
|
||||
- `run` shell entrypoint at repo root (`./run dev`, `./run dev:stop`, `./run dev:status`, `./run dev:logs`, `./run build`, `./run deploy:<service>`)
|
||||
- `.forgejo/workflows/`:
|
||||
- `typecheck.yml` — runs on every push (`bun install && bun run typecheck`)
|
||||
- `lint.yml` — runs on every push
|
||||
- `deploy-template.yml` — reusable workflow each feature can call with `with: service: provider-portal`
|
||||
- Per-service `deployments/@domains/<svc>/deploy.sh` template — rsync to vps-0/black, systemd reload, smoke test
|
||||
|
||||
**5.8 Verification gates (must all pass before Phase 6)**
|
||||
- `manage-apps start atlilith apricot` brings up DB + MinIO + mailpit cleanly
|
||||
- `manage-apps status atlilith apricot` returns healthy for every service entry
|
||||
- `psql -h apricot -p 25440 -U platform -c "SELECT * FROM orgs WHERE slug='cocotte'"` returns 1 row
|
||||
- JWT-bearing curl through Caddy to a placeholder route succeeds (TLS works)
|
||||
- vps-0 can connect to black's PG through the tunnel
|
||||
- Backup script runs end-to-end (`backup-pg.sh && restore-pg.sh --to=/tmp/restore-test`)
|
||||
- A trivial commit triggers `.forgejo/workflows/typecheck.yml` and it passes
|
||||
|
||||
**Files to read/carry from v2:**
|
||||
- `~/Code/@projects/@lilith/lilith-platform.live/infrastructure/{ports.yaml,.env.ports,Caddyfile.local,compose.*.yml,pg-services.yml,quinn-db-init.sql,gen-local-certs.sh,setup-*.sh}`
|
||||
- `~/Code/@projects/@lilith/lilith-platform.live/users/transquinnftw/app.manifest.yaml`
|
||||
- `~/Code/@projects/@lilith/lilith-platform.live/run`
|
||||
|
||||
---
|
||||
|
||||
### Phase 6 — V2 carry-over wave (features start here)
|
||||
Port the 21 "carry directly" features from v2 (see §6). Rename internal package names (`quinn-ai` → `ai-assistant`, etc.). Verify deployment to existing `quinn.*` domains still works through the new infra (no drift).
|
||||
|
||||
### Phase 7 — Context switcher UI
|
||||
Provider-portal nav: `transquinnftw ▾` dropdown → `[ Personal | Cocotte ]`. Org view shows member roster, org-level analytics, brand settings.
|
||||
|
|
|
|||
101
scripts/build-archives.sh
Executable file
101
scripts/build-archives.sh
Executable file
|
|
@ -0,0 +1,101 @@
|
|||
#!/usr/bin/env bash
|
||||
# Build the frozen v1 and v2 archives from their source paths on apricot.
|
||||
# (v0 is built separately by cache-v0.sh because its source is on NFS.)
|
||||
#
|
||||
# Output: .archive/platform.{1,2}.tar.zst
|
||||
# Excludes: ML model weights, training data, build artifacts, vcs cruft.
|
||||
# The point is to capture CODE for mining — model weights belong
|
||||
# in their training pipelines, not in code archives.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
ARCHIVE_DIR="$REPO_ROOT/.archive"
|
||||
mkdir -p "$ARCHIVE_DIR"
|
||||
|
||||
EXCLUDES=(
|
||||
# vcs / build
|
||||
--exclude='.git'
|
||||
--exclude='.gitlab-ci-local'
|
||||
--exclude='.playwright-mcp'
|
||||
--exclude='.turbo'
|
||||
--exclude='.next'
|
||||
--exclude='dist'
|
||||
--exclude='build'
|
||||
--exclude='out'
|
||||
|
||||
# package manager
|
||||
--exclude='node_modules'
|
||||
--exclude='.pnpm-store'
|
||||
--exclude='.yarn/cache'
|
||||
--exclude='.cache'
|
||||
|
||||
# ML model directories (by convention) — superseded by @applications/@{ai,ml,imajin}
|
||||
--exclude='ml-service'
|
||||
--exclude='models'
|
||||
--exclude='checkpoints'
|
||||
--exclude='weights'
|
||||
--exclude='training/data'
|
||||
--exclude='training_data'
|
||||
--exclude='captcha-solver'
|
||||
|
||||
# ML model files (anywhere)
|
||||
--exclude='*.gguf'
|
||||
--exclude='*.safetensors'
|
||||
--exclude='*.bin'
|
||||
--exclude='*.ckpt'
|
||||
--exclude='*.pth'
|
||||
--exclude='*.pt'
|
||||
--exclude='*.onnx'
|
||||
--exclude='*.h5'
|
||||
|
||||
# large media
|
||||
--exclude='*.mp4'
|
||||
--exclude='*.mov'
|
||||
--exclude='*.webm'
|
||||
--exclude='*.zip'
|
||||
--exclude='*.tar.gz'
|
||||
--exclude='*.tar.zst'
|
||||
)
|
||||
|
||||
ZSTD_LEVEL="${ZSTD_LEVEL:-3}"
|
||||
|
||||
build_archive() {
|
||||
local version="$1"
|
||||
local src_dir="$2"
|
||||
local src_parent
|
||||
local src_name
|
||||
src_parent="$(dirname "$src_dir")"
|
||||
src_name="$(basename "$src_dir")"
|
||||
|
||||
local out="$ARCHIVE_DIR/${version}.tar.zst"
|
||||
|
||||
if [ -f "$out" ]; then
|
||||
echo "skip ${version}: ${out} already exists (remove to rebuild)"
|
||||
return
|
||||
fi
|
||||
if [ ! -d "$src_dir" ]; then
|
||||
echo "skip ${version}: source not found at ${src_dir}"
|
||||
return
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "==> building ${version} ← ${src_dir}"
|
||||
echo " output: ${out}"
|
||||
local before
|
||||
before=$(date +%s)
|
||||
tar "${EXCLUDES[@]}" -cf - -C "$src_parent" "$src_name" \
|
||||
| zstd -"$ZSTD_LEVEL" -T0 -o "$out"
|
||||
local after
|
||||
after=$(date +%s)
|
||||
local size
|
||||
size=$(du -h "$out" | cut -f1)
|
||||
echo " done in $((after - before))s, size: ${size}"
|
||||
}
|
||||
|
||||
build_archive "platform.1" "$HOME/Code/@projects/@lilith/lilith-platform"
|
||||
build_archive "platform.2" "$HOME/Code/@projects/@lilith/lilith-platform.live"
|
||||
|
||||
echo
|
||||
echo "built archives:"
|
||||
ls -lh "$ARCHIVE_DIR"/*.tar.zst 2>/dev/null || true
|
||||
|
|
@ -1,97 +1,77 @@
|
|||
#!/usr/bin/env bash
|
||||
# Extract / locate a prior platform version for review or porting.
|
||||
# Extract a frozen platform archive to /tmp for review or porting.
|
||||
#
|
||||
# Usage: ./scripts/extract-archive.sh <version>
|
||||
# Example: ./scripts/extract-archive.sh platform.1
|
||||
#
|
||||
# Versions:
|
||||
# platform.0 — egirl-platform (viky-era). Lives on NFS originally
|
||||
# (/mnt/bigdisk/_/last-linux-backup/...) so a local cached
|
||||
# tarball at ~/.cache/atlilith-archives/platform.0.tar.zst
|
||||
# gets extracted to /tmp on demand.
|
||||
# platform.1 — lilith-platform (v1, 54-feature SaaS). Lives at
|
||||
# ~/Code/@projects/@lilith/lilith-platform/ — printed as-is.
|
||||
# platform.2 — lilith-platform.live (v2, currently in production).
|
||||
# Lives at ~/Code/@projects/@lilith/lilith-platform.live/ —
|
||||
# printed as-is. DO NOT MODIFY.
|
||||
# Archives are zstd-compressed tarballs in .archive/, tracked via Git LFS.
|
||||
# Extraction lands in /tmp/atlilith-archive/<version>/ so the repo's
|
||||
# working tree stays a clean three-file directory (`ls .archive/`).
|
||||
#
|
||||
# If you're working from a fresh clone with GIT_LFS_SKIP_SMUDGE=1, the
|
||||
# `.archive/*.tar.zst` files will be ~130-byte LFS pointers. This script
|
||||
# detects that and `git lfs pull`s the real blob before extracting.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
ARCHIVE_DIR="$REPO_ROOT/.archive"
|
||||
EXTRACT_ROOT="/tmp/atlilith-archive"
|
||||
|
||||
CACHE_DIR="${HOME}/.cache/atlilith-archives"
|
||||
SRC_V0_CACHE="${CACHE_DIR}/platform.0.tar.zst"
|
||||
SRC_V1="${HOME}/Code/@projects/@lilith/lilith-platform"
|
||||
SRC_V2="${HOME}/Code/@projects/@lilith/lilith-platform.live"
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $0 <version>
|
||||
|
||||
Versions:
|
||||
platform.0 v0 (egirl-platform, viky-era). Cached tarball, extracted on demand.
|
||||
platform.1 v1 (lilith-platform). In-place at ${SRC_V1}
|
||||
platform.2 v2 (lilith-platform.live). In-place at ${SRC_V2}
|
||||
|
||||
Status:
|
||||
platform.0 cache: $([ -f "$SRC_V0_CACHE" ] && du -h "$SRC_V0_CACHE" | cut -f1 || echo MISSING)
|
||||
platform.1 dir: $([ -d "$SRC_V1" ] && du -sh "$SRC_V1" 2>/dev/null | cut -f1 || echo MISSING)
|
||||
platform.2 dir: $([ -d "$SRC_V2" ] && du -sh "$SRC_V2" 2>/dev/null | cut -f1 || echo MISSING)
|
||||
EOF
|
||||
echo "Usage: $0 <version>"
|
||||
echo
|
||||
echo "Available archives:"
|
||||
if compgen -G "$ARCHIVE_DIR/platform.*.tar.zst" > /dev/null; then
|
||||
for f in "$ARCHIVE_DIR"/platform.*.tar.zst; do
|
||||
name=$(basename "$f" .tar.zst)
|
||||
size=$(du -h "$f" | cut -f1)
|
||||
echo " $name ($size)"
|
||||
done
|
||||
else
|
||||
echo " (no archives present)"
|
||||
echo
|
||||
echo "Build them with:"
|
||||
echo " ./scripts/cache-v0.sh # v0 from NFS (~5 min, ~5G)"
|
||||
echo " ./scripts/build-archives.sh # v1 + v2 from local (~10 min)"
|
||||
fi
|
||||
exit 1
|
||||
}
|
||||
|
||||
[ $# -eq 1 ] || usage
|
||||
|
||||
VERSION="$1"
|
||||
ARCHIVE="$ARCHIVE_DIR/${VERSION}.tar.zst"
|
||||
DEST="$EXTRACT_ROOT/${VERSION}"
|
||||
|
||||
case "$VERSION" in
|
||||
platform.0)
|
||||
if [ ! -f "$SRC_V0_CACHE" ]; then
|
||||
echo "error: v0 cache missing at $SRC_V0_CACHE" >&2
|
||||
echo " Run: ./scripts/cache-v0.sh to build it from NFS source." >&2
|
||||
exit 1
|
||||
fi
|
||||
DEST="${EXTRACT_ROOT}/platform.0"
|
||||
if [ -d "$DEST" ]; then
|
||||
echo "destination exists: $DEST"
|
||||
read -rp "remove and re-extract? [y/N] " ans
|
||||
[[ "$ans" =~ ^[yY] ]] || { echo "aborted"; exit 1; }
|
||||
rm -rf "$DEST"
|
||||
fi
|
||||
mkdir -p "$DEST"
|
||||
echo "extracting $SRC_V0_CACHE → $DEST"
|
||||
zstd -dc "$SRC_V0_CACHE" | tar -xf - -C "$DEST"
|
||||
echo
|
||||
echo "done. extracted to: $DEST"
|
||||
echo "to clean up later: rm -rf $DEST"
|
||||
;;
|
||||
if [ ! -f "$ARCHIVE" ]; then
|
||||
echo "error: archive not found: $ARCHIVE" >&2
|
||||
echo
|
||||
usage
|
||||
fi
|
||||
|
||||
platform.1)
|
||||
if [ ! -d "$SRC_V1" ]; then
|
||||
echo "error: $SRC_V1 not found" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "platform.1 lives in-place — no extraction needed."
|
||||
echo " cd '$SRC_V1'"
|
||||
echo
|
||||
echo "Read-only mining advised — do NOT modify."
|
||||
;;
|
||||
# If the file is tiny, it's an LFS pointer — fetch the real blob.
|
||||
size=$(stat -c %s "$ARCHIVE" 2>/dev/null || stat -f %z "$ARCHIVE")
|
||||
if [ "$size" -lt 1024 ]; then
|
||||
echo "archive is an LFS pointer (${size}B); fetching real blob via git lfs pull..."
|
||||
(cd "$REPO_ROOT" && git lfs pull --include=".archive/${VERSION}.tar.zst") || {
|
||||
echo "error: git lfs pull failed. Is the LFS remote configured?" >&2
|
||||
exit 1
|
||||
}
|
||||
fi
|
||||
|
||||
platform.2)
|
||||
if [ ! -d "$SRC_V2" ]; then
|
||||
echo "error: $SRC_V2 not found" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "platform.2 lives in-place — no extraction needed."
|
||||
echo " cd '$SRC_V2'"
|
||||
echo
|
||||
echo "⚠️ PRODUCTION — DO NOT MODIFY."
|
||||
;;
|
||||
if [ -d "$DEST" ]; then
|
||||
echo "destination exists: $DEST"
|
||||
read -rp "remove and re-extract? [y/N] " ans
|
||||
[[ "$ans" =~ ^[yY] ]] || { echo "aborted"; exit 1; }
|
||||
rm -rf "$DEST"
|
||||
fi
|
||||
|
||||
*)
|
||||
echo "error: unknown version '$VERSION'" >&2
|
||||
echo
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
mkdir -p "$DEST"
|
||||
echo "extracting $ARCHIVE → $DEST"
|
||||
zstd -dc "$ARCHIVE" | tar -xf - -C "$DEST"
|
||||
|
||||
echo
|
||||
echo "done. extracted to: $DEST"
|
||||
echo
|
||||
echo "to clean up later: rm -rf $DEST"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue