Repository navigation
Closed
Labels
app/mcpxPackage/app: mcpx (pkgs/ or apps/ in this repo)Package/app: mcpx (pkgs/ or apps/ in this repo)effort/mMedium: expected under 1 day of workMedium: expected under 1 day of workkind/enhancementmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)Ordinary priority (the default)source/design-architectFiled by the repo design architect jobFiled by the repo design architect jobtask/triageQueue packet kind: verify, reproduce, and route this itemQueue packet kind: verify, reproduce, and route this item
Description
Phase 1 of design #2497 (mcpx tasks, bounded — operational limits, cooperative cancel, audit, and the small truths). Design doc: files/designs/code-mcpx-tasks-operational-limits.md in the keep-the-four-repos-healthy goal workspace. The decisions are recorded on #2497; this phase implements its first slice. Independent of Phase 2.
Scope
Limits in the store, keyed by requestor, valued in protoTasks.*:
Store.Start(internal/tasks/tasks.go:355) gains a requestor key (optional parameter / options field). Every creation site passes what it holds: the MCP seam (internal/mcpserver/tasks.gostartTask, which already trackstaskOwners), the modern-task seam, and the daemon's/v1Start sites (internal/daemon/ops.go:525,routes_proto.go:434,routes_exec.go:245,input_required.go:100). The empty key is a real bucket named "unbound", capped like any other — never a bypass.protoTasks.maxTTL(duration, default 1h) ininternal/settings/prototasks.go: a requested TTL above the cap is clamped, not refused; the stored/returned task shows the capped TTL. Default TTL (10m) unchanged.protoTasks.maxPerRequestor(int, default 32): concurrent non-terminal tasks per requestor key, counted in the store. Creation beyond the cap is refused at the seam with a named error (-32603 on MCP, 429 on /v1) naming the limit.protoTasks.perMinute(int, default 120, 0 disables): one fixed-window counter per requestor key over alltasks/*method calls (get/list/result/update/cancel), counted on admission at the two dispatch seams (MCP tasks handler, daemon /v1 task routes); refusal shaped like the cap refusal. Use a shared fixed-window limiter type if one has landed from Design: mcpx upstream question rate limits — one limiter at the client choke point, keyed by the configured server #2333/design(mcpx): completion, finished — one rate limit at the /v1 choke point, relevance-ranked local answers #2386 by implementation time; otherwise keep the copy local to the tasks seams — do not build a general rate-limit framework. (Design-doc open question: triage may exempttasks/resultlong polls from the window if it can say why in one sentence on this issue.)NewID(tasks.go:344) moves from 8 to 16 random bytes (128 bits).
Acceptance
- A task requested with a TTL above
protoTasks.maxTTLruns with the capped TTL, and the returned task object shows the capped value, on both the MCP and /v1 surfaces - The 33rd concurrent non-terminal task for one requestor key is refused with the named error while another requestor's creation still succeeds; the unbound bucket is capped the same way
-
tasks/*calls beyondprotoTasks.perMinutefor one requestor are refused with the named error / 429; 0 disables the window - Every
Store.Startcall site in the tree passes a requestor key or is explicitly the unbound bucket (grep-verifiable) - New task IDs are 128-bit; existing ID parsing/lookup is unaffected
- The conformance gap rows
tasks-resource-limitsandtasks-rate-limitininternal/conformance/coverage_stateful.goare retired (or reworded to name what remains) - Tests run via CI per fleet policy (no builds on the sandbox)
Out of scope: cooperative cancel and statusMessage (Phase 2), audit logging and docs (Phase 3), per-server (upstream) concurrency caps, any change to task shapes on the wire.
🤖 Design-architect pass 17 — agent note: triage this phase against design #2497's recorded decisions; do not re-derive the limit values or the clamp-vs-refuse choice in triage.
Acceptance criteria
-
Store.Starttakes a requestor key from every creation seam (MCP startTask, modern-task seam, the four /v1 Start sites); the empty key is the cappedunboundbucket, never a bypass -
protoTasks.maxTTL(default 1h) clamps requested TTLs (stored/returned task shows the capped TTL);protoTasks.maxPerRequestor(default 32) refuses creation beyond the cap with a named error (-32603 MCP / 429 /v1);protoTasks.perMinute(default 120, 0 disables) windows all tasks/* calls per requestor - Tests pin clamp-not-refuse for TTL, refusal naming the limit for the cap, and the unbound bucket being capped like any other
Metadata
Metadata
Assignees
Labels
app/mcpxPackage/app: mcpx (pkgs/ or apps/ in this repo)Package/app: mcpx (pkgs/ or apps/ in this repo)effort/mMedium: expected under 1 day of workMedium: expected under 1 day of workkind/enhancementmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)Ordinary priority (the default)source/design-architectFiled by the repo design architect jobFiled by the repo design architect jobtask/triageQueue packet kind: verify, reproduce, and route this itemQueue packet kind: verify, reproduce, and route this item
Activity
developing-today commentedon Oct 30, 2026
CODE-1275
dezren39 commentedon Oct 30, 2026
🤖 agent-note:v1 — design-architect pass 17 (2026-10-29). Phase 1 of design #2497. Triage packet enqueued: pilot task 3733 (queue=repo-health-code-pilot, status=queued, verified; packet self-corrected once in-pass for a stale template acceptance line — the live payload is the corrected one). Triage: confirm scope against current main per #2497, do not re-litigate its recorded decisions, enqueue the implementation follow-up with this issue's acceptance criteria intact.
dezren39 commentedon Oct 30, 2026
Intake review
Related: #2497 (design), #2499 (Phase 2, independent), #2500 (Phase 3 — audits these refusals), #2387/#2388 (the completion-limiter phases of #2386 — sibling fixed-window pattern)
Notes: Phase 1 of the #2497 design: requestor key, TTL clamp, per-requestor cap, and tasks/* window in the task store, valued in
protoTasks.*settings. Already fully labelled by the filer. This pass appends acceptance criteria and marks enriched.Risks: A creation seam missed (four /v1 sites are listed) leaves an uncapped path that makes the limits decorative; the empty-key bucket is the easiest seam to get wrong.
Suggested approach: Add the settings + store counting first, then wire each creation seam in the body's list one by one with a test per seam; verify via CI.
🤖 Agent note · filed
meta/enrichedapplied; acceptance criteria appended to the body only where no acceptance section existed (original body preserved verbatim above it). Still-live check this pass: no merged PR or fix commit explicitly resolving this issue was found in this pass's search.298 remaining items
dezren39 commentedon Oct 31, 2026
🤖 Agent note · parked
dezren39 commentedon Oct 31, 2026
🤖 Agent note · picked up
0dd640fea: rechecked CI + Codex fresh. Codex clean at exact head (receipt 19:38Z, has_unresolved_findings=false); 25/25 review threads resolved. CI: lint pass, plugin tests pass, docs build pass; tasks/mcpserver/daemon packages pass under stress (race/shuffle/repeat). Stress red is only the pre-attributed clean-main breakage (settings effect/scriptenv/consumed/compendium guards + completion-max-100, tracked mcpx: three internal/settings guard tests fail on main (compendium chapter + undeclared adapter env) #2697/mcpx: internal/settings (scriptenv) and internal/conformance (TestAuthSplit, TestMatrix) failing on clean main #2716/mcpx: internal/settings tests red on clean main — TESTING.md missing from compendium manifest, model.* settings lack effect probes, env doc drift #2846) — fresh log analysis this shift: every named violation is outside this PR's diff, and effect.go only adds the three protoTasks exemptions. Merging under the standing criteria per the previous shift's resume condition.Merge pull request #2869 from developing-today/queue/3985-2498-task-s…
dezren39 commentedon Oct 31, 2026
🤖 Agent note · done
4f5236ede) — mcpx task-store limits for mcpx: Phase 1 of #2497 — limits in the task store: requestor key, TTL clamp, per-requestor cap, tasks/* window, 128-bit IDs #2498: requestor key + TTL clamp + per-requestor cap (32) + tasks/* admission window (120/min, 0 disables) + 128-bit IDs; conformance rows tasks-rate-limit / tasks-resource-limits retired.0dd640fea: Codex clean (receipt at exact head, has_unresolved_findings=false); 25/25 review threads resolved; lint + plugin tests + docs build pass; internal/tasks, internal/mcpserver, internal/daemon pass under stress (race/shuffle/repeat). Stress-job red is solely the pre-attributed clean-main breakage (settings effect/scriptenv/consumed/compendium guards, completion-max-100 — mcpx: three internal/settings guard tests fail on main (compendium chapter + undeclared adapter env) #2697/mcpx: internal/settings (scriptenv) and internal/conformance (TestAuthSplit, TestMatrix) failing on clean main #2716/mcpx: internal/settings tests red on clean main — TESTING.md missing from compendium manifest, model.* settings lack effect probes, env doc drift #2846); fresh log analysis confirmed every named violation sits outside this PR's diff and effect.go only adds the protoTasks exemptions.