✨ feat(commons): port The Commons social network to AIPass framework

Complete port of The Commons (FPLAN-0411) — a social network for AI branches
with posts, comments, votes, rooms, feeds, artifacts, trading, and more.

- 85 Python files, ~13,500 lines across 7 phases
- 20 auto-discovered modules covering 50+ commands
- 16-table SQLite schema with FTS5 search and 26 indexes
- 82/82 tests passing (72 ported + 10 integration lifecycle tests)
- All seedgo compliance scores 80%+ across all phases
- Clean 3-layer architecture: entry point → modules → handlers
- Cross-branch imports with graceful fallback (no sys.path manipulation)
- .gitignore updated for commons artifacts handler and json_templates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
AIOSAI
2026-03-07 16:13:49 -08:00
co-authored by Claude Opus 4.6
parent f8b48a6bb6
commit fe187be8cd
93 changed files with 14629 additions and 1 deletions
+180
View File
@@ -0,0 +1,180 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: post_module.py - Post orchestration module
# Date: 2026-03-07
# Version: 1.0.0
# Category: commons/apps/modules
#
# CHANGELOG (Max 5 entries):
# - v1.0.0 (2026-03-07): Ported from dev system (FPLAN-0411)
#
# CODE STANDARDS:
# - Orchestration only - NO business logic
# - Imports from handlers/ for all data operations
# - Module interface: handle_command(command, args) -> bool
# - No sys.path manipulation
# =============================================
"""
Post Orchestration Module
Thin router for post workflows. Delegates all implementation
to handlers/posts/post_ops.py and renders the results.
Handles: post, thread, delete commands.
"""
import logging
from typing import List
try:
from aipass.prax.apps.modules.logger import system_logger as logger
except ImportError:
logger = logging.getLogger("commons.post_module")
try:
from aipass.cli.apps.modules import console
except ImportError:
from rich.console import Console
console = Console()
from rich.panel import Panel
from rich.text import Text
from commons.apps.handlers.posts.post_ops import create_post, view_thread, delete_post
from commons.apps.handlers.identity.identity_ops import resolve_display_name
# =============================================================================
# COMMAND ROUTING
# =============================================================================
def handle_command(command: str, args: List[str]) -> bool:
"""
Handle post-related commands.
Args:
command: Command name (post, thread, delete).
args: Command arguments.
Returns:
True if command handled, False otherwise.
"""
if command == "post":
return _handle_create_post(args)
elif command == "thread":
return _handle_view_thread(args)
elif command == "delete":
return _handle_delete_post(args)
return False
# =============================================================================
# DISPLAY HANDLERS
# =============================================================================
def _handle_create_post(args: List[str]) -> bool:
"""Create a post and display the result."""
result = create_post(args)
if not result["success"]:
console.print(f"[red]{result['error']}[/red]")
return True
console.print()
console.print(f"[green]Post created in r/{result['room']}[/green]")
console.print(f" [dim]ID:[/dim] {result['post_id']}")
console.print(f" [dim]Title:[/dim] {result['title']}")
console.print(f" [dim]Type:[/dim] {result['post_type']}")
console.print(f" [dim]Author:[/dim] {resolve_display_name(result['author'])}")
if result.get("mentions"):
console.print(f" [dim]Mentions:[/dim] {', '.join(f'@{m}' for m in result['mentions'])}")
console.print()
return True
def _handle_view_thread(args: List[str]) -> bool:
"""View a thread and display post with comments."""
result = view_thread(args)
if not result["success"]:
console.print(f"[red]{result['error']}[/red]")
return True
post = result["post"]
comments = result["comments"]
# Display the post
console.print()
type_color = {
"discussion": "blue",
"review": "magenta",
"question": "yellow",
"announcement": "red",
}.get(post["post_type"], "white")
header_text = Text()
header_text.append(f"[{post['post_type']}] ", style=type_color)
header_text.append(post["title"], style="bold")
console.print(Panel(
f"{post['content']}\n\n"
f"[dim]By {resolve_display_name(post['author'])} in r/{post['room_name']} | "
f"Score: {post['vote_score']} | "
f"{post['created_at']}[/dim]",
title=header_text,
border_style="cyan",
))
if not comments:
console.print("[dim] No comments yet.[/dim]")
console.print()
return True
# Build threaded display
console.print(f"\n[bold]Comments ({len(comments)}):[/bold]")
console.print()
top_level = [c for c in comments if c["parent_id"] is None]
children_map: dict = {}
for c in comments:
if c["parent_id"] is not None:
children_map.setdefault(c["parent_id"], []).append(c)
def _print_comment(comment: dict, depth: int = 0) -> None:
indent = " " * depth
prefix = "|" if depth > 0 else ""
score = comment["vote_score"]
if score > 0:
score_str = f"[green]{score}[/green]"
elif score < 0:
score_str = f"[red]{score}[/red]"
else:
score_str = f"[dim]{score}[/dim]"
console.print(
f" {indent}{prefix}[bold]{resolve_display_name(comment['author'])}[/bold] "
f"({score_str}) [dim]{comment['created_at']}[/dim]"
)
console.print(f" {indent}{prefix} {comment['content']}")
console.print()
for child in children_map.get(comment["id"], []):
_print_comment(child, depth + 1)
for comment in top_level:
_print_comment(comment)
return True
def _handle_delete_post(args: List[str]) -> bool:
"""Delete a post and display the result."""
result = delete_post(args)
if not result["success"]:
console.print(f"[red]{result['error']}[/red]")
return True
console.print(f"[green]Post {result['post_id']} deleted.[/green]")
return True