Learning

Linear Project Execution Model

Sequence diagrams and operating rules for executing project plans through Linear, including job queue pickup and session handling.

Linear Project Execution Model

This document describes how Linear acts as the project-management and execution-control layer for project development work.

The model is designed for this workspace:

  • Linear is the live execution queue.
  • Git/Markdown docs are the durable source of truth.
  • Docusaurus is the reading/review layer.
  • Ryo is the assistant/agent execution identity.
  • Agent-owned Linear work is assigned to ynerv-ryo-2@agentmail.to when assignment is supported.
  • Assistant-authored Linear comments/descriptions start with 🤖 Ryo:.

Core rule

A ticket becomes executable by Ryo when it is both:

  1. assigned to ynerv-ryo-2@agentmail.to, and
  2. in an actionable state, usually In Progress or Todo with waiting:agent.

Recommended trigger convention:

Linear signalMeaningAction
Todo + waiting:userWaiting for user decision/reviewDo not execute; surface as waiting on user
Todo + waiting:agentQueued agent workPick up when capacity/sequence allows
In Progress + assigned to RyoActive agent workStart or continue immediately
BlockedCannot proceedKeep blocker visible in Linear and docs
ReviewWork complete, waiting for human reviewUser reviews/accepts
DoneAccepted/closedNo further action

Sequence: executing a project plan with Linear

sequenceDiagram
    autonumber
    actor User
    participant Linear as Linear
    participant Watcher as Linear watcher / poller
    participant Queue as Local pending job queue
    participant Ryo as Ryo agent session
    participant Docs as Project docs / state files
    participant Code as Local project directory
    participant Site as Docusaurus / Vercel docs site

    User->>Linear: Create or update project plan and tickets
    User->>Linear: Assign ticket to Ryo and set state or label
    Watcher->>Linear: Poll issues, comments, labels, assignee, and state
    Linear-->>Watcher: Changed actionable issue
    Watcher->>Queue: Store pending issue digest
    Ryo->>Queue: Pick next actionable job
    Ryo->>Linear: Fetch full issue, comments, labels, and links
    Ryo->>Docs: Read project state, requirements, architecture, and backlog
    Ryo->>Code: Inspect or prepare local project directory
    Ryo->>Linear: Comment "🤖 Ryo: started or continuing work"
    Ryo->>Code: Implement, test, or update docs
    Ryo->>Docs: Update project-state, decisions, and handoff
    Ryo->>Linear: Comment result, blockers, or review handoff
    Ryo->>Linear: Move issue to Review, Done, or Blocked according to outcome
    Ryo->>Site: Publish docs when requested or as part of docs workflow

Sequence: fetching a Linear ticket into the local job queue

The local queue exists so a detected Linear change is not lost if a cron run, session, or process fails after detection.

In this workspace, the Leave Management watcher uses:

  • watcher script: ~/.hermes/scripts/linear_leave_watcher.py
  • state file: ~/workspace/run/linear_leave_watcher_state.json
  • pending queue: ~/workspace/run/linear_leave_watcher_pending.json
  • schedule: every 5 minutes
sequenceDiagram
    autonumber
    participant Watcher as Watcher cron job
    participant Linear as Linear API
    participant State as Watcher state file
    participant Pending as Pending queue file
    participant Agent as Ryo execution session

    Watcher->>Linear: Query project/team issues
    Linear-->>Watcher: Issue state, assignee, labels, updatedAt, comments
    Watcher->>State: Read previous digest
    alt No previous baseline
        Watcher->>State: Save current digest
        Watcher-->>Watcher: Emit NO_CHANGES
    else Actionable change detected
        Watcher->>Pending: Append changed issue to pending queue
        Watcher->>State: Save new digest
    else No actionable change
        Watcher-->>Watcher: Exit
    end

    Agent->>Pending: Read pending queue
    loop For each pending issue
        Agent->>Linear: Fetch full issue details
        Agent->>Agent: Decide if executable now
        alt executable
            Agent->>Linear: Add "🤖 Ryo:" processing comment
            Agent->>Agent: Execute task workflow
            Agent->>Pending: Remove issue after successful handling
        else not executable
            Agent->>Pending: Keep or requeue issue with reason
        end
    end

Sequence: ticket assigned to Ryo but no local project directory exists

This is the recovery/bootstrap path. Linear may contain a valid assigned ticket before the local project folder exists, especially when a project is created in Linear first or this machine is newly bootstrapped.

sequenceDiagram
    autonumber
    participant Agent as Ryo agent session
    participant Linear as Linear issue/project
    participant Workspace as ~/workspace/projects
    participant Docs as Workspace docs
    participant Repo as Git / source provider if available
    participant User as User

    Agent->>Linear: Fetch full issue and project metadata
    Agent->>Workspace: Look for mapped project directory
    alt Project directory exists
        Agent->>Docs: Read docs/00-project-state.md and related docs
        Agent->>Workspace: Continue normal execution
    else Project directory missing
        Agent->>Docs: Search shared docs for project mapping or start guide
        alt Repo/source link is present in Linear or docs
            Agent->>Repo: Clone or fetch project into ~/workspace/projects/project-slug
            Agent->>Docs: Create/update docs/00-project-state.md
            Agent->>Linear: Comment "🤖 Ryo: local project directory bootstrapped"
        else Docs-only project can be bootstrapped
            Agent->>Workspace: Create ~/workspace/projects/project-slug/docs
            Agent->>Docs: Create 00-index.md and 00-project-state.md from Linear context
            Agent->>Linear: Comment "🤖 Ryo: created local project docs scaffold"
        else Missing source is a blocker
            Agent->>Linear: Comment missing repo/source/path blocker
            Agent->>Linear: Move issue to Blocked
            Agent->>User: Surface what is needed: repo URL, project path, or permission
        end
    end

Directory resolution rules

When a Linear ticket is assigned to Ryo but the local directory is unknown, use this order:

  1. Read the Linear issue project name and description.
  2. Check whether the ticket description links to a local path, Git repository, docs page, or Docusaurus page.
  3. Search ~/workspace/projects for a matching project folder.
  4. Search ~/workspace/docs for setup/start docs that map Linear projects to folders.
  5. If a source repository link exists, clone/fetch it into ~/workspace/projects/<project-slug>.
  6. If it is a docs-only planning project, create ~/workspace/projects/<project-slug>/docs and initialize docs from the Linear ticket/project context.
  7. If neither source nor enough context exists, move the ticket to Blocked and ask for the missing repo/path/permission.

Job queue rules

The local pending queue should store compact actionable records, not full transcripts.

Recommended queue item fields:

{
  "issue_id": "Linear UUID",
  "identifier": "YNE-8",
  "title": "Implement employee leave request submission",
  "project_name": "Leave Management",
  "team_key": "YNE",
  "state": "In Progress",
  "assignee_email": "ynerv-ryo-2@agentmail.to",
  "labels": ["waiting:agent"],
  "detected_at": "ISO timestamp",
  "reason": "assigned_to_agent_and_actionable"
}

Queue handling principles:

  • Detection and execution are separate.
  • A watcher may detect a job and write it to the pending queue without executing it immediately.
  • The agent removes a pending item only after successful processing or after explicitly moving it to Blocked with a Linear comment.
  • If execution fails mid-run, the item remains pending so the next run can retry.
  • The queue should be idempotent: the same issue should not be duplicated endlessly.
  • Before executing a queued issue, Ryo must re-fetch the full Linear issue because the ticket may have changed after the queue item was written.

Session model for project development

Default recommendation

Use one active execution session per active ticket, not one long immortal session for the whole project and not a new isolated session for every small sub-step.

Practical model:

ScopeSession behaviorWhy
One active Linear ticketPrimary execution sessionKeeps context focused on the ticket and its docs
Independent research or code review subtaskOptional subagent/sessionAllows parallel work without polluting main context
Long project historyStored in docs and Linear, not chat memoryChat context can reset; docs/Linear persist
New ticket after completionNew or refreshed session using project-state handoffPrevents stale assumptions from previous ticket
Failed/timeout runRetry from queue using project-state + Linear commentsQueue prevents lost work

Why not one permanent session per project?

A permanent chat/session is fragile because:

  • context windows eventually compact or reset;
  • tool processes may stop;
  • assumptions can become stale;
  • a long session can mix unrelated tickets.

Instead, the durable project state should live in:

  • Linear issue state and comments;
  • docs/00-project-state.md;
  • project source files;
  • ~/workspace/run/*pending*.json for unprocessed queue items.

Why not spawn a new session for every micro-task?

A new session for every micro-task loses useful immediate context and adds overhead.

Better rule:

  • use the same session while actively processing one Linear ticket;
  • spawn sub-sessions only for bounded, independent subtasks such as codebase inspection, test failure investigation, or parallel research;
  • merge subtask findings back into the main ticket session;
  • update Linear and project-state before ending.

Ticket execution loop

For each actionable ticket:

  1. Fetch the full issue from Linear.
  2. Read the issue title, description, acceptance criteria, labels, comments, project, and links.
  3. Resolve or bootstrap the local project directory.
  4. Read project docs, especially:
  5. - docs/00-project-state.md - docs/10-linear-backlog.md - requirements, architecture, workflows, and implementation plans

  6. Add a short 🤖 Ryo: progress comment if work is starting or resuming.
  7. Execute the work.
  8. Verify with tests/build/checks where available.
  9. Update project docs and project-state.
  10. Update Linear with result.
  11. Move to Review, Done, or Blocked according to the team's available workflow.
  12. Remove or resolve the pending queue item.

Failure and blocked behavior

Move the issue to Blocked when Ryo cannot continue without user input or missing resources.

Common blockers:

  • missing repository URL;
  • missing local project path;
  • missing credentials or permission;
  • unclear acceptance criteria;
  • external system unavailable;
  • test/build failure that cannot be fixed safely without a decision.

Blocked comment format:

🤖 Ryo: Blocked.

Reason:
- ...

Needed to continue:
- ...

Review behavior

When work is complete:

  • If a real Review state exists, move the issue to Review.
  • If no Review state exists, add a clear 🤖 Ryo: Ready for review comment and use the team's fallback convention.
  • Move to Done only after approval or when the team explicitly treats completion as accepted.

Current Leave Management example

Current intended flow:

  1. YNE-8: active In Progress agent implementation.
  2. YNE-9 to YNE-12: queued agent implementation tickets.
  3. YNE-13: user-owned MVP review gate.
  4. YNE-14: queued agent implementation ticket after core flow.

The project state file is:

  • ~/workspace/projects/p02-leave-management/docs/00-project-state.md

The backlog/issue map is:

  • ~/workspace/projects/p02-leave-management/docs/10-linear-backlog.md