Skip to content

[RFC / Design] Support for Standalone / Ad-hoc Tasks #22

Description

@espdesign

Overview

Currently, tasks must be bound to an existing project container (TaskTable.project_id is a non-null foreign key). Although the UI and authorization layers have initial scaffolding for standalone tasks (allow_standalone, can_create_standalone, and default TASK-# references), creating one fails at runtime.

This issue tracks the discussion and technical design decisions needed to enable standalone / ad-hoc tasks across the system.

Problem Statement

Users need a way to track quick one-off chores, ad-hoc bugs, or general server tasks without having to create or choose a full project container.

Currently:

  • TaskTable.project_id in PostgreSQL has nullable=False.
  • Task domain model requires project_id: UUID.
  • TaskService.create_task() enforces if not resolved_project_id: raise ValidationError("A project container must be specified for every task.").
  • Short ID allocation (prefix-number) assumes an active project row exists to increment next_task_number.

Design Options Under Consideration

Option A: Default "Standalone" / "General" Project Container (Recommended)

Automatically create a default project named Standalone (or General Tasks) per guild with prefix TASK.

  • Pros:
    • Zero DB schema changes: No nullable migration on tasks.project_id or foreign key adjustments.
    • Existing atomic allocation: Reuses existing next_task_number counter to automatically generate TASK-1, TASK-2, TASK-3 with full concurrency safety.
    • Compatibility: Tech trees, burndown metrics, outbox events, and task board views immediately work without needing if project_id is None guards across queries.
    • Task Board scoping: Users can filter directly to [TASK] Standalone on the board to view all ad-hoc tasks.
    • Channel routing: Since the default project's discord_channel_id is None, tasks post directly in whichever channel/forum the user creates them in.
  • Questions / Decisions:
    • Naming & prefix: Standalone vs General vs Inbox; prefix TASK vs STD vs GEN.
    • Visibility: Should it be hidden from /project list or categorized as a system/general container?
    • Provisioning: Automatically ensure existence on guild join, seeding, or first use.

Option B: True Nullable project_id

Make tasks.project_id nullable across the database and models.

  • Pros:
    • Tasks truly have no parent project entity in the database.
  • Cons & Required Changes:
    • Alembic migration to drop NOT NULL constraint on tasks.project_id.
    • Need a new guild-level sequence / counter mechanism (e.g. guild_task_sequences table) to atomically allocate TASK-# IDs.
    • Must update all aggregations, queries, outbox workers, and board views to handle None project IDs.

Next Steps

  • Decide between Option A (Default Project) and Option B (Nullable Schema).
  • Define UX for /task create (making project_name optional to fallback to standalone).
  • Wire up interactive menus (TaskMenuView.standalone_btn and HubTaskProjectSelectView).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions