Asi workspace-unified
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.
git clone https://github.com/plurigrid/asi
T=$(mktemp -d) && git clone --depth=1 https://github.com/plurigrid/asi "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/workspace-unified" ~/.claude/skills/plurigrid-asi-workspace-unified-fe5cef && rm -rf "$T"
skills/workspace-unified/SKILL.mdWorkspace Unified Skill
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
Overview
Workspace Unified applies categorical database principles to workspace:
- Transform - Operations → GF(3)-typed Interactions
- Route - Interactions → Service-specific ACSet objects
- Compose - Cross-skill morphisms with path commutativity
- Verify - MCP↔API equivalence and Narya proofs
WorkspaceACSet Schema
┌─────────────────────────────────────────────────────────────────────────────────────────┐ │ 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 │ └─────────────────────────────────────────────────────────────────────────────────────────┘
Objects
| Object | Description | Trit Role |
|---|---|---|
| Single workspace action with verb + trit + service | Data |
| Gmail conversation with saturation state | Gmail Aggregate |
| File or folder in Drive | Drive Aggregate |
| Meeting or event | Calendar Aggregate |
| Container for tasks | Tasks Container |
| Individual action item | Tasks Aggregate |
| Google Doc content | Docs Aggregate |
| Spreadsheet data | Sheets Aggregate |
| Queue fiber (MINUS/ERGODIC/PLUS) | Router |
| Links Interaction → Agent3 | Edge |
| User or contact | Node |
| Relationship edge in contact graph | Edge |
| Workspace service identifier | Metadata |
GF(3) Service Typing
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, }
MCP Tool → Trit Mapping
| Tool | Trit | Service | Description |
|---|---|---|---|
| -1 | Gmail | Search inbox (MINUS) |
| -1 | Gmail | Read message (MINUS) |
| -1 | Gmail | Read thread (MINUS) |
| -1 | Gmail | List labels (MINUS) |
| 0 | Gmail | Change labels (ERGODIC) |
| 0 | Gmail | Bulk labels (ERGODIC) |
| +1 | Gmail | Send email (PLUS) |
| +1 | Gmail | Create draft (PLUS) |
| -1 | Drive | List files (MINUS) |
| -1 | Drive | Read file (MINUS) |
| -1 | Drive | Search files (MINUS) |
| 0 | Drive | Share file (ERGODIC) |
| 0 | Drive | Update metadata (ERGODIC) |
| +1 | Drive | Create file (PLUS) |
| -1 | Calendar | Get events (MINUS) |
| 0 | Calendar | Modify event (ERGODIC) |
| +1 | Calendar | Create event (PLUS) |
| -1 | Tasks | List tasks (MINUS) |
| -1 | Tasks | Get task (MINUS) |
| 0 | Tasks | Update task (ERGODIC) |
| +1 | Tasks | Create task (PLUS) |
| -1 | Docs | Read doc (MINUS) |
| +1 | Docs | Create doc (PLUS) |
| -1 | Sheets | Read sheet (MINUS) |
| +1 | Sheets | Write sheet (PLUS) |
Cross-Skill Morphisms
┌──────────────────────────────────────────────────────────────────────────────┐ │ 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 Table
| Morphism | Source | Target | Trigger | GF(3) Effect |
|---|---|---|---|---|
| Thread | DriveFile | Attachment detected | 0 (ERGODIC) |
| Thread | CalendarEvent | Meeting scheduled | +1 (PLUS) |
| Thread | Task | Action item identified | +1 (PLUS) |
| DriveFile | CalendarEvent | File-linked meeting | +1 (PLUS) |
| DriveFile | Task | File review needed | +1 (PLUS) |
| DriveFile | Document | Content extraction | 0 (ERGODIC) |
| CalendarEvent | Task | Event followup | +1 (PLUS) |
| CalendarEvent | Document | Meeting notes | +1 (PLUS) |
| Task | Document | Task documentation | +1 (PLUS) |
| Document | Sheet | Data extraction | 0 (ERGODIC) |
Path Commutativity
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
Saturation Detection → ANIMA State
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(), }
Per-Service Saturation Thresholds
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
Narya Proof Integration
Proofs in
:src/narya_proofs/
1. Path Commutativity (path_commutativity.py)
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
2. GF(3) Global Conservation (gf3_global.py)
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
3. MCP↔API Equivalence (mcp_api_equiv.py)
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
4. Cross-Service Integrity (cross_service.py)
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
Source Files
| 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 |
Workflows
Workflow 1: Email-to-Task with Full Morphism Chain
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 ✓
Workflow 2: Meeting Notes with Cross-Service Morphisms
# 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 ✓
Workflow 3: File Review with Task Creation
# 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
Workflow 4: Weekly Digest with Condensation Check
# 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]}...")
Commands
# 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
Integration with Other Skills
| 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 |
GF(3) Triadic Conservation
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 ✓
MCP ↔ API Equivalence
| # | 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 | Drive Get | get_drive_file_content | GET /drive/v3/files/{id}?alt=media |
| 7 | Drive Create | create_drive_file | POST /upload/drive/v3/files |
| 8 | Drive Share | share_drive_file | POST /drive/v3/files/{id}/permissions |
| 9 | Calendar Events | get_events | GET /calendar/v3/calendars/{id}/events |
| 10 | Calendar Create | create_event | POST /calendar/v3/calendars/{id}/events |
| 11 | Tasks List | list_tasks | GET /tasks/v1/lists/{id}/tasks |
| 12 | Tasks Create | create_task | POST /tasks/v1/lists/{id}/tasks |
| 13 | Docs Get | get_doc_content | GET /docs/v1/documents/{id} |
| 14 | Docs Create | create_doc | POST /docs/v1/documents |
| 15 | Sheets Read | read_sheet_values | GET /sheets/v4/spreadsheets/{id}/values |
Equivalence Verification
@dataclass class MCPAPIEquivalence: operation: str mcp_result: WorkspaceState api_result: WorkspaceState def verify(self) -> bool: """Verify bitwise equivalence after normalization.""" mcp_normalized = normalize(self.mcp_result) api_normalized = normalize(self.api_result) return mcp_normalized == api_normalized def diff(self) -> Optional[StateDiff]: """Return diff if not equivalent.""" if self.verify(): return None return compute_diff(self.mcp_result, self.api_result) def verify_all_equivalences(bridge: WorkspaceBridge) -> Dict: """Run full equivalence suite.""" results = {} for op in bridge.supported_operations: equiv = MCPAPIEquivalence( operation=op, mcp_result=bridge.execute_mcp(op, test_params[op]), api_result=bridge.execute_api(op, test_params[op]) ) results[op] = { 'equivalent': equiv.verify(), 'diff': equiv.diff() } return results
Say Narration Integration
from workspace_bridge import NaryaLogger logger = NaryaLogger(voice="Ava (Premium)") # Announces: "Workspace bridge: MINUS transition on gmail" logger.log(before, after, Trit.MINUS, service="gmail", impact=False) # Announces: "Workspace bridge: PLUS transition on drive, impact detected" logger.log(before, after, Trit.PLUS, service="drive", impact=True) # Cross-skill morphism announcement logger.log_morphism("thread_task", thread, task, Trit.PLUS)
Skill Name: workspace-unified
Type: Workspace Management / ACSet Framework
Trit: 0 (ERGODIC - coordinator)
GF(3): Conserved via cross-skill morphism routing
ANIMA: Workflow Completion = Condensed Equilibrium State