Unified Google Workspace management via WorkspaceACSet. Transforms operations into GF(3)-typed Interactions across Gmail, Drive, Calendar, Tasks, Docs with cross-skill morphisms and MCP↔API equivalence. Use for multi-service workflows or applying ACSet principles to workspace automation.
Transform Google Workspace into an ACSet-structured system with GF(3) conservation and cross-skill morphisms.
Trit: 0 (ERGODIC - coordinator)
Principle: Workflow Completion = Condensed Equilibrium State
Implementation: WorkspaceACSet + PathInvariance + MCPAPIBridge
Workspace Unified applies categorical database principles to workspace:
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│ WorkspaceACSet Schema │
├─────────────────────────────────────────────────────────────────────────────────────────┤
│ │
│ Interaction ───────────┬──────▶ Thread ◀───────────────── DriveFile │
│ ├─ verb: String │ ├─ thread_id: String ├─ file_id: String │
│ ├─ timebin: Int │ ├─ needs_action: Bool ├─ mime_type: String │
│ ├─ trit: Trit │ ├─ last_action_bin: Int └─ saturated: Bool │
│ ├─ service: Service │ └─ saturated: Bool │
│ └─ person ─────────────┼──▶ │
│ │ │
│ CalendarEvent ◀────────┼──────── TaskList ◀────────────── Task │
│ ├─ event_id: String │ ├─ list_id: String ├─ task_id: String │
│ ├─ summary: String │ └─ title: String ├─ title: String │
│ ├─ start: DateTime │ ├─ status: String │
│ └─ saturated: Bool │ └─ due: DateTime │
│ │ │
│ Document ◀─────────────┼──────── Sheet │
│ ├─ doc_id: String │ ├─ sheet_id: String │
│ ├─ title: String │ ├─ title: String │
│ └─ content: Text │ └─ values: Matrix │
│ │ │
│ QueueItem ─────────────┼──────▶ Agent3 │
│ ├─ interaction ────────┘ ├─ fiber: Trit {-1, 0, +1} │
│ └─ agent ───────────────▶ └─ name: String │
│ │
│ Person ◀─────────────────────── Partner ─────────────────▶ Person │
│ ├─ email: String ├─ src │
│ └─ name: String ├─ tgt │
│ └─ weight: Int │
│ │
│ Service │
│ ├─ name: String {gmail, drive, calendar, tasks, docs, sheets} │
│ └─ default_trit: Trit │
└─────────────────────────────────────────────────────────────────────────────────────────┘
| Object | Description | Trit Role |
|--------|-------------|-----------|
| Interaction | Single workspace action with verb + trit + service | Data |
| Thread | Gmail conversation with saturation state | Gmail Aggregate |
| DriveFile | File or folder in Drive | Drive Aggregate |
| CalendarEvent | Meeting or event | Calendar Aggregate |
| TaskList | Container for tasks | Tasks Container |
| Task | Individual action item | Tasks Aggregate |
| Document | Google Doc content | Docs Aggregate |
| Sheet | Spreadsheet data | Sheets Aggregate |
| Agent3 | Queue fiber (MINUS/ERGODIC/PLUS) | Router |
| QueueItem | Links Interaction → Agent3 | Edge |
| Person | User or contact | Node |
| Partner | Relationship edge in contact graph | Edge |
| Service | Workspace service identifier | Metadata |
Workspace actions are assigned trits based on information flow:
VERB_TRIT_MAP = {
# ═══════════════════════════════════════════════════════════════
# GMAIL
# ═══════════════════════════════════════════════════════════════
# MINUS (-1): Consumption/Validation
"gmail_read": -1, "gmail_search": -1, "gmail_get_thread": -1,
"gmail_list_labels": -1,
# ERGODIC (0): Coordination/Metadata
"gmail_label": 0, "gmail_archive": 0, "gmail_snooze": 0,
"gmail_star": 0, "gmail_mark_read": 0, "gmail_move": 0,
# PLUS (+1): Generation/Execution
"gmail_send": +1, "gmail_forward": +1, "gmail_reply": +1,
"gmail_draft": +1, "gmail_compose": +1,
# ═══════════════════════════════════════════════════════════════
# DRIVE
# ═══════════════════════════════════════════════════════════════
# MINUS (-1)
"drive_get_content": -1, "drive_list": -1, "drive_search": -1,
"drive_get_permissions": -1,
# ERGODIC (0)
"drive_share": 0, "drive_move": 0, "drive_rename": 0,
"drive_update_metadata": 0,
# PLUS (+1)
"drive_create": +1, "drive_upload": +1, "drive_copy": +1,
# ═══════════════════════════════════════════════════════════════
# CALENDAR
# ═══════════════════════════════════════════════════════════════
# MINUS (-1)
"calendar_get_events": -1, "calendar_list": -1, "calendar_get_event": -1,
# ERGODIC (0)
"calendar_modify": 0, "calendar_reschedule": 0, "calendar_update_attendees": 0,
# PLUS (+1)
"calendar_create": +1, "calendar_invite": +1, "calendar_duplicate": +1,
# ═══════════════════════════════════════════════════════════════
# TASKS
# ═══════════════════════════════════════════════════════════════
# MINUS (-1)
"tasks_list": -1, "tasks_get": -1, "tasks_list_lists": -1,
# ERGODIC (0)
"tasks_update": 0, "tasks_move": 0, "tasks_complete": 0,
# PLUS (+1)
"tasks_create": +1, "tasks_create_list": +1,
# ═══════════════════════════════════════════════════════════════
# DOCS
# ═══════════════════════════════════════════════════════════════
# MINUS (-1)
"docs_get_content": -1, "docs_read_comments": -1, "docs_inspect": -1,
# ERGODIC (0)
"docs_find_replace": 0, "docs_update_headers": 0, "docs_format": 0,
# PLUS (+1)
"docs_create": +1, "docs_insert_text": +1, "docs_create_table": +1,
# ═══════════════════════════════════════════════════════════════
# SHEETS
# ═══════════════════════════════════════════════════════════════
# MINUS (-1)
"sheets_read": -1, "sheets_get_info": -1,
# ERGODIC (0)
"sheets_clear": 0,
# PLUS (+1)
"sheets_write": +1, "sheets_create": +1, "sheets_create_sheet": +1,
}
| Tool | Trit | Service | Description |
|------|------|---------|-------------|
| search_gmail_messages | -1 | Gmail | Search inbox (MINUS) |
| get_gmail_message_content | -1 | Gmail | Read message (MINUS) |
| get_gmail_thread_content | -1 | Gmail | Read thread (MINUS) |
| list_gmail_labels | -1 | Gmail | List labels (MINUS) |
| modify_gmail_message_labels | 0 | Gmail | Change labels (ERGODIC) |
| batch_modify_gmail_message_labels | 0 | Gmail | Bulk labels (ERGODIC) |
| send_gmail_message | +1 | Gmail | Send email (PLUS) |
| draft_gmail_message | +1 | Gmail | Create draft (PLUS) |
| list_drive_items | -1 | Drive | List files (MINUS) |
| get_drive_file_content | -1 | Drive | Read file (MINUS) |
| search_drive_files | -1 | Drive | Search files (MINUS) |
| share_drive_file | 0 | Drive | Share file (ERGODIC) |
| update_drive_file | 0 | Drive | Update metadata (ERGODIC) |
| create_drive_file | +1 | Drive | Create file (PLUS) |
| get_events | -1 | Calendar | Get events (MINUS) |
| modify_event | 0 | Calendar | Modify event (ERGODIC) |
| create_event | +1 | Calendar | Create event (PLUS) |
| list_tasks | -1 | Tasks | List tasks (MINUS) |
| get_task | -1 | Tasks | Get task (MINUS) |
| update_task | 0 | Tasks | Update task (ERGODIC) |
| create_task | +1 | Tasks | Create task (PLUS) |
| get_doc_content | -1 | Docs | Read doc (MINUS) |
| create_doc | +1 | Docs | Create doc (PLUS) |
| read_sheet_values | -1 | Sheets | Read sheet (MINUS) |
| modify_sheet_values | +1 | Sheets | Write sheet (PLUS) |
┌──────────────────────────────────────────────────────────────────────────────┐
│ CROSS-SKILL MORPHISM DIAGRAM │
├──────────────────────────────────────────────────────────────────────────────┤
│ │
│ thread_file │
│ Thread ─────────────────────────────▶ DriveFile │
│ │ │ │
│ │ thread_event │ file_event │
│ ▼ ▼ │
│ CalendarEvent ◀───── event_file ─────── DriveFile │
│ │ │ │
│ │ event_task │ file_task │
│ ▼ ▼ │
│ Task ◀──────────────────────────────── Task │
│ │ │ │
│ │ task_doc │ file_doc │
│ ▼ ▼ │
│ Document ◀───────────────────────────── Document │
│ │ │
│ │ doc_sheet │
│ ▼ │
│ Sheet │
│ │
│ GF(3) Conservation: All morphism paths preserve trit balance │
└──────────────────────────────────────────────────────────────────────────────┘
| Morphism | Source | Target | Trigger | GF(3) Effect |
|----------|--------|--------|---------|--------------|
| thread_file | Thread | DriveFile | Attachment detected | 0 (ERGODIC) |
| thread_event | Thread | CalendarEvent | Meeting scheduled | +1 (PLUS) |
| thread_task | Thread | Task | Action item identified | +1 (PLUS) |
| file_event | DriveFile | CalendarEvent | File-linked meeting | +1 (PLUS) |
| file_task | DriveFile | Task | File review needed | +1 (PLUS) |
| file_doc | DriveFile | Document | Content extraction | 0 (ERGODIC) |
| event_task | CalendarEvent | Task | Event followup | +1 (PLUS) |
| event_doc | CalendarEvent | Document | Meeting notes | +1 (PLUS) |
| task_doc | Task | Document | Task documentation | +1 (PLUS) |
| doc_sheet | Document | Sheet | Data extraction | 0 (ERGODIC) |
thread_task
Gmail.Thread ─────────────────────────────────▶ Tasks.Task
│ │
│ thread_event │ (identity)
▼ ▼
Calendar.Event ────────────────────────────────▶ Tasks.Task
event_task
INVARIANT: thread_task == event_task ∘ thread_event
thread_file
Gmail.Thread ─────────────────────────────────▶ Drive.File
│ │
│ thread_event │ file_event
▼ ▼
Calendar.Event ◀─────── event_file ─────────── Calendar.Event
INVARIANT: thread_event == event_file⁻¹ ∘ file_event ∘ thread_file
def is_workspace_saturated() -> bool:
"""Workspace is saturated when:
1. All services reach their saturation threshold
2. GF(3) global conservation: sum(trits) ≡ 0 (mod 3)
3. All cross-skill morphism paths commute
4. No pending interactions in any queue
"""
service_states = {
'gmail': gmail_saturated(),
'drive': drive_saturated(),
'calendar': calendar_saturated(),
'tasks': tasks_saturated(),
'docs': docs_saturated(),
'sheets': sheets_saturated(),
}
global_trit_sum = sum(
interaction.trit
for service in services
for interaction in service.interactions
)
return (
all(service_states.values()) and # All saturated
(global_trit_sum % 3) == 0 and # GF(3) conserved
verify_path_commutativity() and # Morphisms commute
all_queues_empty() # No pending work
)
def detect_anima() -> Dict:
"""System at ANIMA when workspace is condensed."""
return {
"at_anima": is_workspace_saturated(),
"condensed_fingerprint": sha256(workspace_state_hash()),
"service_states": get_all_service_states(),
"gf3_balance": compute_global_gf3_balance(),
"pending_interactions": count_pending_interactions(),
}
SATURATION_THRESHOLDS = {
'gmail_threads': 1000,
'drive_files': 500,
'calendar_events': 200,
'tasks': 300,
'docs': 100,
'sheets': 50,
}
def service_saturated(service: str) -> bool:
count = get_service_object_count(service)
threshold = SATURATION_THRESHOLDS.get(service, 100)
return count >= threshold
Proofs in src/narya_proofs/:
def prove_path_commutativity(workspace: WorkspaceACSet) -> bool:
"""Verify all morphism paths commute."""
# thread_task == event_task ∘ thread_event
for thread in workspace.threads:
direct = workspace.thread_task(thread)
composed = workspace.event_task(workspace.thread_event(thread))
if direct != composed:
return False
return True
def prove_gf3_global_conservation(workspace: WorkspaceACSet) -> bool:
"""All cross-service workflows satisfy sum ≡ 0 (mod 3)."""
for workflow in workspace.workflows:
trit_sum = sum(op.trit for op in workflow.operations)
if trit_sum % 3 != 0:
return False
return True
def prove_mcp_api_equivalence(bridge: WorkspaceBridge) -> bool:
"""MCP and API executions produce identical states."""
for operation in bridge.supported_operations:
mcp_state = bridge.execute_mcp(operation, test_params)
api_state = bridge.execute_api(operation, test_params)
if normalize(mcp_state) != normalize(api_state):
return False
return True
def prove_cross_service_integrity(workspace: WorkspaceACSet) -> bool:
"""Thread IDs, file IDs consistent across all services."""
for morphism in workspace.morphisms:
source_id = morphism.source.id
target_id = morphism.target.id
if not workspace.verify_id_consistency(source_id, target_id):
return False
return True
| File | Description | Trit | |------|-------------|------| | workspace_acset.py | ACSet schema + cross-skill morphisms | 0 | | workspace_detector.py | Saturation + equilibrium detection | 0 | | workspace_bridge.py | MCP tool wiring with guards | 0 | | triadic_queues.py | Three disjoint queue fibers | 0 | | path_invariance.py | Morphism commutativity checks | -1 | | mcp_api_equivalence.py | Equivalence verification | -1 | | narya_proofs/ | Formal verification proofs | -1 |
from workspace_bridge import create_workspace_bridge
from workspace_detector import WorkspaceDetector
# Create bridge
bridge = create_workspace_bridge("user@gmail.com")
detector = WorkspaceDetector()
# MINUS: Search for actionable emails
results = bridge.search_gmail_messages("is:unread label:action-required")
for msg in results:
thread = bridge.get_gmail_thread_content(msg.thread_id)
detector.update_service('gmail', trit=Trit.MINUS)
# PLUS: Create task via thread_task morphism
task = bridge.create_task(
title=f"Follow up: {thread.subject}",
notes=thread.snippet,
task_list_id=default_list_id
)
detector.update_service('tasks', trit=Trit.PLUS)
# ERGODIC: Label as processed
bridge.modify_gmail_message_labels(
msg.id,
add_label_ids=["Label_Processed"],
remove_label_ids=["INBOX"]
)
detector.update_service('gmail', trit=Trit.ERGODIC)
# GF(3) check: -1 + 1 + 0 = 0 ✓
# MINUS: Get calendar events
events = bridge.get_events(time_min=today, time_max=tomorrow)
detector.update_service('calendar', trit=Trit.MINUS)
for event in events:
# PLUS: Create meeting notes doc via event_doc morphism
doc = bridge.create_doc(
title=f"Notes: {event.summary}",
content=generate_template(event)
)
detector.update_service('docs', trit=Trit.PLUS)
# ERGODIC: Update event with doc link
bridge.modify_event(
event_id=event.id,
description=f"{event.description}\n\nNotes: {doc.url}"
)
detector.update_service('calendar', trit=Trit.ERGODIC)
# GF(3) check: -1 + 1 + 0 = 0 ✓
# MINUS: Search for files needing review
files = bridge.search_drive_files("modifiedTime > '2024-01-01' and mimeType = 'application/pdf'")
detector.update_service('drive', trit=Trit.MINUS)
for file in files:
# MINUS: Get file content
content = bridge.get_drive_file_content(file.id)
detector.update_service('drive', trit=Trit.MINUS)
# PLUS: Create review task via file_task morphism
task = bridge.create_task(
title=f"Review: {file.name}",
notes=f"File: {file.webViewLink}"
)
detector.update_service('tasks', trit=Trit.PLUS)
# PLUS: Share file with reviewer
bridge.share_drive_file(file.id, share_with="reviewer@example.com")
detector.update_service('drive', trit=Trit.ERGODIC)
# Auto-balance if needed
if detector.gf3_residue() != 0:
bridge.list_tasks(task_list_id=default_list_id) # MINUS to balance
# Create digest from all services
digest = WorkspaceDigest()
# MINUS: Gather data
digest.gmail_threads = bridge.search_gmail_messages("newer_than:7d")
digest.drive_files = bridge.search_drive_files("modifiedTime > '2024-01-01'")
digest.events = bridge.get_events(time_min=week_ago, time_max=now)
digest.tasks = bridge.list_tasks(task_list_id=default_list_id)
# PLUS: Create digest doc
doc = bridge.create_doc(
title=f"Weekly Digest: {week_start} - {week_end}",
content=render_digest(digest)
)
# ERGODIC: Update shared folder
bridge.update_drive_file(doc.id, add_parents="shared_digests_folder_id")
# Check ANIMA
anima = detector.detect_anima()
if anima["at_anima"]:
say("Workspace at ANIMA. Condensed state achieved.")
print(f"Fingerprint: {anima['condensed_fingerprint'][:16]}...")
# Run workspace ACSet demo
python src/workspace_acset.py
# Test cross-skill morphisms
python src/path_invariance.py
# Run MCP↔API equivalence tests
python src/mcp_api_equivalence.py
# Run Narya proofs
python -m src.narya_proofs.runner
# Check workspace saturation
python src/workspace_detector.py
| Skill | Trit | Integration | |-------|------|-------------| | gmail-anima | 0 | Gmail-specific ACSet with thread saturation | | google-workspace | 0 | MCP tool provider | | gay-mcp | +1 | SplitMixTernary RNG for deterministic colors | | sheaf-cohomology | -1 | H¹ obstruction verification | | bisimulation-game | -1 | State equivalence proofs | | ordered-locale | 0 | Service ordering topology | | acsets-algebraic-databases | 0 | ACSet foundations |
workspace-unified (0) ⊗ gmail-anima (0) ⊗ gay-mcp (+1) ⊗ sheaf-cohomology (-1) = 0 ✓
gmail_read (-1) ⊗ drive_create (+1) ⊗ calendar_modify (0) = 0 ✓
thread_file (0) ⊗ file_event (+1) ⊗ event_task (+1) ⊗ tasks_get (-1) ⊗ docs_get (-1) = 0 ✓
| # | Operation | MCP Tool | REST API Equivalent | |---|-----------|----------|---------------------| | 1 | Gmail Search | search_gmail_messages | GET /gmail/v1/users/me/messages | | 2 | Gmail Read | get_gmail_message_content | GET /gmail/v1/users/me/messages/{id} | | 3 | Gmail Send | send_gmail_message | POST /gmail/v1/users/me/messages/send | | 4 | Gmail Label | modify_gmail_message_labels | POST /gmail/v1/users/me/messages/modify | | 5 | Drive List | list_drive_items | GET /drive/v3/files | | 6
<!-- Content truncated for initial SEO render. Open the source file tab for the full file. -->Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer