Feature/process engine - #6
Merged
Merged
Conversation
- Move PROCESS_DRIVEN_AGENTS.md to PROCESS_DRIVEN_PLATFORM/ folder - Add IT1-IT4 thinking documents (analysis, architecture, DDD, UI/UX) - Add phase-based backlog files (MVP, Core, Advanced) - Add BACKLOG_INDEX.md with conventions and traceability - Add DEVELOPMENT_PROCESS.md with workflow and testing strategy This establishes the foundation for implementing the Process Engine feature.
- ProcessId: UUID wrapper with validation and generation
- ExecutionId: UUID wrapper for execution instances
- StepId: Validated string identifier (alphanumeric, hyphens, underscores)
- Version: Major.minor versioning with parsing and comparison
- Duration: Time duration with parsing ("30s", "5m", "2h", "1d")
- Money: Decimal-based currency representation
All value objects are frozen dataclasses for immutability.
Includes 67 unit tests covering all validation and operations.
Refs: IT3 Section 4.3 (Value Objects)
Domain Model: - ProcessDefinition: Aggregate root with validation, publish/archive lifecycle - StepDefinition: Entity for individual steps (agent_task, human_approval, gateway) - StepExecution: Runtime state tracking for step instances - OutputConfig: Process output configuration Step Configurations: - AgentTaskConfig: agent, message, timeout, model, temperature - HumanApprovalConfig: title, description, assignees, timeout (stub) - GatewayConfig: gateway_type, routes, default_route (stub) - TimerConfig, NotificationConfig: stubs for Advanced phase Validation: - Duplicate step ID detection - Invalid dependency reference checking - Circular dependency detection via DFS - Empty name/steps validation Schema & Documentation: - JSON Schema for editor validation (process-definition.schema.json) - Example YAML files (content-pipeline.yaml, approval-workflow.yaml) Includes 27 new tests (94 total process engine tests passing) Refs: IT3 Section 4 (Aggregates)
Repository Interfaces: - ProcessDefinitionRepository: Full CRUD + versioning + filtering - ProcessExecutionRepository: Interface for execution state (impl later) SQLite Implementation: - SqliteProcessDefinitionRepository with JSON storage - Indexed columns for name, status, and name+version uniqueness - In-memory support for testing CRUD Operations: - save: Create or update (upsert by ID) - get_by_id, get_by_name, get_latest_version - list_all, list_by_name with filtering and pagination - delete, exists, count Version Tracking: - Multiple versions per process name - Version major.minor stored separately for efficient queries - get_latest_version returns latest published Also: Updated .gitignore to allow process engine repositories folder Includes 22 new tests (116 total process engine tests passing) Refs: IT3 Section 7 (Repositories)
ProcessValidator Service: - validate_yaml(): Full validation pipeline from raw YAML - validate_definition(): Validate existing ProcessDefinition Validation Levels: 1. YAML syntax validation with line numbers 2. Schema validation (required fields, types) 3. Semantic validation (from domain layer): - No duplicate step IDs - All depends_on references exist - No circular dependencies 4. Agent existence checking (warnings only) ValidationResult: - Separates errors (blocking) from warnings (advisory) - is_valid: True if no errors - to_dict(): API-friendly response format Error/Warning Details: - message: Human-readable description - level: error | warning - path: JSON path (e.g., "steps[0].agent") - line: YAML line number (when available) - suggestion: Fix suggestion Includes 26 new tests (142 total process engine tests passing) Refs: IT3 Section 6 (Domain Services)
Domain Events: - DomainEvent: Base class with kw_only timestamp for inheritance - Process events: ProcessStarted, ProcessCompleted, ProcessFailed, ProcessCancelled - Step events: StepStarted, StepCompleted, StepFailed, StepSkipped - Approval events: ApprovalRequested, ApprovalDecided - All events immutable (frozen dataclasses) with to_dict() serialization Event Bus Infrastructure: - EventBus: Abstract interface for publish/subscribe - InMemoryEventBus: MVP implementation with async dispatch - subscribe(): Handler for specific event types - subscribe_all(): Global handler for all events - unsubscribe(), clear(): Handler management - Async non-blocking dispatch via asyncio.create_task() - Error isolation: handler errors logged but don't stop other handlers - wait_for_pending(): For testing and graceful shutdown Includes 23 new tests (165 total process engine tests passing) Refs: IT3 Section 5 (Domain Events)
Added comprehensive tests for execution-side domain model: - ProcessExecution creation and initialization - State transitions (start, complete, fail, cancel, pause, resume) - Step operations (start_step, complete_step, fail_step) - Query methods (get_completed_step_ids, all_steps_completed) - Serialization roundtrip (to_dict, from_dict) - StepExecution entity tests Fixes gap identified during Sprint 1 review. 31 new tests (196 total process engine tests passing)
Implements REST API for process definitions:
- POST /api/processes - Create new process definition
- GET /api/processes - List all (with filters, pagination)
- GET /api/processes/{id} - Get single definition
- PUT /api/processes/{id} - Update draft definition
- DELETE /api/processes/{id} - Delete draft/archived
- POST /api/processes/{id}/validate - Validate existing
- POST /api/processes/validate - Validate YAML
- POST /api/processes/{id}/publish - Publish draft
- POST /api/processes/{id}/archive - Archive process
- POST /api/processes/{id}/new-version - Create new version
Also marks E2-01 (Execution State Model) as done - was
implemented in Sprint 1 with ProcessExecution aggregate.
21 new API tests (217 total process engine tests passing)
Implements SQLite repository for process executions: - SqliteProcessExecutionRepository with save/get/delete/list operations - Tables: process_executions, step_executions - Proper serialization of Money (as cents), timestamps, JSON data - Query methods: list_by_process, list_active, list_all with filters Also adds input/cost fields to StepExecution entity for tracking step-level inputs and costs (prepares for E2-06 output storage). 21 new repository tests (238 total process engine tests passing)
Implements centralized output storage management:
- OutputStorage service for store/retrieve/delete operations
- OutputPath value object with path pattern /executions/{id}/steps/{step}/output
- Unified API for accessing step outputs regardless of backend
- get_all_outputs() for bulk retrieval
- clear_execution_outputs() for cleanup
- Handles empty dict vs None distinction properly
23 new output storage tests (261 total process engine tests passing)
Sprint 2 complete:
- E1-04: Process Definition API ✓
- E2-01: Execution State Model ✓
- E2-02: Execution Repository ✓
- E2-06: Step Output Storage ✓
Implements the core execution engine for process orchestration: ExecutionEngine: - start() - Start new execution from definition - resume() - Resume paused/partial execution - cancel() - Cancel running execution - Timeout handling per step with asyncio.wait_for - Domain event emission (ProcessStarted, StepCompleted, etc.) DependencyResolver: - get_ready_steps() - Find steps with satisfied dependencies - get_next_step() - Get next step for sequential execution - get_execution_order() - Topological sort of all steps - is_complete() / has_failed_steps() - Status checks StepHandler Interface: - Abstract base for step type handlers (AgentTask, etc.) - StepHandlerRegistry for handler lookup - StepContext for passing execution state - StepResult for success/failure responses 16 new tests (277 total process engine tests passing)
Implements handler for agent_task step type:
AgentTaskHandler:
- Executes agent_task steps by sending messages to Trinity agents
- Variable substitution for {{input.X}} and {{steps.X.output}}
- Timeout handling from step config
- Cost extraction from agent response
AgentGateway (Anti-Corruption Layer):
- Wraps Trinity's AgentClient for clean process engine integration
- Agent availability checking via Docker container status
- Message sending with context metadata
- Error handling and wrapping
10 new tests (287 total process engine tests passing)
Implements template expression evaluation for process messages:
ExpressionEvaluator:
- Evaluates {{expression}} placeholders in strings
- Supports input.X, input.X.Y for nested input data
- Supports steps.X.output, steps.X.output.Y for step outputs
- Supports execution.id, process.name context
- Strict mode raises ExpressionError for undefined expressions
- Expression extraction and validation utilities
EvaluationContext:
- Path-based access to input_data, step_outputs, metadata
- Handles nested dict navigation
AgentTaskHandler Integration:
- Now uses ExpressionEvaluator for variable substitution
- Supports all expression types in message and agent name
30 new tests (317 total process engine tests passing)
Implements REST API for managing process executions:
Endpoints:
- POST /api/processes/{id}/execute - Start new execution
- GET /api/executions - List executions with filters
- GET /api/executions/{id} - Get execution detail
- POST /api/executions/{id}/cancel - Cancel running execution
- POST /api/executions/{id}/retry - Retry failed execution
- GET /api/executions/{id}/steps/{step_id}/output - Get step output
Features:
- Background task execution via BackgroundTasks
- Status filtering (pending, running, completed, failed)
- Process ID filtering
- Pagination support (limit/offset)
- Full step execution details in response
- Authentication required for all endpoints
- Auto-generated OpenAPI docs
13 new tests (330 total process engine tests passing)
Sprint 4: Definition UI (Frontend) E3-01: Process List View - Card grid showing all processes with status badges - Sorting: newest, oldest, name, status - Filtering by status (draft/published/archived) - Actions: Execute, Edit, Delete - Empty state with Create CTA E3-02: YAML Editor Component - Monaco editor integration with dynamic import - YAML syntax highlighting - Line numbers and word wrap - Dark mode theme support - Inline validation error markers - Copy to clipboard, Cmd+S to save E3-04: Process Editor Page - Full editor with validation panel - Save/Publish/Execute buttons - Unsaved changes warning on navigation - Default YAML template for new processes - Keyboard shortcut (Cmd+S) Also: - Added processes Pinia store - Added routes for /processes, /processes/new, /processes/:id - Added Processes link to NavBar - Added monaco-editor dependency
Sprint 5: Monitoring UI (Frontend) E4-01: Execution List View - Table with status icons (✅ ❌ 🔄 ⏳) - Columns: Process Name, Status, Started, Duration, Cost - Filters by status and process - Auto-refresh (30s polling) with pause/resume - Pagination support - Cancel/Retry actions E4-02: Execution Timeline View - Step-by-step progress display - Progress bar with completion percentage - Duration bars relative to longest step - Status indicators (running animation) - Click to expand step details E4-03: Step Detail Panel - Expandable within timeline - Timing info: started, completed, duration, retries - Error display with copy button - Output loading on demand - Copy output to clipboard E4-05: Process Dashboard - Overall stats: processes, executions, success rate, cost - Recent executions list - Published processes with quick execute - Quick action buttons Also: - Added executions Pinia store - Added routes for /executions, /executions/:id, /process-dashboard - Added Executions link to NavBar
…preview, and process domain events
Fixes: - Updated deploy scripts to use `docker compose` (V2) instead of legacy `docker-compose` - Fixed frontend build error by adding `js-yaml` dependency - Fixed backend crash in `executions.py` due to double `Depends` injection - Fixed `sqlite3.OperationalError` in `processes.py` by ensuring DB directory exists - Fixed 404 execution error by aligning DB paths between processes and executions routers - Fixed `AttributeError` in `processes.py` by using `.major` for version logging - Fixed UI "Delete" and "Unsaved Changes" modals by passing `:visible="true"` to ConfirmDialog - Added `TRINITY_DB_PATH` env var to backend service for correct persistence Features: - Implemented `EventLogger` service (E15-04) to persist domain events - Added `SqliteEventRepository` implementation - Added `Event History` tab to Execution Detail UI - Completed Process Dashboard implementation (E4-05) Refs: BACKLOG_MVP.md
…or debugging UI Sprint 7 implements comprehensive error handling for process execution: - Add RetryPolicy value object with configurable max_attempts, initial_delay, backoff_multiplier - Add ErrorPolicy value object with on_error actions (fail_process, skip_step) - Implement retry logic in ExecutionEngine with exponential backoff - Fix error code propagation through fail_step chain - Update API schema to return full error objects (code, message, retry_count) - Enhance ExecutionTimeline UI to display error details, retry attempts - Fix WebSocket handler to properly construct error objects from events - Update dependency resolver to handle skipped steps correctly - Add comprehensive unit tests for error handling scenarios Stories completed: E13-01, E13-02, E13-04
Sprint 8 implements parallel step execution for faster process completion: - Add ParallelGroup and ParallelStructure classes for parallel analysis - DependencyResolver.get_parallel_structure() identifies parallelizable steps - ExecutionEngine runs independent steps concurrently with asyncio.gather() - Add ExecutionConfig.parallel_execution and max_concurrent_steps options - API returns parallel_level for each step and has_parallel_steps flag - UI shows parallel indicator (⫘) for steps at same execution level - Add comprehensive unit tests for parallel detection and execution Stories completed: E5-01, E5-02, E5-03
- ProcessFlowPreview: Vertical orientation by default with swimlane layout - ProcessFlowPreview: Parallel steps grouped horizontally with dashed border - ProcessFlowPreview: Compact design to fit without scrolling - ExecutionTimeline: Parallel indicator (⫘) and level-based sorting
…ox UI Sprint 9 - Human Approval: - Add human_approval step type that pauses execution for review - Add ApprovalRequest entity and ApprovalStatus enum - Add approval API endpoints (list, approve, reject) - Add Approval Inbox UI page with filtering and stats - Add inline approve/reject buttons in execution timeline - Fix WebSocket event serialization for StepId objects - Add non-retryable error handling for APPROVAL_REJECTED - Add execution resume after approval decision
Sprint 10: Gateways & Triggers implementation Gateway Step (E7-01, E7-02, E7-03): - Add gateway step type with exclusive/parallel/inclusive modes - Implement ConditionEvaluator for boolean expressions (==, !=, >, <, and, or) - GatewayHandler evaluates conditions and selects routes - Gateway UI shows route taken and evaluated conditions - Fix _build_step_outputs for proper condition evaluation Webhook Triggers (E8-01, E8-02): - Add TriggerConfig schema (WebhookTriggerConfig, ScheduleTriggerConfig stub) - Implement /api/triggers endpoints (list, invoke, info) - Triggers stored in ProcessDefinition and serialized correctly - Optional secret authentication via X-Webhook-Secret header UI Improvements: - Execute input dialog for providing JSON input data - ProcessList shows Eye icon for published (view) vs Pencil for draft (edit) - ProcessEditor guards against editing published processes - "New Version" button for creating drafts from published processes
- Add notification step type (slack, email stub, generic webhook) - Add webhook event publisher for process_completed/failed/approval_requested - Add compensation handlers for step rollback on process failure - Add CompensationConfig value object for type-safe compensation - Add compensation domain events (Started, Completed, Failed) - Add trigger management UI with webhook URL copy functionality - Add execute dialog for JSON input when starting processes Reference: BACKLOG_MVP.md - E14-01, E14-02, E15-03, E13-03, E8-03
Bugs discovered during manual testing: 1. Notification YAML parsing: Added missing NOTIFICATION branch in StepDefinition.from_dict() - inline fields (channel, message, url) were not being extracted, causing all notifications to default to slack channel. 2. Compensation handler registry: Fixed get_handler() → get() method call on StepHandlerRegistry. 3. Compensation webhook URL: Added 'url' field mapping for generic webhook channel (was only setting webhook_url for Slack). Test: compensation-test.yaml triggers intentional failure to verify compensation handlers execute correctly.
UI/UX improvements for Sprint 11: 1. Retry Execution Tracking: - Add retry_of field to ProcessExecution aggregate - Link retry executions to original failed execution - Display amber "Retry of: <id>" badge with link to original 2. Real-time Compensation Events via WebSocket: - Add CompensationStarted/Completed/Failed to WebSocket publisher - Add compensation event handlers in useProcessWebSocket composable - Display compensation events in Event History without refresh 3. Event Display Improvements: - Format both snake_case and PascalCase event types - Clear events when navigating to different execution - Add 500ms delay before reload to ensure events are persisted - Style compensation events with appropriate colors
Sprint 12 Implementation (E9 - Timer & Scheduling): - Add cron presets (hourly, daily, weekly, monthly, weekdays) - Add cron expression validation to ProcessValidator - Extend scheduler service with process schedule support - Hook schedule registration into publish/archive lifecycle - Add schedule trigger list/info API endpoints - Create TimerHandler for timer step type - Add schedule trigger UI in ProcessEditor - Display next run time in ProcessList Test Debt Fix (Sprints 9-11): - Add test_approval_handler.py (24 tests) - S9 - Add test_gateway_handler.py (18 tests) - S10 - Add test_webhook_triggers.py (14 tests) - S10 - Add test_notification_handler.py (20 tests) - S11 - Add test_compensation.py (22 tests) - S11 - Add test_schedule_triggers.py (23 tests) - S12 - Add test_timer_handler.py (11 tests) - S12 Bug fixes: - Fix timer.py: context.step -> context.step_definition - Remove unused import in timer.py Total: 466 tests passing (was 374)
Sprint 14 Implementation: - E11-02: Process Analytics Dashboard with metrics, trends, step performance - E11-03: Cost Alerts system with thresholds (per-execution, daily, weekly) - E12-01: Process Template Library with bundled templates - E12-02: Template creation from published processes UI Improvements: - Add Process sub-navigation (Processes, Dashboard, Executions, Approvals) - Add Agent sub-navigation (Agents, Files, Templates) - Declutter main nav from 8 to 6 items - Template selector in process creation flow Backend: - Analytics service with ProcessMetrics, TrendData, StepPerformance - CostAlertService with threshold management and alert generation - ProcessTemplateService for bundled and user templates - New API endpoints for analytics, alerts, and templates Frontend: - TrendChart component for execution/cost visualization - TemplateSelector component for process templates - ProcessSubNav and AgentSubNav components - Alerts page and NavBar badge integration - Enhanced ProcessDashboard with analytics Tests: - 59 new unit tests for analytics, alerts, and templates
Sprint 15 - Agent Roles (EMI Pattern): - Add AgentRole enum (Executor/Monitor/Informed) - Add StepRoles entity with validation - Create InformedAgentNotifier service for async notifications - Add RoleMatrix.vue component for interactive role management - Integrate roles tab in ProcessEditor with UI-YAML sync - Extend ProcessValidator for role validation across all step types Sprint 12-14 Completion: - E9-01: Cron validation already implemented (verified) - E10-02: Add breadcrumb navigation for nested sub-process executions - E11-01: Cost tracking already implemented (verified) - E11-03: Integrate CostAlertService with ExecutionEngine - E12-01: Add customer-support bundled process template Tests: - Add test_roles.py for EMI pattern validation - Add test_informed_notifier.py for notification service - Add ExecutionEngine cost alert integration tests Process engine adds ~27,400 LOC (~41% growth to Trinity codebase)
- Move PROCESS_DRIVEN_PLATFORM from docs/drafts/ to docs/ - Add IT5 thinking iteration (scale, reliability, enterprise) - Add Process Engine roadmap with 14 test processes across 5 phases - Create feature flow documentation for Process Engine: - README overview, process-definition, process-execution - process-monitoring, human-approval, process-scheduling - process-analytics, sub-processes, agent-roles-emi, process-templates - Update requirements.md: Add Section 18 (Process Engine) with all features - Update roadmap.md: Mark Phase 14 complete, add decision log entry - Update architecture.md: Add Process Engine section, API endpoints, DB schema - Update feature-flows.md index with Process Engine section
vybe
pushed a commit
that referenced
this pull request
May 26, 2026
… column reads Submodule moves to 9da562f. Skills (groom/roadmap/sprint/metrics/ read-docs) and DEVELOPMENT_WORKFLOW.md now derive Todo/In Progress/ In Dev/Done from status-* labels + GitHub open/closed state instead of the Project #6 Status column, which drifted in practice. Project board is still used for Rank/Tier/Epic/Theme. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 tasks
vybe
pushed a commit
that referenced
this pull request
Jun 2, 2026
…Settings (#995) (#996) * feat(enterprise-ui): User & Org Management view on the #847 seam (#995) Public OSS-bundle frontend for the private user_management module (Abilityai/trinity-enterprise#2). Gated entirely server-side by the `user_management` entitlement — hidden in OSS-only builds and bounced by the route guard on direct URL visits. - views/enterprise/UserManagement.vue: org list + create, membership add/remove, seat counts. Light + dark. No algorithmic IP (CRUD glue over the private /api/enterprise/user-management/* endpoints). - stores/orgManagement.js: domain store, calls via shared axios + auth header (Invariants #6/#7). - router: /enterprise/user-management gated meta.requiresEntitlement: 'user_management' (mirrors the audit route). - views/enterprise/Index.vue: add the catalogue card (available). No public backend/schema/model changes — the entire data model + logic lives in the private submodule per the enterprise open-core split. The submodule pointer is intentionally NOT bumped here; it advances after trinity-enterprise#2 merges. Verified: all four files compile; the only build blocker is the pre-existing unrelated `mermaid` import in AgentWorkspace.vue (stale local node_modules; resolved by CI npm ci). Related to #995, #847 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(enterprise-ui): per-user activity audit in Settings → User Management (#995) Integrates the enterprise activity view INTO the existing OSS user management table (not a separate page). When user_management is entitled, each user row gets a "View activity" action opening a drawer with that user's audit summary + timeline, fetched from the private /api/enterprise/user-management/users/{id}/activity endpoint. - Gated entirely by enterpriseStore.isEntitled('user_management') — column + drawer hidden in OSS-only builds. - No change to the existing role-CRUD behaviour; purely additive column. - loadFeatureFlags() in onMounted (cached/no-op when NavBar already ran). Related to #995 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(user-mgmt): OSS deactivation primitive + enterprise lifecycle UI (#995) Pivots #995 from Organizations to the real net-new gap — user onboarding/offboarding — integrated into the existing Settings → User Management table (not a separate page). OSS primitive (edition-agnostic, small): - users.suspended_at column + migration + surfaced in get_user/list_users. - get_current_user rejects suspended users (both JWT + MCP-key paths), so setting the column blocks new logins AND invalidates live tokens on the next request. - /api/users exposes suspended_at (read-only) so the gated UI can render Deactivate/Reactivate. Enterprise UI (gated by user_management entitlement, hidden in OSS): - Settings → User Management gains an "Invite user" form, per-row Deactivate/Reactivate (not for self or the built-in admin), and the per-user Activity drawer. All call the private /api/enterprise/user-management/* endpoints. Removed: the separate /enterprise/user-management Orgs page, its route, store, and Index card (orgs dropped — single-tenant). Index card now points at Settings. No change to the existing OSS role-CRUD behaviour. Verified live: /api/users carries suspended_at; suspend/reactivate/invite/activity all work; OSS-only builds hide every enterprise control. Related to #995, #847 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(user-mgmt): stop Management column clipping in User Management table (#995) The users table wrapper was overflow-hidden; the extra entitlement-gated Management column pushed total width past the card and clipped the right-side action buttons. Switch to overflow-x-auto so the wider table scrolls within the card instead of clipping. Related to #995 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(user-mgmt): fit User Management table in the card (no h-scroll) (#995) Replace the overflow-x-auto stopgap with an actual fit: trim cell padding px-6→px-4 across the table and let the Management actions wrap within their column (flex-wrap, text-xs, no whitespace-nowrap). The 5-column table now fits the max-w-4xl settings card without clipping or a horizontal scrollbar. Related to #995 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test: add suspended_at to schedule-soft-delete test users DDL (#995) The #995 users.suspended_at primitive added the column to _USER_COLUMNS, so get_user_by_*() now SELECTs it. test_schedule_soft_delete builds its own users table with a hardcoded DDL that lacked the column, causing "no such column: suspended_at" (4 regression-diff failures). Mirror the schema change in the test DDL. Related to #995 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(architecture): document enterprise modules + two-track migrations (#995/#997) - users.suspended_at deactivation primitive (OSS column + enforcement; enterprise-only setter) on the users table + a callout. - Invariant #3 extended: enterprise migrates enterprise_* tables via a separate runner tracked in enterprise_schema_migrations (one file per migration; never ALTERs OSS tables; runs after OSS init). - feature-flags doc gains enterprise_features. - New "Enterprise Modules (#847 seam)" section: audit / user_management / siem entitlements, surfaces, and the gating model. Related to #995, #997, #847 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(enterprise): enterprise registration failure must not crash core boot (#995/#997) main.py wrapped register_enterprise(app) in `except ImportError` only — so a bug in enterprise registration (schema init, migration, router mount, pusher start) would propagate and crash backend startup on an enterprise build. Add a broad `except Exception` that logs loudly + a traceback and continues in OSS-only mode. Modules registered before the failure stay active; the rest are simply absent from feature-flags. The core platform always boots. OSS-only builds are unaffected (still the ImportError path). Verified: happy path still boots (health 200) and registers ['audit','siem']. Related to #995, #997, #847 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 2, 2026
vybe
added a commit
that referenced
this pull request
Jun 3, 2026
#1043) * docs: deprecate Project #6 board — issues-only SDLC (#1042) Move all prioritization metadata off GitHub Project #6 to labels + native sub-issues. Companion to the .claude submodule rewrite (trinity-dev#2), pointer bumped here. - CLAUDE.md: Current Product Focus recast around theme-* labels; Rules of Engagement + SDLC lifecycle de-boarded (Todo → In Progress → In Dev → Done); ordering = priority, bug-before-feature, newest first. - docs/GITHUB_ISSUES_MIGRATION.md: appended 2026-06-03 archive note (board fields → label/sub-issue replacements, dropped Tier/Rank, removed legacy P1b + status-review labels). - docs/planning/PROJECT_BOARD_DEPRECATION_2026-05.md: execution addendum recording the two operator overrides (newest-first ordering; complexity kept as labels). GitHub-state migration applied out-of-band: theme-*/complexity-* labels backfilled from board data, epics converted to type-epic + sub-issues, Project #6 archived. Fixes #1042 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: bump .claude to squashed main after trinity-dev#2 (#1042) Re-point the submodule from the feature-branch commit to the squashed main commit (trinity-dev#2 merged). Coordinated with #1042. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Eugene Vyborov <eugene@beingluminous.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jun 9, 2026
Merged
7 tasks
vybe
pushed a commit
that referenced
this pull request
Jun 26, 2026
…ffects (#1084) (#1351) * feat(idempotency): effect-scoped guard primitive for outbound side effects (#1084) Trigger-boundary idempotency (#525, Invariant #18) dedups the execution but not an agent's individual tool calls — so a re-delivered turn (the at-least-once semantics pull-mode / work-stealing will introduce, Epic #1045/#1081) re-emits the same outbound effect. Add the per-sink primitive that enforces exactly-once external effects at the sink, keyed on resolved effect identity. In services/idempotency_service.py (no new module — avoids the untracked-file / Docker-COPY crash class): - make_effect_scope(execution_id) → effect:{execution_id} - make_payment_scope(agent_request_id) → payment:{agent_request_id} - derive_effect_key: {effect_type}:sha256(execution_id \x00 effect_type \x00 resolved_identifying_args \x00 dedup_label) — STABLE identity only, never the LLM-generated body (non-deterministic across a re-run → would defeat dedup); dedup_label lets an agent intentionally send two distinct messages per turn. - resolve_and_validate_execution: generalizes the MEM-001 server-side resolution (the agent supplies execution_id, never its own identity); FAIL-OPEN on missing/invalid/mismatch so an old image or absent arg never 5xxes a real send. - effect_guard async context manager: completed replay → snapshot (no re-send); in_flight replay → raises retryable EffectInProgressError (codex #6, never a silent None-as-success); fresh claim → complete() on clean exit, fail() (release for retry) on exception. Payment scope path for Nevermined (native token). Reuses the existing 24h-default claim TTL (already exceeds the lease window), so a completed row outlives a late re-delivery — no new TTL plumbing. TDD: 22 new unit tests in tests/test_idempotency.py (40 total green) — body independence, dedup_label, fresh-execution-id, in_flight-raises, fail-open, 6h-aged replay, payment scope. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(payments): guard Nevermined settle with payment-scoped effect idempotency (#1084) The highest-stakes sink first. Add NeverminedPaymentService.settle_payment_once, which wraps settle_payment in the effect guard keyed on payment:{agent_request_id} — Nevermined's native exactly-once token IS the dedup scope. A retried paid chat reusing the same token replays the stored settle receipt instead of burning credits twice; the native token remains the real on-chain guarantee, this avoids even attempting a duplicate and gives a fast local replay. - completed replay → returns the stored sanitized receipt (never the raw SDK object), no re-settle. - a FAILED settle raises an internal _SettleNotCompleted so the in_flight claim is RELEASED (only a successful settle persists as completed/replayable) → a later retry can re-attempt. - a concurrent in-flight settle → retryable "already in progress" result, never a silent skip (codex #6). - no agent_request_id → fail-open, settle proceeds without dedup. routers/paid.py Step 4 now calls settle_payment_once; the existing terminal-turn guard (failed execution → no settle, prior learning terminal-applier-status-leak) is the preserved outer layer. TDD: 4 wiring tests (retried→one settle, failed→release+retry, distinct tokens →both, missing token→fail-open). 44 idempotency tests green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(messages): effect-guard proactive send_message on resolved recipient+channel (#1084) Thread execution_id + dedup_label through routers/messages.py → send_message, and wrap the entry in the effect guard keyed on the RESOLVED recipient + channel (never the LLM-generated body, which is non-deterministic across a re-run). When the turn it ran in is re-delivered (pull-mode at-least-once), the same identity within one execution dedupes to exactly one send; a distinct dedup_label lets an agent intentionally send two messages to the same recipient per turn. - send_message refactored: the entry guard wraps a new _send_message_inner (auth → rate-limit → channel delivery), so a success records a replay snapshot and an exception releases the claim for retry. Replay reconstructs the DeliveryResult. - A chunked message is ONE effect (entry guard) — a mid-chunk crash re-sends the whole message on retry (at-least-once for chunks, documented). - Concurrent in-flight duplicate → EffectInProgressError → router returns 409 (retryable), never a silent skip-and-succeed (codex #6). - Fail-open when execution_id absent/invalid (old image). Drive-by: removed two dead imports (time, enum.Enum) + one stray f-prefix to keep the touched files ruff-clean. TDD: 4 wiring tests (re-delivery→one send, dedup_label→two, no-execution_id→ fail-open, distinct-recipient→not-deduped). 48 idempotency tests green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(voip): effect-guard call_user on resolved dial target (#1084) Thread execution_id + dedup_label through routers/voip.py → place_outbound_call, and wrap the dial in the effect guard keyed on the RESOLVED dial target + Twilio account, scoped to execution_id. When the turn it ran in is re-delivered (pull-mode at-least-once), the same number within one execution replays the original {call_id, status, ...} instead of placing a second PSTN call. - place_outbound_call refactored: the entry guard wraps a new _place_call_inner (abuse controls → stage Gemini intent → dial Twilio), so a success records a replay snapshot and a raised HTTPException releases the claim for retry. - The router's boundary Idempotency-Key gate stays the OUTER layer (kept). - Concurrent in-flight duplicate dial → EffectInProgressError → router releases the outer trigger claim and returns 409 (retryable), never a silent skip. - Fail-open when execution_id absent/invalid (old image). Drive-by: removed one dead twilio import to keep the file ruff-clean. TDD: 4 wiring tests (re-delivery→one dial, dedup_label→two, no-execution_id→ fail-open, distinct-number→not-deduped). 52 idempotency tests green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(files): effect-guard share_file on filename + content version (#1084) Thread execution_id + dedup_label through routers/agent_files.py → create_share, and wrap the token-mint + persist in the effect guard keyed on the filename + a sha256 of the extracted CONTENT, scoped to execution_id. A re-run of the same turn sharing the same file replays the original signed URL instead of minting a second token; a changed file under the same name produces a new share. - create_share extracts up-front (so the key can version on content), then the guard wraps a new _finalize_share (MIME/quota/disk → persist → mint token + DB row → URL). Success records the URL snapshot for replay; an exception releases the claim for retry. - ShareFileMcpRequest gains execution_id + dedup_label; the internal agent-server share path passes neither → fail-open (back-compat). - Concurrent in-flight duplicate → EffectInProgressError → router 409. Drive-by: removed a dead typing.Optional import to keep agent_files.py ruff-clean. TDD: 3 wiring tests (re-run→same URL replay, changed-content→new share, no-execution_id→fail-open). 55 idempotency tests green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(mcp): execution_id + dedup_label params on send_message / call_user / share_file (#1084) Inv #13 third surface. Add optional agent-supplied execution_id + dedup_label params to the messages.ts (send_message), voip.ts (call_user) and files.ts (share_file) tools, and thread them into the request bodies in client.ts (sendUserMessage / placeVoipCall / shareAgentFile). The agent reads execution_id from the 'Execution Context' block of its system prompt (same source as write_user_memory / MEM-001) and passes it so the backend effect guard dedupes a re-delivered turn to exactly one effect; omitting it is fail-open (the send proceeds). dedup_label lets the agent intentionally repeat an effect to the same target in one turn. Trusted runtime injection of execution_id (+ fail-closed-when-absent) is deferred — a BLOCKING prerequisite on Epic #1045/#1081 before pull-mode default-ON for side-effect agents. Tests: new messages.test.ts asserts execution_id + dedup_label reach the body (and undefined when omitted), plus a regression assertion that chat_with_agent still derives a non-empty mcp: Idempotency-Key. 31 MCP tests green; tsc clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(reliability): effect-idempotency contract + architecture + pull-mode gate (#1084) - New docs/memory/feature-flows/effect-idempotency.md: the per-sink exactly-once contract — honest scope (local suppression vs true exactly-once), the 6 design decisions, wired sinks table, the BLOCKING pull-mode-default-ON prerequisite, and the documented failure modes (pre-call crash window, chunk at-least-once, git idempotent-by-construction). - architecture.md: extend the RELIABILITY-006 (#525) Idempotency block with the #1084 effect-scoped layer (effect_guard, scopes, body-independent key, in_flight≠completed, 24h-TTL reuse, wired sinks, the gate). - feature-flows.md: Recent Updates row + a Documented Flows entry. - task_execution_service.py: dispatch_async_eligible carries the pull-mode gate comment (trusted execution_id injection + fail-closed-when-absent required before pull-mode default-ON for side-effect agents — Epic #1045/#1081). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(security): CSO --diff audit for effect-scoped idempotency (#1084) CLEAR — no CRITICAL/HIGH. Confirms the load-bearing auth property: a forged or borrowed execution_id fails-open (no claim, no cross-tenant snapshot read) because agent_name is always authenticated and resolve_and_validate_execution checks ownership before the claim. No secrets, no injection (agent-supplied identifying_args/dedup_label are hash-only), no new deps, no new SQL. One LOW noted (share download token at rest in idempotency_keys — same backend-internal trust level, no net exposure). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(idempotency): harden effect-guard replay + cap key inputs (#1084) - Bound execution_id/dedup_label with max_length=200 on send_message and call_user request models so a hostile/oversized value can't bloat the derived effect key. - Replay-with-missing-snapshot (I2): a completed effect replay is terminal, so never re-emit the side effect even when the stored snapshot is NULL/unparseable. share_file raises 409 (cannot rebuild the signed URL); Nevermined settle reports success without a receipt and logs a warning (never re-enters the external settle path → no double-charge). - Track the _finalize_share → _persist_and_register rename in the share_file guard test. Refs #1084 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(test): #679 paid-settle test mocks settle_payment_once after #1084 reroute paid_chat's success path now settles through settle_payment_once (the effect-scoped idempotency wrapper, #1084) rather than bare settle_payment, so the #679 success-still-settles regression test must mock/await the new entrypoint. The cancel/fail siblings keep asserting non-settle (neither entrypoint is reached on a terminal turn). Refs #1084 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(reliability): requirements §10.10.1 + sink-flow pointers for effect idempotency (#1084) Adds requirements.md §10.10.1 documenting the effect-scoped extension to RELIABILITY-006, and cross-reference pointers from the four wired sink flows (voip-telephony, proactive-messaging, file-sharing-outbound, nevermined-payments) to the canonical effect-idempotency flow (one-home-per-feature rule). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
7 tasks
7 tasks
This was referenced Jul 23, 2026
Merged
vybe
pushed a commit
that referenced
this pull request
Jul 29, 2026
…ab (ent#235) (#1877) * feat(ui): Skills management surface — unhide and rebuild the Skills tab (ent#235) The skills machinery shipped across three planes (#182 distribute/place/expose, #183 package injection with a per-skill result contract) and nothing rendered any of it. The Agent Detail Skills tab was excluded from `visibleTabs` per requirements §22.2 ("component preserved for potential admin-only access"), assignment was REST/MCP-only (§21.3), and #183's statuses and named warnings had no consumer at all. A user could not browse the library, see what an agent had, or assign anything. What lands: * **Tab unhidden** for owners/admins on non-system agents, matching the other management tabs. `OverflowTabs` absorbs it. * **`stores/skills.js`** — a domain store (Invariant #6). The old panel called `axios` directly with a hand-built auth header, silently bypassing the shared client every other call relies on; everything now goes through `api` (Invariant #7). * **Library browse** with the §21.6 contract surfaced: description, automation, `user_invocable`, declared `requires` (binaries/packages/env), multi-file file count, size, and the git tree SHA as version. Dependencies are shown BEFORE assignment, because they are what later becomes a `missing_binary:*` warning. * **Assignment** with bulk save through the existing `PUT .../skills`, plus a dirty/reset affordance so a half-made selection is recoverable. * **Honest injection status.** This is the load-bearing part. #183 reports `injected | unchanged | fallback | failed` with named warnings; the panel renders the verdict per skill and translates the tokens into what they mean for THIS agent ("`jq` is not installed in this agent — the skill may not run"). `fallback` renders as "partial" in amber, never a green tick — an explicit AC. Injection results are kept separate from assignment in the store precisely so a durable assignment cannot be painted with a stale success. * **Manual sync** (`force=True` repair action) with in-flight state, and a 409 from `SkillInjectionBusy` reported as "already running" rather than a generic failure. * **No dead empty states** — the store computes one discriminator (`library_unconfigured` / `library_empty` / `none_assigned`) so the panel cannot invent a fourth. Unconfigured routes an admin to Settings and tells a non-admin to ask one. * **Stopped agent** renders persisted assignment state with Sync disabled and the reason in the tooltip, rather than offering an action that would fail. Verified against the live instance: tab appears, 3-skill library renders with contract fields, bulk assign persists, agent started, "Sync now" returns `{haiku: injected/2 files, word-count: injected/2 files}` and the badges + last-sync line render from that response. Gating confirmed OSS-core with the issue author before building: every file here is already public, the endpoints are ungated, and the paid piece (skill_runner, ent#139) plus exposure curation (#178) are both explicitly out of scope. Related to trinity-enterprise#235 * fix(ui): dead Settings link + error swallowed as an empty library (ent#235 review) Self-review of #1877 found two defects, both in the "no dead empty states" AC this panel exists to satisfy. 1) The "Configure the library" CTA linked to `/settings?tab=skills`. There is no such tab — the Skills Library config lives under Settings → **agents** (`Settings.vue`, `v-if="activeTab === 'agents'"`). So the one call-to-action offered to an admin staring at an unconfigured library went nowhere. I also asserted in the PR body that the Settings panel already reported sync status / last-synced / skill count without checking; it does report all three — but I had the tab wrong, which is what checking would have caught. 2) `api.get('/api/skills/library').catch(() => ({ data: [] }))` swallowed every error, not just the unconfigured case: a 500, a timeout or an auth failure all rendered as "the library is configured but has no skills yet" — a confident, wrong empty state that points the operator at the wrong problem. The list is now fetched only when `status.configured` is true, so the known empty state comes from the status read and any other failure surfaces as one. Related to trinity-enterprise#235
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note
Introduces example workflows and foundational docs for the process-driven platform.
content-review,customer-support,data-analysiswithdefinition.yamlandtemplate.yamlunderconfig/process-templates/IT1–IT4) indocs/PROCESS_DRIVEN_PLATFORM/docker-compose.ymlto set backendTRINITY_DB_PATH=/data/trinity.db.gitignoreto includesrc/backend/services/process_engine/repositories/Written by Cursor Bugbot for commit aa3d56e. Configure here.