Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 2 additions & 9 deletions apps/mcp-server/src/tools/task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
classifyClaimAge,
guardedClaimFile,
listPlans,
liveFileContentionsForClaim,
} from '@colony/core';
import { claimPathRejectionMessage } from '@colony/storage';
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
Expand Down Expand Up @@ -396,12 +395,6 @@ export function register(server: McpServer, ctx: ToolContext): void {
);
}
const previous = store.storage.getClaim(task_id, normalizedFilePath);
const liveContentions = liveFileContentionsForClaim(store, {
task_id,
session_id,
file_path: normalizedFilePath,
assume_requester_live: true,
});
const guarded = guardedClaimFile(store, {
task_id,
session_id,
Expand Down Expand Up @@ -453,8 +446,8 @@ export function register(server: McpServer, ctx: ToolContext): void {
file_path: normalizedFilePath,
claim_status: guarded.status,
claim_task_id: guarded.claim_task_id ?? task_id,
warning: liveContentions[0] ?? null,
live_file_contentions: liveContentions,
warning: null,
live_file_contentions: [],
overlap: previousClaim?.overlap ?? 'none',
previous_claim: previousClaim,
});
Expand Down
21 changes: 21 additions & 0 deletions apps/mcp-server/test/task-threads.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,27 @@ describe('task threads — file claims', () => {
expect(claim?.metadata).toContain('"file_path":"src/viewer.tsx"');
});

it('keeps uncontended task_claim_file calls under the hot-path budget', async () => {
const repoRoot = mkdtempSync(join(dir, 'repo-'));
mkdirSync(join(repoRoot, 'src'), { recursive: true });
const { task_id, sessionA } = seedTwoSessionTask(repoRoot);
const durations: number[] = [];

for (let i = 0; i < 40; i += 1) {
const started = performance.now();
const result = await call<{ live_file_contentions: unknown[] }>('task_claim_file', {
task_id,
session_id: sessionA,
file_path: `src/hot-path-${i}.ts`,
});
durations.push(performance.now() - started);
expect(result.live_file_contentions).toEqual([]);
}

const p95 = [...durations].sort((a, b) => a - b)[Math.floor(durations.length * 0.95)] ?? 0;
expect(p95).toBeLessThan(100);
});

it('rejects pseudo task_claim_file paths with a pseudo-specific message', async () => {
const { task_id, sessionA } = seedTwoSessionTask();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-05-15
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
## Why

`task_claim_file` runs on the edit hot path. `colony gain` showed an average
runtime above 3 seconds, and the MCP handler always performed the full live
file contention scan even for ordinary uncontended claims where that payload is
empty.

## What Changes

- Remove the unconditional live-contention scan from successful
`task_claim_file` responses.
- Keep the guarded claim decision as the authority for blocking active owners,
stale claims, protected branches, and same-session refreshes.
- Return the existing response shape with `warning: null` and
`live_file_contentions: []` for successful claims.

## Impact

- Cuts one repo-wide task/claim scan and OMX active-session read from the common
claim path.
- Preserves existing hard-block behavior for active owners through
`guardedClaimFile`.
- Adds a focused hot-path budget test for uncontended claim batches.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
## ADDED Requirements

### Requirement: task_claim_file avoids live-contention scans on successful claims
The `task_claim_file` MCP handler SHALL avoid the repo-wide live file
contention scan when `guardedClaimFile` returns a successful claim status. For
successful claims it SHALL preserve the response shape with `warning: null` and
`live_file_contentions: []`. The guarded claim decision SHALL remain responsible
for hard failures such as active owners, protected branch rejection, invalid
paths, and takeover recommendations.

#### Scenario: Uncontended claim returns compact success
- **GIVEN** a task has no competing scoped claim for `file_path=F`
- **WHEN** `task_claim_file` is called for `F`
- **THEN** the claim succeeds
- **AND** the response contains `warning: null`
- **AND** the response contains `live_file_contentions: []`

#### Scenario: Active owner still blocks
- **GIVEN** another active session owns a scoped claim for `file_path=F`
- **WHEN** `task_claim_file` is called for `F`
- **THEN** the handler returns `CLAIM_HELD_BY_ACTIVE_OWNER`
- **AND** no successful claim is recorded for the requester
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
## Definition of Done

This change is complete only when **all** of the following are true:

- Every checkbox below is checked.
- The agent branch reaches `MERGED` state on `origin` and the PR URL + state are recorded in the completion handoff.
- If any step blocks (test failure, conflict, ambiguous result), append a `BLOCKED:` line under section 4 explaining the blocker and **STOP**. Do not tick remaining cleanup boxes; do not silently skip the cleanup pipeline.

## Handoff

- Handoff: change=`agent-codex-speed-up-task-claim-file-2026-05-15-15-39`; branch=`agent/codex/speed-up-task-claim-file-2026-05-15-15-39`; scope=`skip live-contention scan on successful task_claim_file`; action=`continue this sandbox or finish cleanup after a usage-limit/manual takeover`.
- Copy prompt: Continue `agent-codex-speed-up-task-claim-file-2026-05-15-15-39` on branch `agent/codex/speed-up-task-claim-file-2026-05-15-15-39`. Work inside the existing sandbox, review `openspec/changes/agent-codex-speed-up-task-claim-file-2026-05-15-15-39/tasks.md`, continue from the current state instead of creating a new sandbox, and when the work is done run `gx branch finish --branch agent/codex/speed-up-task-claim-file-2026-05-15-15-39 --base main --via-pr --cleanup`.

## 1. Specification

- [x] 1.1 Finalize proposal scope and acceptance criteria for `agent-codex-speed-up-task-claim-file-2026-05-15-15-39`.
- [x] 1.2 Define normative requirements in `specs/speed-up-task-claim-file/spec.md`.

## 2. Implementation

- [x] 2.1 Implement scoped behavior changes.
- [x] 2.2 Add/update focused regression coverage.

## 3. Verification

- [x] 3.1 Run targeted project verification commands.
- [x] 3.2 Run `openspec validate agent-codex-speed-up-task-claim-file-2026-05-15-15-39 --type change --strict`.
- [x] 3.3 Run `openspec validate --specs`.

## 4. Cleanup (mandatory; run before claiming completion)

- [ ] 4.1 Run the cleanup pipeline: `gx branch finish --branch agent/<your-name>/<branch-slug> --base dev --via-pr --wait-for-merge --cleanup`. This handles commit -> push -> PR create -> merge wait -> worktree prune in one invocation.
- [ ] 4.2 Record the PR URL and final merge state (`MERGED`) in the completion handoff.
- [ ] 4.3 Confirm the sandbox worktree is gone (`git worktree list` no longer shows the agent path; `git branch -a` shows no surviving local/remote refs for the branch).
Loading