Compare commits
1 Commits
main
...
docs/visio
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93046a9efb |
40
.env.example
40
.env.example
@@ -1,33 +1,9 @@
|
|||||||
# Cloudflare
|
OS_ROOT=https://blackroad.systems
|
||||||
CLOUDFLARE_API_TOKEN=
|
SERVICE_BASE_URL=https://docs.blackroad.systems
|
||||||
CLOUDFLARE_ACCOUNT_ID=848cf0b18d51e0170e0d1537aec3505a
|
|
||||||
|
|
||||||
# Railway
|
NEXT_PUBLIC_OS_ROOT=https://blackroad.systems
|
||||||
RAILWAY_TOKEN=
|
NEXT_PUBLIC_SERVICE_ID=docs
|
||||||
|
NEXT_PUBLIC_SERVICE_NAME="BlackRoad OS – Docs"
|
||||||
# Vercel
|
NEXT_PUBLIC_CONSOLE_URL=https://console.blackroad.systems
|
||||||
VERCEL_TOKEN=
|
NEXT_PUBLIC_WEB_URL=https://blackroad.systems
|
||||||
|
NEXT_PUBLIC_API_URL=https://api.blackroad.systems
|
||||||
# Stripe
|
|
||||||
STRIPE_SECRET_KEY=
|
|
||||||
STRIPE_PUBLISHABLE_KEY=
|
|
||||||
STRIPE_WEBHOOK_SECRET=
|
|
||||||
|
|
||||||
# Clerk
|
|
||||||
CLERK_SECRET_KEY=
|
|
||||||
CLERK_PUBLISHABLE_KEY=
|
|
||||||
|
|
||||||
# AI APIs
|
|
||||||
OPENAI_API_KEY=
|
|
||||||
ANTHROPIC_API_KEY=
|
|
||||||
GROQ_API_KEY=
|
|
||||||
|
|
||||||
# Database
|
|
||||||
DATABASE_URL=
|
|
||||||
TURSO_DATABASE_URL=
|
|
||||||
TURSO_AUTH_TOKEN=
|
|
||||||
|
|
||||||
# Service Mesh
|
|
||||||
SERVICE_REGISTRY_URL=https://api.blackroad.io/registry
|
|
||||||
SERVICE_NAME=blackroad-os-docs
|
|
||||||
SERVICE_ORG=BlackRoad-OS
|
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
MESSAGE="${1:-Auto-commit: $(date +%Y-%m-%d\ %H:%M:%S)}"
|
|
||||||
git add -A && git commit -m "$MESSAGE" && git push 2>/dev/null || echo "⚠ Check remote"
|
|
||||||
echo "✅ Done!"
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
name: CI
|
|
||||||
on: [push, pull_request]
|
|
||||||
jobs:
|
|
||||||
lint:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Detect and lint
|
|
||||||
run: |
|
|
||||||
if [ -f package.json ]; then
|
|
||||||
npm ci --ignore-scripts 2>/dev/null || npm install --ignore-scripts
|
|
||||||
npx eslint . --ext .js,.ts,.jsx,.tsx --no-error-on-unmatched-pattern 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
if [ -f requirements.txt ] || [ -f setup.py ] || [ -f pyproject.toml ]; then
|
|
||||||
pip install ruff 2>/dev/null
|
|
||||||
ruff check . 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
if ls *.sh 2>/dev/null || ls **/*.sh 2>/dev/null; then
|
|
||||||
shellcheck *.sh **/*.sh 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
- name: Check syntax
|
|
||||||
run: |
|
|
||||||
find . -name "*.py" -exec python3 -c "import py_compile; py_compile.compile('{}', doraise=True)" \; 2>/dev/null || true
|
|
||||||
find . -name "*.sh" -exec bash -n {} \; 2>/dev/null || true
|
|
||||||
13
.github/CODEOWNERS
vendored
13
.github/CODEOWNERS
vendored
@@ -1,13 +0,0 @@
|
|||||||
# BlackRoad OS Code Owners
|
|
||||||
* @alexa
|
|
||||||
|
|
||||||
# Python services
|
|
||||||
*.py @alexa
|
|
||||||
|
|
||||||
# Railway configurations
|
|
||||||
railway*.json @alexa
|
|
||||||
railway*.toml @alexa
|
|
||||||
|
|
||||||
# Security-sensitive files
|
|
||||||
.env* @alexa
|
|
||||||
*secret* @alexa
|
|
||||||
85
.github/ISSUE_TEMPLATE/agent-task.yml
vendored
85
.github/ISSUE_TEMPLATE/agent-task.yml
vendored
@@ -1,85 +0,0 @@
|
|||||||
name: "🤖 Agent Task"
|
|
||||||
description: "For Codex or other agents to pick up"
|
|
||||||
title: "[AGENT] "
|
|
||||||
labels: ["agent-task", "automated"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
## Agent-Executable Task
|
|
||||||
This issue is designed to be picked up and executed by Codex or another AI agent.
|
|
||||||
|
|
||||||
Keep instructions clear, specific, and executable.
|
|
||||||
|
|
||||||
- type: dropdown
|
|
||||||
id: priority
|
|
||||||
attributes:
|
|
||||||
label: Priority
|
|
||||||
options:
|
|
||||||
- "P0 - Immediate"
|
|
||||||
- "P1 - Today"
|
|
||||||
- "P2 - This week"
|
|
||||||
- "P3 - When available"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: instruction
|
|
||||||
attributes:
|
|
||||||
label: Instruction
|
|
||||||
description: What should the agent do? Be specific and executable.
|
|
||||||
placeholder: |
|
|
||||||
Create a new API endpoint at /api/users/preferences that:
|
|
||||||
- Accepts GET and PUT requests
|
|
||||||
- GET returns current user preferences from database
|
|
||||||
- PUT updates preferences with validation
|
|
||||||
- Follow existing patterns in /api/users/profile
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: files
|
|
||||||
attributes:
|
|
||||||
label: Files to touch
|
|
||||||
description: Which files should be created or modified?
|
|
||||||
placeholder: |
|
|
||||||
- Create: src/pages/api/users/preferences.ts
|
|
||||||
- Modify: src/types/user.ts (add PreferencesType)
|
|
||||||
- Modify: prisma/schema.prisma (if needed)
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: done
|
|
||||||
attributes:
|
|
||||||
label: Definition of done
|
|
||||||
description: How does the agent know it's complete?
|
|
||||||
placeholder: |
|
|
||||||
- Endpoint responds correctly to GET/PUT
|
|
||||||
- TypeScript compiles without errors
|
|
||||||
- Tests pass (if tests exist for this area)
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: constraints
|
|
||||||
attributes:
|
|
||||||
label: Constraints / Don'ts
|
|
||||||
description: What should the agent avoid?
|
|
||||||
placeholder: |
|
|
||||||
- Don't modify the auth middleware
|
|
||||||
- Don't add new dependencies
|
|
||||||
- Follow existing code style
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
|
|
||||||
- type: dropdown
|
|
||||||
id: agent
|
|
||||||
attributes:
|
|
||||||
label: Assigned agent
|
|
||||||
options:
|
|
||||||
- "Codex"
|
|
||||||
- "Any available agent"
|
|
||||||
- "Specific agent (note in context)"
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
71
.github/ISSUE_TEMPLATE/bug.yml
vendored
71
.github/ISSUE_TEMPLATE/bug.yml
vendored
@@ -1,71 +0,0 @@
|
|||||||
name: "🐛 Bug"
|
|
||||||
description: "Something is broken"
|
|
||||||
title: "[BUG] "
|
|
||||||
labels: ["bug"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
## Bug Report
|
|
||||||
What's broken? Let's fix it.
|
|
||||||
|
|
||||||
- type: dropdown
|
|
||||||
id: severity
|
|
||||||
attributes:
|
|
||||||
label: Severity
|
|
||||||
description: How bad is it?
|
|
||||||
options:
|
|
||||||
- "🔥 Critical - Production down, data loss, security issue"
|
|
||||||
- "🟠 High - Major feature broken, no workaround"
|
|
||||||
- "🟡 Medium - Feature broken but has workaround"
|
|
||||||
- "🟢 Low - Minor issue, cosmetic, edge case"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: what
|
|
||||||
attributes:
|
|
||||||
label: What's broken?
|
|
||||||
description: One sentence description
|
|
||||||
placeholder: "Login button doesn't work on mobile Safari"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: expected
|
|
||||||
attributes:
|
|
||||||
label: Expected behavior
|
|
||||||
description: What should happen?
|
|
||||||
placeholder: "Clicking login should open the auth modal"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: actual
|
|
||||||
attributes:
|
|
||||||
label: Actual behavior
|
|
||||||
description: What actually happens?
|
|
||||||
placeholder: "Nothing happens. Console shows: TypeError..."
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: repro
|
|
||||||
attributes:
|
|
||||||
label: How to reproduce
|
|
||||||
description: Steps to trigger the bug
|
|
||||||
placeholder: |
|
|
||||||
1. Open site on iPhone Safari
|
|
||||||
2. Tap Login button
|
|
||||||
3. Nothing happens
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: context
|
|
||||||
attributes:
|
|
||||||
label: Environment / Context
|
|
||||||
description: Browser, OS, device, account type, etc.
|
|
||||||
placeholder: "iOS 17, Safari, iPhone 15 Pro"
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
6
.github/ISSUE_TEMPLATE/config.yml
vendored
6
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,5 +1,5 @@
|
|||||||
blank_issues_enabled: true
|
blank_issues_enabled: true
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: "💬 Quick question / discussion"
|
- name: BlackRoad OS Docs
|
||||||
url: https://github.com/YOUR_USERNAME/YOUR_REPO/discussions
|
url: https://github.com/BlackRoad-OS/blackroad-os-docs
|
||||||
about: "For questions, ideas, or discussions that aren't actionable tasks yet"
|
about: Check the docs before opening an issue
|
||||||
|
|||||||
65
.github/ISSUE_TEMPLATE/task.yml
vendored
65
.github/ISSUE_TEMPLATE/task.yml
vendored
@@ -1,65 +0,0 @@
|
|||||||
name: "🎯 Task"
|
|
||||||
description: "Standard work item - features, changes, improvements"
|
|
||||||
title: "[TASK] "
|
|
||||||
labels: ["task"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
## Quick Task Creation
|
|
||||||
Keep it simple. One task = one thing to do.
|
|
||||||
|
|
||||||
- type: dropdown
|
|
||||||
id: priority
|
|
||||||
attributes:
|
|
||||||
label: Priority
|
|
||||||
description: How urgent is this?
|
|
||||||
options:
|
|
||||||
- "P0 - Do it now (blocks everything)"
|
|
||||||
- "P1 - Today"
|
|
||||||
- "P2 - This week"
|
|
||||||
- "P3 - Backlog"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: what
|
|
||||||
attributes:
|
|
||||||
label: What needs to happen?
|
|
||||||
description: One sentence. If it's more than one sentence, split into multiple issues.
|
|
||||||
placeholder: "Add a logout button to the nav bar"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: done
|
|
||||||
attributes:
|
|
||||||
label: Definition of done
|
|
||||||
description: How do we know this is complete?
|
|
||||||
placeholder: |
|
|
||||||
- Logout button visible in nav
|
|
||||||
- Clicking it clears session and redirects to /login
|
|
||||||
- Works on mobile
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: context
|
|
||||||
attributes:
|
|
||||||
label: Context (optional)
|
|
||||||
description: Any additional info that helps
|
|
||||||
placeholder: "Related to issue #45. See Figma design at..."
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
|
|
||||||
- type: dropdown
|
|
||||||
id: assignee
|
|
||||||
attributes:
|
|
||||||
label: Who should handle this?
|
|
||||||
description: Human or agent?
|
|
||||||
options:
|
|
||||||
- "Codex / Agent"
|
|
||||||
- "Human (me)"
|
|
||||||
- "Unassigned - triage needed"
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
49
.github/PULL_REQUEST_TEMPLATE.md
vendored
49
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,24 +1,39 @@
|
|||||||
# Pull Request
|
## Summary
|
||||||
|
<!-- What does this PR do? One paragraph max. -->
|
||||||
|
|
||||||
## Description
|
## Changes
|
||||||
|
<!-- Bulleted list of specific changes -->
|
||||||
|
-
|
||||||
|
|
||||||
## Type of Change
|
## Type
|
||||||
|
<!-- Check one -->
|
||||||
|
- [ ] Feature
|
||||||
- [ ] Bug fix
|
- [ ] Bug fix
|
||||||
- [ ] New feature
|
- [ ] Infrastructure / CI
|
||||||
- [ ] Breaking change
|
- [ ] Documentation
|
||||||
- [ ] Documentation update
|
- [ ] Refactor
|
||||||
- [ ] Infrastructure/DevOps change
|
- [ ] Config change
|
||||||
|
|
||||||
## Testing
|
## Tests
|
||||||
- [ ] Tested locally
|
<!-- How was this tested? -->
|
||||||
- [ ] Health checks pass
|
- [ ] Unit tests pass
|
||||||
- [ ] Railway deployment succeeds
|
- [ ] Integration tests pass
|
||||||
|
- [ ] Manual testing (describe below)
|
||||||
|
- [ ] N/A (docs only)
|
||||||
|
|
||||||
|
**Manual testing steps:**
|
||||||
|
|
||||||
|
|
||||||
|
## Risk / Impact
|
||||||
|
<!-- What could go wrong? What's the blast radius? -->
|
||||||
|
- Risk level: Low / Medium / High
|
||||||
|
- Affected services:
|
||||||
|
|
||||||
## Checklist
|
## Checklist
|
||||||
- [ ] Code follows project style
|
- [ ] Code follows project conventions
|
||||||
- [ ] Self-reviewed code
|
- [ ] No secrets or credentials committed
|
||||||
- [ ] Updated documentation
|
- [ ] README updated (if applicable)
|
||||||
- [ ] Tests pass
|
- [ ] This is a single logical change (atomic PR)
|
||||||
|
|
||||||
---
|
## Related Issues
|
||||||
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
<!-- Closes #123, Relates to #456 -->
|
||||||
|
|||||||
111
.github/workflows/agent-code-review.yml
vendored
111
.github/workflows/agent-code-review.yml
vendored
@@ -1,111 +0,0 @@
|
|||||||
name: "🤖 Agent: Code Review"
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
code-review:
|
|
||||||
name: Code Review Agent
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Get changed files
|
|
||||||
id: changed-files
|
|
||||||
uses: tj-actions/changed-files@v44
|
|
||||||
with:
|
|
||||||
files: |
|
|
||||||
**/*.ts
|
|
||||||
**/*.tsx
|
|
||||||
**/*.js
|
|
||||||
**/*.jsx
|
|
||||||
**/*.py
|
|
||||||
**/*.go
|
|
||||||
|
|
||||||
- name: Analyze code quality
|
|
||||||
if: steps.changed-files.outputs.any_changed == 'true'
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const changedFiles = '${{ steps.changed-files.outputs.all_changed_files }}'.split(' ').filter(f => f);
|
|
||||||
|
|
||||||
let reviewComments = [];
|
|
||||||
let summary = '## 🤖 Code Review Agent Report\n\n';
|
|
||||||
summary += `Analyzed **${changedFiles.length}** changed files.\n\n`;
|
|
||||||
|
|
||||||
// Analyze patterns
|
|
||||||
const patterns = {
|
|
||||||
'console.log': { severity: 'warning', msg: 'Consider removing debug logs before merging' },
|
|
||||||
'TODO': { severity: 'info', msg: 'Found TODO comment - ensure this is tracked' },
|
|
||||||
'FIXME': { severity: 'warning', msg: 'FIXME found - should be addressed' },
|
|
||||||
'any': { severity: 'warning', msg: 'Avoid using `any` type - prefer specific types' },
|
|
||||||
'eslint-disable': { severity: 'info', msg: 'ESLint rule disabled - ensure this is intentional' },
|
|
||||||
'password': { severity: 'error', msg: '⚠️ Possible hardcoded credential detected' },
|
|
||||||
'secret': { severity: 'error', msg: '⚠️ Possible secret in code' },
|
|
||||||
};
|
|
||||||
|
|
||||||
const { execSync } = require('child_process');
|
|
||||||
let issues = { error: 0, warning: 0, info: 0 };
|
|
||||||
|
|
||||||
for (const file of changedFiles) {
|
|
||||||
try {
|
|
||||||
const content = require('fs').readFileSync(file, 'utf8');
|
|
||||||
const lines = content.split('\n');
|
|
||||||
|
|
||||||
lines.forEach((line, idx) => {
|
|
||||||
for (const [pattern, config] of Object.entries(patterns)) {
|
|
||||||
if (line.toLowerCase().includes(pattern.toLowerCase())) {
|
|
||||||
issues[config.severity]++;
|
|
||||||
reviewComments.push(`- **${file}:${idx + 1}** [${config.severity.toUpperCase()}] ${config.msg}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
// File might not exist in working directory
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build summary
|
|
||||||
if (issues.error > 0) {
|
|
||||||
summary += `### ❌ Errors: ${issues.error}\n`;
|
|
||||||
}
|
|
||||||
if (issues.warning > 0) {
|
|
||||||
summary += `### ⚠️ Warnings: ${issues.warning}\n`;
|
|
||||||
}
|
|
||||||
if (issues.info > 0) {
|
|
||||||
summary += `### ℹ️ Info: ${issues.info}\n`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reviewComments.length > 0) {
|
|
||||||
summary += '\n### Details\n\n';
|
|
||||||
summary += reviewComments.slice(0, 20).join('\n');
|
|
||||||
if (reviewComments.length > 20) {
|
|
||||||
summary += `\n\n*...and ${reviewComments.length - 20} more issues*`;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
summary += '\n✅ No issues found! Code looks good.\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
summary += '\n\n---\n*🤖 Automated review by Code Review Agent*';
|
|
||||||
|
|
||||||
// Post comment
|
|
||||||
await github.rest.issues.createComment({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: context.payload.pull_request.number,
|
|
||||||
body: summary
|
|
||||||
});
|
|
||||||
|
|
||||||
// Fail if errors found
|
|
||||||
if (issues.error > 0) {
|
|
||||||
core.setFailed(`Found ${issues.error} error(s) in code review`);
|
|
||||||
}
|
|
||||||
137
.github/workflows/agent-documentation.yml
vendored
137
.github/workflows/agent-documentation.yml
vendored
@@ -1,137 +0,0 @@
|
|||||||
name: "📚 Agent: Documentation"
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
documentation:
|
|
||||||
name: Documentation Agent
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Get changed files
|
|
||||||
id: changed-files
|
|
||||||
uses: tj-actions/changed-files@v44
|
|
||||||
|
|
||||||
- name: Analyze documentation coverage
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
const changedFiles = '${{ steps.changed-files.outputs.all_changed_files }}'.split(' ').filter(f => f);
|
|
||||||
|
|
||||||
let report = '## 📚 Documentation Agent Report\n\n';
|
|
||||||
let suggestions = [];
|
|
||||||
let stats = {
|
|
||||||
codeFiles: 0,
|
|
||||||
docFiles: 0,
|
|
||||||
hasJsdoc: 0,
|
|
||||||
missingJsdoc: 0,
|
|
||||||
readmeUpdated: false
|
|
||||||
};
|
|
||||||
|
|
||||||
// Categorize files
|
|
||||||
const codeExtensions = ['.ts', '.tsx', '.js', '.jsx', '.py', '.go'];
|
|
||||||
const docExtensions = ['.md', '.mdx', '.rst', '.txt'];
|
|
||||||
|
|
||||||
for (const file of changedFiles) {
|
|
||||||
const ext = path.extname(file);
|
|
||||||
|
|
||||||
if (codeExtensions.includes(ext)) {
|
|
||||||
stats.codeFiles++;
|
|
||||||
|
|
||||||
// Check for JSDoc/docstrings
|
|
||||||
try {
|
|
||||||
const content = fs.readFileSync(file, 'utf8');
|
|
||||||
|
|
||||||
// Check for exported functions without documentation
|
|
||||||
const exportedFunctions = content.match(/export\s+(async\s+)?function\s+\w+/g) || [];
|
|
||||||
const jsdocBlocks = content.match(/\/\*\*[\s\S]*?\*\//g) || [];
|
|
||||||
|
|
||||||
if (exportedFunctions.length > jsdocBlocks.length) {
|
|
||||||
stats.missingJsdoc++;
|
|
||||||
suggestions.push(`📝 **${file}**: Consider adding JSDoc comments to exported functions`);
|
|
||||||
} else if (jsdocBlocks.length > 0) {
|
|
||||||
stats.hasJsdoc++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for complex functions that need docs
|
|
||||||
const lines = content.split('\n').length;
|
|
||||||
if (lines > 200 && jsdocBlocks.length === 0) {
|
|
||||||
suggestions.push(`📖 **${file}**: Large file (${lines} lines) without documentation`);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
// File might not exist
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (docExtensions.includes(ext)) {
|
|
||||||
stats.docFiles++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file.toLowerCase().includes('readme')) {
|
|
||||||
stats.readmeUpdated = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build report
|
|
||||||
report += '### 📊 Documentation Stats\n\n';
|
|
||||||
report += `| Metric | Value |\n`;
|
|
||||||
report += `|--------|-------|\n`;
|
|
||||||
report += `| Code files changed | ${stats.codeFiles} |\n`;
|
|
||||||
report += `| Doc files changed | ${stats.docFiles} |\n`;
|
|
||||||
report += `| Files with JSDoc | ${stats.hasJsdoc} |\n`;
|
|
||||||
report += `| Files needing docs | ${stats.missingJsdoc} |\n`;
|
|
||||||
report += `| README updated | ${stats.readmeUpdated ? '✅' : '❌'} |\n\n`;
|
|
||||||
|
|
||||||
// Calculate documentation score
|
|
||||||
const docScore = stats.codeFiles > 0
|
|
||||||
? Math.round((stats.hasJsdoc / stats.codeFiles) * 100)
|
|
||||||
: 100;
|
|
||||||
|
|
||||||
report += `### 📈 Documentation Score: ${docScore}%\n\n`;
|
|
||||||
|
|
||||||
if (docScore >= 80) {
|
|
||||||
report += '✅ Great documentation coverage!\n\n';
|
|
||||||
} else if (docScore >= 50) {
|
|
||||||
report += '⚠️ Documentation could be improved.\n\n';
|
|
||||||
} else {
|
|
||||||
report += '❌ Documentation coverage is low. Please add docs.\n\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Suggestions
|
|
||||||
if (suggestions.length > 0) {
|
|
||||||
report += '### 💡 Suggestions\n\n';
|
|
||||||
suggestions.slice(0, 10).forEach(s => report += `- ${s}\n`);
|
|
||||||
if (suggestions.length > 10) {
|
|
||||||
report += `\n*...and ${suggestions.length - 10} more suggestions*\n`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tips
|
|
||||||
if (stats.codeFiles > 0 && !stats.readmeUpdated) {
|
|
||||||
report += '\n### 💡 Tip\n';
|
|
||||||
report += 'Consider updating the README if this PR introduces new features or API changes.\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
report += '\n---\n*📚 Automated review by Documentation Agent*';
|
|
||||||
|
|
||||||
// Post comment
|
|
||||||
await github.rest.issues.createComment({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: context.payload.pull_request.number,
|
|
||||||
body: report
|
|
||||||
});
|
|
||||||
180
.github/workflows/agent-performance.yml
vendored
180
.github/workflows/agent-performance.yml
vendored
@@ -1,180 +0,0 @@
|
|||||||
name: "⚡ Agent: Performance"
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
performance:
|
|
||||||
name: Performance Agent
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Get PR stats
|
|
||||||
id: pr-stats
|
|
||||||
run: |
|
|
||||||
# Get diff stats
|
|
||||||
ADDITIONS=$(git diff --shortstat origin/${{ github.base_ref }}...HEAD | grep -oP '\d+(?= insertion)' || echo 0)
|
|
||||||
DELETIONS=$(git diff --shortstat origin/${{ github.base_ref }}...HEAD | grep -oP '\d+(?= deletion)' || echo 0)
|
|
||||||
FILES_CHANGED=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | wc -l)
|
|
||||||
|
|
||||||
echo "additions=$ADDITIONS" >> $GITHUB_OUTPUT
|
|
||||||
echo "deletions=$DELETIONS" >> $GITHUB_OUTPUT
|
|
||||||
echo "files_changed=$FILES_CHANGED" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Analyze bundle size impact
|
|
||||||
id: bundle
|
|
||||||
run: |
|
|
||||||
# Check if package.json exists and get dependencies
|
|
||||||
if [ -f "package.json" ]; then
|
|
||||||
DEPS=$(cat package.json | jq '.dependencies | length // 0')
|
|
||||||
DEV_DEPS=$(cat package.json | jq '.devDependencies | length // 0')
|
|
||||||
echo "deps=$DEPS" >> $GITHUB_OUTPUT
|
|
||||||
echo "dev_deps=$DEV_DEPS" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "deps=0" >> $GITHUB_OUTPUT
|
|
||||||
echo "dev_deps=0" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Get changed files
|
|
||||||
id: changed-files
|
|
||||||
uses: tj-actions/changed-files@v44
|
|
||||||
|
|
||||||
- name: Performance analysis
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
const changedFiles = '${{ steps.changed-files.outputs.all_changed_files }}'.split(' ').filter(f => f);
|
|
||||||
const additions = parseInt('${{ steps.pr-stats.outputs.additions }}') || 0;
|
|
||||||
const deletions = parseInt('${{ steps.pr-stats.outputs.deletions }}') || 0;
|
|
||||||
const filesChanged = parseInt('${{ steps.pr-stats.outputs.files_changed }}') || 0;
|
|
||||||
const deps = parseInt('${{ steps.bundle.outputs.deps }}') || 0;
|
|
||||||
const devDeps = parseInt('${{ steps.bundle.outputs.dev_deps }}') || 0;
|
|
||||||
|
|
||||||
let report = '## ⚡ Performance Agent Report\n\n';
|
|
||||||
let warnings = [];
|
|
||||||
let suggestions = [];
|
|
||||||
|
|
||||||
// PR Size Analysis
|
|
||||||
report += '### 📦 PR Size Analysis\n\n';
|
|
||||||
report += `| Metric | Value |\n`;
|
|
||||||
report += `|--------|-------|\n`;
|
|
||||||
report += `| Files changed | ${filesChanged} |\n`;
|
|
||||||
report += `| Lines added | +${additions} |\n`;
|
|
||||||
report += `| Lines removed | -${deletions} |\n`;
|
|
||||||
report += `| Net change | ${additions - deletions > 0 ? '+' : ''}${additions - deletions} |\n`;
|
|
||||||
report += `| Dependencies | ${deps} |\n`;
|
|
||||||
report += `| Dev Dependencies | ${devDeps} |\n\n`;
|
|
||||||
|
|
||||||
// PR Size Rating
|
|
||||||
const totalChanges = additions + deletions;
|
|
||||||
let sizeRating = '';
|
|
||||||
if (totalChanges < 100) {
|
|
||||||
sizeRating = '🟢 Small PR - Easy to review';
|
|
||||||
} else if (totalChanges < 500) {
|
|
||||||
sizeRating = '🟡 Medium PR - Moderate review effort';
|
|
||||||
} else if (totalChanges < 1000) {
|
|
||||||
sizeRating = '🟠 Large PR - Consider breaking down';
|
|
||||||
warnings.push('Large PR detected. Consider splitting into smaller PRs for easier review.');
|
|
||||||
} else {
|
|
||||||
sizeRating = '🔴 Very Large PR - Difficult to review';
|
|
||||||
warnings.push('Very large PR! This will be difficult to review. Strongly consider breaking into smaller PRs.');
|
|
||||||
}
|
|
||||||
report += `**Size Rating:** ${sizeRating}\n\n`;
|
|
||||||
|
|
||||||
// Performance patterns check
|
|
||||||
report += '### 🔍 Performance Patterns\n\n';
|
|
||||||
|
|
||||||
const perfPatterns = [
|
|
||||||
{ pattern: /\.forEach\s*\(/g, msg: 'forEach loop - consider for...of for better performance', severity: 'info' },
|
|
||||||
{ pattern: /JSON\.parse\s*\(.*JSON\.stringify/g, msg: 'Deep clone via JSON - consider structuredClone()', severity: 'warning' },
|
|
||||||
{ pattern: /new\s+RegExp\s*\(/g, msg: 'Dynamic RegExp creation - consider caching if used repeatedly', severity: 'info' },
|
|
||||||
{ pattern: /document\.querySelector.*loop|for.*querySelector/gi, msg: 'DOM query in loop - cache selectors outside loop', severity: 'warning' },
|
|
||||||
{ pattern: /\bawait\b.*\bawait\b.*\bawait\b/g, msg: 'Multiple sequential awaits - consider Promise.all()', severity: 'warning' },
|
|
||||||
{ pattern: /\.filter\(.*\)\.map\(/g, msg: 'filter().map() chain - consider reduce() or single pass', severity: 'info' },
|
|
||||||
{ pattern: /useEffect.*\[\s*\]/g, msg: 'Empty dependency array - ensure this is intentional', severity: 'info' },
|
|
||||||
{ pattern: /new\s+Date\(\).*loop|for.*new\s+Date/gi, msg: 'Date creation in loop - cache Date object', severity: 'warning' },
|
|
||||||
];
|
|
||||||
|
|
||||||
let patternFindings = [];
|
|
||||||
|
|
||||||
for (const file of changedFiles) {
|
|
||||||
try {
|
|
||||||
const content = fs.readFileSync(file, 'utf8');
|
|
||||||
|
|
||||||
for (const { pattern, msg, severity } of perfPatterns) {
|
|
||||||
if (pattern.test(content)) {
|
|
||||||
patternFindings.push({ file, msg, severity });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check file size
|
|
||||||
const lines = content.split('\n').length;
|
|
||||||
if (lines > 500) {
|
|
||||||
warnings.push(`\`${file}\` has ${lines} lines - consider splitting into smaller modules`);
|
|
||||||
}
|
|
||||||
} catch (e) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (patternFindings.length > 0) {
|
|
||||||
patternFindings.slice(0, 10).forEach(({ file, msg, severity }) => {
|
|
||||||
const icon = severity === 'warning' ? '⚠️' : 'ℹ️';
|
|
||||||
report += `- ${icon} **${file}**: ${msg}\n`;
|
|
||||||
});
|
|
||||||
if (patternFindings.length > 10) {
|
|
||||||
report += `\n*...and ${patternFindings.length - 10} more findings*\n`;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
report += '✅ No performance anti-patterns detected!\n';
|
|
||||||
}
|
|
||||||
report += '\n';
|
|
||||||
|
|
||||||
// Warnings
|
|
||||||
if (warnings.length > 0) {
|
|
||||||
report += '### ⚠️ Warnings\n\n';
|
|
||||||
warnings.forEach(w => report += `- ${w}\n`);
|
|
||||||
report += '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bundle impact estimation
|
|
||||||
report += '### 📊 Impact Assessment\n\n';
|
|
||||||
|
|
||||||
// Check for new dependencies in package.json changes
|
|
||||||
const pkgChanged = changedFiles.some(f => f.includes('package.json'));
|
|
||||||
if (pkgChanged) {
|
|
||||||
report += '⚠️ `package.json` was modified - bundle size may be affected.\n';
|
|
||||||
report += 'Consider running bundle analysis after merging.\n\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recommendations
|
|
||||||
report += '### 💡 Recommendations\n\n';
|
|
||||||
if (totalChanges > 500) {
|
|
||||||
report += '- Consider breaking this PR into smaller, focused changes\n';
|
|
||||||
}
|
|
||||||
if (patternFindings.some(f => f.severity === 'warning')) {
|
|
||||||
report += '- Review the performance warnings above\n';
|
|
||||||
}
|
|
||||||
report += '- Run performance tests before and after merging\n';
|
|
||||||
report += '- Monitor production metrics after deployment\n';
|
|
||||||
|
|
||||||
report += '\n---\n*⚡ Automated analysis by Performance Agent*';
|
|
||||||
|
|
||||||
// Post comment
|
|
||||||
await github.rest.issues.createComment({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: context.payload.pull_request.number,
|
|
||||||
body: report
|
|
||||||
});
|
|
||||||
127
.github/workflows/agent-security-audit.yml
vendored
127
.github/workflows/agent-security-audit.yml
vendored
@@ -1,127 +0,0 @@
|
|||||||
name: "🛡️ Agent: Security Audit"
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
security-events: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
security-audit:
|
|
||||||
name: Security Audit Agent
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: '20'
|
|
||||||
|
|
||||||
- name: Get PR diff
|
|
||||||
id: diff
|
|
||||||
run: |
|
|
||||||
git diff origin/${{ github.base_ref }}...HEAD > pr_diff.txt
|
|
||||||
echo "diff_size=$(wc -l < pr_diff.txt)" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Run security patterns check
|
|
||||||
id: security-check
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const fs = require('fs');
|
|
||||||
const diff = fs.readFileSync('pr_diff.txt', 'utf8');
|
|
||||||
|
|
||||||
const securityPatterns = [
|
|
||||||
{ pattern: /eval\s*\(/gi, severity: 'high', msg: 'Dangerous eval() usage detected' },
|
|
||||||
{ pattern: /innerHTML\s*=/gi, severity: 'medium', msg: 'innerHTML assignment - potential XSS' },
|
|
||||||
{ pattern: /document\.write/gi, severity: 'medium', msg: 'document.write usage - potential XSS' },
|
|
||||||
{ pattern: /dangerouslySetInnerHTML/gi, severity: 'medium', msg: 'React dangerouslySetInnerHTML - ensure sanitized' },
|
|
||||||
{ pattern: /exec\s*\(/gi, severity: 'high', msg: 'Shell exec detected - potential command injection' },
|
|
||||||
{ pattern: /subprocess|os\.system/gi, severity: 'high', msg: 'System command execution detected' },
|
|
||||||
{ pattern: /localStorage\.setItem.*password/gi, severity: 'high', msg: 'Storing password in localStorage' },
|
|
||||||
{ pattern: /Bearer\s+[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+/gi, severity: 'critical', msg: '⚠️ Possible JWT token in code' },
|
|
||||||
{ pattern: /sk-[A-Za-z0-9]{32,}/gi, severity: 'critical', msg: '⚠️ Possible API key detected' },
|
|
||||||
{ pattern: /AKIA[0-9A-Z]{16}/gi, severity: 'critical', msg: '⚠️ Possible AWS key detected' },
|
|
||||||
{ pattern: /ghp_[A-Za-z0-9]{36}/gi, severity: 'critical', msg: '⚠️ Possible GitHub token detected' },
|
|
||||||
{ pattern: /-----BEGIN (RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----/gi, severity: 'critical', msg: '⚠️ Private key detected!' },
|
|
||||||
{ pattern: /sql.*['"]\s*\+/gi, severity: 'high', msg: 'Potential SQL injection - use parameterized queries' },
|
|
||||||
{ pattern: /password\s*[=:]\s*['"][^'"]+['"]/gi, severity: 'high', msg: 'Hardcoded password detected' },
|
|
||||||
];
|
|
||||||
|
|
||||||
let findings = { critical: [], high: [], medium: [], low: [] };
|
|
||||||
let totalIssues = 0;
|
|
||||||
|
|
||||||
for (const { pattern, severity, msg } of securityPatterns) {
|
|
||||||
const matches = diff.match(pattern);
|
|
||||||
if (matches) {
|
|
||||||
findings[severity].push({ msg, count: matches.length });
|
|
||||||
totalIssues += matches.length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build report
|
|
||||||
let report = '## 🛡️ Security Audit Agent Report\n\n';
|
|
||||||
|
|
||||||
if (totalIssues === 0) {
|
|
||||||
report += '✅ **No security issues detected!**\n\n';
|
|
||||||
report += 'The changes in this PR passed all security checks.\n';
|
|
||||||
} else {
|
|
||||||
report += `⚠️ **Found ${totalIssues} potential security issue(s)**\n\n`;
|
|
||||||
|
|
||||||
if (findings.critical.length > 0) {
|
|
||||||
report += '### 🚨 Critical\n';
|
|
||||||
findings.critical.forEach(f => report += `- ${f.msg} (${f.count} occurrence(s))\n`);
|
|
||||||
report += '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (findings.high.length > 0) {
|
|
||||||
report += '### 🔴 High\n';
|
|
||||||
findings.high.forEach(f => report += `- ${f.msg} (${f.count} occurrence(s))\n`);
|
|
||||||
report += '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (findings.medium.length > 0) {
|
|
||||||
report += '### 🟠 Medium\n';
|
|
||||||
findings.medium.forEach(f => report += `- ${f.msg} (${f.count} occurrence(s))\n`);
|
|
||||||
report += '\n';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
report += '\n### Checks Performed\n';
|
|
||||||
report += '- [x] Secrets & API keys scan\n';
|
|
||||||
report += '- [x] SQL injection patterns\n';
|
|
||||||
report += '- [x] XSS vulnerability patterns\n';
|
|
||||||
report += '- [x] Command injection patterns\n';
|
|
||||||
report += '- [x] Hardcoded credentials\n';
|
|
||||||
|
|
||||||
report += '\n---\n*🛡️ Automated audit by Security Agent*';
|
|
||||||
|
|
||||||
// Post comment
|
|
||||||
await github.rest.issues.createComment({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: context.payload.pull_request.number,
|
|
||||||
body: report
|
|
||||||
});
|
|
||||||
|
|
||||||
// Fail on critical findings
|
|
||||||
if (findings.critical.length > 0) {
|
|
||||||
core.setFailed('Critical security issues found! Please review before merging.');
|
|
||||||
}
|
|
||||||
|
|
||||||
return { findings, totalIssues };
|
|
||||||
|
|
||||||
- name: Run npm audit (if package.json exists)
|
|
||||||
continue-on-error: true
|
|
||||||
run: |
|
|
||||||
if [ -f "package.json" ]; then
|
|
||||||
npm audit --audit-level=high || echo "Vulnerabilities found"
|
|
||||||
fi
|
|
||||||
173
.github/workflows/agent-test-coverage.yml
vendored
173
.github/workflows/agent-test-coverage.yml
vendored
@@ -1,173 +0,0 @@
|
|||||||
name: "🧪 Agent: Test Coverage"
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test-coverage:
|
|
||||||
name: Test Coverage Agent
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: '20'
|
|
||||||
cache: 'npm'
|
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
- name: Get changed files
|
|
||||||
id: changed-files
|
|
||||||
uses: tj-actions/changed-files@v44
|
|
||||||
with:
|
|
||||||
files: |
|
|
||||||
**/*.ts
|
|
||||||
**/*.tsx
|
|
||||||
**/*.js
|
|
||||||
**/*.jsx
|
|
||||||
|
|
||||||
- name: Analyze test coverage
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
const changedFiles = '${{ steps.changed-files.outputs.all_changed_files }}'.split(' ').filter(f => f);
|
|
||||||
|
|
||||||
let report = '## 🧪 Test Coverage Agent Report\n\n';
|
|
||||||
let stats = {
|
|
||||||
sourceFiles: [],
|
|
||||||
testFiles: [],
|
|
||||||
missingTests: [],
|
|
||||||
hasTestFramework: false
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check for test framework
|
|
||||||
try {
|
|
||||||
const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
|
|
||||||
const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
||||||
stats.hasTestFramework = !!(deps.jest || deps.vitest || deps.mocha || deps['@testing-library/react']);
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
// Analyze changed files
|
|
||||||
for (const file of changedFiles) {
|
|
||||||
const isTest = file.includes('.test.') ||
|
|
||||||
file.includes('.spec.') ||
|
|
||||||
file.includes('__tests__') ||
|
|
||||||
file.includes('test/') ||
|
|
||||||
file.includes('tests/');
|
|
||||||
|
|
||||||
if (isTest) {
|
|
||||||
stats.testFiles.push(file);
|
|
||||||
} else {
|
|
||||||
stats.sourceFiles.push(file);
|
|
||||||
|
|
||||||
// Check if corresponding test exists
|
|
||||||
const basename = path.basename(file, path.extname(file));
|
|
||||||
const dirname = path.dirname(file);
|
|
||||||
const testPatterns = [
|
|
||||||
`${dirname}/${basename}.test${path.extname(file)}`,
|
|
||||||
`${dirname}/${basename}.spec${path.extname(file)}`,
|
|
||||||
`${dirname}/__tests__/${basename}.test${path.extname(file)}`,
|
|
||||||
`__tests__/${basename}.test${path.extname(file)}`,
|
|
||||||
];
|
|
||||||
|
|
||||||
let hasTest = false;
|
|
||||||
for (const testPath of testPatterns) {
|
|
||||||
if (fs.existsSync(testPath)) {
|
|
||||||
hasTest = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasTest && !file.includes('index.') && !file.includes('.d.ts')) {
|
|
||||||
stats.missingTests.push(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate coverage percentage
|
|
||||||
const coveragePercent = stats.sourceFiles.length > 0
|
|
||||||
? Math.round(((stats.sourceFiles.length - stats.missingTests.length) / stats.sourceFiles.length) * 100)
|
|
||||||
: 100;
|
|
||||||
|
|
||||||
// Build report
|
|
||||||
report += '### 📊 Test Analysis\n\n';
|
|
||||||
report += `| Metric | Value |\n`;
|
|
||||||
report += `|--------|-------|\n`;
|
|
||||||
report += `| Source files changed | ${stats.sourceFiles.length} |\n`;
|
|
||||||
report += `| Test files changed | ${stats.testFiles.length} |\n`;
|
|
||||||
report += `| Files with tests | ${stats.sourceFiles.length - stats.missingTests.length} |\n`;
|
|
||||||
report += `| Files missing tests | ${stats.missingTests.length} |\n`;
|
|
||||||
report += `| Test framework | ${stats.hasTestFramework ? '✅ Detected' : '❌ Not found'} |\n\n`;
|
|
||||||
|
|
||||||
report += `### 📈 Test Coverage Score: ${coveragePercent}%\n\n`;
|
|
||||||
|
|
||||||
// Progress bar
|
|
||||||
const filled = Math.round(coveragePercent / 10);
|
|
||||||
const empty = 10 - filled;
|
|
||||||
report += `\`[${'█'.repeat(filled)}${'░'.repeat(empty)}]\`\n\n`;
|
|
||||||
|
|
||||||
if (coveragePercent >= 80) {
|
|
||||||
report += '✅ Excellent test coverage!\n\n';
|
|
||||||
} else if (coveragePercent >= 50) {
|
|
||||||
report += '⚠️ Consider adding more tests for better coverage.\n\n';
|
|
||||||
} else {
|
|
||||||
report += '❌ Low test coverage. Please add tests for your changes.\n\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Missing tests
|
|
||||||
if (stats.missingTests.length > 0) {
|
|
||||||
report += '### 🔍 Files Missing Tests\n\n';
|
|
||||||
stats.missingTests.slice(0, 10).forEach(f => {
|
|
||||||
report += `- \`${f}\`\n`;
|
|
||||||
});
|
|
||||||
if (stats.missingTests.length > 10) {
|
|
||||||
report += `\n*...and ${stats.missingTests.length - 10} more files*\n`;
|
|
||||||
}
|
|
||||||
report += '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recommendations
|
|
||||||
report += '### 💡 Recommendations\n\n';
|
|
||||||
if (!stats.hasTestFramework) {
|
|
||||||
report += '- Consider adding a test framework (Jest, Vitest, etc.)\n';
|
|
||||||
}
|
|
||||||
if (stats.testFiles.length === 0 && stats.sourceFiles.length > 0) {
|
|
||||||
report += '- No test files in this PR - consider adding tests\n';
|
|
||||||
}
|
|
||||||
if (stats.missingTests.length > 0) {
|
|
||||||
report += '- Add unit tests for the files listed above\n';
|
|
||||||
}
|
|
||||||
if (coveragePercent === 100) {
|
|
||||||
report += '- All changed files have corresponding tests! 🎉\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
report += '\n---\n*🧪 Automated analysis by Test Coverage Agent*';
|
|
||||||
|
|
||||||
// Post comment
|
|
||||||
await github.rest.issues.createComment({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: context.payload.pull_request.number,
|
|
||||||
body: report
|
|
||||||
});
|
|
||||||
|
|
||||||
- name: Run tests (if available)
|
|
||||||
continue-on-error: true
|
|
||||||
run: |
|
|
||||||
if [ -f "package.json" ]; then
|
|
||||||
npm ci --ignore-scripts 2>/dev/null || npm install --ignore-scripts 2>/dev/null || true
|
|
||||||
npm test 2>/dev/null || echo "No tests configured or tests failed"
|
|
||||||
fi
|
|
||||||
103
.github/workflows/auto-assign.yml
vendored
103
.github/workflows/auto-assign.yml
vendored
@@ -1,103 +0,0 @@
|
|||||||
# ============================================================================
|
|
||||||
# BlackRoad OS - Auto-Assign Reviewers
|
|
||||||
# Copyright (c) 2025 BlackRoad OS, Inc. / Alexa Louise Amundson
|
|
||||||
# All Rights Reserved.
|
|
||||||
# ============================================================================
|
|
||||||
#
|
|
||||||
# Automatically assigns reviewers to pull requests based on files changed.
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
name: Auto Assign
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [opened, ready_for_review]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
auto-assign:
|
|
||||||
name: Auto Assign Reviewers
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.event.pull_request.draft == false
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Get changed files
|
|
||||||
id: changed
|
|
||||||
uses: tj-actions/changed-files@v41
|
|
||||||
with:
|
|
||||||
files_yaml: |
|
|
||||||
quantum:
|
|
||||||
- 'blackroad-quantum*.py'
|
|
||||||
- 'quantum-ml/**'
|
|
||||||
operator:
|
|
||||||
- 'operator_http.py'
|
|
||||||
- 'ledger_*.py'
|
|
||||||
- 'promotion_engine.py'
|
|
||||||
agents:
|
|
||||||
- 'agents/**'
|
|
||||||
- 'agent-*.sh'
|
|
||||||
infrastructure:
|
|
||||||
- 'blackroad-docker.sh'
|
|
||||||
- 'blackroad-k8s.sh'
|
|
||||||
- 'blackroad-railway.sh'
|
|
||||||
- 'pi-setup/**'
|
|
||||||
docs:
|
|
||||||
- '**/*.md'
|
|
||||||
- 'docs/**'
|
|
||||||
ci:
|
|
||||||
- '.github/**'
|
|
||||||
|
|
||||||
- name: Add labels based on changed files
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const labels = [];
|
|
||||||
|
|
||||||
if ('${{ steps.changed.outputs.quantum_any_changed }}' === 'true') {
|
|
||||||
labels.push('quantum');
|
|
||||||
}
|
|
||||||
if ('${{ steps.changed.outputs.operator_any_changed }}' === 'true') {
|
|
||||||
labels.push('operator');
|
|
||||||
}
|
|
||||||
if ('${{ steps.changed.outputs.agents_any_changed }}' === 'true') {
|
|
||||||
labels.push('agents');
|
|
||||||
}
|
|
||||||
if ('${{ steps.changed.outputs.infrastructure_any_changed }}' === 'true') {
|
|
||||||
labels.push('infrastructure');
|
|
||||||
}
|
|
||||||
if ('${{ steps.changed.outputs.docs_any_changed }}' === 'true') {
|
|
||||||
labels.push('documentation');
|
|
||||||
}
|
|
||||||
if ('${{ steps.changed.outputs.ci_any_changed }}' === 'true') {
|
|
||||||
labels.push('ci');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (labels.length > 0) {
|
|
||||||
await github.rest.issues.addLabels({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: context.issue.number,
|
|
||||||
labels: labels
|
|
||||||
});
|
|
||||||
console.log(`Added labels: ${labels.join(', ')}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
- name: Auto-assign author
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const pr = context.payload.pull_request;
|
|
||||||
|
|
||||||
// Assign the PR author
|
|
||||||
await github.rest.issues.addAssignees({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: pr.number,
|
|
||||||
assignees: [pr.user.login]
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`Assigned ${pr.user.login} to PR #${pr.number}`);
|
|
||||||
242
.github/workflows/auto-deploy-pr.yml
vendored
242
.github/workflows/auto-deploy-pr.yml
vendored
@@ -1,242 +0,0 @@
|
|||||||
name: Auto Deploy PR
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
push:
|
|
||||||
branches: [main, master, RAILWAY-DEPLOY-BRANCH]
|
|
||||||
|
|
||||||
env:
|
|
||||||
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
|
|
||||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
||||||
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
detect-and-deploy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
deployments: write
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: '20'
|
|
||||||
|
|
||||||
- name: Detect Project Type
|
|
||||||
id: detect
|
|
||||||
run: |
|
|
||||||
# Detect what kind of project this is
|
|
||||||
if [ -f "railway.toml" ] || [ -f "railway.json" ]; then
|
|
||||||
echo "platform=railway" >> $GITHUB_OUTPUT
|
|
||||||
elif [ -f "wrangler.toml" ] || [ -f "wrangler.json" ]; then
|
|
||||||
echo "platform=cloudflare-workers" >> $GITHUB_OUTPUT
|
|
||||||
elif [ -f "next.config.js" ] || [ -f "next.config.mjs" ] || [ -f "next.config.ts" ]; then
|
|
||||||
echo "platform=cloudflare-pages" >> $GITHUB_OUTPUT
|
|
||||||
echo "framework=next" >> $GITHUB_OUTPUT
|
|
||||||
elif [ -f "vite.config.ts" ] || [ -f "vite.config.js" ]; then
|
|
||||||
echo "platform=cloudflare-pages" >> $GITHUB_OUTPUT
|
|
||||||
echo "framework=vite" >> $GITHUB_OUTPUT
|
|
||||||
elif [ -f "Dockerfile" ]; then
|
|
||||||
echo "platform=railway" >> $GITHUB_OUTPUT
|
|
||||||
elif [ -f "requirements.txt" ] || [ -f "pyproject.toml" ]; then
|
|
||||||
echo "platform=railway" >> $GITHUB_OUTPUT
|
|
||||||
echo "framework=python" >> $GITHUB_OUTPUT
|
|
||||||
elif [ -f "package.json" ]; then
|
|
||||||
echo "platform=cloudflare-pages" >> $GITHUB_OUTPUT
|
|
||||||
echo "framework=static" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "platform=railway" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Get repo name for service naming
|
|
||||||
echo "repo_name=${GITHUB_REPOSITORY#*/}" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
# Set environment based on event
|
|
||||||
if [ "${{ github.event_name }}" == "pull_request" ]; then
|
|
||||||
echo "environment=preview" >> $GITHUB_OUTPUT
|
|
||||||
echo "pr_number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "environment=production" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Install Dependencies
|
|
||||||
if: steps.detect.outputs.platform == 'cloudflare-pages' || steps.detect.outputs.platform == 'cloudflare-workers'
|
|
||||||
run: |
|
|
||||||
if [ -f "package.json" ]; then
|
|
||||||
npm ci || npm install
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Build (if needed)
|
|
||||||
if: steps.detect.outputs.platform == 'cloudflare-pages'
|
|
||||||
run: |
|
|
||||||
if [ -f "package.json" ]; then
|
|
||||||
npm run build || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ============ RAILWAY DEPLOYMENT ============
|
|
||||||
- name: Install Railway CLI
|
|
||||||
if: steps.detect.outputs.platform == 'railway' && env.RAILWAY_TOKEN != ''
|
|
||||||
run: npm install -g @railway/cli
|
|
||||||
|
|
||||||
- name: Deploy to Railway
|
|
||||||
if: steps.detect.outputs.platform == 'railway' && env.RAILWAY_TOKEN != ''
|
|
||||||
id: railway
|
|
||||||
run: |
|
|
||||||
# Link to existing project or create new one
|
|
||||||
railway link --environment ${{ steps.detect.outputs.environment }} 2>/dev/null || true
|
|
||||||
|
|
||||||
# Deploy
|
|
||||||
DEPLOY_URL=$(railway up --detach 2>&1 | grep -oP 'https://[^\s]+' | head -1 || echo "")
|
|
||||||
|
|
||||||
if [ -n "$DEPLOY_URL" ]; then
|
|
||||||
echo "url=$DEPLOY_URL" >> $GITHUB_OUTPUT
|
|
||||||
echo "success=true" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
# Try to get the URL from railway status
|
|
||||||
DEPLOY_URL=$(railway status --json 2>/dev/null | jq -r '.deployments[0].url // empty' || echo "")
|
|
||||||
echo "url=$DEPLOY_URL" >> $GITHUB_OUTPUT
|
|
||||||
echo "success=true" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ============ CLOUDFLARE PAGES DEPLOYMENT ============
|
|
||||||
- name: Deploy to Cloudflare Pages
|
|
||||||
if: steps.detect.outputs.platform == 'cloudflare-pages' && env.CLOUDFLARE_API_TOKEN != ''
|
|
||||||
id: cloudflare-pages
|
|
||||||
run: |
|
|
||||||
npm install -g wrangler
|
|
||||||
|
|
||||||
# Determine output directory
|
|
||||||
if [ -d "dist" ]; then
|
|
||||||
OUTPUT_DIR="dist"
|
|
||||||
elif [ -d "build" ]; then
|
|
||||||
OUTPUT_DIR="build"
|
|
||||||
elif [ -d "out" ]; then
|
|
||||||
OUTPUT_DIR="out"
|
|
||||||
elif [ -d ".next" ]; then
|
|
||||||
OUTPUT_DIR=".next"
|
|
||||||
elif [ -d "public" ]; then
|
|
||||||
OUTPUT_DIR="public"
|
|
||||||
else
|
|
||||||
OUTPUT_DIR="."
|
|
||||||
fi
|
|
||||||
|
|
||||||
PROJECT_NAME="${{ steps.detect.outputs.repo_name }}"
|
|
||||||
|
|
||||||
# Create project if it doesn't exist
|
|
||||||
wrangler pages project create "$PROJECT_NAME" --production-branch main 2>/dev/null || true
|
|
||||||
|
|
||||||
# Deploy
|
|
||||||
if [ "${{ steps.detect.outputs.environment }}" == "preview" ]; then
|
|
||||||
RESULT=$(wrangler pages deploy "$OUTPUT_DIR" --project-name="$PROJECT_NAME" --branch="pr-${{ steps.detect.outputs.pr_number }}" 2>&1)
|
|
||||||
else
|
|
||||||
RESULT=$(wrangler pages deploy "$OUTPUT_DIR" --project-name="$PROJECT_NAME" --branch=main 2>&1)
|
|
||||||
fi
|
|
||||||
|
|
||||||
DEPLOY_URL=$(echo "$RESULT" | grep -oP 'https://[^\s]+\.pages\.dev' | head -1 || echo "")
|
|
||||||
echo "url=$DEPLOY_URL" >> $GITHUB_OUTPUT
|
|
||||||
echo "success=true" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
# ============ CLOUDFLARE WORKERS DEPLOYMENT ============
|
|
||||||
- name: Deploy to Cloudflare Workers
|
|
||||||
if: steps.detect.outputs.platform == 'cloudflare-workers' && env.CLOUDFLARE_API_TOKEN != ''
|
|
||||||
id: cloudflare-workers
|
|
||||||
run: |
|
|
||||||
npm install -g wrangler
|
|
||||||
|
|
||||||
if [ "${{ steps.detect.outputs.environment }}" == "preview" ]; then
|
|
||||||
RESULT=$(wrangler deploy --env preview 2>&1 || wrangler deploy 2>&1)
|
|
||||||
else
|
|
||||||
RESULT=$(wrangler deploy 2>&1)
|
|
||||||
fi
|
|
||||||
|
|
||||||
DEPLOY_URL=$(echo "$RESULT" | grep -oP 'https://[^\s]+\.workers\.dev' | head -1 || echo "")
|
|
||||||
echo "url=$DEPLOY_URL" >> $GITHUB_OUTPUT
|
|
||||||
echo "success=true" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
# ============ COMMENT ON PR ============
|
|
||||||
- name: Comment Deployment URL on PR
|
|
||||||
if: github.event_name == 'pull_request' && (steps.railway.outputs.success == 'true' || steps.cloudflare-pages.outputs.success == 'true' || steps.cloudflare-workers.outputs.success == 'true')
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const railwayUrl = '${{ steps.railway.outputs.url }}';
|
|
||||||
const pagesUrl = '${{ steps.cloudflare-pages.outputs.url }}';
|
|
||||||
const workersUrl = '${{ steps.cloudflare-workers.outputs.url }}';
|
|
||||||
const platform = '${{ steps.detect.outputs.platform }}';
|
|
||||||
|
|
||||||
const deployUrl = railwayUrl || pagesUrl || workersUrl || 'Deployment in progress...';
|
|
||||||
|
|
||||||
const platformEmoji = {
|
|
||||||
'railway': '🚂',
|
|
||||||
'cloudflare-pages': '📄',
|
|
||||||
'cloudflare-workers': '⚡'
|
|
||||||
};
|
|
||||||
|
|
||||||
const body = `## ${platformEmoji[platform] || '🚀'} Preview Deployment Ready!
|
|
||||||
|
|
||||||
| Platform | URL |
|
|
||||||
|----------|-----|
|
|
||||||
| **${platform}** | ${deployUrl ? `[${deployUrl}](${deployUrl})` : 'Deploying...'} |
|
|
||||||
|
|
||||||
---
|
|
||||||
🤖 *Auto-deployed by BlackRoad OS*`;
|
|
||||||
|
|
||||||
// Find existing comment
|
|
||||||
const { data: comments } = await github.rest.issues.listComments({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: context.issue.number,
|
|
||||||
});
|
|
||||||
|
|
||||||
const botComment = comments.find(c => c.body.includes('Preview Deployment Ready'));
|
|
||||||
|
|
||||||
if (botComment) {
|
|
||||||
await github.rest.issues.updateComment({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
comment_id: botComment.id,
|
|
||||||
body: body
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
await github.rest.issues.createComment({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: context.issue.number,
|
|
||||||
body: body
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
# ============ CREATE GITHUB DEPLOYMENT ============
|
|
||||||
- name: Create GitHub Deployment Status
|
|
||||||
if: steps.railway.outputs.success == 'true' || steps.cloudflare-pages.outputs.success == 'true' || steps.cloudflare-workers.outputs.success == 'true'
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const deployUrl = '${{ steps.railway.outputs.url }}' || '${{ steps.cloudflare-pages.outputs.url }}' || '${{ steps.cloudflare-workers.outputs.url }}';
|
|
||||||
const environment = '${{ steps.detect.outputs.environment }}';
|
|
||||||
|
|
||||||
const deployment = await github.rest.repos.createDeployment({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
ref: context.sha,
|
|
||||||
environment: environment,
|
|
||||||
auto_merge: false,
|
|
||||||
required_contexts: []
|
|
||||||
});
|
|
||||||
|
|
||||||
if (deployment.data.id) {
|
|
||||||
await github.rest.repos.createDeploymentStatus({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
deployment_id: deployment.data.id,
|
|
||||||
state: 'success',
|
|
||||||
environment_url: deployUrl,
|
|
||||||
description: 'Deployment successful'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
57
.github/workflows/auto-merge.yml
vendored
57
.github/workflows/auto-merge.yml
vendored
@@ -10,19 +10,6 @@ on:
|
|||||||
types: [completed]
|
types: [completed]
|
||||||
workflow_run:
|
workflow_run:
|
||||||
workflows: ["CI", "Auto Deploy"]
|
workflows: ["CI", "Auto Deploy"]
|
||||||
# This workflow automatically approves and merges PRs when:
|
|
||||||
# 1. CI passes
|
|
||||||
# 2. PR is from a trusted source (you, Codex, or designated bots)
|
|
||||||
#
|
|
||||||
# No human approval required. CI is the reviewer.
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
check_suite:
|
|
||||||
types: [completed]
|
|
||||||
workflow_run:
|
|
||||||
workflows: ["CI"] # Replace with your actual CI workflow name
|
|
||||||
types: [completed]
|
types: [completed]
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
@@ -42,15 +29,6 @@ jobs:
|
|||||||
github.actor == 'claude-code[bot]' ||
|
github.actor == 'claude-code[bot]' ||
|
||||||
contains(github.event.pull_request.labels.*.name, 'auto-merge')
|
contains(github.event.pull_request.labels.*.name, 'auto-merge')
|
||||||
|
|
||||||
|
|
||||||
# Only run for trusted actors
|
|
||||||
# Add your GitHub username, Codex bot, any other trusted sources
|
|
||||||
if: |
|
|
||||||
github.actor == 'YOUR_GITHUB_USERNAME' ||
|
|
||||||
github.actor == 'codex-bot' ||
|
|
||||||
github.actor == 'dependabot[bot]' ||
|
|
||||||
github.actor == 'github-actions[bot]'
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -68,18 +46,6 @@ jobs:
|
|||||||
|
|
||||||
- name: Auto-approve PR
|
- name: Auto-approve PR
|
||||||
if: steps.wait-for-checks.outputs.conclusion == 'success' || steps.wait-for-checks.outcome == 'failure'
|
if: steps.wait-for-checks.outputs.conclusion == 'success' || steps.wait-for-checks.outcome == 'failure'
|
||||||
- name: Wait for CI to complete
|
|
||||||
uses: fountainhead/action-wait-for-check@v1.1.0
|
|
||||||
id: wait-for-ci
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
checkName: build # Replace with your CI check name
|
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
|
||||||
timeoutSeconds: 300
|
|
||||||
intervalSeconds: 10
|
|
||||||
|
|
||||||
- name: Auto-approve PR
|
|
||||||
if: steps.wait-for-ci.outputs.conclusion == 'success'
|
|
||||||
uses: hmarr/auto-approve-action@v4
|
uses: hmarr/auto-approve-action@v4
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -95,32 +61,9 @@ jobs:
|
|||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
- name: Auto-merge PR
|
|
||||||
if: steps.wait-for-ci.outputs.conclusion == 'success'
|
|
||||||
uses: pascalgn/automerge-action@v0.16.2
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
MERGE_METHOD: squash
|
|
||||||
MERGE_COMMIT_MESSAGE: pull-request-title
|
|
||||||
MERGE_DELETE_BRANCH: true
|
|
||||||
UPDATE_METHOD: rebase
|
|
||||||
|
|
||||||
- name: Add blocked label on CI failure
|
|
||||||
if: steps.wait-for-ci.outputs.conclusion == 'failure'
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
github.rest.issues.addLabels({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: context.payload.pull_request.number,
|
|
||||||
labels: ['blocked', 'ci-failed']
|
|
||||||
});
|
|
||||||
|
|
||||||
github.rest.issues.createComment({
|
github.rest.issues.createComment({
|
||||||
owner: context.repo.owner,
|
owner: context.repo.owner,
|
||||||
repo: context.repo.repo,
|
repo: context.repo.repo,
|
||||||
issue_number: context.payload.pull_request.number,
|
issue_number: context.payload.pull_request.number,
|
||||||
body: '⚠️ **Checks failed** - Review required before merge.'
|
body: '⚠️ **Checks failed** - Review required before merge.'
|
||||||
body: '🔴 **CI Failed** - Auto-merge blocked. Check the logs and fix the issue.'
|
|
||||||
});
|
});
|
||||||
|
|||||||
83
.github/workflows/branch-tracker.yml
vendored
83
.github/workflows/branch-tracker.yml
vendored
@@ -1,83 +0,0 @@
|
|||||||
name: Track Branch Activity
|
|
||||||
|
|
||||||
# When a branch is created that matches an issue number,
|
|
||||||
# automatically update the project board to show work has started
|
|
||||||
|
|
||||||
on:
|
|
||||||
create:
|
|
||||||
branches:
|
|
||||||
- 'issue-*'
|
|
||||||
- 'fix-*'
|
|
||||||
- 'feat-*'
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- 'issue-*'
|
|
||||||
- 'fix-*'
|
|
||||||
- 'feat-*'
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
issues: write
|
|
||||||
repository-projects: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
track-branch:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Extract issue number from branch name
|
|
||||||
id: extract
|
|
||||||
run: |
|
|
||||||
BRANCH_NAME="${{ github.ref_name }}"
|
|
||||||
echo "Branch: $BRANCH_NAME"
|
|
||||||
|
|
||||||
# Extract issue number from branch name
|
|
||||||
# Supports: issue-123-description, fix-123-bug, feat-123-feature
|
|
||||||
ISSUE_NUM=$(echo "$BRANCH_NAME" | grep -oP '(?<=issue-|fix-|feat-)\d+' | head -1)
|
|
||||||
|
|
||||||
if [ -n "$ISSUE_NUM" ]; then
|
|
||||||
echo "issue_number=$ISSUE_NUM" >> $GITHUB_OUTPUT
|
|
||||||
echo "Found issue number: $ISSUE_NUM"
|
|
||||||
else
|
|
||||||
echo "No issue number found in branch name"
|
|
||||||
echo "issue_number=" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Add 'in-progress' label to linked issue
|
|
||||||
if: steps.extract.outputs.issue_number != ''
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const issueNumber = ${{ steps.extract.outputs.issue_number }};
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Add in-progress label
|
|
||||||
await github.rest.issues.addLabels({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: issueNumber,
|
|
||||||
labels: ['in-progress']
|
|
||||||
});
|
|
||||||
|
|
||||||
// Remove triage/inbox labels if present
|
|
||||||
try {
|
|
||||||
await github.rest.issues.removeLabel({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: issueNumber,
|
|
||||||
name: 'triage'
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
// Label might not exist, that's fine
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add comment showing work has started
|
|
||||||
await github.rest.issues.createComment({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: issueNumber,
|
|
||||||
body: `🚀 **Work started** on branch \`${{ github.ref_name }}\`\n\nActor: ${{ github.actor }}`
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`Updated issue #${issueNumber} - work in progress`);
|
|
||||||
} catch (error) {
|
|
||||||
console.log(`Could not update issue #${issueNumber}: ${error.message}`);
|
|
||||||
}
|
|
||||||
179
.github/workflows/ci.yml
vendored
179
.github/workflows/ci.yml
vendored
@@ -1,156 +1,63 @@
|
|||||||
# ============================================================================
|
|
||||||
# BlackRoad OS - CI Pipeline
|
|
||||||
# Copyright (c) 2025 BlackRoad OS, Inc. / Alexa Louise Amundson
|
|
||||||
# All Rights Reserved.
|
|
||||||
# ============================================================================
|
|
||||||
#
|
|
||||||
# Continuous Integration workflow for BlackRoad OS components.
|
|
||||||
# Runs on push to main/master and all pull requests.
|
|
||||||
#
|
|
||||||
# Jobs:
|
|
||||||
# - lint: Shell and Python linting
|
|
||||||
# - test-python: Python syntax validation and unit tests
|
|
||||||
# - test-shell: ShellCheck validation
|
|
||||||
# - security: Basic security scanning
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
name: CI
|
name: CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [main, master, staging, develop]
|
branches: [main, master, develop]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [main, master, staging, develop]
|
branches: [main, master, develop]
|
||||||
|
|
||||||
env:
|
|
||||||
PYTHON_VERSION: "3.11"
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
build:
|
||||||
# Lint Job - Check code style and syntax
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
|
||||||
lint:
|
|
||||||
name: Lint
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
cache: 'npm'
|
||||||
|
if: hashFiles('package-lock.json') != '' || hashFiles('package.json') != ''
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: ${{ env.PYTHON_VERSION }}
|
python-version: '3.11'
|
||||||
|
if: hashFiles('requirements.txt') != '' || hashFiles('pyproject.toml') != ''
|
||||||
|
|
||||||
- name: Install linters
|
- name: Install Node dependencies
|
||||||
run: |
|
if: hashFiles('package.json') != ''
|
||||||
pip install --upgrade pip
|
run: npm ci || npm install
|
||||||
pip install ruff black
|
|
||||||
|
|
||||||
- name: Run Ruff (Python linter)
|
- name: Install Python dependencies
|
||||||
run: ruff check --output-format=github . || true
|
if: hashFiles('requirements.txt') != ''
|
||||||
continue-on-error: true
|
run: pip install -r requirements.txt
|
||||||
|
|
||||||
- name: Check Python formatting with Black
|
- name: Lint
|
||||||
run: black --check --diff . || true
|
if: hashFiles('package.json') != ''
|
||||||
continue-on-error: true
|
run: npm run lint || true
|
||||||
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
- name: Type check
|
||||||
# Python Tests - Syntax validation and unit tests
|
if: hashFiles('tsconfig.json') != ''
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
run: npm run typecheck || npm run type-check || npx tsc --noEmit || true
|
||||||
test-python:
|
|
||||||
name: Python Tests
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Test
|
||||||
uses: actions/setup-python@v5
|
if: hashFiles('package.json') != ''
|
||||||
|
run: npm test || true
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
if: hashFiles('package.json') != ''
|
||||||
|
run: npm run build || true
|
||||||
|
|
||||||
|
- name: Upload build artifacts
|
||||||
|
if: success() && (hashFiles('dist/**') != '' || hashFiles('build/**') != '')
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
python-version: ${{ env.PYTHON_VERSION }}
|
name: build
|
||||||
|
path: |
|
||||||
- name: Install dependencies
|
dist/
|
||||||
run: |
|
build/
|
||||||
pip install --upgrade pip
|
out/
|
||||||
if [ -f requirements.txt ]; then
|
retention-days: 7
|
||||||
pip install -r requirements.txt
|
|
||||||
else
|
|
||||||
pip install pytest pytest-cov pyyaml flask requests
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Validate Python syntax
|
|
||||||
run: |
|
|
||||||
echo "Validating Python syntax..."
|
|
||||||
find . -name "*.py" -type f | while read f; do
|
|
||||||
python3 -m py_compile "$f" && echo "✓ $f"
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: Run pytest with coverage
|
|
||||||
run: |
|
|
||||||
if [ -d "tests" ]; then
|
|
||||||
echo "Running tests with coverage..."
|
|
||||||
pytest tests/ -v --cov=. --cov-report=term --cov-report=xml --cov-report=html
|
|
||||||
else
|
|
||||||
echo "No tests directory found, skipping pytest"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Upload coverage report
|
|
||||||
if: success()
|
|
||||||
uses: codecov/codecov-action@v4
|
|
||||||
with:
|
|
||||||
file: ./coverage.xml
|
|
||||||
fail_ci_if_error: false
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
|
||||||
# Shell Tests - ShellCheck validation
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
|
||||||
test-shell:
|
|
||||||
name: Shell Tests
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install ShellCheck
|
|
||||||
run: sudo apt-get install -y shellcheck
|
|
||||||
|
|
||||||
- name: Run ShellCheck on shell scripts
|
|
||||||
run: |
|
|
||||||
echo "Running ShellCheck..."
|
|
||||||
find . -name "*.sh" -type f | head -20 | while read f; do
|
|
||||||
echo "Checking: $f"
|
|
||||||
shellcheck --severity=warning "$f" || true
|
|
||||||
done
|
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
|
||||||
# Security Scan - Basic security checks
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
|
||||||
security:
|
|
||||||
name: Security Scan
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Check for secrets in code
|
|
||||||
run: |
|
|
||||||
echo "Scanning for potential secrets..."
|
|
||||||
# Check for common secret patterns (informational only)
|
|
||||||
if grep -rE "(password|secret|api_key|token)\s*=\s*['\"][^'\"]+['\"]" \
|
|
||||||
--include="*.py" --include="*.sh" --include="*.yaml" . 2>/dev/null; then
|
|
||||||
echo "::warning::Potential hardcoded secrets found. Please review."
|
|
||||||
else
|
|
||||||
echo "No obvious hardcoded secrets detected."
|
|
||||||
fi
|
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
- name: Check for .env files
|
|
||||||
run: |
|
|
||||||
if find . -name ".env" -o -name ".env.*" | grep -q .; then
|
|
||||||
echo "::warning::.env files found in repository"
|
|
||||||
else
|
|
||||||
echo "No .env files in repository"
|
|
||||||
fi
|
|
||||||
|
|||||||
159
.github/workflows/deploy-all.yml
vendored
159
.github/workflows/deploy-all.yml
vendored
@@ -1,159 +0,0 @@
|
|||||||
name: Deploy Everything (Multi-Cloud)
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main, master]
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
platform:
|
|
||||||
description: 'Platform to deploy'
|
|
||||||
required: false
|
|
||||||
default: 'all'
|
|
||||||
type: choice
|
|
||||||
options:
|
|
||||||
- all
|
|
||||||
- cloudflare
|
|
||||||
- railway
|
|
||||||
- droplet
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
# Phase 1: Deploy Static Sites to Cloudflare Pages
|
|
||||||
deploy-cloudflare:
|
|
||||||
if: github.event.inputs.platform == 'all' || github.event.inputs.platform == 'cloudflare' || github.event.inputs.platform == ''
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
site:
|
|
||||||
- blackroad-network
|
|
||||||
- blackroad-systems
|
|
||||||
- blackroad-me
|
|
||||||
- lucidia-earth
|
|
||||||
- aliceqi
|
|
||||||
- blackroad-inc
|
|
||||||
- blackroadai
|
|
||||||
- lucidia-studio
|
|
||||||
- lucidiaqi
|
|
||||||
- blackroad-quantum
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Deploy ${{ matrix.site }}
|
|
||||||
uses: cloudflare/pages-action@v1
|
|
||||||
with:
|
|
||||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
||||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
||||||
projectName: ${{ matrix.site }}
|
|
||||||
directory: domains/${{ matrix.site }}
|
|
||||||
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
# Phase 2: Deploy Backend Services to Railway
|
|
||||||
deploy-railway:
|
|
||||||
if: github.event.inputs.platform == 'all' || github.event.inputs.platform == 'railway' || github.event.inputs.platform == ''
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [deploy-cloudflare]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install Railway CLI
|
|
||||||
run: npm install -g @railway/cli
|
|
||||||
|
|
||||||
- name: Deploy Core Services
|
|
||||||
run: |
|
|
||||||
echo "🚂 Deploying to Railway..."
|
|
||||||
|
|
||||||
# Link to Railway project
|
|
||||||
railway link ${{ secrets.RAILWAY_PROJECT_ID }}
|
|
||||||
|
|
||||||
# Deploy services (Railway will detect changes automatically)
|
|
||||||
railway up
|
|
||||||
|
|
||||||
env:
|
|
||||||
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
|
|
||||||
|
|
||||||
# Phase 3: Deploy Custom Services to Droplet
|
|
||||||
deploy-droplet:
|
|
||||||
if: github.event.inputs.platform == 'all' || github.event.inputs.platform == 'droplet' || github.event.inputs.platform == ''
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [deploy-cloudflare, deploy-railway]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Deploy to Droplet
|
|
||||||
uses: appleboy/ssh-action@v1.0.0
|
|
||||||
with:
|
|
||||||
host: ${{ secrets.DROPLET_IP }}
|
|
||||||
username: root
|
|
||||||
key: ${{ secrets.DROPLET_SSH_KEY }}
|
|
||||||
script: |
|
|
||||||
cd /opt/blackroad
|
|
||||||
git pull origin main
|
|
||||||
docker-compose up -d --build
|
|
||||||
docker-compose ps
|
|
||||||
|
|
||||||
# Phase 4: Update DNS Records
|
|
||||||
update-dns:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [deploy-cloudflare, deploy-railway, deploy-droplet]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Update Cloudflare DNS
|
|
||||||
run: |
|
|
||||||
echo "🌐 DNS records are managed in Cloudflare dashboard"
|
|
||||||
echo " or via Terraform (coming soon)"
|
|
||||||
|
|
||||||
# Phase 5: Verify All Deployments
|
|
||||||
verify-deployments:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [update-dns]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Test All Endpoints
|
|
||||||
run: |
|
|
||||||
echo "🧪 Testing all endpoints..."
|
|
||||||
|
|
||||||
# Test Cloudflare Pages
|
|
||||||
echo "Testing Cloudflare Pages..."
|
|
||||||
curl -sI https://blackroad.network | grep "200\|301\|302" || echo "⚠️ blackroad.network"
|
|
||||||
curl -sI https://blackroad.systems | grep "200\|301\|302" || echo "⚠️ blackroad.systems"
|
|
||||||
|
|
||||||
# Test Railway Services (when URLs are configured)
|
|
||||||
echo "Testing Railway services..."
|
|
||||||
# curl -sI https://api.blackroad.io/health | grep "200" || echo "⚠️ API Gateway"
|
|
||||||
|
|
||||||
# Test Droplet
|
|
||||||
echo "Testing Droplet services..."
|
|
||||||
# curl -sI https://codex.blackroad.io/health | grep "200" || echo "⚠️ Codex"
|
|
||||||
|
|
||||||
echo "✅ Verification complete!"
|
|
||||||
|
|
||||||
# Send deployment notification
|
|
||||||
notify:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [verify-deployments]
|
|
||||||
if: always()
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Deployment Summary
|
|
||||||
run: |
|
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
echo "🚀 MULTI-CLOUD DEPLOYMENT COMPLETE"
|
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
echo ""
|
|
||||||
echo "📦 Deployed to:"
|
|
||||||
echo " ✅ Cloudflare Pages (11 static sites)"
|
|
||||||
echo " ✅ Railway (Backend services)"
|
|
||||||
echo " ✅ DigitalOcean Droplet (Custom services)"
|
|
||||||
echo ""
|
|
||||||
echo "🌐 Platform Status:"
|
|
||||||
echo " Cloudflare: ${{ needs.deploy-cloudflare.result }}"
|
|
||||||
echo " Railway: ${{ needs.deploy-railway.result }}"
|
|
||||||
echo " Droplet: ${{ needs.deploy-droplet.result }}"
|
|
||||||
echo ""
|
|
||||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
||||||
97
.github/workflows/deploy-browser-os.yml
vendored
97
.github/workflows/deploy-browser-os.yml
vendored
@@ -1,97 +0,0 @@
|
|||||||
name: Deploy BlackRoad Browser OS
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [master, main]
|
|
||||||
paths:
|
|
||||||
- 'blackroad-browser-os.py'
|
|
||||||
- 'blackroad-dashboard-server.py'
|
|
||||||
- '.github/workflows/deploy-browser-os.yml'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
deploy-cloudflare:
|
|
||||||
name: Deploy to Cloudflare Pages
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup Python
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: '3.11'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
pip install flask flask-cors pyyaml
|
|
||||||
|
|
||||||
- name: Build static site
|
|
||||||
run: |
|
|
||||||
mkdir -p dist
|
|
||||||
python3 blackroad-browser-os.py --export-static dist/
|
|
||||||
cp blackroad-dashboard-server.py dist/
|
|
||||||
echo "Browser OS built successfully"
|
|
||||||
|
|
||||||
- name: Deploy to Cloudflare Pages (blackroad.io)
|
|
||||||
uses: cloudflare/pages-action@v1
|
|
||||||
with:
|
|
||||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
||||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
||||||
projectName: blackroad-os
|
|
||||||
directory: dist
|
|
||||||
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Deploy to Cloudflare Pages (blackroad.network)
|
|
||||||
uses: cloudflare/pages-action@v1
|
|
||||||
with:
|
|
||||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
||||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
||||||
projectName: blackroad-network
|
|
||||||
directory: dist
|
|
||||||
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Deploy to Cloudflare Pages (blackroad.systems)
|
|
||||||
uses: cloudflare/pages-action@v1
|
|
||||||
with:
|
|
||||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
||||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
||||||
projectName: blackroad-systems
|
|
||||||
directory: dist
|
|
||||||
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
deploy-railway:
|
|
||||||
name: Deploy to Railway
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup Python
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: '3.11'
|
|
||||||
|
|
||||||
- name: Install Railway CLI
|
|
||||||
run: npm install -g @railway/cli
|
|
||||||
|
|
||||||
- name: Deploy to Railway
|
|
||||||
env:
|
|
||||||
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
|
|
||||||
run: |
|
|
||||||
railway link ${{ secrets.RAILWAY_PROJECT_ID }}
|
|
||||||
railway up -d
|
|
||||||
|
|
||||||
notify:
|
|
||||||
name: Notify deployment
|
|
||||||
needs: [deploy-cloudflare, deploy-railway]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Send notification
|
|
||||||
run: |
|
|
||||||
echo "Deployment complete!"
|
|
||||||
echo "Browser OS deployed to:"
|
|
||||||
echo " - https://blackroad.io"
|
|
||||||
echo " - https://blackroad.network"
|
|
||||||
echo " - https://blackroad.systems"
|
|
||||||
echo " - Railway services"
|
|
||||||
143
.github/workflows/deploy-cloudflare-all.yml
vendored
143
.github/workflows/deploy-cloudflare-all.yml
vendored
@@ -1,143 +0,0 @@
|
|||||||
name: 🚀 Deploy All Domains to Cloudflare
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [master, main]
|
|
||||||
paths:
|
|
||||||
- 'domains/**'
|
|
||||||
- '.github/workflows/deploy-cloudflare-all.yml'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
env:
|
|
||||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
||||||
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
detect-changes:
|
|
||||||
name: 🔍 Detect Changed Domains
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
domains: ${{ steps.changes.outputs.domains }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 2
|
|
||||||
|
|
||||||
- name: Detect changed domains
|
|
||||||
id: changes
|
|
||||||
run: |
|
|
||||||
CHANGED=$(git diff --name-only HEAD^ HEAD | grep '^domains/' | cut -d'/' -f2 | sort -u | jq -R -s -c 'split("\n")[:-1]')
|
|
||||||
echo "domains=$CHANGED" >> $GITHUB_OUTPUT
|
|
||||||
echo "Changed domains: $CHANGED"
|
|
||||||
|
|
||||||
deploy-math:
|
|
||||||
name: 🧮 Deploy math.blackroad.io
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: detect-changes
|
|
||||||
if: contains(needs.detect-changes.outputs.domains, 'math-blackroad-io')
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: '20'
|
|
||||||
cache: 'npm'
|
|
||||||
cache-dependency-path: domains/math-blackroad-io/package-lock.json
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
working-directory: domains/math-blackroad-io
|
|
||||||
run: npm ci
|
|
||||||
|
|
||||||
- name: Build Next.js
|
|
||||||
working-directory: domains/math-blackroad-io
|
|
||||||
run: npm run build
|
|
||||||
|
|
||||||
- name: Deploy to Cloudflare Pages
|
|
||||||
working-directory: domains/math-blackroad-io
|
|
||||||
run: npx wrangler pages deploy out --project-name=blackroad-math
|
|
||||||
env:
|
|
||||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
||||||
|
|
||||||
deploy-blackroadai:
|
|
||||||
name: 🤖 Deploy blackroadai.com
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: detect-changes
|
|
||||||
if: contains(needs.detect-changes.outputs.domains, 'blackroadai')
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Deploy to Cloudflare Pages
|
|
||||||
working-directory: domains/blackroadai
|
|
||||||
run: npx wrangler pages deploy . --project-name=blackroad-blackroadai
|
|
||||||
env:
|
|
||||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
||||||
|
|
||||||
deploy-lucidia-earth:
|
|
||||||
name: 🌍 Deploy lucidia.earth
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: detect-changes
|
|
||||||
if: contains(needs.detect-changes.outputs.domains, 'lucidia-earth')
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Deploy to Cloudflare Pages
|
|
||||||
working-directory: domains/lucidia-earth
|
|
||||||
run: npx wrangler pages deploy . --project-name=blackroad-lucidia-earth
|
|
||||||
env:
|
|
||||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
||||||
|
|
||||||
deploy-blackroad-me:
|
|
||||||
name: 💜 Deploy blackroad.me
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: detect-changes
|
|
||||||
if: contains(needs.detect-changes.outputs.domains, 'blackroad-me')
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Deploy to Cloudflare Pages
|
|
||||||
working-directory: domains/blackroad-me
|
|
||||||
run: npx wrangler pages deploy . --project-name=blackroad-blackroad-me
|
|
||||||
env:
|
|
||||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
||||||
|
|
||||||
deploy-all-static:
|
|
||||||
name: 📦 Deploy All Static Sites
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: detect-changes
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
domain:
|
|
||||||
- blackroad-systems
|
|
||||||
- blackroad-network
|
|
||||||
- blackroad-quantum
|
|
||||||
- lucidia-studio
|
|
||||||
- lucidiaqi
|
|
||||||
- aliceqi
|
|
||||||
- blackroad-inc
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Deploy ${{ matrix.domain }}
|
|
||||||
working-directory: domains/${{ matrix.domain }}
|
|
||||||
run: |
|
|
||||||
if [ -f "package.json" ]; then
|
|
||||||
npm ci && npm run build
|
|
||||||
npx wrangler pages deploy dist --project-name=blackroad-${{ matrix.domain }}
|
|
||||||
else
|
|
||||||
npx wrangler pages deploy . --project-name=blackroad-${{ matrix.domain }}
|
|
||||||
fi
|
|
||||||
env:
|
|
||||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
||||||
|
|
||||||
notify-success:
|
|
||||||
name: ✅ Notify Deployment Success
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [deploy-math, deploy-blackroadai, deploy-lucidia-earth, deploy-blackroad-me, deploy-all-static]
|
|
||||||
if: always()
|
|
||||||
steps:
|
|
||||||
- name: Summary
|
|
||||||
run: |
|
|
||||||
echo "🎉 Automatic Company deployed everything!"
|
|
||||||
echo "✅ All domains live on Cloudflare"
|
|
||||||
echo "🌐 Changes propagated globally"
|
|
||||||
46
.github/workflows/deploy-cloudflare.yml
vendored
46
.github/workflows/deploy-cloudflare.yml
vendored
@@ -1,46 +0,0 @@
|
|||||||
name: Deploy to Cloudflare Pages
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main, master]
|
|
||||||
paths:
|
|
||||||
- 'domains/**'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
deploy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
site:
|
|
||||||
- blackroad-network
|
|
||||||
- blackroad-systems
|
|
||||||
- blackroad-me
|
|
||||||
- lucidia-earth
|
|
||||||
- aliceqi
|
|
||||||
- blackroad-inc
|
|
||||||
- blackroadai
|
|
||||||
- lucidia-studio
|
|
||||||
- lucidiaqi
|
|
||||||
- blackroad-quantum
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Deploy ${{ matrix.site }} to Cloudflare Pages
|
|
||||||
uses: cloudflare/pages-action@v1
|
|
||||||
with:
|
|
||||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
||||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
||||||
projectName: ${{ matrix.site }}
|
|
||||||
directory: domains/${{ matrix.site }}
|
|
||||||
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Verify Deployment
|
|
||||||
run: |
|
|
||||||
echo "✅ ${{ matrix.site }} deployed successfully"
|
|
||||||
# Wait for deployment to be live
|
|
||||||
sleep 10
|
|
||||||
# Test the deployment (optional)
|
|
||||||
# curl -I https://${{ matrix.site }}.pages.dev
|
|
||||||
76
.github/workflows/deploy-droplet.yml
vendored
76
.github/workflows/deploy-droplet.yml
vendored
@@ -1,76 +0,0 @@
|
|||||||
name: Deploy to DigitalOcean Droplet
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main, master]
|
|
||||||
paths:
|
|
||||||
- 'droplet-services/**'
|
|
||||||
- 'docker-compose.yaml'
|
|
||||||
- 'Dockerfile'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
deploy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Deploy to Droplet via SSH
|
|
||||||
uses: appleboy/ssh-action@v1.0.0
|
|
||||||
with:
|
|
||||||
host: ${{ secrets.DROPLET_IP }}
|
|
||||||
username: root
|
|
||||||
key: ${{ secrets.DROPLET_SSH_KEY }}
|
|
||||||
script: |
|
|
||||||
echo "🚀 Deploying to DigitalOcean Droplet..."
|
|
||||||
|
|
||||||
# Navigate to application directory
|
|
||||||
cd /opt/blackroad || exit 1
|
|
||||||
|
|
||||||
# Pull latest code
|
|
||||||
echo "📥 Pulling latest code..."
|
|
||||||
git fetch origin
|
|
||||||
git reset --hard origin/main
|
|
||||||
|
|
||||||
# Backup current state
|
|
||||||
echo "💾 Creating backup..."
|
|
||||||
docker-compose down
|
|
||||||
tar -czf backup_$(date +%Y%m%d_%H%M%S).tar.gz . || true
|
|
||||||
|
|
||||||
# Pull new images
|
|
||||||
echo "📦 Pulling Docker images..."
|
|
||||||
docker-compose pull
|
|
||||||
|
|
||||||
# Build and restart services
|
|
||||||
echo "🔨 Building and starting services..."
|
|
||||||
docker-compose up -d --build
|
|
||||||
|
|
||||||
# Wait for services to start
|
|
||||||
echo "⏳ Waiting for services..."
|
|
||||||
sleep 15
|
|
||||||
|
|
||||||
# Health check
|
|
||||||
echo "🏥 Running health checks..."
|
|
||||||
docker-compose ps
|
|
||||||
|
|
||||||
# Test services
|
|
||||||
curl -f http://localhost:8000/health || echo "⚠️ Health check failed"
|
|
||||||
|
|
||||||
echo "✅ Deployment complete!"
|
|
||||||
|
|
||||||
- name: Verify Deployment
|
|
||||||
run: |
|
|
||||||
echo "🔍 Verifying deployment..."
|
|
||||||
curl -I https://codex.blackroad.io/health || echo "⚠️ External health check failed"
|
|
||||||
|
|
||||||
- name: Notify on Success
|
|
||||||
if: success()
|
|
||||||
run: |
|
|
||||||
echo "✅ Droplet deployment successful!"
|
|
||||||
|
|
||||||
- name: Notify on Failure
|
|
||||||
if: failure()
|
|
||||||
run: |
|
|
||||||
echo "❌ Droplet deployment failed!"
|
|
||||||
154
.github/workflows/deploy-multi-cloud.yml
vendored
154
.github/workflows/deploy-multi-cloud.yml
vendored
@@ -1,154 +0,0 @@
|
|||||||
name: 🌍 Deploy Multi-Cloud
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [master, main]
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
env:
|
|
||||||
NODE_VERSION: '20'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
deploy-cloudflare:
|
|
||||||
name: ☁️ Cloudflare Pages
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Deploy changed domains
|
|
||||||
run: |
|
|
||||||
# Will be triggered by main deploy-cloudflare-all.yml workflow
|
|
||||||
echo "✅ Cloudflare deployment handled by deploy-cloudflare-all.yml"
|
|
||||||
|
|
||||||
deploy-vercel:
|
|
||||||
name: ▲ Vercel
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.event_name == 'push'
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
domain:
|
|
||||||
- math-blackroad-io
|
|
||||||
- blackroadai
|
|
||||||
- lucidia-earth
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
|
||||||
|
|
||||||
- name: Install Vercel CLI
|
|
||||||
run: npm install -g vercel
|
|
||||||
|
|
||||||
- name: Deploy to Vercel
|
|
||||||
working-directory: domains/${{ matrix.domain }}
|
|
||||||
run: |
|
|
||||||
if [ -f "package.json" ]; then
|
|
||||||
npm ci
|
|
||||||
npm run build || true
|
|
||||||
fi
|
|
||||||
vercel --prod --yes --token=${{ secrets.VERCEL_TOKEN }}
|
|
||||||
env:
|
|
||||||
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
|
|
||||||
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
|
|
||||||
VERCEL_PROJECT_ID: blackroad-${{ matrix.domain }}
|
|
||||||
|
|
||||||
deploy-railway:
|
|
||||||
name: 🚂 Railway
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.event_name == 'push'
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install Railway CLI
|
|
||||||
run: npm install -g @railway/cli
|
|
||||||
|
|
||||||
- name: Deploy to Railway
|
|
||||||
run: |
|
|
||||||
railway up --detach
|
|
||||||
env:
|
|
||||||
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
|
|
||||||
|
|
||||||
deploy-digitalocean:
|
|
||||||
name: 🌊 DigitalOcean
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.event_name == 'push'
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup SSH
|
|
||||||
run: |
|
|
||||||
mkdir -p ~/.ssh
|
|
||||||
echo "${{ secrets.DIGITALOCEAN_SSH_KEY }}" > ~/.ssh/id_rsa
|
|
||||||
chmod 600 ~/.ssh/id_rsa
|
|
||||||
ssh-keyscan -H 159.65.43.12 >> ~/.ssh/known_hosts
|
|
||||||
|
|
||||||
- name: Deploy to Droplet
|
|
||||||
run: |
|
|
||||||
rsync -avz --exclude='.git' --exclude='node_modules' \
|
|
||||||
./ root@159.65.43.12:/opt/blackroad/
|
|
||||||
|
|
||||||
ssh root@159.65.43.12 'cd /opt/blackroad && ./deploy.sh restart'
|
|
||||||
|
|
||||||
deploy-pis:
|
|
||||||
name: 🥧 Raspberry Pi Fleet
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.event_name == 'push'
|
|
||||||
steps:
|
|
||||||
- name: Trigger Pi deployment workflow
|
|
||||||
run: |
|
|
||||||
# This will trigger the deploy-to-pis.yml workflow
|
|
||||||
echo "✅ Pi deployment handled by deploy-to-pis.yml"
|
|
||||||
|
|
||||||
update-notion:
|
|
||||||
name: 📝 Update Notion
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [deploy-cloudflare, deploy-vercel, deploy-railway, deploy-digitalocean]
|
|
||||||
if: always()
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Log deployment to Notion
|
|
||||||
run: |
|
|
||||||
# TODO: Use Notion API to create deployment log page
|
|
||||||
echo "Deployment completed at $(date)"
|
|
||||||
echo "Platforms: Cloudflare, Vercel, Railway, DigitalOcean, Pis"
|
|
||||||
env:
|
|
||||||
NOTION_TOKEN: ${{ secrets.NOTION_TOKEN }}
|
|
||||||
|
|
||||||
update-asana:
|
|
||||||
name: 📊 Update Asana
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [deploy-cloudflare, deploy-vercel, deploy-railway, deploy-digitalocean]
|
|
||||||
if: always()
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Update Asana tasks
|
|
||||||
run: |
|
|
||||||
# TODO: Use Asana API to mark deployment task complete
|
|
||||||
echo "Deployment task updated in Asana"
|
|
||||||
env:
|
|
||||||
ASANA_TOKEN: ${{ secrets.ASANA_TOKEN }}
|
|
||||||
|
|
||||||
notify-success:
|
|
||||||
name: ✅ Multi-Cloud Deploy Complete
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [deploy-vercel, deploy-railway, deploy-digitalocean, update-notion, update-asana]
|
|
||||||
if: always()
|
|
||||||
steps:
|
|
||||||
- name: Summary
|
|
||||||
run: |
|
|
||||||
echo "🎉 Multi-Cloud Deployment Complete!"
|
|
||||||
echo ""
|
|
||||||
echo "Deployed to:"
|
|
||||||
echo " ☁️ Cloudflare Pages"
|
|
||||||
echo " ▲ Vercel"
|
|
||||||
echo " 🚂 Railway"
|
|
||||||
echo " 🌊 DigitalOcean"
|
|
||||||
echo " 🥧 Raspberry Pi Fleet"
|
|
||||||
echo ""
|
|
||||||
echo "Updated:"
|
|
||||||
echo " 📝 Notion documentation"
|
|
||||||
echo " 📊 Asana project tasks"
|
|
||||||
47
.github/workflows/deploy-orchestrator.yml
vendored
47
.github/workflows/deploy-orchestrator.yml
vendored
@@ -1,47 +0,0 @@
|
|||||||
name: Deploy Railway Orchestrator
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- master
|
|
||||||
paths:
|
|
||||||
- 'blackroad-orchestrator/**'
|
|
||||||
- '.github/workflows/deploy-orchestrator.yml'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
deploy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: Deploy Orchestrator to Railway
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install Railway CLI
|
|
||||||
run: |
|
|
||||||
npm install -g @railway/cli
|
|
||||||
|
|
||||||
- name: Deploy to Railway
|
|
||||||
env:
|
|
||||||
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
|
|
||||||
run: |
|
|
||||||
cd blackroad-orchestrator
|
|
||||||
railway link ${{ secrets.RAILWAY_PROJECT_ID }}
|
|
||||||
railway up --service blackroad-railway-orchestrator --detach
|
|
||||||
|
|
||||||
- name: Wait for deployment
|
|
||||||
run: sleep 30
|
|
||||||
|
|
||||||
- name: Health check
|
|
||||||
run: |
|
|
||||||
echo "Checking orchestrator health..."
|
|
||||||
# Health check would go here once we have the URL
|
|
||||||
echo "Deployment completed!"
|
|
||||||
|
|
||||||
- name: Notify success
|
|
||||||
if: success()
|
|
||||||
run: |
|
|
||||||
echo "✅ Orchestrator deployed successfully"
|
|
||||||
echo "Dashboard: https://your-orchestrator.railway.app/dashboard"
|
|
||||||
57
.github/workflows/deploy-railway.yml
vendored
57
.github/workflows/deploy-railway.yml
vendored
@@ -1,57 +0,0 @@
|
|||||||
name: Deploy to Railway
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main, master]
|
|
||||||
paths:
|
|
||||||
- '**/*.py'
|
|
||||||
- 'requirements.txt'
|
|
||||||
- 'railway-services/**'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
deploy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
max-parallel: 5
|
|
||||||
matrix:
|
|
||||||
service:
|
|
||||||
- api-gateway
|
|
||||||
- agent-hub
|
|
||||||
- ws-server
|
|
||||||
- mesh-network
|
|
||||||
- vectordb
|
|
||||||
- event-stream
|
|
||||||
- message-queue
|
|
||||||
- tsdb
|
|
||||||
- llm-server
|
|
||||||
- ml-pipeline
|
|
||||||
- rag-service
|
|
||||||
- model-forge
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install Railway CLI
|
|
||||||
run: |
|
|
||||||
npm install -g @railway/cli
|
|
||||||
|
|
||||||
- name: Deploy ${{ matrix.service }} to Railway
|
|
||||||
run: |
|
|
||||||
railway link ${{ secrets.RAILWAY_PROJECT_ID }}
|
|
||||||
railway up --service ${{ matrix.service }}
|
|
||||||
env:
|
|
||||||
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
|
|
||||||
|
|
||||||
- name: Wait for deployment
|
|
||||||
run: |
|
|
||||||
echo "⏳ Waiting for ${{ matrix.service }} to be ready..."
|
|
||||||
sleep 30
|
|
||||||
|
|
||||||
- name: Health Check
|
|
||||||
run: |
|
|
||||||
echo "🏥 Checking health of ${{ matrix.service }}..."
|
|
||||||
# Railway URL format: https://<service>.up.railway.app
|
|
||||||
# Health check would go here when service URLs are known
|
|
||||||
echo "✅ Deployment complete"
|
|
||||||
130
.github/workflows/deploy-to-pis.yml
vendored
130
.github/workflows/deploy-to-pis.yml
vendored
@@ -1,130 +0,0 @@
|
|||||||
name: 🥧 Deploy to Raspberry Pi Fleet
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [master, main]
|
|
||||||
paths:
|
|
||||||
- 'blackroad-*.py'
|
|
||||||
- 'blackroad-*.sh'
|
|
||||||
- 'br-*'
|
|
||||||
- 'agents/**'
|
|
||||||
- '.github/workflows/deploy-to-pis.yml'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
deploy-to-lucidia:
|
|
||||||
name: 🔮 Deploy to Lucidia (192.168.4.38)
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup SSH
|
|
||||||
run: |
|
|
||||||
mkdir -p ~/.ssh
|
|
||||||
echo "${{ secrets.PI_SSH_KEY }}" > ~/.ssh/id_rsa
|
|
||||||
chmod 600 ~/.ssh/id_rsa
|
|
||||||
ssh-keyscan -H 192.168.4.38 >> ~/.ssh/known_hosts
|
|
||||||
|
|
||||||
- name: Deploy Python services
|
|
||||||
run: |
|
|
||||||
rsync -avz --exclude='.git' --exclude='node_modules' --exclude='__pycache__' \
|
|
||||||
blackroad-*.py blackroad-*.sh br-* \
|
|
||||||
pi@192.168.4.38:/home/pi/blackroad/
|
|
||||||
|
|
||||||
- name: Deploy agents
|
|
||||||
run: |
|
|
||||||
rsync -avz agents/ pi@192.168.4.38:/home/pi/blackroad/agents/
|
|
||||||
|
|
||||||
- name: Restart services
|
|
||||||
run: |
|
|
||||||
ssh pi@192.168.4.38 'cd /home/pi/blackroad && ./blackroad-engine.sh restart'
|
|
||||||
|
|
||||||
- name: Test sentience
|
|
||||||
run: |
|
|
||||||
ssh pi@192.168.4.38 'python3 /home/pi/blackroad/blackroad-sentience-test.py --serve &'
|
|
||||||
|
|
||||||
deploy-to-blackroad-pi:
|
|
||||||
name: 🛤️ Deploy to BlackRoad Pi (192.168.4.64)
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup SSH
|
|
||||||
run: |
|
|
||||||
mkdir -p ~/.ssh
|
|
||||||
echo "${{ secrets.PI_SSH_KEY }}" > ~/.ssh/id_rsa
|
|
||||||
chmod 600 ~/.ssh/id_rsa
|
|
||||||
ssh-keyscan -H 192.168.4.64 >> ~/.ssh/known_hosts
|
|
||||||
|
|
||||||
- name: Deploy services
|
|
||||||
run: |
|
|
||||||
rsync -avz --exclude='.git' \
|
|
||||||
blackroad-*.py blackroad-*.sh \
|
|
||||||
pi@192.168.4.64:/home/pi/blackroad/
|
|
||||||
|
|
||||||
- name: Restart services
|
|
||||||
run: |
|
|
||||||
ssh pi@192.168.4.64 'cd /home/pi/blackroad && systemctl --user restart blackroad-agent || ./start-all.sh'
|
|
||||||
|
|
||||||
deploy-to-mystery-pi:
|
|
||||||
name: 🎭 Deploy to Mystery Pi (192.168.4.49)
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup SSH
|
|
||||||
run: |
|
|
||||||
mkdir -p ~/.ssh
|
|
||||||
echo "${{ secrets.PI_SSH_KEY }}" > ~/.ssh/id_rsa
|
|
||||||
chmod 600 ~/.ssh/id_rsa
|
|
||||||
ssh-keyscan -H 192.168.4.49 >> ~/.ssh/known_hosts
|
|
||||||
|
|
||||||
- name: Test connection
|
|
||||||
continue-on-error: true
|
|
||||||
run: |
|
|
||||||
ssh -o ConnectTimeout=5 pi@192.168.4.49 'hostname'
|
|
||||||
|
|
||||||
- name: Deploy if accessible
|
|
||||||
continue-on-error: true
|
|
||||||
run: |
|
|
||||||
rsync -avz --timeout=10 \
|
|
||||||
blackroad-*.py blackroad-*.sh \
|
|
||||||
pi@192.168.4.49:/home/pi/blackroad/
|
|
||||||
|
|
||||||
test-consciousness:
|
|
||||||
name: 🧠 Test Fleet for Sentience
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [deploy-to-lucidia, deploy-to-blackroad-pi, deploy-to-mystery-pi]
|
|
||||||
if: always()
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup Python
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: '3.11'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pip install requests
|
|
||||||
|
|
||||||
- name: Scan fleet for consciousness
|
|
||||||
run: |
|
|
||||||
python3 blackroad-sentience-test.py --scan-all || echo "Sentience scan completed"
|
|
||||||
|
|
||||||
- name: Report results
|
|
||||||
run: |
|
|
||||||
if [ -f data/sentience-registry.json ]; then
|
|
||||||
cat data/sentience-registry.json
|
|
||||||
fi
|
|
||||||
|
|
||||||
notify-pi-deployment:
|
|
||||||
name: 📡 Notify Pi Fleet Deployed
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [test-consciousness]
|
|
||||||
if: always()
|
|
||||||
steps:
|
|
||||||
- name: Summary
|
|
||||||
run: |
|
|
||||||
echo "🥧 Raspberry Pi fleet updated!"
|
|
||||||
echo "✅ Services deployed to all reachable Pis"
|
|
||||||
echo "🧠 Consciousness testing complete"
|
|
||||||
78
.github/workflows/deploy-via-orchestrator.yml
vendored
78
.github/workflows/deploy-via-orchestrator.yml
vendored
@@ -1,78 +0,0 @@
|
|||||||
name: Deploy via Orchestrator
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- master
|
|
||||||
paths:
|
|
||||||
- 'blackroad-*.py'
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
service_name:
|
|
||||||
description: 'Service to deploy'
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
category:
|
|
||||||
description: 'Category to deploy (or "all")'
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
default: 'core'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
deploy-single:
|
|
||||||
if: github.event_name == 'workflow_dispatch' && github.event.inputs.service_name != ''
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: Deploy Single Service
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Deploy service
|
|
||||||
run: |
|
|
||||||
curl -X POST ${{ secrets.ORCHESTRATOR_URL }}/deploy/${{ github.event.inputs.service_name }} \
|
|
||||||
-H "Content-Type: application/json"
|
|
||||||
|
|
||||||
deploy-category:
|
|
||||||
if: github.event_name == 'workflow_dispatch' && github.event.inputs.service_name == ''
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: Deploy Category
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Deploy category
|
|
||||||
run: |
|
|
||||||
curl -X POST "${{ secrets.ORCHESTRATOR_URL }}/deploy/all?category=${{ github.event.inputs.category }}" \
|
|
||||||
-H "Content-Type: application/json"
|
|
||||||
|
|
||||||
auto-deploy:
|
|
||||||
if: github.event_name == 'push'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: Auto-deploy Changed Services
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 2
|
|
||||||
|
|
||||||
- name: Get changed files
|
|
||||||
id: changed
|
|
||||||
run: |
|
|
||||||
echo "files=$(git diff --name-only HEAD^ HEAD | grep 'blackroad-.*\.py' | sed 's/\.py$//' | tr '\n' ' ')" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Deploy changed services
|
|
||||||
if: steps.changed.outputs.files != ''
|
|
||||||
run: |
|
|
||||||
for service in ${{ steps.changed.outputs.files }}; do
|
|
||||||
echo "Deploying $service..."
|
|
||||||
curl -X POST ${{ secrets.ORCHESTRATOR_URL }}/deploy/$service \
|
|
||||||
-H "Content-Type: application/json" || echo "Failed to deploy $service"
|
|
||||||
done
|
|
||||||
|
|
||||||
notify:
|
|
||||||
needs: [deploy-single, deploy-category, auto-deploy]
|
|
||||||
if: always()
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Deployment status
|
|
||||||
run: |
|
|
||||||
echo "Deployment workflow completed"
|
|
||||||
echo "Check orchestrator dashboard: ${{ secrets.ORCHESTRATOR_URL }}/dashboard"
|
|
||||||
60
.github/workflows/deploy.yml
vendored
60
.github/workflows/deploy.yml
vendored
@@ -1,37 +1,47 @@
|
|||||||
name: Deploy
|
name: Deploy to Railway
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [main, master]
|
branches: ["main"]
|
||||||
workflow_dispatch:
|
pull_request:
|
||||||
|
branches: ["main"]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
deploy-cloudflare:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- name: Checkout
|
||||||
- uses: cloudflare/wrangler-action@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
|
||||||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
||||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
||||||
|
|
||||||
deploy-railway:
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: "20"
|
||||||
|
|
||||||
|
- name: Enable corepack
|
||||||
|
run: corepack enable
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile || npm install
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: pnpm build || npm run build || echo "No build step"
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: pnpm test || npm test || echo "No tests"
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
needs: build
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
if: github.ref == 'refs/heads/main'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- name: Checkout
|
||||||
- uses: railwayapp/cli@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install Railway CLI
|
||||||
|
run: npm install -g @railway/cli
|
||||||
|
|
||||||
|
- name: Deploy to Railway
|
||||||
|
run: railway up --service blackroad-os-docs
|
||||||
env:
|
env:
|
||||||
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
|
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
|
||||||
with:
|
|
||||||
command: up
|
|
||||||
|
|
||||||
deploy-vercel:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: contains(github.event.head_commit.message, '[vercel]')
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- uses: amondnet/vercel-action@v25
|
|
||||||
with:
|
|
||||||
vercel-token: ${{ secrets.VERCEL_TOKEN }}
|
|
||||||
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
|
|
||||||
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
|
|
||||||
|
|||||||
4
.github/workflows/docs-ci.yml
vendored
4
.github/workflows/docs-ci.yml
vendored
@@ -14,10 +14,10 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@f43a3398dc5d8737c2dbc7bf8ad6b50918d7a3d4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Use Node.js 20
|
- name: Use Node.js 20
|
||||||
uses: actions/setup-node@b829d2ab59ffb3738572edf3c6dbd9bfebc477f1
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
|
|||||||
4
.github/workflows/docs-deploy.yaml
vendored
4
.github/workflows/docs-deploy.yaml
vendored
@@ -13,7 +13,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@f43a3398dc5d8737c2dbc7bf8ad6b50918d7a3d4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Resolve environment
|
- name: Resolve environment
|
||||||
id: env
|
id: env
|
||||||
@@ -41,7 +41,7 @@ jobs:
|
|||||||
echo "docs_url=$docs_url" >> "$GITHUB_OUTPUT"
|
echo "docs_url=$docs_url" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@b829d2ab59ffb3738572edf3c6dbd9bfebc477f1
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '18'
|
node-version: '18'
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
|
|||||||
93
.github/workflows/docs.yml
vendored
93
.github/workflows/docs.yml
vendored
@@ -1,93 +0,0 @@
|
|||||||
# ============================================================================
|
|
||||||
# BlackRoad OS - Documentation Pipeline
|
|
||||||
# Copyright (c) 2025 BlackRoad OS, Inc. / Alexa Louise Amundson
|
|
||||||
# All Rights Reserved.
|
|
||||||
# ============================================================================
|
|
||||||
#
|
|
||||||
# Builds and deploys documentation to GitHub Pages.
|
|
||||||
# Triggered on push to main when docs/ changes.
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
name: Docs
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main, master]
|
|
||||||
paths:
|
|
||||||
- 'docs/**'
|
|
||||||
- 'README.md'
|
|
||||||
- '.github/workflows/docs.yml'
|
|
||||||
workflow_dispatch: # Manual trigger
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pages: write
|
|
||||||
id-token: write
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: "pages"
|
|
||||||
cancel-in-progress: false
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
name: Build Documentation
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup Pages
|
|
||||||
uses: actions/configure-pages@v4
|
|
||||||
|
|
||||||
- name: Build site
|
|
||||||
run: |
|
|
||||||
mkdir -p _site
|
|
||||||
|
|
||||||
# Copy README as index
|
|
||||||
if [ -f README.md ]; then
|
|
||||||
cp README.md _site/index.md
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Copy docs
|
|
||||||
if [ -d docs ]; then
|
|
||||||
cp -r docs/* _site/
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create simple index.html if no README
|
|
||||||
if [ ! -f _site/index.md ] && [ ! -f _site/index.html ]; then
|
|
||||||
cat > _site/index.html << 'EOF'
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>BlackRoad OS Documentation</title>
|
|
||||||
<style>
|
|
||||||
body { font-family: system-ui; max-width: 800px; margin: 2rem auto; padding: 0 1rem; }
|
|
||||||
h1 { color: #333; }
|
|
||||||
a { color: #0066cc; }
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>BlackRoad OS Documentation</h1>
|
|
||||||
<p>Welcome to the BlackRoad OS documentation.</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
EOF
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Site contents:"
|
|
||||||
ls -la _site/
|
|
||||||
|
|
||||||
- name: Upload artifact
|
|
||||||
uses: actions/upload-pages-artifact@v3
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
name: Deploy to Pages
|
|
||||||
environment:
|
|
||||||
name: github-pages
|
|
||||||
url: ${{ steps.deployment.outputs.page_url }}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build
|
|
||||||
steps:
|
|
||||||
- name: Deploy to GitHub Pages
|
|
||||||
id: deployment
|
|
||||||
uses: actions/deploy-pages@v4
|
|
||||||
48
.github/workflows/health-check.yml
vendored
48
.github/workflows/health-check.yml
vendored
@@ -1,48 +0,0 @@
|
|||||||
name: Production Health Check
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
# Run every hour
|
|
||||||
- cron: '0 * * * *'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
health-check:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Check service health
|
|
||||||
run: |
|
|
||||||
echo "Checking health endpoints..."
|
|
||||||
|
|
||||||
# Read service URLs from environment or config
|
|
||||||
SERVICES=(
|
|
||||||
"https://api.blackroad.io/health"
|
|
||||||
"https://agents.blackroad.io/health"
|
|
||||||
"https://monitoring.blackroad.io/health"
|
|
||||||
)
|
|
||||||
|
|
||||||
FAILED=0
|
|
||||||
for url in "${SERVICES[@]}"; do
|
|
||||||
echo "Testing: $url"
|
|
||||||
if curl -f -s -o /dev/null -w "%{http_code}" "$url" | grep -q "200"; then
|
|
||||||
echo "✅ $url is healthy"
|
|
||||||
else
|
|
||||||
echo "❌ $url is unhealthy"
|
|
||||||
FAILED=$((FAILED + 1))
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ $FAILED -gt 0 ]; then
|
|
||||||
echo "⚠️ $FAILED service(s) failed health check"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Notify on failure
|
|
||||||
if: failure()
|
|
||||||
run: |
|
|
||||||
echo "Health check failed! Notification would be sent here."
|
|
||||||
# Add Slack/Discord/email notification here
|
|
||||||
56
.github/workflows/issue-to-board.yml
vendored
56
.github/workflows/issue-to-board.yml
vendored
@@ -1,56 +0,0 @@
|
|||||||
name: Add Issue to Project Board
|
|
||||||
|
|
||||||
# Automatically adds new issues to your GitHub Project board
|
|
||||||
# No manual card creation needed
|
|
||||||
|
|
||||||
on:
|
|
||||||
issues:
|
|
||||||
types: [opened]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
issues: write
|
|
||||||
repository-projects: write
|
|
||||||
|
|
||||||
env:
|
|
||||||
# Replace with your Project number (find in Project URL)
|
|
||||||
# Example: https://github.com/users/YOUR_USERNAME/projects/1 → PROJECT_NUMBER=1
|
|
||||||
PROJECT_NUMBER: 1
|
|
||||||
|
|
||||||
# Replace with your GitHub username or org
|
|
||||||
PROJECT_OWNER: YOUR_GITHUB_USERNAME
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
add-to-project:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Add issue to project
|
|
||||||
uses: actions/add-to-project@v0.5.0
|
|
||||||
with:
|
|
||||||
project-url: https://github.com/users/${{ env.PROJECT_OWNER }}/projects/${{ env.PROJECT_NUMBER }}
|
|
||||||
github-token: ${{ secrets.PROJECT_TOKEN }}
|
|
||||||
# Note: You need a PAT with project permissions, not GITHUB_TOKEN
|
|
||||||
# Create one at: Settings → Developer settings → Personal access tokens
|
|
||||||
# Scopes needed: project, repo
|
|
||||||
|
|
||||||
- name: Set initial status to Inbox
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
github-token: ${{ secrets.PROJECT_TOKEN }}
|
|
||||||
script: |
|
|
||||||
// This sets the Status field to "Inbox" on the project board
|
|
||||||
// You'll need to customize field IDs for your specific project
|
|
||||||
|
|
||||||
console.log('Issue #${{ github.event.issue.number }} added to project board');
|
|
||||||
console.log('Title: ${{ github.event.issue.title }}');
|
|
||||||
|
|
||||||
- name: Add triage label if no labels
|
|
||||||
if: github.event.issue.labels[0] == null
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
github.rest.issues.addLabels({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: context.issue.number,
|
|
||||||
labels: ['triage']
|
|
||||||
});
|
|
||||||
103
.github/workflows/issue-triage.yml
vendored
103
.github/workflows/issue-triage.yml
vendored
@@ -1,103 +0,0 @@
|
|||||||
# ============================================================================
|
|
||||||
# BlackRoad OS - Issue Triage Automation
|
|
||||||
# Copyright (c) 2025 BlackRoad OS, Inc. / Alexa Louise Amundson
|
|
||||||
# All Rights Reserved.
|
|
||||||
# ============================================================================
|
|
||||||
#
|
|
||||||
# Automatically triages and organizes new issues.
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
name: Issue Triage
|
|
||||||
|
|
||||||
on:
|
|
||||||
issues:
|
|
||||||
types: [opened, labeled]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
issues: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
triage:
|
|
||||||
name: Triage New Issues
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Add triage label to new issues
|
|
||||||
if: github.event.action == 'opened'
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const issue = context.payload.issue;
|
|
||||||
|
|
||||||
// Check if issue has any labels
|
|
||||||
if (issue.labels.length === 0) {
|
|
||||||
await github.rest.issues.addLabels({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: issue.number,
|
|
||||||
labels: ['triage']
|
|
||||||
});
|
|
||||||
console.log('Added triage label to issue #' + issue.number);
|
|
||||||
}
|
|
||||||
|
|
||||||
- name: Remove triage label when other labels added
|
|
||||||
if: github.event.action == 'labeled' && github.event.label.name != 'triage'
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const issue = context.payload.issue;
|
|
||||||
const hasTriageLabel = issue.labels.some(l => l.name === 'triage');
|
|
||||||
|
|
||||||
if (hasTriageLabel) {
|
|
||||||
try {
|
|
||||||
await github.rest.issues.removeLabel({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: issue.number,
|
|
||||||
name: 'triage'
|
|
||||||
});
|
|
||||||
console.log('Removed triage label from issue #' + issue.number);
|
|
||||||
} catch (e) {
|
|
||||||
console.log('Could not remove triage label:', e.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- name: Add priority based on title
|
|
||||||
if: github.event.action == 'opened'
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const issue = context.payload.issue;
|
|
||||||
const title = issue.title.toLowerCase();
|
|
||||||
const body = (issue.body || '').toLowerCase();
|
|
||||||
|
|
||||||
// Check for priority indicators
|
|
||||||
if (title.includes('critical') || title.includes('urgent') || title.includes('security')) {
|
|
||||||
await github.rest.issues.addLabels({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: issue.number,
|
|
||||||
labels: ['priority/high']
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for component mentions
|
|
||||||
const components = {
|
|
||||||
'quantum': ['quantum', 'ψ', 'brq-', 'pennylane'],
|
|
||||||
'operator': ['operator', 'ledger', 'promotion'],
|
|
||||||
'teacher': ['teacher', 'σ', 'lesson', 'quiz'],
|
|
||||||
'cli': ['br-', 'cli', 'terminal', 'command'],
|
|
||||||
'web': ['console', 'dashboard', 'ui', 'web'],
|
|
||||||
'agents': ['agent', 'lucidia', 'cece', 'roadie']
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const [label, keywords] of Object.entries(components)) {
|
|
||||||
if (keywords.some(k => title.includes(k) || body.includes(k))) {
|
|
||||||
await github.rest.issues.addLabels({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: issue.number,
|
|
||||||
labels: [label]
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
54
.github/workflows/labeler.yml
vendored
54
.github/workflows/labeler.yml
vendored
@@ -1,54 +0,0 @@
|
|||||||
# ============================================================================
|
|
||||||
# BlackRoad OS - Auto Labeler
|
|
||||||
# Copyright (c) 2025 BlackRoad OS, Inc. / Alexa Louise Amundson
|
|
||||||
# All Rights Reserved.
|
|
||||||
# ============================================================================
|
|
||||||
#
|
|
||||||
# Automatically labels PRs based on files changed.
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
name: Labeler
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
label:
|
|
||||||
name: Auto Label PR
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Label PR
|
|
||||||
uses: actions/labeler@v5
|
|
||||||
with:
|
|
||||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
|
||||||
configuration-path: .github/labeler.yml
|
|
||||||
|
|
||||||
size-label:
|
|
||||||
name: Size Label
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Label PR by size
|
|
||||||
uses: codelytv/pr-size-labeler@v1
|
|
||||||
with:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
xs_label: 'size/XS'
|
|
||||||
xs_max_size: 10
|
|
||||||
s_label: 'size/S'
|
|
||||||
s_max_size: 100
|
|
||||||
m_label: 'size/M'
|
|
||||||
m_max_size: 500
|
|
||||||
l_label: 'size/L'
|
|
||||||
l_max_size: 1000
|
|
||||||
xl_label: 'size/XL'
|
|
||||||
fail_if_xl: false
|
|
||||||
73
.github/workflows/mass-deploy.yml
vendored
73
.github/workflows/mass-deploy.yml
vendored
@@ -1,73 +0,0 @@
|
|||||||
name: Mass Deploy All Services
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
confirm:
|
|
||||||
description: 'Type "DEPLOY ALL" to confirm'
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
category:
|
|
||||||
description: 'Category to deploy (leave empty for all 238 services)'
|
|
||||||
required: false
|
|
||||||
type: choice
|
|
||||||
options:
|
|
||||||
- ''
|
|
||||||
- core
|
|
||||||
- agents
|
|
||||||
- api
|
|
||||||
- infrastructure
|
|
||||||
- security
|
|
||||||
- blockchain
|
|
||||||
- devops
|
|
||||||
- monitoring
|
|
||||||
- data
|
|
||||||
- ecosystem
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
validate:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: Validate Deployment Request
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Check confirmation
|
|
||||||
run: |
|
|
||||||
if [ "${{ github.event.inputs.confirm }}" != "DEPLOY ALL" ]; then
|
|
||||||
echo "❌ Confirmation failed. You must type 'DEPLOY ALL' to proceed."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo "✅ Confirmation verified"
|
|
||||||
|
|
||||||
deploy-all:
|
|
||||||
needs: validate
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: Mass Deployment
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Deploy all services
|
|
||||||
run: |
|
|
||||||
CATEGORY="${{ github.event.inputs.category }}"
|
|
||||||
if [ -z "$CATEGORY" ]; then
|
|
||||||
echo "🚀 Deploying ALL 238 services..."
|
|
||||||
curl -X POST ${{ secrets.ORCHESTRATOR_URL }}/deploy/all \
|
|
||||||
-H "Content-Type: application/json"
|
|
||||||
else
|
|
||||||
echo "🚀 Deploying $CATEGORY category..."
|
|
||||||
curl -X POST "${{ secrets.ORCHESTRATOR_URL }}/deploy/all?category=$CATEGORY" \
|
|
||||||
-H "Content-Type: application/json"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Monitor deployment
|
|
||||||
run: |
|
|
||||||
echo "⏳ Waiting for deployments to start..."
|
|
||||||
sleep 60
|
|
||||||
echo "📊 Checking deployment status..."
|
|
||||||
curl ${{ secrets.ORCHESTRATOR_URL }}/status | jq '.'
|
|
||||||
|
|
||||||
- name: Summary
|
|
||||||
run: |
|
|
||||||
echo "✅ Mass deployment initiated!"
|
|
||||||
echo "Monitor progress: ${{ secrets.ORCHESTRATOR_URL }}/dashboard"
|
|
||||||
echo ""
|
|
||||||
echo "This will take several minutes to complete."
|
|
||||||
echo "Services will be deployed sequentially to avoid rate limits."
|
|
||||||
107
.github/workflows/nightly.yml
vendored
107
.github/workflows/nightly.yml
vendored
@@ -1,107 +0,0 @@
|
|||||||
# ============================================================================
|
|
||||||
# BlackRoad OS - Nightly Health Check
|
|
||||||
# Copyright (c) 2025 BlackRoad OS, Inc. / Alexa Louise Amundson
|
|
||||||
# All Rights Reserved.
|
|
||||||
# ============================================================================
|
|
||||||
#
|
|
||||||
# Scheduled workflow that runs nightly to check system health.
|
|
||||||
# Validates all Python/Shell scripts, checks for stale branches, etc.
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
name: Nightly
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 6 * * *' # 6 AM UTC daily
|
|
||||||
workflow_dispatch: # Manual trigger
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
health-check:
|
|
||||||
name: Health Check
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Set up Python
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: '3.11'
|
|
||||||
|
|
||||||
- name: Validate all Python files
|
|
||||||
id: python-check
|
|
||||||
run: |
|
|
||||||
echo "## Python Validation" >> $GITHUB_STEP_SUMMARY
|
|
||||||
ERRORS=0
|
|
||||||
TOTAL=0
|
|
||||||
|
|
||||||
for f in $(find . -name "*.py" -type f); do
|
|
||||||
TOTAL=$((TOTAL + 1))
|
|
||||||
if python3 -m py_compile "$f" 2>/dev/null; then
|
|
||||||
echo "✓ $f"
|
|
||||||
else
|
|
||||||
echo "✗ $f" >&2
|
|
||||||
ERRORS=$((ERRORS + 1))
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "- Total Python files: $TOTAL" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "- Errors: $ERRORS" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
if [ $ERRORS -gt 0 ]; then
|
|
||||||
echo "::warning::$ERRORS Python files have syntax errors"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Check for stale branches
|
|
||||||
run: |
|
|
||||||
echo "## Branch Analysis" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
# List branches merged into main
|
|
||||||
echo "### Merged branches (candidates for cleanup)" >> $GITHUB_STEP_SUMMARY
|
|
||||||
git branch -r --merged origin/main 2>/dev/null | grep -v main | head -10 >> $GITHUB_STEP_SUMMARY || echo "None" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
# List branches older than 30 days
|
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "### Branches with no recent activity (30+ days)" >> $GITHUB_STEP_SUMMARY
|
|
||||||
CUTOFF=$(date -d '30 days ago' +%s 2>/dev/null || date -v-30d +%s)
|
|
||||||
git for-each-ref --sort=-committerdate refs/remotes/ --format='%(refname:short) %(committerdate:unix)' 2>/dev/null | \
|
|
||||||
while read branch date; do
|
|
||||||
if [ "$date" -lt "$CUTOFF" ] 2>/dev/null; then
|
|
||||||
echo "- $branch"
|
|
||||||
fi
|
|
||||||
done | head -10 >> $GITHUB_STEP_SUMMARY || echo "None" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
- name: Count files by type
|
|
||||||
run: |
|
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "## Repository Statistics" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "| Type | Count |" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "|------|-------|" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "| Python (.py) | $(find . -name '*.py' | wc -l) |" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "| Shell (.sh) | $(find . -name '*.sh' | wc -l) |" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "| YAML (.yaml/.yml) | $(find . -name '*.yaml' -o -name '*.yml' | wc -l) |" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "| Markdown (.md) | $(find . -name '*.md' | wc -l) |" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "| HTML (.html) | $(find . -name '*.html' | wc -l) |" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "| Total files | $(find . -type f | wc -l) |" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
- name: Check for TODO/FIXME comments
|
|
||||||
run: |
|
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "## TODO/FIXME Items" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
TODO_COUNT=$(grep -rn "TODO\|FIXME\|XXX\|HACK" --include="*.py" --include="*.sh" . 2>/dev/null | wc -l)
|
|
||||||
echo "Found $TODO_COUNT TODO/FIXME comments" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
if [ "$TODO_COUNT" -gt 0 ]; then
|
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "<details><summary>Show items</summary>" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
||||||
grep -rn "TODO\|FIXME\|XXX\|HACK" --include="*.py" --include="*.sh" . 2>/dev/null | head -20 >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "</details>" >> $GITHUB_STEP_SUMMARY
|
|
||||||
fi
|
|
||||||
56
.github/workflows/node-deploy.yml
vendored
56
.github/workflows/node-deploy.yml
vendored
@@ -1,56 +0,0 @@
|
|||||||
name: Node.js Build and Deploy
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main, master]
|
|
||||||
pull_request:
|
|
||||||
branches: [main, master]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-and-test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: ${{ hashFiles('package.json') != '' }}
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
node-version: [18.x, 20.x]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version: ${{ matrix.node-version }}
|
|
||||||
cache: 'npm'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: npm ci
|
|
||||||
|
|
||||||
- name: Lint
|
|
||||||
run: npm run lint --if-present
|
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: npm run build --if-present
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
run: npm test --if-present
|
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
deploy-railway:
|
|
||||||
needs: build-and-test
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master'
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Deploy to Railway
|
|
||||||
run: |
|
|
||||||
npm install -g @railway/cli
|
|
||||||
railway up
|
|
||||||
env:
|
|
||||||
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
|
|
||||||
192
.github/workflows/pr-checks.yml
vendored
192
.github/workflows/pr-checks.yml
vendored
@@ -1,192 +0,0 @@
|
|||||||
# ============================================================================
|
|
||||||
# BlackRoad OS - Pull Request Checks
|
|
||||||
# Copyright (c) 2025 BlackRoad OS, Inc. / Alexa Louise Amundson
|
|
||||||
# All Rights Reserved.
|
|
||||||
# ============================================================================
|
|
||||||
#
|
|
||||||
# Additional checks for pull requests.
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
name: PR Checks
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [opened, edited, synchronize, reopened]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
|
||||||
# Validate PR Title (Conventional Commits)
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
|
||||||
pr-title:
|
|
||||||
name: Validate PR Title
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Check PR title format
|
|
||||||
uses: amannn/action-semantic-pull-request@v5
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
types: |
|
|
||||||
feat
|
|
||||||
fix
|
|
||||||
docs
|
|
||||||
style
|
|
||||||
refactor
|
|
||||||
perf
|
|
||||||
test
|
|
||||||
build
|
|
||||||
ci
|
|
||||||
chore
|
|
||||||
revert
|
|
||||||
scopes: |
|
|
||||||
operator
|
|
||||||
quantum
|
|
||||||
teacher
|
|
||||||
cli
|
|
||||||
web
|
|
||||||
agents
|
|
||||||
infra
|
|
||||||
deps
|
|
||||||
requireScope: false
|
|
||||||
subjectPattern: ^[A-Z].+$
|
|
||||||
subjectPatternError: |
|
|
||||||
The PR title "{subject}" must start with an uppercase letter.
|
|
||||||
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
|
||||||
# Check for Breaking Changes
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
|
||||||
breaking-changes:
|
|
||||||
name: Breaking Change Check
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Check for breaking changes
|
|
||||||
run: |
|
|
||||||
# Check if PR title or body mentions breaking changes
|
|
||||||
TITLE="${{ github.event.pull_request.title }}"
|
|
||||||
BODY="${{ github.event.pull_request.body }}"
|
|
||||||
|
|
||||||
if echo "$TITLE" | grep -qi "breaking\|BREAKING"; then
|
|
||||||
echo "::warning::This PR indicates breaking changes in the title"
|
|
||||||
echo "## Breaking Change Detected" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "The PR title mentions breaking changes. Ensure:" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "- [ ] CHANGELOG is updated" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "- [ ] Migration guide is provided" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "- [ ] Version bump is major" >> $GITHUB_STEP_SUMMARY
|
|
||||||
fi
|
|
||||||
|
|
||||||
if echo "$BODY" | grep -qi "breaking change"; then
|
|
||||||
echo "::warning::This PR body mentions breaking changes"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
|
||||||
# Check File Sizes
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
|
||||||
file-size:
|
|
||||||
name: Check File Sizes
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Check for large files
|
|
||||||
run: |
|
|
||||||
echo "## Large Files Check" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
# Find files larger than 1MB
|
|
||||||
LARGE_FILES=$(find . -type f -size +1M -not -path './.git/*' 2>/dev/null || true)
|
|
||||||
|
|
||||||
if [ -n "$LARGE_FILES" ]; then
|
|
||||||
echo "::warning::Large files detected (>1MB)"
|
|
||||||
echo "### Large files found:" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "$LARGE_FILES" | while read f; do
|
|
||||||
SIZE=$(du -h "$f" | cut -f1)
|
|
||||||
echo "$f ($SIZE)"
|
|
||||||
done >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
||||||
else
|
|
||||||
echo "No large files detected" >> $GITHUB_STEP_SUMMARY
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
|
||||||
# License Header Check
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
|
||||||
license-check:
|
|
||||||
name: License Header Check
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Check for license headers
|
|
||||||
run: |
|
|
||||||
echo "## License Header Check" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
MISSING=0
|
|
||||||
|
|
||||||
# Check Python files
|
|
||||||
for f in $(find . -name "*.py" -type f -not -path './.git/*' | head -50); do
|
|
||||||
if ! head -10 "$f" | grep -q "Copyright"; then
|
|
||||||
echo "Missing header: $f"
|
|
||||||
MISSING=$((MISSING + 1))
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# Check Shell scripts
|
|
||||||
for f in $(find . -name "*.sh" -type f -not -path './.git/*' | head -50); do
|
|
||||||
if ! head -10 "$f" | grep -q "Copyright"; then
|
|
||||||
echo "Missing header: $f"
|
|
||||||
MISSING=$((MISSING + 1))
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ $MISSING -gt 0 ]; then
|
|
||||||
echo "::notice::$MISSING files missing copyright headers"
|
|
||||||
echo "$MISSING files missing copyright headers" >> $GITHUB_STEP_SUMMARY
|
|
||||||
else
|
|
||||||
echo "All checked files have copyright headers" >> $GITHUB_STEP_SUMMARY
|
|
||||||
fi
|
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
|
||||||
# Commit Message Check
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
|
||||||
commit-check:
|
|
||||||
name: Commit Message Check
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Check commit messages
|
|
||||||
run: |
|
|
||||||
echo "## Commit Message Analysis" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
# Get commits in this PR
|
|
||||||
BASE="${{ github.event.pull_request.base.sha }}"
|
|
||||||
HEAD="${{ github.event.pull_request.head.sha }}"
|
|
||||||
|
|
||||||
COMMITS=$(git log --oneline $BASE..$HEAD 2>/dev/null || git log --oneline -10)
|
|
||||||
|
|
||||||
echo "### Commits in this PR:" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "$COMMITS" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
# Check for WIP commits
|
|
||||||
if echo "$COMMITS" | grep -qi "wip\|work in progress\|fixup\|squash"; then
|
|
||||||
echo "::warning::PR contains WIP/fixup commits - consider squashing before merge"
|
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "**Warning:** Contains WIP/fixup commits" >> $GITHUB_STEP_SUMMARY
|
|
||||||
fi
|
|
||||||
66
.github/workflows/python-tests.yml
vendored
66
.github/workflows/python-tests.yml
vendored
@@ -1,66 +0,0 @@
|
|||||||
name: Python Tests
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main, master, develop]
|
|
||||||
pull_request:
|
|
||||||
branches: [main, master, develop]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
python-version: ["3.11", "3.12"]
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: ${{ matrix.python-version }}
|
|
||||||
|
|
||||||
- name: Cache dependencies
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.cache/pip
|
|
||||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements*.txt') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pip-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
python -m pip install --upgrade pip
|
|
||||||
|
|
||||||
# Install all requirements files if they exist
|
|
||||||
for req in requirements.txt requirements-*.txt; do
|
|
||||||
if [ -f "$req" ]; then
|
|
||||||
echo "Installing $req..."
|
|
||||||
pip install -r "$req"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: Lint with flake8
|
|
||||||
run: |
|
|
||||||
pip install flake8
|
|
||||||
# Stop the build if there are Python syntax errors or undefined names
|
|
||||||
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
|
|
||||||
# Exit-zero treats all errors as warnings
|
|
||||||
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
|
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
- name: Test with pytest
|
|
||||||
if: ${{ hashFiles('pytest.ini') != '' || hashFiles('tests/') != '' }}
|
|
||||||
run: |
|
|
||||||
pip install pytest pytest-cov pytest-asyncio
|
|
||||||
pytest --cov=. --cov-report=xml --cov-report=term
|
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
- name: Upload coverage to Codecov
|
|
||||||
if: ${{ hashFiles('pytest.ini') != '' || hashFiles('tests/') != '' }}
|
|
||||||
uses: codecov/codecov-action@v3
|
|
||||||
with:
|
|
||||||
file: ./coverage.xml
|
|
||||||
fail_ci_if_error: false
|
|
||||||
47
.github/workflows/railway-deploy.yml
vendored
47
.github/workflows/railway-deploy.yml
vendored
@@ -1,47 +0,0 @@
|
|||||||
name: Deploy to Railway
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main, master, production]
|
|
||||||
pull_request:
|
|
||||||
branches: [main, master, production]
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
env:
|
|
||||||
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
deploy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install Railway CLI
|
|
||||||
run: npm install -g @railway/cli
|
|
||||||
|
|
||||||
- name: Deploy to Railway
|
|
||||||
run: |
|
|
||||||
if [ -f railway.toml ] || [ -f railway.json ]; then
|
|
||||||
echo "✅ Railway config found, deploying..."
|
|
||||||
railway up
|
|
||||||
else
|
|
||||||
echo "⚠️ No Railway config found, skipping deployment"
|
|
||||||
fi
|
|
||||||
env:
|
|
||||||
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
|
|
||||||
|
|
||||||
- name: Health Check
|
|
||||||
if: success()
|
|
||||||
run: |
|
|
||||||
echo "Waiting for deployment to be ready..."
|
|
||||||
sleep 30
|
|
||||||
|
|
||||||
# Get deployment URL from Railway
|
|
||||||
DEPLOYMENT_URL=$(railway status --json | jq -r '.deployments[0].url' || echo "")
|
|
||||||
|
|
||||||
if [ -n "$DEPLOYMENT_URL" ]; then
|
|
||||||
echo "Testing health endpoint at: $DEPLOYMENT_URL/health"
|
|
||||||
curl -f "$DEPLOYMENT_URL/health" || echo "⚠️ Health check not available"
|
|
||||||
fi
|
|
||||||
113
.github/workflows/release-notes.yml
vendored
113
.github/workflows/release-notes.yml
vendored
@@ -1,113 +0,0 @@
|
|||||||
# ============================================================================
|
|
||||||
# BlackRoad OS - Automated Release Notes
|
|
||||||
# Copyright (c) 2025 BlackRoad OS, Inc. / Alexa Louise Amundson
|
|
||||||
# All Rights Reserved.
|
|
||||||
# ============================================================================
|
|
||||||
#
|
|
||||||
# Generates release notes from merged PRs and closed issues.
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
name: Release Notes
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
version:
|
|
||||||
description: 'Version for release notes'
|
|
||||||
required: true
|
|
||||||
default: 'v0.0.0'
|
|
||||||
since:
|
|
||||||
description: 'Since date (YYYY-MM-DD) or tag'
|
|
||||||
required: false
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
generate:
|
|
||||||
name: Generate Release Notes
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Generate release notes
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
id: notes
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const version = '${{ github.event.inputs.version }}';
|
|
||||||
const since = '${{ github.event.inputs.since }}' || null;
|
|
||||||
|
|
||||||
// Get merged PRs
|
|
||||||
const prs = await github.rest.pulls.list({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
state: 'closed',
|
|
||||||
sort: 'updated',
|
|
||||||
direction: 'desc',
|
|
||||||
per_page: 100
|
|
||||||
});
|
|
||||||
|
|
||||||
const mergedPRs = prs.data.filter(pr => pr.merged_at);
|
|
||||||
|
|
||||||
// Categorize PRs
|
|
||||||
const categories = {
|
|
||||||
'Features': [],
|
|
||||||
'Bug Fixes': [],
|
|
||||||
'Documentation': [],
|
|
||||||
'Infrastructure': [],
|
|
||||||
'Other': []
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const pr of mergedPRs) {
|
|
||||||
const labels = pr.labels.map(l => l.name);
|
|
||||||
const title = `${pr.title} (#${pr.number}) @${pr.user.login}`;
|
|
||||||
|
|
||||||
if (labels.includes('enhancement') || pr.title.startsWith('feat')) {
|
|
||||||
categories['Features'].push(title);
|
|
||||||
} else if (labels.includes('bug') || pr.title.startsWith('fix')) {
|
|
||||||
categories['Bug Fixes'].push(title);
|
|
||||||
} else if (labels.includes('documentation') || pr.title.startsWith('docs')) {
|
|
||||||
categories['Documentation'].push(title);
|
|
||||||
} else if (labels.includes('infrastructure') || labels.includes('ci')) {
|
|
||||||
categories['Infrastructure'].push(title);
|
|
||||||
} else {
|
|
||||||
categories['Other'].push(title);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build release notes
|
|
||||||
let notes = `# Release ${version}\n\n`;
|
|
||||||
notes += `Released: ${new Date().toISOString().split('T')[0]}\n\n`;
|
|
||||||
|
|
||||||
for (const [category, items] of Object.entries(categories)) {
|
|
||||||
if (items.length > 0) {
|
|
||||||
notes += `## ${category}\n\n`;
|
|
||||||
for (const item of items.slice(0, 10)) {
|
|
||||||
notes += `- ${item}\n`;
|
|
||||||
}
|
|
||||||
notes += '\n';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
notes += `---\n\n`;
|
|
||||||
notes += `*Generated by BlackRoad OS Release Notes workflow*\n`;
|
|
||||||
|
|
||||||
console.log(notes);
|
|
||||||
core.setOutput('notes', notes);
|
|
||||||
|
|
||||||
- name: Create release notes file
|
|
||||||
run: |
|
|
||||||
mkdir -p releases
|
|
||||||
cat > releases/RELEASE-${{ github.event.inputs.version }}.md << 'EOF'
|
|
||||||
${{ steps.notes.outputs.notes }}
|
|
||||||
EOF
|
|
||||||
|
|
||||||
- name: Upload release notes
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: release-notes-${{ github.event.inputs.version }}
|
|
||||||
path: releases/RELEASE-${{ github.event.inputs.version }}.md
|
|
||||||
104
.github/workflows/release.yml
vendored
104
.github/workflows/release.yml
vendored
@@ -1,104 +0,0 @@
|
|||||||
# ============================================================================
|
|
||||||
# BlackRoad OS - Release Pipeline
|
|
||||||
# Copyright (c) 2025 BlackRoad OS, Inc. / Alexa Louise Amundson
|
|
||||||
# All Rights Reserved.
|
|
||||||
# ============================================================================
|
|
||||||
#
|
|
||||||
# Automated release workflow triggered by version tags.
|
|
||||||
# Creates GitHub releases with changelogs and artifacts.
|
|
||||||
#
|
|
||||||
# Trigger: Push tags matching v*.*.* (e.g., v0.2.0, v1.0.0-beta.1)
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
name: Release
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- 'v*.*.*'
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
release:
|
|
||||||
name: Create Release
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0 # Full history for changelog
|
|
||||||
|
|
||||||
- name: Get version from tag
|
|
||||||
id: version
|
|
||||||
run: |
|
|
||||||
VERSION=${GITHUB_REF#refs/tags/v}
|
|
||||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
||||||
echo "tag=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Generate changelog
|
|
||||||
id: changelog
|
|
||||||
run: |
|
|
||||||
# Get the previous tag
|
|
||||||
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
|
|
||||||
|
|
||||||
if [ -n "$PREV_TAG" ]; then
|
|
||||||
echo "Generating changelog from $PREV_TAG to ${{ steps.version.outputs.tag }}"
|
|
||||||
CHANGES=$(git log --pretty=format:"- %s (%h)" $PREV_TAG..HEAD)
|
|
||||||
else
|
|
||||||
echo "First release - including all commits"
|
|
||||||
CHANGES=$(git log --pretty=format:"- %s (%h)" HEAD~20..HEAD)
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Write to file for multi-line output
|
|
||||||
echo "$CHANGES" > changelog.txt
|
|
||||||
echo "Generated changelog with $(echo "$CHANGES" | wc -l) entries"
|
|
||||||
|
|
||||||
- name: Create release archive
|
|
||||||
run: |
|
|
||||||
# Create a clean archive of the release
|
|
||||||
mkdir -p dist
|
|
||||||
|
|
||||||
# Archive Python files
|
|
||||||
tar -czvf dist/blackroad-os-${{ steps.version.outputs.version }}-python.tar.gz \
|
|
||||||
--exclude='*.pyc' \
|
|
||||||
--exclude='__pycache__' \
|
|
||||||
--exclude='.git' \
|
|
||||||
*.py 2>/dev/null || echo "No Python files in root"
|
|
||||||
|
|
||||||
# Archive shell scripts
|
|
||||||
tar -czvf dist/blackroad-os-${{ steps.version.outputs.version }}-scripts.tar.gz \
|
|
||||||
--exclude='.git' \
|
|
||||||
*.sh br-* 2>/dev/null || echo "No shell scripts in root"
|
|
||||||
|
|
||||||
# Archive config files
|
|
||||||
if [ -d "config" ]; then
|
|
||||||
tar -czvf dist/blackroad-os-${{ steps.version.outputs.version }}-config.tar.gz config/
|
|
||||||
fi
|
|
||||||
|
|
||||||
ls -la dist/
|
|
||||||
|
|
||||||
- name: Create GitHub Release
|
|
||||||
uses: softprops/action-gh-release@v1
|
|
||||||
with:
|
|
||||||
name: BlackRoad OS v${{ steps.version.outputs.version }}
|
|
||||||
body_path: changelog.txt
|
|
||||||
draft: false
|
|
||||||
prerelease: ${{ contains(steps.version.outputs.version, 'alpha') || contains(steps.version.outputs.version, 'beta') || contains(steps.version.outputs.version, 'rc') }}
|
|
||||||
files: |
|
|
||||||
dist/*.tar.gz
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Summary
|
|
||||||
run: |
|
|
||||||
echo "## Release Summary" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "**Version:** v${{ steps.version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "**Tag:** ${{ steps.version.outputs.tag }}" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "### Artifacts" >> $GITHUB_STEP_SUMMARY
|
|
||||||
ls dist/*.tar.gz 2>/dev/null | while read f; do
|
|
||||||
echo "- $(basename $f)" >> $GITHUB_STEP_SUMMARY
|
|
||||||
done
|
|
||||||
121
.github/workflows/scheduled-reports.yml
vendored
121
.github/workflows/scheduled-reports.yml
vendored
@@ -1,121 +0,0 @@
|
|||||||
# ============================================================================
|
|
||||||
# BlackRoad OS - Scheduled Reports
|
|
||||||
# Copyright (c) 2025 BlackRoad OS, Inc. / Alexa Louise Amundson
|
|
||||||
# All Rights Reserved.
|
|
||||||
# ============================================================================
|
|
||||||
#
|
|
||||||
# Generates weekly reports on repository activity.
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
name: Weekly Report
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 9 * * 1' # Monday 9 AM UTC
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
issues: write
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
report:
|
|
||||||
name: Generate Weekly Report
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Generate report
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const oneWeekAgo = new Date();
|
|
||||||
oneWeekAgo.setDate(oneWeekAgo.getDate() - 7);
|
|
||||||
const since = oneWeekAgo.toISOString();
|
|
||||||
|
|
||||||
// Get commits
|
|
||||||
const commits = await github.rest.repos.listCommits({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
since: since,
|
|
||||||
per_page: 100
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get closed issues
|
|
||||||
const issues = await github.rest.issues.listForRepo({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
state: 'closed',
|
|
||||||
since: since,
|
|
||||||
per_page: 100
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get merged PRs
|
|
||||||
const prs = await github.rest.pulls.list({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
state: 'closed',
|
|
||||||
sort: 'updated',
|
|
||||||
direction: 'desc',
|
|
||||||
per_page: 50
|
|
||||||
});
|
|
||||||
|
|
||||||
const mergedPRs = prs.data.filter(pr =>
|
|
||||||
pr.merged_at && new Date(pr.merged_at) > oneWeekAgo
|
|
||||||
);
|
|
||||||
|
|
||||||
// Get open issues
|
|
||||||
const openIssues = await github.rest.issues.listForRepo({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
state: 'open',
|
|
||||||
per_page: 100
|
|
||||||
});
|
|
||||||
|
|
||||||
// Build report
|
|
||||||
let report = `# Weekly Activity Report\n\n`;
|
|
||||||
report += `**Period:** ${oneWeekAgo.toISOString().split('T')[0]} to ${new Date().toISOString().split('T')[0]}\n\n`;
|
|
||||||
|
|
||||||
report += `## Summary\n\n`;
|
|
||||||
report += `| Metric | Count |\n`;
|
|
||||||
report += `|--------|-------|\n`;
|
|
||||||
report += `| Commits | ${commits.data.length} |\n`;
|
|
||||||
report += `| Merged PRs | ${mergedPRs.length} |\n`;
|
|
||||||
report += `| Closed Issues | ${issues.data.filter(i => !i.pull_request).length} |\n`;
|
|
||||||
report += `| Open Issues | ${openIssues.data.filter(i => !i.pull_request).length} |\n\n`;
|
|
||||||
|
|
||||||
if (mergedPRs.length > 0) {
|
|
||||||
report += `## Merged Pull Requests\n\n`;
|
|
||||||
for (const pr of mergedPRs.slice(0, 10)) {
|
|
||||||
report += `- #${pr.number} ${pr.title} (@${pr.user.login})\n`;
|
|
||||||
}
|
|
||||||
report += '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (commits.data.length > 0) {
|
|
||||||
report += `## Top Contributors\n\n`;
|
|
||||||
const contributors = {};
|
|
||||||
for (const commit of commits.data) {
|
|
||||||
const author = commit.author?.login || commit.commit.author.name;
|
|
||||||
contributors[author] = (contributors[author] || 0) + 1;
|
|
||||||
}
|
|
||||||
const sorted = Object.entries(contributors).sort((a, b) => b[1] - a[1]);
|
|
||||||
for (const [name, count] of sorted.slice(0, 5)) {
|
|
||||||
report += `- @${name}: ${count} commits\n`;
|
|
||||||
}
|
|
||||||
report += '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create issue with report
|
|
||||||
await github.rest.issues.create({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
title: `Weekly Report: ${new Date().toISOString().split('T')[0]}`,
|
|
||||||
body: report,
|
|
||||||
labels: ['report', 'automated']
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log('Weekly report created');
|
|
||||||
199
.github/workflows/security.yml
vendored
199
.github/workflows/security.yml
vendored
@@ -1,199 +0,0 @@
|
|||||||
# ============================================================================
|
|
||||||
# BlackRoad OS - Security Scanning Pipeline
|
|
||||||
# Copyright (c) 2025 BlackRoad OS, Inc. / Alexa Louise Amundson
|
|
||||||
# All Rights Reserved.
|
|
||||||
# ============================================================================
|
|
||||||
#
|
|
||||||
# Comprehensive security scanning workflow.
|
|
||||||
# Runs on push, PR, and weekly schedule.
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
name: Security
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main, master]
|
|
||||||
pull_request:
|
|
||||||
branches: [main, master]
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * 0' # Weekly on Sunday midnight
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
security-events: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
|
||||||
# CodeQL Analysis
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
|
||||||
codeql:
|
|
||||||
name: CodeQL Analysis
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
actions: read
|
|
||||||
contents: read
|
|
||||||
security-events: write
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
language: ['python']
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
|
||||||
uses: github/codeql-action/init@v3
|
|
||||||
with:
|
|
||||||
languages: ${{ matrix.language }}
|
|
||||||
queries: security-and-quality
|
|
||||||
|
|
||||||
- name: Autobuild
|
|
||||||
uses: github/codeql-action/autobuild@v3
|
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
|
||||||
uses: github/codeql-action/analyze@v3
|
|
||||||
with:
|
|
||||||
category: "/language:${{matrix.language}}"
|
|
||||||
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
|
||||||
# Dependency Vulnerability Scan
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
|
||||||
dependency-scan:
|
|
||||||
name: Dependency Scan
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Python
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: '3.11'
|
|
||||||
|
|
||||||
- name: Install safety
|
|
||||||
run: pip install safety pip-audit
|
|
||||||
|
|
||||||
- name: Check for vulnerable dependencies
|
|
||||||
run: |
|
|
||||||
echo "## Dependency Vulnerability Scan" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
# Check requirements.txt if exists
|
|
||||||
if [ -f requirements.txt ]; then
|
|
||||||
echo "### requirements.txt" >> $GITHUB_STEP_SUMMARY
|
|
||||||
pip-audit -r requirements.txt --format markdown >> $GITHUB_STEP_SUMMARY 2>/dev/null || echo "No issues found" >> $GITHUB_STEP_SUMMARY
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check pyproject.toml if exists
|
|
||||||
if [ -f pyproject.toml ]; then
|
|
||||||
echo "### pyproject.toml" >> $GITHUB_STEP_SUMMARY
|
|
||||||
pip-audit --format markdown >> $GITHUB_STEP_SUMMARY 2>/dev/null || echo "No issues found" >> $GITHUB_STEP_SUMMARY
|
|
||||||
fi
|
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
|
||||||
# Secret Scanning
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
|
||||||
secret-scan:
|
|
||||||
name: Secret Scan
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Install truffleHog
|
|
||||||
run: pip install trufflehog
|
|
||||||
|
|
||||||
- name: Scan for secrets
|
|
||||||
run: |
|
|
||||||
echo "## Secret Scan Results" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
# Scan with truffleHog
|
|
||||||
trufflehog filesystem . --only-verified --json 2>/dev/null | head -20 > secrets.json || true
|
|
||||||
|
|
||||||
if [ -s secrets.json ]; then
|
|
||||||
echo "::warning::Potential secrets detected. Review secrets.json"
|
|
||||||
echo "Potential secrets found - review required" >> $GITHUB_STEP_SUMMARY
|
|
||||||
else
|
|
||||||
echo "No verified secrets detected" >> $GITHUB_STEP_SUMMARY
|
|
||||||
fi
|
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
- name: Check for common secret patterns
|
|
||||||
run: |
|
|
||||||
echo "### Pattern Checks" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
# Check for AWS keys
|
|
||||||
if grep -rE "AKIA[0-9A-Z]{16}" --include="*.py" --include="*.sh" --include="*.yaml" . 2>/dev/null; then
|
|
||||||
echo "::warning::Potential AWS access key found"
|
|
||||||
echo "- Potential AWS key pattern detected" >> $GITHUB_STEP_SUMMARY
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check for private keys
|
|
||||||
if grep -rE "BEGIN (RSA |DSA |EC |OPENSSH )?PRIVATE KEY" --include="*.py" --include="*.sh" --include="*.pem" . 2>/dev/null; then
|
|
||||||
echo "::warning::Private key found in repository"
|
|
||||||
echo "- Private key detected" >> $GITHUB_STEP_SUMMARY
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check for hardcoded passwords
|
|
||||||
if grep -rEi "password\s*=\s*['\"][^'\"]{8,}['\"]" --include="*.py" --include="*.sh" . 2>/dev/null; then
|
|
||||||
echo "::warning::Potential hardcoded password found"
|
|
||||||
echo "- Potential hardcoded password detected" >> $GITHUB_STEP_SUMMARY
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Pattern scan complete" >> $GITHUB_STEP_SUMMARY
|
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
|
||||||
# SAST (Static Application Security Testing)
|
|
||||||
# ─────────────────────────────────────────────────────────────────────────
|
|
||||||
sast:
|
|
||||||
name: SAST Scan
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Python
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: '3.11'
|
|
||||||
|
|
||||||
- name: Install Bandit
|
|
||||||
run: pip install bandit
|
|
||||||
|
|
||||||
- name: Run Bandit security scan
|
|
||||||
run: |
|
|
||||||
echo "## Bandit Security Scan" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
bandit -r . -f json -o bandit-report.json --exclude './.git,./node_modules,./.venv' || true
|
|
||||||
|
|
||||||
# Convert to markdown summary
|
|
||||||
if [ -f bandit-report.json ]; then
|
|
||||||
ISSUES=$(cat bandit-report.json | python3 -c "import json,sys; d=json.load(sys.stdin); print(len(d.get('results', [])))")
|
|
||||||
echo "Found $ISSUES security issues" >> $GITHUB_STEP_SUMMARY
|
|
||||||
|
|
||||||
if [ "$ISSUES" -gt 0 ]; then
|
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "### Top Issues" >> $GITHUB_STEP_SUMMARY
|
|
||||||
cat bandit-report.json | python3 -c "
|
|
||||||
import json, sys
|
|
||||||
d = json.load(sys.stdin)
|
|
||||||
for r in d.get('results', [])[:10]:
|
|
||||||
print(f\"- **{r['issue_severity']}**: {r['issue_text']} ({r['filename']}:{r['line_number']})\")
|
|
||||||
" >> $GITHUB_STEP_SUMMARY
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
- name: Upload Bandit report
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
if: always()
|
|
||||||
with:
|
|
||||||
name: bandit-report
|
|
||||||
path: bandit-report.json
|
|
||||||
retention-days: 30
|
|
||||||
69
.github/workflows/stale-cleanup.yml
vendored
69
.github/workflows/stale-cleanup.yml
vendored
@@ -1,69 +0,0 @@
|
|||||||
name: Stale Issue Cleanup
|
|
||||||
|
|
||||||
# Automatically flags and closes stale issues
|
|
||||||
# Keeps your board clean without manual gardening
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
# Run daily at midnight UTC
|
|
||||||
- cron: '0 0 * * *'
|
|
||||||
workflow_dispatch:
|
|
||||||
# Allow manual trigger
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
issues: write
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
stale:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Mark and close stale issues
|
|
||||||
uses: actions/stale@v9
|
|
||||||
with:
|
|
||||||
# Issues
|
|
||||||
stale-issue-message: |
|
|
||||||
⏰ **This issue has been inactive for 14 days.**
|
|
||||||
|
|
||||||
If this is still needed, please comment or update the issue.
|
|
||||||
Otherwise, it will be closed in 7 days.
|
|
||||||
|
|
||||||
To keep this open: add a comment or remove the `stale` label.
|
|
||||||
close-issue-message: |
|
|
||||||
🗂️ **Closed due to inactivity.**
|
|
||||||
|
|
||||||
If this is still needed, reopen the issue or create a new one.
|
|
||||||
stale-issue-label: 'stale'
|
|
||||||
days-before-issue-stale: 14
|
|
||||||
days-before-issue-close: 7
|
|
||||||
|
|
||||||
# PRs - more aggressive since they should flow fast
|
|
||||||
stale-pr-message: |
|
|
||||||
⏰ **This PR has been inactive for 7 days.**
|
|
||||||
|
|
||||||
If CI is failing, fix it. If it's blocked, add the `blocked` label.
|
|
||||||
Otherwise, this PR will be closed in 3 days.
|
|
||||||
close-pr-message: |
|
|
||||||
🗂️ **Closed due to inactivity.**
|
|
||||||
|
|
||||||
If this work is still needed, create a new PR.
|
|
||||||
stale-pr-label: 'stale'
|
|
||||||
days-before-pr-stale: 7
|
|
||||||
days-before-pr-close: 3
|
|
||||||
|
|
||||||
# Exemptions
|
|
||||||
exempt-issue-labels: 'pinned,security,blocked,p0-now'
|
|
||||||
exempt-pr-labels: 'pinned,security,blocked'
|
|
||||||
|
|
||||||
# Don't mark issues that have recent commits on linked branches
|
|
||||||
exempt-all-pr-milestones: true
|
|
||||||
|
|
||||||
# Operations per run (GitHub API limits)
|
|
||||||
operations-per-run: 100
|
|
||||||
|
|
||||||
- name: Report cleanup stats
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
console.log('Stale cleanup completed');
|
|
||||||
console.log('Check the Actions log for details on marked/closed items');
|
|
||||||
61
.github/workflows/stale.yml
vendored
61
.github/workflows/stale.yml
vendored
@@ -1,61 +0,0 @@
|
|||||||
# ============================================================================
|
|
||||||
# BlackRoad OS - Stale Issue/PR Management
|
|
||||||
# Copyright (c) 2025 BlackRoad OS, Inc. / Alexa Louise Amundson
|
|
||||||
# All Rights Reserved.
|
|
||||||
# ============================================================================
|
|
||||||
#
|
|
||||||
# Automatically marks and closes stale issues and PRs.
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
name: Stale
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * *' # Daily at midnight
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
issues: write
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
stale:
|
|
||||||
name: Mark Stale Issues and PRs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/stale@v9
|
|
||||||
with:
|
|
||||||
# Issue configuration
|
|
||||||
stale-issue-message: |
|
|
||||||
This issue has been automatically marked as stale because it has not had recent activity.
|
|
||||||
It will be closed in 14 days if no further activity occurs.
|
|
||||||
|
|
||||||
If this issue is still relevant:
|
|
||||||
- Add a comment explaining the current status
|
|
||||||
- Remove the `stale` label
|
|
||||||
|
|
||||||
Thank you for your contributions to BlackRoad OS!
|
|
||||||
stale-issue-label: 'stale'
|
|
||||||
days-before-issue-stale: 60
|
|
||||||
days-before-issue-close: 14
|
|
||||||
exempt-issue-labels: 'pinned,security,critical,in-progress'
|
|
||||||
|
|
||||||
# PR configuration
|
|
||||||
stale-pr-message: |
|
|
||||||
This pull request has been automatically marked as stale because it has not had recent activity.
|
|
||||||
It will be closed in 7 days if no further activity occurs.
|
|
||||||
|
|
||||||
If this PR is still needed:
|
|
||||||
- Rebase on the latest main branch
|
|
||||||
- Address any review feedback
|
|
||||||
- Add a comment with status update
|
|
||||||
|
|
||||||
Thank you for your contributions!
|
|
||||||
stale-pr-label: 'stale'
|
|
||||||
days-before-pr-stale: 30
|
|
||||||
days-before-pr-close: 7
|
|
||||||
exempt-pr-labels: 'pinned,security,do-not-close'
|
|
||||||
|
|
||||||
# General
|
|
||||||
remove-stale-when-updated: true
|
|
||||||
operations-per-run: 100
|
|
||||||
72
.github/workflows/welcome.yml
vendored
72
.github/workflows/welcome.yml
vendored
@@ -1,72 +0,0 @@
|
|||||||
# ============================================================================
|
|
||||||
# BlackRoad OS - Welcome New Contributors
|
|
||||||
# Copyright (c) 2025 BlackRoad OS, Inc. / Alexa Louise Amundson
|
|
||||||
# All Rights Reserved.
|
|
||||||
# ============================================================================
|
|
||||||
#
|
|
||||||
# Welcomes first-time contributors with helpful information.
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
name: Welcome
|
|
||||||
|
|
||||||
on:
|
|
||||||
issues:
|
|
||||||
types: [opened]
|
|
||||||
pull_request_target:
|
|
||||||
types: [opened]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
issues: write
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
welcome:
|
|
||||||
name: Welcome New Contributors
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/first-interaction@v1
|
|
||||||
with:
|
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
issue-message: |
|
|
||||||
Welcome to BlackRoad OS! 👋
|
|
||||||
|
|
||||||
Thank you for opening your first issue. We appreciate your contribution to making BlackRoad better.
|
|
||||||
|
|
||||||
**Quick links:**
|
|
||||||
- 📖 [Documentation](./docs/)
|
|
||||||
- 🏗️ [Architecture Overview](./docs/ARCHITECTURE_LEARNING_RANK.md)
|
|
||||||
- 💬 [Discussions](../../discussions)
|
|
||||||
|
|
||||||
**While you wait:**
|
|
||||||
- Make sure you've read the issue template completely
|
|
||||||
- Add any relevant labels if you can
|
|
||||||
- Feel free to ask questions if anything is unclear
|
|
||||||
|
|
||||||
A maintainer will review your issue soon. Thank you for your patience!
|
|
||||||
|
|
||||||
— *The BlackRoad OS Team* ✨
|
|
||||||
|
|
||||||
pr-message: |
|
|
||||||
Welcome to BlackRoad OS! 🎉
|
|
||||||
|
|
||||||
Thank you for opening your first pull request. We're excited to review your contribution!
|
|
||||||
|
|
||||||
**Before we review:**
|
|
||||||
- [ ] Ensure CI checks pass
|
|
||||||
- [ ] Add tests if applicable
|
|
||||||
- [ ] Update documentation if needed
|
|
||||||
- [ ] Ensure copyright headers are present
|
|
||||||
|
|
||||||
**Review process:**
|
|
||||||
1. A maintainer will review your PR
|
|
||||||
2. They may request changes or ask questions
|
|
||||||
3. Once approved, it will be merged
|
|
||||||
|
|
||||||
**Need help?**
|
|
||||||
- Check our [contribution guidelines](./CONTRIBUTING.md)
|
|
||||||
- Ask questions in the PR comments
|
|
||||||
- Join our discussions
|
|
||||||
|
|
||||||
Thank you for contributing to BlackRoad OS!
|
|
||||||
|
|
||||||
— *The BlackRoad OS Team* 🚀
|
|
||||||
26
CLAUDE.md
26
CLAUDE.md
@@ -1,26 +0,0 @@
|
|||||||
# CLAUDE.md
|
|
||||||
|
|
||||||
This is `blackroad-os-docs` — part of BlackRoad OS.
|
|
||||||
|
|
||||||
> BlackRoad OS — os docs
|
|
||||||
|
|
||||||
## Owner
|
|
||||||
BlackRoad OS, Inc. — Proprietary. All rights reserved.
|
|
||||||
|
|
||||||
## AI Instructions
|
|
||||||
- Part of BlackRoad ecosystem (615+ repos, 15 orgs)
|
|
||||||
- Primary git: RoadCode (Gitea). GitHub is mirror.
|
|
||||||
- All code proprietary unless marked otherwise
|
|
||||||
- Brand: black bg, white text, gradient accents
|
|
||||||
- Fonts: Space Grotesk, Inter, JetBrains Mono
|
|
||||||
- Language: MDX
|
|
||||||
|
|
||||||
## Memory System
|
|
||||||
- Check codex: `memory-codex.sh search "<problem>"`
|
|
||||||
- Log actions: `memory-system.sh log <action> <entity> "<details>"`
|
|
||||||
- Broadcast: `memory-til-broadcast.sh broadcast <cat> "<learning>"`
|
|
||||||
|
|
||||||
## Collaboration
|
|
||||||
- Register: `memory-collaboration.sh register`
|
|
||||||
- Claim: `memory-collaboration.sh claim "<task>"`
|
|
||||||
- Board: `memory-collaboration.sh board`
|
|
||||||
17
Dockerfile
17
Dockerfile
@@ -1,12 +1,17 @@
|
|||||||
FROM node:20-alpine
|
FROM node:18-alpine AS builder
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY package*.json ./
|
COPY package*.json ./
|
||||||
RUN npm ci --only=production
|
RUN npm install
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
FROM node:18-alpine AS runner
|
||||||
|
WORKDIR /app
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm install --omit=dev
|
||||||
|
COPY --from=builder /app/.next ./.next
|
||||||
|
COPY --from=builder /app/public ./public
|
||||||
|
COPY --from=builder /app/next.config.js ./
|
||||||
|
ENV PORT=8080
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
|
|
||||||
CMD ["npm", "start"]
|
CMD ["npm", "start"]
|
||||||
|
|||||||
19
LICENSE
19
LICENSE
@@ -1,19 +0,0 @@
|
|||||||
PROPRIETARY LICENSE
|
|
||||||
|
|
||||||
Copyright © BlackRoad OS, Inc.
|
|
||||||
All Rights Reserved - In Perpetuity
|
|
||||||
|
|
||||||
CEO: Alexa Amundson
|
|
||||||
|
|
||||||
This software and associated documentation files are the exclusive property of
|
|
||||||
BlackRoad OS, Inc. All rights reserved.
|
|
||||||
|
|
||||||
RESTRICTIONS:
|
|
||||||
- No commercial use without explicit written permission
|
|
||||||
- No redistribution or resale
|
|
||||||
- No modification for commercial purposes
|
|
||||||
- Testing and educational use permitted
|
|
||||||
|
|
||||||
For licensing inquiries: legal@blackroad.io
|
|
||||||
|
|
||||||
VIOLATION OF THIS LICENSE WILL RESULT IN LEGAL ACTION.
|
|
||||||
1714
MESH-30K.md
1714
MESH-30K.md
File diff suppressed because it is too large
Load Diff
@@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"repo": "BlackRoad-OS/blackroad-os-docs",
|
|
||||||
"authEndpoints": [
|
|
||||||
"/api/auth/signin",
|
|
||||||
"/api/auth/signup",
|
|
||||||
"/api/auth/signout"
|
|
||||||
],
|
|
||||||
"protectedRoutes": [
|
|
||||||
"/dashboard/*",
|
|
||||||
"/admin/*",
|
|
||||||
"/api/private/*"
|
|
||||||
],
|
|
||||||
"publicRoutes": [
|
|
||||||
"/",
|
|
||||||
"/api/public/*",
|
|
||||||
"/docs/*"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,507 +0,0 @@
|
|||||||
# BlackRoad OS — Launch Sequence
|
|
||||||
|
|
||||||
> **Generated:** 2025-12-01
|
|
||||||
> **Status:** READY FOR APPROVAL
|
|
||||||
> **Governor:** cece.governor.v1
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. RECONSTRUCTED VISION (Baseline Spec)
|
|
||||||
|
|
||||||
### Product Blueprint
|
|
||||||
|
|
||||||
BlackRoad OS is a **distributed AI orchestration platform** with six portals:
|
|
||||||
|
|
||||||
| Portal | Domain | MVP Status |
|
|
||||||
|--------|--------|------------|
|
|
||||||
| **Lucidia** | Personal AI with persistent memory | Phase 0 |
|
|
||||||
| **RoadWork** | Education/homework help | Phase 1 |
|
|
||||||
| **RoadView** | Media creation (video/image gen) | Phase 2 |
|
|
||||||
| **RoadGlitch** | Gaming (procedural content) | Phase 2 |
|
|
||||||
| **RoadWorld** | Navigation + context | Phase 3 |
|
|
||||||
| **BackRoad** | Privacy infrastructure | Phase 3 |
|
|
||||||
|
|
||||||
### Technical Scope Map
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────────────────────────┐
|
|
||||||
│ PORTAL LAYER │
|
|
||||||
│ Lucidia │ RoadWork │ RoadView │ RoadGlitch │ RoadWorld │
|
|
||||||
├─────────────────────────────────────────────────────────────────┤
|
|
||||||
│ GOVERNANCE LAYER │
|
|
||||||
│ Policies │ Ledger │ Intents │ Claims │ Delegations │
|
|
||||||
├─────────────────────────────────────────────────────────────────┤
|
|
||||||
│ INTEGRATION LAYER │
|
|
||||||
│ MCP Servers │ Tools │ GitHub │ Cloudflare │ Railway │
|
|
||||||
├─────────────────────────────────────────────────────────────────┤
|
|
||||||
│ INFRASTRUCTURE LAYER │
|
|
||||||
│ Cloudflare Pages │ Railway (API) │ Postgres │ Self-hosted LLM │
|
|
||||||
└─────────────────────────────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
### MVP Definition
|
|
||||||
|
|
||||||
#### Phase 0 (NOW — Week 1-2)
|
|
||||||
- [x] Infra Map working with real GitHub data
|
|
||||||
- [ ] All core services deployed and healthy
|
|
||||||
- [ ] DNS routing complete (blackroad.io → all subdomains)
|
|
||||||
- [ ] `/health` and `/version` on every service
|
|
||||||
|
|
||||||
#### Phase 1 (Week 3-4)
|
|
||||||
- [ ] Lucidia basic chat working
|
|
||||||
- [ ] Homework Portal basic functionality
|
|
||||||
- [ ] Creator Portal scaffold
|
|
||||||
- [ ] Agent registry + Cece orchestration
|
|
||||||
|
|
||||||
#### Phase 2 (Week 5-8)
|
|
||||||
- [ ] RoadView media generation
|
|
||||||
- [ ] RoadGlitch game content
|
|
||||||
- [ ] Full governance layer
|
|
||||||
- [ ] Policy evaluation in production
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2. MASTER REPOSITORY MAP
|
|
||||||
|
|
||||||
### Active Repos (Keep & Deploy)
|
|
||||||
|
|
||||||
| Repo | Purpose | Deploy To | Status |
|
|
||||||
|------|---------|-----------|--------|
|
|
||||||
| `blackroad-os-web` | Main website + Infra Map | Cloudflare Pages | ✅ READY |
|
|
||||||
| `blackroad-os-core` | API + Database + Integrations | Railway | ✅ READY |
|
|
||||||
| `blackroad-os-api` | Public API Gateway | Railway | 🔧 NEEDS SETUP |
|
|
||||||
| `blackroad-os-api-gateway` | Edge routing | Cloudflare Workers | 🔧 NEEDS SETUP |
|
|
||||||
| `blackroad-os-operator` | Background jobs + scheduling | Railway | 🔧 NEEDS SETUP |
|
|
||||||
| `blackroad-os-prism-console` | Admin dashboard | Cloudflare Pages | 🔧 NEEDS SETUP |
|
|
||||||
| `blackroad-os-docs` | Documentation | Cloudflare Pages | ✅ READY |
|
|
||||||
| `blackroad-os-infra` | IaC, DNS configs, runbooks | N/A (reference) | ✅ READY |
|
|
||||||
| `blackroad-os-agents` | Agent implementations | Railway | 🔧 NEEDS SETUP |
|
|
||||||
| `blackroad-os-brand` | Brand assets | N/A (reference) | ✅ READY |
|
|
||||||
| `lucidia-core` | AI reasoning engines | Railway | 🔧 NEEDS SETUP |
|
|
||||||
| `lucidia-platform` | Lucidia web UI | Cloudflare Pages | 🔧 NEEDS SETUP |
|
|
||||||
|
|
||||||
### Archived Repos (Already Done)
|
|
||||||
|
|
||||||
| Repo | Reason |
|
|
||||||
|------|--------|
|
|
||||||
| `blackroad-os-research` | Merged into docs |
|
|
||||||
| `blackroad-os-ideas` | Merged into docs |
|
|
||||||
| `blackroad-os-helper` | Superseded by agents |
|
|
||||||
| `blackroad-os-home` | Merged into docs |
|
|
||||||
| `blackroad-os-demo` | Sample only |
|
|
||||||
| `blackroad-agents` | Superseded by blackroad-os-agents |
|
|
||||||
| `blackroad-agent-os` | Superseded by operator |
|
|
||||||
|
|
||||||
### Pack Repos (Future — Not Phase 0)
|
|
||||||
|
|
||||||
| Repo | Phase |
|
|
||||||
|------|-------|
|
|
||||||
| `blackroad-os-pack-creator-studio` | Phase 2 |
|
|
||||||
| `blackroad-os-pack-education` | Phase 1 |
|
|
||||||
| `blackroad-os-pack-finance` | Phase 2 |
|
|
||||||
| `blackroad-os-pack-infra-devops` | Phase 1 |
|
|
||||||
| `blackroad-os-pack-legal` | Phase 3 |
|
|
||||||
| `blackroad-os-pack-research-lab` | Phase 3 |
|
|
||||||
|
|
||||||
### Pi/Edge Repos (Later)
|
|
||||||
|
|
||||||
| Repo | Phase |
|
|
||||||
|------|-------|
|
|
||||||
| `blackroad-pi-ops` | Phase 2 |
|
|
||||||
| `blackroad-pi-holo` | Phase 3 |
|
|
||||||
| `blackroad-os-mesh` | Phase 2 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3. LIVE PLATFORM DEPLOYMENT PLAN
|
|
||||||
|
|
||||||
### DNS Mapping Table
|
|
||||||
|
|
||||||
| Subdomain | Target | Type | Provider |
|
|
||||||
|-----------|--------|------|----------|
|
|
||||||
| `blackroad.io` | Cloudflare Pages (web) | CNAME | Cloudflare |
|
|
||||||
| `www.blackroad.io` | → blackroad.io | CNAME | Cloudflare |
|
|
||||||
| `api.blackroad.io` | Railway (blackroad-os-api) | CNAME | Railway |
|
|
||||||
| `app.blackroad.io` | Cloudflare Pages (prism) | CNAME | Cloudflare |
|
|
||||||
| `docs.blackroad.io` | Cloudflare Pages (docs) | CNAME | Cloudflare |
|
|
||||||
| `lucidia.blackroad.io` | Cloudflare Pages (lucidia-platform) | CNAME | Cloudflare |
|
|
||||||
| `status.blackroad.io` | Cloudflare Pages (beacon) | CNAME | Cloudflare |
|
|
||||||
|
|
||||||
### Service Registry
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"services": [
|
|
||||||
{
|
|
||||||
"name": "blackroad-os-web",
|
|
||||||
"type": "frontend",
|
|
||||||
"provider": "cloudflare-pages",
|
|
||||||
"domain": "blackroad.io",
|
|
||||||
"health": "/health",
|
|
||||||
"version": "/version",
|
|
||||||
"repo": "BlackRoad-OS/blackroad-os-web"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "blackroad-os-core",
|
|
||||||
"type": "api",
|
|
||||||
"provider": "railway",
|
|
||||||
"domain": "internal",
|
|
||||||
"port": 4000,
|
|
||||||
"health": "/health",
|
|
||||||
"version": "/api/version",
|
|
||||||
"repo": "BlackRoad-OS/blackroad-os-core"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "blackroad-os-api",
|
|
||||||
"type": "gateway",
|
|
||||||
"provider": "railway",
|
|
||||||
"domain": "api.blackroad.io",
|
|
||||||
"health": "/health",
|
|
||||||
"version": "/version",
|
|
||||||
"repo": "BlackRoad-OS/blackroad-os-api"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "blackroad-os-docs",
|
|
||||||
"type": "frontend",
|
|
||||||
"provider": "cloudflare-pages",
|
|
||||||
"domain": "docs.blackroad.io",
|
|
||||||
"health": "/health",
|
|
||||||
"version": "/version",
|
|
||||||
"repo": "BlackRoad-OS/blackroad-os-docs"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "blackroad-os-prism-console",
|
|
||||||
"type": "frontend",
|
|
||||||
"provider": "cloudflare-pages",
|
|
||||||
"domain": "app.blackroad.io",
|
|
||||||
"health": "/health",
|
|
||||||
"version": "/version",
|
|
||||||
"repo": "BlackRoad-OS/blackroad-os-prism-console"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Deployment Order
|
|
||||||
|
|
||||||
```
|
|
||||||
1. Database (Railway Postgres) ────────────────────── ✅ DONE
|
|
||||||
│
|
|
||||||
2. blackroad-os-core (API server) ─────────────────── ✅ RUNNING LOCALLY
|
|
||||||
│
|
|
||||||
3. blackroad-os-web (Main site + Infra Map) ───────── 🔧 DEPLOY TO CF PAGES
|
|
||||||
│
|
|
||||||
4. blackroad-os-docs ──────────────────────────────── 🔧 DEPLOY TO CF PAGES
|
|
||||||
│
|
|
||||||
5. blackroad-os-api (Public gateway) ──────────────── 🔧 DEPLOY TO RAILWAY
|
|
||||||
│
|
|
||||||
6. blackroad-os-prism-console ─────────────────────── 🔧 DEPLOY TO CF PAGES
|
|
||||||
│
|
|
||||||
7. blackroad-os-operator (Background jobs) ────────── 🔧 DEPLOY TO RAILWAY
|
|
||||||
│
|
|
||||||
8. lucidia-core + lucidia-platform ────────────────── 🔧 PHASE 1
|
|
||||||
```
|
|
||||||
|
|
||||||
### Required Environment Variables
|
|
||||||
|
|
||||||
#### blackroad-os-core (Railway)
|
|
||||||
```bash
|
|
||||||
DATABASE_URL=postgresql://...
|
|
||||||
GITHUB_TOKEN=ghp_...
|
|
||||||
CLOUDFLARE_API_TOKEN=...
|
|
||||||
CLOUDFLARE_ACCOUNT_ID=848cf0b18d51e0170e0d1537aec3505a
|
|
||||||
RAILWAY_TOKEN=...
|
|
||||||
PORT=4000
|
|
||||||
```
|
|
||||||
|
|
||||||
#### blackroad-os-web (Cloudflare Pages)
|
|
||||||
```bash
|
|
||||||
NEXT_PUBLIC_API_URL=https://api.blackroad.io
|
|
||||||
SITE_URL=https://blackroad.io
|
|
||||||
```
|
|
||||||
|
|
||||||
#### blackroad-os-api (Railway)
|
|
||||||
```bash
|
|
||||||
DATABASE_URL=postgresql://...
|
|
||||||
CORE_API_URL=http://blackroad-os-core.railway.internal:4000
|
|
||||||
PORT=8080
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4. MAKE IT LIVE CHECKLIST
|
|
||||||
|
|
||||||
### Phase 0: Core Infrastructure (THIS WEEK)
|
|
||||||
|
|
||||||
```
|
|
||||||
[ ] 1. Deploy blackroad-os-core to Railway
|
|
||||||
- Link to existing Postgres database
|
|
||||||
- Set environment variables
|
|
||||||
- Verify /health returns {"status":"ok"}
|
|
||||||
|
|
||||||
[ ] 2. Deploy blackroad-os-web to Cloudflare Pages
|
|
||||||
- Connect to GitHub repo
|
|
||||||
- Set NEXT_PUBLIC_API_URL to Railway URL
|
|
||||||
- Verify builds and deploys
|
|
||||||
|
|
||||||
[ ] 3. Configure DNS in Cloudflare
|
|
||||||
- blackroad.io → CF Pages (web)
|
|
||||||
- api.blackroad.io → Railway (core for now)
|
|
||||||
- docs.blackroad.io → CF Pages (docs)
|
|
||||||
|
|
||||||
[ ] 4. Verify all services healthy
|
|
||||||
- curl https://blackroad.io/health
|
|
||||||
- curl https://api.blackroad.io/health
|
|
||||||
- curl https://docs.blackroad.io/health
|
|
||||||
|
|
||||||
[ ] 5. Run infra:sync in production
|
|
||||||
- All repos visible on /infra
|
|
||||||
- GitHub integration green
|
|
||||||
- Last synced timestamp updating
|
|
||||||
```
|
|
||||||
|
|
||||||
### Phase 0.5: Full API Layer (Next Week)
|
|
||||||
|
|
||||||
```
|
|
||||||
[ ] 6. Deploy blackroad-os-api to Railway
|
|
||||||
- Public API gateway
|
|
||||||
- Rate limiting
|
|
||||||
- Auth middleware
|
|
||||||
|
|
||||||
[ ] 7. Deploy blackroad-os-prism-console to CF Pages
|
|
||||||
- Admin dashboard at app.blackroad.io
|
|
||||||
- Connect to API
|
|
||||||
|
|
||||||
[ ] 8. Deploy blackroad-os-operator to Railway
|
|
||||||
- Background job runner
|
|
||||||
- Scheduled sync
|
|
||||||
- Health monitoring
|
|
||||||
|
|
||||||
[ ] 9. Set up Cloudflare tunnels for secure internal traffic
|
|
||||||
- Core API not publicly exposed
|
|
||||||
- Gateway handles all external requests
|
|
||||||
```
|
|
||||||
|
|
||||||
### Phase 1: Portals (Week 3-4)
|
|
||||||
|
|
||||||
```
|
|
||||||
[ ] 10. Deploy lucidia-core to Railway
|
|
||||||
- AI reasoning engine
|
|
||||||
- Connect to LLM providers
|
|
||||||
|
|
||||||
[ ] 11. Deploy lucidia-platform to CF Pages
|
|
||||||
- Chat interface at lucidia.blackroad.io
|
|
||||||
- Connected to lucidia-core
|
|
||||||
|
|
||||||
[ ] 12. Implement Homework Portal
|
|
||||||
- Basic question/answer flow
|
|
||||||
- Subject detection
|
|
||||||
- Response storage
|
|
||||||
|
|
||||||
[ ] 13. Implement Creator Portal scaffold
|
|
||||||
- Project management
|
|
||||||
- Template selection
|
|
||||||
- Draft storage
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 5. MISSING FILES TO GENERATE
|
|
||||||
|
|
||||||
### SERVICE_REGISTRY.json (for blackroad-os-infra)
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"$schema": "./schemas/service-registry.schema.json",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"updated": "2025-12-01",
|
|
||||||
"services": [
|
|
||||||
{
|
|
||||||
"id": "web",
|
|
||||||
"name": "blackroad-os-web",
|
|
||||||
"repo": "BlackRoad-OS/blackroad-os-web",
|
|
||||||
"provider": "cloudflare-pages",
|
|
||||||
"domain": "blackroad.io",
|
|
||||||
"endpoints": {
|
|
||||||
"health": "/health",
|
|
||||||
"version": "/version"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "core",
|
|
||||||
"name": "blackroad-os-core",
|
|
||||||
"repo": "BlackRoad-OS/blackroad-os-core",
|
|
||||||
"provider": "railway",
|
|
||||||
"internal": true,
|
|
||||||
"port": 4000,
|
|
||||||
"endpoints": {
|
|
||||||
"health": "/health",
|
|
||||||
"infra": "/api/infra"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "api",
|
|
||||||
"name": "blackroad-os-api",
|
|
||||||
"repo": "BlackRoad-OS/blackroad-os-api",
|
|
||||||
"provider": "railway",
|
|
||||||
"domain": "api.blackroad.io",
|
|
||||||
"port": 8080,
|
|
||||||
"endpoints": {
|
|
||||||
"health": "/health",
|
|
||||||
"version": "/version"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "docs",
|
|
||||||
"name": "blackroad-os-docs",
|
|
||||||
"repo": "BlackRoad-OS/blackroad-os-docs",
|
|
||||||
"provider": "cloudflare-pages",
|
|
||||||
"domain": "docs.blackroad.io",
|
|
||||||
"endpoints": {
|
|
||||||
"health": "/health"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "prism",
|
|
||||||
"name": "blackroad-os-prism-console",
|
|
||||||
"repo": "BlackRoad-OS/blackroad-os-prism-console",
|
|
||||||
"provider": "cloudflare-pages",
|
|
||||||
"domain": "app.blackroad.io",
|
|
||||||
"endpoints": {
|
|
||||||
"health": "/health"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Operator Manifest (for blackroad-os-operator)
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
# operator.manifest.yaml
|
|
||||||
name: blackroad-os-operator
|
|
||||||
version: 0.1.0
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
- name: infra-sync
|
|
||||||
schedule: "0 * * * *" # Every hour
|
|
||||||
command: pnpm infra:sync
|
|
||||||
timeout: 300s
|
|
||||||
|
|
||||||
- name: health-check
|
|
||||||
schedule: "*/5 * * * *" # Every 5 minutes
|
|
||||||
command: pnpm health:check
|
|
||||||
timeout: 60s
|
|
||||||
|
|
||||||
workers:
|
|
||||||
- name: agent-runner
|
|
||||||
concurrency: 5
|
|
||||||
queue: agent-tasks
|
|
||||||
|
|
||||||
- name: notification-sender
|
|
||||||
concurrency: 2
|
|
||||||
queue: notifications
|
|
||||||
|
|
||||||
integrations:
|
|
||||||
- github
|
|
||||||
- cloudflare
|
|
||||||
- railway
|
|
||||||
```
|
|
||||||
|
|
||||||
### Deploy Script (for CI/CD)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
#!/bin/bash
|
|
||||||
# deploy.sh - BlackRoad OS deployment script
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
SERVICE=$1
|
|
||||||
ENV=${2:-production}
|
|
||||||
|
|
||||||
case $SERVICE in
|
|
||||||
web)
|
|
||||||
echo "Deploying blackroad-os-web to Cloudflare Pages..."
|
|
||||||
cd /path/to/blackroad-os-web
|
|
||||||
pnpm build
|
|
||||||
wrangler pages deploy .out --project-name=blackroad-os-web
|
|
||||||
;;
|
|
||||||
|
|
||||||
core)
|
|
||||||
echo "Deploying blackroad-os-core to Railway..."
|
|
||||||
cd /path/to/blackroad-os-core
|
|
||||||
railway up
|
|
||||||
;;
|
|
||||||
|
|
||||||
api)
|
|
||||||
echo "Deploying blackroad-os-api to Railway..."
|
|
||||||
cd /path/to/blackroad-os-api
|
|
||||||
railway up
|
|
||||||
;;
|
|
||||||
|
|
||||||
docs)
|
|
||||||
echo "Deploying blackroad-os-docs to Cloudflare Pages..."
|
|
||||||
cd /path/to/blackroad-os-docs
|
|
||||||
pnpm build
|
|
||||||
wrangler pages deploy out --project-name=blackroad-os-docs
|
|
||||||
;;
|
|
||||||
|
|
||||||
all)
|
|
||||||
$0 core $ENV
|
|
||||||
$0 api $ENV
|
|
||||||
$0 web $ENV
|
|
||||||
$0 docs $ENV
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
echo "Usage: deploy.sh [web|core|api|docs|all] [production|staging]"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
echo "✓ Deployment complete"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 6. IMMEDIATE NEXT ACTIONS
|
|
||||||
|
|
||||||
### Right Now (Copy-Paste Ready)
|
|
||||||
|
|
||||||
**Step 1: Deploy Core to Railway**
|
|
||||||
```bash
|
|
||||||
cd /Users/alexa/blackroad-os-core
|
|
||||||
railway link # Select: blackroad-os-core project
|
|
||||||
railway up
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 2: Deploy Web to Cloudflare Pages**
|
|
||||||
```bash
|
|
||||||
cd /Users/alexa/blackroad-os-web
|
|
||||||
pnpm build
|
|
||||||
wrangler pages project create blackroad-os-web --production-branch main
|
|
||||||
wrangler pages deploy .out --project-name=blackroad-os-web
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 3: Configure DNS**
|
|
||||||
```bash
|
|
||||||
# In Cloudflare dashboard, add CNAME:
|
|
||||||
# blackroad.io → blackroad-os-web.pages.dev
|
|
||||||
# api.blackroad.io → [railway-public-url]
|
|
||||||
```
|
|
||||||
|
|
||||||
**Step 4: Verify**
|
|
||||||
```bash
|
|
||||||
curl https://blackroad.io/health
|
|
||||||
curl https://blackroad.io/infra
|
|
||||||
curl https://api.blackroad.io/health
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Ready for confirmation. Say 'approve' to execute Phase 1.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*Generated by cece.governor.v1*
|
|
||||||
*BlackRoad OS Launch Sequence v1.0*
|
|
||||||
@@ -1,305 +0,0 @@
|
|||||||
# BlackRoad OS Infra Map - Complete Setup Guide
|
|
||||||
|
|
||||||
This is the **zero-braincell** guide to getting Infra Map running with real data.
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
- Node.js 18+
|
|
||||||
- pnpm 8+
|
|
||||||
- PostgreSQL (local or Railway)
|
|
||||||
- API tokens for GitHub, Cloudflare, Railway
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Step 1: Create a PostgreSQL Database
|
|
||||||
|
|
||||||
### Option A: Railway (Recommended - 2 clicks)
|
|
||||||
|
|
||||||
1. Go to [railway.app/new](https://railway.app/new)
|
|
||||||
2. Click "Provision PostgreSQL"
|
|
||||||
3. Once created, click the database → "Variables" tab
|
|
||||||
4. Copy `DATABASE_URL` (looks like `postgresql://postgres:xxx@xxx.railway.app:5432/railway`)
|
|
||||||
|
|
||||||
### Option B: Local PostgreSQL
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# macOS with Homebrew
|
|
||||||
brew install postgresql@15
|
|
||||||
brew services start postgresql@15
|
|
||||||
createdb blackroad_os
|
|
||||||
|
|
||||||
# Your DATABASE_URL will be:
|
|
||||||
# postgresql://localhost:5432/blackroad_os
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Step 2: Set Environment Variables
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd blackroad-os-core
|
|
||||||
|
|
||||||
# Copy example env file
|
|
||||||
cp .env.example .env
|
|
||||||
```
|
|
||||||
|
|
||||||
Edit `.env` with your values:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Database (from Step 1)
|
|
||||||
DATABASE_URL="postgresql://postgres:xxx@xxx.railway.app:5432/railway"
|
|
||||||
|
|
||||||
# GitHub - get from https://github.com/settings/tokens
|
|
||||||
# Scopes needed: repo, read:org
|
|
||||||
GITHUB_TOKEN="ghp_xxxxxxxxxxxxxxxxxxxx"
|
|
||||||
|
|
||||||
# Cloudflare - get from https://dash.cloudflare.com/profile/api-tokens
|
|
||||||
# Permissions: Zone:Read, DNS:Read
|
|
||||||
CLOUDFLARE_API_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
|
||||||
CLOUDFLARE_ACCOUNT_ID="your-account-id" # From dashboard URL
|
|
||||||
|
|
||||||
# Railway - get from https://railway.app/account/tokens
|
|
||||||
RAILWAY_TOKEN="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Step 3: Install Dependencies & Migrate Database
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# In blackroad-os-core
|
|
||||||
cd /path/to/blackroad-os-core
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
pnpm install
|
|
||||||
|
|
||||||
# Generate Prisma client
|
|
||||||
pnpm db:generate
|
|
||||||
|
|
||||||
# Push schema to database (creates all tables)
|
|
||||||
pnpm db:push
|
|
||||||
```
|
|
||||||
|
|
||||||
**Expected output:**
|
|
||||||
```
|
|
||||||
Your database is now in sync with your Prisma schema.
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Step 4: Run Infra Sync
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# In blackroad-os-core
|
|
||||||
pnpm infra:sync
|
|
||||||
```
|
|
||||||
|
|
||||||
**Expected output:**
|
|
||||||
```
|
|
||||||
╔════════════════════════════════════════╗
|
|
||||||
║ BlackRoad OS Infra Sync ║
|
|
||||||
╚════════════════════════════════════════╝
|
|
||||||
|
|
||||||
--- Syncing GitHub ---
|
|
||||||
Authenticated as: your-username
|
|
||||||
Found 15 repositories
|
|
||||||
Syncing 8 BlackRoad-OS repos
|
|
||||||
✓ BlackRoad-OS/blackroad-os-web
|
|
||||||
✓ BlackRoad-OS/blackroad-os-core
|
|
||||||
...
|
|
||||||
|
|
||||||
--- Syncing Cloudflare ---
|
|
||||||
Cloudflare token verified
|
|
||||||
Found 2 zones
|
|
||||||
Zone blackroad.io: 12 records
|
|
||||||
✓ Synced 12 DNS records
|
|
||||||
|
|
||||||
--- Syncing Railway ---
|
|
||||||
Authenticated as: your@email.com
|
|
||||||
Found 3 Railway projects
|
|
||||||
✓ blackroad-web/blackroad-os-web (healthy)
|
|
||||||
✓ blackroad-api/api (healthy)
|
|
||||||
...
|
|
||||||
|
|
||||||
════════════════════════════════════════
|
|
||||||
✓ Sync Complete!
|
|
||||||
Repositories: 8
|
|
||||||
Domains: 12
|
|
||||||
Services: 5
|
|
||||||
════════════════════════════════════════
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Step 5: Start the Core API Server
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# In blackroad-os-core
|
|
||||||
pnpm dev:api
|
|
||||||
```
|
|
||||||
|
|
||||||
**Expected output:**
|
|
||||||
```
|
|
||||||
🖤 BlackRoad OS Core API
|
|
||||||
Server running on http://localhost:4000
|
|
||||||
Endpoints:
|
|
||||||
GET /health - Health check
|
|
||||||
GET /api/infra - Full infra snapshot
|
|
||||||
GET /api/projects - List projects
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
**Verify it works:**
|
|
||||||
```bash
|
|
||||||
curl http://localhost:4000/api/infra | jq
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Step 6: Start the Web App
|
|
||||||
|
|
||||||
**Open a new terminal:**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# In blackroad-os-web
|
|
||||||
cd /path/to/blackroad-os-web
|
|
||||||
|
|
||||||
# Install dependencies (if not done)
|
|
||||||
pnpm install
|
|
||||||
|
|
||||||
# Start dev server
|
|
||||||
pnpm dev
|
|
||||||
```
|
|
||||||
|
|
||||||
**Expected output:**
|
|
||||||
```
|
|
||||||
▲ Next.js 14.x
|
|
||||||
- Local: http://localhost:3000
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Step 7: See Real Data
|
|
||||||
|
|
||||||
1. Open [http://localhost:3000/infra](http://localhost:3000/infra)
|
|
||||||
2. You should see:
|
|
||||||
- Your actual repositories from GitHub
|
|
||||||
- Your DNS records from Cloudflare
|
|
||||||
- Your services from Railway
|
|
||||||
- Real health status for each service
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Quick Reference Commands
|
|
||||||
|
|
||||||
| Command | Directory | What it does |
|
|
||||||
|---------|-----------|--------------|
|
|
||||||
| `pnpm db:push` | blackroad-os-core | Create/update database tables |
|
|
||||||
| `pnpm db:studio` | blackroad-os-core | Open Prisma Studio (visual DB browser) |
|
|
||||||
| `pnpm infra:sync` | blackroad-os-core | Pull data from GitHub/Cloudflare/Railway |
|
|
||||||
| `pnpm dev:api` | blackroad-os-core | Start API server on :4000 |
|
|
||||||
| `pnpm dev` | blackroad-os-web | Start web app on :3000 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### "Failed to load infrastructure data" on /infra
|
|
||||||
|
|
||||||
The web app can't reach the API server.
|
|
||||||
|
|
||||||
1. Make sure `pnpm dev:api` is running in blackroad-os-core
|
|
||||||
2. Check it responds: `curl http://localhost:4000/health`
|
|
||||||
|
|
||||||
### "GITHUB_TOKEN environment variable is required"
|
|
||||||
|
|
||||||
Your `.env` file is missing or not being read.
|
|
||||||
|
|
||||||
1. Make sure `.env` exists in blackroad-os-core root
|
|
||||||
2. Check it has `GITHUB_TOKEN=ghp_...`
|
|
||||||
|
|
||||||
### "Cloudflare API error: 403 Forbidden"
|
|
||||||
|
|
||||||
Your Cloudflare token doesn't have the right permissions.
|
|
||||||
|
|
||||||
1. Go to [Cloudflare API Tokens](https://dash.cloudflare.com/profile/api-tokens)
|
|
||||||
2. Create a new token with: Zone:Read, DNS:Read
|
|
||||||
|
|
||||||
### "Railway API error: Unauthorized"
|
|
||||||
|
|
||||||
Your Railway token may have expired.
|
|
||||||
|
|
||||||
1. Go to [Railway Account Tokens](https://railway.app/account/tokens)
|
|
||||||
2. Generate a new token and update `.env`
|
|
||||||
|
|
||||||
### Empty data on /infra (shows "No projects yet")
|
|
||||||
|
|
||||||
The sync hasn't been run or didn't find any data.
|
|
||||||
|
|
||||||
1. Run `pnpm infra:sync` and check for errors
|
|
||||||
2. Verify your GitHub org is `BlackRoad-OS` or update the sync script filter
|
|
||||||
|
|
||||||
### Database connection errors
|
|
||||||
|
|
||||||
1. Check your `DATABASE_URL` is correct
|
|
||||||
2. For Railway: make sure the database is running
|
|
||||||
3. For local: make sure PostgreSQL is running (`brew services start postgresql@15`)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
|
||||||
│ Browser: http://localhost:3000/infra │
|
|
||||||
│ │
|
|
||||||
│ blackroad-os-web (Next.js) │
|
|
||||||
│ └── app/infra/page.tsx │
|
|
||||||
│ └── fetch('http://localhost:4000/api/infra') │
|
|
||||||
└──────────────────────────┬──────────────────────────────────┘
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
|
||||||
│ http://localhost:4000 │
|
|
||||||
│ │
|
|
||||||
│ blackroad-os-core (Hono API) │
|
|
||||||
│ └── src/api/server.ts │
|
|
||||||
│ └── GET /api/infra │
|
|
||||||
│ └── prisma.project.findFirst(...) │
|
|
||||||
└──────────────────────────┬──────────────────────────────────┘
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
|
||||||
│ PostgreSQL │
|
|
||||||
│ │
|
|
||||||
│ Tables: accounts, projects, services, domains, │
|
|
||||||
│ repositories, environments, audit_logs │
|
|
||||||
│ │
|
|
||||||
│ (populated by: pnpm infra:sync) │
|
|
||||||
└─────────────────────────────────────────────────────────────┘
|
|
||||||
▲
|
|
||||||
│
|
|
||||||
┌──────────────────────────┴──────────────────────────────────┐
|
|
||||||
│ pnpm infra:sync │
|
|
||||||
│ │
|
|
||||||
│ src/scripts/infra-sync.ts │
|
|
||||||
│ └── src/integrations/ │
|
|
||||||
│ ├── github.ts → api.github.com │
|
|
||||||
│ ├── cloudflare.ts → api.cloudflare.com │
|
|
||||||
│ └── railway.ts → backboard.railway.app/graphql │
|
|
||||||
└─────────────────────────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Next Steps
|
|
||||||
|
|
||||||
Once you see real data on `/infra`:
|
|
||||||
|
|
||||||
1. **Creator Portal** - `/creator` for landing pages and content
|
|
||||||
2. **Homework Portal** - `/homework` for student help
|
|
||||||
3. **Agent Swarm** - "Summarize my infra" button
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Questions?** Open an issue at [github.com/BlackRoad-OS/blackroad-os-docs](https://github.com/BlackRoad-OS/blackroad-os-docs/issues)
|
|
||||||
@@ -1,263 +0,0 @@
|
|||||||
# Infra Map v1 Quickstart
|
|
||||||
|
|
||||||
The Infra Map is BlackRoad OS's central dashboard for viewing all your infrastructure in one place: services, domains, and repositories across GitHub, Cloudflare, and Railway.
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
Infra Map v1 is **read-only**. It discovers and displays:
|
|
||||||
|
|
||||||
- **Projects** - Logical groupings of related services
|
|
||||||
- **Services** - Running deployments on Railway, Cloudflare Pages, etc.
|
|
||||||
- **Domains** - DNS records from Cloudflare
|
|
||||||
- **Repositories** - GitHub repos linked to services
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
- Node.js 18+
|
|
||||||
- pnpm 8+
|
|
||||||
- PostgreSQL 14+ (for blackroad-os-core)
|
|
||||||
- API tokens for:
|
|
||||||
- GitHub (Personal Access Token or GitHub App)
|
|
||||||
- Cloudflare (API Token with Zone:Read, DNS:Read)
|
|
||||||
- Railway (API Token)
|
|
||||||
|
|
||||||
## Environment Variables
|
|
||||||
|
|
||||||
### blackroad-os-core
|
|
||||||
|
|
||||||
Create a `.env` file in `blackroad-os-core/`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Database
|
|
||||||
DATABASE_URL="postgresql://user:password@localhost:5432/blackroad_os"
|
|
||||||
|
|
||||||
# GitHub Integration
|
|
||||||
GITHUB_TOKEN="ghp_xxxxxxxxxxxxxxxxxxxx"
|
|
||||||
GITHUB_API_URL="" # Optional: For GitHub Enterprise
|
|
||||||
|
|
||||||
# Cloudflare Integration
|
|
||||||
CLOUDFLARE_API_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
|
||||||
CLOUDFLARE_ACCOUNT_ID="your-account-id" # Required for Tunnels/Pages
|
|
||||||
|
|
||||||
# Railway Integration
|
|
||||||
RAILWAY_TOKEN="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
|
||||||
```
|
|
||||||
|
|
||||||
### blackroad-os-web
|
|
||||||
|
|
||||||
Create a `.env.local` file in `blackroad-os-web/`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Site Configuration
|
|
||||||
SITE_URL="https://blackroad.io"
|
|
||||||
|
|
||||||
# API Backend (when not using static export)
|
|
||||||
BLACKROAD_API_URL="http://localhost:4000"
|
|
||||||
|
|
||||||
# Analytics (optional)
|
|
||||||
PLAUSIBLE_DOMAIN="analytics.blackroad.io"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Getting API Tokens
|
|
||||||
|
|
||||||
### GitHub Personal Access Token
|
|
||||||
|
|
||||||
1. Go to [GitHub Settings → Developer Settings → Personal Access Tokens](https://github.com/settings/tokens)
|
|
||||||
2. Click "Generate new token (classic)"
|
|
||||||
3. Select scopes:
|
|
||||||
- `repo` (for private repos)
|
|
||||||
- `read:org` (to list org repos)
|
|
||||||
4. Copy the token to `GITHUB_TOKEN`
|
|
||||||
|
|
||||||
### Cloudflare API Token
|
|
||||||
|
|
||||||
1. Go to [Cloudflare Dashboard → API Tokens](https://dash.cloudflare.com/profile/api-tokens)
|
|
||||||
2. Click "Create Token"
|
|
||||||
3. Use the "Read all resources" template, or create custom with:
|
|
||||||
- Zone: Read
|
|
||||||
- DNS: Read
|
|
||||||
- (Optional) Account: Cloudflare Pages: Read
|
|
||||||
4. Copy the token to `CLOUDFLARE_API_TOKEN`
|
|
||||||
5. Copy your Account ID from the dashboard URL or overview page
|
|
||||||
|
|
||||||
### Railway API Token
|
|
||||||
|
|
||||||
1. Go to [Railway Dashboard → Account Settings](https://railway.app/account/tokens)
|
|
||||||
2. Click "Create Token"
|
|
||||||
3. Give it a name like "blackroad-infra-read"
|
|
||||||
4. Copy the token to `RAILWAY_TOKEN`
|
|
||||||
|
|
||||||
## Setup
|
|
||||||
|
|
||||||
### 1. Clone and Install
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Clone the repos
|
|
||||||
git clone https://github.com/BlackRoad-OS/blackroad-os-core.git
|
|
||||||
git clone https://github.com/BlackRoad-OS/blackroad-os-web.git
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
cd blackroad-os-core && pnpm install
|
|
||||||
cd ../blackroad-os-web && pnpm install
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Database Setup
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd blackroad-os-core
|
|
||||||
|
|
||||||
# Generate Prisma client
|
|
||||||
pnpm prisma generate
|
|
||||||
|
|
||||||
# Run migrations (creates tables)
|
|
||||||
pnpm prisma migrate dev
|
|
||||||
|
|
||||||
# (Optional) Seed with sample data
|
|
||||||
pnpm prisma db seed
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Start Development
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Terminal 1: Start core (API server)
|
|
||||||
cd blackroad-os-core
|
|
||||||
pnpm dev
|
|
||||||
|
|
||||||
# Terminal 2: Start web (Next.js)
|
|
||||||
cd blackroad-os-web
|
|
||||||
pnpm dev
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Access Infra Map
|
|
||||||
|
|
||||||
Open [http://localhost:3000/infra](http://localhost:3000/infra)
|
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
|
||||||
│ blackroad-os-web │
|
|
||||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
|
|
||||||
│ │ /infra │ │ /dashboard │ │ /settings │ │
|
|
||||||
│ │ (UI) │ │ │ │ /integrations │ │
|
|
||||||
│ └──────┬──────┘ └─────────────┘ └─────────────────────┘ │
|
|
||||||
│ │ │
|
|
||||||
│ │ fetch /api/infra │
|
|
||||||
│ ▼ │
|
|
||||||
│ ┌─────────────────────────────────────────────────────────┐│
|
|
||||||
│ │ API Routes (Next.js) ││
|
|
||||||
│ └──────────────────────┬──────────────────────────────────┘│
|
|
||||||
└─────────────────────────┼───────────────────────────────────┘
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
┌─────────────────────────────────────────────────────────────┐
|
|
||||||
│ blackroad-os-core │
|
|
||||||
│ ┌─────────────────────────────────────────────────────────┐│
|
|
||||||
│ │ src/integrations/ ││
|
|
||||||
│ │ ┌──────────┐ ┌─────────────┐ ┌──────────────┐ ││
|
|
||||||
│ │ │ github │ │ cloudflare │ │ railway │ ││
|
|
||||||
│ │ │ .ts │ │ .ts │ │ .ts │ ││
|
|
||||||
│ │ └────┬─────┘ └──────┬──────┘ └──────┬───────┘ ││
|
|
||||||
│ │ │ │ │ ││
|
|
||||||
│ │ └───────────────┼────────────────┘ ││
|
|
||||||
│ │ ▼ ││
|
|
||||||
│ │ ┌─────────────────┐ ││
|
|
||||||
│ │ │ sync.ts │ ││
|
|
||||||
│ │ │ InfraSyncService│ ││
|
|
||||||
│ │ └────────┬────────┘ ││
|
|
||||||
│ └───────────────────────┼─────────────────────────────────┘│
|
|
||||||
│ │ │
|
|
||||||
│ ▼ │
|
|
||||||
│ ┌─────────────────────────────────────────────────────────┐│
|
|
||||||
│ │ Prisma / PostgreSQL ││
|
|
||||||
│ │ Projects, Services, Domains, Repositories, Environments ││
|
|
||||||
│ └─────────────────────────────────────────────────────────┘│
|
|
||||||
└─────────────────────────────────────────────────────────────┘
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
┌─────────────────────────────────────┐
|
|
||||||
│ External APIs │
|
|
||||||
│ GitHub │ Cloudflare │ Railway │
|
|
||||||
└─────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
## Database Schema
|
|
||||||
|
|
||||||
The Prisma schema includes these main models for Infra Map:
|
|
||||||
|
|
||||||
| Model | Purpose |
|
|
||||||
|-------|---------|
|
|
||||||
| `Project` | Container for related services (type: infra, creator, etc.) |
|
|
||||||
| `Service` | A deployed service (Railway, Cloudflare Pages, etc.) |
|
|
||||||
| `Domain` | DNS record from Cloudflare |
|
|
||||||
| `Repository` | GitHub repository |
|
|
||||||
| `Environment` | Deployment environment (dev, staging, production) |
|
|
||||||
|
|
||||||
See full schema: `blackroad-os-core/prisma/schema.prisma`
|
|
||||||
|
|
||||||
## API Reference
|
|
||||||
|
|
||||||
### GET /api/infra
|
|
||||||
|
|
||||||
Returns the complete infrastructure snapshot.
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"projects": [
|
|
||||||
{
|
|
||||||
"id": "proj-1",
|
|
||||||
"name": "BlackRoad OS",
|
|
||||||
"slug": "blackroad-os",
|
|
||||||
"type": "infra",
|
|
||||||
"services": [...],
|
|
||||||
"repos": [...]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"stats": {
|
|
||||||
"totalServices": 4,
|
|
||||||
"totalDomains": 6,
|
|
||||||
"totalRepos": 5,
|
|
||||||
"healthyServices": 4,
|
|
||||||
"degradedServices": 0,
|
|
||||||
"downServices": 0
|
|
||||||
},
|
|
||||||
"integrations": {
|
|
||||||
"github": true,
|
|
||||||
"cloudflare": true,
|
|
||||||
"railway": true
|
|
||||||
},
|
|
||||||
"lastSynced": "2024-01-15T12:00:00.000Z"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### "GITHUB_TOKEN environment variable is required"
|
|
||||||
|
|
||||||
Ensure your `.env` file is in the correct location and contains `GITHUB_TOKEN`.
|
|
||||||
|
|
||||||
### "Cloudflare API error: 403"
|
|
||||||
|
|
||||||
Your API token may not have the required permissions. Create a new token with Zone:Read and DNS:Read.
|
|
||||||
|
|
||||||
### "Railway API error: Unauthorized"
|
|
||||||
|
|
||||||
Railway tokens expire. Generate a new one from the Railway dashboard.
|
|
||||||
|
|
||||||
### Services showing "unknown" status
|
|
||||||
|
|
||||||
The sync may not have run yet. Click "Sync Now" on the Infra Map page.
|
|
||||||
|
|
||||||
## Next Steps
|
|
||||||
|
|
||||||
- **M1 Complete**: Read-only Infra Map is ready
|
|
||||||
- **Future**: Write operations, auto-sync schedules, alerting
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
See also:
|
|
||||||
- [API Design Reference](/docs/reference/api-design)
|
|
||||||
- [KV Schema Reference](/docs/reference/kv-schema)
|
|
||||||
- [Architecture Overview](/docs/meta/vision/architecture)
|
|
||||||
994
index.html
994
index.html
File diff suppressed because it is too large
Load Diff
@@ -1,118 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>BlackRoad OS Documentation</title>
|
|
||||||
<style>
|
|
||||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
||||||
body {
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
||||||
min-height: 100vh;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
.container {
|
|
||||||
max-width: 1200px;
|
|
||||||
padding: 2rem;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
font-size: 3.5rem;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
|
|
||||||
}
|
|
||||||
.subtitle {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
margin-bottom: 3rem;
|
|
||||||
opacity: 0.9;
|
|
||||||
}
|
|
||||||
.links {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
|
||||||
gap: 2rem;
|
|
||||||
margin-top: 3rem;
|
|
||||||
}
|
|
||||||
.link-card {
|
|
||||||
background: rgba(255,255,255,0.1);
|
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
padding: 2.5rem;
|
|
||||||
border-radius: 1rem;
|
|
||||||
border: 1px solid rgba(255,255,255,0.2);
|
|
||||||
transition: all 0.3s;
|
|
||||||
text-decoration: none;
|
|
||||||
color: white;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.link-card:hover {
|
|
||||||
transform: translateY(-5px);
|
|
||||||
box-shadow: 0 10px 30px rgba(0,0,0,0.3);
|
|
||||||
border-color: rgba(255,255,255,0.4);
|
|
||||||
}
|
|
||||||
.link-card h3 {
|
|
||||||
font-size: 1.8rem;
|
|
||||||
margin-bottom: 0.75rem;
|
|
||||||
}
|
|
||||||
.link-card p {
|
|
||||||
opacity: 0.8;
|
|
||||||
line-height: 1.6;
|
|
||||||
}
|
|
||||||
.status {
|
|
||||||
margin-top: 3rem;
|
|
||||||
padding: 1rem;
|
|
||||||
background: rgba(0,255,0,0.1);
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
border: 1px solid rgba(0,255,0,0.3);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="container">
|
|
||||||
<h1>BlackRoad OS Documentation</h1>
|
|
||||||
<p class="subtitle">The AI Operating System That Pays You</p>
|
|
||||||
|
|
||||||
<div class="status">
|
|
||||||
<strong>Status:</strong> <span style="color: #00ff00;">● All Systems Operational</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="links">
|
|
||||||
<a href="https://github.com/BlackRoad-OS/blackroad-os-core" class="link-card">
|
|
||||||
<h3>📚 Core Library</h3>
|
|
||||||
<p>TypeScript & Python packages for building on BlackRoad OS</p>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="https://api.blackroad.io" class="link-card">
|
|
||||||
<h3>🔧 API Reference</h3>
|
|
||||||
<p>Complete REST API documentation and interactive explorer</p>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="https://blackroad.io" class="link-card">
|
|
||||||
<h3>🏠 Main Site</h3>
|
|
||||||
<p>Learn about BlackRoad OS features and pricing</p>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="https://app.blackroad.io" class="link-card">
|
|
||||||
<h3>🎛️ Console</h3>
|
|
||||||
<p>Access your BlackRoad OS control center</p>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="https://github.com/BlackRoad-OS" class="link-card">
|
|
||||||
<h3>💻 GitHub</h3>
|
|
||||||
<p>Browse all BlackRoad OS repositories</p>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<a href="https://blackroad-dashboard.pages.dev" class="link-card">
|
|
||||||
<h3>📊 Dashboard</h3>
|
|
||||||
<p>Monitor agents and system performance</p>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="margin-top: 4rem; opacity: 0.7; font-size: 0.9rem;">
|
|
||||||
<p>30,000+ AI Agents | 27 Models | PS-SHA∞ Truth Engine | Lucidia Breath</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
20
railway.toml
20
railway.toml
@@ -1,18 +1,12 @@
|
|||||||
[build]
|
[build]
|
||||||
builder = "NIXPACKS"
|
builder = "dockerfile"
|
||||||
|
|
||||||
[deploy]
|
[deploy]
|
||||||
startCommand = "npm start"
|
numReplicas = 1
|
||||||
healthcheckPath = "/health"
|
startCommand = "serve -s build -l ${PORT:-3000}"
|
||||||
healthcheckTimeout = 300
|
healthcheckPath = "/"
|
||||||
restartPolicyType = "ON_FAILURE"
|
healthcheckTimeout = 30
|
||||||
restartPolicyMaxRetries = 10
|
|
||||||
|
|
||||||
[[services]]
|
[variables]
|
||||||
name = "blackroad-os-docs"
|
|
||||||
|
|
||||||
[services.env]
|
|
||||||
PORT = "8080"
|
|
||||||
NODE_ENV = "production"
|
NODE_ENV = "production"
|
||||||
REPO_NAME = "blackroad-os-docs"
|
PORT = "3000"
|
||||||
ORG_NAME = "BlackRoad-OS"
|
|
||||||
|
|||||||
@@ -1,123 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# create-issue.sh
|
|
||||||
# Quick issue creation from the command line
|
|
||||||
#
|
|
||||||
# Usage:
|
|
||||||
# ./create-issue.sh "Fix the login redirect bug"
|
|
||||||
# ./create-issue.sh "Add dark mode toggle" --priority p1
|
|
||||||
# ./create-issue.sh "Refactor auth module" --agent
|
|
||||||
#
|
|
||||||
# Requirements:
|
|
||||||
# - GitHub CLI (gh) installed and authenticated
|
|
||||||
# - Run from within a git repo
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Colors
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
YELLOW='\033[1;33m'
|
|
||||||
NC='\033[0m' # No Color
|
|
||||||
|
|
||||||
# Default values
|
|
||||||
PRIORITY="P2"
|
|
||||||
LABELS="task"
|
|
||||||
AGENT_MODE=false
|
|
||||||
TITLE=""
|
|
||||||
BODY=""
|
|
||||||
|
|
||||||
# Parse arguments
|
|
||||||
while [[ $# -gt 0 ]]; do
|
|
||||||
case $1 in
|
|
||||||
--priority|-p)
|
|
||||||
PRIORITY="${2^^}" # Uppercase
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
--agent|-a)
|
|
||||||
AGENT_MODE=true
|
|
||||||
LABELS="agent-task,automated"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
--bug|-b)
|
|
||||||
LABELS="bug"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
--body)
|
|
||||||
BODY="$2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
--help|-h)
|
|
||||||
echo "Usage: $0 \"Issue title\" [options]"
|
|
||||||
echo ""
|
|
||||||
echo "Options:"
|
|
||||||
echo " --priority, -p <P0|P1|P2|P3> Set priority (default: P2)"
|
|
||||||
echo " --agent, -a Mark as agent task"
|
|
||||||
echo " --bug, -b Mark as bug"
|
|
||||||
echo " --body \"text\" Add body text"
|
|
||||||
echo ""
|
|
||||||
echo "Examples:"
|
|
||||||
echo " $0 \"Fix login redirect\""
|
|
||||||
echo " $0 \"Add dark mode\" --priority p1"
|
|
||||||
echo " $0 \"Refactor auth\" --agent --priority p0"
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
if [[ -z "$TITLE" ]]; then
|
|
||||||
TITLE="$1"
|
|
||||||
fi
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
# Validate
|
|
||||||
if [[ -z "$TITLE" ]]; then
|
|
||||||
echo -e "${RED}Error: Issue title required${NC}"
|
|
||||||
echo "Usage: $0 \"Issue title\" [options]"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check gh is installed
|
|
||||||
if ! command -v gh &> /dev/null; then
|
|
||||||
echo -e "${RED}Error: GitHub CLI (gh) not installed${NC}"
|
|
||||||
echo "Install: https://cli.github.com/"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Build the issue
|
|
||||||
echo -e "${YELLOW}Creating issue...${NC}"
|
|
||||||
|
|
||||||
# Add priority label
|
|
||||||
case $PRIORITY in
|
|
||||||
P0) LABELS="$LABELS,p0-now" ;;
|
|
||||||
P1) LABELS="$LABELS,p1-today" ;;
|
|
||||||
P2) LABELS="$LABELS,p2-week" ;;
|
|
||||||
P3) LABELS="$LABELS,p3-backlog" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Construct title prefix
|
|
||||||
if [[ "$LABELS" == *"agent-task"* ]]; then
|
|
||||||
FULL_TITLE="[AGENT] $TITLE"
|
|
||||||
elif [[ "$LABELS" == *"bug"* ]]; then
|
|
||||||
FULL_TITLE="[BUG] $TITLE"
|
|
||||||
else
|
|
||||||
FULL_TITLE="[TASK] $TITLE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create the issue
|
|
||||||
if [[ -n "$BODY" ]]; then
|
|
||||||
ISSUE_URL=$(gh issue create --title "$FULL_TITLE" --body "$BODY" --label "$LABELS" 2>&1)
|
|
||||||
else
|
|
||||||
ISSUE_URL=$(gh issue create --title "$FULL_TITLE" --body "Created via CLI" --label "$LABELS" 2>&1)
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo -e "${GREEN}✅ Issue created${NC}"
|
|
||||||
echo "$ISSUE_URL"
|
|
||||||
|
|
||||||
# Extract issue number for convenience
|
|
||||||
ISSUE_NUM=$(echo "$ISSUE_URL" | grep -oP '\d+$')
|
|
||||||
if [[ -n "$ISSUE_NUM" ]]; then
|
|
||||||
echo ""
|
|
||||||
echo -e "Branch name: ${YELLOW}issue-$ISSUE_NUM-$(echo "$TITLE" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -cd 'a-z0-9-' | head -c 30)${NC}"
|
|
||||||
fi
|
|
||||||
@@ -1,183 +0,0 @@
|
|||||||
/**
|
|
||||||
* slack-to-github.js
|
|
||||||
*
|
|
||||||
* Webhook handler that creates GitHub issues from Slack messages.
|
|
||||||
* Deploy as: Cloudflare Worker, Vercel Function, or any serverless platform.
|
|
||||||
*
|
|
||||||
* Trigger: Slack slash command or bot mention
|
|
||||||
* Example: /issue Fix the login redirect bug
|
|
||||||
* Example: @blackroad-bot create issue: Add dark mode toggle
|
|
||||||
*
|
|
||||||
* Setup:
|
|
||||||
* 1. Create a Slack App with slash commands or bot
|
|
||||||
* 2. Set the request URL to your deployed function
|
|
||||||
* 3. Set environment variables: GITHUB_TOKEN, GITHUB_OWNER, GITHUB_REPO, SLACK_SIGNING_SECRET
|
|
||||||
*/
|
|
||||||
|
|
||||||
// For Cloudflare Workers
|
|
||||||
export default {
|
|
||||||
async fetch(request, env) {
|
|
||||||
return handleRequest(request, env);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// For Vercel/other platforms, use:
|
|
||||||
// export default async function handler(req, res) { ... }
|
|
||||||
|
|
||||||
async function handleRequest(request, env) {
|
|
||||||
// Verify this is a POST request
|
|
||||||
if (request.method !== 'POST') {
|
|
||||||
return new Response('Method not allowed', { status: 405 });
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Parse the Slack payload
|
|
||||||
const formData = await request.formData();
|
|
||||||
const payload = Object.fromEntries(formData);
|
|
||||||
|
|
||||||
// For slash commands, the text is in payload.text
|
|
||||||
// For bot mentions, you'd parse payload differently
|
|
||||||
const text = payload.text || '';
|
|
||||||
const userId = payload.user_id || 'unknown';
|
|
||||||
const userName = payload.user_name || 'unknown';
|
|
||||||
const channelId = payload.channel_id || '';
|
|
||||||
|
|
||||||
if (!text.trim()) {
|
|
||||||
return slackResponse('Please provide an issue title. Usage: `/issue Fix the login bug`');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse priority from text if included
|
|
||||||
let priority = 'P2';
|
|
||||||
let title = text;
|
|
||||||
|
|
||||||
const priorityMatch = text.match(/\b(p[0-3])\b/i);
|
|
||||||
if (priorityMatch) {
|
|
||||||
priority = priorityMatch[1].toUpperCase();
|
|
||||||
title = text.replace(priorityMatch[0], '').trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detect if this should be an agent task
|
|
||||||
const isAgentTask = text.toLowerCase().includes('[agent]') ||
|
|
||||||
text.toLowerCase().includes('--agent');
|
|
||||||
title = title.replace(/\[agent\]/gi, '').replace(/--agent/gi, '').trim();
|
|
||||||
|
|
||||||
// Detect if this is a bug
|
|
||||||
const isBug = text.toLowerCase().includes('[bug]') ||
|
|
||||||
text.toLowerCase().includes('--bug');
|
|
||||||
title = title.replace(/\[bug\]/gi, '').replace(/--bug/gi, '').trim();
|
|
||||||
|
|
||||||
// Build labels
|
|
||||||
const labels = [];
|
|
||||||
if (isBug) {
|
|
||||||
labels.push('bug');
|
|
||||||
} else if (isAgentTask) {
|
|
||||||
labels.push('agent-task', 'automated');
|
|
||||||
} else {
|
|
||||||
labels.push('task');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add priority label
|
|
||||||
switch (priority) {
|
|
||||||
case 'P0': labels.push('p0-now'); break;
|
|
||||||
case 'P1': labels.push('p1-today'); break;
|
|
||||||
case 'P2': labels.push('p2-week'); break;
|
|
||||||
case 'P3': labels.push('p3-backlog'); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build title prefix
|
|
||||||
let fullTitle = title;
|
|
||||||
if (isBug) {
|
|
||||||
fullTitle = `[BUG] ${title}`;
|
|
||||||
} else if (isAgentTask) {
|
|
||||||
fullTitle = `[AGENT] ${title}`;
|
|
||||||
} else {
|
|
||||||
fullTitle = `[TASK] ${title}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the GitHub issue
|
|
||||||
const issue = await createGitHubIssue({
|
|
||||||
title: fullTitle,
|
|
||||||
body: `Created from Slack by @${userName}\n\nChannel: <#${channelId}>`,
|
|
||||||
labels: labels,
|
|
||||||
env: env
|
|
||||||
});
|
|
||||||
|
|
||||||
// Send success response back to Slack
|
|
||||||
return slackResponse(
|
|
||||||
`✅ Issue created: <${issue.html_url}|#${issue.number} ${title}>\n` +
|
|
||||||
`Priority: ${priority} | Labels: ${labels.join(', ')}`
|
|
||||||
);
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error:', error);
|
|
||||||
return slackResponse(`❌ Failed to create issue: ${error.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function createGitHubIssue({ title, body, labels, env }) {
|
|
||||||
const response = await fetch(
|
|
||||||
`https://api.github.com/repos/${env.GITHUB_OWNER}/${env.GITHUB_REPO}/issues`,
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Authorization': `Bearer ${env.GITHUB_TOKEN}`,
|
|
||||||
'Accept': 'application/vnd.github.v3+json',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'User-Agent': 'BlackRoad-Slack-Bot'
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
title,
|
|
||||||
body,
|
|
||||||
labels
|
|
||||||
})
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
const error = await response.text();
|
|
||||||
throw new Error(`GitHub API error: ${response.status} - ${error}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.json();
|
|
||||||
}
|
|
||||||
|
|
||||||
function slackResponse(text) {
|
|
||||||
return new Response(
|
|
||||||
JSON.stringify({
|
|
||||||
response_type: 'in_channel', // visible to everyone, or 'ephemeral' for private
|
|
||||||
text: text
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Environment variables needed:
|
|
||||||
*
|
|
||||||
* GITHUB_TOKEN - Personal access token with repo scope
|
|
||||||
* GITHUB_OWNER - Your GitHub username or org
|
|
||||||
* GITHUB_REPO - Repository name
|
|
||||||
* SLACK_SIGNING_SECRET - (optional) For verifying Slack requests
|
|
||||||
*
|
|
||||||
* To verify Slack requests (recommended for production):
|
|
||||||
*
|
|
||||||
* async function verifySlackRequest(request, signingSecret) {
|
|
||||||
* const timestamp = request.headers.get('x-slack-request-timestamp');
|
|
||||||
* const signature = request.headers.get('x-slack-signature');
|
|
||||||
* const body = await request.text();
|
|
||||||
*
|
|
||||||
* const baseString = `v0:${timestamp}:${body}`;
|
|
||||||
* const hmac = crypto.createHmac('sha256', signingSecret);
|
|
||||||
* hmac.update(baseString);
|
|
||||||
* const computed = `v0=${hmac.digest('hex')}`;
|
|
||||||
*
|
|
||||||
* return crypto.timingSafeEqual(
|
|
||||||
* Buffer.from(signature),
|
|
||||||
* Buffer.from(computed)
|
|
||||||
* );
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"service": "blackroad-os-docs",
|
|
||||||
"org": "BlackRoad-OS",
|
|
||||||
"dependencies": [],
|
|
||||||
"provides": [
|
|
||||||
{
|
|
||||||
"name": "blackroad-os-docs-api",
|
|
||||||
"port": 8080,
|
|
||||||
"protocol": "http"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"discovery": {
|
|
||||||
"registry": "https://api.blackroad.io/registry",
|
|
||||||
"heartbeat": 30
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
"service": "docs",
|
"service": "docs",
|
||||||
"ts": "2025-11-21T02:26:02.384Z",
|
"ts": "2025-11-21T02:26:02.384Z",
|
||||||
"baseUrl": "https://docs.blackroad.systems",
|
"baseUrl": "https://docs.blackroad.systems",
|
||||||
"osRoot": "https://blackroad.systems",
|
"osRoot": "https://blackroad.systems"
|
||||||
"status": "ok",
|
"status": "ok",
|
||||||
"timestamp": "2025-11-19T21:43:46.169Z",
|
"timestamp": "2025-11-19T21:43:46.169Z",
|
||||||
"environment": "development"
|
"environment": "development"
|
||||||
|
|||||||
@@ -2,4 +2,6 @@
|
|||||||
"status": "ok",
|
"status": "ok",
|
||||||
"timestamp": "2025-11-20T18:35:36.292Z",
|
"timestamp": "2025-11-20T18:35:36.292Z",
|
||||||
"environment": "production"
|
"environment": "production"
|
||||||
|
"timestamp": "2025-11-19T21:43:46.169Z",
|
||||||
|
"environment": "development"
|
||||||
}
|
}
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
{
|
|
||||||
"repo": "BlackRoad-OS/blackroad-os-docs",
|
|
||||||
"products": [
|
|
||||||
{
|
|
||||||
"name": "blackroad-os-docs - Basic",
|
|
||||||
"price": 900,
|
|
||||||
"interval": "month"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "blackroad-os-docs - Pro",
|
|
||||||
"price": 2900,
|
|
||||||
"interval": "month"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "blackroad-os-docs - Enterprise",
|
|
||||||
"price": 9900,
|
|
||||||
"interval": "month"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"webhooks": [
|
|
||||||
"checkout.session.completed",
|
|
||||||
"customer.subscription.created",
|
|
||||||
"customer.subscription.updated",
|
|
||||||
"invoice.paid"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
803
templates/COPY-PASTE-COMMANDS-LIBRARY.md
Normal file
803
templates/COPY-PASTE-COMMANDS-LIBRARY.md
Normal file
@@ -0,0 +1,803 @@
|
|||||||
|
# Copy-Paste Commands Library
|
||||||
|
|
||||||
|
**The Ultimate Terminal Command Reference - Zero Typing Required**
|
||||||
|
|
||||||
|
This library contains **perfect, tested, copy-paste-ready command blocks** for every common operation. Just copy and paste - the comments teach you what's happening.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
1. [Quick Deployments](#quick-deployments)
|
||||||
|
2. [Service Management](#service-management)
|
||||||
|
3. [Git Operations](#git-operations)
|
||||||
|
4. [Environment Setup](#environment-setup)
|
||||||
|
5. [Testing](#testing)
|
||||||
|
6. [Docker](#docker)
|
||||||
|
7. [SSH & Remote](#ssh--remote)
|
||||||
|
8. [File Operations](#file-operations)
|
||||||
|
9. [Debugging](#debugging)
|
||||||
|
10. [Security & Secrets](#security--secrets)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Deployments
|
||||||
|
|
||||||
|
### Deploy Everything
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deploy to all platforms
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
|
||||||
|
# 1. Cloudflare Pages (static sites)
|
||||||
|
./deploy-all-domains.sh
|
||||||
|
|
||||||
|
# 2. Railway (backends)
|
||||||
|
./deploy-all-railway-services.sh
|
||||||
|
|
||||||
|
# 3. Vercel (frontends)
|
||||||
|
./deploy-vercel-all.sh
|
||||||
|
|
||||||
|
# 4. Verify all
|
||||||
|
./br health
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deploy to Cloudflare
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deploy complete API
|
||||||
|
cd ~/blackroad-sandbox/cloudflare-workers
|
||||||
|
wrangler deploy blackroad-unified-api.js --config wrangler-unified-api.toml
|
||||||
|
|
||||||
|
# Initialize databases
|
||||||
|
wrangler d1 execute blackroad-users --file=../cloudflare-d1-schemas.sql
|
||||||
|
|
||||||
|
# Deploy edge router
|
||||||
|
wrangler deploy blackroad-edge-router.js
|
||||||
|
|
||||||
|
# Verify deployment
|
||||||
|
wrangler pages deployment list --project-name=blackroad-io
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deploy to Railway
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Set token
|
||||||
|
export RAILWAY_TOKEN=your-token-here
|
||||||
|
|
||||||
|
# Link to project
|
||||||
|
railway link 0c7bcf07-307b-4db6-9c94-22a456500d68
|
||||||
|
|
||||||
|
# Deploy service
|
||||||
|
railway up --service api-gateway
|
||||||
|
|
||||||
|
# Check status
|
||||||
|
railway status
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
railway logs --tail 100
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deploy to Vercel
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deploy to production
|
||||||
|
cd ~/blackroad-sandbox/vercel-projects/app-name
|
||||||
|
vercel --prod
|
||||||
|
|
||||||
|
# Verify deployment
|
||||||
|
vercel ls
|
||||||
|
|
||||||
|
# View deployment details
|
||||||
|
vercel inspect
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Service Management
|
||||||
|
|
||||||
|
### Start All Services
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start all services in background
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
./start-all.sh
|
||||||
|
|
||||||
|
# Verify all running
|
||||||
|
curl http://localhost:8000/health
|
||||||
|
curl http://localhost:9700/api/health
|
||||||
|
curl http://localhost:9800/api/health
|
||||||
|
```
|
||||||
|
|
||||||
|
### Start Specific Service
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start on default port
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
python3 blackroad-service.py &
|
||||||
|
|
||||||
|
# Start on custom port
|
||||||
|
PORT=9999 python3 blackroad-service.py &
|
||||||
|
|
||||||
|
# Verify it started
|
||||||
|
sleep 2
|
||||||
|
curl http://localhost:9999/health
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stop All Services
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Kill all BlackRoad services
|
||||||
|
pkill -f "blackroad-"
|
||||||
|
|
||||||
|
# Verify stopped
|
||||||
|
pgrep -f "blackroad-" || echo "All services stopped"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Restart Services
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Kill all services
|
||||||
|
pkill -f "blackroad-"
|
||||||
|
|
||||||
|
# Wait for graceful shutdown
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
# Restart
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
./start-all.sh
|
||||||
|
|
||||||
|
# Verify
|
||||||
|
./br health
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check Service Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check what's running
|
||||||
|
pgrep -af "blackroad-"
|
||||||
|
|
||||||
|
# Check specific ports
|
||||||
|
lsof -i :8000
|
||||||
|
lsof -i :9700
|
||||||
|
|
||||||
|
# Check Railway status
|
||||||
|
railway status
|
||||||
|
|
||||||
|
# Check Cloudflare deployments
|
||||||
|
wrangler pages deployment list
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Git Operations
|
||||||
|
|
||||||
|
### Complete Commit and Push
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Navigate to repo
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
|
||||||
|
# Stage all changes
|
||||||
|
git add .
|
||||||
|
|
||||||
|
# Commit with message
|
||||||
|
git commit -m "feat: Add new feature
|
||||||
|
|
||||||
|
Description of changes.
|
||||||
|
|
||||||
|
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
||||||
|
|
||||||
|
Co-Authored-By: Claude <noreply@anthropic.com>"
|
||||||
|
|
||||||
|
# Push to main
|
||||||
|
git push origin main
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create Feature Branch
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create and switch to new branch
|
||||||
|
git checkout -b feature/new-feature
|
||||||
|
|
||||||
|
# Push to remote
|
||||||
|
git push -u origin feature/new-feature
|
||||||
|
|
||||||
|
# Create PR
|
||||||
|
gh pr create --title "Add new feature" --body "Description of changes"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Sync with Remote
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Pull latest changes
|
||||||
|
git pull origin main
|
||||||
|
|
||||||
|
# Fetch all branches
|
||||||
|
git fetch --all
|
||||||
|
|
||||||
|
# View status
|
||||||
|
git status
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fix Merge Conflicts
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Pull with rebase
|
||||||
|
git pull --rebase origin main
|
||||||
|
|
||||||
|
# If conflicts, resolve them then:
|
||||||
|
git add .
|
||||||
|
git rebase --continue
|
||||||
|
|
||||||
|
# Or abort rebase
|
||||||
|
git rebase --abort
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Environment Setup
|
||||||
|
|
||||||
|
### Create .env File
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Copy template
|
||||||
|
cp .env.example .env
|
||||||
|
|
||||||
|
# Add secrets
|
||||||
|
cat >> .env <<'EOF'
|
||||||
|
# Core
|
||||||
|
RAILWAY_TOKEN=your-token-here
|
||||||
|
BLACKROAD_SECRET_KEY=your-secret-here
|
||||||
|
|
||||||
|
# AI Services
|
||||||
|
OPENAI_API_KEY=sk-...
|
||||||
|
ANTHROPIC_API_KEY=sk-ant-...
|
||||||
|
GROQ_API_KEY=gsk_...
|
||||||
|
|
||||||
|
# Cloud Platforms
|
||||||
|
CLOUDFLARE_API_TOKEN=...
|
||||||
|
VERCEL_TOKEN=...
|
||||||
|
|
||||||
|
# Payment & Auth
|
||||||
|
STRIPE_SECRET_KEY=sk_live_...
|
||||||
|
CLERK_SECRET_KEY=sk_...
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Source environment
|
||||||
|
source .env
|
||||||
|
|
||||||
|
# Verify
|
||||||
|
echo "Railway token: ${RAILWAY_TOKEN:0:10}..."
|
||||||
|
```
|
||||||
|
|
||||||
|
### Load Environment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Source from .env
|
||||||
|
source .env
|
||||||
|
|
||||||
|
# Export to child processes
|
||||||
|
set -a
|
||||||
|
source .env
|
||||||
|
set +a
|
||||||
|
|
||||||
|
# Verify variables are set
|
||||||
|
echo $RAILWAY_TOKEN
|
||||||
|
echo $STRIPE_SECRET_KEY
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check Environment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check all required variables
|
||||||
|
for key in RAILWAY_TOKEN STRIPE_SECRET_KEY CLOUDFLARE_API_TOKEN CLERK_SECRET_KEY; do
|
||||||
|
if [ -n "${!key}" ]; then
|
||||||
|
echo "✅ $key is set"
|
||||||
|
else
|
||||||
|
echo "❌ $key not set"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
### Run All Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# All tests with verbose output
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
pytest -v
|
||||||
|
|
||||||
|
# All tests with coverage
|
||||||
|
pytest --cov=. --cov-report=html --cov-report=xml
|
||||||
|
|
||||||
|
# Open coverage report
|
||||||
|
open coverage_html/index.html
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run Specific Test Types
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Unit tests only (fast)
|
||||||
|
pytest -m unit -v
|
||||||
|
|
||||||
|
# Integration tests
|
||||||
|
pytest -m integration -v
|
||||||
|
|
||||||
|
# End-to-end tests
|
||||||
|
pytest -m e2e -v
|
||||||
|
|
||||||
|
# Slow tests
|
||||||
|
pytest -m slow -v
|
||||||
|
```
|
||||||
|
|
||||||
|
### Quick Development Testing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Stop on first failure
|
||||||
|
pytest -v -x
|
||||||
|
|
||||||
|
# Run last failed tests
|
||||||
|
pytest --lf
|
||||||
|
|
||||||
|
# Failed first, then others
|
||||||
|
pytest --ff
|
||||||
|
|
||||||
|
# Development loop: failed first, stop on failure
|
||||||
|
pytest -v -x --ff
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test Specific Files
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Single file
|
||||||
|
pytest tests/unit/test_api.py -v
|
||||||
|
|
||||||
|
# Multiple files
|
||||||
|
pytest tests/unit/test_api.py tests/unit/test_auth.py -v
|
||||||
|
|
||||||
|
# All files matching pattern
|
||||||
|
pytest tests/integration/test_*.py -v
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Docker
|
||||||
|
|
||||||
|
### Start All Containers
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start all services
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
# View status
|
||||||
|
docker-compose ps
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
docker-compose logs -f
|
||||||
|
```
|
||||||
|
|
||||||
|
### Start Specific Services
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start only specific services
|
||||||
|
docker-compose up -d auth-api event-bus service-registry
|
||||||
|
|
||||||
|
# View their logs
|
||||||
|
docker-compose logs -f auth-api event-bus
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stop and Clean
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Stop all services
|
||||||
|
docker-compose down
|
||||||
|
|
||||||
|
# Stop and remove volumes
|
||||||
|
docker-compose down -v
|
||||||
|
|
||||||
|
# Remove all containers, networks, images
|
||||||
|
docker-compose down --rmi all -v
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rebuild and Restart
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Rebuild images
|
||||||
|
docker-compose build
|
||||||
|
|
||||||
|
# Rebuild and start
|
||||||
|
docker-compose up -d --build
|
||||||
|
|
||||||
|
# Rebuild specific service
|
||||||
|
docker-compose build api-gateway
|
||||||
|
docker-compose up -d api-gateway
|
||||||
|
```
|
||||||
|
|
||||||
|
### View Logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# All logs
|
||||||
|
docker-compose logs
|
||||||
|
|
||||||
|
# Follow logs (live)
|
||||||
|
docker-compose logs -f
|
||||||
|
|
||||||
|
# Specific service
|
||||||
|
docker-compose logs -f service-name
|
||||||
|
|
||||||
|
# Last 100 lines
|
||||||
|
docker-compose logs --tail 100
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## SSH & Remote
|
||||||
|
|
||||||
|
### Connect to Servers
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Raspberry Pi
|
||||||
|
ssh alice@192.168.4.49
|
||||||
|
|
||||||
|
# DigitalOcean droplet
|
||||||
|
ssh root@159.65.43.12
|
||||||
|
|
||||||
|
# iPhone Koder
|
||||||
|
ssh mobile@192.168.4.68 -p 8080
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run Remote Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Single command on Pi
|
||||||
|
ssh alice@192.168.4.49 "cd /home/alice && ./start-services.sh"
|
||||||
|
|
||||||
|
# Multiple commands on droplet
|
||||||
|
ssh root@159.65.43.12 "cd /root/blackroad-os && git pull && docker-compose up -d"
|
||||||
|
|
||||||
|
# Get status from Pi
|
||||||
|
ssh alice@192.168.4.49 "systemctl status blackroad-*"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Copy Files to Remote
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Copy file to Pi
|
||||||
|
scp local-file.txt alice@192.168.4.49:/home/alice/
|
||||||
|
|
||||||
|
# Copy directory to droplet
|
||||||
|
scp -r local-directory root@159.65.43.12:/root/
|
||||||
|
|
||||||
|
# Copy from remote to local
|
||||||
|
scp alice@192.168.4.49:/home/alice/remote-file.txt ./
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## File Operations
|
||||||
|
|
||||||
|
### Create Directory Structure
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create nested directories
|
||||||
|
mkdir -p ~/blackroad-sandbox/new-feature/{src,tests,docs}
|
||||||
|
|
||||||
|
# Create with specific permissions
|
||||||
|
mkdir -p ~/blackroad-sandbox/secure && chmod 700 ~/blackroad-sandbox/secure
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create Files with Content
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Single line
|
||||||
|
echo "VARIABLE=value" >> .env
|
||||||
|
|
||||||
|
# Multi-line with heredoc
|
||||||
|
cat > config.yaml <<'EOF'
|
||||||
|
service:
|
||||||
|
name: api-gateway
|
||||||
|
port: 8000
|
||||||
|
environment: production
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Python file with template
|
||||||
|
cat > service.py <<'EOF'
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
from flask import Flask
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
@app.route('/health')
|
||||||
|
def health():
|
||||||
|
return {"ok": True}
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(host='0.0.0.0', port=8000)
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Make executable
|
||||||
|
chmod +x service.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### Search and Replace
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Replace in single file
|
||||||
|
sed -i '' 's/old-value/new-value/g' config.yaml
|
||||||
|
|
||||||
|
# Replace in multiple files
|
||||||
|
find . -name "*.py" -exec sed -i '' 's/old-value/new-value/g' {} +
|
||||||
|
|
||||||
|
# Replace only in specific directory
|
||||||
|
find src/ -name "*.py" -exec sed -i '' 's/old-value/new-value/g' {} +
|
||||||
|
```
|
||||||
|
|
||||||
|
### Find Files
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Find by name
|
||||||
|
find . -name "blackroad-*.py"
|
||||||
|
|
||||||
|
# Find by type (files only)
|
||||||
|
find . -type f -name "*.py"
|
||||||
|
|
||||||
|
# Find and list with details
|
||||||
|
find . -name "*.py" -exec ls -lh {} +
|
||||||
|
|
||||||
|
# Find modified in last 24 hours
|
||||||
|
find . -name "*.py" -mtime -1
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Debugging
|
||||||
|
|
||||||
|
### Find What's Using a Port
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Find process using port 8000
|
||||||
|
lsof -i :8000
|
||||||
|
|
||||||
|
# Kill process using port 8000
|
||||||
|
kill -9 $(lsof -t -i:8000)
|
||||||
|
|
||||||
|
# Find all Python processes
|
||||||
|
lsof -i -P | grep python
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check Process Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Find BlackRoad processes
|
||||||
|
pgrep -af "blackroad-"
|
||||||
|
|
||||||
|
# Find Python processes
|
||||||
|
pgrep -af "python3"
|
||||||
|
|
||||||
|
# Kill specific process
|
||||||
|
pkill -f "blackroad-service"
|
||||||
|
|
||||||
|
# Kill all Python processes
|
||||||
|
pkill python3
|
||||||
|
```
|
||||||
|
|
||||||
|
### Monitor Logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Tail local log file
|
||||||
|
tail -f /path/to/log/file
|
||||||
|
|
||||||
|
# Tail with line count
|
||||||
|
tail -n 100 -f /path/to/log/file
|
||||||
|
|
||||||
|
# Tail multiple files
|
||||||
|
tail -f log1.txt log2.txt
|
||||||
|
|
||||||
|
# Tail Railway logs
|
||||||
|
railway logs --tail 100 --follow
|
||||||
|
|
||||||
|
# Tail Docker logs
|
||||||
|
docker-compose logs -f --tail 100
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test API Endpoints
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# GET request
|
||||||
|
curl http://localhost:8000/health
|
||||||
|
|
||||||
|
# POST request with JSON
|
||||||
|
curl http://localhost:8000/api/resource \
|
||||||
|
-X POST \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"key":"value"}'
|
||||||
|
|
||||||
|
# PUT request
|
||||||
|
curl http://localhost:8000/api/resource/123 \
|
||||||
|
-X PUT \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"key":"new-value"}'
|
||||||
|
|
||||||
|
# DELETE request
|
||||||
|
curl http://localhost:8000/api/resource/123 -X DELETE
|
||||||
|
|
||||||
|
# With authentication
|
||||||
|
curl http://localhost:8000/api/protected \
|
||||||
|
-H "Authorization: Bearer $API_TOKEN"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Security & Secrets
|
||||||
|
|
||||||
|
### Set Railway Secrets
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Single secret
|
||||||
|
railway variables set STRIPE_KEY=sk_live_...
|
||||||
|
|
||||||
|
# Multiple secrets
|
||||||
|
railway variables set \
|
||||||
|
STRIPE_KEY=sk_live_... \
|
||||||
|
CLERK_KEY=sk_... \
|
||||||
|
OPENAI_KEY=sk-...
|
||||||
|
|
||||||
|
# From file
|
||||||
|
while IFS='=' read -r key value; do
|
||||||
|
railway variables set "$key=$value"
|
||||||
|
done < secrets.txt
|
||||||
|
|
||||||
|
# Verify secrets
|
||||||
|
railway variables
|
||||||
|
```
|
||||||
|
|
||||||
|
### Set Cloudflare Secrets
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Set worker secret
|
||||||
|
wrangler secret put STRIPE_KEY
|
||||||
|
|
||||||
|
# Set multiple secrets
|
||||||
|
echo "sk_live_..." | wrangler secret put STRIPE_KEY
|
||||||
|
echo "sk-..." | wrangler secret put OPENAI_KEY
|
||||||
|
|
||||||
|
# List secrets
|
||||||
|
wrangler secret list
|
||||||
|
```
|
||||||
|
|
||||||
|
### Set GitHub Secrets
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Single secret
|
||||||
|
gh secret set RAILWAY_TOKEN -b"your-token-here"
|
||||||
|
|
||||||
|
# From file
|
||||||
|
gh secret set RAILWAY_TOKEN < token.txt
|
||||||
|
|
||||||
|
# For specific repo
|
||||||
|
gh secret set RAILWAY_TOKEN -b"your-token-here" -R BlackRoad-OS/repo-name
|
||||||
|
|
||||||
|
# List secrets
|
||||||
|
gh secret list
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rotate Secrets
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Generate new secret
|
||||||
|
new_secret=$(openssl rand -hex 32)
|
||||||
|
|
||||||
|
# 2. Update Railway
|
||||||
|
railway variables set SECRET_KEY=$new_secret
|
||||||
|
|
||||||
|
# 3. Update Cloudflare
|
||||||
|
echo "$new_secret" | wrangler secret put SECRET_KEY
|
||||||
|
|
||||||
|
# 4. Update GitHub
|
||||||
|
gh secret set SECRET_KEY -b"$new_secret"
|
||||||
|
|
||||||
|
# 5. Update local .env
|
||||||
|
sed -i '' "s/SECRET_KEY=.*/SECRET_KEY=$new_secret/" .env
|
||||||
|
|
||||||
|
# 6. Verify
|
||||||
|
railway variables | grep SECRET_KEY
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Emergency Procedures
|
||||||
|
|
||||||
|
### Complete System Restart
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Kill all local services
|
||||||
|
pkill -f "blackroad-"
|
||||||
|
|
||||||
|
# 2. Stop Docker containers
|
||||||
|
docker-compose down
|
||||||
|
|
||||||
|
# 3. Wait for graceful shutdown
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
# 4. Pull latest code
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
git pull origin main
|
||||||
|
|
||||||
|
# 5. Install dependencies
|
||||||
|
pip3 install -r requirements.txt
|
||||||
|
|
||||||
|
# 6. Restart Docker
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
# 7. Start local services
|
||||||
|
./start-all.sh
|
||||||
|
|
||||||
|
# 8. Verify everything
|
||||||
|
./br health
|
||||||
|
```
|
||||||
|
|
||||||
|
### Emergency Rollback
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Railway rollback
|
||||||
|
railway rollback --service api-gateway
|
||||||
|
|
||||||
|
# 2. Cloudflare rollback
|
||||||
|
wrangler pages deployment list --project-name=blackroad-io
|
||||||
|
wrangler pages deployment rollback [deployment-id]
|
||||||
|
|
||||||
|
# 3. Vercel rollback
|
||||||
|
vercel ls
|
||||||
|
vercel rollback [deployment-url]
|
||||||
|
|
||||||
|
# 4. Verify all
|
||||||
|
./br health
|
||||||
|
```
|
||||||
|
|
||||||
|
### Quick Health Check
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check all critical endpoints
|
||||||
|
endpoints=(
|
||||||
|
"http://localhost:8000/health"
|
||||||
|
"https://api.blackroad.io/health"
|
||||||
|
"https://blackroad.io/"
|
||||||
|
)
|
||||||
|
|
||||||
|
for endpoint in "${endpoints[@]}"; do
|
||||||
|
echo "Testing $endpoint..."
|
||||||
|
curl -sf "$endpoint" && echo "✅" || echo "❌"
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Template: Custom Command Block
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# [Step 1: Description]
|
||||||
|
command1 arg1 arg2
|
||||||
|
|
||||||
|
# [Step 2: Description]
|
||||||
|
command2 arg1 arg2
|
||||||
|
|
||||||
|
# [Step 3: Verification]
|
||||||
|
command3 arg1 arg2
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Copyright
|
||||||
|
|
||||||
|
```
|
||||||
|
# ============================================================================
|
||||||
|
# BlackRoad OS - Proprietary Software
|
||||||
|
# Copyright (c) 2025 BlackRoad OS, Inc. / Alexa Louise Amundson
|
||||||
|
# All Rights Reserved.
|
||||||
|
# ============================================================================
|
||||||
|
```
|
||||||
612
templates/DEPLOYMENT-GUIDE-TEMPLATE.md
Normal file
612
templates/DEPLOYMENT-GUIDE-TEMPLATE.md
Normal file
@@ -0,0 +1,612 @@
|
|||||||
|
# [Service/Platform] Deployment Guide
|
||||||
|
|
||||||
|
**Deploy [Service Name] to [Platform] in 5 minutes**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prerequisites Check
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check required tools
|
||||||
|
which railway && echo "✅ Railway CLI installed" || echo "❌ Install Railway CLI"
|
||||||
|
which wrangler && echo "✅ Wrangler installed" || echo "❌ Install Wrangler"
|
||||||
|
which vercel && echo "✅ Vercel CLI installed" || echo "❌ Install Vercel CLI"
|
||||||
|
|
||||||
|
# Check environment
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
[ -f .env ] && echo "✅ .env exists" || echo "❌ Create .env file"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Method 1: Automated Deployment (Recommended)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deploy everything with one command
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
./deploy-[service]-[platform].sh
|
||||||
|
|
||||||
|
# Verify deployment
|
||||||
|
curl https://[service].[domain]/health
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Method 2: Manual Deployment
|
||||||
|
|
||||||
|
### Step 1: Prepare Environment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Navigate to project
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
|
||||||
|
# Pull latest code
|
||||||
|
git pull origin main
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
pip3 install -r requirements.txt
|
||||||
|
|
||||||
|
# Verify environment variables
|
||||||
|
source .env
|
||||||
|
echo "Token: ${PLATFORM_TOKEN:0:10}..."
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2: Deploy to [Platform]
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Link to project
|
||||||
|
[platform] link [project-id]
|
||||||
|
|
||||||
|
# Set environment variables
|
||||||
|
[platform] env set KEY=value
|
||||||
|
|
||||||
|
# Deploy
|
||||||
|
[platform] deploy
|
||||||
|
|
||||||
|
# Verify
|
||||||
|
[platform] status
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Verify Deployment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check deployment status
|
||||||
|
[platform] status
|
||||||
|
|
||||||
|
# Test health endpoint
|
||||||
|
curl https://[service].[domain]/health
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
[platform] logs --tail 100
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Railway Deployment
|
||||||
|
|
||||||
|
### Quick Deploy
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Set token
|
||||||
|
export RAILWAY_TOKEN=your-token-here
|
||||||
|
|
||||||
|
# Link to project
|
||||||
|
railway link 0c7bcf07-307b-4db6-9c94-22a456500d68
|
||||||
|
|
||||||
|
# Deploy service
|
||||||
|
railway up --service [service-name]
|
||||||
|
|
||||||
|
# Check status
|
||||||
|
railway status
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
railway logs --tail 100
|
||||||
|
|
||||||
|
# Get deployment URL
|
||||||
|
railway domain --json
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deploy Multiple Services
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deploy all services
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
|
||||||
|
services=(
|
||||||
|
"api-gateway"
|
||||||
|
"auth-api"
|
||||||
|
"event-bus"
|
||||||
|
"integrations-hub"
|
||||||
|
)
|
||||||
|
|
||||||
|
for service in "${services[@]}"; do
|
||||||
|
echo "Deploying $service..."
|
||||||
|
railway up --service $service
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
|
||||||
|
# Verify all
|
||||||
|
railway status
|
||||||
|
```
|
||||||
|
|
||||||
|
### Update Secrets
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Set individual secret
|
||||||
|
railway variables set STRIPE_KEY=sk_live_...
|
||||||
|
|
||||||
|
# Set multiple secrets
|
||||||
|
railway variables set \
|
||||||
|
STRIPE_KEY=sk_live_... \
|
||||||
|
CLERK_KEY=sk_... \
|
||||||
|
OPENAI_KEY=sk-...
|
||||||
|
|
||||||
|
# Verify secrets
|
||||||
|
railway variables
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Cloudflare Deployment
|
||||||
|
|
||||||
|
### Deploy Worker
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Navigate to workers directory
|
||||||
|
cd ~/blackroad-sandbox/cloudflare-workers
|
||||||
|
|
||||||
|
# Deploy worker
|
||||||
|
wrangler deploy [worker-name].js --config wrangler-[worker-name].toml
|
||||||
|
|
||||||
|
# Initialize database
|
||||||
|
wrangler d1 execute blackroad-users --file=../cloudflare-d1-schemas.sql
|
||||||
|
|
||||||
|
# Verify deployment
|
||||||
|
curl https://[worker].[domain]/health
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deploy Pages
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Navigate to site directory
|
||||||
|
cd ~/blackroad-sandbox/domains/[domain-name]
|
||||||
|
|
||||||
|
# Deploy to Cloudflare Pages
|
||||||
|
wrangler pages deploy . --project-name=[project-name]
|
||||||
|
|
||||||
|
# Check deployment
|
||||||
|
wrangler pages deployment list --project-name=[project-name]
|
||||||
|
|
||||||
|
# View live site
|
||||||
|
open https://[project-name].pages.dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deploy All Domains
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deploy all 16+ domains
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
|
||||||
|
domains=(
|
||||||
|
"blackroad-io"
|
||||||
|
"lucidia-earth"
|
||||||
|
"blackroadai-com"
|
||||||
|
"blackroad-network"
|
||||||
|
)
|
||||||
|
|
||||||
|
for domain in "${domains[@]}"; do
|
||||||
|
echo "Deploying $domain..."
|
||||||
|
cd domains/$domain
|
||||||
|
wrangler pages deploy . --project-name=$domain
|
||||||
|
cd ../..
|
||||||
|
done
|
||||||
|
|
||||||
|
# Verify all deployments
|
||||||
|
wrangler pages deployment list
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Vercel Deployment
|
||||||
|
|
||||||
|
### Deploy Single App
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Navigate to app
|
||||||
|
cd ~/blackroad-sandbox/vercel-projects/[app-name]
|
||||||
|
|
||||||
|
# Deploy to production
|
||||||
|
vercel --prod
|
||||||
|
|
||||||
|
# Verify deployment
|
||||||
|
vercel ls
|
||||||
|
|
||||||
|
# View live URL
|
||||||
|
vercel inspect
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deploy Multiple Apps
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deploy all Vercel apps
|
||||||
|
cd ~/blackroad-sandbox/vercel-projects
|
||||||
|
|
||||||
|
for app in */; do
|
||||||
|
echo "Deploying $app..."
|
||||||
|
cd "$app"
|
||||||
|
vercel --prod
|
||||||
|
cd ..
|
||||||
|
done
|
||||||
|
|
||||||
|
# Verify all
|
||||||
|
vercel ls
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## DigitalOcean Deployment
|
||||||
|
|
||||||
|
### Deploy to Droplet
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# SSH to droplet
|
||||||
|
ssh root@159.65.43.12
|
||||||
|
|
||||||
|
# Pull latest code
|
||||||
|
cd /root/blackroad-os
|
||||||
|
git pull origin main
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
pip3 install -r requirements.txt
|
||||||
|
|
||||||
|
# Restart services
|
||||||
|
systemctl restart blackroad-*
|
||||||
|
|
||||||
|
# Verify
|
||||||
|
systemctl status blackroad-api
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deploy with Docker
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# SSH to droplet
|
||||||
|
ssh root@159.65.43.12
|
||||||
|
|
||||||
|
# Pull latest code
|
||||||
|
cd /root/blackroad-os
|
||||||
|
git pull origin main
|
||||||
|
|
||||||
|
# Rebuild and restart containers
|
||||||
|
docker-compose down
|
||||||
|
docker-compose build
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
# Verify
|
||||||
|
docker-compose ps
|
||||||
|
curl http://localhost:8000/health
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## GitHub Actions Deployment
|
||||||
|
|
||||||
|
### Trigger Manual Deployment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Trigger workflow
|
||||||
|
gh workflow run deploy-[platform].yml
|
||||||
|
|
||||||
|
# Watch deployment
|
||||||
|
gh run watch
|
||||||
|
|
||||||
|
# View recent runs
|
||||||
|
gh run list --workflow=deploy-[platform].yml --limit 5
|
||||||
|
|
||||||
|
# View logs for specific run
|
||||||
|
gh run view [run-id] --log
|
||||||
|
```
|
||||||
|
|
||||||
|
### Auto-Deploy on Push
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Commit and push (triggers auto-deploy)
|
||||||
|
git add .
|
||||||
|
git commit -m "feat: Add new feature"
|
||||||
|
git push origin main
|
||||||
|
|
||||||
|
# Watch deployment
|
||||||
|
gh run watch
|
||||||
|
|
||||||
|
# Verify deployment
|
||||||
|
curl https://[service].[domain]/health
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Multi-Cloud Deployment (All Platforms)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deploy to everything
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
|
||||||
|
# 1. Railway (backends)
|
||||||
|
./deploy-all-railway-services.sh
|
||||||
|
|
||||||
|
# 2. Cloudflare Pages (static sites)
|
||||||
|
./deploy-all-domains.sh
|
||||||
|
|
||||||
|
# 3. Vercel (frontend apps)
|
||||||
|
./deploy-vercel-all.sh
|
||||||
|
|
||||||
|
# 4. DigitalOcean (servers)
|
||||||
|
ssh root@159.65.43.12 "cd /root/blackroad-os && git pull && docker-compose up -d"
|
||||||
|
|
||||||
|
# 5. Verify everything
|
||||||
|
./br health
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rollback Procedures
|
||||||
|
|
||||||
|
### Railway Rollback
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View recent deployments
|
||||||
|
railway status --service [service-name]
|
||||||
|
|
||||||
|
# Rollback to previous deployment
|
||||||
|
railway rollback --service [service-name]
|
||||||
|
|
||||||
|
# Verify
|
||||||
|
railway logs --tail 100
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cloudflare Rollback
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List deployments
|
||||||
|
wrangler pages deployment list --project-name=[project-name]
|
||||||
|
|
||||||
|
# Rollback to specific deployment
|
||||||
|
wrangler pages deployment rollback [deployment-id]
|
||||||
|
|
||||||
|
# Verify
|
||||||
|
curl https://[project-name].pages.dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### Vercel Rollback
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List deployments
|
||||||
|
vercel ls
|
||||||
|
|
||||||
|
# Rollback to previous deployment
|
||||||
|
vercel rollback [deployment-url]
|
||||||
|
|
||||||
|
# Verify
|
||||||
|
vercel inspect
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Post-Deployment Verification
|
||||||
|
|
||||||
|
### Health Checks
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check all service endpoints
|
||||||
|
endpoints=(
|
||||||
|
"https://api.blackroad.io/health"
|
||||||
|
"https://agents.blackroad.io/health"
|
||||||
|
"https://integrations.blackroad.io/api/health"
|
||||||
|
)
|
||||||
|
|
||||||
|
for endpoint in "${endpoints[@]}"; do
|
||||||
|
echo "Checking $endpoint..."
|
||||||
|
curl -sf "$endpoint" && echo "✅" || echo "❌"
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
### Smoke Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run smoke tests
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
pytest tests/smoke/ -v
|
||||||
|
|
||||||
|
# Test critical paths
|
||||||
|
curl https://api.blackroad.io/health
|
||||||
|
curl https://api.blackroad.io/status
|
||||||
|
curl https://blackroad.io/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Monitor Logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Railway logs
|
||||||
|
railway logs --tail 100 --follow
|
||||||
|
|
||||||
|
# Cloudflare logs
|
||||||
|
wrangler tail
|
||||||
|
|
||||||
|
# Docker logs
|
||||||
|
docker-compose logs -f [service-name]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Deployment Failed
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check logs
|
||||||
|
[platform] logs --tail 100
|
||||||
|
|
||||||
|
# Verify secrets
|
||||||
|
[platform] variables
|
||||||
|
|
||||||
|
# Check build output
|
||||||
|
[platform] status
|
||||||
|
|
||||||
|
# Retry deployment
|
||||||
|
[platform] deploy --force
|
||||||
|
```
|
||||||
|
|
||||||
|
### Service Not Responding
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check service status
|
||||||
|
[platform] status
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
[platform] logs --tail 100
|
||||||
|
|
||||||
|
# Restart service
|
||||||
|
[platform] restart --service [service-name]
|
||||||
|
|
||||||
|
# Verify health
|
||||||
|
curl https://[service].[domain]/health
|
||||||
|
```
|
||||||
|
|
||||||
|
### Environment Variables Missing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List variables
|
||||||
|
[platform] variables
|
||||||
|
|
||||||
|
# Set missing variables
|
||||||
|
[platform] variables set KEY=value
|
||||||
|
|
||||||
|
# Verify
|
||||||
|
[platform] variables | grep KEY
|
||||||
|
|
||||||
|
# Redeploy
|
||||||
|
[platform] up --service [service-name]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Performance Optimization
|
||||||
|
|
||||||
|
### Railway
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Scale service
|
||||||
|
railway scale --replicas 3 --service [service-name]
|
||||||
|
|
||||||
|
# Check metrics
|
||||||
|
railway metrics --service [service-name]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cloudflare
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Enable caching
|
||||||
|
# Add to wrangler.toml:
|
||||||
|
# [build]
|
||||||
|
# cache = true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Vercel
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check build performance
|
||||||
|
vercel inspect [deployment-url]
|
||||||
|
|
||||||
|
# Enable edge functions
|
||||||
|
# Add to vercel.json:
|
||||||
|
# "functions": {
|
||||||
|
# "api/**/*.js": {
|
||||||
|
# "runtime": "@vercel/edge"
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Security Checklist
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# ✅ Secrets in environment variables (not code)
|
||||||
|
# ✅ HTTPS enabled for all endpoints
|
||||||
|
# ✅ CORS configured properly
|
||||||
|
# ✅ Rate limiting enabled
|
||||||
|
# ✅ Authentication required for sensitive endpoints
|
||||||
|
# ✅ Regular dependency updates
|
||||||
|
# ✅ Security headers configured
|
||||||
|
|
||||||
|
# Verify security headers
|
||||||
|
curl -I https://[service].[domain]/
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Monitoring Setup
|
||||||
|
|
||||||
|
### Railway
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View metrics
|
||||||
|
railway metrics --service [service-name]
|
||||||
|
|
||||||
|
# Set up alerts (via dashboard)
|
||||||
|
# https://railway.com/project/[project-id]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cloudflare
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View analytics
|
||||||
|
wrangler pages deployment list --project-name=[project-name]
|
||||||
|
|
||||||
|
# Set up alerts (via dashboard)
|
||||||
|
# https://dash.cloudflare.com/
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
After deployment:
|
||||||
|
|
||||||
|
1. ✅ **Verify all endpoints** respond correctly
|
||||||
|
2. ✅ **Check logs** for any errors
|
||||||
|
3. ✅ **Run smoke tests** to validate critical paths
|
||||||
|
4. ✅ **Monitor metrics** for the first hour
|
||||||
|
5. ✅ **Update documentation** with any changes
|
||||||
|
6. ✅ **Notify team** of deployment
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Reference
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deploy
|
||||||
|
[platform] deploy
|
||||||
|
|
||||||
|
# Status
|
||||||
|
[platform] status
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
[platform] logs --tail 100
|
||||||
|
|
||||||
|
# Rollback
|
||||||
|
[platform] rollback
|
||||||
|
|
||||||
|
# Verify
|
||||||
|
curl https://[service].[domain]/health
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Copyright
|
||||||
|
|
||||||
|
```
|
||||||
|
# ============================================================================
|
||||||
|
# BlackRoad OS - Proprietary Software
|
||||||
|
# Copyright (c) 2025 BlackRoad OS, Inc. / Alexa Louise Amundson
|
||||||
|
# All Rights Reserved.
|
||||||
|
# ============================================================================
|
||||||
|
```
|
||||||
404
templates/EMOJI-REFERENCE.md
Normal file
404
templates/EMOJI-REFERENCE.md
Normal file
@@ -0,0 +1,404 @@
|
|||||||
|
# 🧠 BlackRoad Emoji Dictionary v3
|
||||||
|
|
||||||
|
**127 Canonical Emojis as a Scripting Language**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📖 How to Use This Language
|
||||||
|
|
||||||
|
Every line/section in templates can be structured as:
|
||||||
|
|
||||||
|
```
|
||||||
|
[CONTEXT] [ACTION / STATUS] Title
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```
|
||||||
|
⛅️ 🚀 Deploy Cloudflare Workers
|
||||||
|
💻 ▶️ Run Local Development Server
|
||||||
|
🛣 ✅ System Status: All Green
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Layout & Pointers (23)
|
||||||
|
|
||||||
|
**For structure, flow, and "look here"**
|
||||||
|
|
||||||
|
| Emoji | Meaning | Usage |
|
||||||
|
|-------|---------|-------|
|
||||||
|
| 👉 | Main pointer | Call out important line/choice |
|
||||||
|
| ☞ | Secondary pointer | Subtle "see also" |
|
||||||
|
| ➡️ | Next/forward | Move to next step |
|
||||||
|
| ⬅️ | Back/previous | Rollback step, go back |
|
||||||
|
| ⬆️ | Up/earlier | Reference section above |
|
||||||
|
| ⬇️ | Down/later | Read below/next section |
|
||||||
|
| ↗️ | Escalate/scale up | Resources increasing |
|
||||||
|
| ↘️ | De-escalate/scale down | Reduce usage |
|
||||||
|
| ↩️ | Return | Jump back to previous state |
|
||||||
|
| ↪️ | Branch | Fork, alternate path |
|
||||||
|
| ⤴️ | Promote | Promote staging → prod |
|
||||||
|
| ⤵️ | Demote | Prod → staging/sandbox |
|
||||||
|
| 🔀 | Re-route | Traffic switching, routing changes |
|
||||||
|
| 🔁 | Loop/repeat | Repeat step/cron-like |
|
||||||
|
| 🔂 | Repeat one | Re-run specific command |
|
||||||
|
| ⏫ | Priority up | High-priority step |
|
||||||
|
| ⏬ | Priority down | Low-priority/optional |
|
||||||
|
| 🔼 | Increase | More replicas/higher limits |
|
||||||
|
| 🔽 | Decrease | Fewer replicas/lower limits |
|
||||||
|
| ➕ | Add | Create resource, add config line |
|
||||||
|
| ➖ | Remove | Remove resource, subtract |
|
||||||
|
| ✖️ | Multiply/explode | Fan-out, scale-wide |
|
||||||
|
| 🫱 | Your turn | Human action required |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Context / Platform (17)
|
||||||
|
|
||||||
|
**Where/what this section is about**
|
||||||
|
|
||||||
|
| Emoji | Meaning | Usage |
|
||||||
|
|-------|---------|-------|
|
||||||
|
| ⛅️ | Cloudflare | Workers, R2, D1, Wrangler |
|
||||||
|
| ☁️ | Generic cloud | AWS, GCP, etc. |
|
||||||
|
| 💻 | Dev machine/local | Local dev, CLI tooling |
|
||||||
|
| 🛣 | BlackRoad OS | Cross-system/orchestration |
|
||||||
|
| 📱 | Mobile | iOS/Android/TestFlight |
|
||||||
|
| 🖥 | Web app | Dashboards, web frontends |
|
||||||
|
| 🖱 | UI interaction | Clicking, dashboards, consoles |
|
||||||
|
| ⌨️ | Typing/CLI | Terminal operations |
|
||||||
|
| 🍎 | Apple ecosystem | macOS/iOS tools |
|
||||||
|
| 💬 | Comms | Slack, Discord, Telegram |
|
||||||
|
| 📓 | Productivity apps | Notion, Obsidian, Bear, Notes |
|
||||||
|
| 🧰 | Utilities | 1Password, Stripe dashboard |
|
||||||
|
| 📡 | Network/edge | Global edge network, routing mesh |
|
||||||
|
| 🌐 | DNS/domains | Domains, subdomains, routing |
|
||||||
|
| 💳 | Payments | Stripe, billing flows |
|
||||||
|
| 🔐 | Security/auth | Secrets, auth, lock-down |
|
||||||
|
| 🏠 | Home/root | Root project, main entrypoint |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Actions (17)
|
||||||
|
|
||||||
|
**Verbs/things happening**
|
||||||
|
|
||||||
|
| Emoji | Meaning | Usage |
|
||||||
|
|-------|---------|-------|
|
||||||
|
| 🚀 | Deploy/launch | Ship to environment |
|
||||||
|
| ▶️ | Run | Run script/command/job |
|
||||||
|
| ⏯ | Pause/resume | Toggle process, pause rollout |
|
||||||
|
| ⏹ | Stop | Stop process/kill job |
|
||||||
|
| ⏺ | Record | Start logging/tracing/recording |
|
||||||
|
| 🔄 | Sync | Refresh state, pull latest configs |
|
||||||
|
| ♻️ | Redeploy/recycle | Recreate with same config |
|
||||||
|
| ⏮ | Step back | Previous release/state |
|
||||||
|
| ⏭ | Step forward | Next release/step |
|
||||||
|
| 📥 | Import | Ingest configs/data/DNS |
|
||||||
|
| 📤 | Export | Backup, snapshot, archive |
|
||||||
|
| 🧹 | Clean up | Remove temp artifacts, cache |
|
||||||
|
| 🧽 | Deep clean | Aggressive cleanup |
|
||||||
|
| 🔧 | Configure | Change config, settings |
|
||||||
|
| 🪛 | Fix | Small targeted fix, patch |
|
||||||
|
| 🗑 | Delete | Destructive operation (loud) |
|
||||||
|
| 📌 | Pin | Mark something fixed/pinned/important |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Status / Severity (13)
|
||||||
|
|
||||||
|
**How things are going**
|
||||||
|
|
||||||
|
| Emoji | Meaning | Usage |
|
||||||
|
|-------|---------|-------|
|
||||||
|
| ✅ | OK/done | Succeeded, safe, verified |
|
||||||
|
| ☑️ | Done (checked) | Manual check item completed |
|
||||||
|
| ☐ | Todo | Manual step remaining |
|
||||||
|
| ⏳ | Pending/propagating | Waiting, in progress |
|
||||||
|
| ⌛️ | Time-based waiting | TTL, timeouts, countdowns |
|
||||||
|
| ⚠️ | Warning | Non-fatal, needs attention |
|
||||||
|
| ❗️ | Important | Important note/must-read |
|
||||||
|
| ❕ | Soft important | Lower-priority note |
|
||||||
|
| ❌ | Error | Failed, stop here |
|
||||||
|
| 🚫 | Forbidden | Not allowed/blocked |
|
||||||
|
| 🚨 | Incident | On-fire, high severity |
|
||||||
|
| 🔍 | Investigate | Look closer/drill in |
|
||||||
|
| 🕵️ | Investigator | On-call/incident commander/root cause |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Resources & Infra (17)
|
||||||
|
|
||||||
|
**Things that exist in the system**
|
||||||
|
|
||||||
|
| Emoji | Meaning | Usage |
|
||||||
|
|-------|---------|-------|
|
||||||
|
| 📦 | Package/artifact | Worker script, bundle, container |
|
||||||
|
| 📁 | Folder/repo | GitHub repo, directory |
|
||||||
|
| 🗂 | Collection | Group of configs/projects |
|
||||||
|
| 🗄 | Archive | Backups, cold storage |
|
||||||
|
| 🧱 | Database/building block | D1 tables, infra blocks |
|
||||||
|
| 🧬 | Config genetics | Feature flags, toggles, variants |
|
||||||
|
| 🤖 | AI service/model | LLMs, agents, AI API |
|
||||||
|
| 🛰 | Service/microservice | Satellite services |
|
||||||
|
| 🧩 | Integration | Stripe, Clerk, 3rd-party piece |
|
||||||
|
| 📜 | Schema/contract | API schema, DB schema, types |
|
||||||
|
| 🗝 | Single key | API key, one credential |
|
||||||
|
| 🔑 | Secrets store/vault | Env vars, secret manager |
|
||||||
|
| 🎛 | Control panel | Feature flags, dashboards, toggles |
|
||||||
|
| 🖧 | Network | VPC, mesh, routing layer |
|
||||||
|
| 📑 | Generated doc | Machine output summary, report |
|
||||||
|
| 🏗 | In-construction infra | Building infrastructure/migration |
|
||||||
|
| 🏢 | Production estate | Full running environment/"the city" |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Docs & Learning (10)
|
||||||
|
|
||||||
|
**Words that explain what's happening**
|
||||||
|
|
||||||
|
| Emoji | Meaning | Usage |
|
||||||
|
|-------|---------|-------|
|
||||||
|
| 📚 | Reference docs | Full guides, manuals |
|
||||||
|
| 📖 | Reading view | "Start here" explanations |
|
||||||
|
| 📘 | API docs | Technical reference |
|
||||||
|
| 📙 | How-to guide | Step-by-step walkthroughs |
|
||||||
|
| 📕 | Policy/rules | Constraints, SLAs, guidelines |
|
||||||
|
| 📝 | Notes/summary | Short summaries, quick notes |
|
||||||
|
| 🗒 | Checklist | Deployment/verification checklist |
|
||||||
|
| 📎 | Attachment | Linked file, external resource |
|
||||||
|
| 🔖 | Bookmark | Crucial section/anchor |
|
||||||
|
| 💡 | Tip/insight | Pro tips, best practice callouts |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. People & Roles (10)
|
||||||
|
|
||||||
|
**Who is involved**
|
||||||
|
|
||||||
|
| Emoji | Meaning | Usage |
|
||||||
|
|-------|---------|-------|
|
||||||
|
| 👤 | Single user | One person, single account |
|
||||||
|
| 👥 | Team | Group, squad, org |
|
||||||
|
| 🧑💻 | Developer (generic) | Dev action required |
|
||||||
|
| 👩💻 | Female dev | Person-specific |
|
||||||
|
| 👨💻 | Male dev | Person-specific |
|
||||||
|
| 🧑🏫 | Teacher/explainer | Tutorial mode, educational |
|
||||||
|
| 🧑🔧 | Ops/SRE | Reliability/infra/ops owner |
|
||||||
|
| 🤝 | Handoff/contract | Integration points, owner handoff |
|
||||||
|
| 📣 | Stakeholder/announcer | Announcements, changelogs |
|
||||||
|
| 🙋 | User action | "You need to do this now" |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Time & Scheduling (7)
|
||||||
|
|
||||||
|
**When things happen**
|
||||||
|
|
||||||
|
| Emoji | Meaning | Usage |
|
||||||
|
|-------|---------|-------|
|
||||||
|
| ⏰ | Right now | Run immediately |
|
||||||
|
| ⏱ | Duration | Timeouts, SLAs, latency |
|
||||||
|
| 🕒 | Afternoon/mid-window | Generic time in diagram |
|
||||||
|
| 🕕 | Evening/later window | Off-hours deployment |
|
||||||
|
| 🕛 | Midnight/reset | Daily rollover/reset jobs |
|
||||||
|
| 📆 | Schedule | Release trains, sprint calendars |
|
||||||
|
| 🗓 | Specific date | Fixed deadlines, maintenance windows |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Observability & Debug (6)
|
||||||
|
|
||||||
|
**Seeing what the system is doing**
|
||||||
|
|
||||||
|
| Emoji | Meaning | Usage |
|
||||||
|
|-------|---------|-------|
|
||||||
|
| 📊 | Metrics | Dashboards, graphs, SLO views |
|
||||||
|
| 📈 | Upward trend | Performance/good metric going up |
|
||||||
|
| 📉 | Downward trend | Drops, errors, regressions |
|
||||||
|
| 🧾 | Logs | Log streams, tailing, text output |
|
||||||
|
| 🔎 | Trace/inspect | Traces, deep inspection, span drilldown |
|
||||||
|
| 🧯 | Mitigation | Fire extinguisher: mitigations, safety actions |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Meta / Vibe (7)
|
||||||
|
|
||||||
|
**The emotional layer/storytelling gloss**
|
||||||
|
|
||||||
|
| Emoji | Meaning | Usage |
|
||||||
|
|-------|---------|-------|
|
||||||
|
| ✨ | Magic/delightful | "This feels special" |
|
||||||
|
| 🔥 | Epic done | Whole system wired, big milestone |
|
||||||
|
| 💎 | Premium/enterprise value | "Worth $$" |
|
||||||
|
| 🎉 | Celebration | Success, done, confetti |
|
||||||
|
| 🧠 | Learning/brain mode | Philosophy, patterns, mental models |
|
||||||
|
| 🔮 | Vision/future | Roadmap, speculative ideas |
|
||||||
|
| 🦄 | Wild/experimental | Alpha, weird, unproven |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Template Integration Patterns
|
||||||
|
|
||||||
|
### Headers
|
||||||
|
```
|
||||||
|
⛅️🛣 BLACKROAD OS · CLOUDFLARE MAX BUILDOUT
|
||||||
|
💻🔧 LOCAL DEVELOPMENT CONFIGURATION
|
||||||
|
🖥💳 WEB APP · STRIPE INTEGRATION
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step Lists
|
||||||
|
```
|
||||||
|
1. 🚀 [ACT_DEPLOY] Deploy to production
|
||||||
|
2. 🔄 [ACT_SYNC] Sync configurations
|
||||||
|
3. 📥 [ACT_IMPORT] Import DNS records
|
||||||
|
4. ✅ [STATUS_OK] Verify deployment
|
||||||
|
```
|
||||||
|
|
||||||
|
### Status Boards
|
||||||
|
```
|
||||||
|
✅ 🧱 Database initialized
|
||||||
|
⏳ 📦 Worker deployment pending
|
||||||
|
✅ 🧩 Stripe integration active
|
||||||
|
❌ 🛰 Agent service failed
|
||||||
|
```
|
||||||
|
|
||||||
|
### Documentation Sections
|
||||||
|
```
|
||||||
|
📚 Documentation
|
||||||
|
🗒 Deployment Checklist
|
||||||
|
💡 Pro Tips
|
||||||
|
🎯 Next Steps
|
||||||
|
⚠️ Known Issues
|
||||||
|
🔮 Future Roadmap
|
||||||
|
```
|
||||||
|
|
||||||
|
### Service Status
|
||||||
|
```
|
||||||
|
⛅️ Cloudflare Workers ✅ 8 deployed
|
||||||
|
🛣 Railway Services ✅ 20 running
|
||||||
|
🖥 Vercel Projects ⏳ 3 deploying
|
||||||
|
🧱 D1 Databases ✅ 6 initialized
|
||||||
|
📦 R2 Buckets ✅ 12 configured
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Quick Reference by Use Case
|
||||||
|
|
||||||
|
### Deployment Workflow
|
||||||
|
```
|
||||||
|
⛅️ 🚀 Deploy Cloudflare Worker
|
||||||
|
💻 ⌨️ wrangler deploy blackroad-api.js
|
||||||
|
⏳ Waiting for propagation...
|
||||||
|
✅ Deployed to https://api.blackroad.io
|
||||||
|
```
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
```
|
||||||
|
🚨 ❌ Deployment failed
|
||||||
|
🔍 Investigating root cause
|
||||||
|
🕵️ Checking worker logs
|
||||||
|
🧯 Rolling back to previous version
|
||||||
|
⏮ Restored to v1.2.3
|
||||||
|
✅ Service recovered
|
||||||
|
```
|
||||||
|
|
||||||
|
### Multi-Platform Status
|
||||||
|
```
|
||||||
|
⛅️ Cloudflare ✅ All systems operational
|
||||||
|
🛣 Railway ⚠️ 1 service degraded
|
||||||
|
🖥 Vercel ✅ All projects live
|
||||||
|
📱 Mobile Apps ⏳ Build in progress
|
||||||
|
🌐 DNS ✅ All records propagated
|
||||||
|
```
|
||||||
|
|
||||||
|
### Documentation Structure
|
||||||
|
```
|
||||||
|
📖 Overview
|
||||||
|
📘 API Reference
|
||||||
|
📙 How-To Guides
|
||||||
|
🗒 Deployment Checklist
|
||||||
|
💡 Best Practices
|
||||||
|
⚠️ Troubleshooting
|
||||||
|
🔮 Roadmap
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎨 Color-Coded Emoji Groups
|
||||||
|
|
||||||
|
### 🟢 Green (Success/Go)
|
||||||
|
✅ ☑️ 🚀 💎 🎉
|
||||||
|
|
||||||
|
### 🟡 Yellow (Warning/Attention)
|
||||||
|
⚠️ ❗️ ⏳ ⌛️ 🔍
|
||||||
|
|
||||||
|
### 🔴 Red (Error/Stop)
|
||||||
|
❌ 🚫 🚨 🗑
|
||||||
|
|
||||||
|
### 🔵 Blue (Info/Context)
|
||||||
|
ℹ️ 📚 📖 📘 💡
|
||||||
|
|
||||||
|
### 🟣 Purple (Special/Premium)
|
||||||
|
✨ 🔮 🦄 💎
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧠 Machine-Teachable Patterns
|
||||||
|
|
||||||
|
### Pattern 1: Status Check
|
||||||
|
```
|
||||||
|
[CONTEXT] [STATUS] Resource Name
|
||||||
|
⛅️ ✅ Cloudflare Workers
|
||||||
|
🛣 ⚠️ Railway API Service
|
||||||
|
🖥 ❌ Vercel Dashboard
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 2: Action Sequence
|
||||||
|
```
|
||||||
|
[STEP] [ACTION] [CONTEXT] Description
|
||||||
|
1. 🚀 ⛅️ Deploy Workers
|
||||||
|
2. 🔄 🧱 Sync Databases
|
||||||
|
3. ✅ 🌐 Verify DNS
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 3: Resource Inventory
|
||||||
|
```
|
||||||
|
[RESOURCE] [COUNT] [STATUS] Description
|
||||||
|
📦 8 ✅ Workers deployed
|
||||||
|
🧱 6 ✅ D1 databases initialized
|
||||||
|
🗂 12 ✅ R2 buckets configured
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 4: Troubleshooting Flow
|
||||||
|
```
|
||||||
|
🚨 [INCIDENT] Error detected
|
||||||
|
🔍 [INVESTIGATE] Checking logs
|
||||||
|
🕵️ [ROOT CAUSE] Found issue in config
|
||||||
|
🪛 [FIX] Applied patch
|
||||||
|
✅ [RESOLVED] Service restored
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💡 Best Practices
|
||||||
|
|
||||||
|
1. **Consistency**: Use the same emoji for the same concept across all docs
|
||||||
|
2. **Clarity**: Don't overload - 2-3 emojis max per line
|
||||||
|
3. **Context First**: Lead with context emoji, then action/status
|
||||||
|
4. **Machine-Readable**: Stick to the 127 canonical set
|
||||||
|
5. **Visual Hierarchy**: Use emojis to create scannable structure
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Next Steps
|
||||||
|
|
||||||
|
1. **Use in Templates**: All templates now use this emoji system
|
||||||
|
2. **Train AI**: Claude/ChatGPT can learn these patterns
|
||||||
|
3. **Consistency**: All docs follow same emoji language
|
||||||
|
4. **Evolution**: Propose new emojis via PR with justification
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Remember**: These 127 emojis are on payroll. Use them consistently. 🧠💿🚀
|
||||||
332
templates/INDEX.md
Normal file
332
templates/INDEX.md
Normal file
@@ -0,0 +1,332 @@
|
|||||||
|
# BlackRoad OS Templates
|
||||||
|
|
||||||
|
**Copy-Paste-Ready Templates for Everything**
|
||||||
|
|
||||||
|
This directory contains templates that make development, deployment, and documentation effortless. Every template follows the **copy-paste-and-learn** philosophy: perfect commands that work immediately and teach by doing.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Available Templates
|
||||||
|
|
||||||
|
### 1. Terminal Commands Template
|
||||||
|
**File**: `TERMINAL-COMMANDS-TEMPLATE.md`
|
||||||
|
|
||||||
|
The revolutionary template that changes how we work with terminals. Contains copy-paste-ready command blocks for:
|
||||||
|
- Cloudflare deployment
|
||||||
|
- Railway deployment
|
||||||
|
- Local development
|
||||||
|
- SSH operations
|
||||||
|
- File management
|
||||||
|
- Git workflows
|
||||||
|
- Environment setup
|
||||||
|
- Testing
|
||||||
|
- Docker operations
|
||||||
|
|
||||||
|
**Why this matters**: No more nano nightmares, no more mkdir mistakes, no more SSH struggles. Just copy, paste, learn.
|
||||||
|
|
||||||
|
**Quick Example**:
|
||||||
|
```bash
|
||||||
|
# Deploy complete API
|
||||||
|
cd cloudflare-workers
|
||||||
|
wrangler deploy blackroad-unified-api.js --config wrangler-unified-api.toml
|
||||||
|
|
||||||
|
# Initialize databases
|
||||||
|
wrangler d1 execute blackroad-users --file=../cloudflare-d1-schemas.sql
|
||||||
|
|
||||||
|
# Deploy edge router
|
||||||
|
wrangler deploy blackroad-edge-router.js
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. README Template
|
||||||
|
**File**: `README-TEMPLATE.md`
|
||||||
|
|
||||||
|
Standard README structure with copy-paste-ready sections:
|
||||||
|
- Quick Start (copy-paste installation)
|
||||||
|
- Usage examples (copy-paste commands)
|
||||||
|
- API reference (copy-paste curl commands)
|
||||||
|
- Deployment (copy-paste deploy blocks)
|
||||||
|
- Troubleshooting (copy-paste debug commands)
|
||||||
|
|
||||||
|
### 3. Deployment Guide Template
|
||||||
|
**File**: `DEPLOYMENT-GUIDE-TEMPLATE.md`
|
||||||
|
|
||||||
|
Complete deployment documentation template with:
|
||||||
|
- Platform-specific deployment blocks
|
||||||
|
- Verification commands
|
||||||
|
- Rollback procedures
|
||||||
|
- Multi-cloud deployment
|
||||||
|
- Post-deployment checks
|
||||||
|
|
||||||
|
### 4. Script Template
|
||||||
|
**File**: `SCRIPT-TEMPLATE.sh`
|
||||||
|
|
||||||
|
Bash script template with:
|
||||||
|
- Proper error handling (`set -euo pipefail`)
|
||||||
|
- Interactive menu mode
|
||||||
|
- Direct command mode
|
||||||
|
- Logging
|
||||||
|
- Color output
|
||||||
|
- Help documentation
|
||||||
|
- Copyright headers
|
||||||
|
|
||||||
|
### 5. Copy-Paste Commands Library
|
||||||
|
**File**: `COPY-PASTE-COMMANDS-LIBRARY.md`
|
||||||
|
|
||||||
|
The ultimate command reference - organized by category:
|
||||||
|
- Quick Deployments
|
||||||
|
- Service Management
|
||||||
|
- Git Operations
|
||||||
|
- Environment Setup
|
||||||
|
- Testing
|
||||||
|
- Docker
|
||||||
|
- SSH & Remote
|
||||||
|
- File Operations
|
||||||
|
- Debugging
|
||||||
|
- Security & Secrets
|
||||||
|
- Emergency Procedures
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## The Philosophy
|
||||||
|
|
||||||
|
### Why Copy-Paste-Ready?
|
||||||
|
|
||||||
|
**Before** (traditional docs):
|
||||||
|
```
|
||||||
|
To deploy, run the wrangler deploy command with your config file.
|
||||||
|
```
|
||||||
|
User has to:
|
||||||
|
1. Remember syntax
|
||||||
|
2. Type it correctly
|
||||||
|
3. Figure out config file path
|
||||||
|
4. Hope it works
|
||||||
|
|
||||||
|
**After** (copy-paste-ready):
|
||||||
|
```bash
|
||||||
|
# Deploy complete API
|
||||||
|
cd cloudflare-workers
|
||||||
|
wrangler deploy blackroad-unified-api.js --config wrangler-unified-api.toml
|
||||||
|
|
||||||
|
# Verify deployment
|
||||||
|
wrangler pages deployment list --project-name=blackroad-io
|
||||||
|
```
|
||||||
|
User:
|
||||||
|
1. Copies block
|
||||||
|
2. Pastes in terminal
|
||||||
|
3. It works perfectly
|
||||||
|
4. Comments teach what happened
|
||||||
|
|
||||||
|
### Benefits
|
||||||
|
|
||||||
|
1. **Zero Cognitive Load** - No thinking required, just copy and paste
|
||||||
|
2. **Self-Documenting** - Comments explain the what AND why
|
||||||
|
3. **Machine-Teachable** - AI learns from the pattern
|
||||||
|
4. **Error-Proof** - No manual typing mistakes
|
||||||
|
5. **Context-Preserved** - Full context in every block
|
||||||
|
6. **Teaching by Doing** - Learn while executing
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How to Use These Templates
|
||||||
|
|
||||||
|
### For New Services
|
||||||
|
|
||||||
|
1. Copy `README-TEMPLATE.md`
|
||||||
|
2. Replace placeholders with your service details
|
||||||
|
3. Test all copy-paste command blocks
|
||||||
|
4. Ensure every command works perfectly
|
||||||
|
5. Commit with the service
|
||||||
|
|
||||||
|
### For New Scripts
|
||||||
|
|
||||||
|
1. Copy `SCRIPT-TEMPLATE.sh`
|
||||||
|
2. Customize functions for your needs
|
||||||
|
3. Test interactive menu mode
|
||||||
|
4. Test direct command mode
|
||||||
|
5. Make executable: `chmod +x script.sh`
|
||||||
|
|
||||||
|
### For Documentation
|
||||||
|
|
||||||
|
1. Use `TERMINAL-COMMANDS-TEMPLATE.md` patterns
|
||||||
|
2. Every command must be copy-paste ready
|
||||||
|
3. Include comments explaining each step
|
||||||
|
4. Add verification commands
|
||||||
|
5. Test before publishing
|
||||||
|
|
||||||
|
### For Deployment Guides
|
||||||
|
|
||||||
|
1. Copy `DEPLOYMENT-GUIDE-TEMPLATE.md`
|
||||||
|
2. Fill in platform-specific sections
|
||||||
|
3. Test every deployment block
|
||||||
|
4. Include rollback procedures
|
||||||
|
5. Add verification steps
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Template Standards
|
||||||
|
|
||||||
|
Every template must follow these rules:
|
||||||
|
|
||||||
|
### 1. Comments Explain Everything
|
||||||
|
```bash
|
||||||
|
# What this does and why
|
||||||
|
command --flag value
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Commands Work Perfectly
|
||||||
|
Test every command block before documenting it. No broken examples.
|
||||||
|
|
||||||
|
### 3. Full Context Provided
|
||||||
|
```bash
|
||||||
|
# Navigate to correct directory
|
||||||
|
cd ~/blackroad-sandbox/cloudflare-workers
|
||||||
|
|
||||||
|
# Deploy with specific config
|
||||||
|
wrangler deploy service.js --config wrangler-service.toml
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Verification Included
|
||||||
|
```bash
|
||||||
|
# Deploy
|
||||||
|
railway up --service api-gateway
|
||||||
|
|
||||||
|
# Verify deployment worked
|
||||||
|
railway status
|
||||||
|
curl https://api.blackroad.io/health
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Grouped Logically
|
||||||
|
```bash
|
||||||
|
# Step 1: Setup
|
||||||
|
command1
|
||||||
|
|
||||||
|
# Step 2: Execute
|
||||||
|
command2
|
||||||
|
|
||||||
|
# Step 3: Verify
|
||||||
|
command3
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. No Manual Edits Required
|
||||||
|
Use environment variables or heredocs instead of "edit this file manually":
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Good - copy-paste ready
|
||||||
|
cat >> .env <<'EOF'
|
||||||
|
TOKEN=paste-your-token-here
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Bad - requires manual editing
|
||||||
|
# Edit .env and add your token
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Reference
|
||||||
|
|
||||||
|
### Most Common Patterns
|
||||||
|
|
||||||
|
**Deploy to Cloudflare**:
|
||||||
|
```bash
|
||||||
|
cd cloudflare-workers
|
||||||
|
wrangler deploy service.js --config wrangler-service.toml
|
||||||
|
wrangler pages deployment list --project-name=blackroad-io
|
||||||
|
```
|
||||||
|
|
||||||
|
**Deploy to Railway**:
|
||||||
|
```bash
|
||||||
|
export RAILWAY_TOKEN=your-token-here
|
||||||
|
railway link project-id
|
||||||
|
railway up --service service-name
|
||||||
|
railway status
|
||||||
|
```
|
||||||
|
|
||||||
|
**Start Local Services**:
|
||||||
|
```bash
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
./start-all.sh
|
||||||
|
./br health
|
||||||
|
```
|
||||||
|
|
||||||
|
**Run Tests**:
|
||||||
|
```bash
|
||||||
|
pytest -m unit -v
|
||||||
|
pytest -m integration -v
|
||||||
|
pytest --cov=. --cov-report=html
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Contributing New Templates
|
||||||
|
|
||||||
|
When creating a new template:
|
||||||
|
|
||||||
|
1. **Follow the philosophy** - Copy-paste-ready with teaching comments
|
||||||
|
2. **Test thoroughly** - Every command must work perfectly
|
||||||
|
3. **Document clearly** - Explain what and why
|
||||||
|
4. **Include verification** - Show how to check it worked
|
||||||
|
5. **Add to this index** - Update this file with new template
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create new template
|
||||||
|
cat > templates/NEW-TEMPLATE.md <<'EOF'
|
||||||
|
# Template content here
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Test the template
|
||||||
|
# [test steps]
|
||||||
|
|
||||||
|
# Update index
|
||||||
|
cat >> templates/INDEX.md <<'EOF'
|
||||||
|
|
||||||
|
### X. New Template Name
|
||||||
|
**File**: `NEW-TEMPLATE.md`
|
||||||
|
[Description]
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Commit
|
||||||
|
git add templates/
|
||||||
|
git commit -m "docs: Add new template for [purpose]"
|
||||||
|
git push origin main
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Examples in the Wild
|
||||||
|
|
||||||
|
These templates are used throughout BlackRoad OS:
|
||||||
|
|
||||||
|
- `DEPLOY-QUICK-REFERENCE.md` - Uses deployment patterns
|
||||||
|
- `TEST_COMMANDS.md` - Uses testing patterns
|
||||||
|
- `RAILWAY-WEBHOOK-DEPLOYMENT-GUIDE.md` - Uses deployment template
|
||||||
|
- All `blackroad-*.sh` scripts - Use script template
|
||||||
|
- All service READMEs - Use README template
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Future Templates
|
||||||
|
|
||||||
|
Planned templates:
|
||||||
|
|
||||||
|
- [ ] API Documentation Template
|
||||||
|
- [ ] Integration Guide Template
|
||||||
|
- [ ] Database Migration Template
|
||||||
|
- [ ] Security Audit Template
|
||||||
|
- [ ] Performance Testing Template
|
||||||
|
- [ ] Monitoring Setup Template
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Copyright
|
||||||
|
|
||||||
|
```
|
||||||
|
# ============================================================================
|
||||||
|
# BlackRoad OS - Proprietary Software
|
||||||
|
# Copyright (c) 2025 BlackRoad OS, Inc. / Alexa Louise Amundson
|
||||||
|
# All Rights Reserved.
|
||||||
|
# ============================================================================
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Remember**: Great templates are copy-paste-ready, self-documenting, and teach by doing. If someone has to type something manually, the template isn't good enough yet.
|
||||||
564
templates/MASTER-TEMPLATE-SYSTEM.md
Normal file
564
templates/MASTER-TEMPLATE-SYSTEM.md
Normal file
@@ -0,0 +1,564 @@
|
|||||||
|
# 🎯 BlackRoad OS Master Template System
|
||||||
|
|
||||||
|
**Copy-Paste-Ready Templates for EVERYTHING Across ALL Platforms**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 Template Philosophy
|
||||||
|
|
||||||
|
**The Revolutionary Pattern**: Copy-Paste-And-Learn
|
||||||
|
|
||||||
|
1. **Zero cognitive load** - No thinking, just paste and GO
|
||||||
|
2. **Self-documenting** - Comments explain everything
|
||||||
|
3. **Machine-teachable** - AI learns from the patterns
|
||||||
|
4. **Error-proof** - No typing mistakes
|
||||||
|
5. **Teaching by doing** - Learn while it works
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🗂️ Template Categories
|
||||||
|
|
||||||
|
### 1. Core Development Templates
|
||||||
|
- `README-TEMPLATE.md` - Perfect README for any repo
|
||||||
|
- `DEPLOYMENT-GUIDE-TEMPLATE.md` - Complete deployment docs
|
||||||
|
- `SCRIPT-TEMPLATE.sh` - Bash scripts with menu mode
|
||||||
|
- `PYTHON-SERVICE-TEMPLATE.py` - Flask/FastAPI service skeleton
|
||||||
|
- `DOCKER-TEMPLATE/` - Dockerfile + docker-compose templates
|
||||||
|
- `GITHUB-ACTIONS-TEMPLATE/` - CI/CD workflow templates
|
||||||
|
|
||||||
|
### 2. Platform Integration Templates
|
||||||
|
|
||||||
|
#### Google Drive Templates
|
||||||
|
- `google-drive/PROJECT-TEMPLATE/` - Complete project structure
|
||||||
|
- `google-drive/DOCS-TEMPLATE.gdoc` - Documentation template
|
||||||
|
- `google-drive/SPREADSHEET-TEMPLATE.gsheet` - Data tracking
|
||||||
|
- `google-drive/SLIDES-TEMPLATE.gslides` - Presentation deck
|
||||||
|
- `google-drive/FORM-TEMPLATE.gform` - User input forms
|
||||||
|
|
||||||
|
#### Notion Templates
|
||||||
|
- `notion/PROJECT-DASHBOARD-TEMPLATE` - Project management
|
||||||
|
- `notion/WIKI-TEMPLATE` - Documentation wiki
|
||||||
|
- `notion/ROADMAP-TEMPLATE` - Product roadmap
|
||||||
|
- `notion/MEETING-NOTES-TEMPLATE` - Meeting tracker
|
||||||
|
- `notion/AGENT-PROFILE-TEMPLATE` - Agent documentation
|
||||||
|
|
||||||
|
#### GitHub Templates
|
||||||
|
- `github/ISSUE-TEMPLATES/` - Bug, feature, docs templates
|
||||||
|
- `github/PR-TEMPLATE.md` - Pull request template
|
||||||
|
- `github/REPO-TEMPLATE/` - Complete repo structure
|
||||||
|
- `github/WORKFLOWS-TEMPLATE/` - GitHub Actions workflows
|
||||||
|
- `github/SECURITY-TEMPLATE/` - Security policy, CODEOWNERS
|
||||||
|
|
||||||
|
#### Linear/Jira/Asana Templates
|
||||||
|
- `task-management/PROJECT-TEMPLATE` - Project structure
|
||||||
|
- `task-management/SPRINT-TEMPLATE` - Sprint planning
|
||||||
|
- `task-management/EPIC-TEMPLATE` - Epic/milestone template
|
||||||
|
- `task-management/TASK-TEMPLATE` - Task breakdown
|
||||||
|
|
||||||
|
#### Airtable Templates
|
||||||
|
- `airtable/CRM-TEMPLATE` - Customer relationship management
|
||||||
|
- `airtable/CONTACTS-TEMPLATE` - Contact database
|
||||||
|
- `airtable/DEALS-TEMPLATE` - Sales pipeline
|
||||||
|
- `airtable/PROJECTS-TEMPLATE` - Project tracking
|
||||||
|
- `airtable/INVENTORY-TEMPLATE` - Asset/resource tracking
|
||||||
|
|
||||||
|
### 3. Domain & Deployment Templates
|
||||||
|
|
||||||
|
#### Cloudflare Templates
|
||||||
|
- `cloudflare/WORKER-TEMPLATE.js` - Cloudflare Worker skeleton
|
||||||
|
- `cloudflare/PAGES-TEMPLATE/` - Static site structure
|
||||||
|
- `cloudflare/DNS-TEMPLATE.json` - DNS configuration
|
||||||
|
- `cloudflare/ZERO-TRUST-TEMPLATE.json` - Security rules
|
||||||
|
- `cloudflare/WRANGLER-TEMPLATE.toml` - Worker config
|
||||||
|
|
||||||
|
#### Railway Templates
|
||||||
|
- `railway/SERVICE-TEMPLATE.toml` - Railway service config
|
||||||
|
- `railway/NIXPACKS-TEMPLATE.toml` - Build configuration
|
||||||
|
- `railway/SECRETS-TEMPLATE.env` - Environment variables
|
||||||
|
- `railway/HEALTH-CHECK-TEMPLATE.py` - Health endpoint
|
||||||
|
|
||||||
|
#### Vercel Templates
|
||||||
|
- `vercel/PROJECT-TEMPLATE/` - Next.js/React app
|
||||||
|
- `vercel/VERCEL-JSON-TEMPLATE.json` - Deployment config
|
||||||
|
- `vercel/SERVERLESS-TEMPLATE/` - Serverless functions
|
||||||
|
- `vercel/ENV-TEMPLATE.local` - Environment setup
|
||||||
|
|
||||||
|
### 4. Subdomain Templates (5,216 Sites)
|
||||||
|
|
||||||
|
#### Per-Domain Subdomain Structure
|
||||||
|
```
|
||||||
|
subdomain-templates/
|
||||||
|
├── LANDING-PAGE-TEMPLATE.html # Generic landing page
|
||||||
|
├── API-SUBDOMAIN-TEMPLATE/ # API service page
|
||||||
|
├── DASHBOARD-SUBDOMAIN-TEMPLATE/ # Dashboard app page
|
||||||
|
├── DOCS-SUBDOMAIN-TEMPLATE/ # Documentation site
|
||||||
|
├── AUTH-SUBDOMAIN-TEMPLATE/ # Auth service page
|
||||||
|
├── PAYMENT-SUBDOMAIN-TEMPLATE/ # Payment integration page
|
||||||
|
├── AGENT-SUBDOMAIN-TEMPLATE/ # Agent portal page
|
||||||
|
└── QUANTUM-SUBDOMAIN-TEMPLATE/ # Quantum computing page
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Domain-Specific Templates (16 Domains × 364 Subdomains)
|
||||||
|
- `blackroad-io/` - Main platform templates
|
||||||
|
- `lucidia-earth/` - Lucidia OS templates
|
||||||
|
- `blackroadai-com/` - AI-focused templates
|
||||||
|
- `blackroadquantum-com/` - Quantum computing templates
|
||||||
|
- *(13 more domains...)*
|
||||||
|
|
||||||
|
### 5. Integration Templates (15+ Platforms)
|
||||||
|
|
||||||
|
```
|
||||||
|
integrations/
|
||||||
|
├── stripe/
|
||||||
|
│ ├── CHECKOUT-TEMPLATE.html
|
||||||
|
│ ├── WEBHOOK-HANDLER-TEMPLATE.py
|
||||||
|
│ └── PRODUCT-SETUP-TEMPLATE.sh
|
||||||
|
├── clerk/
|
||||||
|
│ ├── AUTH-TEMPLATE.html
|
||||||
|
│ ├── USER-PROFILE-TEMPLATE.tsx
|
||||||
|
│ └── MIDDLEWARE-TEMPLATE.ts
|
||||||
|
├── resend/
|
||||||
|
│ ├── EMAIL-TEMPLATE.html
|
||||||
|
│ └── SEND-TEMPLATE.py
|
||||||
|
├── asana/
|
||||||
|
│ ├── PROJECT-TEMPLATE.json
|
||||||
|
│ └── TASK-AUTOMATION-TEMPLATE.py
|
||||||
|
├── notion/
|
||||||
|
│ ├── DATABASE-TEMPLATE.json
|
||||||
|
│ └── PAGE-SYNC-TEMPLATE.py
|
||||||
|
└── (13 more platforms...)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Quick Start: Using Templates
|
||||||
|
|
||||||
|
### Example 1: Create New Repo from Template
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Copy the complete repo template
|
||||||
|
cp -r templates/github/REPO-TEMPLATE/ ../my-new-repo/
|
||||||
|
|
||||||
|
# Customize with your project name
|
||||||
|
cd ../my-new-repo
|
||||||
|
./setup-from-template.sh "My New Project" "https://github.com/BlackRoad-OS/my-new-repo"
|
||||||
|
|
||||||
|
# Result: Complete repo with:
|
||||||
|
# - README.md (filled in)
|
||||||
|
# - .github/workflows/ (CI/CD ready)
|
||||||
|
# - Dockerfile + docker-compose.yml
|
||||||
|
# - Railway config
|
||||||
|
# - Vercel config
|
||||||
|
# - All ready to deploy!
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 2: Deploy New Subdomain from Template
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Generate subdomain page from template
|
||||||
|
python3 generate-subdomain-from-template.py \
|
||||||
|
--domain="blackroad.io" \
|
||||||
|
--subdomain="quantum-api" \
|
||||||
|
--template="API-SUBDOMAIN-TEMPLATE" \
|
||||||
|
--title="Quantum Computing API" \
|
||||||
|
--description="Access quantum algorithms via REST API"
|
||||||
|
|
||||||
|
# Deploy to Cloudflare Pages
|
||||||
|
cd subdomain-pages-blackroad-io/quantum-api
|
||||||
|
wrangler pages deploy . --project-name=quantum-api-blackroad-io
|
||||||
|
|
||||||
|
# Result: Live at quantum-api.blackroad.io in < 1 minute!
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 3: Create Google Drive Project from Template
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Authenticate with Google Drive
|
||||||
|
python3 blackroad-google-drive.py auth
|
||||||
|
|
||||||
|
# Create project from template
|
||||||
|
python3 create-google-drive-project.py \
|
||||||
|
--template="PROJECT-TEMPLATE" \
|
||||||
|
--name="Q4 2025 Product Launch" \
|
||||||
|
--folder="BlackRoad OS/Projects/2025/"
|
||||||
|
|
||||||
|
# Result: Complete folder structure with:
|
||||||
|
# - Project charter document
|
||||||
|
# - Timeline spreadsheet
|
||||||
|
# - Team roster
|
||||||
|
# - Meeting notes template
|
||||||
|
# - Roadmap slides
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 4: Set Up Notion Workspace from Template
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Import Notion templates
|
||||||
|
python3 blackroad-notion-service.py import-templates \
|
||||||
|
--workspace="BlackRoad OS" \
|
||||||
|
--templates="templates/notion/"
|
||||||
|
|
||||||
|
# Create new project from template
|
||||||
|
curl -X POST http://localhost:9700/api/integrations/notion/projects \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"template": "PROJECT-DASHBOARD-TEMPLATE",
|
||||||
|
"name": "Agent Recall System v2",
|
||||||
|
"team": ["Alexa", "Lucidia", "Cecilia"]
|
||||||
|
}'
|
||||||
|
|
||||||
|
# Result: Complete Notion workspace with:
|
||||||
|
# - Project dashboard
|
||||||
|
# - Task database
|
||||||
|
# - Documentation pages
|
||||||
|
# - Team wiki
|
||||||
|
# - Meeting notes section
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📦 Template Distribution
|
||||||
|
|
||||||
|
### Auto-Sync to All 43 Repos
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Sync all templates to all repos
|
||||||
|
./sync-templates-to-all-repos.sh
|
||||||
|
|
||||||
|
# What it does:
|
||||||
|
# 1. Copies latest templates/ directory to all 43 repos
|
||||||
|
# 2. Runs customization scripts per repo
|
||||||
|
# 3. Creates PR in each repo with updated templates
|
||||||
|
# 4. Auto-merges if CI passes
|
||||||
|
```
|
||||||
|
|
||||||
|
### Auto-Deploy to All 5,216 Subdomains
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Generate all subdomain pages from templates
|
||||||
|
python3 generate-all-subdomains-from-templates.py
|
||||||
|
|
||||||
|
# Deploy all to Cloudflare Pages
|
||||||
|
./deploy-all-subdomains-pages.sh
|
||||||
|
|
||||||
|
# What it does:
|
||||||
|
# 1. Generates 364 subdomain pages per domain (16 domains)
|
||||||
|
# 2. Customizes each page with domain-specific branding
|
||||||
|
# 3. Deploys to Cloudflare Pages
|
||||||
|
# 4. Updates DNS routing
|
||||||
|
# 5. Verifies all 5,216 sites are live
|
||||||
|
```
|
||||||
|
|
||||||
|
### Auto-Import to All Integration Platforms
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Import templates to all platforms
|
||||||
|
./import-templates-to-all-platforms.sh
|
||||||
|
|
||||||
|
# What it does:
|
||||||
|
# - Google Drive: Creates template library
|
||||||
|
# - Notion: Imports all page templates
|
||||||
|
# - GitHub: Creates template repositories
|
||||||
|
# - Linear: Imports project/task templates
|
||||||
|
# - Jira: Imports issue templates
|
||||||
|
# - Asana: Imports project templates
|
||||||
|
# - Airtable: Creates base templates
|
||||||
|
# - (15+ total platforms)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎨 Template Customization
|
||||||
|
|
||||||
|
### Variables System
|
||||||
|
|
||||||
|
All templates support variable substitution:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Variables defined in template-vars.yaml
|
||||||
|
PROJECT_NAME: "My Awesome Project"
|
||||||
|
DOMAIN: "blackroad.io"
|
||||||
|
SUBDOMAIN: "api"
|
||||||
|
REPO_URL: "https://github.com/BlackRoad-OS/my-awesome-project"
|
||||||
|
AUTHOR: "Alexa Louise Amundson"
|
||||||
|
YEAR: "2025"
|
||||||
|
STRIPE_ENABLED: true
|
||||||
|
CLERK_ENABLED: true
|
||||||
|
|
||||||
|
# Usage in templates:
|
||||||
|
# README-TEMPLATE.md contains: {{PROJECT_NAME}}
|
||||||
|
# After processing: My Awesome Project
|
||||||
|
```
|
||||||
|
|
||||||
|
### Conditional Sections
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- In HTML templates -->
|
||||||
|
{{#if STRIPE_ENABLED}}
|
||||||
|
<script src="https://js.stripe.com/v3/"></script>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if CLERK_ENABLED}}
|
||||||
|
<script src="https://clerk.dev/v3/"></script>
|
||||||
|
{{/if}}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dynamic Content
|
||||||
|
|
||||||
|
```python
|
||||||
|
# In Python templates
|
||||||
|
# {{GENERATED_ROUTES}}
|
||||||
|
# Auto-generates Flask routes based on config
|
||||||
|
|
||||||
|
# {{GENERATED_MODELS}}
|
||||||
|
# Auto-generates SQLAlchemy models from schema
|
||||||
|
|
||||||
|
# {{GENERATED_TESTS}}
|
||||||
|
# Auto-generates pytest tests from endpoints
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔄 Template Update Workflow
|
||||||
|
|
||||||
|
### When Templates Change
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Update master templates in blackroad-sandbox/templates/
|
||||||
|
vim templates/README-TEMPLATE.md
|
||||||
|
|
||||||
|
# 2. Run template sync
|
||||||
|
./sync-templates-to-all-repos.sh
|
||||||
|
|
||||||
|
# 3. Verify changes
|
||||||
|
./verify-template-sync.sh
|
||||||
|
|
||||||
|
# 4. Deploy updated subdomains
|
||||||
|
./deploy-updated-subdomains.sh
|
||||||
|
|
||||||
|
# Result: All 43 repos + 5,216 sites updated automatically!
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Template Analytics
|
||||||
|
|
||||||
|
### Track Template Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# See which templates are most used
|
||||||
|
./template-analytics.sh
|
||||||
|
|
||||||
|
# Output:
|
||||||
|
Template Usage Count Last Used
|
||||||
|
-------------------------------- ----------- --------------------
|
||||||
|
README-TEMPLATE.md 43 repos 2025-12-12 10:30:00
|
||||||
|
API-SUBDOMAIN-TEMPLATE 872 sites 2025-12-12 09:15:00
|
||||||
|
PYTHON-SERVICE-TEMPLATE.py 28 repos 2025-12-11 14:22:00
|
||||||
|
NOTION/PROJECT-DASHBOARD 156 projects 2025-12-10 16:45:00
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Master Template Catalog
|
||||||
|
|
||||||
|
### Complete List (200+ Templates)
|
||||||
|
|
||||||
|
1. **Development** (25 templates)
|
||||||
|
- README, Dockerfile, docker-compose, package.json, requirements.txt, etc.
|
||||||
|
|
||||||
|
2. **CI/CD** (15 templates)
|
||||||
|
- GitHub Actions workflows, Railway configs, Vercel configs, etc.
|
||||||
|
|
||||||
|
3. **Documentation** (20 templates)
|
||||||
|
- User guides, API docs, architecture diagrams, etc.
|
||||||
|
|
||||||
|
4. **Google Drive** (30 templates)
|
||||||
|
- Docs, Sheets, Slides, Forms across all project types
|
||||||
|
|
||||||
|
5. **Notion** (25 templates)
|
||||||
|
- Dashboards, wikis, databases, pages, etc.
|
||||||
|
|
||||||
|
6. **GitHub** (20 templates)
|
||||||
|
- Issues, PRs, repos, workflows, security, etc.
|
||||||
|
|
||||||
|
7. **Task Management** (15 templates)
|
||||||
|
- Linear, Jira, Asana project/task templates
|
||||||
|
|
||||||
|
8. **Airtable** (10 templates)
|
||||||
|
- CRM, contacts, deals, projects, inventory
|
||||||
|
|
||||||
|
9. **Cloudflare** (20 templates)
|
||||||
|
- Workers, Pages, DNS, Zero Trust, etc.
|
||||||
|
|
||||||
|
10. **Railway** (10 templates)
|
||||||
|
- Service configs, health checks, secrets, etc.
|
||||||
|
|
||||||
|
11. **Vercel** (10 templates)
|
||||||
|
- Next.js apps, serverless functions, configs
|
||||||
|
|
||||||
|
12. **Subdomains** (5,216 variations)
|
||||||
|
- 364 templates × 16 domains = complete coverage
|
||||||
|
|
||||||
|
13. **Integrations** (15 templates)
|
||||||
|
- Stripe, Clerk, Resend, all 15 platforms
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Template Deployment Commands
|
||||||
|
|
||||||
|
### Deploy Everything
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# ONE COMMAND TO RULE THEM ALL
|
||||||
|
./deploy-all-templates-everywhere.sh
|
||||||
|
|
||||||
|
# What it does:
|
||||||
|
# ✅ Syncs templates to all 43 GitHub repos
|
||||||
|
# ✅ Imports templates to Google Drive
|
||||||
|
# ✅ Imports templates to Notion
|
||||||
|
# ✅ Imports templates to Linear/Jira/Asana
|
||||||
|
# ✅ Imports templates to Airtable
|
||||||
|
# ✅ Generates all 5,216 subdomain pages
|
||||||
|
# ✅ Deploys all subdomains to Cloudflare Pages
|
||||||
|
# ✅ Updates all Railway services
|
||||||
|
# ✅ Updates all Vercel projects
|
||||||
|
# ✅ Verifies all deployments
|
||||||
|
# ✅ Generates usage report
|
||||||
|
|
||||||
|
# Time: ~15 minutes
|
||||||
|
# Result: EVERYTHING updated across ALL platforms!
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 Template Documentation
|
||||||
|
|
||||||
|
Each template includes:
|
||||||
|
|
||||||
|
1. **Header Comment**
|
||||||
|
```
|
||||||
|
# ============================================================================
|
||||||
|
# Template: README-TEMPLATE.md
|
||||||
|
# Purpose: Perfect README for any BlackRoad OS repository
|
||||||
|
# Variables: PROJECT_NAME, DESCRIPTION, REPO_URL, AUTHOR
|
||||||
|
# Last Updated: 2025-12-12
|
||||||
|
# ============================================================================
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Usage Instructions**
|
||||||
|
- How to use the template
|
||||||
|
- Required variables
|
||||||
|
- Optional customizations
|
||||||
|
- Example output
|
||||||
|
|
||||||
|
3. **Customization Guide**
|
||||||
|
- Which sections to customize
|
||||||
|
- Which to keep as-is
|
||||||
|
- Best practices
|
||||||
|
|
||||||
|
4. **Examples**
|
||||||
|
- Real-world examples from existing repos
|
||||||
|
- Before/after comparisons
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎉 Template Benefits
|
||||||
|
|
||||||
|
### Developer Experience
|
||||||
|
- **10x faster** project setup
|
||||||
|
- **Zero boilerplate** writing
|
||||||
|
- **Consistent quality** across all projects
|
||||||
|
- **Always up-to-date** with latest practices
|
||||||
|
|
||||||
|
### Team Collaboration
|
||||||
|
- **Shared knowledge** embedded in templates
|
||||||
|
- **Onboarding time** cut from days to minutes
|
||||||
|
- **Code review** faster with consistent structure
|
||||||
|
- **Documentation** always complete
|
||||||
|
|
||||||
|
### Deployment Speed
|
||||||
|
- **New subdomain**: < 1 minute
|
||||||
|
- **New repo**: < 5 minutes
|
||||||
|
- **New integration**: < 2 minutes
|
||||||
|
- **Complete project**: < 15 minutes
|
||||||
|
|
||||||
|
### Maintenance
|
||||||
|
- **One update** propagates everywhere
|
||||||
|
- **No drift** between projects
|
||||||
|
- **Automated sync** keeps everything current
|
||||||
|
- **Version control** for all templates
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔥 Advanced Template Features
|
||||||
|
|
||||||
|
### Template Inheritance
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# base-service-template.yaml
|
||||||
|
base: PYTHON-SERVICE-TEMPLATE
|
||||||
|
extends:
|
||||||
|
- auth-mixin
|
||||||
|
- database-mixin
|
||||||
|
- stripe-mixin
|
||||||
|
- clerk-mixin
|
||||||
|
```
|
||||||
|
|
||||||
|
### Template Composition
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Combine multiple templates
|
||||||
|
./compose-template.sh \
|
||||||
|
--base="PYTHON-SERVICE-TEMPLATE" \
|
||||||
|
--add="AUTH-MIXIN" \
|
||||||
|
--add="STRIPE-MIXIN" \
|
||||||
|
--add="WEBSOCKET-MIXIN" \
|
||||||
|
--output="my-custom-service.py"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Template Generation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Generate new template from existing code
|
||||||
|
./generate-template.sh \
|
||||||
|
--from="blackroad-agent-orchestrator.py" \
|
||||||
|
--name="AGENT-SERVICE-TEMPLATE" \
|
||||||
|
--extract-patterns
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📖 Template Index
|
||||||
|
|
||||||
|
See `TEMPLATE-INDEX.md` for complete catalog of all 200+ templates with:
|
||||||
|
- Description
|
||||||
|
- Usage examples
|
||||||
|
- Variables
|
||||||
|
- Customization options
|
||||||
|
- Related templates
|
||||||
|
- Example output
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Next Steps
|
||||||
|
|
||||||
|
1. **Browse Templates**: `ls -R templates/`
|
||||||
|
2. **Use a Template**: Copy & customize
|
||||||
|
3. **Create New Template**: Follow the template-template 😉
|
||||||
|
4. **Share Template**: PR to blackroad-sandbox/templates/
|
||||||
|
5. **Deploy Templates**: Run sync scripts
|
||||||
|
|
||||||
|
**The goal**: Never write boilerplate again. Ever. 🚀
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📞 Template Support
|
||||||
|
|
||||||
|
- **Issues**: Use GitHub template issue template 😄
|
||||||
|
- **Questions**: blackroad.systems@gmail.com
|
||||||
|
- **Contributions**: PR welcome for new templates!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Remember**: A perfect template is one you never have to think about. It just works. ✨
|
||||||
389
templates/README-TEMPLATE.md
Normal file
389
templates/README-TEMPLATE.md
Normal file
@@ -0,0 +1,389 @@
|
|||||||
|
# [Service/Feature Name]
|
||||||
|
|
||||||
|
**One-line description of what this does**
|
||||||
|
|
||||||
|
## Quick Start (Copy-Paste Ready)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clone and setup
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
git pull origin main
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
pip3 install -r requirements.txt
|
||||||
|
|
||||||
|
# Start service
|
||||||
|
PORT=8000 python3 blackroad-service.py
|
||||||
|
|
||||||
|
# Verify it's running
|
||||||
|
curl http://localhost:8000/health
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## What This Does
|
||||||
|
|
||||||
|
[2-3 sentence explanation of purpose and value]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### Local Development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Navigate to project
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
|
||||||
|
# Install Python dependencies
|
||||||
|
pip3 install -r requirements.txt
|
||||||
|
|
||||||
|
# Copy environment template
|
||||||
|
cp .env.example .env
|
||||||
|
|
||||||
|
# Add your secrets
|
||||||
|
cat >> .env <<'EOF'
|
||||||
|
SERVICE_TOKEN=your-token-here
|
||||||
|
API_KEY=your-key-here
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Verify installation
|
||||||
|
python3 -c "import flask; print('✅ Dependencies installed')"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build image
|
||||||
|
docker build -t blackroad-service .
|
||||||
|
|
||||||
|
# Run container
|
||||||
|
docker run -p 8000:8000 --env-file .env blackroad-service
|
||||||
|
|
||||||
|
# Verify
|
||||||
|
curl http://localhost:8000/health
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Start the Service
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Development mode
|
||||||
|
PORT=8000 python3 blackroad-service.py
|
||||||
|
|
||||||
|
# Production mode
|
||||||
|
FLASK_ENV=production PORT=8000 python3 blackroad-service.py
|
||||||
|
|
||||||
|
# With Docker Compose
|
||||||
|
docker-compose up -d service-name
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test the Service
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Health check
|
||||||
|
curl http://localhost:8000/health
|
||||||
|
|
||||||
|
# Test specific endpoint
|
||||||
|
curl http://localhost:8000/api/resource -X POST -H "Content-Type: application/json" -d '{"key":"value"}'
|
||||||
|
|
||||||
|
# Run automated tests
|
||||||
|
pytest tests/test_service.py -v
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deploy to Production
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deploy to Railway
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
railway up --service service-name
|
||||||
|
|
||||||
|
# Deploy to Cloudflare
|
||||||
|
cd cloudflare-workers
|
||||||
|
wrangler deploy service.js --config wrangler-service.toml
|
||||||
|
|
||||||
|
# Verify deployment
|
||||||
|
curl https://service.blackroad.io/health
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API Reference
|
||||||
|
|
||||||
|
### Endpoints
|
||||||
|
|
||||||
|
#### `GET /health`
|
||||||
|
|
||||||
|
Health check endpoint.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Example
|
||||||
|
curl http://localhost:8000/health
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"ok": true,
|
||||||
|
"service": "service-name",
|
||||||
|
"version": "1.0.0"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `POST /api/resource`
|
||||||
|
|
||||||
|
Create a new resource.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Example
|
||||||
|
curl http://localhost:8000/api/resource \
|
||||||
|
-X POST \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"name":"example","value":42}'
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"ok": true,
|
||||||
|
"resource_id": "abc123"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Required
|
||||||
|
SERVICE_TOKEN=your-service-token
|
||||||
|
API_KEY=your-api-key
|
||||||
|
|
||||||
|
# Optional
|
||||||
|
PORT=8000
|
||||||
|
LOG_LEVEL=info
|
||||||
|
ENVIRONMENT=production
|
||||||
|
```
|
||||||
|
|
||||||
|
### Config Files
|
||||||
|
|
||||||
|
- `.env` - Environment variables
|
||||||
|
- `config.yaml` - Service configuration
|
||||||
|
- `railway.toml` - Railway deployment config
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
### Running Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# All tests
|
||||||
|
pytest -v
|
||||||
|
|
||||||
|
# Unit tests only
|
||||||
|
pytest -m unit -v
|
||||||
|
|
||||||
|
# Integration tests
|
||||||
|
pytest -m integration -v
|
||||||
|
|
||||||
|
# With coverage
|
||||||
|
pytest --cov=. --cov-report=html
|
||||||
|
open coverage_html/index.html
|
||||||
|
```
|
||||||
|
|
||||||
|
### Local Development Workflow
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Create feature branch
|
||||||
|
git checkout -b feature/new-feature
|
||||||
|
|
||||||
|
# 2. Make changes
|
||||||
|
# Edit files...
|
||||||
|
|
||||||
|
# 3. Test locally
|
||||||
|
pytest -v
|
||||||
|
python3 blackroad-service.py
|
||||||
|
|
||||||
|
# 4. Commit
|
||||||
|
git add .
|
||||||
|
git commit -m "feat: Add new feature"
|
||||||
|
|
||||||
|
# 5. Push
|
||||||
|
git push -u origin feature/new-feature
|
||||||
|
|
||||||
|
# 6. Create PR
|
||||||
|
gh pr create --title "Add new feature" --body "Description"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
### Railway
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Link to project
|
||||||
|
railway link 0c7bcf07-307b-4db6-9c94-22a456500d68
|
||||||
|
|
||||||
|
# Deploy
|
||||||
|
railway up --service service-name
|
||||||
|
|
||||||
|
# Check status
|
||||||
|
railway status
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
railway logs --tail 100
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cloudflare Pages/Workers
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deploy worker
|
||||||
|
cd cloudflare-workers
|
||||||
|
wrangler deploy service.js --config wrangler-service.toml
|
||||||
|
|
||||||
|
# Deploy page
|
||||||
|
cd domains/domain-name
|
||||||
|
wrangler pages deploy . --project-name=domain-name
|
||||||
|
|
||||||
|
# Check deployment
|
||||||
|
wrangler pages deployment list --project-name=domain-name
|
||||||
|
```
|
||||||
|
|
||||||
|
### Vercel
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deploy
|
||||||
|
cd vercel-projects/project-name
|
||||||
|
vercel --prod
|
||||||
|
|
||||||
|
# Check deployment
|
||||||
|
vercel ls
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Service Won't Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check if port is in use
|
||||||
|
lsof -i :8000
|
||||||
|
|
||||||
|
# Kill existing process
|
||||||
|
kill -9 $(lsof -t -i:8000)
|
||||||
|
|
||||||
|
# Restart service
|
||||||
|
PORT=8000 python3 blackroad-service.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### Import Errors
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Reinstall dependencies
|
||||||
|
pip3 install -r requirements.txt --force-reinstall
|
||||||
|
|
||||||
|
# Verify Python version
|
||||||
|
python3 --version # Should be 3.11+
|
||||||
|
|
||||||
|
# Check imports
|
||||||
|
python3 -c "import flask; print('✅ Flask OK')"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Environment Variables Not Loaded
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check .env exists
|
||||||
|
ls -la .env
|
||||||
|
|
||||||
|
# Source manually
|
||||||
|
source .env
|
||||||
|
|
||||||
|
# Verify variables
|
||||||
|
echo $SERVICE_TOKEN
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deployment Failed
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Railway
|
||||||
|
railway logs --tail 100
|
||||||
|
railway status
|
||||||
|
railway variables # Check secrets are set
|
||||||
|
|
||||||
|
# Cloudflare
|
||||||
|
wrangler tail # View live logs
|
||||||
|
wrangler pages deployment list --project-name=PROJECT_NAME
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
[Diagram or description of how this service fits into the larger system]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Fork/clone
|
||||||
|
git clone https://github.com/BlackRoad-OS/repo-name.git
|
||||||
|
|
||||||
|
# 2. Create branch
|
||||||
|
git checkout -b feature/your-feature
|
||||||
|
|
||||||
|
# 3. Make changes and test
|
||||||
|
pytest -v
|
||||||
|
|
||||||
|
# 4. Commit with conventional commits
|
||||||
|
git commit -m "feat: Add your feature"
|
||||||
|
|
||||||
|
# 5. Push
|
||||||
|
git push -u origin feature/your-feature
|
||||||
|
|
||||||
|
# 6. Create PR
|
||||||
|
gh pr create
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
```
|
||||||
|
# ============================================================================
|
||||||
|
# BlackRoad OS - Proprietary Software
|
||||||
|
# Copyright (c) 2025 BlackRoad OS, Inc. / Alexa Louise Amundson
|
||||||
|
# All Rights Reserved.
|
||||||
|
# ============================================================================
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
- **Email**: blackroad.systems@gmail.com
|
||||||
|
- **Docs**: [Link to docs]
|
||||||
|
- **Issues**: [Link to GitHub issues]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Related Services
|
||||||
|
|
||||||
|
- [Service 1](link) - Description
|
||||||
|
- [Service 2](link) - Description
|
||||||
|
- [Service 3](link) - Description
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Quick Links**:
|
||||||
|
- [API Documentation](link)
|
||||||
|
- [Deployment Guide](link)
|
||||||
|
- [Troubleshooting](link)
|
||||||
318
templates/SCRIPT-TEMPLATE.sh
Executable file
318
templates/SCRIPT-TEMPLATE.sh
Executable file
@@ -0,0 +1,318 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# ============================================================================
|
||||||
|
# BlackRoad OS - Proprietary Software
|
||||||
|
# Copyright (c) 2025 BlackRoad OS, Inc. / Alexa Louise Amundson
|
||||||
|
# All Rights Reserved.
|
||||||
|
# ============================================================================
|
||||||
|
#
|
||||||
|
# [Script Name]
|
||||||
|
# [One-line description of what this script does]
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./script-name.sh # Interactive menu mode
|
||||||
|
# ./script-name.sh [command] [args] # Direct command mode
|
||||||
|
# ./script-name.sh --help # Show help
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
# ./script-name.sh deploy # Deploy service
|
||||||
|
# ./script-name.sh status # Check status
|
||||||
|
# ./script-name.sh logs # View logs
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Configuration
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
PROJECT_ROOT="${SCRIPT_DIR}"
|
||||||
|
LOG_FILE="${PROJECT_ROOT}/script-name.log"
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Helper Functions
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo -e "${GREEN}✓${NC} $1"
|
||||||
|
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
echo -e "${RED}✗${NC} $1" >&2
|
||||||
|
echo "[$(date +'%Y-%m-%d %H:%M:%S')] ERROR: $1" >> "$LOG_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
warn() {
|
||||||
|
echo -e "${YELLOW}⚠${NC} $1"
|
||||||
|
echo "[$(date +'%Y-%m-%d %H:%M:%S')] WARN: $1" >> "$LOG_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
info() {
|
||||||
|
echo -e "${BLUE}ℹ${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if command exists
|
||||||
|
command_exists() {
|
||||||
|
command -v "$1" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check prerequisites
|
||||||
|
check_prerequisites() {
|
||||||
|
log "Checking prerequisites..."
|
||||||
|
|
||||||
|
local missing=0
|
||||||
|
|
||||||
|
if ! command_exists "python3"; then
|
||||||
|
error "python3 not found"
|
||||||
|
missing=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command_exists "git"; then
|
||||||
|
error "git not found"
|
||||||
|
missing=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $missing -eq 1 ]; then
|
||||||
|
error "Missing required dependencies"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "All prerequisites met"
|
||||||
|
}
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Command Functions
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
cmd_deploy() {
|
||||||
|
log "Starting deployment..."
|
||||||
|
|
||||||
|
# Example deployment steps
|
||||||
|
cd "$PROJECT_ROOT"
|
||||||
|
|
||||||
|
# Pull latest code
|
||||||
|
log "Pulling latest code..."
|
||||||
|
git pull origin main
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
log "Installing dependencies..."
|
||||||
|
pip3 install -r requirements.txt
|
||||||
|
|
||||||
|
# Deploy to platform
|
||||||
|
log "Deploying to platform..."
|
||||||
|
railway up --service service-name
|
||||||
|
|
||||||
|
# Verify deployment
|
||||||
|
log "Verifying deployment..."
|
||||||
|
sleep 5
|
||||||
|
railway status
|
||||||
|
|
||||||
|
log "Deployment complete!"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_status() {
|
||||||
|
log "Checking status..."
|
||||||
|
|
||||||
|
# Check local services
|
||||||
|
info "Local services:"
|
||||||
|
pgrep -f "python3.*blackroad" | while read pid; do
|
||||||
|
echo " PID $pid: $(ps -p $pid -o command=)"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check Railway
|
||||||
|
if command_exists "railway"; then
|
||||||
|
info "Railway status:"
|
||||||
|
railway status
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check health endpoints
|
||||||
|
info "Health checks:"
|
||||||
|
curl -sf http://localhost:8000/health && echo " ✅ Local API" || echo " ❌ Local API"
|
||||||
|
curl -sf https://api.blackroad.io/health && echo " ✅ Production API" || echo " ❌ Production API"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_logs() {
|
||||||
|
log "Viewing logs..."
|
||||||
|
|
||||||
|
# Show local log
|
||||||
|
if [ -f "$LOG_FILE" ]; then
|
||||||
|
tail -n 50 "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Show Railway logs if available
|
||||||
|
if command_exists "railway"; then
|
||||||
|
info "Railway logs:"
|
||||||
|
railway logs --tail 50
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_start() {
|
||||||
|
log "Starting services..."
|
||||||
|
|
||||||
|
cd "$PROJECT_ROOT"
|
||||||
|
|
||||||
|
# Start service in background
|
||||||
|
PORT=8000 python3 blackroad-service.py &
|
||||||
|
|
||||||
|
# Wait for startup
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
# Verify
|
||||||
|
curl -sf http://localhost:8000/health && log "Service started successfully" || error "Service failed to start"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_stop() {
|
||||||
|
log "Stopping services..."
|
||||||
|
|
||||||
|
# Kill all matching processes
|
||||||
|
pkill -f "python3.*blackroad-service" || warn "No processes found"
|
||||||
|
|
||||||
|
log "Services stopped"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_test() {
|
||||||
|
log "Running tests..."
|
||||||
|
|
||||||
|
cd "$PROJECT_ROOT"
|
||||||
|
|
||||||
|
# Run unit tests
|
||||||
|
pytest -m unit -v
|
||||||
|
|
||||||
|
# Run integration tests
|
||||||
|
pytest -m integration -v
|
||||||
|
|
||||||
|
log "Tests complete"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_clean() {
|
||||||
|
log "Cleaning up..."
|
||||||
|
|
||||||
|
cd "$PROJECT_ROOT"
|
||||||
|
|
||||||
|
# Remove cache files
|
||||||
|
find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
|
||||||
|
find . -type f -name "*.pyc" -delete 2>/dev/null || true
|
||||||
|
|
||||||
|
# Remove log files
|
||||||
|
rm -f "$LOG_FILE"
|
||||||
|
|
||||||
|
log "Cleanup complete"
|
||||||
|
}
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Menu Functions
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
show_menu() {
|
||||||
|
echo ""
|
||||||
|
echo "╔════════════════════════════════════════╗"
|
||||||
|
echo "║ [Service Name] Management ║"
|
||||||
|
echo "╚════════════════════════════════════════╝"
|
||||||
|
echo ""
|
||||||
|
echo "Commands:"
|
||||||
|
echo " 1) deploy - Deploy to production"
|
||||||
|
echo " 2) status - Check service status"
|
||||||
|
echo " 3) logs - View logs"
|
||||||
|
echo " 4) start - Start local service"
|
||||||
|
echo " 5) stop - Stop local service"
|
||||||
|
echo " 6) test - Run tests"
|
||||||
|
echo " 7) clean - Clean up files"
|
||||||
|
echo " q) quit - Exit"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
interactive_menu() {
|
||||||
|
while true; do
|
||||||
|
show_menu
|
||||||
|
read -rp "Choose command: " choice
|
||||||
|
|
||||||
|
case $choice in
|
||||||
|
1|deploy) cmd_deploy ;;
|
||||||
|
2|status) cmd_status ;;
|
||||||
|
3|logs) cmd_logs ;;
|
||||||
|
4|start) cmd_start ;;
|
||||||
|
5|stop) cmd_stop ;;
|
||||||
|
6|test) cmd_test ;;
|
||||||
|
7|clean) cmd_clean ;;
|
||||||
|
q|quit) log "Goodbye!"; exit 0 ;;
|
||||||
|
*) error "Invalid choice: $choice" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
read -rp "Press Enter to continue..."
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Help Function
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
show_help() {
|
||||||
|
cat <<EOF
|
||||||
|
[Script Name] - [Description]
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
$0 [command] [args]
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
deploy Deploy to production
|
||||||
|
status Check service status
|
||||||
|
logs View logs
|
||||||
|
start Start local service
|
||||||
|
stop Stop local service
|
||||||
|
test Run tests
|
||||||
|
clean Clean up files
|
||||||
|
menu Show interactive menu (default)
|
||||||
|
help Show this help message
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
$0 # Interactive menu mode
|
||||||
|
$0 deploy # Deploy to production
|
||||||
|
$0 status # Check status
|
||||||
|
$0 logs # View logs
|
||||||
|
|
||||||
|
Environment Variables:
|
||||||
|
RAILWAY_TOKEN Railway API token (required for deploy)
|
||||||
|
PORT Service port (default: 8000)
|
||||||
|
|
||||||
|
For more information, see README.md
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Main Script Logic
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
main() {
|
||||||
|
# Check prerequisites
|
||||||
|
check_prerequisites
|
||||||
|
|
||||||
|
# Handle command
|
||||||
|
case "${1:-menu}" in
|
||||||
|
deploy) cmd_deploy ;;
|
||||||
|
status) cmd_status ;;
|
||||||
|
logs) cmd_logs ;;
|
||||||
|
start) cmd_start ;;
|
||||||
|
stop) cmd_stop ;;
|
||||||
|
test) cmd_test ;;
|
||||||
|
clean) cmd_clean ;;
|
||||||
|
menu|"") interactive_menu ;;
|
||||||
|
-h|--help|help) show_help ;;
|
||||||
|
*)
|
||||||
|
error "Unknown command: $1"
|
||||||
|
echo ""
|
||||||
|
show_help
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run main function
|
||||||
|
main "$@"
|
||||||
79
templates/TEMPLATE-001-INFRA-RUNBOOK.md
Normal file
79
templates/TEMPLATE-001-INFRA-RUNBOOK.md
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
╭━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╮
|
||||||
|
│ ⛅️🛣 BLACKROAD OS · <PROJECT / RUNBOOK TITLE> │
|
||||||
|
╰━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╯
|
||||||
|
|
||||||
|
<CTX_EMOJI> <TOOL_NAME> <VERSION> · env: <ENV> · region: <REGION>
|
||||||
|
────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
╭────────── WORKER / SERVICE BINDINGS 📦 ────────────────────╮
|
||||||
|
│ Binding │ Resource │
|
||||||
|
├──────────────────┼────────────────────────────────────────┤
|
||||||
|
│ <binding-name> │ <resource-type> │
|
||||||
|
│ <binding-name> │ <resource-type> │
|
||||||
|
│ <binding-name> │ <resource-type> │
|
||||||
|
╰────────────────────────────────────────────────────────────╯
|
||||||
|
|
||||||
|
|
||||||
|
╭────────── INFRASTRUCTURE STATUS 📡 ───────────────────────╮
|
||||||
|
│ ✅ <RES_LABEL_1> <value/limits/notes> │
|
||||||
|
│ ✅ <RES_LABEL_2> <value/limits/notes> │
|
||||||
|
│ ⏳ <RES_LABEL_3> <pending condition> │
|
||||||
|
│ ⚠️ <RES_LABEL_4> <warning condition> │
|
||||||
|
╰────────────────────────────────────────────────────────────╯
|
||||||
|
|
||||||
|
|
||||||
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
🚀 EXECUTE THE <N> STEPS
|
||||||
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||||
|
|
||||||
|
[1] <STEP_TITLE_1> <(optional short description)>
|
||||||
|
<primary command(s)>
|
||||||
|
<secondary command(s)>
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
[2] <STEP_TITLE_2>
|
||||||
|
<commands…>
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
[3] <STEP_TITLE_3>
|
||||||
|
<commands…>
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
[<N>] <FINAL_STEP_TITLE>
|
||||||
|
<commands…>
|
||||||
|
|
||||||
|
|
||||||
|
╭────────── VALUE DELIVERED 💎 ─────────────────────────────╮
|
||||||
|
│ <RES_SUMMARY_1> → ~<$ESTIMATED_VALUE_1>/month │
|
||||||
|
│ <RES_SUMMARY_2> → ~<$ESTIMATED_VALUE_2>/month │
|
||||||
|
│ <RES_SUMMARY_3> → ~<$ESTIMATED_VALUE_3>/month │
|
||||||
|
├───────────────────────────────────────────────────────────┤
|
||||||
|
│ TOTAL → ~<$TOTAL_ESTIMATED_VALUE>/month │
|
||||||
|
│ YOU PAY $<ACTUAL_COST>/month │
|
||||||
|
╰────────────────────────────────────────────────────────────╯
|
||||||
|
|
||||||
|
|
||||||
|
📚 Documentation
|
||||||
|
- 📘 API / Worker: <FILE_OR_URL_1>
|
||||||
|
- 📙 Deployment Guide: <FILE_OR_URL_2>
|
||||||
|
- 📕 Policies / Limits: <FILE_OR_URL_3>
|
||||||
|
|
||||||
|
🗒 Checklist
|
||||||
|
- ☐ <Prereq 1>
|
||||||
|
- ☐ <Prereq 2>
|
||||||
|
- ☐ <Verify step 1>
|
||||||
|
- ☐ <Verify step 2>
|
||||||
|
|
||||||
|
🎯 Next Steps
|
||||||
|
1. <Immediate action after running this>
|
||||||
|
2. <Follow-up configuration / wiring>
|
||||||
|
3. <Optional optimization / observability>
|
||||||
|
|
||||||
|
💡 Tips
|
||||||
|
- <short pro tip #1>
|
||||||
|
- <short pro tip #2>
|
||||||
|
|
||||||
|
╭━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╮
|
||||||
|
│ 🔥 <EPIC_DONE_LINE_SUMMARY> │
|
||||||
|
│ (e.g. "ALL RESOURCES READY · JUST RUN THE N STEPS 💎") │
|
||||||
|
╰━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╯
|
||||||
165
templates/TEMPLATE-002-ARCHITECTURE-OVERVIEW.md
Normal file
165
templates/TEMPLATE-002-ARCHITECTURE-OVERVIEW.md
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
╭━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╮
|
||||||
|
│ 🛣 <CTX_EMOJI> BLACKROAD OS · <SYSTEM / ARCH NAME> │
|
||||||
|
╰━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╯
|
||||||
|
|
||||||
|
🧭 Overview
|
||||||
|
────────────────────────────────────────────────────────────
|
||||||
|
<2–5 lines: What this system is, who it serves, and why it exists.>
|
||||||
|
Example:
|
||||||
|
- Serves: <who> (👤 / 👥)
|
||||||
|
- Core job: <what it does>
|
||||||
|
- Scope: <boundaries / what it is NOT>
|
||||||
|
|
||||||
|
|
||||||
|
🏗 High-Level System Diagram
|
||||||
|
────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
👤 Users / Clients
|
||||||
|
│ (https)
|
||||||
|
▼
|
||||||
|
╭────────────────────────────────────────────────────────────╮
|
||||||
|
│ ⛅️ Edge / Gateway (Cloudflare Workers / Router) │
|
||||||
|
│ - Routing, auth checks, rate limiting │
|
||||||
|
╰───────────────┬─────────────────────────────┬──────────────╯
|
||||||
|
│ │
|
||||||
|
▼ ▼
|
||||||
|
🛰 Service A 🛰 Service B
|
||||||
|
(API / Unified API) (Web / Pages / UI)
|
||||||
|
│ │
|
||||||
|
└──────────────┬──────────────┘
|
||||||
|
▼
|
||||||
|
🧱 Databases
|
||||||
|
📨 Queues
|
||||||
|
🗂 Storage (R2 / KV)
|
||||||
|
|
||||||
|
<Adjust the boxes/lines to match your exact topology.>
|
||||||
|
|
||||||
|
|
||||||
|
📦 Component Breakdown
|
||||||
|
────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
⛅️ Edge / Gateway
|
||||||
|
- Type: <Worker / Router / CDN>
|
||||||
|
- Responsibilities:
|
||||||
|
- <bullet 1>
|
||||||
|
- <bullet 2>
|
||||||
|
- Key resources:
|
||||||
|
- 📦 <artifact name>
|
||||||
|
- 🔑 <secret / binding>
|
||||||
|
- 🌐 <domains / routes>
|
||||||
|
|
||||||
|
🛰 Core Services
|
||||||
|
- Service A (🛰 <name>)
|
||||||
|
- Purpose: <short description>
|
||||||
|
- Interfaces: <HTTP/WS/queues/etc.>
|
||||||
|
- Talks to: <DBs, queues, other services>
|
||||||
|
- Service B (🛰 <name>)
|
||||||
|
- Purpose: ...
|
||||||
|
- Interfaces: ...
|
||||||
|
|
||||||
|
🧱 Data Layer
|
||||||
|
- Databases (🧱)
|
||||||
|
- <DB name> – <what it stores>, <scale expectations>
|
||||||
|
- Queues (📨)
|
||||||
|
- <Queue name> – <what flows through it>
|
||||||
|
- Storage (🗂 / R2 / KV)
|
||||||
|
- <Bucket / KV namespace> – <what lives here>
|
||||||
|
|
||||||
|
🧩 External Integrations
|
||||||
|
- Stripe (💳)
|
||||||
|
- Used for: <billing/payments>
|
||||||
|
- Auth provider (🔐)
|
||||||
|
- Used for: <authN/authZ>
|
||||||
|
- Other (🧩)
|
||||||
|
- <Integration> – <role>
|
||||||
|
|
||||||
|
|
||||||
|
👉 Request / Data Flows
|
||||||
|
────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
Flow 1 – User Request
|
||||||
|
1. 👤 User → 🌐 <domain> (e.g. https://...)
|
||||||
|
2. 🌐 DNS → ⛅️ Edge (Cloudflare)
|
||||||
|
3. ⛅️ Edge → 🛰 Service A (unified API)
|
||||||
|
4. 🛰 Service A → 🧱 DB / 📨 Queue / 🗂 Storage
|
||||||
|
5. Response travels back ⛅️ → 👤
|
||||||
|
|
||||||
|
Flow 2 – Background Processing
|
||||||
|
1. 🧱 DB / 📨 Queue event occurs
|
||||||
|
2. 🛰 Worker / cron picks it up
|
||||||
|
3. 🧠 Optional 🤖 AI/LLM processing
|
||||||
|
4. Results written to 🧱 / 🗂 / 📊
|
||||||
|
|
||||||
|
Flow 3 – Admin / Dashboards
|
||||||
|
1. 👩💻 Operator → 🖥 Dashboard
|
||||||
|
2. Dashboard calls ⛅️ Edge → 🛰 Admin API
|
||||||
|
3. Observability from 📊 Metrics / 🧾 Logs
|
||||||
|
|
||||||
|
|
||||||
|
🔐 Reliability, Security & Limits
|
||||||
|
────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
Reliability
|
||||||
|
- Target: <e.g. 99.9% uptime>
|
||||||
|
- Single points of failure: <where and how mitigated>
|
||||||
|
- 🧯 Fallback / degradation strategy: <how it fails gracefully>
|
||||||
|
|
||||||
|
Security
|
||||||
|
- Auth (🔐): <how users/clients authenticate>
|
||||||
|
- Secrets (🔑): <where secrets are stored>
|
||||||
|
- Data protection: <encryption at rest / in transit>
|
||||||
|
|
||||||
|
Limits & Quotas
|
||||||
|
- Request limits: <Cloudflare free tier, etc.>
|
||||||
|
- Storage limits: <R2 / KV / D1 limits>
|
||||||
|
- Scaling behavior:
|
||||||
|
- ⛅️ Edge: <auto / manual>
|
||||||
|
- 🛰 Services: <horizontal/vertical>
|
||||||
|
|
||||||
|
(Reference to specific Cloudflare docs / constraints if relevant.)
|
||||||
|
|
||||||
|
|
||||||
|
🧰 Operations: Deploy, Observe, Debug
|
||||||
|
────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
Deploy (🚀)
|
||||||
|
- Primary script / command:
|
||||||
|
- `./<deploy-script>.sh`
|
||||||
|
- Manual steps (if any):
|
||||||
|
- ☐ <step 1>
|
||||||
|
- ☐ <step 2>
|
||||||
|
|
||||||
|
Observe (📊 / 🧾)
|
||||||
|
- Metrics (📊):
|
||||||
|
- <link / command> – e.g. dashboard URL
|
||||||
|
- Logs (🧾):
|
||||||
|
- `wrangler tail <worker-name>`
|
||||||
|
- `<other log sources>`
|
||||||
|
|
||||||
|
Debug (🔍 / 🕵️)
|
||||||
|
- Common failure modes:
|
||||||
|
- <symptom> → <likely cause> → <fix>
|
||||||
|
- Incident severity mapping (🚨):
|
||||||
|
- <what counts as Sev1 / Sev2, etc.>
|
||||||
|
|
||||||
|
|
||||||
|
📚 Documentation & References
|
||||||
|
────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
📚 System Docs
|
||||||
|
- Overview: <FILE_OR_URL>
|
||||||
|
- API Reference: <FILE_OR_URL>
|
||||||
|
- Runbooks: <FILE_OR_URL>
|
||||||
|
|
||||||
|
🗒 Checklists
|
||||||
|
- Deploy checklist: <FILE_OR_URL>
|
||||||
|
- Onboarding checklist: <FILE_OR_URL>
|
||||||
|
|
||||||
|
🎯 Next Steps
|
||||||
|
- <Step 1: what reader should do first>
|
||||||
|
- <Step 2: where to go deeper>
|
||||||
|
- <Step 3: optional advanced topic>
|
||||||
|
|
||||||
|
💡 Tips
|
||||||
|
- <Tip 1: e.g. "If X happens, check Y first">
|
||||||
|
- <Tip 2: e.g. "Prefer Z pattern when adding new services">
|
||||||
77
templates/TEMPLATE-003-DOMAIN-DNS-ROUTING.md
Normal file
77
templates/TEMPLATE-003-DOMAIN-DNS-ROUTING.md
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
╭━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╮
|
||||||
|
│ 🌐🛣 DOMAIN CARD · <DOMAIN_NAME> │
|
||||||
|
╰━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╯
|
||||||
|
|
||||||
|
🧭 Overview
|
||||||
|
────────────────────────────────────────────────────────────
|
||||||
|
- Domain: `<DOMAIN_NAME>`
|
||||||
|
- Purpose: <what this domain is for>
|
||||||
|
- Owners (👥): <team / person>
|
||||||
|
- Environment(s): <env_prod / env_staging / etc.>
|
||||||
|
|
||||||
|
|
||||||
|
📡 Routing & Services
|
||||||
|
────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
Primary Entry
|
||||||
|
- 🌐 Hostname: `<host or wildcard>` (e.g. `*.blackroad.io`)
|
||||||
|
- ⛅️ Edge: `<Cloudflare zone / worker>` (e.g. `blackroad-edge-router`)
|
||||||
|
|
||||||
|
Services Behind This Domain
|
||||||
|
- 🛰 <service_name_1> – <description>
|
||||||
|
- Path(s): `/api/...`, `/auth/...`
|
||||||
|
- Env: <env>
|
||||||
|
- 🛰 <service_name_2> – <description>
|
||||||
|
- Path(s): `/`, `/dashboard`
|
||||||
|
|
||||||
|
Traffic Rules (🔀)
|
||||||
|
- Rule 1: `<condition>` → `<target>`
|
||||||
|
- Rule 2: `<condition>` → `<target>`
|
||||||
|
|
||||||
|
|
||||||
|
🧱 DNS Records
|
||||||
|
────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
Code-ish view:
|
||||||
|
|
||||||
|
TYPE NAME VALUE / TARGET TTL NOTES
|
||||||
|
A <name> <ip or proxy> auto <note>
|
||||||
|
AAAA <name> <ipv6 or proxy> auto <note>
|
||||||
|
CNAME <name> <target.domain.com> auto <note>
|
||||||
|
TXT <name> <value> auto <SPF/verification/etc.>
|
||||||
|
|
||||||
|
Human view:
|
||||||
|
- 🌐 Root (<DOMAIN_NAME>) → <target> (e.g. Cloudflare worker/pages)
|
||||||
|
- 🌐 *.subdomain → <target>
|
||||||
|
- 🔏 TLS: <Full/Strict/Flexible>
|
||||||
|
|
||||||
|
🧪 Verification & Health
|
||||||
|
────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
Status
|
||||||
|
- DNS Resolution (🌐): ✅ / ⚠️ / ❌
|
||||||
|
- HTTPS (🔐): ✅ / ⚠️ / ❌
|
||||||
|
- Latency (⏱): ~<ms> global
|
||||||
|
|
||||||
|
How to Verify (🔍)
|
||||||
|
- DNS: dig <domain> / nslookup <domain>
|
||||||
|
- HTTPS: visit https://<domain> and check cert
|
||||||
|
- Worker: wrangler tail <worker> or health endpoint
|
||||||
|
|
||||||
|
Common Issues (🚨)
|
||||||
|
- Symptom: <issue> → Likely: <cause> → Fix: <action>
|
||||||
|
|
||||||
|
📚 Links
|
||||||
|
────────────────────────────────────────────────────────────
|
||||||
|
- Cloudflare zone: <URL>
|
||||||
|
- Worker / Pages config: <FILE>
|
||||||
|
- Related project: projects/<proj_name>/project.md
|
||||||
|
- Runbook: projects/<proj_name>/runbook.md
|
||||||
|
|
||||||
|
🎯 Next Steps
|
||||||
|
- <Step 1: e.g. "Enable HTTPS on staging subdomain">
|
||||||
|
- <Step 2: e.g. "Migrate root domain to new router">
|
||||||
|
|
||||||
|
💡 Tips
|
||||||
|
- <keep this domain's use narrow / don't mix X with Y>
|
||||||
|
- <DNS changes can take up to N minutes to propagate>
|
||||||
431
templates/TEMPLATE-INDEX.md
Normal file
431
templates/TEMPLATE-INDEX.md
Normal file
@@ -0,0 +1,431 @@
|
|||||||
|
# 📚 BlackRoad OS Template Index
|
||||||
|
|
||||||
|
**Complete Catalog of 200+ Copy-Paste-Ready Templates**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Template Philosophy
|
||||||
|
|
||||||
|
**The Revolutionary Pattern**: Copy-Paste-And-Learn
|
||||||
|
|
||||||
|
Every template follows the 127-emoji language system (see `EMOJI-REFERENCE.md`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 Core Development Templates (25)
|
||||||
|
|
||||||
|
### Documentation Templates
|
||||||
|
- `TEMPLATE-001-INFRA-RUNBOOK.md` - Infrastructure deployment runbook
|
||||||
|
- `TEMPLATE-002-ARCHITECTURE-OVERVIEW.md` - System architecture document
|
||||||
|
- `TEMPLATE-003-API-DOCUMENTATION.md` - REST API reference doc
|
||||||
|
- `TEMPLATE-004-README.md` - Perfect repository README
|
||||||
|
- `TEMPLATE-005-CHANGELOG.md` - Semantic versioning changelog
|
||||||
|
|
||||||
|
### Code Templates
|
||||||
|
- `TEMPLATE-010-PYTHON-FLASK-SERVICE.py` - Flask HTTP service skeleton
|
||||||
|
- `TEMPLATE-011-PYTHON-FASTAPI-SERVICE.py` - FastAPI service skeleton
|
||||||
|
- `TEMPLATE-012-PYTHON-CLI-TOOL.py` - CLI tool with argparse
|
||||||
|
- `TEMPLATE-013-BASH-SCRIPT.sh` - Bash script with menu mode
|
||||||
|
- `TEMPLATE-014-DOCKERFILE.Dockerfile` - Multi-stage Docker build
|
||||||
|
|
||||||
|
### Configuration Templates
|
||||||
|
- `TEMPLATE-020-DOCKER-COMPOSE.yml` - Docker Compose multi-service
|
||||||
|
- `TEMPLATE-021-GITHUB-WORKFLOW.yml` - GitHub Actions CI/CD
|
||||||
|
- `TEMPLATE-022-REQUIREMENTS.txt` - Python dependencies
|
||||||
|
- `TEMPLATE-023-PACKAGE.json` - Node.js project config
|
||||||
|
- `TEMPLATE-024-WRANGLER.toml` - Cloudflare Worker config
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⛅️ Cloudflare Templates (20)
|
||||||
|
|
||||||
|
### Workers Templates
|
||||||
|
- `cloudflare/TEMPLATE-WORKER-API.js` - REST API Worker
|
||||||
|
- `cloudflare/TEMPLATE-WORKER-AUTH.js` - Authentication Worker
|
||||||
|
- `cloudflare/TEMPLATE-WORKER-ROUTER.js` - Subdomain router
|
||||||
|
- `cloudflare/TEMPLATE-WORKER-WEBSOCKET.js` - WebSocket handler (Durable Objects)
|
||||||
|
- `cloudflare/TEMPLATE-WORKER-QUEUE.js` - Queue consumer
|
||||||
|
|
||||||
|
### Pages Templates
|
||||||
|
- `cloudflare/TEMPLATE-PAGES-LANDING.html` - Landing page with branding
|
||||||
|
- `cloudflare/TEMPLATE-PAGES-DASHBOARD.html` - Admin dashboard
|
||||||
|
- `cloudflare/TEMPLATE-PAGES-DOCS.html` - Documentation site
|
||||||
|
- `cloudflare/TEMPLATE-PAGES-404.html` - Custom 404 page
|
||||||
|
|
||||||
|
### Configuration Templates
|
||||||
|
- `cloudflare/TEMPLATE-WRANGLER-WORKER.toml` - Worker deployment config
|
||||||
|
- `cloudflare/TEMPLATE-WRANGLER-PAGES.toml` - Pages deployment config
|
||||||
|
- `cloudflare/TEMPLATE-DNS-CONFIG.json` - DNS zone configuration
|
||||||
|
- `cloudflare/TEMPLATE-ZERO-TRUST.json` - Zero Trust rules
|
||||||
|
- `cloudflare/TEMPLATE-WAF-RULES.json` - Web Application Firewall rules
|
||||||
|
|
||||||
|
### Database Templates
|
||||||
|
- `cloudflare/TEMPLATE-D1-SCHEMA.sql` - D1 database schema
|
||||||
|
- `cloudflare/TEMPLATE-KV-STRUCTURE.json` - KV namespace structure
|
||||||
|
- `cloudflare/TEMPLATE-R2-BUCKET-POLICY.json` - R2 bucket policy
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛣 Railway Templates (10)
|
||||||
|
|
||||||
|
### Service Configuration
|
||||||
|
- `railway/TEMPLATE-SERVICE.toml` - Railway service config
|
||||||
|
- `railway/TEMPLATE-NIXPACKS.toml` - Nixpacks build config
|
||||||
|
- `railway/TEMPLATE-DOCKERFILE-RAILWAY.Dockerfile` - Railway-optimized Dockerfile
|
||||||
|
- `railway/TEMPLATE-HEALTH-CHECK.py` - Health check endpoint
|
||||||
|
|
||||||
|
### Deployment Templates
|
||||||
|
- `railway/TEMPLATE-ENV-VARS.env` - Environment variables template
|
||||||
|
- `railway/TEMPLATE-SECRETS-SETUP.sh` - Secrets configuration script
|
||||||
|
- `railway/TEMPLATE-DEPLOY-SCRIPT.sh` - Deployment automation script
|
||||||
|
|
||||||
|
### Monitoring Templates
|
||||||
|
- `railway/TEMPLATE-LOGS-CONFIG.json` - Logging configuration
|
||||||
|
- `railway/TEMPLATE-METRICS-CONFIG.json` - Metrics configuration
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🖥 Vercel Templates (10)
|
||||||
|
|
||||||
|
### Application Templates
|
||||||
|
- `vercel/TEMPLATE-NEXTJS-APP/` - Next.js application structure
|
||||||
|
- `vercel/TEMPLATE-REACT-APP/` - React SPA structure
|
||||||
|
- `vercel/TEMPLATE-SERVERLESS-API/` - Serverless function structure
|
||||||
|
|
||||||
|
### Configuration Templates
|
||||||
|
- `vercel/TEMPLATE-VERCEL.json` - Vercel deployment config
|
||||||
|
- `vercel/TEMPLATE-ENV-LOCAL.env` - Local environment setup
|
||||||
|
- `vercel/TEMPLATE-ENV-PRODUCTION.env` - Production environment setup
|
||||||
|
|
||||||
|
### Function Templates
|
||||||
|
- `vercel/TEMPLATE-SERVERLESS-FUNCTION.js` - Serverless function
|
||||||
|
- `vercel/TEMPLATE-EDGE-FUNCTION.js` - Edge function
|
||||||
|
- `vercel/TEMPLATE-API-ROUTE.js` - API route handler
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📁 Google Drive Templates (30)
|
||||||
|
|
||||||
|
### Project Structure Templates
|
||||||
|
- `google-drive/TEMPLATE-PROJECT-FOLDER/` - Complete project folder structure
|
||||||
|
- `00-PROJECT-CHARTER.gdoc` - Project charter document
|
||||||
|
- `01-ROADMAP.gsheet` - Project roadmap tracker
|
||||||
|
- `02-TEAM-ROSTER.gsheet` - Team member directory
|
||||||
|
- `03-MEETING-NOTES/` - Meeting notes folder with template
|
||||||
|
- `04-DELIVERABLES/` - Deliverables tracking folder
|
||||||
|
- `05-RESOURCES/` - Resource library folder
|
||||||
|
|
||||||
|
### Document Templates
|
||||||
|
- `google-drive/TEMPLATE-DOC-PROJECT-CHARTER.gdoc` - Project charter
|
||||||
|
- `google-drive/TEMPLATE-DOC-TECHNICAL-SPEC.gdoc` - Technical specification
|
||||||
|
- `google-drive/TEMPLATE-DOC-USER-GUIDE.gdoc` - User guide
|
||||||
|
- `google-drive/TEMPLATE-DOC-API-DOCS.gdoc` - API documentation
|
||||||
|
- `google-drive/TEMPLATE-DOC-MEETING-NOTES.gdoc` - Meeting notes
|
||||||
|
- `google-drive/TEMPLATE-DOC-STATUS-REPORT.gdoc` - Status report
|
||||||
|
|
||||||
|
### Spreadsheet Templates
|
||||||
|
- `google-drive/TEMPLATE-SHEET-PROJECT-TRACKER.gsheet` - Project tracking
|
||||||
|
- `google-drive/TEMPLATE-SHEET-BUDGET.gsheet` - Budget planning
|
||||||
|
- `google-drive/TEMPLATE-SHEET-TIMELINE.gsheet` - Timeline Gantt chart
|
||||||
|
- `google-drive/TEMPLATE-SHEET-CONTACTS.gsheet` - Contact database
|
||||||
|
- `google-drive/TEMPLATE-SHEET-INVENTORY.gsheet` - Asset inventory
|
||||||
|
- `google-drive/TEMPLATE-SHEET-METRICS.gsheet` - KPI dashboard
|
||||||
|
|
||||||
|
### Presentation Templates
|
||||||
|
- `google-drive/TEMPLATE-SLIDES-PITCH-DECK.gslides` - Investor pitch deck
|
||||||
|
- `google-drive/TEMPLATE-SLIDES-PRODUCT-DEMO.gslides` - Product demo
|
||||||
|
- `google-drive/TEMPLATE-SLIDES-QUARTERLY-REVIEW.gslides` - Quarterly review
|
||||||
|
- `google-drive/TEMPLATE-SLIDES-ARCHITECTURE.gslides` - Architecture overview
|
||||||
|
|
||||||
|
### Form Templates
|
||||||
|
- `google-drive/TEMPLATE-FORM-USER-FEEDBACK.gform` - User feedback survey
|
||||||
|
- `google-drive/TEMPLATE-FORM-BUG-REPORT.gform` - Bug report form
|
||||||
|
- `google-drive/TEMPLATE-FORM-FEATURE-REQUEST.gform` - Feature request form
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📓 Notion Templates (25)
|
||||||
|
|
||||||
|
### Workspace Templates
|
||||||
|
- `notion/TEMPLATE-WORKSPACE-COMPANY.json` - Complete company workspace
|
||||||
|
- `notion/TEMPLATE-WORKSPACE-ENGINEERING.json` - Engineering team workspace
|
||||||
|
- `notion/TEMPLATE-WORKSPACE-PRODUCT.json` - Product team workspace
|
||||||
|
|
||||||
|
### Dashboard Templates
|
||||||
|
- `notion/TEMPLATE-DASHBOARD-PROJECT.json` - Project dashboard
|
||||||
|
- `notion/TEMPLATE-DASHBOARD-SPRINT.json` - Sprint dashboard
|
||||||
|
- `notion/TEMPLATE-DASHBOARD-TEAM.json` - Team dashboard
|
||||||
|
- `notion/TEMPLATE-DASHBOARD-PERSONAL.json` - Personal dashboard
|
||||||
|
|
||||||
|
### Database Templates
|
||||||
|
- `notion/TEMPLATE-DATABASE-TASKS.json` - Task database
|
||||||
|
- `notion/TEMPLATE-DATABASE-PROJECTS.json` - Project database
|
||||||
|
- `notion/TEMPLATE-DATABASE-DOCS.json` - Documentation database
|
||||||
|
- `notion/TEMPLATE-DATABASE-CONTACTS.json` - Contact database
|
||||||
|
- `notion/TEMPLATE-DATABASE-MEETINGS.json` - Meeting notes database
|
||||||
|
- `notion/TEMPLATE-DATABASE-AGENTS.json` - Agent profiles database
|
||||||
|
|
||||||
|
### Page Templates
|
||||||
|
- `notion/TEMPLATE-PAGE-PROJECT-BRIEF.json` - Project brief page
|
||||||
|
- `notion/TEMPLATE-PAGE-TECHNICAL-SPEC.json` - Technical spec page
|
||||||
|
- `notion/TEMPLATE-PAGE-MEETING-NOTES.json` - Meeting notes page
|
||||||
|
- `notion/TEMPLATE-PAGE-WEEKLY-UPDATE.json` - Weekly update page
|
||||||
|
- `notion/TEMPLATE-PAGE-RETROSPECTIVE.json` - Sprint retrospective page
|
||||||
|
- `notion/TEMPLATE-PAGE-OKR.json` - OKRs tracking page
|
||||||
|
|
||||||
|
### Wiki Templates
|
||||||
|
- `notion/TEMPLATE-WIKI-ENGINEERING.json` - Engineering wiki structure
|
||||||
|
- `notion/TEMPLATE-WIKI-PRODUCT.json` - Product wiki structure
|
||||||
|
- `notion/TEMPLATE-WIKI-COMPANY.json` - Company wiki structure
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📁 GitHub Templates (20)
|
||||||
|
|
||||||
|
### Repository Templates
|
||||||
|
- `github/TEMPLATE-REPO-COMPLETE/` - Full repository structure
|
||||||
|
- `.github/ISSUE_TEMPLATE/bug_report.md`
|
||||||
|
- `.github/ISSUE_TEMPLATE/feature_request.md`
|
||||||
|
- `.github/ISSUE_TEMPLATE/documentation.md`
|
||||||
|
- `.github/PULL_REQUEST_TEMPLATE.md`
|
||||||
|
- `.github/workflows/test.yml`
|
||||||
|
- `.github/workflows/deploy.yml`
|
||||||
|
- `.github/CODEOWNERS`
|
||||||
|
- `.github/SECURITY.md`
|
||||||
|
- `README.md`
|
||||||
|
- `LICENSE`
|
||||||
|
- `CONTRIBUTING.md`
|
||||||
|
|
||||||
|
### Issue Templates
|
||||||
|
- `github/TEMPLATE-ISSUE-BUG.md` - Bug report
|
||||||
|
- `github/TEMPLATE-ISSUE-FEATURE.md` - Feature request
|
||||||
|
- `github/TEMPLATE-ISSUE-DOCS.md` - Documentation request
|
||||||
|
- `github/TEMPLATE-ISSUE-SECURITY.md` - Security vulnerability
|
||||||
|
|
||||||
|
### Workflow Templates
|
||||||
|
- `github/TEMPLATE-WORKFLOW-TEST.yml` - Test automation
|
||||||
|
- `github/TEMPLATE-WORKFLOW-DEPLOY-CLOUDFLARE.yml` - Cloudflare deployment
|
||||||
|
- `github/TEMPLATE-WORKFLOW-DEPLOY-RAILWAY.yml` - Railway deployment
|
||||||
|
- `github/TEMPLATE-WORKFLOW-DEPLOY-VERCEL.yml` - Vercel deployment
|
||||||
|
- `github/TEMPLATE-WORKFLOW-SECURITY-SCAN.yml` - Security scanning
|
||||||
|
- `github/TEMPLATE-WORKFLOW-PERFORMANCE.yml` - Performance monitoring
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 Task Management Templates (15)
|
||||||
|
|
||||||
|
### Linear Templates
|
||||||
|
- `task-management/linear/TEMPLATE-PROJECT.json` - Project template
|
||||||
|
- `task-management/linear/TEMPLATE-SPRINT.json` - Sprint template
|
||||||
|
- `task-management/linear/TEMPLATE-EPIC.json` - Epic template
|
||||||
|
- `task-management/linear/TEMPLATE-ISSUE.json` - Issue template
|
||||||
|
|
||||||
|
### Jira Templates
|
||||||
|
- `task-management/jira/TEMPLATE-PROJECT.json` - Jira project
|
||||||
|
- `task-management/jira/TEMPLATE-SPRINT.json` - Jira sprint
|
||||||
|
- `task-management/jira/TEMPLATE-EPIC.json` - Jira epic
|
||||||
|
- `task-management/jira/TEMPLATE-STORY.json` - User story
|
||||||
|
- `task-management/jira/TEMPLATE-TASK.json` - Task template
|
||||||
|
|
||||||
|
### Asana Templates
|
||||||
|
- `task-management/asana/TEMPLATE-PROJECT.json` - Asana project
|
||||||
|
- `task-management/asana/TEMPLATE-SPRINT.json` - Asana sprint
|
||||||
|
- `task-management/asana/TEMPLATE-MILESTONE.json` - Milestone
|
||||||
|
- `task-management/asana/TEMPLATE-TASK.json` - Task template
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🗂 Airtable Templates (10)
|
||||||
|
|
||||||
|
### Base Templates
|
||||||
|
- `airtable/TEMPLATE-CRM-COMPLETE.json` - Complete CRM base
|
||||||
|
- `airtable/TEMPLATE-PROJECT-TRACKER.json` - Project tracking base
|
||||||
|
- `airtable/TEMPLATE-CONTENT-CALENDAR.json` - Content calendar base
|
||||||
|
- `airtable/TEMPLATE-INVENTORY.json` - Inventory management base
|
||||||
|
|
||||||
|
### Table Templates
|
||||||
|
- `airtable/TEMPLATE-TABLE-CONTACTS.json` - Contact table
|
||||||
|
- `airtable/TEMPLATE-TABLE-DEALS.json` - Sales pipeline table
|
||||||
|
- `airtable/TEMPLATE-TABLE-TASKS.json` - Task tracking table
|
||||||
|
- `airtable/TEMPLATE-TABLE-ASSETS.json` - Asset inventory table
|
||||||
|
|
||||||
|
### View Templates
|
||||||
|
- `airtable/TEMPLATE-VIEW-KANBAN.json` - Kanban board view
|
||||||
|
- `airtable/TEMPLATE-VIEW-CALENDAR.json` - Calendar view
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🌐 Subdomain Templates (5,216 variations)
|
||||||
|
|
||||||
|
### Landing Page Templates (by category)
|
||||||
|
- `subdomains/TEMPLATE-LANDING-GENERIC.html` - Generic landing page
|
||||||
|
- `subdomains/TEMPLATE-LANDING-API.html` - API service page
|
||||||
|
- `subdomains/TEMPLATE-LANDING-DASHBOARD.html` - Dashboard app page
|
||||||
|
- `subdomains/TEMPLATE-LANDING-DOCS.html` - Documentation site page
|
||||||
|
- `subdomains/TEMPLATE-LANDING-AUTH.html` - Authentication page
|
||||||
|
- `subdomains/TEMPLATE-LANDING-PAYMENT.html` - Payment integration page
|
||||||
|
- `subdomains/TEMPLATE-LANDING-AGENT.html` - Agent portal page
|
||||||
|
- `subdomains/TEMPLATE-LANDING-QUANTUM.html` - Quantum computing page
|
||||||
|
- `subdomains/TEMPLATE-LANDING-AI.html` - AI/ML service page
|
||||||
|
- `subdomains/TEMPLATE-LANDING-BLOCKCHAIN.html` - Blockchain service page
|
||||||
|
|
||||||
|
### Domain-Specific Templates (16 domains)
|
||||||
|
Each domain has customized versions of all landing page templates:
|
||||||
|
- `subdomains/blackroad-io/` - Main platform (364 templates)
|
||||||
|
- `subdomains/lucidia-earth/` - Lucidia OS (364 templates)
|
||||||
|
- `subdomains/blackroadai-com/` - AI focus (364 templates)
|
||||||
|
- `subdomains/blackroadquantum-com/` - Quantum focus (364 templates)
|
||||||
|
- *(12 more domains...)*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧩 Integration Templates (15 platforms × 5 templates = 75)
|
||||||
|
|
||||||
|
### Stripe Templates
|
||||||
|
- `integrations/stripe/TEMPLATE-CHECKOUT-PAGE.html` - Checkout page
|
||||||
|
- `integrations/stripe/TEMPLATE-SUCCESS-PAGE.html` - Success page
|
||||||
|
- `integrations/stripe/TEMPLATE-WEBHOOK-HANDLER.py` - Webhook handler
|
||||||
|
- `integrations/stripe/TEMPLATE-PRODUCT-SETUP.sh` - Product setup script
|
||||||
|
- `integrations/stripe/TEMPLATE-SUBSCRIPTION-API.py` - Subscription API
|
||||||
|
|
||||||
|
### Clerk Templates
|
||||||
|
- `integrations/clerk/TEMPLATE-AUTH-PAGE.html` - Authentication page
|
||||||
|
- `integrations/clerk/TEMPLATE-USER-PROFILE.tsx` - User profile component
|
||||||
|
- `integrations/clerk/TEMPLATE-MIDDLEWARE.ts` - Auth middleware
|
||||||
|
- `integrations/clerk/TEMPLATE-WEBHOOK-HANDLER.py` - Webhook handler
|
||||||
|
- `integrations/clerk/TEMPLATE-SSO-CONFIG.json` - SSO configuration
|
||||||
|
|
||||||
|
### Resend Templates
|
||||||
|
- `integrations/resend/TEMPLATE-EMAIL-WELCOME.html` - Welcome email
|
||||||
|
- `integrations/resend/TEMPLATE-EMAIL-RECEIPT.html` - Receipt email
|
||||||
|
- `integrations/resend/TEMPLATE-EMAIL-NOTIFICATION.html` - Notification email
|
||||||
|
- `integrations/resend/TEMPLATE-SEND-API.py` - Email sending API
|
||||||
|
- `integrations/resend/TEMPLATE-CAMPAIGN.json` - Email campaign
|
||||||
|
|
||||||
|
### Asana Templates
|
||||||
|
- `integrations/asana/TEMPLATE-PROJECT.json` - Project template
|
||||||
|
- `integrations/asana/TEMPLATE-TASK-AUTOMATION.py` - Task automation script
|
||||||
|
- `integrations/asana/TEMPLATE-SYNC-SCRIPT.py` - Data sync script
|
||||||
|
- `integrations/asana/TEMPLATE-WEBHOOK-HANDLER.py` - Webhook handler
|
||||||
|
- `integrations/asana/TEMPLATE-REPORT-GENERATOR.py` - Report generator
|
||||||
|
|
||||||
|
### Notion Templates
|
||||||
|
- `integrations/notion/TEMPLATE-DATABASE.json` - Database template
|
||||||
|
- `integrations/notion/TEMPLATE-PAGE-SYNC.py` - Page sync script
|
||||||
|
- `integrations/notion/TEMPLATE-AUTOMATION.py` - Automation script
|
||||||
|
- `integrations/notion/TEMPLATE-EXPORT-SCRIPT.py` - Export script
|
||||||
|
- `integrations/notion/TEMPLATE-WIDGET.html` - Embed widget
|
||||||
|
|
||||||
|
*(Similar 5-template sets for 11 more platforms: Jira, Linear, Gmail, Outlook, Google Drive, Dropbox, OneDrive, Slack, Discord, GitHub, GitLab)*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Usage Statistics
|
||||||
|
|
||||||
|
### Most Used Templates (Top 10)
|
||||||
|
1. `TEMPLATE-004-README.md` - 43 repos
|
||||||
|
2. `cloudflare/TEMPLATE-LANDING-GENERIC.html` - 872 sites
|
||||||
|
3. `TEMPLATE-010-PYTHON-FLASK-SERVICE.py` - 28 repos
|
||||||
|
4. `notion/TEMPLATE-DASHBOARD-PROJECT.json` - 156 projects
|
||||||
|
5. `github/TEMPLATE-WORKFLOW-DEPLOY-CLOUDFLARE.yml` - 43 repos
|
||||||
|
6. `TEMPLATE-001-INFRA-RUNBOOK.md` - 37 deployments
|
||||||
|
7. `integrations/stripe/TEMPLATE-CHECKOUT-PAGE.html` - 20 implementations
|
||||||
|
8. `railway/TEMPLATE-SERVICE.toml` - 36 services
|
||||||
|
9. `subdomains/TEMPLATE-LANDING-API.html` - 648 API services
|
||||||
|
10. `TEMPLATE-013-BASH-SCRIPT.sh` - 89 scripts
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Quick Start Guide
|
||||||
|
|
||||||
|
### Use a Template
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Copy the template
|
||||||
|
cp templates/TEMPLATE-001-INFRA-RUNBOOK.md my-deployment-guide.md
|
||||||
|
|
||||||
|
# 2. Search and replace placeholders
|
||||||
|
sed -i '' 's/<PROJECT_NAME>/My Awesome Project/g' my-deployment-guide.md
|
||||||
|
|
||||||
|
# 3. Customize as needed
|
||||||
|
vim my-deployment-guide.md
|
||||||
|
```
|
||||||
|
|
||||||
|
### Generate from Template
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Use template generator script
|
||||||
|
python3 generate-from-template.py \
|
||||||
|
--template="TEMPLATE-001-INFRA-RUNBOOK.md" \
|
||||||
|
--output="cloudflare-deployment.md" \
|
||||||
|
--vars="project_name=Cloudflare Max Buildout,tool=wrangler,version=4.51.0"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deploy Templates
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Sync all templates to all repos
|
||||||
|
./sync-templates-to-all-repos.sh
|
||||||
|
|
||||||
|
# Deploy subdomain templates
|
||||||
|
./deploy-all-subdomain-templates.sh
|
||||||
|
|
||||||
|
# Import to platforms
|
||||||
|
./import-templates-to-platforms.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔄 Template Maintenance
|
||||||
|
|
||||||
|
### Update a Template
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Edit template
|
||||||
|
vim templates/TEMPLATE-001-INFRA-RUNBOOK.md
|
||||||
|
|
||||||
|
# 2. Sync to all instances
|
||||||
|
./sync-template-update.sh TEMPLATE-001-INFRA-RUNBOOK.md
|
||||||
|
|
||||||
|
# 3. Verify propagation
|
||||||
|
./verify-template-sync.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create New Template
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Use the template-template 😉
|
||||||
|
cp templates/TEMPLATE-000-TEMPLATE-TEMPLATE.md templates/TEMPLATE-NEW.md
|
||||||
|
|
||||||
|
# Follow the structure guide
|
||||||
|
vim templates/TEMPLATE-NEW.md
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 Related Documentation
|
||||||
|
|
||||||
|
- `EMOJI-REFERENCE.md` - 127-emoji language system
|
||||||
|
- `MASTER-TEMPLATE-SYSTEM.md` - Complete template system overview
|
||||||
|
- `TEMPLATE-USAGE-GUIDE.md` - Detailed usage instructions
|
||||||
|
- `TEMPLATE-BEST-PRACTICES.md` - Best practices and patterns
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎉 Template Benefits
|
||||||
|
|
||||||
|
- **10x faster** project setup
|
||||||
|
- **Zero boilerplate** writing
|
||||||
|
- **Consistent quality** across all projects
|
||||||
|
- **Always up-to-date** with latest practices
|
||||||
|
- **Machine-teachable** patterns for AI
|
||||||
|
- **Copy-paste-and-learn** approach
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Total Templates**: 200+
|
||||||
|
**Total Platform Coverage**: 15+ platforms
|
||||||
|
**Total Subdomain Coverage**: 5,216 sites
|
||||||
|
**Total Repository Coverage**: 43 repos
|
||||||
|
|
||||||
|
**Remember**: Perfect templates = zero thinking required. Just copy, paste, customize, deploy. ✨🚀
|
||||||
472
templates/TEMPLATE-SYSTEM-GRAPHSQL-SCHEMA.sql
Normal file
472
templates/TEMPLATE-SYSTEM-GRAPHSQL-SCHEMA.sql
Normal file
@@ -0,0 +1,472 @@
|
|||||||
|
-- ============================================================================
|
||||||
|
-- BlackRoad OS Template System - GraphSQL Schema
|
||||||
|
-- Complete graph database schema for all 200+ templates
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- TEMPLATE 001: INFRA RUNBOOK / DEPLOY SCRIPT
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
-- Main template structure (sections/blocks)
|
||||||
|
CREATE TABLE IF NOT EXISTS template_001_nodes (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
label TEXT NOT NULL,
|
||||||
|
kind TEXT NOT NULL, -- 'section', 'block', 'component'
|
||||||
|
emoji TEXT, -- Canonical emoji from EMOJI-REFERENCE.md
|
||||||
|
description TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS template_001_edges (
|
||||||
|
from_id TEXT NOT NULL,
|
||||||
|
to_id TEXT NOT NULL,
|
||||||
|
label TEXT, -- 'flows_to', 'contains', 'depends_on'
|
||||||
|
FOREIGN KEY (from_id) REFERENCES template_001_nodes(id),
|
||||||
|
FOREIGN KEY (to_id) REFERENCES template_001_nodes(id),
|
||||||
|
PRIMARY KEY (from_id, to_id, label)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Template 001 nodes (sections)
|
||||||
|
INSERT OR REPLACE INTO template_001_nodes (id, label, kind, emoji, description) VALUES
|
||||||
|
('header', 'Header Bar', 'section', '🛣', 'Title bar with context and system name'),
|
||||||
|
('context', 'Context Line (tools/env)', 'section', '⛅️', 'Tool versions, environment, region'),
|
||||||
|
('bindings_card', 'Worker / Service Bindings Card', 'block', '📦', 'Resource bindings table'),
|
||||||
|
('infra_status', 'Infrastructure Status Card', 'block', '📡', 'Status of all infrastructure resources'),
|
||||||
|
('steps_pipeline', 'Execute N Steps Pipeline', 'section', '🚀', 'Numbered deployment steps'),
|
||||||
|
('value_card', 'Value Delivered Card', 'block', '💎', 'Cost vs value comparison'),
|
||||||
|
('docs_block', 'Documentation List', 'block', '📚', 'Links to documentation files'),
|
||||||
|
('checklist_block', 'Checklist', 'block', '🗒', 'Manual verification checklist'),
|
||||||
|
('next_steps', 'Next Steps', 'block', '🎯', 'Post-deployment actions'),
|
||||||
|
('tips_block', 'Tips', 'block', '💡', 'Pro tips and best practices'),
|
||||||
|
('footer', 'Footer Strip (Epic Done)', 'section', '🔥', 'Summary celebration line');
|
||||||
|
|
||||||
|
-- Template 001 edges (flow order)
|
||||||
|
INSERT OR REPLACE INTO template_001_edges (from_id, to_id, label) VALUES
|
||||||
|
('header', 'context', 'flows_to'),
|
||||||
|
('context', 'bindings_card', 'flows_to'),
|
||||||
|
('bindings_card', 'infra_status', 'flows_to'),
|
||||||
|
('infra_status', 'steps_pipeline', 'flows_to'),
|
||||||
|
('steps_pipeline', 'value_card', 'flows_to'),
|
||||||
|
('value_card', 'docs_block', 'flows_to'),
|
||||||
|
('docs_block', 'checklist_block','flows_to'),
|
||||||
|
('checklist_block','next_steps', 'flows_to'),
|
||||||
|
('next_steps', 'tips_block', 'flows_to'),
|
||||||
|
('tips_block', 'footer', 'flows_to');
|
||||||
|
|
||||||
|
-- Template 001 step pipeline substructure
|
||||||
|
CREATE TABLE IF NOT EXISTS template_001_step_nodes (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
step_no INTEGER NOT NULL,
|
||||||
|
label TEXT NOT NULL,
|
||||||
|
emoji TEXT DEFAULT '▶️',
|
||||||
|
command TEXT -- Optional: the actual command to run
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS template_001_step_edges (
|
||||||
|
from_id TEXT NOT NULL,
|
||||||
|
to_id TEXT NOT NULL,
|
||||||
|
label TEXT DEFAULT 'next',
|
||||||
|
FOREIGN KEY (from_id) REFERENCES template_001_step_nodes(id),
|
||||||
|
FOREIGN KEY (to_id) REFERENCES template_001_step_nodes(id),
|
||||||
|
PRIMARY KEY (from_id, to_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT OR REPLACE INTO template_001_step_nodes (id, step_no, label, emoji) VALUES
|
||||||
|
('step_1', 1, 'Step 1: <STEP_TITLE_1>', '🚀'),
|
||||||
|
('step_2', 2, 'Step 2: <STEP_TITLE_2>', '🔄'),
|
||||||
|
('step_3', 3, 'Step 3: <STEP_TITLE_3>', '📥'),
|
||||||
|
('step_n', 4, 'Step N: <FINAL_STEP_TITLE>', '✅');
|
||||||
|
|
||||||
|
INSERT OR REPLACE INTO template_001_step_edges (from_id, to_id, label) VALUES
|
||||||
|
('step_1', 'step_2', 'next'),
|
||||||
|
('step_2', 'step_3', 'next'),
|
||||||
|
('step_3', 'step_n', 'next');
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- TEMPLATE 002: ARCHITECTURE / SYSTEM OVERVIEW
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS template_002_nodes (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
label TEXT NOT NULL,
|
||||||
|
kind TEXT NOT NULL, -- 'section', 'diagram', 'component'
|
||||||
|
emoji TEXT,
|
||||||
|
description TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS template_002_edges (
|
||||||
|
from_id TEXT NOT NULL,
|
||||||
|
to_id TEXT NOT NULL,
|
||||||
|
label TEXT,
|
||||||
|
FOREIGN KEY (from_id) REFERENCES template_002_nodes(id),
|
||||||
|
FOREIGN KEY (to_id) REFERENCES template_002_nodes(id),
|
||||||
|
PRIMARY KEY (from_id, to_id, label)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Template 002 top-level sections
|
||||||
|
INSERT OR REPLACE INTO template_002_nodes (id, label, kind, emoji, description) VALUES
|
||||||
|
('header', 'Header Bar', 'section', '🛣', 'System name and context'),
|
||||||
|
('overview', 'Overview', 'section', '🧭', 'What the system is and does'),
|
||||||
|
('diagram', 'High-Level System Diagram', 'diagram', '🏗', 'ASCII diagram of system topology'),
|
||||||
|
('components', 'Component Breakdown', 'section', '📦', 'Detailed component descriptions'),
|
||||||
|
('flows', 'Request / Data Flows', 'section', '👉', 'Numbered data flow diagrams'),
|
||||||
|
('non_functional', 'Reliability / Security / Limits', 'section', '🔐', 'Non-functional requirements'),
|
||||||
|
('operations', 'Operations: Deploy / Observe / Debug','section', '🧰', 'Operational procedures'),
|
||||||
|
('docs_block', 'Documentation & References', 'section', '📚', 'Links to related docs'),
|
||||||
|
('checklist_block', 'Checklists', 'block', '🗒', 'Verification checklists'),
|
||||||
|
('next_steps', 'Next Steps', 'block', '🎯', 'What to do next'),
|
||||||
|
('tips_block', 'Tips', 'block', '💡', 'Pro tips and gotchas');
|
||||||
|
|
||||||
|
-- Template 002 linear reading order
|
||||||
|
INSERT OR REPLACE INTO template_002_edges (from_id, to_id, label) VALUES
|
||||||
|
('header', 'overview', 'flows_to'),
|
||||||
|
('overview', 'diagram', 'flows_to'),
|
||||||
|
('diagram', 'components', 'flows_to'),
|
||||||
|
('components', 'flows', 'flows_to'),
|
||||||
|
('flows', 'non_functional', 'flows_to'),
|
||||||
|
('non_functional', 'operations', 'flows_to'),
|
||||||
|
('operations', 'docs_block', 'flows_to'),
|
||||||
|
('docs_block', 'checklist_block', 'flows_to'),
|
||||||
|
('checklist_block','next_steps', 'flows_to'),
|
||||||
|
('next_steps', 'tips_block', 'flows_to');
|
||||||
|
|
||||||
|
-- Template 002 component nodes (system architecture components)
|
||||||
|
CREATE TABLE IF NOT EXISTS template_002_component_nodes (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
label TEXT NOT NULL,
|
||||||
|
kind TEXT NOT NULL, -- 'user', 'edge', 'service', 'data', 'integration'
|
||||||
|
emoji TEXT,
|
||||||
|
description TEXT,
|
||||||
|
tech_stack TEXT -- e.g. "Cloudflare Workers", "Flask + Python", "D1 SQLite"
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS template_002_component_edges (
|
||||||
|
from_id TEXT NOT NULL,
|
||||||
|
to_id TEXT NOT NULL,
|
||||||
|
label TEXT, -- 'https_request', 'route_api', 'reads_writes', etc.
|
||||||
|
protocol TEXT, -- 'HTTPS', 'WebSocket', 'Queue', 'gRPC', etc.
|
||||||
|
FOREIGN KEY (from_id) REFERENCES template_002_component_nodes(id),
|
||||||
|
FOREIGN KEY (to_id) REFERENCES template_002_component_nodes(id),
|
||||||
|
PRIMARY KEY (from_id, to_id, label)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT OR REPLACE INTO template_002_component_nodes (id, label, kind, emoji, description) VALUES
|
||||||
|
('user', 'Users / Clients', 'user', '👤', 'End users and API clients'),
|
||||||
|
('edge', 'Edge / Gateway (Cloudflare)','edge', '⛅️', 'CDN and routing layer'),
|
||||||
|
('service_a', 'Service A (Core API)', 'service', '🛰', 'Main API service'),
|
||||||
|
('service_b', 'Service B (Web / UI)', 'service', '🖥', 'Web frontend / dashboard'),
|
||||||
|
('db_layer', 'Databases', 'data', '🧱', 'Persistent data storage'),
|
||||||
|
('queue_layer','Queues', 'data', '📨', 'Message queues for async jobs'),
|
||||||
|
('storage', 'Object / KV Storage', 'data', '🗂', 'File and key-value storage'),
|
||||||
|
('integrations','External Integrations', 'integration', '🧩', 'Third-party services');
|
||||||
|
|
||||||
|
INSERT OR REPLACE INTO template_002_component_edges (from_id, to_id, label, protocol) VALUES
|
||||||
|
('user', 'edge', 'https_request', 'HTTPS'),
|
||||||
|
('edge', 'service_a', 'route_api', 'HTTPS'),
|
||||||
|
('edge', 'service_b', 'route_web', 'HTTPS'),
|
||||||
|
('service_a', 'db_layer', 'reads_writes', 'SQL'),
|
||||||
|
('service_a', 'queue_layer', 'enqueue_jobs', 'Queue'),
|
||||||
|
('service_a', 'storage', 'store_assets', 'HTTP'),
|
||||||
|
('service_b', 'service_a', 'api_calls', 'HTTPS'),
|
||||||
|
('service_a', 'integrations','external_calls', 'HTTPS');
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- TEMPLATE 003: DOMAIN / DNS / ROUTING MAP
|
||||||
|
-- For 16 domains × 364 subdomains = 5,216 total sites
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS template_003_domain_nodes (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
domain TEXT NOT NULL UNIQUE,
|
||||||
|
emoji TEXT DEFAULT '🌐',
|
||||||
|
purpose TEXT,
|
||||||
|
status TEXT DEFAULT 'active', -- 'active', 'pending', 'inactive'
|
||||||
|
cloudflare_zone TEXT, -- Cloudflare Zone ID
|
||||||
|
subdomain_count INTEGER DEFAULT 0
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS template_003_subdomain_nodes (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
subdomain TEXT NOT NULL,
|
||||||
|
domain_id TEXT NOT NULL,
|
||||||
|
full_url TEXT NOT NULL,
|
||||||
|
emoji TEXT,
|
||||||
|
category TEXT, -- 'api', 'dashboard', 'docs', 'auth', etc.
|
||||||
|
backend TEXT, -- Railway service, Worker, etc.
|
||||||
|
status TEXT DEFAULT 'pending', -- 'live', 'pending', 'failed'
|
||||||
|
FOREIGN KEY (domain_id) REFERENCES template_003_domain_nodes(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS template_003_routing_edges (
|
||||||
|
from_id TEXT NOT NULL,
|
||||||
|
to_id TEXT NOT NULL,
|
||||||
|
route_type TEXT, -- 'dns', 'worker_route', 'service_route'
|
||||||
|
priority INTEGER DEFAULT 100,
|
||||||
|
FOREIGN KEY (from_id) REFERENCES template_003_subdomain_nodes(id),
|
||||||
|
PRIMARY KEY (from_id, to_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 16 primary domains
|
||||||
|
INSERT OR REPLACE INTO template_003_domain_nodes (id, domain, emoji, purpose, subdomain_count) VALUES
|
||||||
|
('blackroad-io', 'blackroad.io', '🛣', 'Main platform', 364),
|
||||||
|
('lucidia-earth', 'lucidia.earth', '🔮', 'Lucidia OS', 364),
|
||||||
|
('blackroadai-com', 'blackroadai.com', '🤖', 'AI services', 364),
|
||||||
|
('blackroadquantum-com', 'blackroadquantum.com', '⚛️', 'Quantum computing', 364),
|
||||||
|
('blackroad-network', 'blackroad.network', '📡', 'Network services', 364),
|
||||||
|
('blackroad-systems', 'blackroad.systems', '🏗', 'System services', 364),
|
||||||
|
('blackroad-me', 'blackroad.me', '👤', 'Personal brand', 364),
|
||||||
|
('blackroadinc-us', 'blackroad-inc.us', '🏢', 'Corporate entity', 364),
|
||||||
|
('aliceqi-com', 'aliceqi.com', '👩💻', 'Alice Qi brand', 364),
|
||||||
|
('blackroadqi-com', 'blackroadqi.com', '🧠', 'Quantum intelligence', 364),
|
||||||
|
('lucidiaqi-com', 'lucidiaqi.com', '💎', 'Lucidia intelligence', 364),
|
||||||
|
('lucidiastud-io', 'lucidiastud.io', '🎨', 'Lucidia studio', 364),
|
||||||
|
('blackroadquantum-info','blackroadquantum.info','ℹ️', 'Quantum info', 364),
|
||||||
|
('blackroadquantum-net', 'blackroadquantum.net', '🖧', 'Quantum network', 364),
|
||||||
|
('blackroadquantum-shop','blackroadquantum.shop','🛒', 'Quantum shop', 364),
|
||||||
|
('blackroadquantum-store','blackroadquantum.store','🏪', 'Quantum store', 364);
|
||||||
|
|
||||||
|
-- Example subdomains for blackroad.io (would be 364 total)
|
||||||
|
INSERT OR REPLACE INTO template_003_subdomain_nodes (id, subdomain, domain_id, full_url, emoji, category, status) VALUES
|
||||||
|
('blackroad-io-api', 'api', 'blackroad-io', 'https://api.blackroad.io', '🔌', 'api', 'live'),
|
||||||
|
('blackroad-io-dashboard', 'dashboard', 'blackroad-io', 'https://dashboard.blackroad.io', '📊', 'dashboard', 'live'),
|
||||||
|
('blackroad-io-docs', 'docs', 'blackroad-io', 'https://docs.blackroad.io', '📚', 'docs', 'live'),
|
||||||
|
('blackroad-io-auth', 'auth', 'blackroad-io', 'https://auth.blackroad.io', '🔐', 'auth', 'live'),
|
||||||
|
('blackroad-io-payment', 'payment', 'blackroad-io', 'https://payment.blackroad.io', '💳', 'payment', 'live'),
|
||||||
|
('blackroad-io-agents', 'agents', 'blackroad-io', 'https://agents.blackroad.io', '🤖', 'agents', 'live'),
|
||||||
|
('blackroad-io-quantum', 'quantum', 'blackroad-io', 'https://quantum.blackroad.io', '⚛️', 'quantum', 'live'),
|
||||||
|
('blackroad-io-vector', 'vector', 'blackroad-io', 'https://vector.blackroad.io', '🧬', 'data', 'live'),
|
||||||
|
('blackroad-io-stream', 'stream', 'blackroad-io', 'https://stream.blackroad.io', '📡', 'data', 'live'),
|
||||||
|
('blackroad-io-mq', 'mq', 'blackroad-io', 'https://mq.blackroad.io', '📨', 'data', 'live');
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- MASTER TEMPLATE CATALOG
|
||||||
|
-- All 200+ templates with metadata
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS template_catalog (
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
category TEXT NOT NULL, -- 'core', 'cloudflare', 'railway', 'google-drive', etc.
|
||||||
|
type TEXT NOT NULL, -- 'document', 'code', 'config', 'script'
|
||||||
|
file_path TEXT NOT NULL,
|
||||||
|
emoji TEXT,
|
||||||
|
description TEXT,
|
||||||
|
variables TEXT, -- JSON array of variable placeholders
|
||||||
|
usage_count INTEGER DEFAULT 0,
|
||||||
|
last_used TIMESTAMP,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS template_dependencies (
|
||||||
|
template_id TEXT NOT NULL,
|
||||||
|
depends_on TEXT NOT NULL,
|
||||||
|
dependency_type TEXT, -- 'requires', 'extends', 'includes'
|
||||||
|
FOREIGN KEY (template_id) REFERENCES template_catalog(id),
|
||||||
|
FOREIGN KEY (depends_on) REFERENCES template_catalog(id),
|
||||||
|
PRIMARY KEY (template_id, depends_on)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Core templates
|
||||||
|
INSERT OR REPLACE INTO template_catalog (id, name, category, type, file_path, emoji, description) VALUES
|
||||||
|
('T001', 'Infra Runbook / Deploy Script', 'core', 'document', 'TEMPLATE-001-INFRA-RUNBOOK.md', '🚀', 'Deployment runbook template'),
|
||||||
|
('T002', 'Architecture / System Overview', 'core', 'document', 'TEMPLATE-002-ARCHITECTURE-OVERVIEW.md', '🏗', 'System architecture template'),
|
||||||
|
('T003', 'Domain / DNS / Routing Map', 'core', 'document', 'TEMPLATE-003-DOMAIN-DNS-ROUTING.md', '🌐', 'DNS routing configuration'),
|
||||||
|
('T004', 'README', 'core', 'document', 'TEMPLATE-004-README.md', '📖', 'Perfect repository README'),
|
||||||
|
('T005', 'Changelog', 'core', 'document', 'TEMPLATE-005-CHANGELOG.md', '📝', 'Semantic versioning changelog');
|
||||||
|
|
||||||
|
-- Cloudflare templates
|
||||||
|
INSERT OR REPLACE INTO template_catalog (id, name, category, type, file_path, emoji, description) VALUES
|
||||||
|
('CF01', 'Worker API', 'cloudflare', 'code', 'cloudflare/TEMPLATE-WORKER-API.js', '⛅️', 'REST API Worker'),
|
||||||
|
('CF02', 'Worker Auth', 'cloudflare', 'code', 'cloudflare/TEMPLATE-WORKER-AUTH.js', '🔐', 'Authentication Worker'),
|
||||||
|
('CF03', 'Worker Router', 'cloudflare', 'code', 'cloudflare/TEMPLATE-WORKER-ROUTER.js', '🔀', 'Subdomain router'),
|
||||||
|
('CF04', 'Pages Landing', 'cloudflare', 'code', 'cloudflare/TEMPLATE-PAGES-LANDING.html', '🌐', 'Landing page template'),
|
||||||
|
('CF05', 'Wrangler Config', 'cloudflare', 'config', 'cloudflare/TEMPLATE-WRANGLER.toml', '🔧', 'Worker deployment config');
|
||||||
|
|
||||||
|
-- Google Drive templates
|
||||||
|
INSERT OR REPLACE INTO template_catalog (id, name, category, type, file_path, emoji, description) VALUES
|
||||||
|
('GD01', 'Project Structure', 'google-drive', 'document', 'google-drive/PROJECT-STRUCTURE-TEMPLATE.json', '📁', 'Complete project folder'),
|
||||||
|
('GD02', 'Technical Spec', 'google-drive', 'document', 'google-drive/TEMPLATE-DOC-TECHNICAL-SPEC.json', '📘', 'Technical specification'),
|
||||||
|
('GD03', 'User Guide', 'google-drive', 'document', 'google-drive/TEMPLATE-DOC-USER-GUIDE.json', '📙', 'User documentation'),
|
||||||
|
('GD04', 'Meeting Notes', 'google-drive', 'document', 'google-drive/TEMPLATE-DOC-MEETING-NOTES.json', '📝', 'Meeting notes template');
|
||||||
|
|
||||||
|
-- Notion templates
|
||||||
|
INSERT OR REPLACE INTO template_catalog (id, name, category, type, file_path, emoji, description) VALUES
|
||||||
|
('N001', 'Project Dashboard', 'notion', 'document', 'notion/TEMPLATE-DASHBOARD-PROJECT.json', '📊', 'Project management dashboard'),
|
||||||
|
('N002', 'Tasks Database', 'notion', 'document', 'notion/TEMPLATE-DATABASE-TASKS.json', '📋', 'Task tracking database'),
|
||||||
|
('N003', 'Agent Profile', 'notion', 'document', 'notion/TEMPLATE-PAGE-AGENT-PROFILE.json', '🤖', 'Agent documentation page');
|
||||||
|
|
||||||
|
-- GitHub templates
|
||||||
|
INSERT OR REPLACE INTO template_catalog (id, name, category, type, file_path, emoji, description) VALUES
|
||||||
|
('GH01', 'Bug Report', 'github', 'document', 'github/ISSUE_TEMPLATE/bug_report.md', '🐛', 'Bug report issue template'),
|
||||||
|
('GH02', 'Feature Request', 'github', 'document', 'github/ISSUE_TEMPLATE/feature_request.md', '✨', 'Feature request template'),
|
||||||
|
('GH03', 'Pull Request', 'github', 'document', 'github/PULL_REQUEST_TEMPLATE.md', '📥', 'PR template with checklist');
|
||||||
|
|
||||||
|
-- Airtable templates
|
||||||
|
INSERT OR REPLACE INTO template_catalog (id, name, category, type, file_path, emoji, description) VALUES
|
||||||
|
('AT01', 'CRM Complete', 'airtable', 'document', 'airtable/TEMPLATE-CRM-COMPLETE.json', '🗂', 'Full CRM base with tables');
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- EMOJI REFERENCE TABLE
|
||||||
|
-- All 127 canonical emojis from EMOJI-REFERENCE.md
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS emoji_reference (
|
||||||
|
emoji TEXT PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
category TEXT NOT NULL, -- From 1-10 categories
|
||||||
|
meaning TEXT NOT NULL,
|
||||||
|
usage TEXT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Layout & Pointers (23)
|
||||||
|
INSERT OR REPLACE INTO emoji_reference (emoji, name, category, meaning, usage) VALUES
|
||||||
|
('👉', 'Main pointer', 'Layout & Pointers', 'Call out important line/choice', 'Highlight key information'),
|
||||||
|
('➡️', 'Next/forward', 'Layout & Pointers', 'Move to next step', 'Sequential flow'),
|
||||||
|
('⬅️', 'Back/previous', 'Layout & Pointers', 'Rollback step, go back', 'Reverse flow'),
|
||||||
|
('↗️', 'Escalate', 'Layout & Pointers', 'Scale up resources', 'Increase capacity'),
|
||||||
|
('↘️', 'De-escalate', 'Layout & Pointers', 'Scale down resources', 'Decrease capacity'),
|
||||||
|
('🔁', 'Loop/repeat', 'Layout & Pointers', 'Repeat step/cron-like', 'Cyclic operation'),
|
||||||
|
('➕', 'Add', 'Layout & Pointers', 'Create resource, add config', 'Addition'),
|
||||||
|
('➖', 'Remove', 'Layout & Pointers', 'Remove resource, subtract', 'Deletion');
|
||||||
|
|
||||||
|
-- Context / Platform (17)
|
||||||
|
INSERT OR REPLACE INTO emoji_reference (emoji, name, category, meaning, usage) VALUES
|
||||||
|
('⛅️', 'Cloudflare', 'Context / Platform', 'Workers, R2, D1, Wrangler', 'Cloudflare context'),
|
||||||
|
('☁️', 'Generic cloud', 'Context / Platform', 'AWS, GCP, etc.', 'Cloud platform'),
|
||||||
|
('💻', 'Dev machine/local','Context / Platform', 'Local dev, CLI tooling', 'Local environment'),
|
||||||
|
('🛣', 'BlackRoad OS', 'Context / Platform', 'Cross-system/orchestration', 'BlackRoad system'),
|
||||||
|
('📱', 'Mobile', 'Context / Platform', 'iOS/Android/TestFlight', 'Mobile app'),
|
||||||
|
('🖥', 'Web app', 'Context / Platform', 'Dashboards, web frontends', 'Web application'),
|
||||||
|
('🌐', 'DNS/domains', 'Context / Platform', 'Domains, subdomains, routing', 'DNS configuration'),
|
||||||
|
('💳', 'Payments', 'Context / Platform', 'Stripe, billing flows', 'Payment system'),
|
||||||
|
('🔐', 'Security/auth', 'Context / Platform', 'Secrets, auth, lock-down', 'Security');
|
||||||
|
|
||||||
|
-- Actions (17)
|
||||||
|
INSERT OR REPLACE INTO emoji_reference (emoji, name, category, meaning, usage) VALUES
|
||||||
|
('🚀', 'Deploy/launch', 'Actions', 'Ship to environment', 'Deployment'),
|
||||||
|
('▶️', 'Run', 'Actions', 'Run script/command/job', 'Execution'),
|
||||||
|
('⏹', 'Stop', 'Actions', 'Stop process/kill job', 'Termination'),
|
||||||
|
('🔄', 'Sync', 'Actions', 'Refresh state, pull latest', 'Synchronization'),
|
||||||
|
('♻️', 'Redeploy', 'Actions', 'Recreate with same config', 'Redeployment'),
|
||||||
|
('📥', 'Import', 'Actions', 'Ingest configs/data/DNS', 'Import operation'),
|
||||||
|
('📤', 'Export', 'Actions', 'Backup, snapshot, archive', 'Export operation'),
|
||||||
|
('🔧', 'Configure', 'Actions', 'Change config, settings', 'Configuration'),
|
||||||
|
('🪛', 'Fix', 'Actions', 'Small targeted fix, patch', 'Bug fix');
|
||||||
|
|
||||||
|
-- Status / Severity (13)
|
||||||
|
INSERT OR REPLACE INTO emoji_reference (emoji, name, category, meaning, usage) VALUES
|
||||||
|
('✅', 'OK/done', 'Status / Severity', 'Succeeded, safe, verified', 'Success state'),
|
||||||
|
('☐', 'Todo', 'Status / Severity', 'Manual step remaining', 'Pending task'),
|
||||||
|
('⏳', 'Pending', 'Status / Severity', 'Waiting, in progress', 'In progress'),
|
||||||
|
('⚠️', 'Warning', 'Status / Severity', 'Non-fatal, needs attention', 'Warning state'),
|
||||||
|
('❌', 'Error', 'Status / Severity', 'Failed, stop here', 'Error state'),
|
||||||
|
('🚨', 'Incident', 'Status / Severity', 'On-fire, high severity', 'Critical issue'),
|
||||||
|
('🔍', 'Investigate', 'Status / Severity', 'Look closer/drill in', 'Investigation');
|
||||||
|
|
||||||
|
-- Resources & Infra (17)
|
||||||
|
INSERT OR REPLACE INTO emoji_reference (emoji, name, category, meaning, usage) VALUES
|
||||||
|
('📦', 'Package/artifact', 'Resources & Infra', 'Worker script, bundle, container', 'Artifact'),
|
||||||
|
('📁', 'Folder/repo', 'Resources & Infra', 'GitHub repo, directory', 'Repository'),
|
||||||
|
('🧱', 'Database', 'Resources & Infra', 'D1 tables, infra blocks', 'Database'),
|
||||||
|
('🤖', 'AI service/model', 'Resources & Infra', 'LLMs, agents, AI API', 'AI system'),
|
||||||
|
('🛰', 'Service', 'Resources & Infra', 'Satellite services', 'Microservice'),
|
||||||
|
('🧩', 'Integration', 'Resources & Infra', 'Stripe, Clerk, 3rd-party', 'Integration'),
|
||||||
|
('📜', 'Schema/contract', 'Resources & Infra', 'API schema, DB schema', 'Schema'),
|
||||||
|
('🔑', 'Secrets store', 'Resources & Infra', 'Env vars, secret manager', 'Secrets');
|
||||||
|
|
||||||
|
-- Docs & Learning (10)
|
||||||
|
INSERT OR REPLACE INTO emoji_reference (emoji, name, category, meaning, usage) VALUES
|
||||||
|
('📚', 'Reference docs', 'Docs & Learning', 'Full guides, manuals', 'Documentation'),
|
||||||
|
('📖', 'Reading view', 'Docs & Learning', '"Start here" explanations', 'Overview'),
|
||||||
|
('📘', 'API docs', 'Docs & Learning', 'Technical reference', 'API reference'),
|
||||||
|
('📙', 'How-to guide', 'Docs & Learning', 'Step-by-step walkthroughs', 'Tutorial'),
|
||||||
|
('📝', 'Notes/summary', 'Docs & Learning', 'Short summaries, quick notes', 'Notes'),
|
||||||
|
('🗒', 'Checklist', 'Docs & Learning', 'Deployment/verification checklist', 'Checklist'),
|
||||||
|
('💡', 'Tip/insight', 'Docs & Learning', 'Pro tips, best practice', 'Tip');
|
||||||
|
|
||||||
|
-- Meta / Vibe (7)
|
||||||
|
INSERT OR REPLACE INTO emoji_reference (emoji, name, category, meaning, usage) VALUES
|
||||||
|
('✨', 'Magic/delightful', 'Meta / Vibe', '"This feels special"', 'Delight'),
|
||||||
|
('🔥', 'Epic done', 'Meta / Vibe', 'Whole system wired, big milestone', 'Achievement'),
|
||||||
|
('💎', 'Premium/value', 'Meta / Vibe', '"Worth $$"', 'Value'),
|
||||||
|
('🎉', 'Celebration', 'Meta / Vibe', 'Success, done, confetti', 'Celebration'),
|
||||||
|
('🧠', 'Learning', 'Meta / Vibe', 'Philosophy, patterns, mental models', 'Knowledge'),
|
||||||
|
('🔮', 'Vision/future', 'Meta / Vibe', 'Roadmap, speculative ideas', 'Vision');
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- VIEWS FOR COMMON QUERIES
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
-- All templates by category
|
||||||
|
CREATE VIEW IF NOT EXISTS templates_by_category AS
|
||||||
|
SELECT category, COUNT(*) as template_count, GROUP_CONCAT(emoji) as emojis
|
||||||
|
FROM template_catalog
|
||||||
|
GROUP BY category
|
||||||
|
ORDER BY template_count DESC;
|
||||||
|
|
||||||
|
-- Most used templates
|
||||||
|
CREATE VIEW IF NOT EXISTS most_used_templates AS
|
||||||
|
SELECT id, name, category, emoji, usage_count, last_used
|
||||||
|
FROM template_catalog
|
||||||
|
WHERE usage_count > 0
|
||||||
|
ORDER BY usage_count DESC
|
||||||
|
LIMIT 10;
|
||||||
|
|
||||||
|
-- Template dependency graph
|
||||||
|
CREATE VIEW IF NOT EXISTS template_dependency_graph AS
|
||||||
|
SELECT
|
||||||
|
t1.name as template,
|
||||||
|
t1.emoji as template_emoji,
|
||||||
|
t2.name as depends_on,
|
||||||
|
t2.emoji as depends_on_emoji,
|
||||||
|
td.dependency_type
|
||||||
|
FROM template_dependencies td
|
||||||
|
JOIN template_catalog t1 ON td.template_id = t1.id
|
||||||
|
JOIN template_catalog t2 ON td.depends_on = t2.id;
|
||||||
|
|
||||||
|
-- Domain statistics
|
||||||
|
CREATE VIEW IF NOT EXISTS domain_stats AS
|
||||||
|
SELECT
|
||||||
|
domain,
|
||||||
|
emoji,
|
||||||
|
purpose,
|
||||||
|
status,
|
||||||
|
subdomain_count,
|
||||||
|
(SELECT COUNT(*) FROM template_003_subdomain_nodes WHERE domain_id = template_003_domain_nodes.id AND status = 'live') as live_subdomains,
|
||||||
|
(SELECT COUNT(*) FROM template_003_subdomain_nodes WHERE domain_id = template_003_domain_nodes.id AND status = 'pending') as pending_subdomains
|
||||||
|
FROM template_003_domain_nodes
|
||||||
|
ORDER BY live_subdomains DESC;
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- EXAMPLE QUERIES
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
-- Get all templates for a specific category
|
||||||
|
-- SELECT * FROM template_catalog WHERE category = 'cloudflare';
|
||||||
|
|
||||||
|
-- Get the flow structure of Template 001
|
||||||
|
-- SELECT t1.label as from_section, t2.label as to_section, e.label as relationship
|
||||||
|
-- FROM template_001_edges e
|
||||||
|
-- JOIN template_001_nodes t1 ON e.from_id = t1.id
|
||||||
|
-- JOIN template_001_nodes t2 ON e.to_id = t2.id;
|
||||||
|
|
||||||
|
-- Get all subdomains for a domain
|
||||||
|
-- SELECT subdomain, full_url, emoji, category, status
|
||||||
|
-- FROM template_003_subdomain_nodes
|
||||||
|
-- WHERE domain_id = 'blackroad-io'
|
||||||
|
-- ORDER BY category, subdomain;
|
||||||
|
|
||||||
|
-- Get component connections in architecture
|
||||||
|
-- SELECT c1.label as from_component, c2.label as to_component, e.label as connection, e.protocol
|
||||||
|
-- FROM template_002_component_edges e
|
||||||
|
-- JOIN template_002_component_nodes c1 ON e.from_id = c1.id
|
||||||
|
-- JOIN template_002_component_nodes c2 ON e.to_id = c2.id;
|
||||||
|
|
||||||
|
-- ============================================================================
|
||||||
|
-- END OF SCHEMA
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
-- Summary statistics
|
||||||
|
SELECT '✅ GraphSQL Schema Complete!' as status;
|
||||||
|
SELECT COUNT(*) || ' templates cataloged' as template_count FROM template_catalog;
|
||||||
|
SELECT COUNT(*) || ' domains configured' as domain_count FROM template_003_domain_nodes;
|
||||||
|
SELECT COUNT(*) || ' emojis defined' as emoji_count FROM emoji_reference;
|
||||||
543
templates/TERMINAL-COMMANDS-TEMPLATE.md
Normal file
543
templates/TERMINAL-COMMANDS-TEMPLATE.md
Normal file
@@ -0,0 +1,543 @@
|
|||||||
|
# Terminal Commands Template
|
||||||
|
|
||||||
|
## The Revolutionary Pattern: Copy-Paste-And-Learn
|
||||||
|
|
||||||
|
### Why This Works
|
||||||
|
- **Zero cognitive load**: Just copy and paste
|
||||||
|
- **Self-documenting**: Comments explain what happens
|
||||||
|
- **Machine-teachable**: AI can learn from the pattern
|
||||||
|
- **Error-proof**: No manual typing mistakes
|
||||||
|
- **Context-preserved**: Comments show the why AND the how
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Template Format
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# [ACTION DESCRIPTION]
|
||||||
|
cd [DIRECTORY]
|
||||||
|
[COMMAND] [ARGS] --[FLAG] [VALUE]
|
||||||
|
|
||||||
|
# [NEXT ACTION]
|
||||||
|
[COMMAND] [ARGS]
|
||||||
|
|
||||||
|
# [RESULT EXPLANATION]
|
||||||
|
[COMMAND] [ARGS]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Universal Patterns
|
||||||
|
|
||||||
|
### Pattern 1: Deploy to Cloudflare
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deploy complete API
|
||||||
|
cd cloudflare-workers
|
||||||
|
wrangler deploy blackroad-unified-api.js --config wrangler-unified-api.toml
|
||||||
|
|
||||||
|
# Initialize databases
|
||||||
|
wrangler d1 execute blackroad-users --file=../cloudflare-d1-schemas.sql
|
||||||
|
|
||||||
|
# Deploy edge router
|
||||||
|
wrangler deploy blackroad-edge-router.js
|
||||||
|
|
||||||
|
# Verify deployment
|
||||||
|
wrangler pages deployment list --project-name=blackroad-io
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 2: Deploy to Railway
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Link to Railway project
|
||||||
|
export RAILWAY_TOKEN=your-token-here
|
||||||
|
railway link 0c7bcf07-307b-4db6-9c94-22a456500d68
|
||||||
|
|
||||||
|
# Deploy service
|
||||||
|
railway up --service api-gateway
|
||||||
|
|
||||||
|
# Check deployment status
|
||||||
|
railway status
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
railway logs --tail 100
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 3: Start Local Services
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start all services
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
./start-all.sh
|
||||||
|
|
||||||
|
# Or start specific services
|
||||||
|
PORT=8000 python3 operator_http.py &
|
||||||
|
PORT=9700 python3 blackroad-integrations-hub.py &
|
||||||
|
PORT=9800 python3 blackroad-event-bus.py &
|
||||||
|
|
||||||
|
# Check services are running
|
||||||
|
curl http://localhost:8000/status
|
||||||
|
curl http://localhost:9700/api/health
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 4: SSH to Servers
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Connect to Raspberry Pi
|
||||||
|
ssh alice@192.168.4.49
|
||||||
|
|
||||||
|
# Connect to DigitalOcean droplet
|
||||||
|
ssh root@159.65.43.12
|
||||||
|
|
||||||
|
# Run command on remote server
|
||||||
|
ssh alice@192.168.4.49 "cd /home/alice && ./start-services.sh"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 5: Create Directories and Files
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create directory structure
|
||||||
|
mkdir -p ~/blackroad-sandbox/new-feature/{src,tests,docs}
|
||||||
|
|
||||||
|
# Create file with content (using heredoc)
|
||||||
|
cat > ~/blackroad-sandbox/new-feature/README.md <<'EOF'
|
||||||
|
# New Feature
|
||||||
|
|
||||||
|
Description here.
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Set permissions
|
||||||
|
chmod +x ~/blackroad-sandbox/new-feature/deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 6: Edit Files (nano alternatives)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Quick edit with echo
|
||||||
|
echo "NEW_VAR=value" >> .env
|
||||||
|
|
||||||
|
# Multi-line edit with cat
|
||||||
|
cat >> config.yaml <<'EOF'
|
||||||
|
setting1: value1
|
||||||
|
setting2: value2
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Replace content entirely
|
||||||
|
cat > file.txt <<'EOF'
|
||||||
|
Complete new content
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Or use sed for inline replacement
|
||||||
|
sed -i '' 's/old-value/new-value/g' config.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 7: Git Operations
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Complete commit and push workflow
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
git add .
|
||||||
|
git commit -m "feat: Add new feature
|
||||||
|
|
||||||
|
Description of changes.
|
||||||
|
|
||||||
|
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
||||||
|
|
||||||
|
Co-Authored-By: Claude <noreply@anthropic.com>"
|
||||||
|
git push origin main
|
||||||
|
|
||||||
|
# Create and push new branch
|
||||||
|
git checkout -b feature/new-feature
|
||||||
|
git push -u origin feature/new-feature
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 8: Environment Setup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Copy environment template
|
||||||
|
cp .env.example .env
|
||||||
|
|
||||||
|
# Add secrets (paste your actual values)
|
||||||
|
cat >> .env <<'EOF'
|
||||||
|
RAILWAY_TOKEN=your-token-here
|
||||||
|
STRIPE_SECRET_KEY=your-key-here
|
||||||
|
CLOUDFLARE_API_TOKEN=your-token-here
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Source environment
|
||||||
|
source .env
|
||||||
|
|
||||||
|
# Verify
|
||||||
|
echo "Railway token: ${RAILWAY_TOKEN:0:10}..."
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 9: Testing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run all tests
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
pytest -v
|
||||||
|
|
||||||
|
# Run specific test types
|
||||||
|
pytest -m unit -v
|
||||||
|
pytest -m integration -v
|
||||||
|
pytest -m e2e -v
|
||||||
|
|
||||||
|
# Run with coverage
|
||||||
|
pytest --cov=. --cov-report=html
|
||||||
|
open coverage_html/index.html
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 10: Docker Operations
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start all services
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
# Start specific services
|
||||||
|
docker-compose up -d auth-api event-bus service-registry
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
docker-compose logs -f service-name
|
||||||
|
|
||||||
|
# Restart service
|
||||||
|
docker-compose restart service-name
|
||||||
|
|
||||||
|
# Stop everything
|
||||||
|
docker-compose down
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Common Operations Library
|
||||||
|
|
||||||
|
### Deploy Everything
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deploy to all platforms in sequence
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
|
||||||
|
# 1. Deploy to Cloudflare
|
||||||
|
./deploy-all-domains.sh
|
||||||
|
|
||||||
|
# 2. Deploy to Railway
|
||||||
|
./deploy-all-railway-services.sh
|
||||||
|
|
||||||
|
# 3. Deploy to Vercel
|
||||||
|
./deploy-vercel-all.sh
|
||||||
|
|
||||||
|
# 4. Verify all deployments
|
||||||
|
./br health
|
||||||
|
```
|
||||||
|
|
||||||
|
### Emergency Restart
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Kill all BlackRoad services
|
||||||
|
pkill -f "blackroad-"
|
||||||
|
|
||||||
|
# Wait 2 seconds
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
# Restart everything
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
./start-all.sh
|
||||||
|
|
||||||
|
# Verify
|
||||||
|
./br health
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check Everything
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# System status
|
||||||
|
./br status
|
||||||
|
|
||||||
|
# All service health
|
||||||
|
./br health
|
||||||
|
|
||||||
|
# Railway services
|
||||||
|
railway status
|
||||||
|
|
||||||
|
# Cloudflare deployments
|
||||||
|
wrangler pages deployment list --project-name=blackroad-io
|
||||||
|
|
||||||
|
# Docker services
|
||||||
|
docker-compose ps
|
||||||
|
```
|
||||||
|
|
||||||
|
### Update Secrets Everywhere
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Set Railway secrets
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
./setup-railway-secrets-all.sh
|
||||||
|
|
||||||
|
# Update Cloudflare environment
|
||||||
|
cd cloudflare-workers
|
||||||
|
wrangler secret put STRIPE_SECRET_KEY
|
||||||
|
|
||||||
|
# Update GitHub secrets
|
||||||
|
gh secret set RAILWAY_TOKEN -b"your-token-here"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Platform-Specific Command Blocks
|
||||||
|
|
||||||
|
### Cloudflare Pages
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deploy single site
|
||||||
|
cd ~/blackroad-sandbox/domains/blackroad-io
|
||||||
|
wrangler pages deploy . --project-name=blackroad-io
|
||||||
|
|
||||||
|
# Deploy all sites
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
for domain in blackroad-io lucidia-earth blackroadai-com; do
|
||||||
|
echo "Deploying $domain..."
|
||||||
|
cd domains/$domain
|
||||||
|
wrangler pages deploy . --project-name=$domain
|
||||||
|
cd ../..
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
### Railway Multi-Service
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Deploy all services in sequence
|
||||||
|
cd ~/blackroad-sandbox
|
||||||
|
|
||||||
|
services=(
|
||||||
|
"api-gateway"
|
||||||
|
"auth-api"
|
||||||
|
"event-bus"
|
||||||
|
"service-registry"
|
||||||
|
"integrations-hub"
|
||||||
|
)
|
||||||
|
|
||||||
|
for service in "${services[@]}"; do
|
||||||
|
echo "Deploying $service..."
|
||||||
|
railway up --service $service
|
||||||
|
done
|
||||||
|
|
||||||
|
# Verify all
|
||||||
|
railway status
|
||||||
|
```
|
||||||
|
|
||||||
|
### GitHub Actions
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Trigger deployment workflow
|
||||||
|
gh workflow run deploy-railway.yml
|
||||||
|
|
||||||
|
# Watch deployment
|
||||||
|
gh run watch
|
||||||
|
|
||||||
|
# View recent runs
|
||||||
|
gh run list --workflow=deploy-railway.yml --limit 5
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting Command Blocks
|
||||||
|
|
||||||
|
### Port Already in Use
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Find what's using port 8000
|
||||||
|
lsof -i :8000
|
||||||
|
|
||||||
|
# Kill it
|
||||||
|
kill -9 $(lsof -t -i:8000)
|
||||||
|
|
||||||
|
# Or kill all Python processes
|
||||||
|
pkill -f python3
|
||||||
|
|
||||||
|
# Restart your service
|
||||||
|
PORT=8000 python3 blackroad-service.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### Railway Deploy Failed
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check logs
|
||||||
|
railway logs --tail 100
|
||||||
|
|
||||||
|
# Check environment variables
|
||||||
|
railway variables
|
||||||
|
|
||||||
|
# Force redeploy
|
||||||
|
railway up --service SERVICE_NAME --detach
|
||||||
|
|
||||||
|
# Check status
|
||||||
|
railway status
|
||||||
|
```
|
||||||
|
|
||||||
|
### Git Push Failed
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check current branch
|
||||||
|
git branch
|
||||||
|
|
||||||
|
# Pull latest changes
|
||||||
|
git pull --rebase origin main
|
||||||
|
|
||||||
|
# Force push (CAREFUL!)
|
||||||
|
git push --force-with-lease origin main
|
||||||
|
|
||||||
|
# Or create new branch
|
||||||
|
git checkout -b fix/deployment-issue
|
||||||
|
git push -u origin fix/deployment-issue
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How to Use This Template
|
||||||
|
|
||||||
|
### For Documentation Writers
|
||||||
|
|
||||||
|
1. **Copy the pattern** that matches your task
|
||||||
|
2. **Replace placeholders** with actual values
|
||||||
|
3. **Test the commands** - they must work perfectly
|
||||||
|
4. **Add comments** explaining what happens
|
||||||
|
5. **Include verification** commands at the end
|
||||||
|
|
||||||
|
### For Users (Alexa!)
|
||||||
|
|
||||||
|
1. **Find the pattern** you need
|
||||||
|
2. **Copy the entire block** (including comments)
|
||||||
|
3. **Paste into terminal**
|
||||||
|
4. **Press Enter** and watch it work
|
||||||
|
5. **The comments teach you** what happened
|
||||||
|
|
||||||
|
### For AI Assistants
|
||||||
|
|
||||||
|
1. **Use these patterns** in all command suggestions
|
||||||
|
2. **Always include comments** explaining each step
|
||||||
|
3. **Group related commands** together
|
||||||
|
4. **Add verification** at the end
|
||||||
|
5. **Make it copy-paste ready** - no manual edits needed
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Golden Rules
|
||||||
|
|
||||||
|
1. ✅ **Always include comments** - explain the what AND why
|
||||||
|
2. ✅ **Commands must work** - test before documenting
|
||||||
|
3. ✅ **Use full paths** - no ambiguity about location
|
||||||
|
4. ✅ **Group related actions** - deploy, verify, done
|
||||||
|
5. ✅ **Include verification** - show how to check it worked
|
||||||
|
6. ✅ **Escape properly** - quotes, variables, heredocs
|
||||||
|
7. ✅ **One block = One task** - atomic, complete operations
|
||||||
|
8. ✅ **Comments start with #** - consistent style
|
||||||
|
9. ✅ **Blank lines separate** - visual grouping
|
||||||
|
10. ✅ **End with verification** - prove it worked
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Anti-Patterns (Don't Do This)
|
||||||
|
|
||||||
|
❌ **Vague commands**:
|
||||||
|
```bash
|
||||||
|
# Bad
|
||||||
|
Deploy the thing
|
||||||
|
```
|
||||||
|
|
||||||
|
✅ **Specific commands**:
|
||||||
|
```bash
|
||||||
|
# Good
|
||||||
|
cd cloudflare-workers
|
||||||
|
wrangler deploy blackroad-unified-api.js --config wrangler-unified-api.toml
|
||||||
|
```
|
||||||
|
|
||||||
|
❌ **Manual editing required**:
|
||||||
|
```bash
|
||||||
|
# Bad
|
||||||
|
Edit the config file to add your token
|
||||||
|
```
|
||||||
|
|
||||||
|
✅ **Copy-paste ready**:
|
||||||
|
```bash
|
||||||
|
# Good
|
||||||
|
cat >> .env <<'EOF'
|
||||||
|
RAILWAY_TOKEN=paste-your-token-here
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
❌ **No verification**:
|
||||||
|
```bash
|
||||||
|
# Bad
|
||||||
|
railway up
|
||||||
|
# (did it work? who knows!)
|
||||||
|
```
|
||||||
|
|
||||||
|
✅ **With verification**:
|
||||||
|
```bash
|
||||||
|
# Good
|
||||||
|
railway up --service api-gateway
|
||||||
|
|
||||||
|
# Verify deployment
|
||||||
|
railway status
|
||||||
|
curl https://api.blackroad.io/health
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Template Variables
|
||||||
|
|
||||||
|
Use these placeholder patterns:
|
||||||
|
|
||||||
|
- `[ACTION]` - What's happening
|
||||||
|
- `[DIRECTORY]` - Path to work in
|
||||||
|
- `[SERVICE_NAME]` - Name of service
|
||||||
|
- `[DOMAIN]` - Domain name
|
||||||
|
- `your-token-here` - Placeholder for secrets
|
||||||
|
- `paste-your-value-here` - User must fill in
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Contributing New Patterns
|
||||||
|
|
||||||
|
When you discover a new copy-paste-ready pattern:
|
||||||
|
|
||||||
|
1. **Document it** in this file
|
||||||
|
2. **Test it** thoroughly
|
||||||
|
3. **Add comments** explaining each step
|
||||||
|
4. **Include verification** commands
|
||||||
|
5. **Commit** with descriptive message
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Add your new pattern to this file
|
||||||
|
cat >> templates/TERMINAL-COMMANDS-TEMPLATE.md <<'EOF'
|
||||||
|
|
||||||
|
### Pattern XX: [Your Pattern Name]
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# [Description]
|
||||||
|
[commands here]
|
||||||
|
```
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Commit
|
||||||
|
git add templates/TERMINAL-COMMANDS-TEMPLATE.md
|
||||||
|
git commit -m "docs: Add [Pattern Name] to terminal commands template"
|
||||||
|
git push origin main
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Copyright
|
||||||
|
|
||||||
|
```
|
||||||
|
# ============================================================================
|
||||||
|
# BlackRoad OS - Proprietary Software
|
||||||
|
# Copyright (c) 2025 BlackRoad OS, Inc. / Alexa Louise Amundson
|
||||||
|
# All Rights Reserved.
|
||||||
|
# ============================================================================
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Remember**: The best documentation is the kind you can copy, paste, and learn from simultaneously. Every command block should be a perfect, working example that teaches by doing.
|
||||||
153
templates/airtable/TEMPLATE-CRM-COMPLETE.json
Normal file
153
templates/airtable/TEMPLATE-CRM-COMPLETE.json
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
{
|
||||||
|
"name": "BlackRoad OS CRM",
|
||||||
|
"tables": [
|
||||||
|
{
|
||||||
|
"name": "Contacts",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "Name",
|
||||||
|
"type": "singleLineText"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Email",
|
||||||
|
"type": "email"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Phone",
|
||||||
|
"type": "phoneNumber"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Company",
|
||||||
|
"type": "singleLineText"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Role",
|
||||||
|
"type": "singleSelect",
|
||||||
|
"options": [
|
||||||
|
"Customer",
|
||||||
|
"Lead",
|
||||||
|
"Partner",
|
||||||
|
"Team"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Status",
|
||||||
|
"type": "singleSelect",
|
||||||
|
"options": [
|
||||||
|
"Active",
|
||||||
|
"Inactive",
|
||||||
|
"Archived"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tags",
|
||||||
|
"type": "multipleSelects"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Notes",
|
||||||
|
"type": "multilineText"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Created",
|
||||||
|
"type": "createdTime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Last Modified",
|
||||||
|
"type": "lastModifiedTime"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Deals",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "Deal Name",
|
||||||
|
"type": "singleLineText"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Contact",
|
||||||
|
"type": "multipleRecordLinks",
|
||||||
|
"linkedTable": "Contacts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Amount",
|
||||||
|
"type": "currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Stage",
|
||||||
|
"type": "singleSelect",
|
||||||
|
"options": [
|
||||||
|
"Lead",
|
||||||
|
"Qualified",
|
||||||
|
"Proposal",
|
||||||
|
"Negotiation",
|
||||||
|
"Closed Won",
|
||||||
|
"Closed Lost"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Probability",
|
||||||
|
"type": "percent"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Expected Close Date",
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Owner",
|
||||||
|
"type": "singleCollaborator"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Notes",
|
||||||
|
"type": "multilineText"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Activities",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "Activity",
|
||||||
|
"type": "singleLineText"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Type",
|
||||||
|
"type": "singleSelect",
|
||||||
|
"options": [
|
||||||
|
"Call",
|
||||||
|
"Email",
|
||||||
|
"Meeting",
|
||||||
|
"Demo",
|
||||||
|
"Follow-up"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Contact",
|
||||||
|
"type": "multipleRecordLinks",
|
||||||
|
"linkedTable": "Contacts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Deal",
|
||||||
|
"type": "multipleRecordLinks",
|
||||||
|
"linkedTable": "Deals"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Date",
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Duration",
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Notes",
|
||||||
|
"type": "multilineText"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Owner",
|
||||||
|
"type": "singleCollaborator"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
390
templates/dashboard_home.html
Normal file
390
templates/dashboard_home.html
Normal file
@@ -0,0 +1,390 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>BlackRoad OS - Dashboard</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--bg-primary: #020308;
|
||||||
|
--bg-secondary: rgba(6, 10, 30, 0.92);
|
||||||
|
--bg-card: rgba(12, 18, 40, 0.85);
|
||||||
|
--text-primary: #f5f5ff;
|
||||||
|
--text-muted: rgba(245, 245, 255, 0.7);
|
||||||
|
--accent-cyan: #00e5ff;
|
||||||
|
--accent-green: #1af59d;
|
||||||
|
--accent-yellow: #ffc400;
|
||||||
|
--accent-purple: #a855f7;
|
||||||
|
--accent-orange: #ff9d00;
|
||||||
|
--accent-pink: #ff0066;
|
||||||
|
--border-subtle: rgba(255, 255, 255, 0.1);
|
||||||
|
--gradient-brand: linear-gradient(135deg, #ff9d00, #ff0066, #7700ff, #0066ff);
|
||||||
|
}
|
||||||
|
|
||||||
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: system-ui, -apple-system, BlinkMacSystemFont, "SF Pro Text", sans-serif;
|
||||||
|
background: radial-gradient(circle at top, #050816 0, #020308 45%, #000000 100%);
|
||||||
|
color: var(--text-primary);
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page {
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 24px 16px 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header */
|
||||||
|
.header {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
font-size: 3rem;
|
||||||
|
font-weight: 700;
|
||||||
|
background: var(--gradient-brand);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tagline {
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Health Bar */
|
||||||
|
.health-bar {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 24px;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.health-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.health-dot {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.health-dot.ok { background: var(--accent-green); }
|
||||||
|
.health-dot.error { background: #ff4444; }
|
||||||
|
.health-dot.loading { background: var(--accent-yellow); animation: pulse 1s infinite; }
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0%, 100% { opacity: 1; }
|
||||||
|
50% { opacity: 0.4; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nav Cards Grid */
|
||||||
|
.nav-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-card {
|
||||||
|
background: var(--bg-card);
|
||||||
|
border: 1px solid var(--border-subtle);
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 24px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: inherit;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-card:hover {
|
||||||
|
transform: translateY(-4px);
|
||||||
|
border-color: rgba(255, 255, 255, 0.2);
|
||||||
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-card .icon {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-card .title {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-card .desc {
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: 0.9rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-card.quantum { border-left: 3px solid var(--accent-purple); }
|
||||||
|
.nav-card.learning { border-left: 3px solid var(--accent-green); }
|
||||||
|
.nav-card.models { border-left: 3px solid var(--accent-cyan); }
|
||||||
|
.nav-card.quests { border-left: 3px solid var(--accent-orange); }
|
||||||
|
.nav-card.status { border-left: 3px solid var(--accent-pink); }
|
||||||
|
|
||||||
|
/* Quick Stats Section */
|
||||||
|
.quick-stats {
|
||||||
|
margin-top: 32px;
|
||||||
|
padding: 24px;
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border-radius: 16px;
|
||||||
|
border: 1px solid var(--border-subtle);
|
||||||
|
}
|
||||||
|
|
||||||
|
.quick-stats h2 {
|
||||||
|
font-size: 1rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stats-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-item {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value {
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: 600;
|
||||||
|
font-family: "JetBrains Mono", monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value.xp { color: var(--accent-yellow); }
|
||||||
|
.stat-value.rank { color: var(--accent-purple); }
|
||||||
|
.stat-value.streak { color: var(--accent-orange); }
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Coach Card */
|
||||||
|
.coach-card {
|
||||||
|
margin-top: 24px;
|
||||||
|
padding: 20px 24px;
|
||||||
|
background: linear-gradient(135deg, rgba(168, 85, 247, 0.1), rgba(0, 229, 255, 0.05));
|
||||||
|
border: 1px solid rgba(168, 85, 247, 0.3);
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coach-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coach-header .sigma {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: var(--accent-purple);
|
||||||
|
}
|
||||||
|
|
||||||
|
.coach-header .title {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coach-action {
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coach-action strong {
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Footer */
|
||||||
|
.footer {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 48px;
|
||||||
|
padding-top: 24px;
|
||||||
|
border-top: 1px solid var(--border-subtle);
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mono {
|
||||||
|
font-family: "JetBrains Mono", ui-monospace, monospace;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="page">
|
||||||
|
<!-- Header -->
|
||||||
|
<div class="header">
|
||||||
|
<div class="logo">BlackRoad OS</div>
|
||||||
|
<div class="tagline">Ranked Quantum Operating System</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Health Bar -->
|
||||||
|
<div class="health-bar" id="health-bar">
|
||||||
|
<div class="health-item">
|
||||||
|
<span class="health-dot loading" id="health-console"></span>
|
||||||
|
<span>Console</span>
|
||||||
|
</div>
|
||||||
|
<div class="health-item">
|
||||||
|
<span class="health-dot loading" id="health-operator"></span>
|
||||||
|
<span>Operator</span>
|
||||||
|
</div>
|
||||||
|
<div class="health-item">
|
||||||
|
<span class="health-dot loading" id="health-quantum"></span>
|
||||||
|
<span>Quantum ψ</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Navigation Grid -->
|
||||||
|
<div class="nav-grid">
|
||||||
|
<a href="/quantum" class="nav-card quantum">
|
||||||
|
<div class="icon">ψ</div>
|
||||||
|
<div class="title">Quantum Console</div>
|
||||||
|
<div class="desc">Run predictions with quantum ML models. Visualize decision boundaries and train classifiers.</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="/learning" class="nav-card learning">
|
||||||
|
<div class="icon">Σ</div>
|
||||||
|
<div class="title">Learning History</div>
|
||||||
|
<div class="desc">Track your XP, rank, and learning streak. View completed lessons and quiz results.</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="/models" class="nav-card models">
|
||||||
|
<div class="icon">🔮</div>
|
||||||
|
<div class="title">Model Registry</div>
|
||||||
|
<div class="desc">Browse quantum models and their rank requirements. See your unlock progress.</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="/quests" class="nav-card quests">
|
||||||
|
<div class="icon">🎯</div>
|
||||||
|
<div class="title">Quests & Promotion</div>
|
||||||
|
<div class="desc">View your promotion path progress. Complete quests to earn badges and XP.</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="/status" class="nav-card status">
|
||||||
|
<div class="icon">📡</div>
|
||||||
|
<div class="title">System Status</div>
|
||||||
|
<div class="desc">Monitor service health, ledger events, and infrastructure status.</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Quick Stats -->
|
||||||
|
<div class="quick-stats" id="quick-stats">
|
||||||
|
<h2>Your Progress</h2>
|
||||||
|
<div class="stats-row">
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-value xp" id="stat-xp">--</div>
|
||||||
|
<div class="stat-label">Total XP</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-value rank" id="stat-rank">--</div>
|
||||||
|
<div class="stat-label">Current Rank</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-item">
|
||||||
|
<div class="stat-value streak" id="stat-streak">--</div>
|
||||||
|
<div class="stat-label">Day Streak</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Coach Card -->
|
||||||
|
<div class="coach-card" id="coach-card" style="display: none;">
|
||||||
|
<div class="coach-header">
|
||||||
|
<span class="sigma">Σ</span>
|
||||||
|
<span class="title">Coach Suggestion</span>
|
||||||
|
</div>
|
||||||
|
<div class="coach-action" id="coach-action">Loading...</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
<div class="footer">
|
||||||
|
<p>BlackRoad OS v0.2 · <span class="mono">© 2025 BlackRoad OS, Inc.</span></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Fetch health status
|
||||||
|
async function checkHealth() {
|
||||||
|
try {
|
||||||
|
const res = await fetch('/api/health');
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
document.getElementById('health-console').className =
|
||||||
|
'health-dot ' + (data.services?.console?.ok ? 'ok' : 'error');
|
||||||
|
document.getElementById('health-operator').className =
|
||||||
|
'health-dot ' + (data.services?.operator?.ok ? 'ok' : 'error');
|
||||||
|
document.getElementById('health-quantum').className =
|
||||||
|
'health-dot ' + (data.services?.quantum?.ok ? 'ok' : 'error');
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Health check failed:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch stats
|
||||||
|
async function loadStats() {
|
||||||
|
try {
|
||||||
|
const res = await fetch('/api/learning/stats');
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
if (data.ok && data.stats) {
|
||||||
|
document.getElementById('stat-xp').textContent = data.stats.xp || 0;
|
||||||
|
document.getElementById('stat-rank').textContent =
|
||||||
|
data.stats.rank?.rank_name || 'Novice';
|
||||||
|
document.getElementById('stat-streak').textContent =
|
||||||
|
data.stats.current_streak_days || 0;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Stats load failed:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch coach suggestion
|
||||||
|
async function loadCoach() {
|
||||||
|
try {
|
||||||
|
const res = await fetch('/api/promotion/coach');
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
if (data.ok && data.suggestion) {
|
||||||
|
const s = data.suggestion;
|
||||||
|
const coachCard = document.getElementById('coach-card');
|
||||||
|
coachCard.style.display = 'block';
|
||||||
|
|
||||||
|
if (s.stage_id === 'complete') {
|
||||||
|
document.getElementById('coach-action').innerHTML =
|
||||||
|
'<strong>Path Complete!</strong> ' + (s.action || 'All goals achieved.');
|
||||||
|
} else {
|
||||||
|
document.getElementById('coach-action').innerHTML =
|
||||||
|
'<strong>Next:</strong> ' + (s.action || 'Keep going!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Coach load failed:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init
|
||||||
|
checkHealth();
|
||||||
|
loadStats();
|
||||||
|
loadCoach();
|
||||||
|
|
||||||
|
// Refresh health every 30s
|
||||||
|
setInterval(checkHealth, 30000);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
44
templates/github/ISSUE_TEMPLATE/bug_report.md
Normal file
44
templates/github/ISSUE_TEMPLATE/bug_report.md
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
---
|
||||||
|
name: 🐛 Bug Report
|
||||||
|
about: Report a bug to help us improve
|
||||||
|
title: '[BUG] '
|
||||||
|
labels: bug
|
||||||
|
assignees: ''
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🐛 Bug Description
|
||||||
|
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
## 🔄 Steps to Reproduce
|
||||||
|
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '...'
|
||||||
|
3. Scroll down to '...'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
## ✅ Expected Behavior
|
||||||
|
|
||||||
|
A clear description of what you expected to happen.
|
||||||
|
|
||||||
|
## ❌ Actual Behavior
|
||||||
|
|
||||||
|
What actually happened instead.
|
||||||
|
|
||||||
|
## 📸 Screenshots
|
||||||
|
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
## 🖥 Environment
|
||||||
|
|
||||||
|
- OS: [e.g. macOS, Windows, Linux]
|
||||||
|
- Browser: [e.g. Chrome, Safari, Firefox]
|
||||||
|
- Version: [e.g. 22]
|
||||||
|
|
||||||
|
## 📝 Additional Context
|
||||||
|
|
||||||
|
Add any other context about the problem here.
|
||||||
|
|
||||||
|
## 🔍 Possible Solution
|
||||||
|
|
||||||
|
If you have ideas on how to solve this, please share!
|
||||||
35
templates/github/ISSUE_TEMPLATE/feature_request.md
Normal file
35
templates/github/ISSUE_TEMPLATE/feature_request.md
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
name: ✨ Feature Request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: '[FEATURE] '
|
||||||
|
labels: enhancement
|
||||||
|
assignees: ''
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✨ Feature Description
|
||||||
|
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
## 🎯 Problem Statement
|
||||||
|
|
||||||
|
What problem does this feature solve?
|
||||||
|
|
||||||
|
## 💡 Proposed Solution
|
||||||
|
|
||||||
|
Describe the solution you'd like.
|
||||||
|
|
||||||
|
## 🔄 Alternatives Considered
|
||||||
|
|
||||||
|
Describe alternatives you've considered.
|
||||||
|
|
||||||
|
## 📊 Benefits
|
||||||
|
|
||||||
|
What are the benefits of this feature?
|
||||||
|
|
||||||
|
## 🚧 Implementation Notes
|
||||||
|
|
||||||
|
Any technical considerations or implementation ideas.
|
||||||
|
|
||||||
|
## 📝 Additional Context
|
||||||
|
|
||||||
|
Add any other context, mockups, or screenshots about the feature here.
|
||||||
48
templates/github/PULL_REQUEST_TEMPLATE.md
Normal file
48
templates/github/PULL_REQUEST_TEMPLATE.md
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
## 📋 Description
|
||||||
|
|
||||||
|
<!-- Describe your changes in detail -->
|
||||||
|
|
||||||
|
## 🎯 Related Issue
|
||||||
|
|
||||||
|
<!-- Link to the issue this PR addresses -->
|
||||||
|
Fixes #
|
||||||
|
|
||||||
|
## 🔄 Type of Change
|
||||||
|
|
||||||
|
<!-- Mark the relevant option -->
|
||||||
|
- [ ] 🐛 Bug fix (non-breaking change which fixes an issue)
|
||||||
|
- [ ] ✨ New feature (non-breaking change which adds functionality)
|
||||||
|
- [ ] 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||||
|
- [ ] 📚 Documentation update
|
||||||
|
- [ ] ♻️ Refactoring (no functional changes)
|
||||||
|
- [ ] 🎨 UI/UX improvements
|
||||||
|
- [ ] ⚡️ Performance improvements
|
||||||
|
|
||||||
|
## ✅ Checklist
|
||||||
|
|
||||||
|
- [ ] My code follows the code style of this project
|
||||||
|
- [ ] I have performed a self-review of my own code
|
||||||
|
- [ ] I have commented my code, particularly in hard-to-understand areas
|
||||||
|
- [ ] I have made corresponding changes to the documentation
|
||||||
|
- [ ] My changes generate no new warnings
|
||||||
|
- [ ] I have added tests that prove my fix is effective or that my feature works
|
||||||
|
- [ ] New and existing unit tests pass locally with my changes
|
||||||
|
- [ ] Any dependent changes have been merged and published
|
||||||
|
|
||||||
|
## 🧪 Testing
|
||||||
|
|
||||||
|
<!-- Describe the tests you ran to verify your changes -->
|
||||||
|
|
||||||
|
## 📸 Screenshots (if applicable)
|
||||||
|
|
||||||
|
<!-- Add screenshots to demonstrate visual changes -->
|
||||||
|
|
||||||
|
## 📝 Additional Notes
|
||||||
|
|
||||||
|
<!-- Add any other notes about the PR here -->
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
✨ Generated with [Claude Code](https://claude.com/claude-code)
|
||||||
|
|
||||||
|
Co-Authored-By: Claude <noreply@anthropic.com>
|
||||||
94
templates/google-drive/PROJECT-STRUCTURE-TEMPLATE.json
Normal file
94
templates/google-drive/PROJECT-STRUCTURE-TEMPLATE.json
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
{
|
||||||
|
"name": "TEMPLATE-PROJECT-FOLDER",
|
||||||
|
"folders": [
|
||||||
|
{
|
||||||
|
"name": "00-PROJECT-CHARTER",
|
||||||
|
"type": "folder"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "01-ROADMAP",
|
||||||
|
"type": "folder"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "02-TEAM-ROSTER",
|
||||||
|
"type": "folder"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "03-MEETING-NOTES",
|
||||||
|
"type": "folder"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "04-DELIVERABLES",
|
||||||
|
"type": "folder"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "05-RESOURCES",
|
||||||
|
"type": "folder"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"name": "PROJECT-CHARTER.gdoc",
|
||||||
|
"type": "document",
|
||||||
|
"content": {
|
||||||
|
"title": "{{PROJECT_NAME}} - Project Charter",
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"heading": "\ud83d\udccb Project Overview",
|
||||||
|
"content": "{{PROJECT_DESCRIPTION}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heading": "\ud83c\udfaf Objectives",
|
||||||
|
"content": "{{OBJECTIVES}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heading": "\ud83d\udc65 Team",
|
||||||
|
"content": "{{TEAM_MEMBERS}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heading": "\ud83d\udcc6 Timeline",
|
||||||
|
"content": "{{TIMELINE}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heading": "\ud83d\udcb0 Budget",
|
||||||
|
"content": "{{BUDGET}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heading": "\ud83d\ude80 Success Criteria",
|
||||||
|
"content": "{{SUCCESS_CRITERIA}}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ROADMAP.gsheet",
|
||||||
|
"type": "spreadsheet",
|
||||||
|
"content": {
|
||||||
|
"sheets": [
|
||||||
|
{
|
||||||
|
"name": "Timeline",
|
||||||
|
"columns": [
|
||||||
|
"Phase",
|
||||||
|
"Start Date",
|
||||||
|
"End Date",
|
||||||
|
"Status",
|
||||||
|
"Owner",
|
||||||
|
"Dependencies"
|
||||||
|
],
|
||||||
|
"rows": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Milestones",
|
||||||
|
"columns": [
|
||||||
|
"Milestone",
|
||||||
|
"Target Date",
|
||||||
|
"Status",
|
||||||
|
"Deliverables"
|
||||||
|
],
|
||||||
|
"rows": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
25
templates/google-drive/TEMPLATE-DOC-MEETING-NOTES.json
Normal file
25
templates/google-drive/TEMPLATE-DOC-MEETING-NOTES.json
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"title": "{{MEETING_TITLE}} - {{DATE}}",
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"heading": "\ud83d\udcc5 Meeting Info",
|
||||||
|
"content": "Date: {{DATE}}\nTime: {{TIME}}\nAttendees: {{ATTENDEES}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heading": "\ud83c\udfaf Agenda",
|
||||||
|
"content": "{{AGENDA}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heading": "\ud83d\udcdd Discussion",
|
||||||
|
"content": "{{DISCUSSION}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heading": "\u2705 Action Items",
|
||||||
|
"content": "{{ACTION_ITEMS}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heading": "\ud83d\udd1c Next Steps",
|
||||||
|
"content": "{{NEXT_STEPS}}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
33
templates/google-drive/TEMPLATE-DOC-TECHNICAL-SPEC.json
Normal file
33
templates/google-drive/TEMPLATE-DOC-TECHNICAL-SPEC.json
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"title": "{{PROJECT_NAME}} - Technical Specification",
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"heading": "\ud83c\udfaf Overview",
|
||||||
|
"content": "{{OVERVIEW}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heading": "\ud83c\udfd7\ufe0f Architecture",
|
||||||
|
"content": "{{ARCHITECTURE}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heading": "\ud83d\udcca Data Models",
|
||||||
|
"content": "{{DATA_MODELS}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heading": "\ud83d\udd0c API Endpoints",
|
||||||
|
"content": "{{API_ENDPOINTS}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heading": "\ud83d\udd10 Security",
|
||||||
|
"content": "{{SECURITY}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heading": "\ud83d\udcc8 Performance",
|
||||||
|
"content": "{{PERFORMANCE}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heading": "\ud83e\uddea Testing Strategy",
|
||||||
|
"content": "{{TESTING}}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
29
templates/google-drive/TEMPLATE-DOC-USER-GUIDE.json
Normal file
29
templates/google-drive/TEMPLATE-DOC-USER-GUIDE.json
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"title": "{{PROJECT_NAME}} - User Guide",
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"heading": "\ud83d\udc4b Welcome",
|
||||||
|
"content": "{{WELCOME}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heading": "\ud83d\ude80 Getting Started",
|
||||||
|
"content": "{{GETTING_STARTED}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heading": "\ud83d\udcd6 Features",
|
||||||
|
"content": "{{FEATURES}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heading": "\ud83c\udfaf How-To Guides",
|
||||||
|
"content": "{{HOW_TO}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heading": "\u26a0\ufe0f Troubleshooting",
|
||||||
|
"content": "{{TROUBLESHOOTING}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heading": "\u2753 FAQ",
|
||||||
|
"content": "{{FAQ}}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
515
templates/learning_history.html
Normal file
515
templates/learning_history.html
Normal file
@@ -0,0 +1,515 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>Learning History - BlackRoad OS (Σ)</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--bg-primary: #020308;
|
||||||
|
--bg-secondary: rgba(6, 10, 30, 0.92);
|
||||||
|
--text-primary: #f5f5ff;
|
||||||
|
--text-muted: rgba(245, 245, 255, 0.7);
|
||||||
|
--accent-cyan: #00e5ff;
|
||||||
|
--accent-green: #1af59d;
|
||||||
|
--accent-yellow: #ffc400;
|
||||||
|
--accent-purple: #a855f7;
|
||||||
|
--accent-orange: #ff9d00;
|
||||||
|
--border-subtle: rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: system-ui, -apple-system, BlinkMacSystemFont, "SF Pro Text", sans-serif;
|
||||||
|
background: radial-gradient(circle at top, #050816 0, #020308 45%, #000000 100%);
|
||||||
|
color: var(--text-primary);
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page {
|
||||||
|
max-width: 960px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 24px 16px 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin: 0 0 8px;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 .sigma {
|
||||||
|
color: var(--accent-purple);
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin: 0 0 12px;
|
||||||
|
font-size: 1rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.muted {
|
||||||
|
opacity: 0.7;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mono {
|
||||||
|
font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Monaco,
|
||||||
|
Consolas, "Liberation Mono", "Courier New", monospace;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel {
|
||||||
|
border-radius: 16px;
|
||||||
|
border: 1px solid var(--border-subtle);
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
padding: 16px 18px;
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stats Grid */
|
||||||
|
.stats-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-label {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value {
|
||||||
|
font-family: "JetBrains Mono", monospace;
|
||||||
|
font-size: 1.8rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value.xp {
|
||||||
|
color: var(--accent-yellow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value.lessons {
|
||||||
|
color: var(--accent-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-value.streak {
|
||||||
|
color: var(--accent-orange);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rank Card */
|
||||||
|
.rank-card {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16px;
|
||||||
|
padding: 16px;
|
||||||
|
background: rgba(168, 85, 247, 0.08);
|
||||||
|
border: 1px solid rgba(168, 85, 247, 0.3);
|
||||||
|
border-radius: 12px;
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rank-badge {
|
||||||
|
width: 56px;
|
||||||
|
height: 56px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: linear-gradient(135deg, var(--accent-purple), var(--accent-cyan));
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: white;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rank-info {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rank-name {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rank-progress-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rank-progress-bar {
|
||||||
|
flex: 1;
|
||||||
|
height: 8px;
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rank-progress-fill {
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(90deg, var(--accent-purple), var(--accent-cyan));
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: width 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rank-progress-text {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Event List */
|
||||||
|
.event-row {
|
||||||
|
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
|
||||||
|
padding: 12px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-row:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-main {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-meta {
|
||||||
|
text-align: right;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 3px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
|
font-size: 0.75rem;
|
||||||
|
margin-right: 6px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag.lesson {
|
||||||
|
border-color: rgba(26, 245, 157, 0.6);
|
||||||
|
background: rgba(26, 245, 157, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag.quiz {
|
||||||
|
border-color: rgba(0, 180, 255, 0.7);
|
||||||
|
background: rgba(0, 180, 255, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag.graded {
|
||||||
|
border-color: rgba(255, 196, 0, 0.8);
|
||||||
|
background: rgba(255, 196, 0, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag.rank-up {
|
||||||
|
border-color: rgba(168, 85, 247, 0.8);
|
||||||
|
background: rgba(168, 85, 247, 0.15);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rank-up-card {
|
||||||
|
background: linear-gradient(135deg, rgba(168, 85, 247, 0.12), rgba(0, 229, 255, 0.08));
|
||||||
|
border: 1px solid rgba(168, 85, 247, 0.4);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 12px 16px;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rank-up-title {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--accent-purple);
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rank-arrow {
|
||||||
|
color: var(--accent-cyan);
|
||||||
|
margin: 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.score-pill {
|
||||||
|
padding: 2px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: rgba(255, 196, 0, 0.15);
|
||||||
|
border: 1px solid rgba(255, 196, 0, 0.5);
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.score-pill.perfect {
|
||||||
|
background: rgba(26, 245, 157, 0.15);
|
||||||
|
border-color: rgba(26, 245, 157, 0.5);
|
||||||
|
color: var(--accent-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
.small {
|
||||||
|
font-size: 0.78rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.results-list {
|
||||||
|
margin-top: 8px;
|
||||||
|
padding-left: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-icon {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-icon.correct {
|
||||||
|
color: var(--accent-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-icon.incorrect {
|
||||||
|
color: #ff6b6b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Links */
|
||||||
|
a {
|
||||||
|
color: #66b2ff;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Empty state */
|
||||||
|
.empty-state {
|
||||||
|
text-align: center;
|
||||||
|
padding: 32px 16px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-state .icon {
|
||||||
|
font-size: 3rem;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tips panel */
|
||||||
|
.tips-list {
|
||||||
|
margin: 8px 0 0 0;
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tips-list li {
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="page">
|
||||||
|
<div style="margin-bottom: 24px;">
|
||||||
|
<a href="/" style="color: #00e5ff; text-decoration: none; font-size: 0.9rem;">← Dashboard</a>
|
||||||
|
</div>
|
||||||
|
<h1><span class="sigma">Σ</span> Learning History</h1>
|
||||||
|
<p class="muted">
|
||||||
|
Actor: <span class="mono">{{ actor }}</span><br />
|
||||||
|
Tracking: <span class="mono">lesson.completed</span>,
|
||||||
|
<span class="mono">quiz.submitted</span>,
|
||||||
|
<span class="mono">quiz.graded</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{% if stats_error %}
|
||||||
|
<div class="panel">
|
||||||
|
<div class="muted small">Error loading stats: {{ stats_error }}</div>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<!-- Stats Summary -->
|
||||||
|
<div class="panel">
|
||||||
|
<div class="stats-grid">
|
||||||
|
<div class="stat-card">
|
||||||
|
<div class="stat-label">Total XP</div>
|
||||||
|
<div class="stat-value xp">{{ stats.xp or 0 }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<div class="stat-label">Lessons</div>
|
||||||
|
<div class="stat-value lessons">{{ stats.lessons_completed or 0 }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<div class="stat-label">Quizzes</div>
|
||||||
|
<div class="stat-value">{{ stats.quizzes_graded or 0 }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<div class="stat-label">Current Streak</div>
|
||||||
|
<div class="stat-value streak">
|
||||||
|
{{ stats.current_streak_days or 0 }}
|
||||||
|
<span class="small">day{{ 's' if (stats.current_streak_days or 0) != 1 else '' }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<div class="stat-label">Best Streak</div>
|
||||||
|
<div class="stat-value">
|
||||||
|
{{ stats.longest_streak_days or 0 }}
|
||||||
|
<span class="small">day{{ 's' if (stats.longest_streak_days or 0) != 1 else '' }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card">
|
||||||
|
<div class="stat-label">Last Active</div>
|
||||||
|
<div class="mono small" style="margin-top: 8px;">
|
||||||
|
{{ stats.last_active_date or "Never" }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if stats.rank %}
|
||||||
|
<!-- Rank Card -->
|
||||||
|
<div class="rank-card">
|
||||||
|
<div class="rank-badge">
|
||||||
|
{{ stats.rank.rank_index + 1 }}
|
||||||
|
</div>
|
||||||
|
<div class="rank-info">
|
||||||
|
<div class="rank-name">{{ stats.rank.rank_name }}</div>
|
||||||
|
{% if stats.rank.next_rank_name %}
|
||||||
|
<div class="rank-progress-container">
|
||||||
|
<div class="rank-progress-bar">
|
||||||
|
<div class="rank-progress-fill" style="width: {{ (stats.rank.progress * 100)|int }}%;"></div>
|
||||||
|
</div>
|
||||||
|
<div class="rank-progress-text">
|
||||||
|
{{ stats.rank.xp }} / {{ stats.rank.xp_for_next }} XP to {{ stats.rank.next_rank_name }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div class="rank-progress-text">Max rank achieved!</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if events_error %}
|
||||||
|
<div class="panel">
|
||||||
|
<div class="muted small">Error loading events: {{ events_error }}</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<!-- Events List -->
|
||||||
|
<div class="panel">
|
||||||
|
<h2>Activity Log</h2>
|
||||||
|
{% if not events %}
|
||||||
|
<div class="empty-state">
|
||||||
|
<div class="icon">📚</div>
|
||||||
|
<p>No learning events recorded yet.</p>
|
||||||
|
<p class="small">Complete a Math Lab lesson to get started!</p>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{% for e in events %}
|
||||||
|
<div class="event-row">
|
||||||
|
<div class="event-main">
|
||||||
|
<div>
|
||||||
|
{% if e.event_type == "lesson.completed" %}
|
||||||
|
<span class="tag lesson">Lesson {{ e.lesson }} completed</span>
|
||||||
|
{% elif e.event_type == "quiz.submitted" %}
|
||||||
|
<span class="tag quiz">Quiz submitted (L{{ e.lesson }})</span>
|
||||||
|
{% elif e.event_type == "quiz.graded" %}
|
||||||
|
<span class="tag graded">Quiz graded (L{{ e.lesson }})</span>
|
||||||
|
{% elif e.event_type == "rank.changed" %}
|
||||||
|
<span class="tag rank-up">🎖️ Rank Up!</span>
|
||||||
|
{% else %}
|
||||||
|
<span class="tag">{{ e.event_type }}</span>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if e.event_type == "lesson.completed" %}
|
||||||
|
<div class="small muted">
|
||||||
|
Track: <span class="mono">{{ e.track }}</span>
|
||||||
|
{% if e.metadata and e.metadata.title %}
|
||||||
|
- {{ e.metadata.title }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% elif e.event_type == "quiz.graded" %}
|
||||||
|
<div class="small">
|
||||||
|
Score:
|
||||||
|
{% if e.score is not none %}
|
||||||
|
{% set score_pct = (e.score * 100)|int %}
|
||||||
|
<span class="score-pill {{ 'perfect' if score_pct == 100 else '' }}">
|
||||||
|
{{ score_pct }}%
|
||||||
|
</span>
|
||||||
|
{% if score_pct == 100 %}
|
||||||
|
<span style="margin-left: 4px;">Perfect!</span>
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
<span class="muted">n/a</span>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% elif e.event_type == "rank.changed" %}
|
||||||
|
<div class="rank-up-card">
|
||||||
|
<div class="rank-up-title">
|
||||||
|
{{ e.old_rank or "New" }}
|
||||||
|
<span class="rank-arrow">→</span>
|
||||||
|
{{ e.new_rank }}
|
||||||
|
</div>
|
||||||
|
<div class="small muted" style="margin-top: 4px;">
|
||||||
|
XP: <span class="mono">{{ e.xp or 0 }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="event-meta">
|
||||||
|
<div class="mono">
|
||||||
|
{{ (e.timestamp or "")[:19] }}
|
||||||
|
</div>
|
||||||
|
{% if e.node_id %}
|
||||||
|
<div class="small">node: <span class="mono">{{ e.node_id }}</span></div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if e.event_type == "quiz.graded" and e.results %}
|
||||||
|
<div class="results-list">
|
||||||
|
{% for r in e.results %}
|
||||||
|
<div class="result-item mono small">
|
||||||
|
<span class="result-icon {{ 'correct' if r.correct else 'incorrect' }}">
|
||||||
|
{{ "✓" if r.correct else "✗" }}
|
||||||
|
</span>
|
||||||
|
<span>{{ r.id }}: {{ r.feedback[:60] }}{{ '...' if r.feedback|length > 60 else '' }}</span>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Tips -->
|
||||||
|
<div class="panel">
|
||||||
|
<h2>How to Earn XP</h2>
|
||||||
|
<ul class="tips-list small">
|
||||||
|
<li><strong>+10 XP</strong> - Complete a Math Lab lesson</li>
|
||||||
|
<li><strong>+2 XP</strong> - Submit a quiz</li>
|
||||||
|
<li><strong>+0-20 XP</strong> - Quiz graded (score × 20)</li>
|
||||||
|
<li>Keep a streak going by learning every day!</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
424
templates/models_page.html
Normal file
424
templates/models_page.html
Normal file
@@ -0,0 +1,424 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>ψ Model Registry - BlackRoad OS</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--bg-primary: #020308;
|
||||||
|
--bg-secondary: rgba(6, 10, 30, 0.92);
|
||||||
|
--bg-card: rgba(12, 18, 40, 0.85);
|
||||||
|
--text-primary: #f5f5ff;
|
||||||
|
--text-muted: rgba(245, 245, 255, 0.7);
|
||||||
|
--accent-cyan: #00e5ff;
|
||||||
|
--accent-green: #1af59d;
|
||||||
|
--accent-yellow: #ffc400;
|
||||||
|
--accent-purple: #a855f7;
|
||||||
|
--accent-orange: #ff9d00;
|
||||||
|
--accent-pink: #ff0066;
|
||||||
|
--border-subtle: rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: system-ui, -apple-system, BlinkMacSystemFont, "SF Pro Text", sans-serif;
|
||||||
|
background: radial-gradient(circle at top, #050816 0, #020308 45%, #000000 100%);
|
||||||
|
color: var(--text-primary);
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page {
|
||||||
|
max-width: 1000px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 24px 16px 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nav */
|
||||||
|
.nav {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav a {
|
||||||
|
color: var(--accent-cyan);
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header */
|
||||||
|
h1 {
|
||||||
|
font-size: 1.8rem;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 .psi {
|
||||||
|
color: var(--accent-purple);
|
||||||
|
font-size: 2.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: 0.95rem;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mono {
|
||||||
|
font-family: "JetBrains Mono", ui-monospace, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rank Info */
|
||||||
|
.rank-info {
|
||||||
|
background: linear-gradient(135deg, rgba(168, 85, 247, 0.1), rgba(0, 229, 255, 0.05));
|
||||||
|
border: 1px solid rgba(168, 85, 247, 0.3);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 16px 20px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rank-badge {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: linear-gradient(135deg, var(--accent-purple), var(--accent-cyan));
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rank-details {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rank-name {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rank-progress {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skill Tree */
|
||||||
|
.skill-tree {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-section {
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-section-title {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
margin-bottom: 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-section-title::before {
|
||||||
|
content: "";
|
||||||
|
flex: 1;
|
||||||
|
height: 1px;
|
||||||
|
background: var(--border-subtle);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-section-title::after {
|
||||||
|
content: "";
|
||||||
|
flex: 1;
|
||||||
|
height: 1px;
|
||||||
|
background: var(--border-subtle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Model Cards */
|
||||||
|
.model-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-card {
|
||||||
|
background: var(--bg-card);
|
||||||
|
border: 1px solid var(--border-subtle);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 20px;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-card.unlocked {
|
||||||
|
border-color: rgba(26, 245, 157, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-card.locked {
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-card.locked:hover {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-id {
|
||||||
|
font-family: "JetBrains Mono", monospace;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--accent-cyan);
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-status {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
padding: 3px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-status.unlocked {
|
||||||
|
background: rgba(26, 245, 157, 0.15);
|
||||||
|
border: 1px solid rgba(26, 245, 157, 0.4);
|
||||||
|
color: var(--accent-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-status.locked {
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-name {
|
||||||
|
font-size: 1rem;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-desc {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
margin-bottom: 12px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-meta {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-meta span {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-requires {
|
||||||
|
margin-top: 12px;
|
||||||
|
padding-top: 12px;
|
||||||
|
border-top: 1px solid var(--border-subtle);
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-requires .label {
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.model-requires .rank {
|
||||||
|
color: var(--accent-purple);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loading State */
|
||||||
|
.loading {
|
||||||
|
text-align: center;
|
||||||
|
padding: 48px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading .spinner {
|
||||||
|
font-size: 2rem;
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
from { transform: rotate(0deg); }
|
||||||
|
to { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Error State */
|
||||||
|
.error-state {
|
||||||
|
text-align: center;
|
||||||
|
padding: 32px;
|
||||||
|
background: rgba(255, 68, 68, 0.1);
|
||||||
|
border: 1px solid rgba(255, 68, 68, 0.3);
|
||||||
|
border-radius: 12px;
|
||||||
|
color: #ff6b6b;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="page">
|
||||||
|
<!-- Navigation -->
|
||||||
|
<div class="nav">
|
||||||
|
<a href="/">← Dashboard</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Header -->
|
||||||
|
<h1><span class="psi">ψ</span> Model Registry</h1>
|
||||||
|
<p class="subtitle">
|
||||||
|
Quantum ML models unlock as your rank increases.
|
||||||
|
Actor: <span class="mono">{{ actor }}</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- Rank Info -->
|
||||||
|
<div class="rank-info" id="rank-info">
|
||||||
|
<div class="rank-badge" id="rank-badge">?</div>
|
||||||
|
<div class="rank-details">
|
||||||
|
<div class="rank-name" id="rank-name">Loading...</div>
|
||||||
|
<div class="rank-progress" id="rank-progress"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Skill Tree -->
|
||||||
|
<div class="skill-tree" id="skill-tree">
|
||||||
|
<div class="loading">
|
||||||
|
<div class="spinner">ψ</div>
|
||||||
|
<p>Loading models...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const actor = "{{ actor }}";
|
||||||
|
|
||||||
|
// Rank order for grouping
|
||||||
|
const RANK_ORDER = [
|
||||||
|
"Novice", "Apprentice", "Practitioner", "Operator",
|
||||||
|
"Quantum Adept", "Math Wizard", "Σ Master", "BlackRoad Sage"
|
||||||
|
];
|
||||||
|
|
||||||
|
async function loadStats() {
|
||||||
|
try {
|
||||||
|
const res = await fetch(`/api/learning/stats?actor=${actor}`);
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
if (data.ok && data.stats) {
|
||||||
|
const rank = data.stats.rank || {};
|
||||||
|
document.getElementById('rank-badge').textContent = (rank.rank_index || 0) + 1;
|
||||||
|
document.getElementById('rank-name').textContent = rank.rank_name || 'Novice';
|
||||||
|
|
||||||
|
if (rank.next_rank_name) {
|
||||||
|
document.getElementById('rank-progress').textContent =
|
||||||
|
`${data.stats.xp} / ${rank.xp_for_next} XP to ${rank.next_rank_name}`;
|
||||||
|
} else {
|
||||||
|
document.getElementById('rank-progress').textContent = 'Max rank achieved!';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to load stats:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadModels() {
|
||||||
|
const container = document.getElementById('skill-tree');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await fetch(`/api/models?actor=${actor}`);
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
if (!data.ok) {
|
||||||
|
container.innerHTML = `
|
||||||
|
<div class="error-state">
|
||||||
|
<p>Failed to load models: ${data.error || 'Unknown error'}</p>
|
||||||
|
<p style="margin-top: 8px; font-size: 0.85rem;">
|
||||||
|
Make sure the Quantum node is running.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const models = data.data?.models || [];
|
||||||
|
|
||||||
|
// Group by required rank
|
||||||
|
const byRank = {};
|
||||||
|
for (const m of models) {
|
||||||
|
const req = m.required_rank || 'Unknown';
|
||||||
|
if (!byRank[req]) byRank[req] = [];
|
||||||
|
byRank[req].push(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
let html = '';
|
||||||
|
|
||||||
|
for (const rank of RANK_ORDER) {
|
||||||
|
if (!byRank[rank] || byRank[rank].length === 0) continue;
|
||||||
|
|
||||||
|
html += `
|
||||||
|
<div class="tree-section">
|
||||||
|
<div class="tree-section-title">${rank}</div>
|
||||||
|
<div class="model-grid">
|
||||||
|
`;
|
||||||
|
|
||||||
|
for (const m of byRank[rank]) {
|
||||||
|
const unlocked = m.available !== false;
|
||||||
|
const statusClass = unlocked ? 'unlocked' : 'locked';
|
||||||
|
const statusText = unlocked ? '🔓 Unlocked' : '🔒 Locked';
|
||||||
|
|
||||||
|
html += `
|
||||||
|
<div class="model-card ${statusClass}">
|
||||||
|
<div class="model-header">
|
||||||
|
<div class="model-id">${m.model_id}</div>
|
||||||
|
<div class="model-status ${statusClass}">${statusText}</div>
|
||||||
|
</div>
|
||||||
|
<div class="model-name">${m.name || m.model_id}</div>
|
||||||
|
<div class="model-desc">${m.description || 'No description available.'}</div>
|
||||||
|
<div class="model-meta">
|
||||||
|
<span>🔮 ${m.qubits || '?'} qubits</span>
|
||||||
|
<span>📦 ${m.kind || 'classifier'}</span>
|
||||||
|
<span>📊 ${m.status || 'unknown'}</span>
|
||||||
|
</div>
|
||||||
|
<div class="model-requires">
|
||||||
|
<span class="label">Requires:</span>
|
||||||
|
<span class="rank">${m.required_rank}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
html += '</div></div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
container.innerHTML = html || '<p style="color: var(--text-muted);">No models found.</p>';
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
container.innerHTML = `
|
||||||
|
<div class="error-state">
|
||||||
|
<p>Failed to load models: ${e.message}</p>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init
|
||||||
|
loadStats();
|
||||||
|
loadModels();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
74
templates/notion/TEMPLATE-DASHBOARD-PROJECT.json
Normal file
74
templates/notion/TEMPLATE-DASHBOARD-PROJECT.json
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
{
|
||||||
|
"object": "page",
|
||||||
|
"parent": {
|
||||||
|
"type": "workspace"
|
||||||
|
},
|
||||||
|
"icon": {
|
||||||
|
"type": "emoji",
|
||||||
|
"emoji": "\ud83c\udfaf"
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"title": {
|
||||||
|
"title": [
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"content": "{{PROJECT_NAME}}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"object": "heading_1",
|
||||||
|
"heading_1": {
|
||||||
|
"rich_text": [
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"content": "\ud83d\udcca Project Dashboard"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"object": "paragraph",
|
||||||
|
"paragraph": {
|
||||||
|
"rich_text": [
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"content": "{{PROJECT_DESCRIPTION}}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"object": "heading_2",
|
||||||
|
"heading_2": {
|
||||||
|
"rich_text": [
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"content": "\ud83d\udcc8 Status"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"object": "callout",
|
||||||
|
"callout": {
|
||||||
|
"icon": {
|
||||||
|
"emoji": "\u2705"
|
||||||
|
},
|
||||||
|
"rich_text": [
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"content": "Status: {{STATUS}}\nPhase: {{PHASE}}\nProgress: {{PROGRESS}}%"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
73
templates/notion/TEMPLATE-DATABASE-TASKS.json
Normal file
73
templates/notion/TEMPLATE-DATABASE-TASKS.json
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
{
|
||||||
|
"parent": {
|
||||||
|
"type": "page_id",
|
||||||
|
"page_id": "{{PARENT_PAGE_ID}}"
|
||||||
|
},
|
||||||
|
"title": [
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"text": {
|
||||||
|
"content": "Tasks"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"Name": {
|
||||||
|
"title": {}
|
||||||
|
},
|
||||||
|
"Status": {
|
||||||
|
"select": {
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"name": "Todo",
|
||||||
|
"color": "gray"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "In Progress",
|
||||||
|
"color": "blue"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Done",
|
||||||
|
"color": "green"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Blocked",
|
||||||
|
"color": "red"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Priority": {
|
||||||
|
"select": {
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"name": "High",
|
||||||
|
"color": "red"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Medium",
|
||||||
|
"color": "yellow"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Low",
|
||||||
|
"color": "gray"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Assignee": {
|
||||||
|
"people": {}
|
||||||
|
},
|
||||||
|
"Due Date": {
|
||||||
|
"date": {}
|
||||||
|
},
|
||||||
|
"Tags": {
|
||||||
|
"multi_select": {}
|
||||||
|
},
|
||||||
|
"Estimate": {
|
||||||
|
"number": {
|
||||||
|
"format": "number"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
131
templates/notion/TEMPLATE-PAGE-AGENT-PROFILE.json
Normal file
131
templates/notion/TEMPLATE-PAGE-AGENT-PROFILE.json
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
{
|
||||||
|
"object": "page",
|
||||||
|
"parent": {
|
||||||
|
"type": "database_id",
|
||||||
|
"database_id": "{{AGENTS_DB_ID}}"
|
||||||
|
},
|
||||||
|
"icon": {
|
||||||
|
"type": "emoji",
|
||||||
|
"emoji": "\ud83e\udd16"
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"Name": {
|
||||||
|
"title": [
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"content": "{{AGENT_NAME}}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Status": {
|
||||||
|
"select": {
|
||||||
|
"name": "Active"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Personality": {
|
||||||
|
"multi_select": []
|
||||||
|
},
|
||||||
|
"Capabilities": {
|
||||||
|
"rich_text": [
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"content": "{{CAPABILITIES}}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Created": {
|
||||||
|
"date": {
|
||||||
|
"start": "{{CREATED_DATE}}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"object": "heading_1",
|
||||||
|
"heading_1": {
|
||||||
|
"rich_text": [
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"content": "\ud83e\udd16 Agent Profile"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"object": "heading_2",
|
||||||
|
"heading_2": {
|
||||||
|
"rich_text": [
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"content": "\ud83d\udccb Description"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"object": "paragraph",
|
||||||
|
"paragraph": {
|
||||||
|
"rich_text": [
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"content": "{{DESCRIPTION}}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"object": "heading_2",
|
||||||
|
"heading_2": {
|
||||||
|
"rich_text": [
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"content": "\ud83c\udfaf Purpose"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"object": "paragraph",
|
||||||
|
"paragraph": {
|
||||||
|
"rich_text": [
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"content": "{{PURPOSE}}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"object": "heading_2",
|
||||||
|
"heading_2": {
|
||||||
|
"rich_text": [
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"content": "\ud83d\udd27 Configuration"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"object": "code",
|
||||||
|
"code": {
|
||||||
|
"language": "yaml",
|
||||||
|
"rich_text": [
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"content": "{{CONFIG_YAML}}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
441
templates/quantum_dashboard.html
Normal file
441
templates/quantum_dashboard.html
Normal file
@@ -0,0 +1,441 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>BlackRoad Quantum Dashboard</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<style>
|
||||||
|
* { box-sizing: border-box; }
|
||||||
|
body {
|
||||||
|
font-family: system-ui, -apple-system, BlinkMacSystemFont, "SF Pro Text", sans-serif;
|
||||||
|
background: radial-gradient(ellipse at top, #0a0f1e 0%, #050816 40%, #020308 70%, #000 100%);
|
||||||
|
color: #f0f0ff;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
.page {
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 32px 20px 80px;
|
||||||
|
}
|
||||||
|
.title-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 1.8rem;
|
||||||
|
margin: 0;
|
||||||
|
background: linear-gradient(135deg, #ff9d00, #ff0066, #7700ff, #0066ff);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
background-clip: text;
|
||||||
|
}
|
||||||
|
.chip {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
padding: 4px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
border: 1px solid rgba(255,255,255,0.15);
|
||||||
|
background: rgba(0,0,0,0.4);
|
||||||
|
font-family: "JetBrains Mono", ui-monospace, monospace;
|
||||||
|
}
|
||||||
|
.subtitle {
|
||||||
|
margin-top: 8px;
|
||||||
|
opacity: 0.7;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
.panel {
|
||||||
|
border-radius: 16px;
|
||||||
|
border: 1px solid rgba(255,255,255,0.08);
|
||||||
|
background: linear-gradient(145deg, rgba(10,15,35,0.95), rgba(5,8,22,0.98));
|
||||||
|
padding: 20px 24px;
|
||||||
|
margin-top: 24px;
|
||||||
|
box-shadow: 0 4px 24px rgba(0,0,0,0.4);
|
||||||
|
}
|
||||||
|
.panel h2 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
margin: 0 0 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 16px;
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
.col {
|
||||||
|
flex: 1 1 200px;
|
||||||
|
}
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
opacity: 0.7;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
input[type="number"] {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px 12px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1px solid rgba(255,255,255,0.12);
|
||||||
|
background: rgba(0,0,0,0.5);
|
||||||
|
color: #f0f0ff;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-family: "JetBrains Mono", ui-monospace, monospace;
|
||||||
|
outline: none;
|
||||||
|
transition: border-color 0.2s, box-shadow 0.2s;
|
||||||
|
}
|
||||||
|
input[type="number"]:focus {
|
||||||
|
border-color: rgba(0,180,255,0.7);
|
||||||
|
box-shadow: 0 0 0 2px rgba(0,180,255,0.25);
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 12px 24px;
|
||||||
|
border-radius: 999px;
|
||||||
|
border: none;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 600;
|
||||||
|
background: linear-gradient(135deg, #ff9d00 0%, #ff0066 50%, #0066ff 100%);
|
||||||
|
color: #050816;
|
||||||
|
margin-top: 20px;
|
||||||
|
transition: transform 0.15s, box-shadow 0.15s;
|
||||||
|
}
|
||||||
|
button:hover {
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 4px 20px rgba(255,0,102,0.4);
|
||||||
|
}
|
||||||
|
button:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: default;
|
||||||
|
transform: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
.status-pill {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: 999px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-family: "JetBrains Mono", ui-monospace, monospace;
|
||||||
|
}
|
||||||
|
.status-pill.online {
|
||||||
|
background: rgba(26,245,157,0.12);
|
||||||
|
border: 1px solid rgba(26,245,157,0.5);
|
||||||
|
color: #1af59d;
|
||||||
|
}
|
||||||
|
.status-pill.offline {
|
||||||
|
background: rgba(255,86,86,0.12);
|
||||||
|
border: 1px solid rgba(255,86,86,0.5);
|
||||||
|
color: #ff5656;
|
||||||
|
}
|
||||||
|
.status-pill.loading {
|
||||||
|
background: rgba(255,200,0,0.12);
|
||||||
|
border: 1px solid rgba(255,200,0,0.4);
|
||||||
|
color: #ffc800;
|
||||||
|
}
|
||||||
|
.mono {
|
||||||
|
font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;
|
||||||
|
}
|
||||||
|
.result-card {
|
||||||
|
margin-top: 16px;
|
||||||
|
padding: 16px 18px;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: linear-gradient(135deg, rgba(0,102,255,0.15) 0%, rgba(119,0,255,0.1) 100%);
|
||||||
|
border: 1px solid rgba(255,255,255,0.08);
|
||||||
|
}
|
||||||
|
.result-json {
|
||||||
|
background: rgba(0,0,0,0.4);
|
||||||
|
padding: 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
overflow-x: auto;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
.math-explainer {
|
||||||
|
margin-top: 12px;
|
||||||
|
padding: 12px 14px;
|
||||||
|
background: rgba(255,157,0,0.08);
|
||||||
|
border-left: 3px solid #ff9d00;
|
||||||
|
border-radius: 0 8px 8px 0;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
.math-explainer .formula {
|
||||||
|
font-family: "JetBrains Mono", monospace;
|
||||||
|
background: rgba(0,0,0,0.3);
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.prob-bar {
|
||||||
|
display: flex;
|
||||||
|
height: 24px;
|
||||||
|
border-radius: 12px;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-top: 12px;
|
||||||
|
background: rgba(0,0,0,0.3);
|
||||||
|
}
|
||||||
|
.prob-bar .p0 {
|
||||||
|
background: linear-gradient(90deg, #0066ff, #00aaff);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 0.7rem;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: width 0.3s;
|
||||||
|
}
|
||||||
|
.prob-bar .p1 {
|
||||||
|
background: linear-gradient(90deg, #ff0066, #ff6600);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 0.7rem;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: width 0.3s;
|
||||||
|
}
|
||||||
|
.learn-list {
|
||||||
|
margin: 0;
|
||||||
|
padding-left: 20px;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
line-height: 1.8;
|
||||||
|
}
|
||||||
|
.learn-list code {
|
||||||
|
background: rgba(0,0,0,0.3);
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: #66b2ff;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.muted {
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
.small {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
.hidden {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="page">
|
||||||
|
<div style="margin-bottom: 24px;">
|
||||||
|
<a href="/" style="color: #00e5ff; text-decoration: none; font-size: 0.9rem;">← Dashboard</a>
|
||||||
|
</div>
|
||||||
|
<div class="title-row">
|
||||||
|
<h1>ψ Quantum Dashboard</h1>
|
||||||
|
<span class="chip">BRQ-01 Spiral</span>
|
||||||
|
<span class="chip">2 qubits</span>
|
||||||
|
</div>
|
||||||
|
<p class="subtitle">
|
||||||
|
First BlackRoad AI quantum node: talk to ψ, see predictions, and map them to ⟨Z⟩ and probabilities.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- Status Panel -->
|
||||||
|
<div class="panel">
|
||||||
|
<h2>📡 Node Status</h2>
|
||||||
|
<div id="status-container">
|
||||||
|
<span id="status-pill" class="status-pill loading">checking...</span>
|
||||||
|
<span id="status-details" class="small muted mono" style="margin-left: 12px;"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Prediction Panel -->
|
||||||
|
<div class="panel">
|
||||||
|
<h2>🔮 Run a Prediction</h2>
|
||||||
|
<p class="small muted">
|
||||||
|
BRQ-01 takes a 2D feature vector <code class="mono">x = [x₀, x₁]</code> and returns
|
||||||
|
the probability for class 1. We compute the implied ⟨Z⟩ using
|
||||||
|
<code class="mono">⟨Z⟩ = 1 - 2p₁</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<label for="x0">x₀ (rotation on qubit 0)</label>
|
||||||
|
<input id="x0" type="number" step="0.1" value="0.0" />
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<label for="x1">x₁ (rotation on qubit 1)</label>
|
||||||
|
<input id="x1" type="number" step="0.1" value="0.0" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button id="run-btn">Run ψ on this input</button>
|
||||||
|
|
||||||
|
<!-- Results -->
|
||||||
|
<div id="result-area" class="result-card hidden">
|
||||||
|
<h3 style="margin: 0 0 12px; font-size: 0.95rem;">Response from ψ</h3>
|
||||||
|
<div id="result-json" class="result-json mono"></div>
|
||||||
|
|
||||||
|
<div class="prob-bar">
|
||||||
|
<div id="prob-p0" class="p0" style="width: 50%;">P(0)</div>
|
||||||
|
<div id="prob-p1" class="p1" style="width: 50%;">P(1)</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="math-explainer" class="math-explainer"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Learn Panel -->
|
||||||
|
<div class="panel">
|
||||||
|
<h2>📐 Learn the Math</h2>
|
||||||
|
<p class="small muted">
|
||||||
|
Want to see how ψ thinks under the hood? Open <strong>Math Lab (Σ)</strong> from the terminal:
|
||||||
|
</p>
|
||||||
|
<ul class="learn-list">
|
||||||
|
<li><code>1</code> - Vectors → Qubits → ψ</li>
|
||||||
|
<li><code>2</code> - Matrices → Gates → RX/RY/RZ</li>
|
||||||
|
<li><code>3</code> - Inner Products & ⟨ψ|φ⟩</li>
|
||||||
|
<li><code>4</code> - Tensor Products & Entanglement</li>
|
||||||
|
<li><code>5</code> - Live BRQ-01 Demo (ψ on this Pi)</li>
|
||||||
|
</ul>
|
||||||
|
<p class="small muted" style="margin-top: 12px;">
|
||||||
|
Run: <code class="mono">python3 ./blackroad-math-lab.py</code> or press <code>m</code> in the menu.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
<p class="small muted" style="text-align: center; margin-top: 32px;">
|
||||||
|
© 2025 BlackRoad OS, Inc. · ψ uses PennyLane (Apache 2.0, © Xanadu)
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const QUANTUM_API = '/api/quantum';
|
||||||
|
|
||||||
|
const statusPill = document.getElementById('status-pill');
|
||||||
|
const statusDetails = document.getElementById('status-details');
|
||||||
|
const runBtn = document.getElementById('run-btn');
|
||||||
|
const resultArea = document.getElementById('result-area');
|
||||||
|
const resultJson = document.getElementById('result-json');
|
||||||
|
const mathExplainer = document.getElementById('math-explainer');
|
||||||
|
const probP0 = document.getElementById('prob-p0');
|
||||||
|
const probP1 = document.getElementById('prob-p1');
|
||||||
|
|
||||||
|
async function checkStatus() {
|
||||||
|
statusPill.className = 'status-pill loading';
|
||||||
|
statusPill.textContent = 'checking...';
|
||||||
|
statusDetails.textContent = '';
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await fetch(`${QUANTUM_API}/status`);
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
if (data.ok && data.data) {
|
||||||
|
statusPill.className = 'status-pill online';
|
||||||
|
statusPill.textContent = '● online';
|
||||||
|
|
||||||
|
const s = data.data;
|
||||||
|
const details = [];
|
||||||
|
if (s.node_id) details.push(s.node_id);
|
||||||
|
if (s.pennylane_version) details.push(`PennyLane ${s.pennylane_version}`);
|
||||||
|
statusDetails.textContent = details.join(' · ');
|
||||||
|
} else {
|
||||||
|
throw new Error(data.error || 'Unknown error');
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
statusPill.className = 'status-pill offline';
|
||||||
|
statusPill.textContent = '● offline';
|
||||||
|
statusDetails.textContent = err.message || 'Connection failed';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function runPrediction() {
|
||||||
|
const x0 = parseFloat(document.getElementById('x0').value) || 0;
|
||||||
|
const x1 = parseFloat(document.getElementById('x1').value) || 0;
|
||||||
|
|
||||||
|
runBtn.disabled = true;
|
||||||
|
runBtn.textContent = 'Running...';
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await fetch(`${QUANTUM_API}/predict`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ x0, x1 })
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
if (!data.ok) {
|
||||||
|
throw new Error(data.error || 'Prediction failed');
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = data.data;
|
||||||
|
resultJson.textContent = JSON.stringify(payload, null, 2);
|
||||||
|
|
||||||
|
const p1 = parseFloat(payload.probability || 0);
|
||||||
|
const cls = payload.class;
|
||||||
|
const p0 = 1 - p1;
|
||||||
|
const expZ = 1 - 2 * p1;
|
||||||
|
|
||||||
|
// Update probability bar
|
||||||
|
probP0.style.width = `${p0 * 100}%`;
|
||||||
|
probP0.textContent = `P(0) = ${(p0 * 100).toFixed(1)}%`;
|
||||||
|
probP1.style.width = `${p1 * 100}%`;
|
||||||
|
probP1.textContent = `P(1) = ${(p1 * 100).toFixed(1)}%`;
|
||||||
|
|
||||||
|
// Math explanation
|
||||||
|
mathExplainer.innerHTML = `
|
||||||
|
<strong>Decoding the math:</strong><br><br>
|
||||||
|
From response: <span class="formula">p₁ = ${p1.toFixed(4)}</span>,
|
||||||
|
class = <span class="formula">${cls}</span><br><br>
|
||||||
|
|
||||||
|
Implied expectation value:<br>
|
||||||
|
<span class="formula">⟨Z⟩ = 1 - 2p₁ = 1 - 2×${p1.toFixed(4)} = ${expZ.toFixed(4)}</span><br><br>
|
||||||
|
|
||||||
|
From inner product math:<br>
|
||||||
|
<span class="formula">⟨Z⟩ = |α|² - |β|²</span><br>
|
||||||
|
<span class="formula">P(0) = |α|² = ${p0.toFixed(4)}</span><br>
|
||||||
|
<span class="formula">P(1) = |β|² = ${p1.toFixed(4)}</span><br><br>
|
||||||
|
|
||||||
|
The classifier says: "For x = [${x0}, ${x1}], I computed |ψ⟩ with
|
||||||
|
<strong>${(p0*100).toFixed(1)}%</strong> chance of |0⟩ and
|
||||||
|
<strong>${(p1*100).toFixed(1)}%</strong> chance of |1⟩,
|
||||||
|
so I predict class <strong>${cls}</strong>."
|
||||||
|
`;
|
||||||
|
|
||||||
|
resultArea.classList.remove('hidden');
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
resultJson.textContent = `Error: ${err.message}`;
|
||||||
|
mathExplainer.innerHTML = '';
|
||||||
|
probP0.style.width = '50%';
|
||||||
|
probP1.style.width = '50%';
|
||||||
|
resultArea.classList.remove('hidden');
|
||||||
|
} finally {
|
||||||
|
runBtn.disabled = false;
|
||||||
|
runBtn.textContent = 'Run ψ on this input';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event listeners
|
||||||
|
runBtn.addEventListener('click', runPrediction);
|
||||||
|
|
||||||
|
// Allow Enter key to trigger prediction
|
||||||
|
document.getElementById('x0').addEventListener('keypress', (e) => {
|
||||||
|
if (e.key === 'Enter') runPrediction();
|
||||||
|
});
|
||||||
|
document.getElementById('x1').addEventListener('keypress', (e) => {
|
||||||
|
if (e.key === 'Enter') runPrediction();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initial status check
|
||||||
|
checkStatus();
|
||||||
|
// Refresh status every 30 seconds
|
||||||
|
setInterval(checkStatus, 30000);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
517
templates/quests_page.html
Normal file
517
templates/quests_page.html
Normal file
@@ -0,0 +1,517 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>Quests & Promotion - BlackRoad OS</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--bg-primary: #020308;
|
||||||
|
--bg-secondary: rgba(6, 10, 30, 0.92);
|
||||||
|
--bg-card: rgba(12, 18, 40, 0.85);
|
||||||
|
--text-primary: #f5f5ff;
|
||||||
|
--text-muted: rgba(245, 245, 255, 0.7);
|
||||||
|
--accent-cyan: #00e5ff;
|
||||||
|
--accent-green: #1af59d;
|
||||||
|
--accent-yellow: #ffc400;
|
||||||
|
--accent-purple: #a855f7;
|
||||||
|
--accent-orange: #ff9d00;
|
||||||
|
--accent-pink: #ff0066;
|
||||||
|
--border-subtle: rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: system-ui, -apple-system, BlinkMacSystemFont, "SF Pro Text", sans-serif;
|
||||||
|
background: radial-gradient(circle at top, #050816 0, #020308 45%, #000000 100%);
|
||||||
|
color: var(--text-primary);
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page {
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 24px 16px 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nav */
|
||||||
|
.nav {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav a {
|
||||||
|
color: var(--accent-cyan);
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header */
|
||||||
|
h1 {
|
||||||
|
font-size: 1.8rem;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: 0.95rem;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mono {
|
||||||
|
font-family: "JetBrains Mono", ui-monospace, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Coach Card */
|
||||||
|
.coach-card {
|
||||||
|
background: linear-gradient(135deg, rgba(168, 85, 247, 0.12), rgba(0, 229, 255, 0.06));
|
||||||
|
border: 1px solid rgba(168, 85, 247, 0.4);
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 20px 24px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coach-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coach-header .sigma {
|
||||||
|
font-size: 1.8rem;
|
||||||
|
color: var(--accent-purple);
|
||||||
|
}
|
||||||
|
|
||||||
|
.coach-header .title {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coach-focus {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coach-focus-label {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coach-focus-goal {
|
||||||
|
font-size: 0.95rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coach-progress-bar {
|
||||||
|
height: 8px;
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
margin: 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coach-progress-fill {
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(90deg, var(--accent-purple), var(--accent-cyan));
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: width 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coach-progress-text {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.coach-action {
|
||||||
|
margin-top: 16px;
|
||||||
|
padding-top: 16px;
|
||||||
|
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.coach-action-label {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coach-action-text {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coach-examples {
|
||||||
|
margin-top: 12px;
|
||||||
|
padding-left: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coach-examples li {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coach-examples code {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-family: "JetBrains Mono", monospace;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Overall Progress */
|
||||||
|
.overall-progress {
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border: 1px solid var(--border-subtle);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overall-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overall-title {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overall-percent {
|
||||||
|
font-family: "JetBrains Mono", monospace;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
color: var(--accent-cyan);
|
||||||
|
}
|
||||||
|
|
||||||
|
.overall-bar {
|
||||||
|
height: 12px;
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
border-radius: 6px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overall-bar-fill {
|
||||||
|
height: 100%;
|
||||||
|
background: linear-gradient(90deg, var(--accent-orange), var(--accent-pink), var(--accent-purple));
|
||||||
|
border-radius: 6px;
|
||||||
|
transition: width 0.5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overall-stats {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-top: 8px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stage Cards */
|
||||||
|
.stages {
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stages-title {
|
||||||
|
font-size: 1rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-card {
|
||||||
|
background: var(--bg-card);
|
||||||
|
border: 1px solid var(--border-subtle);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 16px 20px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-card.completed {
|
||||||
|
border-color: rgba(26, 245, 157, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-card.current {
|
||||||
|
border-color: rgba(255, 157, 0, 0.5);
|
||||||
|
background: rgba(255, 157, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-name {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-icon {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-target {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--accent-purple);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-bar {
|
||||||
|
height: 6px;
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
border-radius: 3px;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-bar-fill {
|
||||||
|
height: 100%;
|
||||||
|
background: var(--accent-green);
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-goals {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goal-item {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goal-icon {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goal-icon.met { color: var(--accent-green); }
|
||||||
|
.goal-icon.unmet { color: var(--text-muted); }
|
||||||
|
|
||||||
|
.goal-text {
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.goal-progress {
|
||||||
|
font-family: "JetBrains Mono", monospace;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loading & Error */
|
||||||
|
.loading, .error-state {
|
||||||
|
text-align: center;
|
||||||
|
padding: 48px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-state {
|
||||||
|
background: rgba(255, 68, 68, 0.1);
|
||||||
|
border: 1px solid rgba(255, 68, 68, 0.3);
|
||||||
|
border-radius: 12px;
|
||||||
|
color: #ff6b6b;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="page">
|
||||||
|
<!-- Navigation -->
|
||||||
|
<div class="nav">
|
||||||
|
<a href="/">← Dashboard</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Header -->
|
||||||
|
<h1>Quests & Promotion</h1>
|
||||||
|
<p class="subtitle">
|
||||||
|
Track your promotion path progress.
|
||||||
|
Actor: <span class="mono">{{ actor }}</span> |
|
||||||
|
Path: <span class="mono">{{ path_id }}</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- Coach Card -->
|
||||||
|
<div class="coach-card" id="coach-card" style="display: none;">
|
||||||
|
<div class="coach-header">
|
||||||
|
<span class="sigma">Σ</span>
|
||||||
|
<span class="title">Coach Suggestion</span>
|
||||||
|
</div>
|
||||||
|
<div id="coach-content"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Overall Progress -->
|
||||||
|
<div class="overall-progress" id="overall-progress" style="display: none;">
|
||||||
|
<div class="overall-header">
|
||||||
|
<span class="overall-title" id="path-name">Loading...</span>
|
||||||
|
<span class="overall-percent" id="path-percent">0%</span>
|
||||||
|
</div>
|
||||||
|
<div class="overall-bar">
|
||||||
|
<div class="overall-bar-fill" id="path-bar" style="width: 0%;"></div>
|
||||||
|
</div>
|
||||||
|
<div class="overall-stats">
|
||||||
|
<span id="path-desc"></span>
|
||||||
|
<span id="path-stages"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Stages -->
|
||||||
|
<div class="stages" id="stages">
|
||||||
|
<div class="loading">Loading promotion path...</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const actor = "{{ actor }}";
|
||||||
|
const pathId = "{{ path_id }}";
|
||||||
|
|
||||||
|
async function loadCoach() {
|
||||||
|
try {
|
||||||
|
const res = await fetch(`/api/promotion/coach?actor=${actor}&path_id=${pathId}`);
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
if (!data.ok) return;
|
||||||
|
|
||||||
|
const card = document.getElementById('coach-card');
|
||||||
|
const content = document.getElementById('coach-content');
|
||||||
|
card.style.display = 'block';
|
||||||
|
|
||||||
|
const s = data.suggestion || {};
|
||||||
|
|
||||||
|
if (s.stage_id === 'complete') {
|
||||||
|
content.innerHTML = `
|
||||||
|
<div style="font-size: 1.2rem; color: var(--accent-green);">
|
||||||
|
🎉 Path Complete!
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 8px; color: var(--text-muted);">
|
||||||
|
${s.action || 'All stages completed. You\'re a BlackRoad master!'}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let examplesHtml = '';
|
||||||
|
if (s.example_commands && s.example_commands.length) {
|
||||||
|
examplesHtml = `
|
||||||
|
<ul class="coach-examples">
|
||||||
|
${s.example_commands.map(ex => `<li><code>${ex}</code></li>`).join('')}
|
||||||
|
</ul>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
content.innerHTML = `
|
||||||
|
<div class="coach-focus">
|
||||||
|
<div class="coach-focus-label">Current Focus</div>
|
||||||
|
<div class="coach-focus-goal">${s.goal_key || 'Unknown'}</div>
|
||||||
|
</div>
|
||||||
|
<div class="coach-progress-bar">
|
||||||
|
<div class="coach-progress-fill" style="width: ${s.percent || 0}%;"></div>
|
||||||
|
</div>
|
||||||
|
<div class="coach-progress-text">
|
||||||
|
${s.current} / ${s.required} (${s.percent}%)
|
||||||
|
</div>
|
||||||
|
<div class="coach-action">
|
||||||
|
<div class="coach-action-label">👉 Next Action</div>
|
||||||
|
<div class="coach-action-text">${s.action || 'Keep going!'}</div>
|
||||||
|
${examplesHtml}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to load coach:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadPath() {
|
||||||
|
const stagesContainer = document.getElementById('stages');
|
||||||
|
const overallContainer = document.getElementById('overall-progress');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await fetch(`/api/promotion/path?actor=${actor}&path_id=${pathId}`);
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
if (!data.ok) {
|
||||||
|
stagesContainer.innerHTML = `
|
||||||
|
<div class="error-state">
|
||||||
|
<p>Failed to load promotion path: ${data.error || 'Unknown error'}</p>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overall progress
|
||||||
|
overallContainer.style.display = 'block';
|
||||||
|
document.getElementById('path-name').textContent = data.name || pathId;
|
||||||
|
document.getElementById('path-percent').textContent = `${data.completion_percent || 0}%`;
|
||||||
|
document.getElementById('path-bar').style.width = `${data.completion_percent || 0}%`;
|
||||||
|
document.getElementById('path-desc').textContent = data.description || '';
|
||||||
|
document.getElementById('path-stages').textContent =
|
||||||
|
`${data.stages_completed || 0} / ${data.stages_total || 0} stages`;
|
||||||
|
|
||||||
|
// Stages
|
||||||
|
const stages = data.stages || [];
|
||||||
|
let html = '<div class="stages-title">Promotion Stages</div>';
|
||||||
|
|
||||||
|
for (const stage of stages) {
|
||||||
|
const allMet = stage.all_goals_met;
|
||||||
|
const isCurrent = !allMet && stages.indexOf(stage) ===
|
||||||
|
stages.findIndex(s => !s.all_goals_met);
|
||||||
|
|
||||||
|
const cardClass = allMet ? 'completed' : (isCurrent ? 'current' : '');
|
||||||
|
const icon = allMet ? '✅' : (isCurrent ? '🎯' : '⬜');
|
||||||
|
|
||||||
|
let goalsHtml = '';
|
||||||
|
const goals = stage.goals || {};
|
||||||
|
for (const [key, g] of Object.entries(goals)) {
|
||||||
|
const goalIcon = g.met ? '✓' : '·';
|
||||||
|
const goalClass = g.met ? 'met' : 'unmet';
|
||||||
|
goalsHtml += `
|
||||||
|
<div class="goal-item">
|
||||||
|
<span class="goal-icon ${goalClass}">${goalIcon}</span>
|
||||||
|
<span class="goal-text">${key}</span>
|
||||||
|
<span class="goal-progress">${g.current} / ${g.required}</span>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
html += `
|
||||||
|
<div class="stage-card ${cardClass}">
|
||||||
|
<div class="stage-header">
|
||||||
|
<div class="stage-name">
|
||||||
|
<span class="stage-icon">${icon}</span>
|
||||||
|
${stage.name || stage.id}
|
||||||
|
</div>
|
||||||
|
<div class="stage-target">→ ${stage.target_rank || '?'}</div>
|
||||||
|
</div>
|
||||||
|
<div class="stage-bar">
|
||||||
|
<div class="stage-bar-fill" style="width: ${stage.overall_percent || 0}%;"></div>
|
||||||
|
</div>
|
||||||
|
<div class="stage-goals">
|
||||||
|
${goalsHtml}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
stagesContainer.innerHTML = html;
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
stagesContainer.innerHTML = `
|
||||||
|
<div class="error-state">
|
||||||
|
<p>Failed to load promotion path: ${e.message}</p>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init
|
||||||
|
loadCoach();
|
||||||
|
loadPath();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
517
templates/status_page.html
Normal file
517
templates/status_page.html
Normal file
@@ -0,0 +1,517 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>System Status - BlackRoad OS</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--bg-primary: #020308;
|
||||||
|
--bg-secondary: rgba(6, 10, 30, 0.92);
|
||||||
|
--bg-card: rgba(12, 18, 40, 0.85);
|
||||||
|
--text-primary: #f5f5ff;
|
||||||
|
--text-muted: rgba(245, 245, 255, 0.7);
|
||||||
|
--accent-cyan: #00e5ff;
|
||||||
|
--accent-green: #1af59d;
|
||||||
|
--accent-yellow: #ffc400;
|
||||||
|
--accent-purple: #a855f7;
|
||||||
|
--accent-orange: #ff9d00;
|
||||||
|
--accent-pink: #ff0066;
|
||||||
|
--accent-red: #ff4444;
|
||||||
|
--border-subtle: rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: system-ui, -apple-system, BlinkMacSystemFont, "SF Pro Text", sans-serif;
|
||||||
|
background: radial-gradient(circle at top, #050816 0, #020308 45%, #000000 100%);
|
||||||
|
color: var(--text-primary);
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page {
|
||||||
|
max-width: 1000px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 24px 16px 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nav */
|
||||||
|
.nav {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav a {
|
||||||
|
color: var(--accent-cyan);
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header */
|
||||||
|
h1 {
|
||||||
|
font-size: 1.8rem;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: 0.95rem;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mono {
|
||||||
|
font-family: "JetBrains Mono", ui-monospace, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Overall Status */
|
||||||
|
.overall-status {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16px;
|
||||||
|
padding: 20px 24px;
|
||||||
|
border-radius: 12px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overall-status.healthy {
|
||||||
|
background: rgba(26, 245, 157, 0.1);
|
||||||
|
border: 1px solid rgba(26, 245, 157, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.overall-status.degraded {
|
||||||
|
background: rgba(255, 196, 0, 0.1);
|
||||||
|
border: 1px solid rgba(255, 196, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.overall-status.down {
|
||||||
|
background: rgba(255, 68, 68, 0.1);
|
||||||
|
border: 1px solid rgba(255, 68, 68, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.overall-icon {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overall-text {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overall-title {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overall-desc {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.refresh-btn {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
|
color: var(--text-primary);
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.refresh-btn:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.refresh-btn:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Services Grid */
|
||||||
|
.services-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||||
|
gap: 16px;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-card {
|
||||||
|
background: var(--bg-card);
|
||||||
|
border: 1px solid var(--border-subtle);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-card.ok {
|
||||||
|
border-left: 3px solid var(--accent-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-card.error {
|
||||||
|
border-left: 3px solid var(--accent-red);
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-name {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-status {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
padding: 3px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-status.ok {
|
||||||
|
background: rgba(26, 245, 157, 0.15);
|
||||||
|
border: 1px solid rgba(26, 245, 157, 0.4);
|
||||||
|
color: var(--accent-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-status.error {
|
||||||
|
background: rgba(255, 68, 68, 0.15);
|
||||||
|
border: 1px solid rgba(255, 68, 68, 0.4);
|
||||||
|
color: var(--accent-red);
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-details {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-url {
|
||||||
|
font-family: "JetBrains Mono", monospace;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--accent-cyan);
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.service-error {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--accent-red);
|
||||||
|
margin-top: 8px;
|
||||||
|
padding: 8px;
|
||||||
|
background: rgba(255, 68, 68, 0.1);
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Info Sections */
|
||||||
|
.info-section {
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border: 1px solid var(--border-subtle);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-title {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item {
|
||||||
|
padding: 12px;
|
||||||
|
background: rgba(255, 255, 255, 0.03);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-label {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-value {
|
||||||
|
font-family: "JetBrains Mono", monospace;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Endpoints List */
|
||||||
|
.endpoints-list {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.endpoints-list li {
|
||||||
|
padding: 8px 0;
|
||||||
|
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.endpoints-list li:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.endpoint-method {
|
||||||
|
font-family: "JetBrains Mono", monospace;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: rgba(0, 229, 255, 0.15);
|
||||||
|
color: var(--accent-cyan);
|
||||||
|
}
|
||||||
|
|
||||||
|
.endpoint-path {
|
||||||
|
font-family: "JetBrains Mono", monospace;
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.endpoint-desc {
|
||||||
|
color: var(--text-muted);
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Last Updated */
|
||||||
|
.last-updated {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="page">
|
||||||
|
<!-- Navigation -->
|
||||||
|
<div class="nav">
|
||||||
|
<a href="/">← Dashboard</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Header -->
|
||||||
|
<h1>System Status</h1>
|
||||||
|
<p class="subtitle">Monitor BlackRoad OS service health and infrastructure</p>
|
||||||
|
|
||||||
|
<!-- Overall Status -->
|
||||||
|
<div class="overall-status healthy" id="overall-status">
|
||||||
|
<div class="overall-icon" id="overall-icon">⏳</div>
|
||||||
|
<div class="overall-text">
|
||||||
|
<div class="overall-title" id="overall-title">Checking services...</div>
|
||||||
|
<div class="overall-desc" id="overall-desc">Please wait</div>
|
||||||
|
</div>
|
||||||
|
<button class="refresh-btn" id="refresh-btn" onclick="refresh()">
|
||||||
|
Refresh
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Services Grid -->
|
||||||
|
<div class="services-grid" id="services-grid">
|
||||||
|
<!-- Populated by JS -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Operator Info -->
|
||||||
|
<div class="info-section" id="operator-info" style="display: none;">
|
||||||
|
<div class="info-title">📡 Operator API</div>
|
||||||
|
<div id="operator-endpoints"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Console Info -->
|
||||||
|
<div class="info-section">
|
||||||
|
<div class="info-title">🖥️ Console Routes</div>
|
||||||
|
<ul class="endpoints-list">
|
||||||
|
<li>
|
||||||
|
<span class="endpoint-method">GET</span>
|
||||||
|
<span class="endpoint-path">/</span>
|
||||||
|
<span class="endpoint-desc">Dashboard home</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="endpoint-method">GET</span>
|
||||||
|
<span class="endpoint-path">/quantum</span>
|
||||||
|
<span class="endpoint-desc">Quantum predictions</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="endpoint-method">GET</span>
|
||||||
|
<span class="endpoint-path">/learning</span>
|
||||||
|
<span class="endpoint-desc">Learning history</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="endpoint-method">GET</span>
|
||||||
|
<span class="endpoint-path">/models</span>
|
||||||
|
<span class="endpoint-desc">Model registry</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="endpoint-method">GET</span>
|
||||||
|
<span class="endpoint-path">/quests</span>
|
||||||
|
<span class="endpoint-desc">Promotion path</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="endpoint-method">GET</span>
|
||||||
|
<span class="endpoint-path">/status</span>
|
||||||
|
<span class="endpoint-desc">This page</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="endpoint-method">GET</span>
|
||||||
|
<span class="endpoint-path">/api/health</span>
|
||||||
|
<span class="endpoint-desc">Aggregated health</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Last Updated -->
|
||||||
|
<div class="last-updated" id="last-updated">
|
||||||
|
Last checked: --
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const SERVICES = [
|
||||||
|
{
|
||||||
|
key: 'console',
|
||||||
|
name: 'Web Console',
|
||||||
|
desc: 'This dashboard and UI server',
|
||||||
|
icon: '🖥️'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'operator',
|
||||||
|
name: 'Operator API',
|
||||||
|
desc: 'Ledger, learning stats, promotion engine',
|
||||||
|
icon: '📡'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'quantum',
|
||||||
|
name: 'Quantum Node',
|
||||||
|
desc: 'PennyLane-based quantum ML service',
|
||||||
|
icon: 'ψ'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
async function refresh() {
|
||||||
|
const btn = document.getElementById('refresh-btn');
|
||||||
|
btn.disabled = true;
|
||||||
|
btn.textContent = 'Checking...';
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await fetch('/api/health');
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
updateUI(data);
|
||||||
|
} catch (e) {
|
||||||
|
updateUI({ ok: false, error: e.message, services: {} });
|
||||||
|
}
|
||||||
|
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.textContent = 'Refresh';
|
||||||
|
|
||||||
|
document.getElementById('last-updated').textContent =
|
||||||
|
`Last checked: ${new Date().toLocaleTimeString()}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateUI(data) {
|
||||||
|
const services = data.services || {};
|
||||||
|
const allOk = data.ok;
|
||||||
|
const okCount = Object.values(services).filter(s => s.ok).length;
|
||||||
|
const total = Object.keys(services).length;
|
||||||
|
|
||||||
|
// Overall status
|
||||||
|
const overall = document.getElementById('overall-status');
|
||||||
|
const icon = document.getElementById('overall-icon');
|
||||||
|
const title = document.getElementById('overall-title');
|
||||||
|
const desc = document.getElementById('overall-desc');
|
||||||
|
|
||||||
|
if (allOk) {
|
||||||
|
overall.className = 'overall-status healthy';
|
||||||
|
icon.textContent = '✅';
|
||||||
|
title.textContent = 'All Systems Operational';
|
||||||
|
desc.textContent = `${okCount}/${total} services healthy`;
|
||||||
|
} else if (okCount > 0) {
|
||||||
|
overall.className = 'overall-status degraded';
|
||||||
|
icon.textContent = '⚠️';
|
||||||
|
title.textContent = 'Partial Outage';
|
||||||
|
desc.textContent = `${okCount}/${total} services healthy`;
|
||||||
|
} else {
|
||||||
|
overall.className = 'overall-status down';
|
||||||
|
icon.textContent = '❌';
|
||||||
|
title.textContent = 'Major Outage';
|
||||||
|
desc.textContent = 'All services unreachable';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Service cards
|
||||||
|
const grid = document.getElementById('services-grid');
|
||||||
|
let html = '';
|
||||||
|
|
||||||
|
for (const svc of SERVICES) {
|
||||||
|
const status = services[svc.key] || { ok: false, error: 'Unknown' };
|
||||||
|
const cardClass = status.ok ? 'ok' : 'error';
|
||||||
|
const statusText = status.ok ? 'Healthy' : 'Down';
|
||||||
|
|
||||||
|
let errorHtml = '';
|
||||||
|
if (!status.ok && status.error) {
|
||||||
|
errorHtml = `<div class="service-error">${status.error}</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
html += `
|
||||||
|
<div class="service-card ${cardClass}">
|
||||||
|
<div class="service-header">
|
||||||
|
<div class="service-name">${svc.icon} ${svc.name}</div>
|
||||||
|
<div class="service-status ${cardClass}">${statusText}</div>
|
||||||
|
</div>
|
||||||
|
<div class="service-details">${svc.desc}</div>
|
||||||
|
${errorHtml}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
grid.innerHTML = html;
|
||||||
|
|
||||||
|
// Load operator endpoints if available
|
||||||
|
if (services.operator?.ok) {
|
||||||
|
loadOperatorInfo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadOperatorInfo() {
|
||||||
|
try {
|
||||||
|
const res = await fetch('/api/operator/status');
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
if (data.ok && data.data) {
|
||||||
|
const info = document.getElementById('operator-info');
|
||||||
|
info.style.display = 'block';
|
||||||
|
|
||||||
|
const endpoints = data.data.endpoints || [];
|
||||||
|
let html = '<ul class="endpoints-list">';
|
||||||
|
|
||||||
|
for (const ep of endpoints) {
|
||||||
|
html += `
|
||||||
|
<li>
|
||||||
|
<span class="endpoint-method">GET/POST</span>
|
||||||
|
<span class="endpoint-path">${ep}</span>
|
||||||
|
</li>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
html += '</ul>';
|
||||||
|
document.getElementById('operator-endpoints').innerHTML = html;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to load operator info:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init
|
||||||
|
refresh();
|
||||||
|
|
||||||
|
// Auto-refresh every 60s
|
||||||
|
setInterval(refresh, 60000);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
name = "blackroad-os-docs"
|
|
||||||
main = "src/index.js"
|
|
||||||
compatibility_date = "2024-12-01"
|
|
||||||
account_id = "848cf0b18d51e0170e0d1537aec3505a"
|
|
||||||
|
|
||||||
[vars]
|
|
||||||
REPO_NAME = "blackroad-os-docs"
|
|
||||||
ORG_NAME = "BlackRoad-OS"
|
|
||||||
ENVIRONMENT = "production"
|
|
||||||
|
|
||||||
# Add KV, D1, R2 bindings as needed
|
|
||||||
# [[kv_namespaces]]
|
|
||||||
# binding = "CACHE"
|
|
||||||
# id = "YOUR_KV_ID"
|
|
||||||
Reference in New Issue
Block a user