diff --git a/.claude/knowledge/architecture.md b/.claude/knowledge/architecture.md new file mode 100644 index 00000000..2e7b6bd0 --- /dev/null +++ b/.claude/knowledge/architecture.md @@ -0,0 +1,638 @@ +# TogetherOS Architecture + +## Monorepo Structure + +### Directory Layout +``` +TogetherOS/ +├── apps/ +│ ├── web/ # Next.js 14 frontend +│ │ ├── app/ +│ │ │ ├── (auth)/ # Auth routes group +│ │ │ │ ├── login/ +│ │ │ │ └── signup/ +│ │ │ ├── (platform)/ # Main app routes +│ │ │ │ ├── governance/ +│ │ │ │ ├── bridge/ +│ │ │ │ ├── forum/ +│ │ │ │ ├── profiles/ +│ │ │ │ └── groups/ +│ │ │ ├── layout.tsx +│ │ │ └── page.tsx +│ │ ├── public/ +│ │ ├── styles/ +│ │ │ └── globals.css +│ │ ├── package.json +│ │ └── next.config.js +│ │ +│ ├── api/ # Backend services +│ │ ├── src/ +│ │ │ ├── modules/ +│ │ │ │ ├── governance/ +│ │ │ │ │ ├── entities/ +│ │ │ │ │ ├── repos/ +│ │ │ │ │ ├── handlers/ +│ │ │ │ │ └── fixtures/ +│ │ │ │ ├── bridge/ +│ │ │ │ ├── profiles/ +│ │ │ │ └── groups/ +│ │ │ ├── lib/ +│ │ │ │ ├── ndjson.ts +│ │ │ │ ├── privacy.ts +│ │ │ │ └── validators.ts +│ │ │ ├── trpc/ +│ │ │ │ ├── router.ts +│ │ │ │ └── context.ts +│ │ │ └── server.ts +│ │ ├── package.json +│ │ └── tsconfig.json +│ │ +│ └── docs-site/ # Documentation site (future) +│ +├── packages/ +│ ├── ui/ # Shared components +│ │ ├── src/ +│ │ │ ├── button.tsx +│ │ │ ├── card.tsx +│ │ │ ├── input.tsx +│ │ │ └── index.ts +│ │ ├── tailwind.config.ts +│ │ └── package.json +│ │ +│ ├── types/ # Shared TypeScript types +│ │ ├── src/ +│ │ │ ├── governance.ts +│ │ │ ├── profiles.ts +│ │ │ ├── bridge.ts +│ │ │ └── index.ts +│ │ └── package.json +│ │ +│ ├── fixtures/ # Test data +│ │ ├── src/ +│ │ │ ├── proposals.ts +│ │ │ ├── members.ts +│ │ │ └── index.ts +│ │ └── package.json +│ │ +│ ├── validators/ # Zod schemas +│ │ ├── src/ +│ │ │ ├── governance.ts +│ │ │ ├── bridge.ts +│ │ │ └── index.ts +│ │ └── package.json +│ │ +│ └── config/ # Shared configs +│ ├── eslint-config/ +│ ├── tsconfig/ +│ └── tailwind-config/ +│ +├── docs/ # Specs & playbooks +├── codex/ # Knowledge base +├── scripts/ # Validation scripts +├── .github/workflows/ # CI/CD +├── .devcontainer/ # Dev environment +├── pnpm-workspace.yaml +├── package.json +├── tsconfig.base.json +└── .env.example +``` + +--- + +## Domain-Driven Design Pattern + +### Standard Module Structure + +Every module follows this consistent pattern: + +``` +Module: governance +├── apps/api/src/modules/governance/ +│ ├── entities/ # Domain models (pure TypeScript) +│ │ ├── Proposal.ts +│ │ ├── Decision.ts +│ │ └── index.ts +│ │ +│ ├── repos/ # Data access interfaces +│ │ ├── ProposalRepo.ts # Interface +│ │ ├── InMemoryProposalRepo.ts +│ │ └── index.ts +│ │ +│ ├── handlers/ # API handlers +│ │ ├── createProposal.ts +│ │ ├── listProposals.ts +│ │ ├── getProposal.ts +│ │ └── index.ts +│ │ +│ └── fixtures/ # Test data +│ ├── proposals.json +│ ├── seed.ts +│ └── index.ts +│ +├── apps/web/app/(platform)/governance/ +│ ├── page.tsx # List view +│ ├── [id]/ +│ │ └── page.tsx # Detail view +│ └── layout.tsx # Shared layout +│ +├── packages/types/src/governance.ts +├── packages/validators/src/governance.ts +└── packages/ui/src/governance/ + ├── ProposalList.tsx + ├── ProposalCard.tsx + └── ProposalView.tsx +``` + +### Entities +- **Pure domain models** — No framework dependencies +- **Business logic** — Validation, state transitions +- **Immutable patterns** — Return new instances on changes + +### Repositories +- **Interface-based** — Define contracts, swap implementations +- **Fixture-first** — Start with in-memory/JSON +- **Future-proof** — Easy database migration path + +### Handlers +- **Thin controllers** — Orchestrate entities + repos +- **Zod validation** — All inputs validated +- **Error taxonomy:** 401 (unauth), 403 (forbidden), 422 (validation), 500 (unexpected) + +--- + +## API Architecture + +### tRPC Pattern (Preferred) + +```typescript +// packages/types/src/governance.ts +export interface Proposal { + id: string + title: string + summary: string + authorId: string + createdAt: Date + updatedAt: Date +} + +// packages/validators/src/governance.ts +import { z } from 'zod' + +export const createProposalSchema = z.object({ + title: z.string().min(3).max(200), + summary: z.string().min(10).max(2000), + authorId: z.string().uuid(), +}) + +// apps/api/src/modules/governance/handlers/createProposal.ts +import { createProposalSchema } from '@togetheros/validators' +import { ProposalRepo } from '../repos' + +export async function createProposal( + input: unknown, + repo: ProposalRepo +) { + const data = createProposalSchema.parse(input) + const proposal = await repo.create(data) + return { id: proposal.id } +} + +// apps/api/src/trpc/routers/governance.ts +import { createProposal } from '../../modules/governance/handlers' + +export const governanceRouter = router({ + createProposal: publicProcedure + .input(createProposalSchema) + .mutation(({ input }) => createProposal(input, proposalRepo)), +}) +``` + +### REST Alternative + +```typescript +// apps/api/src/modules/governance/handlers/createProposal.ts +export async function POST(request: Request) { + const body = await request.json() + const data = createProposalSchema.parse(body) + const proposal = await proposalRepo.create(data) + return Response.json({ id: proposal.id }, { status: 201 }) +} +``` + +### Error Responses + +```typescript +// Standard error shape +{ + "error": { + "code": "VALIDATION_ERROR", + "message": "Title must be at least 3 characters", + "details": { "field": "title" } + } +} + +// HTTP status codes +401 — Unauthorized (missing/invalid auth) +403 — Forbidden (insufficient permissions/feature disabled) +422 — Unprocessable (validation failed, contract breach) +204 — No Content (empty result, valid but nothing to return) +500 — Internal Server Error (unexpected failure) +``` + +--- + +## Data Models (Core Entities) + +### Group +```typescript +interface Group { + id: string + name: string + handle: string // Unique, federation-ready + type: 'local' | 'thematic' | 'federated' + createdAt: Date + members: Member[] +} +``` + +### Member +```typescript +interface Member { + id: string + email: string // Private + handle: string // Public + archetypes: Archetype[] // Builder, Community Heart, etc. + capabilities: string[] // Unlocked features + reputation: number // Earned contributions + supportPoints: number // 100 start, max 10/idea + createdAt: Date +} +``` + +### Proposal +```typescript +interface Proposal { + id: string + groupId: string + authorId: string + title: string + summary: string + evidence: Evidence[] // Research, links, data + options: Option[] // Alternatives with trade-offs + positions: Position[] // Member stances + minorityReport?: string // Objections codified + status: 'draft' | 'deliberation' | 'voting' | 'decided' + createdAt: Date + updatedAt: Date +} +``` + +### Decision +```typescript +interface Decision { + id: string + proposalId: string + method: 'approval' | 'ranked' | 'consent' + quorum: number + outcome: 'approved' | 'rejected' | 'amended' + votes: Vote[] + minorityReport?: string + challengeWindow: Date // Appeals deadline + decidedAt: Date +} +``` + +### Initiative +```typescript +interface Initiative { + id: string + decisionId: string + title: string + tasks: Task[] + owners: string[] // Member IDs + milestones: Milestone[] + proofs: Proof[] // Delivery artifacts + status: 'planned' | 'in_progress' | 'delivered' | 'reviewed' + createdAt: Date + completedAt?: Date +} +``` + +### Transaction +```typescript +interface Transaction { + id: string + type: 'support_points' | 'timebank' | 'treasury' + from: string // Member or Group ID + to: string + amount: number + currency: 'SP' | 'time' | 'SH' // Support Points, hours, Social Horizon + metadata: Record + timestamp: Date +} +``` + +### Event +```typescript +interface Event { + id: string + groupId: string + title: string + description: string + location: string + startDate: Date + endDate: Date + attendees: string[] // Member IDs + skills: string[] // Skill exchange tags + createdAt: Date +} +``` + +--- + +## NDJSON Logging Pattern + +### Log Structure +```typescript +interface LogEntry { + id: string // UUID + timestamp: string // ISO 8601 + event_type: 'qa' | 'tidy' | 'moderation' | 'transaction' + metadata: { + // Event-specific data + [key: string]: any + } + content_hash?: string // SHA-256 for integrity +} +``` + +### Bridge Q&A Log Example +```json +{"id":"uuid","timestamp":"2025-01-15T10:30:00Z","event_type":"qa","metadata":{"question_hash":"sha256","answer_length":245,"sources":[{"path":"docs/Manifesto.md","lines":[12,28]}],"ip_hash":"sha256"}} +``` + +### Validation Script +```bash +# scripts/validate.sh checks: +# 1. File exists +# 2. Last non-empty line is valid JSON +# 3. Required fields present (id, timestamp, event_type) +# 4. Prints: VALIDATORS=GREEN +``` + +--- + +## Privacy & Security Patterns + +### PII Redaction +```typescript +function redactPII(text: string): string { + // Remove emails + text = text.replace(/\b[\w\.-]+@[\w\.-]+\.\w{2,4}\b/gi, '[REDACTED_EMAIL]') + + // Remove phone numbers + text = text.replace(/\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/g, '[REDACTED_PHONE]') + + // Remove handles (context-aware) + text = text.replace(/@[\w-]+/g, '[REDACTED_HANDLE]') + + return text +} +``` + +### IP Hashing +```typescript +import { createHash } from 'crypto' + +function hashIP(ip: string, salt: string): string { + return createHash('sha256') + .update(ip + salt) + .digest('hex') + .substring(0, 16) // Shortened for storage +} +``` + +### Session Privacy +```typescript +interface Session { + id: string + memberId: string + expiresAt: Date + // NO: ip, user-agent, location +} +``` + +--- + +## Federation Architecture + +### Group Handles +```typescript +// Format: @groupname@domain.tld +const handle = '@boston-mutual-aid@together.os' + +interface FederatedGroup { + handle: string + homeInstance: string // Domain + publicKey: string // For signatures + protocols: string[] // Supported federation features +} +``` + +### Proposal Sync +```typescript +interface FederatedProposal { + localId: string + remoteId: string + remoteInstance: string + syncedAt: Date + status: 'synced' | 'diverged' | 'conflict' +} +``` + +### Local Autonomy Rules +- **Data silos:** Each group owns its data +- **Opt-in sharing:** Explicit consent for federation +- **Local decisions stand:** No central authority overrides + +--- + +## State Management + +### Client State (Planned) +- **React Context** — Global state (auth, theme) +- **Server State** — tRPC queries (cached, reactive) +- **Local State** — Component-level with useState +- **Form State** — React Hook Form + Zod + +### Server State +- **In-memory** — Fixture repos (MVP) +- **Future database** — Repository pattern enables swap + +--- + +## UI Component Patterns + +### Required States +Every component must handle: +```typescript +type ComponentState = + | { status: 'loading' } + | { status: 'empty' } + | { status: 'error'; error: Error } + | { status: 'success'; data: T } +``` + +### Example: ProposalList +```typescript +export function ProposalList() { + const { data, isLoading, error } = trpc.governance.list.useQuery() + + if (isLoading) return + if (error) return + if (!data || data.length === 0) return + + return +} +``` + +### Accessibility Requirements +- **Keyboard navigation:** Tab order, Enter/Space actions +- **Screen readers:** ARIA labels, roles, live regions +- **Focus management:** Visible focus indicators +- **Color contrast:** WCAG AA minimum + +--- + +## Route Conventions + +### Next.js App Router + +``` +app/ +├── (auth)/ # Layout group (no route segment) +│ ├── login/ +│ │ └── page.tsx # /login +│ └── signup/ +│ └── page.tsx # /signup +│ +├── (platform)/ # Layout group (authenticated) +│ ├── governance/ +│ │ ├── page.tsx # /governance (list) +│ │ ├── [id]/ +│ │ │ └── page.tsx # /governance/[id] (detail) +│ │ └── layout.tsx +│ │ +│ ├── bridge/ +│ │ └── page.tsx # /bridge (Q&A interface) +│ │ +│ └── profiles/ +│ ├── page.tsx # /profiles (directory) +│ └── [handle]/ +│ └── page.tsx # /profiles/[handle] +│ +├── api/ # API routes +│ ├── trpc/ +│ │ └── [trpc]/ +│ │ └── route.ts +│ └── bridge/ +│ ├── qa/ +│ │ └── route.ts # POST /api/bridge/qa +│ └── tidy/ +│ └── route.ts # POST /api/bridge/tidy +│ +├── layout.tsx # Root layout +└── page.tsx # Home page +``` + +--- + +## Environment & Config + +### Environment Variables +```bash +# .env.local (never commit) +DATABASE_URL=... +LLM_API_KEY=... +BRIDGE_LOG_KEY=... + +# .env.example (committed) +DATABASE_URL=postgresql://... +LLM_API_KEY=your_key_here +BRIDGE_ENABLED=true +``` + +### Config Files +- **next.config.js** — Next.js settings +- **tailwind.config.ts** — Design tokens +- **tsconfig.base.json** — Shared TS config +- **pnpm-workspace.yaml** — Monorepo packages + +--- + +## Testing Strategy + +### Unit Tests +```typescript +// packages/governance-domain/__tests__/Proposal.test.ts +import { describe, it, expect } from 'vitest' +import { Proposal } from '../entities/Proposal' + +describe('Proposal', () => { + it('validates title length', () => { + expect(() => new Proposal({ title: 'AB' })).toThrow() + }) +}) +``` + +### Contract Tests +```typescript +// apps/api/src/modules/governance/__tests__/createProposal.test.ts +import { describe, it, expect } from 'vitest' +import { createProposalSchema } from '@togetheros/validators' + +describe('POST /api/proposals', () => { + it('rejects invalid input', () => { + const result = createProposalSchema.safeParse({ title: '' }) + expect(result.success).toBe(false) + }) +}) +``` + +### Storybook Stories +```typescript +// packages/ui/src/governance/ProposalCard.stories.tsx +import type { Meta, StoryObj } from '@storybook/react' +import { ProposalCard } from './ProposalCard' + +export default { + component: ProposalCard, +} satisfies Meta + +export const Default: StoryObj = { + args: { + proposal: { + id: '1', + title: 'Add community garden', + summary: 'Proposal to create...', + } + } +} + +export const Loading: StoryObj = { + args: { loading: true } +} + +export const Error: StoryObj = { + args: { error: new Error('Failed to load') } +} +``` + +--- + +## Related KB Files + +- [Main KB](./togetheros-kb.md) — Core identity and workflow +- [Tech Stack](./tech-stack.md) — Frameworks, tools, versions +- [Data Models](./data-models.md) — Complete entity specifications +- [CI/CD Discipline](./ci-cd-discipline.md) — Validation and proofs diff --git a/.claude/knowledge/ci-cd-discipline.md b/.claude/knowledge/ci-cd-discipline.md new file mode 100644 index 00000000..f3e2e1b0 --- /dev/null +++ b/.claude/knowledge/ci-cd-discipline.md @@ -0,0 +1,502 @@ +# CI/CD Discipline & Proof Lines + +## Core Discipline (Non-Negotiable) + +### The Rules +1. **One tiny change per PR** — Smallest shippable increment only +2. **Full files for YAML/JSON** — No partial patches +3. **Fix one red check at a time** — Don't stack unrelated changes +4. **Docs-first** — Any behavior/config change must update relevant docs +5. **Proof lines required** — Every PR body includes validation output + +--- + +## Required Checks (Gate to Merge) + +### ci/lint (Always Required) +**Purpose:** Validate all GitHub workflow YAML + +**Tools:** +- `yamllint` — Uses `.yamllint.yaml` config +- `actionlint` — GitHub Actions workflow validation + +**Log Proof Lines:** +``` +PROOF: YAMLLINT=OK +PROOF: ACTIONLINT=OK +PROOF: LINT=OK +``` + +**Branch Protection:** ✅ **ci/lint** always required + +--- + +### ci/docs (Required for Docs PRs) +**Purpose:** Validate Markdown and links + +**Tools:** +- `markdownlint-cli2` — Uses `.markdownlint.jsonc` config +- `lychee` — Link checker (internal & external) + +**Log Proof Lines:** +``` +PROOF: MARKDOWNLINT=OK +PROOF: LINKS=OK +PROOF: DOCS=OK +``` + +**Branch Protection:** ✅ **ci/docs** required for docs changes + +**Path Triggers:** +- Runs on changes to `**/*.md` files +- `ci/lint` skips `.md` files (via `paths-ignore`) + +--- + +### ci/smoke (Optional but Recommended) +**Purpose:** Repo health checks, validator availability + +**Runs:** `scripts/validate.sh` + +**Checks:** +- Tool presence (`jq`, `yamllint`, `actionlint`, `gh`) +- Lint suite execution +- Custom validators (Bridge logs, fixtures, etc.) + +**Log Proof Lines:** +``` +PROOF: VALIDATORS=GREEN +PROOF: SMOKE=OK +``` + +**Branch Protection:** Optional (enable if needed) + +--- + +## When Workflows Run + +### Pull Request → main +- **ci/lint** — Always +- **ci/docs** — If `**/*.md` changed +- **ci/smoke** — If configured + +### Push → main +- Same checks confirm main's health + +### Manual Trigger +- Any workflow with `workflow_dispatch` (Actions tab → Run workflow) + +--- + +## PR Body Convention + +### Required Proof Lines (Human-Visible) +Every PR description must include: +``` +Category: +Keywords: comma, separated, words + +LINT=OK +SMOKE=OK (or VALIDATORS=GREEN) +``` + +**For docs-only PRs:** +``` +Category: Cooperative Technology +Keywords: documentation, ci, playbook + +DOCS=OK +LINT=OK +``` + +**For CI/docs or infra changes:** +- Set `Category: Cooperative Technology` + +--- + +## Reading Logs & Capturing Proof + +### How to Read CI Logs +1. Open PR → **Checks** tab +2. Click failing job +3. Click failing step +4. Scroll to end +5. Copy proof lines + +### Example Output +```bash +# End of ci/lint job +PROOF: YAMLLINT=OK +PROOF: ACTIONLINT=OK +PROOF: LINT=OK + +# End of ci/docs job +PROOF: MARKDOWNLINT=OK +PROOF: LINKS=OK +PROOF: DOCS=OK + +# End of ci/smoke job +PROOF: VALIDATORS=GREEN +PROOF: SMOKE=OK +``` + +--- + +## Common Failures & Quick Fixes + +### YAML Errors (ci/lint) + +**Brackets/spacing:** +```yaml +# ❌ Bad +branches: [ main ] + +# ✅ Good +branches: [main] +``` + +**Document start:** +```yaml +# Add if .yamllint.yaml requires it +--- +name: CI Lint +``` + +**Truthy values:** +```yaml +# Quote when needed +on: "push" +``` + +**Actionlint path/expr errors:** +- Fix the exact file:line it prints + +--- + +### Markdown & Link Errors (ci/docs) + +**Headings:** +```markdown +# Single H1 per file +## Nested levels increase by 1 +### Not allowed to skip levels (H1 → H3) +``` + +**Line length:** +- Wrap long lines +- Or add exceptions in `.markdownlint.jsonc` if truly needed + +**Code fences:** +```markdown + +```bash +echo "Good" +``` + +``` +echo "Bad" +``` +``` + +**Link failures:** +- **Internal:** Fix relative paths (prefer `./file.md` under `docs/`) +- **External:** If site blocks bots, add to lychee ignore list; otherwise update URL +- **Mailto:** Already excluded by `--exclude-mail` + +--- + +### HTTP Error Codes (Any Job) + +**401 Unauthorized:** +- Bad/expired credentials +- **Fix:** Refresh token/secret + +**403 Forbidden:** +- Missing scopes or branch protection rule +- **Fix:** Adjust PAT/scopes or update rule + +**422 Unprocessable Entity:** +- Invalid input / schema mismatch +- **Fix:** Fix workflow inputs or file format + +--- + +### Merge Conflicts + +**Resolution:** +1. Use **Resolve conflicts** button in PR +2. Remove conflict markers (`<<<<<<<`, `=======`, `>>>>>>>`) +3. Commit resolution +4. Re-run checks + +--- + +## scripts/validate.sh + +### Purpose +Runs all validators and outputs proof lines + +### What It Checks +```bash +#!/usr/bin/env bash +set -euo pipefail + +# 1. Tool presence +command -v jq >/dev/null || { echo "jq missing"; exit 1; } +command -v yamllint >/dev/null || { echo "yamllint missing"; exit 1; } +command -v actionlint >/dev/null || { echo "actionlint missing"; exit 1; } + +# 2. Lint suite +yamllint . || { echo "YAML lint failed"; exit 1; } +actionlint || { echo "Action lint failed"; exit 1; } + +# 3. Custom validators (add as needed) +# Example: Bridge log validation +if [[ -f logs/bridge/actions-$(date +%Y-%m-%d).ndjson ]]; then + tail -n 1 logs/bridge/actions-$(date +%Y-%m-%d).ndjson | jq empty || { + echo "Invalid NDJSON in Bridge logs" + exit 1 + } +fi + +# 4. Output proof lines +echo "LINT=OK" +echo "VALIDATORS=GREEN" +echo "SMOKE=OK" +``` + +### Running Locally +```bash +# From repo root +./scripts/validate.sh + +# Expected output: +LINT=OK +VALIDATORS=GREEN +SMOKE=OK +``` + +--- + +## Branching Strategy + +### Branch Naming +```bash +# Feature branches +feature/bridge-qa-endpoint +feature/governance-list-view + +# Docs branches +docs/update-operations-playbook +docs/add-module-spec + +# Claude sessions (special format) +claude/bridge-landing-011CUQtanTsWEweh3xMQupeE +# Must start with "claude/" and end with session ID +``` + +### Branch from main +```bash +git checkout main +git pull origin main +git checkout -b feature/my-tiny-change +``` + +--- + +## Commit Message Convention + +### Format +``` +(): + +[optional body] + +[optional footer] +``` + +### Types +- `feat` — New feature +- `fix` — Bug fix +- `docs` — Documentation only +- `style` — Formatting, missing semi-colons +- `refactor` — Code change that neither fixes bug nor adds feature +- `test` — Adding missing tests +- `chore` — Maintain (CI, build, deps) + +### Examples +```bash +docs: align overview with contributor hub + +feat(governance): add proposal scoring util + +fix(ci): correct docs workflow include paths + +chore(deps): bump next to 14.2.0 +``` + +--- + +## PR Template + +### Copy/Paste for PR Body +```markdown +## What & Why +<1-3 sentences describing the change> + +## Smallest Change +<1 sentence confirming this is the smallest shippable increment> + +## Touchpoints +- Files: + - `path/to/file1.ts` + - `path/to/file2.md` + +## Proof + +LINT=OK +SMOKE=OK (or VALIDATORS=GREEN, or DOCS=OK) + +## Category & Keywords +Category: +Keywords: comma, separated, words +``` + +--- + +## After Merge + +### Verify Main Health +1. Check push to `main` re-runs checks +2. Confirm output: + ``` + LINT=OK + VALIDATORS=GREEN + SMOKE=OK + ``` + +### Update Discussions +If change affects onboarding or contributor flow: +- Post short note in [Discussions #88](https://github.com/coopeverything/TogetherOS/discussions/88) + +### Update STATUS_v2.md +If module progress changed: +```bash +# Bump progress marker +docs/STATUS_v2.md + +# Find HTML comment like: + + +# Update to: + + +# Commit: +git commit -m "docs(status): bump governance to 5%" +``` + +--- + +## Useful Paths + +### CI/CD Files +``` +.github/workflows/ # All workflow YAMLs +.github/workflows/lint.yml # ci/lint +.github/workflows/ci_docs.yml # ci/docs +.github/workflows/deploy.yml # VPS deployment + +.yamllint.yaml # YAML linting rules +.markdownlint.jsonc # Markdown rules + +scripts/validate.sh # Main validator script +scripts/lint.sh # Lint runner +``` + +### Documentation +``` +docs/OPERATIONS.md # Contributor flow (start here) +docs/CI/Actions_Playbook.md # This spec, detailed +docs/modules/INDEX.md # Module hub +``` + +--- + +## Security & Access + +### Least-Privilege Tokens +- GitHub Actions use minimal permissions +- Contents/PR/Actions as needed +- **Never** use admin tokens unless absolutely required + +### Never Echo Secrets +```yaml +# ❌ Bad +- run: echo ${{ secrets.API_KEY }} + +# ✅ Good +- run: | + # Use secret in command, don't echo + curl -H "Authorization: Bearer ${{ secrets.API_KEY }}" ... +``` + +### Deployment Keys +- Stored in GitHub Secrets +- `SSH_PRIVATE_KEY`, `VPS_HOST`, `VPS_USER`, `VPS_PATH` +- Details in `docs/OPS/MAINTAINERS_DEPLOY.md` (internal) + +--- + +## Path Labels & Taxonomy + +### Canonical Path Names +Use these exact labels (from `codex/taxonomy/CATEGORY_TREE.json`): +``` +path:collaborative-education +path:social-economy +path:common-wellbeing +path:cooperative-technology +path:collective-governance +path:community-connection +path:collaborative-media-culture +path:common-planet +``` + +### Adding New Keywords +If you add a keyword: +1. Update `codex/taxonomy/CATEGORY_TREE.json` +2. Include short rationale in PR description +3. Update `docs/TogetherOS_CATEGORIES_AND_KEYWORDS.md` + +--- + +## Quick Checklist + +### Before Opening PR +- [ ] Smallest possible change +- [ ] Correct Path label selected +- [ ] Ran `./scripts/validate.sh` locally +- [ ] Relevant docs updated +- [ ] Proof lines captured (LINT=OK, SMOKE=OK, etc.) +- [ ] Commit messages follow convention + +### PR Description Includes +- [ ] What & Why (1-3 sentences) +- [ ] Smallest change confirmation +- [ ] Files touched list +- [ ] Proof lines +- [ ] Category & Keywords + +### After Merge +- [ ] Verify main health (checks pass) +- [ ] Update STATUS_v2.md if needed +- [ ] Post to Discussions #88 if affects contributors + +--- + +## Related KB Files + +- [Main KB](./togetheros-kb.md) — Core principles, workflow +- [Tech Stack](./tech-stack.md) — Tools, versions, dependencies +- [Architecture](./architecture.md) — Code structure, patterns +- [Cooperation Paths](./cooperation-paths.md) — Path labels and taxonomy diff --git a/.claude/knowledge/cooperation-paths.md b/.claude/knowledge/cooperation-paths.md new file mode 100644 index 00000000..8e5a1e49 --- /dev/null +++ b/.claude/knowledge/cooperation-paths.md @@ -0,0 +1,382 @@ +# 8 Cooperation Paths — Taxonomy + +## Overview + +TogetherOS organizes all activities around **8 Cooperation Paths** — the foundational categories for resilience and prosperity. Every issue, PR, proposal, and initiative must be labeled with one primary path. + +**Source:** `codex/taxonomy/CATEGORY_TREE.json` + +--- + +## 1. Collaborative Education + +**Mission:** Empower communities through shared learning and skill-building + +### Subcategories +- **Local organizing** — Community coordination, facilitation skills +- **Project management** — Planning, execution, delivery tracking +- **Caring for the elderly** — Elder care, intergenerational learning +- **Repairing electronics** — Right-to-repair, fix-it skills +- **Sustainable design** — Regenerative systems, circular economy principles +- **Peaceful conflict resolution** — Mediation, restorative justice +- **Mentorship & peer learning** — Skill exchanges, cohort learning + +### Examples +- Civic reasoning studios (claims → evidence → tradeoffs) +- Skill trees and badges anchored to real initiatives +- Co-teaching cohorts on governance, tech, sustainability +- Project-tethered learning (immediately useful) +- Global repository of best practices + +### Tech Features (Planned) +- Cohort management +- Skill trees with progression +- Lesson runner (scenario-based micro-challenges) +- Badge system tied to verified contributions +- Peer review and feedback loops + +--- + +## 2. Social Economy + +**Mission:** Build cooperative enterprises and mutual support systems + +### Subcategories +- **Cooperatives** — Worker/consumer co-ops, producer associations +- **Timebank exchange** — Hour-for-hour service trading +- **Repair & reuse** — Fix-it cafes, tool libraries +- **Upcycling** — Transform waste into value +- **Mutual aid** — Request/offer boards, emergency relief +- **Donations & meaningful investment** — Cooperative treasury, impact investing + +### Examples +- Timebanking with fair-exchange index +- Collective purchasing (bulk buys, transparent bids) +- CSAs (Community Supported Agriculture) +- Repair/reuse networks +- Community investment pools +- Member-owned credit unions +- Circular economy practices +- Social Horizon currency (equitable wealth distribution) + +### Tech Features (Planned) +- Mutual aid request/offer boards +- Timebank ledger with balance tracking +- Fair-exchange index (prevent exploitation) +- Collective purchase coordination +- Support Points allocation +- Social Horizon wallet (mock → testnet → real) + +--- + +## 3. Common Wellbeing + +**Mission:** Ensure health, nutrition, and care for all community members + +### Subcategories +- **Preventative care** — Wellness programs, health education +- **Public health** — Disease prevention, vaccination drives +- **Nutrition** — Food security, healthy eating education +- **Mental health first aid** — Peer support, crisis intervention +- **Community clinics** — Local health services, integrative care +- **Movement & recovery** — Exercise groups, physical therapy + +### Examples +- Peer support circles +- Mental-health crisis response +- Community clinics (sliding scale) +- Integrative care networks +- Food-security ladders (gardens, pantries, meal programs) +- Emergency relief protocols + +### Tech Features (Planned) +- Peer support board templates +- Resource directory (clinics, counselors, food banks) +- Event coordination (wellness workshops, support groups) +- Privacy-preserving check-ins + +--- + +## 4. Cooperative Technology + +**Mission:** Build open, auditable, privacy-preserving digital infrastructure + +### Subcategories +- **Open hardware** — Repairable, modular devices +- **Open source software** — Community-auditable code +- **Privacy & security** — Encryption, zero-knowledge proofs +- **Community networks** — Mesh networks, local ISPs +- **Federated services** — Decentralized platforms with local autonomy +- **Human-centered AI** — Assist-not-adjudicate AI like Bridge + +### Examples +- TogetherOS platform itself +- Open-source modules for governance, mutual aid +- Privacy-preserving identity (pseudonymous by default) +- Federated protocols (inter-group coordination) +- Bridge AI assistant (grounded, cited, transparent) +- Modular tools communities can fork and deploy + +### Tech Features +- Monorepo with Next.js 14, TypeScript, Tailwind +- tRPC for typed APIs +- NDJSON audit logs +- Federation gateway (planned) +- Zero-knowledge attestations (exploratory) + +--- + +## 5. Collective Governance + +**Mission:** Enable transparent, consent-based decision-making + +### Subcategories +- **Direct legislation** — Community-written laws and policies +- **Deliberation & discourse** — Structured discussions, evidence-based +- **Empathic moderation** — De-escalation, fairness, rotating roles +- **Consensus tools** — Approval, ranked choice, consent voting +- **Participatory budgeting** — Community allocates funds +- **Conflict resolution** — Civic jury, minority reports, appeals + +### Examples +- Proposal pipeline (Present → Research → Deliberate → Vote → Act → Review) +- Support Points for prioritization +- Minority report preservation +- Cooling-off periods, challenge windows +- Civic jury for disputes +- Rotating, recallable moderators +- Post-decision reviews + +### Tech Features (Planned) +- Proposals & Decisions module (MVP: create/list/view) +- Voting methods (approval, ranked, consent) +- Evidence bundles, option trees, trade-off matrices +- Position recording (including minority) +- Delivery reports tied to proposals +- Audit logs and public dashboards + +--- + +## 6. Community Connection + +**Mission:** Foster relationships, events, and local coordination + +### Subcategories +- **Local hubs** — Physical/virtual gathering spaces +- **Mutual aid boards** — Help requests and offers +- **Timebanking** — Service exchange tracking +- **Events & meetups** — Community gatherings, celebrations +- **Volunteer matching** — Connect helpers with needs +- **Skill exchanges** — Trade expertise and knowledge + +### Examples +- Directory of local/thematic groups +- Event calendar with RSVP tracking +- Mutual aid classifieds +- Volunteer opportunity board +- Skill exchange coordination +- Mobility/couch-surfing network +- Social feed (community activity) + +### Tech Features (Planned) +- Group directory with federation handles +- Event management (create, RSVP, reminders) +- Mutual aid boards (already covered in Social Economy) +- Social feed with Path filtering +- Geo-mapping of projects and needs +- Member profiles with skills/interests + +--- + +## 7. Collaborative Media & Culture + +**Mission:** Create positive narratives and preserve cooperative achievements + +### Subcategories +- **Storytelling** — Member-made films, podcasts, articles +- **Open archives** — Living history of movements +- **Community radio** — Local broadcasting +- **Documentaries** — Visual storytelling of projects +- **Commons media** — Shared creative resources +- **Cultural restoration** — Revive traditions, languages, practices + +### Examples +- Member-made films, music, writing +- Documentation of cooperative projects +- Positive narratives (counter to extractive media) +- Living archive of achievements +- Cultural celebrations and festivals +- Oral history projects + +### Tech Features (Planned) +- Media posts and showcases +- Gallery component for visual content +- Video/audio embedding +- Tagging by Path and theme +- Creative Commons licensing support + +--- + +## 8. Common Planet + +**Mission:** Regenerate ecosystems and build climate resilience + +### Subcategories +- **Regeneration** — Soil health, ecosystem restoration +- **Conservation** — Protect biodiversity, natural habitats +- **Local agriculture** — Urban farms, community gardens +- **Circular materials** — Zero waste, composting, recycling +- **Right-to-repair** — Fix products, reduce e-waste +- **Climate resilience** — Adaptation strategies, disaster prep + +### Examples +- Regenerative agriculture projects +- Energy cooperatives +- Circular material flows +- Modular sustainable tech +- Resilience networks (climate adaptation) +- Seed banks and local food systems +- Conservation initiatives + +### Tech Features (Planned) +- Project cards with impact metrics +- Resource tracking (carbon, waste, energy) +- Map of ecological projects +- Metric stubs for environmental impact +- Supply chain transparency + +--- + +## Path Labels (GitHub/Issues/PRs) + +### Required Format +``` +path:collaborative-education +path:social-economy +path:common-wellbeing +path:cooperative-technology +path:collective-governance +path:community-connection +path:collaborative-media-culture +path:common-planet +``` + +### Usage Rules +1. **Every issue/PR must have exactly one Path label** +2. **Use kebab-case** (lowercase with hyphens) +3. **No shortcuts** — Use full canonical names from taxonomy +4. **Update taxonomy if new keywords needed** — Add to `codex/taxonomy/CATEGORY_TREE.json` with rationale + +--- + +## Keyword Palette + +### From CATEGORY_TREE.json +```json +{ + "Collaborative": ["education", "art", "design", "innovation", "culture"], + "Social": ["economy", "justice", "inclusion", "care"], + "Common": ["wellbeing", "environment", "shared resources"], + "Cooperative": ["technology", "organization", "governance"], + "Collective": ["action", "legislation", "transformation"] +} +``` + +### How to Use +- **Issues:** Add Path label + specific keywords in description +- **PRs:** Path label required; keywords in commit messages +- **Proposals:** Tagged with primary Path + secondary themes +- **Codex notes:** Stored in `codex/notes/{path}/` + +--- + +## Archetype Paths (Member Journeys) + +These are **member archetypes**, not Cooperation Paths (but often aligned): + +1. **Builder** — Aligned with Cooperative Technology +2. **Community Heart** — Aligned with Community Connection, Common Wellbeing +3. **Guided Contributor** — Follows structured tasks across all paths +4. **Steady Cultivator** — Long-term support across all paths + +Members can blend archetypes and contribute to multiple Cooperation Paths. + +--- + +## How Paths Drive Prioritization + +### Support Points Allocation +- Members allocate SP to proposals tagged with Paths +- High-SP proposals in a Path → that Path gets prioritized +- Transparent portfolios show community values + +### Contributor Interest +- **Discussions #88:** Contributors declare Path interest +- Module work mapped to Paths +- Interest raises priority for that Path's modules + +### Balanced Growth +- Aim for progress across all 8 Paths (not just tech) +- Monthly reviews: Are any Paths neglected? +- Adjust outreach and recruitment accordingly + +--- + +## Metrics per Path (Future) + +### Collaborative Education +- Cohorts launched +- Skills taught/learned +- Badges earned +- Completion rates + +### Social Economy +- Mutual aid transactions +- Timebank hours exchanged +- Collective purchase savings +- Support Points allocated + +### Common Wellbeing +- Support groups active +- Members served +- Resources distributed +- Crisis interventions + +### Cooperative Technology +- Modules shipped +- PRs merged +- Contributors onboarded +- Infrastructure uptime + +### Collective Governance +- Proposals submitted/decided +- Voter participation % +- Delivery reports published +- Minority reports preserved + +### Community Connection +- Events held +- Attendance rates +- New groups formed +- Member connections made + +### Collaborative Media & Culture +- Media pieces created +- Reach/views +- Cultural events held +- Archives populated + +### Common Planet +- Projects launched +- Carbon impact (reduced) +- Ecosystems restored +- Resilience plans active + +--- + +## Related KB Files + +- [Main KB](./togetheros-kb.md) — Core principles, workflow +- [Social Economy](./social-economy.md) — Support Points, mutual aid, timebanking +- [Governance Module](./governance-module.md) — Proposals and decisions +- [Architecture](./architecture.md) — How Paths map to code structure diff --git a/.claude/knowledge/data-models.md b/.claude/knowledge/data-models.md new file mode 100644 index 00000000..a7365714 --- /dev/null +++ b/.claude/knowledge/data-models.md @@ -0,0 +1,716 @@ +# TogetherOS Data Models + +## Overview + +This document consolidates all **core entity specifications** for TogetherOS. Each entity follows domain-driven design principles with clear interfaces and validation rules. + +**Current Phase:** All models are conceptual. Implementation uses **fixture repos** (in-memory) for MVP. + +--- + +## Core Entities + +### Group +```typescript +interface Group { + id: string // UUID + name: string // Display name + handle: string // Unique, federation-ready (@group@domain.tld) + type: 'local' | 'thematic' | 'federated' + description?: string + location?: string // City, region + members: string[] // Member IDs + createdAt: Date + updatedAt: Date +} +``` + +**Validation:** +- `name`: 3-100 chars +- `handle`: Unique, lowercase, alphanumeric + hyphens, 3-50 chars +- `type`: Required enum + +**Repository Interface:** +```typescript +interface GroupRepo { + create(input: CreateGroupInput): Promise + findById(id: string): Promise + findByHandle(handle: string): Promise + list(filters: GroupFilters): Promise + update(id: string, updates: Partial): Promise + delete(id: string): Promise +} +``` + +--- + +### Member +```typescript +interface Member { + id: string // UUID + email: string // Private, unique + handle: string // Public, unique + displayName?: string + bio?: string + archetypes: Archetype[] // ['builder', 'community_heart', etc.] + capabilities: string[] // Unlocked features + reputation: MemberReputation + supportPoints: SupportPointsWallet + createdAt: Date + updatedAt: Date + lastActiveAt?: Date +} + +type Archetype = 'builder' | 'community_heart' | 'guided_contributor' | 'steady_cultivator' +``` + +**Validation:** +- `email`: Valid email format, unique +- `handle`: 3-30 chars, alphanumeric + underscores, unique +- `archetypes`: At least one required + +**Privacy:** +- **Public:** `handle`, `displayName`, `bio`, `archetypes`, `reputation` +- **Private:** `email`, `lastActiveAt` (unless member opts in) + +--- + +### Proposal +```typescript +interface Proposal { + id: string // UUID + groupId: string // Which group owns this + authorId: string // Member who created + title: string // 3-200 chars + summary: string // 10-2000 chars + evidence: Evidence[] // Research, links, data + options: Option[] // Alternatives with trade-offs + positions: Position[] // Member stances + minorityReport?: string // Objections codified + status: ProposalStatus + createdAt: Date + updatedAt: Date + decidedAt?: Date +} + +type ProposalStatus = + | 'draft' // Being written + | 'research' // Gathering evidence/options + | 'deliberation' // Discussion phase + | 'voting' // Decision in progress + | 'decided' // Outcome reached + | 'delivery' // Being implemented + | 'reviewed' // Post-implementation review + | 'archived' // Closed/historical +``` + +**Validation:** +- `title`: 3-200 chars, required +- `summary`: 10-2000 chars, required +- `status`: Valid enum value +- `evidence`: Array (can be empty) +- `options`: Array (can be empty) + +--- + +### Evidence +```typescript +interface Evidence { + id: string // UUID + proposalId: string + type: 'research' | 'data' | 'expert' | 'precedent' + title: string // 3-100 chars + url?: string // Valid URL or null + summary: string // 10-500 chars + attachedBy: string // Member ID + attachedAt: Date +} +``` + +--- + +### Option +```typescript +interface Option { + id: string // UUID + proposalId: string + title: string // 3-100 chars + description: string // 10-1000 chars + tradeoffs: Tradeoff[] + estimatedCost?: number // In local currency or SP + estimatedTime?: string // e.g., "3 months" + proposedBy: string // Member ID + proposedAt: Date +} + +interface Tradeoff { + aspect: string // e.g., "Cost", "Time", "Impact" + pro: string // What's good + con: string // What's challenging +} +``` + +--- + +### Position +```typescript +interface Position { + id: string // UUID + proposalId: string + memberId: string + stance: 'support' | 'oppose' | 'abstain' | 'block' + reasoning: string // 10-500 chars + isMinority: boolean // Flagged for preservation + recordedAt: Date +} +``` + +**Validation:** +- `stance`: Required enum +- `reasoning`: Required if `stance` is 'oppose' or 'block' +- `isMinority`: Auto-computed based on vote outcome + +--- + +### Decision +```typescript +interface Decision { + id: string // UUID + proposalId: string + method: 'approval' | 'ranked_choice' | 'consent' + quorum: number // Required participation (%) + threshold: number // % needed to pass + outcome: 'approved' | 'rejected' | 'amended' + votes: Vote[] + minorityReport?: string // Preserved objections + challengeWindow: Date // Appeals deadline + decidedAt: Date +} + +interface Vote { + memberId: string + choice: string | string[] // Depends on method + weight: number // Usually 1, could be role-based + castAt: Date +} +``` + +--- + +### Initiative +```typescript +interface Initiative { + id: string // UUID + decisionId: string // Links to approved proposal + title: string + tasks: Task[] + owners: string[] // Member IDs + milestones: Milestone[] + proofs: Proof[] // Delivery artifacts + status: 'planned' | 'in_progress' | 'delivered' | 'reviewed' + createdAt: Date + completedAt?: Date +} + +interface Task { + id: string + title: string + description: string + assignee?: string // Member ID + status: 'todo' | 'in_progress' | 'done' + dueDate?: Date +} + +interface Milestone { + id: string + title: string + targetDate: Date + completed: boolean + completedAt?: Date +} + +interface Proof { + id: string + type: 'pr_link' | 'commit_id' | 'report' | 'metric' + url?: string + description: string + timestamp: Date +} +``` + +--- + +## Social Economy Models + +### SupportPointsWallet +```typescript +interface SupportPointsWallet { + memberId: string + total: number // Current balance + allocated: number // Locked in active proposals + earned: number // From contributions + history: SPTransaction[] +} + +interface SPTransaction { + id: string // UUID + memberId: string + type: 'allocate' | 'reclaim' | 'earn' | 'initial' + amount: number // Positive or negative + targetId?: string // Proposal/initiative ID + timestamp: Date + reason?: string +} +``` + +**Rules:** +- All members start with 100 SP +- Max 10 SP per idea +- Allocated SP locked until proposal closes +- Earning SP: Complete initiatives, helpful actions + +--- + +### MutualAidRequest +```typescript +interface MutualAidRequest { + id: string // UUID + groupId: string + requesterId: string // Member ID + category: 'material' | 'time' | 'skill' | 'space' + title: string // 3-100 chars + description: string // 10-500 chars + urgency: 'low' | 'medium' | 'high' + location?: string + neededBy?: Date + status: 'open' | 'matched' | 'completed' | 'cancelled' + createdAt: Date + updatedAt: Date +} +``` + +--- + +### MutualAidOffer +```typescript +interface MutualAidOffer { + id: string // UUID + requestId: string + offererId: string // Member ID + message: string // 10-500 chars + availability: string // e.g., "Saturday 2-4pm" + status: 'pending' | 'accepted' | 'declined' | 'withdrawn' + createdAt: Date +} +``` + +--- + +### MutualAidTransaction +```typescript +interface MutualAidTransaction { + id: string // UUID + requestId: string + offererId: string + requesterId: string + confirmedBy: string[] // Both IDs when complete + completedAt?: Date + rating?: number // 1-5 stars + feedback?: string // Optional text +} +``` + +--- + +### TimeBankAccount +```typescript +interface TimeBankAccount { + memberId: string + balance: number // Current time credits + earned: number // Total earned (all time) + spent: number // Total spent (all time) + transactions: TimeBankTransaction[] +} + +interface TimeBankTransaction { + id: string // UUID + fromId: string // Service provider + toId: string // Service receiver + hours: number // Decimal (e.g., 2.5) + service: string // Description (e.g., "Car repair") + confirmedBy: string[] // Both parties + timestamp: Date +} +``` + +--- + +### FairExchangeIndex +```typescript +interface FairExchangeIndex { + memberId: string + balance: number // Current time credits + earnedLast6Mo: number // Hours provided + spentLast6Mo: number // Hours received + ratio: number // spent / earned + alert: boolean // True if ratio > 2.0 + message?: string // Nudge message if imbalanced +} +``` + +**Rules:** +- Alert triggered if `ratio > 2.0` (taking 2x more than giving) +- Nudge: "Consider offering a service to balance your exchange" +- Not punitive, just informational + +--- + +### CollectivePurchase +```typescript +interface CollectivePurchase { + id: string // UUID + groupId: string + coordinatorId: string // Organizer + item: string // What's being purchased + supplier?: string // Vendor name + quantity: number // Total needed + unit: string // lbs, units, etc. + pricePerUnit: number + threshold: number // Min participants to proceed + deadline: Date + status: 'open' | 'threshold_met' | 'ordered' | 'delivered' | 'cancelled' + participants: PurchaseParticipant[] + createdAt: Date +} + +interface PurchaseParticipant { + memberId: string + quantity: number // Amount they want + price: number // May vary (solidarity pricing) + paid: boolean + pickedUp: boolean +} +``` + +--- + +### SocialHorizonWallet (Placeholder) +```typescript +interface SocialHorizonWallet { + memberId: string + balance: number // SH tokens + staked: number // Long-term locked + earned: number // From verified contributions + spent: number // Total spent + transactions: SHTransaction[] +} + +interface SHTransaction { + id: string // UUID + fromId: string + toId: string + amount: number + type: 'contribution_reward' | 'purchase' | 'grant' | 'treasury_distribution' + metadata: Record + timestamp: Date +} +``` + +**Status:** Conceptual design only. Implementation TBD. + +--- + +## Bridge AI Models + +### BridgeQuery +```typescript +interface BridgeQuery { + id: string // UUID + question: string // User's question + questionHash: string // SHA-256 for privacy + answer: string // Generated response + sources: Source[] // Citations + disclaimer: string // Standard warning + ipHash: string // Anonymized + timestamp: Date +} + +interface Source { + path: string // Relative to repo root + lines: number[] // Line ranges cited +} +``` + +--- + +### BridgeSummary +```typescript +interface BridgeSummary { + id: string // UUID + threadId: string // Forum topic or discussion + summary: string // Structured markdown + tags: string[] // e.g., ["type:increment", "size:S"] + links: string[] // Relevant URLs + sources: Source[] // Citations + disclaimer: string // Standard warning + generatedAt: Date +} +``` + +--- + +### BridgeLogEntry (NDJSON) +```typescript +interface BridgeLogEntry { + id: string // UUID + timestamp: string // ISO 8601 + event_type: 'qa' | 'tidy' | 'moderation' + metadata: { + question_hash?: string // SHA-256 + answer_length?: number + sources?: Source[] + ip_hash?: string // SHA-256 + [key: string]: any + } + content_hash?: string // SHA-256 for integrity +} +``` + +**Storage:** `logs/bridge/actions-YYYY-MM-DD.ndjson` + +**Validation:** Last line must parse as valid JSON with required fields + +--- + +## Reputation & Gamification + +### MemberReputation +```typescript +interface MemberReputation { + memberId: string + badges: Badge[] + contributions: Contribution[] + mutualAidScore: number // 0-100 + governanceScore: number // 0-100 + overallScore: number // Composite +} +``` + +--- + +### Badge +```typescript +interface Badge { + id: string // UUID + name: string // "Gardener", "Code Contributor" + description: string + icon: string // URL or emoji + earnedAt: Date + criteria: string // How it's earned +} +``` + +--- + +### Contribution +```typescript +interface Contribution { + id: string // UUID + memberId: string + type: 'code' | 'docs' | 'organizing' | 'mutual_aid' | 'proposal' + title: string + description: string + verifiedBy?: string[] // Member IDs who verified + timestamp: Date +} +``` + +--- + +### MemberPath +```typescript +interface MemberPath { + memberId: string + primaryPath: 'builder' | 'community_heart' | 'guided_contributor' | 'steady_cultivator' + secondaryPaths: string[] // Additional paths + skillTree: SkillNode[] + level: number // Based on contributions + visualState: 'seed' | 'seedling' | 'young_tree' | 'majestic_tree' +} + +interface SkillNode { + id: string // UUID + name: string // "First PR Merged" + description: string + path: string // Which archetype path + unlocked: boolean + unlockedAt?: Date + requirements: string[] // Prerequisites +} +``` + +--- + +## Events & Community + +### Event +```typescript +interface Event { + id: string // UUID + groupId: string + organizerId: string // Member ID + title: string // 3-100 chars + description: string // 10-2000 chars + location: string // Address or "Virtual" + startDate: Date + endDate: Date + attendees: string[] // Member IDs + skills: string[] // Skill exchange tags + status: 'upcoming' | 'ongoing' | 'completed' | 'cancelled' + createdAt: Date +} +``` + +--- + +### Transaction (Universal) +```typescript +interface Transaction { + id: string // UUID + type: 'support_points' | 'timebank' | 'treasury' | 'mutual_aid' + fromId: string // Member or Group ID + toId: string // Member or Group ID + amount: number + currency: 'SP' | 'time' | 'SH' | 'USD' + metadata: Record + timestamp: Date +} +``` + +**Purpose:** Unified transaction log across all economic activities + +--- + +## Federation Models (Future) + +### FederatedGroup +```typescript +interface FederatedGroup { + handle: string // @groupname@domain.tld + homeInstance: string // Domain + publicKey: string // For signatures + protocols: string[] // Supported federation features + lastSyncedAt?: Date +} +``` + +--- + +### FederatedProposal +```typescript +interface FederatedProposal { + localId: string // Local proposal ID + remoteId: string // Remote proposal ID + remoteInstance: string // Domain + syncedAt: Date + status: 'synced' | 'diverged' | 'conflict' +} +``` + +--- + +## Validation Schemas (Zod Examples) + +### Proposal Creation +```typescript +import { z } from 'zod' + +export const createProposalSchema = z.object({ + title: z.string().min(3).max(200), + summary: z.string().min(10).max(2000), + authorId: z.string().uuid(), + groupId: z.string().uuid().optional(), +}) + +export type CreateProposalInput = z.infer +``` + +### Member Profile Update +```typescript +export const updateMemberSchema = z.object({ + displayName: z.string().min(1).max(50).optional(), + bio: z.string().max(500).optional(), + archetypes: z.array(z.enum(['builder', 'community_heart', 'guided_contributor', 'steady_cultivator'])).optional(), +}) + +export type UpdateMemberInput = z.infer +``` + +--- + +## Fixture Examples + +### Proposal Fixtures +```json +{ + "proposals": [ + { + "id": "prop-1", + "groupId": "group-boston", + "authorId": "member-alice", + "title": "Community garden in Central Park", + "summary": "Convert unused northeast corner into shared garden space with raised beds, tool shed, and composting area.", + "evidence": [], + "options": [], + "positions": [], + "status": "draft", + "createdAt": "2025-01-10T09:00:00Z", + "updatedAt": "2025-01-10T09:00:00Z" + } + ] +} +``` + +### Member Fixtures +```json +{ + "members": [ + { + "id": "member-alice", + "email": "alice@example.com", + "handle": "alice_organizer", + "displayName": "Alice", + "bio": "Community organizer passionate about local food systems", + "archetypes": ["community_heart"], + "capabilities": ["create_proposal", "organize_events"], + "reputation": { + "memberId": "member-alice", + "badges": [], + "contributions": [], + "mutualAidScore": 75, + "governanceScore": 60, + "overallScore": 68 + }, + "supportPoints": { + "memberId": "member-alice", + "total": 100, + "allocated": 0, + "earned": 0, + "history": [] + }, + "createdAt": "2025-01-01T00:00:00Z", + "updatedAt": "2025-01-15T10:00:00Z" + } + ] +} +``` + +--- + +## Related KB Files + +- [Main KB](./togetheros-kb.md) — Core principles, workflow +- [Architecture](./architecture.md) — Repository pattern, domain-driven design +- [Bridge Module](./bridge-module.md) — Bridge-specific entities +- [Governance Module](./governance-module.md) — Proposal/decision flow +- [Social Economy](./social-economy.md) — Economic primitives diff --git a/.claude/knowledge/governance-module.md b/.claude/knowledge/governance-module.md new file mode 100644 index 00000000..67a82d4f --- /dev/null +++ b/.claude/knowledge/governance-module.md @@ -0,0 +1,673 @@ +# Governance Module — Proposals & Decisions + +## Overview + +**Scope:** Create, deliberate, and decide on proposals with transparent rules and lightweight, testable flows + +**Status:** 0% implementation +**Owner:** @coopeverything-core +**Labels:** `module:governance` +**Next milestone:** Submit a minimal proposal and see it in a list + +--- + +## Why This Exists + +Members must be able to: +- Turn ideas into formal proposals +- Discuss with evidence and trade-offs +- Make consent-based decisions +- Track delivery and review outcomes + +We ship a **thin vertical slice first** so contributors can see end-to-end value quickly: +**Submit → List → View details** (voting comes later) + +--- + +## MVP Slices (Implementation Order) + +### 1. Proposal Create (API + Domain) + +**Acceptance Criteria:** +- `POST /api/proposals` validates with Zod (`title`, `summary`, `authorId`, `createdAt`) +- Stores to in-memory/fixture repo +- Returns `201` with `{id}` +- Unit test covers happy path + validation errors + +**Files:** +``` +packages/types/src/governance.ts # Proposal interface +packages/validators/src/governance.ts # createProposalSchema +apps/api/src/modules/governance/ + ├── entities/Proposal.ts # Domain model + ├── repos/ProposalRepo.ts # Interface + ├── repos/InMemoryProposalRepo.ts # Fixture implementation + └── handlers/createProposal.ts # API handler +``` + +**Example:** +```typescript +// Request +POST /api/proposals +{ + "title": "Add community garden to park", + "summary": "Proposal to convert unused space...", + "authorId": "user-123" +} + +// Response +201 Created +{ + "id": "proposal-abc", + "createdAt": "2025-01-15T10:00:00Z" +} +``` + +--- + +### 2. Proposal List (UI) + +**Acceptance Criteria:** +- Route `/governance` lists proposals with: `title`, `author`, `createdAt` +- Empty state, loading skeleton, and error state present +- Storybook story for `` with empty/loaded states + +**Files:** +``` +apps/web/app/(platform)/governance/ + ├── page.tsx # List route + └── layout.tsx # Shared layout + +packages/ui/src/governance/ + ├── ProposalList.tsx # Main component + ├── ProposalCard.tsx # Individual proposal + ├── ProposalListSkeleton.tsx # Loading state + └── EmptyProposals.tsx # Empty state +``` + +**UI States:** +```typescript +type ProposalListState = + | { status: 'loading' } + | { status: 'empty' } + | { status: 'error'; error: Error } + | { status: 'success'; data: Proposal[] } +``` + +--- + +### 3. Proposal Details (UI + API) + +**Acceptance Criteria:** +- `/governance/[id]` shows `title`, `summary`, timestamps +- 404 guarded (invalid id) +- Contract test for `GET /api/proposals/:id` with Zod parsing + +**Files:** +``` +apps/web/app/(platform)/governance/ + └── [id]/ + └── page.tsx # Detail route + +packages/ui/src/governance/ + ├── ProposalView.tsx # Detail component + ├── ProposalViewSkeleton.tsx # Loading state + └── ProposalNotFound.tsx # 404 state + +apps/api/src/modules/governance/handlers/ + └── getProposal.ts # GET handler +``` + +**Example:** +```typescript +// Request +GET /api/proposals/proposal-abc + +// Response (Success) +200 OK +{ + "id": "proposal-abc", + "title": "Add community garden", + "summary": "Proposal to convert...", + "authorId": "user-123", + "createdAt": "2025-01-15T10:00:00Z", + "updatedAt": "2025-01-15T10:00:00Z", + "status": "draft" +} + +// Response (Not Found) +404 Not Found +{ + "error": { + "code": "PROPOSAL_NOT_FOUND", + "message": "Proposal with id 'proposal-xyz' does not exist" + } +} +``` + +--- + +### 4. Seed & Fixtures (Ops) + +**Acceptance Criteria:** +- `packages/governance-fixtures/seed.ts` adds 3 demo proposals +- `pnpm -w seed:governance` runs and logs inserted ids +- Proof-line in `scripts/validate.sh` confirms seeds runnable + +**Files:** +``` +packages/governance-fixtures/ + ├── proposals.json # Demo data + ├── seed.ts # Seed script + └── index.ts # Exports + +scripts/validate.sh # Add seed check +``` + +**Example Fixture:** +```json +{ + "proposals": [ + { + "id": "prop-1", + "title": "Community garden in Central Park", + "summary": "Convert unused northeast corner...", + "authorId": "member-alice", + "status": "draft", + "createdAt": "2025-01-10T09:00:00Z" + }, + { + "id": "prop-2", + "title": "Weekly farmers market", + "summary": "Partner with local farms...", + "authorId": "member-bob", + "status": "deliberation", + "createdAt": "2025-01-12T14:30:00Z" + } + ] +} +``` + +--- + +## Full Governance Pipeline (Future Phases) + +### Complete Flow +1. **Present** — Submit proposal with evidence +2. **Prioritize** — Community allocates Support Points +3. **Research** — Stewards produce options + trade-offs +4. **Positions** — Members record stances (including minority) +5. **Deliberate** — Structured discussion with empathy rules +6. **Vote** — Configurable methods (approval, ranked, consent) +7. **Act** — Convert to Initiative with tasks/owners +8. **Review** — Delivery report, metrics, learnings +9. **Legislate/Amend** — Revisit via feedback loop + +### Safeguards +- **Minority reports:** Codified and preserved +- **Cooling-off periods:** Prevent rushed decisions +- **Challenge windows:** Appeals deadline +- **Civic jury:** Dispute resolution +- **Conflict of interest:** Declarations and recusal +- **Delivery reports:** Tied to proposals, public audit + +--- + +## Data Models + +### Proposal Entity +```typescript +interface Proposal { + id: string + groupId: string // Which group owns this + authorId: string // Member who created + title: string // 3-200 chars + summary: string // 10-2000 chars + evidence: Evidence[] // Research, links, data + options: Option[] // Alternatives with trade-offs + positions: Position[] // Member stances + minorityReport?: string // Objections codified + status: ProposalStatus + createdAt: Date + updatedAt: Date + decidedAt?: Date +} + +type ProposalStatus = + | 'draft' // Being written + | 'research' // Gathering evidence/options + | 'deliberation' // Discussion phase + | 'voting' // Decision in progress + | 'decided' // Outcome reached + | 'delivery' // Being implemented + | 'reviewed' // Post-implementation review + | 'archived' // Closed/historical +``` + +### Evidence +```typescript +interface Evidence { + id: string + proposalId: string + type: 'research' | 'data' | 'expert' | 'precedent' + title: string + url?: string + summary: string + attachedBy: string // Member ID + attachedAt: Date +} +``` + +### Option +```typescript +interface Option { + id: string + proposalId: string + title: string + description: string + tradeoffs: Tradeoff[] + estimatedCost?: number + estimatedTime?: string // e.g., "3 months" + proposedBy: string // Member ID + proposedAt: Date +} + +interface Tradeoff { + aspect: string // e.g., "Cost", "Time", "Impact" + pro: string + con: string +} +``` + +### Position +```typescript +interface Position { + id: string + proposalId: string + memberId: string + stance: 'support' | 'oppose' | 'abstain' | 'block' + reasoning: string + isMinority: boolean // Flagged for preservation + recordedAt: Date +} +``` + +### Decision (Future) +```typescript +interface Decision { + id: string + proposalId: string + method: 'approval' | 'ranked_choice' | 'consent' + quorum: number // Required participation + threshold: number // % needed to pass + outcome: 'approved' | 'rejected' | 'amended' + votes: Vote[] + minorityReport?: string + challengeWindow: Date // Appeals deadline + decidedAt: Date +} + +interface Vote { + memberId: string + choice: string | string[] // Depends on method + weight: number // Usually 1, could be role-based + castAt: Date +} +``` + +--- + +## API Contracts + +### POST /api/proposals + +**Request:** +```typescript +{ + title: string // 3-200 chars + summary: string // 10-2000 chars + authorId: string // UUID + groupId?: string // Optional, defaults to member's primary group +} +``` + +**Response (Success):** +```typescript +201 Created +{ + id: string + createdAt: string // ISO 8601 +} +``` + +**Response (Validation Error):** +```typescript +422 Unprocessable Entity +{ + error: { + code: "VALIDATION_ERROR", + message: "Title must be at least 3 characters", + details: { field: "title", value: "AB" } + } +} +``` + +--- + +### GET /api/proposals + +**Query Params:** +```typescript +{ + groupId?: string // Filter by group + status?: string // Filter by status + authorId?: string // Filter by author + limit?: number // Default 50, max 100 + offset?: number // Pagination +} +``` + +**Response:** +```typescript +200 OK +{ + proposals: Proposal[] + total: number + limit: number + offset: number +} +``` + +--- + +### GET /api/proposals/:id + +**Response (Success):** +```typescript +200 OK +{ + id: string + groupId: string + authorId: string + title: string + summary: string + evidence: Evidence[] + options: Option[] + positions: Position[] + minorityReport?: string + status: string + createdAt: string + updatedAt: string + decidedAt?: string +} +``` + +**Response (Not Found):** +```typescript +404 Not Found +{ + error: { + code: "PROPOSAL_NOT_FOUND", + message: "Proposal with id 'xyz' does not exist" + } +} +``` + +--- + +## UI Components + +### ProposalList +```typescript +interface ProposalListProps { + groupId?: string + status?: ProposalStatus + emptyMessage?: string +} + +// States: loading | empty | error | success +``` + +### ProposalCard +```typescript +interface ProposalCardProps { + proposal: Proposal + onView?: (id: string) => void + showAuthor?: boolean + showStatus?: boolean +} +``` + +### ProposalView +```typescript +interface ProposalViewProps { + proposalId: string +} + +// Fetches proposal, handles loading/error/404 +// Shows: title, summary, evidence, options, positions +``` + +### ProposalForm (Future) +```typescript +interface ProposalFormProps { + initialValues?: Partial + onSubmit: (data: CreateProposalInput) => Promise + onCancel?: () => void +} + +// Uses React Hook Form + Zod validation +``` + +--- + +## Validation Schemas (Zod) + +### Create Proposal +```typescript +import { z } from 'zod' + +export const createProposalSchema = z.object({ + title: z.string().min(3).max(200), + summary: z.string().min(10).max(2000), + authorId: z.string().uuid(), + groupId: z.string().uuid().optional(), +}) + +export type CreateProposalInput = z.infer +``` + +### Proposal Response +```typescript +export const proposalSchema = z.object({ + id: z.string().uuid(), + groupId: z.string().uuid(), + authorId: z.string().uuid(), + title: z.string(), + summary: z.string(), + evidence: z.array(evidenceSchema).default([]), + options: z.array(optionSchema).default([]), + positions: z.array(positionSchema).default([]), + minorityReport: z.string().optional(), + status: z.enum(['draft', 'research', 'deliberation', 'voting', 'decided', 'delivery', 'reviewed', 'archived']), + createdAt: z.coerce.date(), + updatedAt: z.coerce.date(), + decidedAt: z.coerce.date().optional(), +}) +``` + +--- + +## Repository Pattern + +### Interface +```typescript +// packages/governance-domain/repos/ProposalRepo.ts +export interface ProposalRepo { + create(input: CreateProposalInput): Promise + findById(id: string): Promise + list(filters: ProposalFilters): Promise + update(id: string, updates: Partial): Promise + delete(id: string): Promise +} + +export interface ProposalFilters { + groupId?: string + status?: ProposalStatus + authorId?: string + limit?: number + offset?: number +} +``` + +### In-Memory Implementation (MVP) +```typescript +// packages/governance-domain/repos/InMemoryProposalRepo.ts +export class InMemoryProposalRepo implements ProposalRepo { + private proposals: Map = new Map() + + async create(input: CreateProposalInput): Promise { + const proposal: Proposal = { + id: generateId(), + groupId: input.groupId || 'default', + authorId: input.authorId, + title: input.title, + summary: input.summary, + evidence: [], + options: [], + positions: [], + status: 'draft', + createdAt: new Date(), + updatedAt: new Date(), + } + this.proposals.set(proposal.id, proposal) + return proposal + } + + async findById(id: string): Promise { + return this.proposals.get(id) || null + } + + async list(filters: ProposalFilters): Promise { + let results = Array.from(this.proposals.values()) + + if (filters.groupId) { + results = results.filter(p => p.groupId === filters.groupId) + } + if (filters.status) { + results = results.filter(p => p.status === filters.status) + } + if (filters.authorId) { + results = results.filter(p => p.authorId === filters.authorId) + } + + const offset = filters.offset || 0 + const limit = filters.limit || 50 + return results.slice(offset, offset + limit) + } + + // ... update, delete methods +} +``` + +--- + +## Testing Strategy + +### Unit Tests +```typescript +// packages/governance-domain/__tests__/Proposal.test.ts +import { describe, it, expect } from 'vitest' +import { Proposal } from '../entities/Proposal' + +describe('Proposal entity', () => { + it('validates title length', () => { + expect(() => new Proposal({ title: 'AB' })).toThrow() + }) + + it('initializes with draft status', () => { + const proposal = new Proposal({ title: 'Valid title', summary: 'Valid summary' }) + expect(proposal.status).toBe('draft') + }) +}) +``` + +### Contract Tests +```typescript +// apps/api/src/modules/governance/__tests__/createProposal.test.ts +import { describe, it, expect } from 'vitest' +import { createProposalSchema } from '@togetheros/validators' + +describe('POST /api/proposals', () => { + it('rejects empty title', () => { + const result = createProposalSchema.safeParse({ title: '', summary: 'Valid', authorId: 'abc' }) + expect(result.success).toBe(false) + }) + + it('accepts valid input', () => { + const result = createProposalSchema.safeParse({ + title: 'Community garden', + summary: 'Proposal to convert unused space...', + authorId: '550e8400-e29b-41d4-a716-446655440000' + }) + expect(result.success).toBe(true) + }) +}) +``` + +### Storybook Stories +```typescript +// packages/ui/src/governance/ProposalCard.stories.tsx +import type { Meta, StoryObj } from '@storybook/react' +import { ProposalCard } from './ProposalCard' + +export default { + component: ProposalCard, +} satisfies Meta + +export const Draft: StoryObj = { + args: { + proposal: { + id: 'prop-1', + title: 'Community garden', + summary: 'Convert unused space...', + status: 'draft', + authorId: 'alice', + createdAt: new Date(), + } + } +} + +export const Deliberation: StoryObj = { + args: { + proposal: { ...Draft.args.proposal, status: 'deliberation' } + } +} +``` + +--- + +## Definition of Done (DoD) + +When MVP slices are complete: + +✅ Tests or manual steps verified (list loads, details render, create works) +✅ Docs updated (this page + `docs/modules/INDEX.md` link present) +✅ Proofs in PR body: +``` +LINT=OK +VALIDATORS=GREEN +SMOKE=OK +``` +✅ Storybook stories for all UI components (empty, loading, error, success states) +✅ Contract tests for API endpoints pass +✅ Fixtures seed successfully with `pnpm -w seed:governance` + +--- + +## Related KB Files + +- [Main KB](./togetheros-kb.md) — Core principles, workflow +- [Architecture](./architecture.md) — Domain-driven design patterns +- [Data Models](./data-models.md) — Complete entity specifications +- [CI/CD Discipline](./ci-cd-discipline.md) — Proof lines, validation diff --git a/.claude/knowledge/social-economy.md b/.claude/knowledge/social-economy.md new file mode 100644 index 00000000..f81f3029 --- /dev/null +++ b/.claude/knowledge/social-economy.md @@ -0,0 +1,588 @@ +# Social Economy — Cooperative Economic Primitives + +## Overview + +TogetherOS enables a **fair social economy** that redirects surplus back to communities through: +- **Support Points** — Non-transferable points to signal priorities +- **Mutual Aid** — Request/offer boards with escrowed confirmations +- **Time-Banking** — Fair-exchange ledger to prevent exploitation +- **Collective Purchasing** — Group buys with transparent bids +- **Social Horizon Currency** — Equitable distribution, anti-whale controls + +--- + +## Support Points + +### Mechanics + +**Allocation:** +- Every member starts with **100 Support Points (SP)** +- **Max 10 SP per idea/proposal** +- Non-transferable (cannot gift or sell) +- Participation unlocks more points + +**Purpose:** +- Signal community priorities +- Unlock capabilities (e.g., create proposals, start initiatives) +- Drive gamification (badges, skill trees) + +**Anti-Abuse:** +- Max 10/idea prevents whale behavior +- Allocation history is public +- Reclaim points when proposals close + +###Example Flow +``` +Alice (100 SP) → + Allocates 10 SP to "Community Garden" + Allocates 5 SP to "Farmers Market" + Allocates 8 SP to "Repair Cafe" + → Remaining: 77 SP + +Community Garden reaches 150 SP threshold → prioritized +Alice's 10 SP locked until delivery or cancellation +``` + +### Data Model +```typescript +interface SupportPointsWallet { + memberId: string + total: number // Current balance + allocated: number // Locked in active proposals + earned: number // From contributions + history: SPTransaction[] +} + +interface SPTransaction { + id: string + memberId: string + type: 'allocate' | 'reclaim' | 'earn' | 'initial' + amount: number + targetId?: string // Proposal/initiative ID + timestamp: Date + reason?: string +} +``` + +### API Endpoints (Planned) +```typescript +// GET /api/members/:id/support-points +// POST /api/support-points/allocate +// POST /api/support-points/reclaim +``` + +--- + +## Mutual Aid + +### Mechanics + +**Request/Offer Flow:** +1. Member posts **request** (e.g., "Need help moving on Saturday") +2. Other members post **offers** (e.g., "I can help 2-4pm") +3. Requester **accepts** an offer +4. System **escrows** confirmation (both parties confirm completion) +5. **Reputation** updated for both parties + +**Categories:** +- Material aid (food, supplies, equipment) +- Time/labor (moving, childcare, repairs) +- Skills/knowledge (tutoring, consulting) +- Space (temporary housing, workspace) + +**Safeguards:** +- Escrow prevents one-sided claims +- Reputation visible on profiles +- Abuse reports to moderators +- Fair-exchange index (track imbalances) + +### Data Model +```typescript +interface MutualAidRequest { + id: string + groupId: string + requesterId: string + category: 'material' | 'time' | 'skill' | 'space' + title: string + description: string + urgency: 'low' | 'medium' | 'high' + location?: string + needed_by?: Date + status: 'open' | 'matched' | 'completed' | 'cancelled' + createdAt: Date +} + +interface MutualAidOffer { + id: string + requestId: string + offererId: string + message: string + availability: string // e.g., "Saturday 2-4pm" + status: 'pending' | 'accepted' | 'declined' | 'withdrawn' + createdAt: Date +} + +interface MutualAidTransaction { + id: string + requestId: string + offererId: string + requesterId: string + confirmedBy: string[] // Both IDs when complete + completedAt?: Date + rating?: number // 1-5 stars + feedback?: string +} +``` + +--- + +## Time-Banking + +### Mechanics + +**How It Works:** +- 1 hour of service = 1 time credit +- All hours valued equally (plumber = tutor = gardener) +- Credits stored in member's timebank ledger +- **Fair-exchange index** tracks imbalances to prevent exploitation + +**Example:** +``` +Bob provides 3 hours of car repair to Alice → Earns 3 credits +Bob uses 2 credits for tutoring from Carol +Bob's balance: 1 credit +``` + +**Anti-Exploitation:** +- Fair-exchange index: warns if member consistently takes without giving +- Group norms: e.g., "aim for ±10 credits balance over 6 months" +- Transparency: full ledger visible (privacy-aware) + +### Data Model +```typescript +interface TimeBankAccount { + memberId: string + balance: number // Current time credits + earned: number // Total earned + spent: number // Total spent + transactions: TimeBankTransaction[] +} + +interface TimeBankTransaction { + id: string + fromId: string // Service provider + toId: string // Service receiver + hours: number + service: string // Description + confirmedBy: string[] // Both parties + timestamp: Date +} + +interface FairExchangeIndex { + memberId: string + balance: number // Current credits + earnedLast6Mo: number + spentLast6Mo: number + ratio: number // spent / earned + alert: boolean // True if ratio > 2.0 (taking 2x giving) +} +``` + +### API Endpoints (Planned) +```typescript +// GET /api/timebank/:memberId +// POST /api/timebank/transactions +// GET /api/timebank/fair-exchange-index/:memberId +``` + +--- + +## Collective Purchasing + +### Mechanics + +**Group Buying Power:** +1. Member proposes bulk purchase (e.g., "100 lbs organic flour") +2. Others commit (e.g., "I'll take 10 lbs") +3. Once threshold met, purchase is made +4. Distribution coordinated +5. Savings shared + +**Benefits:** +- Lower prices through bulk discounts +- Support local/ethical producers +- Reduce packaging waste +- Build community connections + +**Features:** +- **Transparent bidding:** Suppliers compete openly +- **Solidarity pricing:** Those who can pay more subsidize those who can't +- **Recurring essentials:** Monthly staples (rice, beans, etc.) + +### Data Model +```typescript +interface CollectivePurchase { + id: string + groupId: string + coordinatorId: string + item: string + supplier?: string + quantity: number // Total needed + unit: string // lbs, units, etc. + pricePerUnit: number + threshold: number // Min participants + deadline: Date + status: 'open' | 'threshold_met' | 'ordered' | 'delivered' | 'cancelled' + participants: PurchaseParticipant[] + createdAt: Date +} + +interface PurchaseParticipant { + memberId: string + quantity: number + price: number // May vary (solidarity pricing) + paid: boolean + picked_up: boolean +} +``` + +--- + +## Social Horizon Currency (SH) + +### High-Level Goals + +- **Equitable distribution** — Issued based on verified contributions +- **Anti-whale** — Prevent large holders from dominating +- **Pro-contribution** — Reward steady, long-term support +- **Long-term resilience** — Treasury rebalancing toward underserved groups + +### Mechanics (Conceptual) + +**Issuance:** +- Tied to **verified contributions** (code, organizing, mutual aid) +- Not tradable on speculation markets (by design) +- Staking favors long-term steady support (vs. pump-and-dump) + +**Velocity Dampers:** +- Circuit-breakers on abnormal flows +- Stake decay for short-term speculation +- Treasury rebalancing algorithms + +**On/Off-Ramps:** +- Transparent with compliance modules +- Communities adopt per jurisdiction +- KYC/AML where legally required (otherwise off by default) + +**Cooperative Treasury:** +- Pooled funds invest in member-led projects +- Returns flow to public goods, safety nets, long-term security +- Transparent allocation via governance proposals + +### Data Model (Placeholder) +```typescript +interface SocialHorizonWallet { + memberId: string + balance: number + staked: number + earned: number + spent: number + transactions: SHTransaction[] +} + +interface SHTransaction { + id: string + fromId: string + toId: string + amount: number + type: 'contribution_reward' | 'purchase' | 'grant' | 'treasury_distribution' + metadata: Record + timestamp: Date +} + +interface CooperativeTreasury { + groupId: string + totalSH: number + reserves: number + allocated: number + investments: Investment[] + distributionHistory: Distribution[] +} +``` + +### Status +**Current:** Conceptual design only +**Phase 1:** Testnet with mock wallet +**Phase 2:** Real integration with compliance modules + +--- + +## Investment Pools & Relief Funds + +### Mechanics + +**Community Investment Pools:** +- Members contribute to shared fund +- Projects apply for funding +- Governance votes on allocation +- Returns flow back to pool or public goods + +**Emergency Relief Funds:** +- Pre-funded safety net +- Fast approval for urgent needs (e.g., medical, housing) +- Transparent beneficiary disclosure +- Risk limits (max % of pool per person) + +### Data Model +```typescript +interface InvestmentPool { + id: string + groupId: string + name: string + totalFunds: number + allocated: number + available: number + contributors: PoolContributor[] + investments: Investment[] + returnPolicy: 'reinvest' | 'distribute' | 'hybrid' +} + +interface PoolContributor { + memberId: string + amount: number + share: number // % of pool + joinedAt: Date +} + +interface Investment { + id: string + poolId: string + projectId: string + amount: number + terms: string // Interest rate, timeline + status: 'pending' | 'active' | 'repaid' | 'defaulted' + approvedAt: Date + dueDate?: Date +} + +interface ReliefFund { + id: string + groupId: string + balance: number + maxPerPerson: number // e.g., $500 + requests: ReliefRequest[] +} + +interface ReliefRequest { + id: string + fundId: string + memberId: string + amount: number + reason: string + urgency: 'critical' | 'high' | 'medium' + status: 'pending' | 'approved' | 'disbursed' | 'rejected' + approvedBy?: string[] // Steward IDs + submittedAt: Date +} +``` + +--- + +## Reputation & Badges + +### Reputation System + +**How It's Earned:** +- Completing mutual aid transactions +- Delivering on proposals/initiatives +- Contributing code, docs, organizing +- Consistent positive feedback + +**How It's Displayed:** +- Profile badge count +- Contribution history (public) +- Skill tags (verified by community) + +**NOT Like Traditional "Credit Scores":** +- No single number +- Context-rich (what did they contribute?) +- Focus on positive contributions, not punishments + +### Data Model +```typescript +interface MemberReputation { + memberId: string + badges: Badge[] + contributions: Contribution[] + mutualAidScore: number // 0-100 + governanceScore: number // 0-100 + overallScore: number // Composite +} + +interface Badge { + id: string + name: string // "Gardener", "Code Contributor", "Organizer" + description: string + icon: string + earnedAt: Date + criteria: string // How it's earned +} + +interface Contribution { + id: string + memberId: string + type: 'code' | 'docs' | 'organizing' | 'mutual_aid' | 'proposal' + title: string + description: string + verifiedBy?: string[] // Community verification + timestamp: Date +} +``` + +--- + +## Gamification & Skill Trees + +### Archetype Paths + +Members choose starting path (fluid, can blend): +1. **Builder** — Code, design, infrastructure +2. **Community Heart** — Organizing, care, connection +3. **Guided Contributor** — Learning, following structured tasks +4. **Steady Cultivator** — Long-term, reliable support + +### Skill Trees + +Each path has skill tree with badges: +``` +Builder Path: +├── First PR Merged +├── 10 PRs Merged +├── Maintainer Status +├── Architecture Contributor +└── Code Reviewer + +Community Heart Path: +├── First Mutual Aid +├── 10 Mutual Aids Completed +├── Event Organizer +├── Moderator +└── Steward +``` + +### Immersive Experience + +**Visual Progression:** +- Seed → Seedling → Young Tree → Majestic Tree animations +- 3D globe visualizing live projects and achievements +- **Global-scale RPG aesthetic** — Every node = real people and contactable projects + +### Data Model +```typescript +interface MemberPath { + memberId: string + primaryPath: 'builder' | 'community_heart' | 'guided_contributor' | 'steady_cultivator' + secondaryPaths: string[] + skillTree: SkillNode[] + level: number // Based on contributions + visualState: 'seed' | 'seedling' | 'young_tree' | 'majestic_tree' +} + +interface SkillNode { + id: string + name: string + description: string + path: string + unlocked: boolean + unlockedAt?: Date + requirements: string[] // What's needed to unlock +} +``` + +--- + +## Transparency & Metrics + +### Public Dashboards + +**What Gets Tracked:** +- Support Points allocation trends +- Mutual aid completion rates +- Timebank balance distribution +- Collective purchase savings +- Treasury flows and investments +- Local value retained + +**Privacy Balance:** +- Aggregate data public +- Individual transactions anonymized +- Opt-in for detailed sharing + +### Data Model +```typescript +interface EconomyMetrics { + groupId: string + period: string // e.g., "2025-01" + supportPointsAllocated: number + mutualAidTransactions: number + timeBankHours: number + collectivePurchaseSavings: number + socialHorizonCirculation: number + localValueRetained: number // $ or % + memberParticipation: number // % active +} +``` + +--- + +## API Endpoints (Future) + +### Support Points +```typescript +GET /api/members/:id/support-points +POST /api/support-points/allocate +POST /api/support-points/reclaim +GET /api/proposals/:id/support-points +``` + +### Mutual Aid +```typescript +GET /api/mutual-aid/requests +POST /api/mutual-aid/requests +POST /api/mutual-aid/offers +POST /api/mutual-aid/confirm +GET /api/members/:id/mutual-aid-history +``` + +### Time-Banking +```typescript +GET /api/timebank/:memberId +POST /api/timebank/transactions +GET /api/timebank/fair-exchange-index/:memberId +POST /api/timebank/confirm +``` + +### Collective Purchasing +```typescript +GET /api/collective-purchases +POST /api/collective-purchases +POST /api/collective-purchases/:id/join +POST /api/collective-purchases/:id/confirm-payment +``` + +### Social Horizon +```typescript +GET /api/social-horizon/:memberId/balance +POST /api/social-horizon/transfer +GET /api/treasury/balance +GET /api/treasury/investments +``` + +--- + +## Related KB Files + +- [Main KB](./togetheros-kb.md) — Core principles, workflow +- [Architecture](./architecture.md) — Domain-driven design, data patterns +- [Data Models](./data-models.md) — Complete entity specifications +- [Governance Module](./governance-module.md) — How proposals/decisions work diff --git a/.claude/knowledge/tech-stack.md b/.claude/knowledge/tech-stack.md new file mode 100644 index 00000000..d41651b2 --- /dev/null +++ b/.claude/knowledge/tech-stack.md @@ -0,0 +1,393 @@ +# TogetherOS Tech Stack + +## Frontend Stack + +### Core Framework +- **Next.js 14** — React framework with App Router +- **React 18+** — UI library +- **TypeScript** — Type-safe development (strict mode) + +### Styling & UI +- **Tailwind CSS v4** — Utility-first styling +- **shadcn/ui** — Component library (planned, not yet installed) +- **Design tokens** — Tailwind config with TogetherOS brand colors +- **Dark mode** — Configurable theme support (planned) + +### Component Development +- **Storybook** — Component documentation and testing (planned) +- **Component patterns:** + - Loading skeletons + - Empty states + - Error boundaries + - Accessibility (a11y) required + +--- + +## Backend Stack + +### API Layer +- **tRPC** or **REST APIs** — Typed endpoints (tRPC preferred) +- **Node.js 20+** — Runtime environment +- **Zod** — Schema validation for all inputs/outputs + +### Background Jobs +- **Workers** — Queue pattern for async tasks +- **NDJSON logging** — Append-only audit trails + +### Data Layer (MVP Phase) +- **In-memory repositories** — Fixture-based data (no database yet) +- **Fixture repos** — `packages/{module}-fixtures/` +- **Future:** Database layer (not yet specified) + +--- + +## Monorepo Structure + +### Package Manager +- **pnpm** — Fast, disk-efficient package manager +- **Workspace pattern:** + ``` + pnpm-workspace.yaml + apps/ + ├── web/ # Next.js frontend + └── api/ # Backend services + packages/ + ├── ui/ # Shared components + ├── types/ # TypeScript types + ├── validators/ # Zod schemas + ├── fixtures/ # Test data + └── config/ # Shared configs + ``` + +### Build Tool +- **Turbo** (optional) — Monorepo build orchestration +- **Next.js compiler** — Built-in Rust-based bundler + +--- + +## Development Tools + +### Code Quality +- **ESLint** — JavaScript/TypeScript linting +- **Prettier** — Code formatting +- **TypeScript** — Type checking (`tsc --noEmit`) + +### YAML & Markdown +- **yamllint** — YAML validation (`.yamllint.yaml` config) +- **actionlint** — GitHub Actions workflow validation +- **markdownlint-cli2** — Markdown style checks (`.markdownlint.jsonc` config) +- **lychee** — Link validation (internal & external) + +### Validation Scripts +- **scripts/validate.sh** — Main validator (checks tool presence, runs lint suite) +- **scripts/lint.sh** — Multi-tool linting +- **Expected output:** + ``` + LINT=OK + VALIDATORS=GREEN + SMOKE=OK + ``` + +--- + +## Testing Stack + +### Test Framework +- **Vitest** — Fast unit test runner +- **Contract tests** — Zod schema validation in tests +- **Fixture-based testing** — Deterministic test data + +### Test Patterns +- **Unit tests** — For entities, repos, handlers +- **Contract tests** — API endpoint schemas +- **Storybook stories** — Visual component testing +- **Integration tests** — End-to-end flows (planned) + +--- + +## Infrastructure & DevOps + +### Containerization +- **Docker** — Development and production containers +- **Docker Compose** — Multi-container orchestration +- **Dev Container** — VS Code + Node.js 20 + Git + GitHub CLI + +### CI/CD +- **GitHub Actions** — 16 workflows total +- **Required checks:** + - `ci/lint` — YAML validation (yamllint, actionlint) + - `ci/docs` — Markdown + link validation + - `ci/smoke` — Validator scripts (optional but recommended) + +### Deployment +- **VPS deployment** — Rsync to remote server +- **GitHub Actions secrets:** + - `SSH_PRIVATE_KEY` + - `VPS_HOST` + - `VPS_USER` + - `VPS_PATH` +- **Deployment trigger:** Push to main or manual workflow dispatch + +--- + +## Logging & Observability + +### Log Format +- **NDJSON** (Newline-Delimited JSON) +- **Required fields:** + ```json + { + "id": "uuid", + "timestamp": "ISO8601", + "event_type": "qa|tidy|moderation|transaction", + "metadata": {} + } + ``` +- **Privacy:** IP hashing, PII redaction, no raw prompts + +### Log Validation +- **Integrity checks:** SHA-256 chain validation +- **CI validation:** `scripts/validate.sh` checks: + - File exists + - Last non-empty line parses as JSON + - Required fields present + +### Observability (Planned) +- **Error boundaries** — React error catching +- **Uptime monitoring** — Simple health checks +- **Public dashboards** — Activity metrics, delivery reports +- **Third-party options:** Self-hosted or external service (TBD) + +--- + +## Security & Privacy Tools + +### Security +- **Least-privilege tokens** — Minimal GitHub Actions permissions +- **Secrets management** — GitHub Actions secrets only +- **No secrets in logs** — Never echo secret values +- **Dependency scans** — Regular updates via Dependabot (planned) + +### Privacy +- **PII redaction** — Emails, phones, handles removed from logs +- **IP hashing** — Anonymous usage tracking +- **No raw prompts stored** — Bridge AI logs only metadata +- **Data minimization** — Store least required information + +--- + +## Database (Future) + +### Planned Approach +- **MVP phase:** In-memory/fixture repos only +- **Phase 2:** Database layer (not yet specified) +- **Options being considered:** + - PostgreSQL with Prisma + - SQLite for local/small groups + - Distributed options for federation + +### Data Access Patterns +- **Repository pattern** — `packages/{module}-domain/repos/` +- **Entity models** — Domain-driven design +- **Fixtures first** — All features start with fixture data + +--- + +## AI/LLM Integration (Bridge) + +### Bridge AI Assistant +- **LLM provider:** Hosted API (specific provider not specified) +- **No tools yet** — Simple Q&A and summarization +- **Citation required** — 100% of answers must include sources +- **Rate limiting:** 30 requests/hour/IP (landing pilot) +- **Streaming responses** — Progressive UI updates + +### Future AI Capabilities +- **Local LLM** — Ollama integration (optional, behind flag) +- **Moderation assist** — Tone cues, de-escalation suggestions +- **Thread tidying** — Structured summaries (problem → options → trade-offs) + +--- + +## Federation (Future) + +### Inter-Group Protocols +- **Group handles** — Unique identifiers +- **Proposal sync** — Cross-group initiatives +- **Result mirroring** — Shared decision outcomes +- **Local autonomy** — Per-group data silos with opt-in federation + +### Technical Requirements +- **APIs:** Typed endpoints for federation +- **Webhooks:** External tool integrations +- **Data portability:** Exportable decision histories + +--- + +## Environment Configuration + +### Environment Variables (Planned) +```bash +# API +API_URL=http://localhost:3000 +TRPC_URL=/api/trpc + +# Bridge +BRIDGE_ENABLED=true +BRIDGE_TIDY_ENABLED=false +BRIDGE_FIXTURES=/path/to/docs.jsonl +BRIDGE_LOG_DIR=/path/to/logs/bridge/ +BRIDGE_LOG_KEY= + +# LLM Provider (TBD) +LLM_API_KEY= +LLM_ENDPOINT= + +# Deployment +VPS_HOST= +VPS_USER= +VPS_PATH=/var/www/togetheros +``` + +### Configuration Files +- **pnpm-workspace.yaml** — Monorepo package definition +- **tsconfig.base.json** — Shared TypeScript config +- **tailwind.config.ts** — Design tokens +- **.yamllint.yaml** — YAML linting rules +- **.markdownlint.jsonc** — Markdown linting rules +- **next.config.js** — Next.js configuration + +--- + +## Development Environment + +### Dev Container Specs +- **Base image:** TypeScript-Node:20 +- **Includes:** + - Git + - GitHub CLI (`gh`) + - pnpm + - Docker Compose +- **Extensions:** VS Code recommended extensions (TBD) + +### Local Setup +```bash +# Install dependencies +pnpm install + +# Run dev server +pnpm dev + +# Run validation +./scripts/validate.sh + +# Run linters +./scripts/lint.sh +``` + +--- + +## Path Aliases (TypeScript) + +### Planned Aliases +```json +{ + "@togetheros/ui": ["packages/ui/src"], + "@togetheros/types": ["packages/types/src"], + "@togetheros/validators": ["packages/validators/src"], + "@togetheros/fixtures": ["packages/fixtures/src"] +} +``` + +--- + +## Dependency Management + +### Package Versions +- **Node.js:** 20+ (LTS) +- **pnpm:** Latest stable +- **Next.js:** 14.x +- **React:** 18.x +- **TypeScript:** 5.x +- **Tailwind CSS:** v4 (latest alpha/beta) + +### Update Strategy +- **Regular updates** — Dependabot or manual checks +- **Lock files committed** — `pnpm-lock.yaml` tracked +- **Breaking changes** — Document in changelog + +--- + +## Browser Support + +### Target Browsers (Planned) +- **Modern browsers:** Chrome, Firefox, Safari, Edge (latest 2 versions) +- **Mobile:** iOS Safari, Chrome Mobile +- **Accessibility:** WCAG 2.1 Level AA compliance + +--- + +## Performance Targets (Planned) + +### Core Web Vitals +- **LCP (Largest Contentful Paint):** < 2.5s +- **FID (First Input Delay):** < 100ms +- **CLS (Cumulative Layout Shift):** < 0.1 + +### Bridge AI Assistant +- **Time-to-first-useful-answer (p95):** < 800ms (fixture mode) +- **Streaming latency:** < 200ms to first token + +--- + +## Useful Commands Reference + +### Package Management +```bash +# Install all workspace dependencies +pnpm install + +# Add dependency to specific package +pnpm --filter @togetheros/ui add react + +# Run command in all packages +pnpm -r run build +``` + +### Validation +```bash +# Full validation suite +./scripts/validate.sh + +# YAML only +yamllint . + +# Actions only +actionlint + +# Markdown only +markdownlint-cli2 "**/*.md" + +# Links only +lychee --exclude-mail "**/*.md" +``` + +### Git Operations +```bash +# Create feature branch +git checkout -b feature/bridge-qa-endpoint + +# Push with upstream +git push -u origin feature/bridge-qa-endpoint + +# Fetch specific branch +git fetch origin main +``` + +--- + +## Related KB Files + +- [Main KB](./togetheros-kb.md) — Core identity and workflow +- [Architecture](./architecture.md) — Monorepo structure, patterns +- [CI/CD Discipline](./ci-cd-discipline.md) — Proof lines, validation workflows diff --git a/.claude/knowledge/togetheros-kb.md b/.claude/knowledge/togetheros-kb.md new file mode 100644 index 00000000..aa726d5c --- /dev/null +++ b/.claude/knowledge/togetheros-kb.md @@ -0,0 +1,278 @@ +# TogetherOS Project Knowledge Base + +## Core Identity + +**TogetherOS** is a **cooperation-first operating system stack** (OS = Operating System, not "open source") designed to help communities self-organize through: +- Transparent, consent-based governance +- Tiny, verifiable steps with public proofs +- Fair social economy (mutual aid, timebanking, cooperative treasury) +- Shared knowledge and power without fragmentation + +### The Problem We Solve +Power concentrated in a few hands routes wealth and political power upward and pain downward. This results in struggle, poverty, exploitation, ecological breakdown, anxiety, isolation, and social disconnection. + +### The Solution +TogetherOS helps people **unlearn division and learn coordination**. It resets default assumptions (individualism, zero-sum thinking) and cultivates cooperative habits through: +- **Shared decisions, shared power:** Transparent participatory governance with rotating/recallable roles +- **Cooperative economy:** Redirect surplus back to communities (Support Points, timebanking, Social Horizon currency) +- **Tiny, verifiable steps:** Every initiative = shippable increments with public proofs + +--- + +## Key Constraints & Principles + +### Non-Negotiable Discipline + +1. **Tiny, verifiable steps:** Every change = smallest shippable increment +2. **Docs-first:** Spec before code, always +3. **Proof lines required:** Every PR must include in description: + ``` + LINT=OK + VALIDATORS=GREEN (or SMOKE=OK) + ``` +4. **One change per PR:** No bundling unrelated work +5. **Path labels mandatory:** All issues/PRs tagged with 1 of 8 Cooperation Paths + +### Privacy & Transparency + +- **Privacy-first:** No raw prompts stored, IP hashing, PII redaction +- **Append-only logs:** NDJSON audit trails (Bridge, moderation, transactions) +- **Least-privilege by default:** Minimal tokens, role-based access +- **Exportable data:** Portable identities, decision histories, audit logs + +### Governance Principles + +- **Leaderless & accountable:** Rotating, recallable roles; traceable actions +- **Minority-interest protection:** Minority reports codified and preserved +- **Consent-based:** Not majority-rule; amendments must address objections +- **Empathy-first moderation:** De-escalation rules, AI-assisted discourse management + +--- + +## Current Phase: Pre-MVP + +- **All 17 modules at 0% code implementation** +- **Comprehensive documentation complete:** 1,114+ lines of specs +- **Next priority:** Bridge landing pilot (internal MVP) at `/bridge` +- **Repository type:** Monorepo (Next.js 14 + TypeScript + Tailwind) + +--- + +## 8 Cooperation Paths (Taxonomy) + +Every issue, PR, and initiative must be labeled with one of these paths: + +1. **Collaborative Education** — Learning, co-teaching, peer mentorship, skill documentation +2. **Social Economy** — Cooperatives, timebanking, mutual aid, repair/reuse networks +3. **Common Wellbeing** — Health, nutrition, mental health, community clinics, care networks +4. **Cooperative Technology** — Open-source software, privacy tools, federated services, human-centered AI +5. **Collective Governance** — Direct legislation, deliberation, empathic moderation, consensus tools +6. **Community Connection** — Local hubs, events, volunteer matching, skill exchanges +7. **Collaborative Media & Culture** — Storytelling, documentaries, cultural restoration, commons media +8. **Common Planet** — Regeneration, local agriculture, circular materials, climate resilience + +--- + +## Development Workflow + +### Standard Flow + +1. **Check spec:** Read `docs/modules/{module}.md` for requirements +2. **Create branch:** `claude/{module}-{sessionId}` or `feature/{short-topic}` +3. **Implement smallest slice:** One tiny change only +4. **Run validation:** `scripts/validate.sh` (expect: `LINT=OK`, `VALIDATORS=GREEN`, `SMOKE=OK`) +5. **Open PR** with: + - Clear description (what/why) + - Proof lines in body + - Path label (e.g., `path:cooperative-technology`) + - Files touched list +6. **Update docs:** Keep `docs/STATUS_v2.md` progress markers current +7. **After merge:** Post note in Discussions #88 if it affects contributors + +### Branch Naming Conventions + +- **Feature branches:** `feature/` +- **Docs branches:** `docs/` +- **Claude sessions:** `claude/{module}-{sessionId}` (must start with `claude/` and end with session ID) + +### Git Push Retry Logic + +- **For push:** Always use `git push -u origin ` +- **CRITICAL:** Branch must start with `claude/` and end with matching session ID, otherwise push fails with 403 +- **Retry on network errors:** Up to 4 retries with exponential backoff (2s, 4s, 8s, 16s) +- **For fetch/pull:** Prefer `git fetch origin ` with same retry logic + +--- + +## Key File Locations + +### Documentation +- **Vision:** `docs/Manifesto.md` +- **Architecture:** `docs/TogetherOS_WhitePaper.md` +- **Operations playbook:** `docs/OPERATIONS.md` +- **CI playbook:** `docs/CI/Actions_Playbook.md` +- **Module specs:** `docs/modules/{module}.md` +- **Modules hub:** `docs/modules/INDEX.md` +- **Status tracking:** `docs/STATUS_v2.md` + +### Taxonomy & Knowledge +- **Cooperation Paths:** `codex/taxonomy/CATEGORY_TREE.json` +- **Codex notes:** `codex/notes/` + +### Scripts & Validation +- **Main validator:** `scripts/validate.sh` +- **Linting:** `scripts/lint.sh` + +### CI/CD +- **Workflows:** `.github/workflows/` (16 workflows) +- **Lint:** `.github/workflows/lint.yml` +- **Docs:** `.github/workflows/ci_docs.yml` +- **Deploy:** `.github/workflows/deploy.yml` + +--- + +## Architecture Patterns + +### Domain-Driven Structure +Each module follows this pattern: +``` +apps/api/src/modules/{module}/ + ├── entities/ # Domain models + ├── repos/ # Data access layer + ├── handlers/ # API handlers + └── fixtures/ # Test data + +apps/web/app/{module}/ + ├── page.tsx # Route component + └── layout.tsx # Layout wrapper + +packages/types/src/{module}.ts # Shared TypeScript types +packages/ui/src/{module}/ # Shared UI components +``` + +### Append-Only Logs (NDJSON) +- **Format:** Newline-delimited JSON +- **Required fields:** `id`, `timestamp`, `event_type`, `metadata` +- **Validation:** SHA-256 chain, integrity checks in CI +- **Privacy:** IP hashing, PII redaction, no raw prompts +- **Examples:** Bridge Q&A logs, moderation events, transactions + +### Federation-Ready +- **Group handles:** Inter-group protocols +- **Local autonomy:** Per-group data silos with opt-in federation +- **Proposal sync:** Cross-group initiatives with result mirroring + +--- + +## Success Metrics & North Star + +### For Bridge (AI Assistant) +- Time-to-first-useful-answer (p95) < 800ms (fixture mode) +- Citation coverage = 100% for all answers +- Trust index: ≥70% "helpful" ratings after 30 days + +### For Governance +- Proposals have documented trade-offs and minority reports +- Decision cycle time measured +- Delivery reports linked to proposals + +### For Social Economy +- Support Points allocated fairly (max 10/idea per member) +- Timebank transactions balanced +- Local value retained (tracked via cooperative treasury) + +--- + +## Common Commands + +### Local Development +```bash +# Validate repo health +./scripts/validate.sh + +# Run linters +./scripts/lint.sh + +# Expected output: +# LINT=OK +# VALIDATORS=GREEN +# SMOKE=OK +``` + +### Git Operations +```bash +# Create feature branch +git checkout -b feature/bridge-qa-endpoint + +# Create Claude session branch (required format) +git checkout -b claude/bridge-landing-011CUQtanTsWEweh3xMQupeE + +# Push with retry (always use -u) +git push -u origin + +# Fetch specific branch +git fetch origin +``` + +--- + +## Priority Modules (Implementation Order) + +### Phase 1: Bridge Landing Pilot (Now) +- Minimal `/bridge` page +- Streaming Q&A with LLM +- NDJSON logs with validation +- Rate limiting (30 req/hour/IP) +- Citations required for all answers + +### Phase 2: Governance MVP (Next) +- Proposal create/list/view +- Zod validation +- Fixture repos (in-memory) +- Routes: `/governance`, `/governance/[id]` + +### Phase 3: Monorepo Foundation (Critical) +- Next.js 14 app shell +- tRPC server boilerplate +- Tailwind CSS v4 + shadcn/ui +- Package structure (`@togetheros/ui`, `@togetheros/types`) + +--- + +## When to Ask Questions + +### Clarify with the user when: +- Multiple valid architectural approaches exist +- Library/framework choice is ambiguous +- Design decisions affect multiple modules +- Requirements conflict or are unclear +- Security/privacy trade-offs need discussion + +### Do NOT ask when: +- The spec in `docs/modules/{module}.md` is clear +- Standard patterns are documented in this KB +- CI/CD workflows are defined in `docs/CI/Actions_Playbook.md` + +--- + +## Important Reminders + +1. **Never create files unless necessary** — Always prefer editing existing files +2. **Never create markdown docs proactively** — Only create documentation if explicitly requested +3. **Always run validation before PR** — `./scripts/validate.sh` must pass +4. **Update STATUS_v2.md after changes** — Bump progress markers using HTML comments +5. **Bridge pilot is core-team only** — Not open for public contributions yet +6. **All PRs need Path labels** — Use canonical names from CATEGORY_TREE.json + +--- + +## Related KB Files + +- [Tech Stack Details](./tech-stack.md) — Framework versions, dependencies, tooling +- [Architecture Patterns](./architecture.md) — Data models, API contracts, monorepo structure +- [Bridge Module Spec](./bridge-module.md) — Complete AI assistant specification +- [Governance Module Spec](./governance-module.md) — Proposals & decisions implementation +- [Social Economy](./social-economy.md) — Support Points, timebanking, Social Horizon currency +- [Cooperation Paths](./cooperation-paths.md) — Full taxonomy with subcategories +- [CI/CD Discipline](./ci-cd-discipline.md) — Proof lines, validation workflows, contributor rules +- [Data Models](./data-models.md) — Core entities and relationships diff --git a/.markdownlint.jsonc b/.markdownlint.jsonc index 5c926fd9..10da4b68 100644 Binary files a/.markdownlint.jsonc and b/.markdownlint.jsonc differ diff --git a/.markdownlintignore b/.markdownlintignore new file mode 100644 index 00000000..f9110dfa --- /dev/null +++ b/.markdownlintignore @@ -0,0 +1,2 @@ +# Ignore Knowledge Base files - lenient formatting for AI context +.claude/knowledge/