initial commit
All checks were successful
Build & publish Docker images / Build & push all images (push) Successful in 2s

This commit is contained in:
Hexadual
2026-04-30 21:11:07 -05:00
commit 18a8051600
8 changed files with 233 additions and 0 deletions

4
.gitattributes vendored Normal file
View File

@@ -0,0 +1,4 @@
* text=auto
Dockerfile text eol=lf
*.sh text eol=lf
*.py text eol=lf

View File

@@ -0,0 +1,43 @@
name: Build & publish Docker images
on:
push:
branches: [main]
release:
types: [published]
env:
REGISTRY: git.hexadual.io
jobs:
build:
name: Build & push all images
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout
run: |
git clone --depth 1 \
https://${{ github.actor }}:${{ secrets.GITHUB_TOKEN }}@git.hexadual.io/${{ github.repository }}.git \
.
git checkout ${{ github.sha }}
- name: Log in to registry
run: |
echo "${{ secrets.REGISTRY_TOKEN }}" | \
docker login ${{ env.REGISTRY }} -u ${{ github.actor }} --password-stdin
- name: Build & push egg
run: |
docker compose build egg
docker compose push egg
docker tag ${{ env.REGISTRY }}/rocobo/gcp-dot-egg:latest \
${{ env.REGISTRY }}/rocobo/gcp-dot-egg:${{ github.sha }}
docker push ${{ env.REGISTRY }}/rocobo/gcp-dot-egg:${{ github.sha }}
- name: Logout
if: always()
run: docker logout ${{ env.REGISTRY }} || true

6
.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
__pycache__/
*.pyc
*.pyo
.env
*.db
.DS_Store

12
Dockerfile Normal file
View File

@@ -0,0 +1,12 @@
FROM python:3.14-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY egg.py .
VOLUME ["/data"]
CMD ["python", "egg.py"]

84
README.md Normal file
View File

@@ -0,0 +1,84 @@
# GCP Egg
Distributed client for the **Global Consciousness Project** — a self-hosted network variance tracker inspired by the [Global Consciousness Project](https://global-mind.org).
Each "egg" container draws 200 random bits per second from the OS hardware-entropy pool and submits the count of 1-bits to a central server, which runs Stouffer Z-score analysis and displays a live colored dot.
## Architecture
```
Egg containers (anyone can run)
│ POST /api/data (one 200-bit trial per second)
Server (FastAPI + SQLite)
│ Stouffer Z network variance analysis every 60 s
Website → animated dot + history chart + embeddable iframe
```
The server is maintained separately. This repo contains only the egg client.
## Run an Egg
Download the compose file and start it — no building required:
```bash
curl -O https://git.hexadual.io/rocobo/GCP-Dot/raw/branch/main/docker-compose.yml
docker compose up -d
```
Docker will pull the pre-built image from the registry automatically. The egg will immediately start sending one trial per second and persist its ID across restarts.
## Environment Variables
| Variable | Default | Description |
|---|---|---|
| `SERVER_URL` | `https://gcp.hexadual.io` | Server to send trials to |
| `EGG_ID` | auto-generated | Override the egg's unique identifier |
The auto-generated ID is derived from a SHA-256 hash stored at `/data/egg_id` — mount a volume there to keep it stable across restarts.
## Published Image
The egg image is built and published automatically on every push to `main`:
```bash
docker pull git.hexadual.io/rocobo/gcp-dot-egg:latest
```
## How the Analysis Works
The server analyses the past hour of data every 60 seconds:
1. **Normalise** each trial to a Z-score: `z = (trial 100) / √50`
(Binomial(200, 0.5) has mean = 100, variance = 50)
2. **Stouffer Z** per second across all active eggs: `S_t = Σzᵢ / √N`
3. **Network variance**: `V = Σ S_t²` — follows χ²(T) under H₀
4. **Index** = lower-tail CDF × 100
### Color Table
| Color | Index | Meaning |
|---|---|---|
| Blue | > 95% | Significantly small variance — deep coherence |
| Cyan | 9095% | Small variance — probable coherence |
| Green | 4090% | Normal random behavior |
| Yellow | 1040% | Slightly elevated variance |
| Orange | 510% | Strongly elevated variance |
| Red | < 5% | Significantly large variance |
## Embed the Dot
```html
<iframe src="https://gcp.hexadual.io/gcp.html"
height="48" width="48" scrolling="no" frameborder="0"></iframe>
```
## Server API Reference
| Endpoint | Description |
|---|---|
| `POST /api/data` | Submit a trial `{egg_id, timestamp, trial}` |
| `GET /api/status` | Latest analysis result |
| `GET /api/history?limit=60` | Last N analysis records |
| `GET /api/eggs` | Eggs active in the last 2 minutes |

12
docker-compose.yml Normal file
View File

@@ -0,0 +1,12 @@
services:
egg:
image: git.hexadual.io/rocobo/gcp-dot-egg:latest
volumes:
- gcp_egg_data:/data
restart: unless-stopped
environment:
- SERVER_URL=https://gcp.hexadual.io
- PYTHONUNBUFFERED=1
volumes:
gcp_egg_data:

71
egg.py Normal file
View File

@@ -0,0 +1,71 @@
import os
import time
import hashlib
import platform
import requests
ID_FILE = "/data/egg_id"
def generate_trial():
"""Sum of 200 random bits drawn from the OS CSPRNG (hardware entropy pool)."""
raw = os.urandom(25) # 25 bytes = 200 bits
return sum(bin(b).count("1") for b in raw)
def load_or_create_id():
try:
with open(ID_FILE) as f:
egg_id = f.read().strip()
if egg_id:
return egg_id
except OSError:
pass
egg_id = hashlib.sha256(os.urandom(32)).hexdigest()[:16]
try:
os.makedirs("/data", exist_ok=True)
with open(ID_FILE, "w") as f:
f.write(egg_id)
except OSError:
pass
return egg_id
def main():
server_url = os.environ.get("SERVER_URL", "http://localhost:8000").rstrip("/")
egg_id = os.environ.get("EGG_ID") or load_or_create_id()
print(f"GCP Egg id={egg_id} server={server_url} platform={platform.system()}")
session = requests.Session()
errors = 0
while True:
loop_start = time.time()
timestamp = int(loop_start)
trial = generate_trial()
try:
resp = session.post(
f"{server_url}/api/data",
json={"egg_id": egg_id, "timestamp": timestamp, "trial": trial},
timeout=5,
)
if resp.status_code == 200:
errors = 0
else:
errors += 1
if errors % 10 == 1:
print(f"Server returned {resp.status_code} (error #{errors})")
except Exception as exc:
errors += 1
if errors % 10 == 1:
print(f"Send error (#{errors}): {exc}")
elapsed = time.time() - loop_start
time.sleep(max(0.0, 1.0 - elapsed))
if __name__ == "__main__":
main()

1
requirements.txt Normal file
View File

@@ -0,0 +1 @@
requests>=2.32.0