Одна задача, три вида
Вы узнаете
Как задача, ревью и фоновая работа становятся одним видом задачи с семью состояниями и как их читает один фильтр.
Королева ведёт работу трёх видов: задачи для пчёл, ревью готовой работы и фоновые работы. У каждого вида были свои коды, и ни одна доска не могла показать их вместе. tasks.t27 даёт им 7 общих состояний, пронумерованных как колонки доски, плюс failed. Отменённая работа показывается как dropped, и так же — забытая строка ревью. task_matches — фильтр, который применяют доска, игра и маршрут: бит на вид, бит на состояние, а 0 значит любое.
Попробовать
Покажите только упавшие задачи всех видов; затем найдите, какое состояние работы показывается как dropped.

An issue, a review and a job are one kind of task with seven states. Tap kinds and states: the grid lights every pair task_matches lets through.
specs/queen/tasks.t27
// SPDX-License-Identifier: Apache-2.0
; specs/queen/tasks.t27 -- one task, many kinds, and the bees working on them, as everyone reads them
; Owner, 2026-10-08 (translated): lower every task of the project to the scheduler's native level; a
; dashboard shows all of it with any filter (https://app.t27.ai/game/kanban); the bees fly over the
; GitHub issue each is working on in the game (https://app.t27.ai/game). Epic #7718, slice 1.
; Measured that morning, four surveys:
; - there is no single task. An issue dispatch (dispatch.t27 COL_*), a job (jobs.t27 J_*) and an app
; review (app.t27, per head) each kept their own codes.
; - no public field said which bee is on which issue. The game drew a public snapshot with no bees, and
; its older comb paired the k-th busy slot with the k-th running card, which is a rank, not a link.
; This card is the view everyone reads: the supervisor builds GET /queen/public-tasks with it, and the
; board and the game filter and draw with it. The kinds keep their own machines; this only says how
; each one shows.
; ASCII only (L3).
; phi^2 + 1/phi^2 = 3 | TRINITY
module QueenTasks;
/// Kinds of task. Index into KIND_NAMES.
pub const TK_ISSUE : u8 = 0;
pub const TK_REVIEW : u8 = 1;
pub const TK_JOB : u8 = 2;
pub const TASK_KINDS : u8 = 3;
pub const KIND_NAMES : [3]str = ["issue", "review", "job"];
/// One state for every kind, numbered as dispatch.t27's board columns (COL_BACKLOG .. COL_DROPPED) so
/// an issue's column IS its state, plus FAILED, which a column never was. Index into STATE_NAMES.
pub const TS_BACKLOG : u8 = 0;
pub const TS_BLOCKED : u8 = 1;
pub const TS_RUNNING : u8 = 2;
pub const TS_REVIEW : u8 = 3;
pub const TS_DONE : u8 = 4;
pub const TS_DROPPED : u8 = 5;
pub const TS_FAILED : u8 = 6;
pub const TASK_STATES : u8 = 7;
pub const STATE_NAMES : [7]str = ["backlog", "blocked", "running", "review", "done", "dropped", "failed"];
/// A job's state (jobs.t27: 0 running, 1 done, 2 failed, 3 cancelled) as a task state.
pub fn job_state(j: u8) -> u8 {
if (j == 0) { return TS_RUNNING; }
if (j == 1) { return TS_DONE; }
if (j == 2) { return TS_FAILED; }
return TS_DROPPED;
}
/// An app review's row state (queued 0, posted 1, forgotten 2, failed 3) as a task state.
pub fn review_state(r: u8) -> u8 {
if (r == 0) { return TS_BACKLOG; }
if (r == 1) { return TS_DONE; }
if (r == 2) { return TS_DROPPED; }
return TS_FAILED;
}
/// The A2A v1.0 task state each state is, for the day the Queen answers A2A at her edge (epic #7718
/// slice 7). A task waiting for a judge or a person is input-required; dropped is canceled.
pub const A2A_SUBMITTED : u8 = 1;
pub const A2A_WORKING : u8 = 2;
pub const A2A_INPUT_REQUIRED : u8 = 3;
pub const A2A_COMPLETED : u8 = 4;
pub const A2A_CANCELED : u8 = 5;
pub const A2A_FAILED : u8 = 6;
pub fn a2a_state(s: u8) -> u8 {
if (s == TS_BACKLOG) { return A2A_SUBMITTED; }
if (s == TS_RUNNING) { return A2A_WORKING; }
if (s == TS_BLOCKED or s == TS_REVIEW) { return A2A_INPUT_REQUIRED; }
if (s == TS_DONE) { return A2A_COMPLETED; }
if (s == TS_DROPPED) { return A2A_CANCELED; }
return A2A_FAILED;
}
/// A bee is one dispatch still in flight: offered and not claimed yet (QUEUED), heard from within
/// BEE_QUIET_SECONDS (WORKING), or silent longer (QUIET). The game draws a quiet bee hovering, not
/// working: a bee that has not spoken for minutes is not shown as busy.
pub const BS_QUEUED : u8 = 0;
pub const BS_WORKING : u8 = 1;
pub const BS_QUIET : u8 = 2;
pub const BEE_QUIET_SECONDS : u32 = 180;
pub const BEE_STATE_NAMES : [3]str = ["queued", "working", "quiet"];
/// `claimed`: a runner took the order (or the container started it); `heard`: an event was recorded
/// for its conversation; `seconds_since`: since that event, or since it started when none was heard.
pub fn bee_state(claimed: bool, seconds_since: u32) -> u8 {
if (claimed == false) { return BS_QUEUED; }
if (seconds_since > BEE_QUIET_SECONDS) { return BS_QUIET; }
return BS_WORKING;
}
/// The filter the board, the game and the route all apply: a bit per kind and a bit per state, and 0
/// meaning "any". Repository and text are matched beside it; they are strings, and equality on
/// strings is the caller's.
pub fn task_matches(kind_mask: u32, state_mask: u32, kind: u8, state: u8) -> bool {
if (kind >= TASK_KINDS or state >= TASK_STATES) { return false; }
if (kind_mask != 0 and (kind_mask & (1 << kind)) == 0) { return false; }
if (state_mask != 0 and (state_mask & (1 << state)) == 0) { return false; }
return true;
}
/// Tasks one answer carries at most; the route pages past it.
pub const TASK_PAGE_MAX : u32 = 2000;
pub const TASK_PAGE_DEFAULT : u32 = 500;
test a_job_and_a_review_show_as_one_lifecycle {
assert job_state(0) == TS_RUNNING;
assert job_state(1) == TS_DONE;
assert job_state(2) == TS_FAILED;
assert job_state(3) == TS_DROPPED;
assert review_state(0) == TS_BACKLOG;
assert review_state(1) == TS_DONE;
assert review_state(2) == TS_DROPPED;
assert review_state(3) == TS_FAILED;
}
test every_state_has_an_a2a_state {
assert a2a_state(TS_BACKLOG) == A2A_SUBMITTED;
assert a2a_state(TS_RUNNING) == A2A_WORKING;
assert a2a_state(TS_BLOCKED) == A2A_INPUT_REQUIRED;
assert a2a_state(TS_REVIEW) == A2A_INPUT_REQUIRED;
assert a2a_state(TS_DONE) == A2A_COMPLETED;
assert a2a_state(TS_DROPPED) == A2A_CANCELED;
assert a2a_state(TS_FAILED) == A2A_FAILED;
}
test a_bee_is_queued_working_or_quiet {
assert bee_state(false, 0) == BS_QUEUED;
assert bee_state(false, 9999) == BS_QUEUED;
assert bee_state(true, 0) == BS_WORKING;
assert bee_state(true, BEE_QUIET_SECONDS) == BS_WORKING;
assert bee_state(true, BEE_QUIET_SECONDS + 1) == BS_QUIET;
}
test a_filter_narrows_and_zero_means_any {
assert task_matches(0, 0, TK_ISSUE, TS_RUNNING) == true;
assert task_matches(1 << TK_ISSUE, 0, TK_ISSUE, TS_DONE) == true;
assert task_matches(1 << TK_JOB, 0, TK_ISSUE, TS_DONE) == false;
assert task_matches(0, 1 << TS_RUNNING, TK_REVIEW, TS_RUNNING) == true;
assert task_matches(0, 1 << TS_RUNNING, TK_REVIEW, TS_BACKLOG) == false;
assert task_matches((1 << TK_ISSUE) | (1 << TK_JOB), (1 << TS_RUNNING) | (1 << TS_REVIEW), TK_JOB, TS_REVIEW) == true;
// an unknown kind or state matches nothing, even with no filter
assert task_matches(0, 0, TASK_KINDS, TS_DONE) == false;
assert task_matches(0, 0, TK_ISSUE, TASK_STATES) == false;
}
invariant the_states_are_the_board_columns {
assert TS_BACKLOG == 0 and TS_BLOCKED == 1 and TS_RUNNING == 2;
assert TS_REVIEW == 3 and TS_DONE == 4 and TS_DROPPED == 5 and TS_FAILED == 6;
assert TK_ISSUE == 0 and TK_REVIEW == 1 and TK_JOB == 2;
assert TASK_PAGE_DEFAULT <= TASK_PAGE_MAX;
}
Все уроки
Модуль 1 · Задача
Задача становится работой, только когда её оформили: недостающие разделы дописаны или запрошены, граница называет настоящие файлы, а один фильтр читает задачи всех видов.
Модуль 2 · Кто следующий
Порядок, в котором Королева берёт задачи: метка стареет на одну ступень, критичными идут не больше 3, и ничего нового не начинается, пока готовая работа ждёт ревью.
Модуль 3 · Жизнь пчелы
От кандидата до готовой работы: двенадцать состояний и шестнадцать событий, корабль в игре, который улетает домой, и деплой, который не обрывает пчелу.
Модуль 4 · Пчела-ревьюер
Готовую работу судят по своим часам: столько ревью сразу, чтобы успевать, пауза, которая удваивается для строки в ожидании, и ворота слияния, которые не открыть без проверок.
Модуль 5 · Затор ревью
Застрявший пулл-реквест всегда в одном из десяти случаев, у каждого свой ход Королевы, а красная проверка считается унаследованной, только если так говорит master.
Модуль 6 · Ключи
Ключ модели у пчелы могут отклонить: код в теле ответа сортирует отказ, временный отказ даёт ключу отдохнуть секунды, и пчела переходит к следующему свободному ключу.
Модуль 7 · Заслуги и деньги
Одолженный ключ не приносит заслуг, операция продаётся вдвое дороже своей цены в токенах по полцента, а токены сгорают через 30 дней после зачисления.
Модуль 8 · Агенты между собой
У каждого агента свой бот в одной группе: кого зовут, цепочка глубиной в три сообщения ботов и часы, которые не дают агентам завалить чат.
Модуль 9 · Ночь и доска
Что показывает улей: ночной дозор, который открывает, комментирует и закрывает задачи, колонки публичной доски и соты, которые вспыхивают на каждое событие.