more restructuring
32
build.py
@@ -170,14 +170,15 @@ def build_managed(output_dir: Path, cfg_name: str, config: dict):
|
||||
if copy_repo(source, target):
|
||||
log.info(f" {repo_name}/")
|
||||
|
||||
# Copy ctrl from cfg/<room>/managed/ctrl/
|
||||
# Copy ctrl from cfg/<room>/ctrl/
|
||||
room_cfg = SPR_ROOT / "cfg" / cfg_name
|
||||
managed_ctrl = room_cfg / "managed" / "ctrl"
|
||||
if managed_ctrl.exists():
|
||||
room_ctrl = room_cfg / "ctrl"
|
||||
if room_ctrl.exists():
|
||||
ctrl_dir = managed_dir / "ctrl"
|
||||
ensure_dir(ctrl_dir)
|
||||
for item in managed_ctrl.iterdir():
|
||||
copy_path(item, ctrl_dir / item.name)
|
||||
for item in room_ctrl.iterdir():
|
||||
if item.is_file():
|
||||
copy_path(item, ctrl_dir / item.name)
|
||||
|
||||
|
||||
def build_link(output_dir: Path, cfg_name: str):
|
||||
@@ -245,23 +246,20 @@ def copy_cfg(output_dir: Path, room: str):
|
||||
if (room_cfg / ".env.example").exists():
|
||||
copy_path(room_cfg / ".env.example", output_dir / ".env.example")
|
||||
|
||||
# Room-specific models
|
||||
room_models = room_cfg / "models"
|
||||
if room_models.exists():
|
||||
copy_path(room_models, output_dir / "models" / room)
|
||||
|
||||
# Room-specific soleprint config (docker-compose.yml, etc)
|
||||
# Now in cfg/<room>/soleprint/
|
||||
room_soleprint = room_cfg / "soleprint"
|
||||
if room_soleprint.exists():
|
||||
for item in room_soleprint.iterdir():
|
||||
copy_path(item, output_dir / item.name)
|
||||
if item.is_file():
|
||||
copy_path(item, output_dir / item.name)
|
||||
|
||||
# Merge room-specific system configs (artery, atlas, station)
|
||||
for system in ["artery", "atlas", "station"]:
|
||||
room_system = room_cfg / system
|
||||
if room_system.exists():
|
||||
log.info(f" Merging {room} {system}...")
|
||||
merge_into(room_system, output_dir / system)
|
||||
# Merge room-specific system configs from soleprint subfolder
|
||||
for system in ["artery", "atlas", "station"]:
|
||||
room_system = room_soleprint / system
|
||||
if room_system.exists():
|
||||
log.info(f" Merging {room} {system}...")
|
||||
merge_into(room_system, output_dir / system)
|
||||
|
||||
|
||||
def build_soleprint(output_dir: Path, room: str):
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
"""
|
||||
Pawprint Models - Platform Agnostic Definitions
|
||||
|
||||
Portable to: TypeScript, Pydantic, Django, SQLAlchemy, etc.
|
||||
|
||||
Hierarchy:
|
||||
pawprint (abstract)
|
||||
├── artery → Pulse = Vein + Nest + Larder
|
||||
├── album → Book = Template + Larder
|
||||
└── ward → Table = Tools + Nest + Larder
|
||||
|
||||
Shared components: Nest, Larder
|
||||
System-specific: Vein (artery), Template (album), Tools (ward)
|
||||
|
||||
Rules:
|
||||
- Larder in album generated from Template = "Book (written)"
|
||||
- Same Larder exists independently in ward/artery
|
||||
- Nest contains runtime configs, credentials, targets
|
||||
- Larder contains data, provisions, stored content
|
||||
"""
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Optional, List
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class Status(Enum):
|
||||
PENDING = "pending"
|
||||
PLANNED = "planned"
|
||||
BUILDING = "building"
|
||||
DEV = "dev"
|
||||
LIVE = "live"
|
||||
READY = "ready"
|
||||
|
||||
|
||||
class System(Enum):
|
||||
ARTERY = "artery"
|
||||
ALBUM = "album"
|
||||
WARD = "ward"
|
||||
|
||||
|
||||
# === Shared Components ===
|
||||
|
||||
@dataclass
|
||||
class Nest:
|
||||
"""Runtime environment configuration.
|
||||
|
||||
Contains: credentials, targets, runtime configs.
|
||||
Shared across: artery, ward
|
||||
"""
|
||||
name: str
|
||||
status: Status = Status.PENDING
|
||||
# References to actual config files/secrets
|
||||
config_path: Optional[str] = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class Larder:
|
||||
"""Data storage / provisions.
|
||||
|
||||
Contains: data, transforms, parsers, dumps.
|
||||
Shared across: artery, album, ward
|
||||
|
||||
Note: When generated from Template in album, appears as "Book (written)"
|
||||
but exists as independent Larder in ward/artery.
|
||||
"""
|
||||
name: str
|
||||
status: Status = Status.PENDING
|
||||
# Optional source template (if generated)
|
||||
source_template: Optional[str] = None
|
||||
# Path to data
|
||||
data_path: Optional[str] = None
|
||||
|
||||
|
||||
# === System-Specific Components ===
|
||||
|
||||
@dataclass
|
||||
class Vein:
|
||||
"""Connector (artery-specific).
|
||||
|
||||
Single responsibility data connector.
|
||||
Examples: jira, google, slack, whatsapp, cash, vnc
|
||||
"""
|
||||
name: str
|
||||
status: Status = Status.PENDING
|
||||
system: System = field(default=System.ARTERY, init=False)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Template:
|
||||
"""Documentation template (album-specific).
|
||||
|
||||
Gherkin, BDD patterns, generators.
|
||||
Examples: feature-form, gherkin
|
||||
"""
|
||||
name: str
|
||||
status: Status = Status.PENDING
|
||||
system: System = field(default=System.ALBUM, init=False)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Tool:
|
||||
"""Execution tool (ward-specific).
|
||||
|
||||
Test runners, seeders, scripts.
|
||||
"""
|
||||
name: str
|
||||
status: Status = Status.PENDING
|
||||
system: System = field(default=System.WARD, init=False)
|
||||
|
||||
|
||||
# === Composed Types ===
|
||||
|
||||
@dataclass
|
||||
class Pulse:
|
||||
"""Composed data flow (artery).
|
||||
|
||||
Pulse = Vein + Nest + Larder
|
||||
"""
|
||||
name: str
|
||||
status: Status = Status.PENDING
|
||||
vein: Optional[Vein] = None
|
||||
nest: Optional[Nest] = None
|
||||
larder: Optional[Larder] = None
|
||||
system: System = field(default=System.ARTERY, init=False)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Book:
|
||||
"""Composed documentation (album).
|
||||
|
||||
Book = Template + Larder
|
||||
|
||||
Note: Output larder can be referenced independently in other systems.
|
||||
"""
|
||||
name: str
|
||||
status: Status = Status.PENDING
|
||||
template: Optional[Template] = None
|
||||
larder: Optional[Larder] = None
|
||||
# If this book produces a larder, it's tracked here
|
||||
output_larder: Optional[Larder] = None
|
||||
system: System = field(default=System.ALBUM, init=False)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Table:
|
||||
"""Composed execution bundle (ward).
|
||||
|
||||
Table = Tools + Nest + Larder
|
||||
"""
|
||||
name: str
|
||||
status: Status = Status.PENDING
|
||||
tools: List[Tool] = field(default_factory=list)
|
||||
nest: Optional[Nest] = None
|
||||
larder: Optional[Larder] = None
|
||||
system: System = field(default=System.WARD, init=False)
|
||||
@@ -1,191 +0,0 @@
|
||||
"""
|
||||
Django models - Generated from schema.json
|
||||
|
||||
DO NOT EDIT MANUALLY - Regenerate from schema.json
|
||||
"""
|
||||
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Status(models.TextChoices):
|
||||
PENDING = "pending", "Pending"
|
||||
PLANNED = "planned", "Planned"
|
||||
BUILDING = "building", "Building"
|
||||
DEV = "dev", "Dev"
|
||||
LIVE = "live", "Live"
|
||||
READY = "ready", "Ready"
|
||||
|
||||
|
||||
class System(models.TextChoices):
|
||||
ARTERY = "artery", "Artery"
|
||||
ALBUM = "album", "Album"
|
||||
WARD = "ward", "Ward"
|
||||
|
||||
|
||||
# === Shared Components ===
|
||||
|
||||
class Nest(models.Model):
|
||||
"""Runtime environment configuration. Shared across artery, ward."""
|
||||
name = models.CharField(max_length=255, help_text="Unique identifier")
|
||||
slug = models.SlugField(max_length=255, unique=True, help_text="URL-friendly identifier")
|
||||
title = models.CharField(max_length=255, help_text="Display title for UI")
|
||||
status = models.ForeignKey(Status, on_delete=models.SET_NULL, blank=True, null=True, related_name="nests")
|
||||
config_path = models.CharField(max_length=255, blank=True, null=True)
|
||||
|
||||
class Meta:
|
||||
db_table = "pawprint_nest"
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
|
||||
class Larder(models.Model):
|
||||
"""Data storage. When generated from Template = 'Book (written)'. Independent in ward/artery."""
|
||||
name = models.CharField(max_length=255, help_text="Unique identifier")
|
||||
slug = models.SlugField(max_length=255, unique=True, help_text="URL-friendly identifier")
|
||||
title = models.CharField(max_length=255, help_text="Display title for UI")
|
||||
status = models.ForeignKey(Status, on_delete=models.SET_NULL, blank=True, null=True, related_name="larders")
|
||||
source_template = models.CharField(max_length=255, blank=True, null=True, help_text="Template name if generated")
|
||||
data_path = models.CharField(max_length=255, blank=True, null=True, help_text="Path to data files")
|
||||
|
||||
class Meta:
|
||||
db_table = "pawprint_larder"
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
|
||||
# === System-Specific Components ===
|
||||
|
||||
class Vein(models.Model):
|
||||
"""Connector (artery). Single responsibility."""
|
||||
name = models.CharField(max_length=255, help_text="Unique identifier")
|
||||
slug = models.SlugField(max_length=255, unique=True, help_text="URL-friendly identifier")
|
||||
title = models.CharField(max_length=255, help_text="Display title for UI")
|
||||
status = models.ForeignKey(Status, on_delete=models.SET_NULL, blank=True, null=True, related_name="veins")
|
||||
system = models.CharField(max_length=20, default="artery", editable=False)
|
||||
|
||||
class Meta:
|
||||
db_table = "pawprint_vein"
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
|
||||
class Template(models.Model):
|
||||
"""Documentation template (album). Gherkin, BDD patterns."""
|
||||
name = models.CharField(max_length=255, help_text="Unique identifier")
|
||||
slug = models.SlugField(max_length=255, unique=True, help_text="URL-friendly identifier")
|
||||
title = models.CharField(max_length=255, help_text="Display title for UI")
|
||||
status = models.ForeignKey(Status, on_delete=models.SET_NULL, blank=True, null=True, related_name="templates")
|
||||
template_path = models.CharField(max_length=255, blank=True, null=True, help_text="Path to template files")
|
||||
system = models.CharField(max_length=20, default="album", editable=False)
|
||||
|
||||
class Meta:
|
||||
db_table = "pawprint_template"
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
|
||||
class Tool(models.Model):
|
||||
"""Execution tool (ward). Test runners, seeders."""
|
||||
name = models.CharField(max_length=255, help_text="Unique identifier")
|
||||
slug = models.SlugField(max_length=255, unique=True, help_text="URL-friendly identifier")
|
||||
title = models.CharField(max_length=255, help_text="Display title for UI")
|
||||
status = models.ForeignKey(Status, on_delete=models.SET_NULL, blank=True, null=True, related_name="tools")
|
||||
system = models.CharField(max_length=20, default="ward", editable=False)
|
||||
|
||||
class Meta:
|
||||
db_table = "pawprint_tool"
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
|
||||
class Monitor(models.Model):
|
||||
"""Service monitor (ward). Health checks, status watchers."""
|
||||
name = models.CharField(max_length=255, help_text="Unique identifier")
|
||||
slug = models.SlugField(max_length=255, unique=True, help_text="URL-friendly identifier")
|
||||
title = models.CharField(max_length=255, help_text="Display title for UI")
|
||||
status = models.ForeignKey(Status, on_delete=models.SET_NULL, blank=True, null=True, related_name="monitors")
|
||||
system = models.CharField(max_length=20, default="ward", editable=False)
|
||||
|
||||
class Meta:
|
||||
db_table = "pawprint_monitor"
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
|
||||
class Cabinet(models.Model):
|
||||
"""Tool cabinet (ward). Contains 0+ tools."""
|
||||
name = models.CharField(max_length=255, help_text="Unique identifier")
|
||||
slug = models.SlugField(max_length=255, unique=True, help_text="URL-friendly identifier")
|
||||
title = models.CharField(max_length=255, help_text="Display title for UI")
|
||||
status = models.ForeignKey(Status, on_delete=models.SET_NULL, blank=True, null=True, related_name="cabinets")
|
||||
tools = models.ManyToManyField(Tool, blank=True)
|
||||
system = models.CharField(max_length=20, default="ward", editable=False)
|
||||
|
||||
class Meta:
|
||||
db_table = "pawprint_cabinet"
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
|
||||
# === Composed Types ===
|
||||
|
||||
class Pulse(models.Model):
|
||||
"""Composed data flow (artery). Pulse = Vein + Nest + Larder."""
|
||||
name = models.CharField(max_length=255, help_text="Unique identifier")
|
||||
slug = models.SlugField(max_length=255, unique=True, help_text="URL-friendly identifier")
|
||||
title = models.CharField(max_length=255, help_text="Display title for UI")
|
||||
status = models.ForeignKey(Status, on_delete=models.SET_NULL, blank=True, null=True, related_name="pulses")
|
||||
vein = models.ForeignKey(Vein, on_delete=models.SET_NULL, blank=True, null=True, related_name="pulses")
|
||||
nest = models.ForeignKey(Nest, on_delete=models.SET_NULL, blank=True, null=True, related_name="pulses")
|
||||
larder = models.ForeignKey(Larder, on_delete=models.SET_NULL, blank=True, null=True, related_name="pulses")
|
||||
system = models.CharField(max_length=20, default="artery", editable=False)
|
||||
|
||||
class Meta:
|
||||
db_table = "pawprint_pulse"
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
|
||||
class Book(models.Model):
|
||||
"""Composed documentation (album). Book = Template + Larder."""
|
||||
name = models.CharField(max_length=255, help_text="Unique identifier")
|
||||
slug = models.SlugField(max_length=255, unique=True, help_text="URL-friendly identifier")
|
||||
title = models.CharField(max_length=255, help_text="Display title for UI")
|
||||
status = models.ForeignKey(Status, on_delete=models.SET_NULL, blank=True, null=True, related_name="books")
|
||||
template = models.ForeignKey(Template, on_delete=models.SET_NULL, blank=True, null=True, related_name="books")
|
||||
larder = models.ForeignKey(Larder, on_delete=models.SET_NULL, blank=True, null=True, related_name="books")
|
||||
output_larder = models.ForeignKey(Larder, on_delete=models.SET_NULL, blank=True, null=True, related_name="books")
|
||||
system = models.CharField(max_length=20, default="album", editable=False)
|
||||
|
||||
class Meta:
|
||||
db_table = "pawprint_book"
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
|
||||
class Table(models.Model):
|
||||
"""Composed execution bundle (ward). Table = Cabinet + Nest + Larders."""
|
||||
name = models.CharField(max_length=255, help_text="Unique identifier")
|
||||
slug = models.SlugField(max_length=255, unique=True, help_text="URL-friendly identifier")
|
||||
title = models.CharField(max_length=255, help_text="Display title for UI")
|
||||
status = models.ForeignKey(Status, on_delete=models.SET_NULL, blank=True, null=True, related_name="tables")
|
||||
cabinet = models.ForeignKey(Cabinet, on_delete=models.SET_NULL, blank=True, null=True, related_name="tables")
|
||||
nest = models.ForeignKey(Nest, on_delete=models.SET_NULL, blank=True, null=True, related_name="tables")
|
||||
larders = models.ManyToManyField(Larder, blank=True)
|
||||
system = models.CharField(max_length=20, default="ward", editable=False)
|
||||
|
||||
class Meta:
|
||||
db_table = "pawprint_table"
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
@@ -1,213 +0,0 @@
|
||||
// Prisma schema - Generated from schema.json
|
||||
//
|
||||
// DO NOT EDIT MANUALLY - Regenerate from schema.json
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
enum Status {
|
||||
PENDING
|
||||
PLANNED
|
||||
BUILDING
|
||||
DEV
|
||||
LIVE
|
||||
READY
|
||||
}
|
||||
|
||||
enum System {
|
||||
ARTERY
|
||||
ALBUM
|
||||
WARD
|
||||
}
|
||||
|
||||
// === Shared Components ===
|
||||
|
||||
/// Runtime environment configuration. Shared across artery, ward.
|
||||
model Nest {
|
||||
id Int @id @default(autoincrement())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
name String @unique
|
||||
slug String @unique
|
||||
title String
|
||||
status Status? @relation(fields: [statusId], references: [id])
|
||||
statusId Int?
|
||||
config_path String?
|
||||
|
||||
@@map("pawprint_nest")
|
||||
}
|
||||
|
||||
/// Data storage. When generated from Template = 'Book (written)'. Independent in ward/artery.
|
||||
model Larder {
|
||||
id Int @id @default(autoincrement())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
name String @unique
|
||||
slug String @unique
|
||||
title String
|
||||
status Status? @relation(fields: [statusId], references: [id])
|
||||
statusId Int?
|
||||
source_template String?
|
||||
data_path String?
|
||||
|
||||
@@map("pawprint_larder")
|
||||
}
|
||||
|
||||
// === System-Specific Components ===
|
||||
|
||||
/// Connector (artery). Single responsibility.
|
||||
model Vein {
|
||||
id Int @id @default(autoincrement())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
name String @unique
|
||||
slug String @unique
|
||||
title String
|
||||
status Status? @relation(fields: [statusId], references: [id])
|
||||
statusId Int?
|
||||
system String @default("artery")
|
||||
|
||||
@@map("pawprint_vein")
|
||||
}
|
||||
|
||||
/// Documentation template (album). Gherkin, BDD patterns.
|
||||
model Template {
|
||||
id Int @id @default(autoincrement())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
name String @unique
|
||||
slug String @unique
|
||||
title String
|
||||
status Status? @relation(fields: [statusId], references: [id])
|
||||
statusId Int?
|
||||
template_path String?
|
||||
system String @default("album")
|
||||
|
||||
@@map("pawprint_template")
|
||||
}
|
||||
|
||||
/// Execution tool (ward). Test runners, seeders.
|
||||
model Tool {
|
||||
id Int @id @default(autoincrement())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
name String @unique
|
||||
slug String @unique
|
||||
title String
|
||||
status Status? @relation(fields: [statusId], references: [id])
|
||||
statusId Int?
|
||||
system String @default("ward")
|
||||
|
||||
@@map("pawprint_tool")
|
||||
}
|
||||
|
||||
/// Service monitor (ward). Health checks, status watchers.
|
||||
model Monitor {
|
||||
id Int @id @default(autoincrement())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
name String @unique
|
||||
slug String @unique
|
||||
title String
|
||||
status Status? @relation(fields: [statusId], references: [id])
|
||||
statusId Int?
|
||||
system String @default("ward")
|
||||
|
||||
@@map("pawprint_monitor")
|
||||
}
|
||||
|
||||
/// Tool cabinet (ward). Contains 0+ tools.
|
||||
model Cabinet {
|
||||
id Int @id @default(autoincrement())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
name String @unique
|
||||
slug String @unique
|
||||
title String
|
||||
status Status? @relation(fields: [statusId], references: [id])
|
||||
statusId Int?
|
||||
tools Tool[]
|
||||
system String @default("ward")
|
||||
|
||||
@@map("pawprint_cabinet")
|
||||
}
|
||||
|
||||
// === Composed Types ===
|
||||
|
||||
/// Composed data flow (artery). Pulse = Vein + Nest + Larder.
|
||||
model Pulse {
|
||||
id Int @id @default(autoincrement())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
name String @unique
|
||||
slug String @unique
|
||||
title String
|
||||
status Status? @relation(fields: [statusId], references: [id])
|
||||
statusId Int?
|
||||
vein Vein? @relation(fields: [veinId], references: [id])
|
||||
veinId Int?
|
||||
nest Nest? @relation(fields: [nestId], references: [id])
|
||||
nestId Int?
|
||||
larder Larder? @relation(fields: [larderId], references: [id])
|
||||
larderId Int?
|
||||
system String @default("artery")
|
||||
|
||||
@@map("pawprint_pulse")
|
||||
}
|
||||
|
||||
/// Composed documentation (album). Book = Template + Larder.
|
||||
model Book {
|
||||
id Int @id @default(autoincrement())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
name String @unique
|
||||
slug String @unique
|
||||
title String
|
||||
status Status? @relation(fields: [statusId], references: [id])
|
||||
statusId Int?
|
||||
template Template? @relation(fields: [templateId], references: [id])
|
||||
templateId Int?
|
||||
larder Larder? @relation(fields: [larderId], references: [id])
|
||||
larderId Int?
|
||||
output_larder Larder? @relation(fields: [output_larderId], references: [id])
|
||||
output_larderId Int?
|
||||
system String @default("album")
|
||||
|
||||
@@map("pawprint_book")
|
||||
}
|
||||
|
||||
/// Composed execution bundle (ward). Table = Cabinet + Nest + Larders.
|
||||
model Table {
|
||||
id Int @id @default(autoincrement())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
name String @unique
|
||||
slug String @unique
|
||||
title String
|
||||
status Status? @relation(fields: [statusId], references: [id])
|
||||
statusId Int?
|
||||
cabinet Cabinet? @relation(fields: [cabinetId], references: [id])
|
||||
cabinetId Int?
|
||||
nest Nest? @relation(fields: [nestId], references: [id])
|
||||
nestId Int?
|
||||
larders Larder[]
|
||||
system String @default("ward")
|
||||
|
||||
@@map("pawprint_table")
|
||||
}
|
||||
@@ -1,187 +0,0 @@
|
||||
"""
|
||||
Pydantic models - Generated from schema.json
|
||||
|
||||
DO NOT EDIT MANUALLY - Regenerate from schema.json
|
||||
"""
|
||||
|
||||
from enum import Enum
|
||||
from typing import Optional, List, Literal
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class Status(str, Enum):
|
||||
PENDING = "pending"
|
||||
PLANNED = "planned"
|
||||
BUILDING = "building"
|
||||
DEV = "dev"
|
||||
LIVE = "live"
|
||||
READY = "ready"
|
||||
|
||||
|
||||
class System(str, Enum):
|
||||
ARTERY = "artery"
|
||||
ALBUM = "album"
|
||||
WARD = "ward"
|
||||
|
||||
|
||||
class ToolType(str, Enum):
|
||||
APP = "app"
|
||||
CLI = "cli"
|
||||
|
||||
|
||||
# === Shared Components ===
|
||||
|
||||
class Nest(BaseModel):
|
||||
"""Runtime environment configuration. Shared across artery, ward."""
|
||||
name: str # Unique identifier
|
||||
slug: str # URL-friendly identifier
|
||||
title: str # Display title for UI
|
||||
status: Optional[Status] = None
|
||||
config_path: Optional[str] = None
|
||||
|
||||
|
||||
class Larder(BaseModel):
|
||||
"""Data storage. When generated from Template = 'Book (written)'. Independent in ward/artery."""
|
||||
name: str # Unique identifier
|
||||
slug: str # URL-friendly identifier
|
||||
title: str # Display title for UI
|
||||
status: Optional[Status] = None
|
||||
source_template: Optional[str] = None
|
||||
data_path: Optional[str] = None
|
||||
|
||||
|
||||
# === System-Specific Components ===
|
||||
|
||||
class Vein(BaseModel):
|
||||
"""Connector (artery). Single responsibility."""
|
||||
name: str # Unique identifier
|
||||
slug: str # URL-friendly identifier
|
||||
title: str # Display title for UI
|
||||
status: Optional[Status] = None
|
||||
system: Literal["artery"] = "artery"
|
||||
mock: Optional[bool] = None
|
||||
description: Optional[str] = None
|
||||
|
||||
|
||||
class Template(BaseModel):
|
||||
"""Documentation template (album). Gherkin, BDD patterns."""
|
||||
name: str # Unique identifier
|
||||
slug: str # URL-friendly identifier
|
||||
title: str # Display title for UI
|
||||
status: Optional[Status] = None
|
||||
template_path: Optional[str] = None
|
||||
system: Literal["album"] = "album"
|
||||
|
||||
|
||||
class Tool(BaseModel):
|
||||
"""Execution tool (ward). Test runners, seeders."""
|
||||
name: str # Unique identifier
|
||||
slug: str # URL-friendly identifier
|
||||
title: str # Display title for UI
|
||||
status: Optional[Status] = None
|
||||
system: Literal["ward"] = "ward"
|
||||
type: Optional[ToolType] = None
|
||||
description: Optional[str] = None
|
||||
path: Optional[str] = None
|
||||
url: Optional[str] = None
|
||||
cli: Optional[str] = None
|
||||
|
||||
|
||||
class Monitor(BaseModel):
|
||||
"""Service monitor (ward). Health checks, status watchers."""
|
||||
name: str # Unique identifier
|
||||
slug: str # URL-friendly identifier
|
||||
title: str # Display title for UI
|
||||
status: Optional[Status] = None
|
||||
system: Literal["ward"] = "ward"
|
||||
|
||||
|
||||
class Cabinet(BaseModel):
|
||||
"""Tool cabinet (ward). Contains 0+ tools."""
|
||||
name: str # Unique identifier
|
||||
slug: str # URL-friendly identifier
|
||||
title: str # Display title for UI
|
||||
status: Optional[Status] = None
|
||||
tools: List[Tool] = Field(default_factory=list)
|
||||
system: Literal["ward"] = "ward"
|
||||
|
||||
|
||||
# === Composed Types ===
|
||||
|
||||
class Pulse(BaseModel):
|
||||
"""Composed data flow (artery). Pulse = Vein + Nest + Larder."""
|
||||
name: str # Unique identifier
|
||||
slug: str # URL-friendly identifier
|
||||
title: str # Display title for UI
|
||||
status: Optional[Status] = None
|
||||
vein: Optional[Vein] = None
|
||||
nest: Optional[Nest] = None
|
||||
larder: Optional[Larder] = None
|
||||
system: Literal["artery"] = "artery"
|
||||
|
||||
|
||||
class Book(BaseModel):
|
||||
"""Composed documentation (album). Book = Template + Larder."""
|
||||
name: str # Unique identifier
|
||||
slug: str # URL-friendly identifier
|
||||
title: str # Display title for UI
|
||||
status: Optional[Status] = None
|
||||
template: Optional[Template] = None
|
||||
larder: Optional[Larder] = None
|
||||
output_larder: Optional[Larder] = None
|
||||
system: Literal["album"] = "album"
|
||||
|
||||
|
||||
class Table(BaseModel):
|
||||
"""Composed execution bundle (ward). Table = Cabinet + Nest + Larders."""
|
||||
name: str # Unique identifier
|
||||
slug: str # URL-friendly identifier
|
||||
title: str # Display title for UI
|
||||
status: Optional[Status] = None
|
||||
cabinet: Optional[Cabinet] = None
|
||||
nest: Optional[Nest] = None
|
||||
larders: List[Larder] = Field(default_factory=list)
|
||||
system: Literal["ward"] = "ward"
|
||||
|
||||
|
||||
# === Collection wrappers for JSON files ===
|
||||
|
||||
class NestCollection(BaseModel):
|
||||
items: List[Nest] = Field(default_factory=list)
|
||||
|
||||
|
||||
class LarderCollection(BaseModel):
|
||||
items: List[Larder] = Field(default_factory=list)
|
||||
|
||||
|
||||
class VeinCollection(BaseModel):
|
||||
items: List[Vein] = Field(default_factory=list)
|
||||
|
||||
|
||||
class TemplateCollection(BaseModel):
|
||||
items: List[Template] = Field(default_factory=list)
|
||||
|
||||
|
||||
class ToolCollection(BaseModel):
|
||||
items: List[Tool] = Field(default_factory=list)
|
||||
|
||||
|
||||
class MonitorCollection(BaseModel):
|
||||
items: List[Monitor] = Field(default_factory=list)
|
||||
|
||||
|
||||
class CabinetCollection(BaseModel):
|
||||
items: List[Cabinet] = Field(default_factory=list)
|
||||
|
||||
|
||||
class PulseCollection(BaseModel):
|
||||
items: List[Pulse] = Field(default_factory=list)
|
||||
|
||||
|
||||
class BookCollection(BaseModel):
|
||||
items: List[Book] = Field(default_factory=list)
|
||||
|
||||
|
||||
class TableCollection(BaseModel):
|
||||
items: List[Table] = Field(default_factory=list)
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "Pawprint Models",
|
||||
"description": "Platform-agnostic model definitions. Portable to TypeScript, Pydantic, Django, Prisma.",
|
||||
"definitions": {
|
||||
"Status": {
|
||||
"type": "string",
|
||||
"enum": ["pending", "planned", "building", "dev", "live", "ready"]
|
||||
},
|
||||
"System": {
|
||||
"type": "string",
|
||||
"enum": ["artery", "album", "ward"]
|
||||
},
|
||||
"Nest": {
|
||||
"type": "object",
|
||||
"description": "Runtime environment configuration. Shared across artery, ward.",
|
||||
"properties": {
|
||||
"name": { "type": "string", "description": "Unique identifier" },
|
||||
"slug": { "type": "string", "description": "URL-friendly identifier" },
|
||||
"title": { "type": "string", "description": "Display title for UI" },
|
||||
"status": { "$ref": "#/definitions/Status" },
|
||||
"config_path": { "type": "string" }
|
||||
},
|
||||
"required": ["name", "slug", "title"]
|
||||
},
|
||||
"Larder": {
|
||||
"type": "object",
|
||||
"description": "Data storage. When generated from Template = 'Book (written)'. Independent in ward/artery.",
|
||||
"properties": {
|
||||
"name": { "type": "string", "description": "Unique identifier" },
|
||||
"slug": { "type": "string", "description": "URL-friendly identifier" },
|
||||
"title": { "type": "string", "description": "Display title for UI" },
|
||||
"status": { "$ref": "#/definitions/Status" },
|
||||
"source_template": { "type": "string", "description": "Template name if generated" },
|
||||
"data_path": { "type": "string", "description": "Path to data files" }
|
||||
},
|
||||
"required": ["name", "slug", "title"]
|
||||
},
|
||||
"Vein": {
|
||||
"type": "object",
|
||||
"description": "Connector (artery). Single responsibility.",
|
||||
"properties": {
|
||||
"name": { "type": "string", "description": "Unique identifier" },
|
||||
"slug": { "type": "string", "description": "URL-friendly identifier" },
|
||||
"title": { "type": "string", "description": "Display title for UI" },
|
||||
"status": { "$ref": "#/definitions/Status" },
|
||||
"system": { "const": "artery" }
|
||||
},
|
||||
"required": ["name", "slug", "title"]
|
||||
},
|
||||
"Template": {
|
||||
"type": "object",
|
||||
"description": "Documentation template (album). Gherkin, BDD patterns.",
|
||||
"properties": {
|
||||
"name": { "type": "string", "description": "Unique identifier" },
|
||||
"slug": { "type": "string", "description": "URL-friendly identifier" },
|
||||
"title": { "type": "string", "description": "Display title for UI" },
|
||||
"status": { "$ref": "#/definitions/Status" },
|
||||
"template_path": { "type": "string", "description": "Path to template files" },
|
||||
"system": { "const": "album" }
|
||||
},
|
||||
"required": ["name", "slug", "title"]
|
||||
},
|
||||
"ToolType": {
|
||||
"type": "string",
|
||||
"enum": ["app", "cli"],
|
||||
"description": "Type of tool: app (web UI) or cli (command line)"
|
||||
},
|
||||
"Tool": {
|
||||
"type": "object",
|
||||
"description": "Execution tool (ward). Test runners, seeders.",
|
||||
"properties": {
|
||||
"name": { "type": "string", "description": "Unique identifier" },
|
||||
"slug": { "type": "string", "description": "URL-friendly identifier" },
|
||||
"title": { "type": "string", "description": "Display title for UI" },
|
||||
"status": { "$ref": "#/definitions/Status" },
|
||||
"system": { "const": "ward" },
|
||||
"type": { "$ref": "#/definitions/ToolType" },
|
||||
"description": { "type": "string", "description": "Human-readable description" },
|
||||
"path": { "type": "string", "description": "Path to tool source" },
|
||||
"url": { "type": "string", "description": "URL path for app tools" },
|
||||
"cli": { "type": "string", "description": "CLI command for cli tools" }
|
||||
},
|
||||
"required": ["name", "slug", "title"]
|
||||
},
|
||||
"Monitor": {
|
||||
"type": "object",
|
||||
"description": "Service monitor (ward). Health checks, status watchers.",
|
||||
"properties": {
|
||||
"name": { "type": "string", "description": "Unique identifier" },
|
||||
"slug": { "type": "string", "description": "URL-friendly identifier" },
|
||||
"title": { "type": "string", "description": "Display title for UI" },
|
||||
"status": { "$ref": "#/definitions/Status" },
|
||||
"system": { "const": "ward" }
|
||||
},
|
||||
"required": ["name", "slug", "title"]
|
||||
},
|
||||
"Cabinet": {
|
||||
"type": "object",
|
||||
"description": "Tool cabinet (ward). Contains 0+ tools.",
|
||||
"properties": {
|
||||
"name": { "type": "string", "description": "Unique identifier" },
|
||||
"slug": { "type": "string", "description": "URL-friendly identifier" },
|
||||
"title": { "type": "string", "description": "Display title for UI" },
|
||||
"status": { "$ref": "#/definitions/Status" },
|
||||
"tools": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/definitions/Tool" }
|
||||
},
|
||||
"system": { "const": "ward" }
|
||||
},
|
||||
"required": ["name", "slug", "title"]
|
||||
},
|
||||
"Pulse": {
|
||||
"type": "object",
|
||||
"description": "Composed data flow (artery). Pulse = Vein + Nest + Larder.",
|
||||
"properties": {
|
||||
"name": { "type": "string", "description": "Unique identifier" },
|
||||
"slug": { "type": "string", "description": "URL-friendly identifier" },
|
||||
"title": { "type": "string", "description": "Display title for UI" },
|
||||
"status": { "$ref": "#/definitions/Status" },
|
||||
"vein": { "$ref": "#/definitions/Vein" },
|
||||
"nest": { "$ref": "#/definitions/Nest" },
|
||||
"larder": { "$ref": "#/definitions/Larder" },
|
||||
"system": { "const": "artery" }
|
||||
},
|
||||
"required": ["name", "slug", "title"]
|
||||
},
|
||||
"Book": {
|
||||
"type": "object",
|
||||
"description": "Composed documentation (album). Book = Template + Larder.",
|
||||
"properties": {
|
||||
"name": { "type": "string", "description": "Unique identifier" },
|
||||
"slug": { "type": "string", "description": "URL-friendly identifier" },
|
||||
"title": { "type": "string", "description": "Display title for UI" },
|
||||
"status": { "$ref": "#/definitions/Status" },
|
||||
"template": { "$ref": "#/definitions/Template" },
|
||||
"larder": { "$ref": "#/definitions/Larder" },
|
||||
"output_larder": { "$ref": "#/definitions/Larder" },
|
||||
"system": { "const": "album" }
|
||||
},
|
||||
"required": ["name", "slug", "title"]
|
||||
},
|
||||
"Table": {
|
||||
"type": "object",
|
||||
"description": "Composed execution bundle (ward). Table = Cabinet + Nest + Larders.",
|
||||
"properties": {
|
||||
"name": { "type": "string", "description": "Unique identifier" },
|
||||
"slug": { "type": "string", "description": "URL-friendly identifier" },
|
||||
"title": { "type": "string", "description": "Display title for UI" },
|
||||
"status": { "$ref": "#/definitions/Status" },
|
||||
"cabinet": { "$ref": "#/definitions/Cabinet" },
|
||||
"nest": { "$ref": "#/definitions/Nest" },
|
||||
"larders": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/definitions/Larder" }
|
||||
},
|
||||
"system": { "const": "ward" }
|
||||
},
|
||||
"required": ["name", "slug", "title"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |