Task Management System
Reported by candidates from Anthropic's online assessment. Pattern, common pitfall, and the honest play if you blank under the timer.
Anthropic's Task Management System OA, reported in August 2026, reads like a spec you'd get from a real ticket, not a puzzle. Nine opcodes, strictly increasing timestamps, and a quota that can drop below the active count without evicting anything. That last detail trips people. The hinted pattern is queue, because tasks expire in time order and you drain them before every operation. It's a simulation with a lot of small rules, and one missed rule fails hidden tests. If you blank on the structure, StealthCoder runs invisibly during the live OA and gives you a working skeleton to fall back on.
The problem
Implement a task-management service by processing a finite sequence of timestamped operations in order. Every operation begins with an opcode. Timestamps are strictly increasing. ["ADD_USER", t, userId, quota] creates a user with a maximum number of active tasks. ["CREATE", t, taskId, userId, priority, dueAt, expiresAt] creates an active task. It fails if the task identifier already exists, the user does not exist, or the user's active-task quota is full. ["GET", t, taskId] returns [taskId, userId, priority, createdAt, dueAt, expiresAt, status], or an empty row for a missing or deleted task. ["UPDATE", t, taskId, priority, dueAt, expiresAt] updates an active task. ["DELETE", t, taskId] marks an existing non-deleted task as deleted. ["SEARCH", t, userId] returns that user's active task identifiers ordered by decreasing priority, then increasing creation timestamp, then identifier. ["SET_QUOTA", t, userId, quota] changes a user's quota. Lowering it does not remove existing tasks, but new tasks remain blocked until the active count is below the quota. ["COMPLETE", t, taskId] marks an active task completed. ["HISTORY", t, userId, view] returns identifiers in increasing creation order. view is COMPLETED, EXPIRED, UNFINISHED, or OVERDUE. Unfinished tasks are active; overdue tasks are active tasks with dueAt < t. Before each operation at time t, every active task with expiresAt <= t becomes expired. Completion, deletion, and expiration free an active-task quota slot. Return one row per input operation. State-changing operations return ["OK"] on success. Failures return one of ["UNKNOWN_USER"], ["DUPLICATE_TASK"], ["QUOTA_EXCEEDED"], ["NOT_FOUND"], or ["NOT_ACTIVE"]. Search and history operations may return an empty row. Function processTaskOperations(operations: String[][]) → String[][] Examples Example 1 operations = [["ADD_USER","1","u1","2"],["CREATE","2","t1","u1","5","10","20"],["CREATE","3","t2","u1","7","4","30"],["SEARCH","5","u1"],["COMPLETE","6","t2"],["HISTORY","7","u1","COMPLETED"],["SET_QUOTA","8","u1","1"],["CREATE","9","t3","u1","9","12","40"],["GET","20","t1"]] return = [["OK"],["OK"],["OK"],["t2","t1"],["OK"],["t2"],["OK"],["QUOTA_EXCEEDED"],["t1","u1","5","2","10","20","EXPIRED"]] The higher-priority task is returned first. Completing it frees a quota slot, but the later quota reduction leaves one active task, so the next creation is rejected. The final read first expires t1. Constraints 1 <= operations.length <= 200000. All timestamps and task time fields are integers in [0, 10^9]; operation timestamps are strictly increasing. For every CREATE or UPDATE, operation timestamp < dueAt < expiresAt. User and task identifiers are nonempty ASCII strings of at most 40 characters. Priority is an integer in [-10^9, 10^9]; quota is in [0, 200000]. ADD_USER uses a new user identifier. SET_QUOTA, SEARCH, and HISTORY name an existing user. The total number of task records examined by all SEARCH and HISTORY operations is at most 200000.
Reported by candidates. Source: FastPrep
Pattern and pitfall
The trick is lazy expiration. Keep a min-heap keyed on expiresAt holding active tasks. Before every operation at time t, pop while top.expiresAt <= t, check the task is still active (it may have been completed, deleted, or updated), mark it EXPIRED, and decrement the user's active count. Updates change expiresAt, so push a new heap entry and skip stale ones by comparing against the task's current value. Store per-user active counts, plus a per-user list of task ids in creation order for HISTORY. SEARCH sorts the user's active tasks by priority descending, creation time, then id. The constraint caps total records examined at 200000, so a scan is fine. Pitfalls: SET_QUOTA never evicts, so compare count >= quota on CREATE. OVERDUE uses dueAt < t, strictly. Expire first, then handle the opcode. StealthCoder is your hedge if the live OA throws you off on stale heap entries.
Drill it cold or hedge it with StealthCoder. Either way, don't walk into the OA hoping you remember the trick.
You can drill Task Management System cold, or you can hedge it. StealthCoder runs invisibly during screen share and surfaces a working solution in under 2 seconds. The proctor sees the IDE. They don't see what's behind it. Made for the candidate who got the OA invite this morning and has 72 hours, not six months.
Get StealthCoderRelated leaked OAs
You've seen the question.
Make sure you actually pass Anthropic's OA.
Anthropic reuses patterns across OAs. Made for the candidate who got the OA invite this morning and has 72 hours, not six months. Works on HackerRank, CodeSignal, CoderPad, and Karat.
Task Management System FAQ
What's the trick in the Anthropic Task Management System OA?+
Expire lazily. Before every operation, pop a min-heap of expiresAt values until the top is in the future, and update status and quota counts. Everything else is dictionaries and careful rule-following. Do the expiry step first, always, or GET and HISTORY will return stale statuses.
How hard is this problem really?+
The algorithms are easy, the bookkeeping is not. There's no clever data structure beyond a heap. Difficulty comes from nine opcodes, six failure codes, and edge cases like lowering quota below the active count. Expect to lose points on small rule misses, not on complexity.
How do I handle UPDATE changing expiresAt?+
Push a fresh heap entry with the new expiresAt. When you pop an entry, compare it to the task's current expiresAt and its status. If either doesn't match, discard it. This avoids needing a heap with decrease-key or removal.
Do I need to worry about performance with 200000 operations?+
Not much. The heap gives O(log n) per operation, and the constraints cap total records examined by SEARCH and HISTORY at 200000. So sorting or scanning a user's tasks on each call is fine. Don't over-engineer an ordered index.
How should I prepare in 48 hours?+
Write a small version yourself: users map, tasks map, expiry heap, per-user creation-ordered list. Then test the example, especially the quota drop and the final expired GET. Practice returning the exact failure codes, since a wrong string fails a test even when the logic is right.