← DEEP CYGNUS
🛡

PKA Mainframe Integration Strategy

Shore Party / Claude Cowork Technical Ecosystem Audit

Prepared by: Neo, Chief Code Architect

Date: 2026-03-28

Status: For Will's review


1. Current State Audit

1.1 The Mainframe (What Exists Today)

The mainframe (mainframe.py) is a SQLite database with six tables:

TablePurposeRecords
team_membersPKA team roster4 (founding team)
projectsProject trackingEmpty
tasksTask managementEmpty
task_notesActivity log per taskEmpty
deliverablesWork product trackingEmpty
skillsTeam member capabilities17 (Neo's skills)
comms_logInter-team communicationsEmpty

The mainframe is clean, well-structured, and ready for extension. It has no knowledge of vessels, routes, positions, activity zones, or any Shore Party operational data.

1.2 External Systems Inventory

A. Activity Intelligence Engine (Claude Skill)

B. MarineTraffic / Vessel Intelligence (Claude Skill)

C. Shore Party Proxy (Cloudflare Worker)

D. Shore Party Master Document

E. Notion (via MCP)

F. Gmail + Google Calendar (via MCP)


2. Integration Architecture

2.1 Design Principles

  1. SQLite stays as the core. The mainframe is lightweight and portable. No need to migrate to Postgres for this workload.
  2. The mainframe is the truth store. External systems feed into it. When there is a conflict, the mainframe record wins after human review.
  3. Sync, don't replace. Notion, MarineTraffic, and RWGPS continue to function as they do. The mainframe captures snapshots and derived intelligence.
  4. File-based ingestion for skill data. The activity zones JSON and fleet registry markdown are already structured. Parse them into mainframe tables on initialization.
  5. API-based ingestion for live data. RWGPS routes, vessel positions, and weather data come through API calls and get persisted locally.

2.2 Connection Map

                      PKA MAINFRAME (SQLite)
                              |
        +----------+----------+----------+----------+
        |          |          |          |          |
   [RWGPS API]  [MarineTraffic]  [Notion]  [Open-Meteo]  [Datalastic]
        |          |          |          |               |
   File sync    Chrome MCP   MCP tools  Direct API   Cloudflare proxy
   + API pull   + Dense Track            (free)      (CORS bridge)
        |          |          |
   routes.db   positions.db  Two-way sync
   (cached)    (time-series) (vessel registry,
                              positions, captain intel)

2.3 Integration Method Per System

SystemMethodFrequencyDirection
Activity ZonesFile parse (activity_zones.json -> SQLite)On init + on changeOne-way in
Fleet RegistryFile parse (fleet-registry.md -> SQLite)On init + on changeOne-way in
RWGPS RoutesAPI pull -> SQLite cacheDaily or on-demandOne-way in
Vessel PositionsChrome MCP scrape -> SQLiteDaily (morning pull)One-way in
Notion Vessel RegistryMCP read/writeOn-demand syncTwo-way
Notion Daily PositionsMCP writeAfter each position pullOne-way out
Open-Meteo WeatherDirect API -> SQLiteOn-demand per zone/positionOne-way in
Datalastic/AISVia Cloudflare proxy -> SQLiteOn-demandOne-way in
Dense Track (MT)Chrome MCP -> SQLiteOn-demand per vesselOne-way in
Shore Party MasterReference only (not ingested)N/ARead-only

3. Database Schema Extensions

These tables would be added to mainframe.py alongside the existing schema.

3.1 Vessels

CREATE TABLE IF NOT EXISTS vessels (
    id              INTEGER PRIMARY KEY AUTOINCREMENT,
    name            TEXT NOT NULL UNIQUE,
    mmsi            TEXT,
    imo             TEXT,
    call_sign       TEXT,
    flag            TEXT,
    loa_m           REAL,
    builder         TEXT,
    build_year      INTEGER,
    owner           TEXT,
    charter_rate    TEXT,
    ice_class       TEXT,
    market_class    TEXT CHECK (market_class IN ('CHARTER', 'PRIVATE')),
    tier            INTEGER DEFAULT 3,
    mt_search_note  TEXT,
    mt_ship_id      TEXT,
    notion_page_id  TEXT,
    philosophy      TEXT,
    status          TEXT DEFAULT 'active',
    created_at      TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
    updated_at      TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
);

3.2 Fleet Membership

CREATE TABLE IF NOT EXISTS fleet_membership (
    vessel_id   INTEGER NOT NULL REFERENCES vessels(id),
    fleet       TEXT NOT NULL CHECK (fleet IN ('CHARTER', 'PRIVATE', 'DATA SET', 'TIER ONE')),
    PRIMARY KEY (vessel_id, fleet)
);

3.3 Vessel Positions (Time-Series)

CREATE TABLE IF NOT EXISTS vessel_positions (
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    vessel_id   INTEGER NOT NULL REFERENCES vessels(id),
    lat         REAL NOT NULL,
    lon         REAL NOT NULL,
    speed_kn    REAL,
    course      REAL,
    current_port TEXT,
    destination TEXT,
    nav_status  TEXT,
    source      TEXT DEFAULT 'marinetraffic',
    recorded_at TEXT NOT NULL,
    created_at  TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
);

CREATE INDEX IF NOT EXISTS idx_positions_vessel ON vessel_positions(vessel_id);
CREATE INDEX IF NOT EXISTS idx_positions_time ON vessel_positions(recorded_at);
CREATE INDEX IF NOT EXISTS idx_positions_vessel_time ON vessel_positions(vessel_id, recorded_at DESC);

3.4 Activity Zones

CREATE TABLE IF NOT EXISTS activity_zones (
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    name        TEXT NOT NULL UNIQUE,
    tier        TEXT NOT NULL,
    center_lat  REAL NOT NULL,
    center_lng  REAL NOT NULL,
    radius_nm   REAL NOT NULL,
    season      TEXT,
    notes       TEXT,
    created_at  TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
);

3.5 Routes (RWGPS Cache)

CREATE TABLE IF NOT EXISTS routes (
    id              INTEGER PRIMARY KEY,  -- RWGPS route ID (natural key)
    name            TEXT NOT NULL,
    description     TEXT,
    locality        TEXT,
    admin_area      TEXT,
    country_code    TEXT,
    distance_m      REAL,
    elevation_gain_m REAL,
    elevation_loss_m REAL,
    first_lat       REAL,
    first_lng       REAL,
    last_lat        REAL,
    last_lng        REAL,
    track_type      TEXT,
    terrain         TEXT,
    difficulty      TEXT,
    surface         TEXT,
    unpaved_pct     REAL,
    rwgps_url       TEXT,
    collection      TEXT,
    archived        INTEGER DEFAULT 0,
    synced_at       TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
);

3.6 Proximity Alerts

CREATE TABLE IF NOT EXISTS proximity_alerts (
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    vessel_id   INTEGER NOT NULL REFERENCES vessels(id),
    zone_id     INTEGER REFERENCES activity_zones(id),
    alert_type  TEXT NOT NULL CHECK (alert_type IN ('zone_entry', 'zone_exit', 'vessel_proximity', 'repositioning')),
    distance_nm REAL,
    details     TEXT,
    acknowledged INTEGER DEFAULT 0,
    created_at  TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
);

3.7 Weather Snapshots

CREATE TABLE IF NOT EXISTS weather_snapshots (
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    lat         REAL NOT NULL,
    lon         REAL NOT NULL,
    zone_id     INTEGER REFERENCES activity_zones(id),
    temp_c      REAL,
    wind_mph    REAL,
    precip_mm   REAL,
    wave_m      REAL,
    cycling_go  INTEGER,
    kayaking_go INTEGER,
    hiking_go   INTEGER,
    source      TEXT DEFAULT 'open-meteo',
    recorded_at TEXT NOT NULL,
    created_at  TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
);

3.8 Condition Gates (Reference Table)

CREATE TABLE IF NOT EXISTS condition_gates (
    activity    TEXT PRIMARY KEY,
    min_temp_f  REAL,
    max_temp_f  REAL,
    max_wind_mph REAL,
    max_precip_mm_hr REAL,
    max_wave_m  REAL,
    notes       TEXT
);

4. Priority Order

Fleet Registry + Activity Zones -> Mainframe

Why first: This is pure data ingestion from files we already control. No API keys needed, no network calls, no browser context. It gives the mainframe situational awareness -- it knows what vessels exist and what zones matter.

Deliverable: mainframe.py can answer "What vessels are in TIER ONE?", "What zones support kayaking?", "What's the season window for Mallorca?"

Phase 2: Route Library (Week 2)

RWGPS -> Mainframe

Why second: The route library is Shore Party's core IP. Caching 1,088 routes locally means any PKA team member can query routes by proximity, country, difficulty, or surface without needing browser context or API calls.

MarineTraffic -> Mainframe

Why third: This is the highest-value operational data but also the hardest to automate. Building the persistence layer first means that when positions are pulled, they go straight into the time-series table.

Phase 4: Weather + Condition Gates (Week 4)

Open-Meteo -> Mainframe

Mainframe <-> Notion


5. Questions for Will

Must Have Before Phase 2

  1. RWGPS API credentials -- The x-rwgps-api-key and x-rwgps-auth-token are needed for the route library sync. Are these stored somewhere accessible, or do I need to extract them from the browser session?
  2. Strava API credentials -- Are these configured anywhere? The skill references Strava segment intelligence but notes "when Strava integration is active." Is it active? Do you have an API token?

Must Have Before Phase 3

  1. Datalastic API key -- The Cloudflare proxy at shore-party-proxy forwards requests to api.datalastic.com. What is the API key, and what is the rate limit / monthly quota? Is this an active subscription?
  2. MarineTraffic automation preference -- The current position pull requires Chrome MCP (browser scraping). Are you open to keeping it manual, scheduling automated pulls, or exploring the paid API?

Architecture Decisions

  1. Notion as source of truth vs. mainframe as source of truth -- My recommendation: mainframe is truth for position data and intelligence; Notion is truth for vessel metadata since you edit that directly.
  2. Cloudflare proxy scope -- Should I extend it to proxy RWGPS API calls as well?
  3. Dense Track API usage -- How often do you use this? Is it worth building a local track database?

Nice to Know

  1. Website concierge bot -- Interest in connecting it to the mainframe's route/zone data?
  2. AllTrails -- Future plan or active data source?
  3. Scheduled briefings -- The "daily 9 AM fleet position task" -- currently running or aspirational?

Summary

The ecosystem is rich but fragmented. The core intelligence -- routes, vessels, zones, positions -- lives across markdown files, JSON files, browser scraping sessions, and Notion databases with no persistent local query layer. The mainframe is perfectly positioned to become that layer.

The integration is five phases over roughly five weeks. Phase 1 requires zero external dependencies. Each subsequent phase builds on the last. By the end, a single call to activity_briefing("CLOUDBREAK") would return: current position, matched activity zone, nearby routes with distances, weather conditions, GO/NO-GO status per activity, and any proximity alerts -- all from local data.

The ten questions above are ordered by urgency. The first two unlock Phase 2. The next two unlock Phase 3. The rest can be answered anytime.

Standing by.

-- Neo

Voice Reply