Skip to content

feat: accept unique job id prefixes#6

Open
Boulea7 wants to merge 5 commits into
mainfrom
codex/job-id-prefix-lookup
Open

feat: accept unique job id prefixes#6
Boulea7 wants to merge 5 commits into
mainfrom
codex/job-id-prefix-lookup

Conversation

@Boulea7
Copy link
Copy Markdown
Owner

@Boulea7 Boulea7 commented May 27, 2026

Summary

  • allow agy_status, agy_read, agy_result, and agy_cancel to resolve a full job_id or unique job-id prefix
  • add SessionStore prefix resolution with ambiguity errors instead of guessing
  • document prefix support across README variants, examples, and installed skill usage reference

Test plan

  • UV_CACHE_DIR=/private/tmp/agy-mcp-uv-cache uv --no-config run --index-url https://pypi.org/simple pytest tests/test_mcp_server.py tests/test_session_store.py -q
  • UV_CACHE_DIR=/private/tmp/agy-mcp-uv-cache uv --no-config run --index-url https://pypi.org/simple ruff check src/agy_mcp/server.py src/agy_mcp/session_store.py tests/test_mcp_server.py tests/test_session_store.py
  • git diff --check

Reference: inspired by gemini-plugin-cc/codex-plugin-cc status/result/cancel workflows, where short job references make result lookup less fragile.

Summary by Sourcery

Allow job metadata tools to accept full job IDs or unique prefixes and document this behavior across server, session store, and user-facing docs.

New Features:

  • Support resolving full job IDs or unique job-id prefixes in agy_status, agy_read, agy_result, and agy_cancel tools.
  • Add SessionStore support for resolving job references by exact ID or unique prefix with explicit ambiguity handling.

Enhancements:

  • Improve error handling for invalid or ambiguous job ID references with redacted, structured errors instead of guessing.

Documentation:

  • Document job-id prefix support and ambiguity behavior in all README variants, examples, and installed skill usage reference.

Tests:

  • Add tests covering unique and ambiguous job-id prefix resolution in both the MCP server tools and SessionStore.

Summary by cubic

Allow unique job_id prefixes in agy_status, agy_read, agy_result, and agy_cancel to make lookup easier, with stricter validation, clearer errors, and optimized resolution that short-circuits exact IDs and avoids scanning metadata. Synced docs across READMEs, examples, and both Claude and Codex skill usage to explain prefix support.

  • New Features

    • Tools accept a full job_id or a unique prefix (e.g., job_177986); ambiguous prefixes return success=false with a clear ambiguity error.
    • Added prefix resolution in the server and SessionStore with an optimized lookup; tests cover unique, ambiguous, bare-prefix, and lookup failure cases.
  • Bug Fixes

    • Hardened prefix handling: strict regex validation (rejects bare job_), simplified fallback that preserves exact-id not-found behavior, and structured, redacted errors when reference lookup fails.

Written for commit 43e96a1. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

  • New Features

    • Job-oriented tools (agy_status, agy_read, agy_result, agy_cancel) now accept job IDs as either full identifiers or unique prefixes for convenience.
    • Ambiguous prefixes matching multiple jobs return a structured error instead of guessing.
  • Documentation

    • Updated tool documentation to clarify job ID prefix support across all language variants and examples.

Review Change Stack

Change-Id: I5aa2b30645932d59288950d0e43cad788b43ff99
Copilot AI review requested due to automatic review settings May 27, 2026 08:01
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 27, 2026

Reviewer's Guide

Adds support for resolving job metadata tools by unique job_id prefixes, centralizing resolution/validation in SessionStore and server helpers, and documents prefix behavior across README variants and examples.

Sequence diagram for resolving job_id prefixes in metadata tools

sequenceDiagram
    actor Client
    participant agy_status_tool
    participant _resolve_job_id_reference
    participant SessionStore
    participant Supervisor

    Client->>agy_status_tool: agy_status_tool(job_id)
    agy_status_tool->>_resolve_job_id_reference: _resolve_job_id_reference(safety, store, job_id)
    _resolve_job_id_reference->>SessionStore: resolve_job_reference(reference)
    alt exact id exists
        SessionStore->>SessionStore: get_job(reference)
        SessionStore-->>_resolve_job_id_reference: JobRecord
    else unique prefix
        SessionStore->>SessionStore: list_jobs(limit=None)
        SessionStore-->>_resolve_job_id_reference: JobRecord
    else no match
        SessionStore-->>_resolve_job_id_reference: None
    else ambiguous prefix
        SessionStore--x _resolve_job_id_reference: ValueError("job_id reference is ambiguous ...")
    end
    alt resolved job_id
        _resolve_job_id_reference-->>agy_status_tool: (job_id, None)
        agy_status_tool->>Supervisor: status(job_id)
        Supervisor-->>agy_status_tool: JobRecord | None
        agy_status_tool-->>Client: StatusToolResponse
    else error
        _resolve_job_id_reference-->>agy_status_tool: (None, error)
        agy_status_tool-->>Client: StatusToolResponse(success=False)
    end
Loading

File-Level Changes

Change Details Files
Introduce shared job_id reference validation and resolution in the MCP server so job tools accept full IDs or unique prefixes with clear failure modes.
  • Add a relaxed job-id reference regex permitting zero or more suffix characters for prefix lookups.
  • Implement _validate_job_id_reference to enforce length/shape/secret checks on job references distinct from full IDs.
  • Implement _resolve_job_id_reference to call SessionStore.resolve_job_reference, surface ambiguity errors, and fall back to the old exact-ID-not-found behavior.
  • Wire agy_status, agy_read, agy_result, and agy_cancel through _resolve_job_id_reference, updating error messages, logging context, and returned job_id fields to use the resolved ID when available.
src/agy_mcp/server.py
tests/test_mcp_server.py
Extend SessionStore with first-class job reference resolution by exact ID or unique prefix, rejecting invalid or ambiguous references.
  • Add a job-id prefix regex and _validate_job_reference to constrain reference format before lookup.
  • Implement SessionStore.resolve_job_reference to return exact matches via get_job, otherwise search list_jobs for prefix matches, raising on ambiguity and returning None on no match.
  • Add tests covering successful exact/prefix resolution and ambiguous prefix errors.
src/agy_mcp/session_store.py
tests/test_session_store.py
Document job_id prefix support for metadata tools across user-facing docs and examples.
  • Update Chinese, English, Japanese, and Traditional Chinese READMEs to mention that agy_status, agy_read, agy_result, and agy_cancel accept unique job_id prefixes.
  • Expand the examples doc to describe prefix usage and ambiguity behavior for the metadata tools.
  • Update the installed Claude skill usage reference to mention prefix support and ambiguity errors.
README.md
docs/README_EN.md
docs/README_JA.md
docs/README_ZH-TW.md
docs/examples.md
src/agy_mcp/_skill_bodies/claude/references/usage.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 27, 2026

📝 Walkthrough

Walkthrough

This PR adds job-id prefix resolution to the MCP server, enabling users to reference long-running jobs by either their full ID or a unique prefix. The implementation adds a SessionStore.resolve_job_reference method and applies prefix resolution across four job-management tools: agy_status, agy_read, agy_result, and agy_cancel. Documentation is updated across all supported languages to clarify prefix behavior and error handling.

Changes

Job ID Prefix Support

Layer / File(s) Summary
Session store job reference resolution foundation
src/agy_mcp/session_store.py, tests/test_session_store.py
Introduces _JOB_ID_PREFIX_RE regex for validating job-id references, a _validate_job_reference validator function, and the new SessionStore.resolve_job_reference(reference) method that resolves either an exact job ID or a unique prefix by scanning stored records; raises ValueError on ambiguous matches and returns None on no match. Unit tests verify successful resolution and ambiguity detection.
Server helpers and agy_status tool with prefix support
src/agy_mcp/server.py, tests/test_mcp_server.py
Adds server-side _JOB_ID_REFERENCE_PATTERN regex, _validate_job_id_reference and _resolve_job_id_reference helper functions to validate and resolve prefixes via the session store. Updates agy_status_tool to resolve the job_id reference before querying supervisor status and improves not-found error messages. Integration tests verify that unique prefixes correctly resolve to stored jobs and that ambiguous prefixes return structured failure envelopes.
agy_read, agy_result, agy_cancel tools with prefix support
src/agy_mcp/server.py
Updates agy_read_tool, agy_result_tool, and agy_cancel_tool to resolve job_id references (full ID or prefix) before job lookup, event reading, or cancellation. Each tool passes the resolved ID to downstream operations and returns responses keyed by the resolved ID. Tool descriptions are updated to document the prefix-capable job_id input semantics.
Documentation and usage guides
README.md, docs/README_EN.md, docs/README_JA.md, docs/README_ZH-TW.md, docs/examples.md, src/agy_mcp/_skill_bodies/claude/references/usage.md
Updates all README variants and example/usage documentation to explicitly state that agy_status, agy_read, agy_result, and agy_cancel accept job_id as either a full ID or unique prefix; clarifies that ambiguous prefixes (matching multiple jobs) return structured success=false errors instead of guessing.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • Boulea7/agy-mcp#2: Earlier implementation of agy_result tool that this PR extends with job-id prefix resolution capability.

Poem

🐰 With prefixes now, the jobs align,
No need for full IDs every time—
Just start with a few, if unique they stay,
The tools resolve paths the swift rabbit way! 🌙

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 41.18% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: accept unique job id prefixes' clearly and concisely summarizes the main change—adding support for job ID prefix resolution across multiple tools.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/job-id-prefix-lookup

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • The job-id regexes are now duplicated between server.py and session_store.py (_JOB_ID_PATTERN / _JOB_ID_REFERENCE_PATTERN vs _JOB_ID_RE / _JOB_ID_PREFIX_RE); consider centralizing these patterns (or at least their definitions) to avoid drift between layers.
  • SessionStore.resolve_job_reference currently calls list_jobs(limit=None) and then filters in Python; if stores can grow large, you may want a more targeted lookup (e.g., early exit after finding >1 match or an optimized listing) to avoid scanning the full job set for every prefix resolution.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The job-id regexes are now duplicated between `server.py` and `session_store.py` (`_JOB_ID_PATTERN` / `_JOB_ID_REFERENCE_PATTERN` vs `_JOB_ID_RE` / `_JOB_ID_PREFIX_RE`); consider centralizing these patterns (or at least their definitions) to avoid drift between layers.
- `SessionStore.resolve_job_reference` currently calls `list_jobs(limit=None)` and then filters in Python; if stores can grow large, you may want a more targeted lookup (e.g., early exit after finding >1 match or an optimized listing) to avoid scanning the full job set for every prefix resolution.

## Individual Comments

### Comment 1
<location path="src/agy_mcp/session_store.py" line_range="41" />
<code_context>
 # anything that could traverse out of the store root. Generated ids satisfy
 # this regex (see generate_job_id).
 _JOB_ID_RE = re.compile(r"^job_[A-Za-z0-9_-]{1,80}$")
+_JOB_ID_PREFIX_RE = re.compile(r"^job_[A-Za-z0-9_-]{0,80}$")


</code_context>
<issue_to_address>
**suggestion:** Consider disallowing the empty string as a job reference at the store level for consistency and to avoid pathological prefixes.

The server-side `_validate_job_id_reference` rejects empty references, but `_JOB_ID_PREFIX_RE` allows them via `{0,80}`. If `resolve_job_reference` is called with `""`, `record.job_id.startswith(reference)` will match every job, likely causing an unnecessary full scan and an "ambiguous" error. To align behavior and avoid this edge case, either change the prefix regex to `{1,80}` or add an explicit `if not reference: raise ValueError(...)` in `_validate_job_reference`.

```suggestion
_JOB_ID_PREFIX_RE = re.compile(r"^job_[A-Za-z0-9_-]{1,80}$")
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/agy_mcp/session_store.py Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for addressing background jobs by either a full job_id or a unique job_id prefix across the MCP metadata tools, and documents that behavior across user-facing READMEs and skill usage docs.

Changes:

  • Add SessionStore.resolve_job_reference() to resolve exact IDs or unique prefixes, with explicit ambiguity errors.
  • Update agy_status, agy_read, agy_result, and agy_cancel to accept and resolve unique job_id prefixes.
  • Add tests for unique/ambiguous prefix handling and update documentation to describe the new behavior.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/agy_mcp/session_store.py Adds job-id prefix validation and resolve_job_reference() to map prefixes to stored jobs.
src/agy_mcp/server.py Adds server-side validation + prefix resolution plumbing for job metadata tools.
tests/test_session_store.py Adds unit tests for exact and ambiguous prefix resolution in SessionStore.
tests/test_mcp_server.py Adds integration tests ensuring tools accept unique prefixes and reject ambiguous ones.
src/agy_mcp/_skill_bodies/claude/references/usage.md Documents prefix support and ambiguity behavior for metadata tools.
README.md Documents prefix support for job metadata tools (ZH).
docs/README_ZH-TW.md Documents prefix support for job metadata tools (ZH-TW).
docs/README_JA.md Documents prefix support for job metadata tools (JA).
docs/README_EN.md Documents prefix support for job metadata tools (EN).
docs/examples.md Adds examples/notes describing prefix support and ambiguity errors.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/agy_mcp/session_store.py Outdated
# anything that could traverse out of the store root. Generated ids satisfy
# this regex (see generate_job_id).
_JOB_ID_RE = re.compile(r"^job_[A-Za-z0-9_-]{1,80}$")
_JOB_ID_PREFIX_RE = re.compile(r"^job_[A-Za-z0-9_-]{0,80}$")
Comment thread src/agy_mcp/session_store.py Outdated
Comment on lines +356 to +363
matches = [
record for record in self.list_jobs(limit=None)
if record.job_id.startswith(reference)
]
if len(matches) > 1:
raise ValueError("job_id reference is ambiguous; pass a longer job_id")
return matches[0] if matches else None

Comment thread src/agy_mcp/server.py Outdated
# (Phase 5 R3 security P2).
_MAX_JOB_ID_LEN = 84
_JOB_ID_PATTERN = re.compile(r"^job_[A-Za-z0-9_-]{1,80}$")
_JOB_ID_REFERENCE_PATTERN = re.compile(r"^job_[A-Za-z0-9_-]{0,80}$")
Comment thread src/agy_mcp/server.py
try:
record = store.resolve_job_reference(reference)
except ValueError as exc:
return None, safety.redact(str(exc))
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/agy_mcp/_skill_bodies/claude/references/usage.md`:
- Around line 68-71: The packaged copy of
src/agy_mcp/_skill_bodies/claude/references/usage.md diverges from the source;
check for duplicate copies and packaging steps that copy or transform this file
by searching the repo for other usage.md instances and references to usage.md in
build scripts (as suggested by the provided shell commands), compare the
contents of any matches to the source file, and update either the packaging
script or the out-of-source copy so the packaged copy matches the canonical
file; ensure any install/build step (e.g., a packaging/prepare script, MANIFEST,
setup.cfg/pyproject.toml include/exclude rules) references the correct path and
that CI uses the same source before committing the synchronized change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ce157d40-e26a-4610-90a3-b432b47e81b2

📥 Commits

Reviewing files that changed from the base of the PR and between 6d619b0 and dd1a257.

📒 Files selected for processing (10)
  • README.md
  • docs/README_EN.md
  • docs/README_JA.md
  • docs/README_ZH-TW.md
  • docs/examples.md
  • src/agy_mcp/_skill_bodies/claude/references/usage.md
  • src/agy_mcp/server.py
  • src/agy_mcp/session_store.py
  • tests/test_mcp_server.py
  • tests/test_session_store.py

Comment on lines +68 to +71
The metadata tools accept a full `job_id` or a unique prefix. For example,
`agy_status("job_177986")` resolves to the matching stored job when exactly
one id starts with that prefix; ambiguous prefixes return `success=false`
with an explicit ambiguity error.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Investigate the pipeline drift test failure.

The CI pipeline reports a content mismatch between the source file and the packaged copy. The drift test indicates "additional/changed paragraph about job_id handling present in packaged copy." This suggests the build or packaging step may not be syncing the latest documentation correctly.

Run the following script to check if there are multiple copies of this file that need to be synchronized:

#!/bin/bash
# Find all copies of usage.md in the repository
fd -t f 'usage.md' --exec echo "Found: {}"

# Check if there's a build/packaging script that copies this file
rg -n 'usage\.md' --type=python --type=toml --type=yaml -C 3
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/agy_mcp/_skill_bodies/claude/references/usage.md` around lines 68 - 71,
The packaged copy of src/agy_mcp/_skill_bodies/claude/references/usage.md
diverges from the source; check for duplicate copies and packaging steps that
copy or transform this file by searching the repo for other usage.md instances
and references to usage.md in build scripts (as suggested by the provided shell
commands), compare the contents of any matches to the source file, and update
either the packaging script or the out-of-source copy so the packaged copy
matches the canonical file; ensure any install/build step (e.g., a
packaging/prepare script, MANIFEST, setup.cfg/pyproject.toml include/exclude
rules) references the correct path and that CI uses the same source before
committing the synchronized change.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 10 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/agy_mcp/server.py
Comment thread src/agy_mcp/session_store.py Outdated
Boulea7 added 3 commits May 27, 2026 16:11
Change-Id: Ie26683c8529026a4471b36da6cca7d5c105b2717
Change-Id: I2732d7c75f71c5c6dcfbd1ef3ecd1c959a24858d
Change-Id: I17c43d41da0dbaca7b9c79b14ca2ffb84526689a
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 4 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread src/agy_mcp/server.py Outdated
Change-Id: I7b60e129caaa8bbb44e5dc531eee1586adf446c8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants