Skip to content

feat(items): accept sequence_id in item/claim tools; switch id generation to nanoid - #257

Merged
getappz merged 3 commits into
masterfrom
task/184
Jul 18, 2026
Merged

getappz merged 3 commits into
masterfrom
task/184

Conversation

@getappz

@getappz getappz commented Jul 18, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • item/claim MCP tools now accept either a UUID or a numeric sequence_id (bare or #-prefixed) wherever an item id is taken — get, update, update_state, delete, claim, heartbeat, release, done, add_label, remove_label, and claim's target param. Resolved via agentflare_backend::item::resolve_id, scoped to the repo's linked project. Not-found numeric ids return the same shape as an unmatched UUID. Closes feat(gateway): put lean-ctx behind the gateway, rename gateway_search/execute to tool_search/tool_execute #184.
  • Switches db_kit::ids::new_id() from uuid::Uuid::now_v7() to nanoid::nanoid!(), with every caller updated (agentflare-artifacts, and agentflare-backend's asset/comment/label/project/state/webhook/workspace).

Test plan

  • cargo build --workspace --all-features — clean
  • cargo test --workspace — 630+ tests passing across the bin and every crate, 0 failed
  • cargo fmt --check — clean
  • cargo clippy --workspace --all-features -- -D warnings -A unsafe_code -A clippy::pedantic — clean (excluding the pre-existing Windows-only agent_launch.rs test-import warning, already tracked separately as item handoff: assign items + attach versioned assets instead of raw artifacts #169, unrelated to this change)

Summary by CodeRabbit

  • New Features

    • Item actions and claim operations now accept numeric item sequence IDs in addition to canonical item IDs.
    • Claim targets using item sequence IDs are automatically translated to canonical IDs.
    • Item/claim-related responses now consistently return the resolved canonical item ID.
  • Improvements

    • Newly created records now use shorter, consistent identifiers.
    • Artifact filenames are normalized using item slugification (not just lowercasing).
    • MCP documentation now clearly describes supported item and claim identifier formats.

…neration to nanoid

item/claim MCP tools (get, update, update_state, delete, claim, heartbeat,
release, done, add_label, remove_label; claim's target param) now accept
either a UUID or a numeric sequence_id (bare or #-prefixed), resolved via
agentflare_backend::item::resolve_id scoped to the repo's linked project.
Not-found numeric ids return the same not-found shape as an unmatched UUID.
Closes #184.

Also switches db_kit::ids::new_id() from uuid::Uuid::now_v7() to
nanoid::nanoid!(), updating every caller across agentflare-artifacts and
agentflare-backend (asset/comment/label/project/state/webhook/workspace).

cargo build --workspace --all-features, cargo test --workspace (630+
passing across the bin plus every crate), cargo fmt --check, and cargo
clippy --workspace --all-features -D warnings all clean (the one remaining
clippy hit is the pre-existing Windows-only agent_launch.rs test import,
tracked separately as item #169, unrelated to this change).
@coderabbitai

coderabbitai Bot commented Jul 18, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6f372080-6261-49a2-8ba6-23cf5d04c7fe

📥 Commits

Reviewing files that changed from the base of the PR and between 5817ec2 and 113ee63.

📒 Files selected for processing (4)
  • crates/agentflare-backend/src/item.rs
  • src/mcp_server/item.rs
  • src/mcp_server/tests/artifact_tests.rs
  • src/mcp_server/tests/item_tests.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/agentflare-backend/src/item.rs

📝 Walkthrough

Walkthrough

The change replaces UUID-based generation with NanoID-backed identifiers, adds sequence-ID resolution for items, routes MCP item and claim actions through canonical IDs, and updates related tests and schema descriptions.

Changes

Identifier migration and MCP resolution

Layer / File(s) Summary
NanoID-backed identifier generation
crates/agentflare-artifacts/*, crates/agentflare-backend/Cargo.toml, crates/agentflare-backend/src/{asset,comment,item,label,project,state,webhook,workspace}.rs, crates/agentflare-db-kit/*
Artifact and backend identifier generation now uses nanoid::nanoid!() directly or through db_kit::ids::new_id(), and affected UUID dependencies are removed.
Canonical item and claim resolution
crates/agentflare-backend/src/item.rs, src/mcp_server/{item,claim}.rs
Numeric item identifiers are resolved as sequence_id values, while MCP item and claim actions pass canonical item IDs to backend operations.
Validation and schema updates
src/mcp_server/tests/{action_tests,artifact_tests,item_tests}.rs, src/mcp_server/types.rs
Tests cover sequence-ID resolution, unknown identifiers, slugified asset filenames, and runtime identifier ordering; MCP descriptions document UUID and numeric sequence-ID inputs.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MCPClient
  participant AgentflareMcp
  participant ItemResolver
  participant BackendAction
  MCPClient->>AgentflareMcp: submit item or claim action
  AgentflareMcp->>ItemResolver: resolve UUID or sequence_id
  ItemResolver-->>AgentflareMcp: return canonical item ID
  AgentflareMcp->>BackendAction: execute action with canonical item ID
  BackendAction-->>MCPClient: return action result
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR does not implement linked issue #184's LeanCtx gateway integration or tool_search/tool_execute rename; it instead changes item IDs and NanoID generation. Rework the PR to address #184: add LeanCtx gateway registration, remove duplicate native config, rename the gateway tools, and add the fallback guidance/checks.
Out of Scope Changes check ⚠️ Warning The diff is largely unrelated to the linked issue, replacing UUIDs with NanoIDs and adding sequence_id resolution instead of LeanCtx gateway work. Split the item/claim sequence_id and NanoID changes into a separate PR, or retarget this one to the LeanCtx gateway scope in #184.
Docstring Coverage ⚠️ Warning Docstring coverage is 56.52% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main changes: sequence_id support for item/claim tools and NanoID-based ID generation.
Description check ✅ Passed The description covers Summary and Test plan with concrete details; it only omits the optional reviewer notes section.
✨ 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 task/184

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 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 `@crates/agentflare-backend/src/comment.rs`:
- Line 41: Update comment ID generation in the comment persistence flow around
new_id so IDs retain insertion-time ordering, or introduce and populate an
explicit monotonic insertion-order column used by the is_latest query. Ensure
the created_at DESC, id DESC ordering cannot misclassify comments created within
the same second.

In `@crates/agentflare-backend/src/item.rs`:
- Around line 197-218: Normalize the input in the sequence-resolution function
before the `parse::<i64>()` branch by removing one leading `#` prefix, then
parse and query using the normalized value while preserving the existing
direct-ID fallback for non-numeric identifiers.
- Around line 192-221: Update item action handlers in src/mcp_server/item.rs so
every backend operation accepting an item ID first passes the supplied
identifier through agentflare_backend::item::resolve_id, including item_get’s
current direct get call. Use the resolved UUID for subsequent backend operations
while preserving project scoping and existing behavior for UUID inputs.

In `@src/mcp_server/item.rs`:
- Around line 147-154: Update resolve_item_id to remove exactly one leading “#”
from id_or_seq before calling agentflare_backend::item::resolve_id, while
leaving canonical IDs and unprefixed sequence IDs unchanged. Add regression
coverage confirming mutation resolution accepts the documented “#<sequence_id>”
form.

In `@src/mcp_server/types.rs`:
- Around line 570-574: Update item_get to pass the requested ID through
resolve_item_id before calling get, so numeric IDs resolve against the current
project’s sequence_id while canonical UUIDs remain supported. Preserve the
existing get behavior after resolution and use the current project context
required by resolve_item_id.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 71bc228e-3b7a-4d09-b025-0f6ef630191c

📥 Commits

Reviewing files that changed from the base of the PR and between 6cda051 and 5817ec2.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (18)
  • crates/agentflare-artifacts/Cargo.toml
  • crates/agentflare-artifacts/src/store.rs
  • crates/agentflare-backend/Cargo.toml
  • crates/agentflare-backend/src/asset.rs
  • crates/agentflare-backend/src/comment.rs
  • crates/agentflare-backend/src/item.rs
  • crates/agentflare-backend/src/label.rs
  • crates/agentflare-backend/src/project.rs
  • crates/agentflare-backend/src/state.rs
  • crates/agentflare-backend/src/webhook.rs
  • crates/agentflare-backend/src/workspace.rs
  • crates/agentflare-db-kit/Cargo.toml
  • crates/agentflare-db-kit/src/ids.rs
  • src/mcp_server/claim.rs
  • src/mcp_server/item.rs
  • src/mcp_server/tests/action_tests.rs
  • src/mcp_server/tests/artifact_tests.rs
  • src/mcp_server/types.rs
💤 Files with no reviewable changes (1)
  • crates/agentflare-backend/Cargo.toml

body: &str,
) -> Result<ItemComment> {
let id = uuid::Uuid::now_v7().to_string();
let id = db_kit::ids::new_id();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Do not use NanoID ordering to identify the latest comment.

is_latest still uses created_at DESC, id DESC; after this change, NanoIDs are random rather than UUIDv7 time-ordered, so same-second comments can be misclassified. Keep time-ordered IDs for this table or add an explicit monotonic insertion-order column.

🤖 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 `@crates/agentflare-backend/src/comment.rs` at line 41, Update comment ID
generation in the comment persistence flow around new_id so IDs retain
insertion-time ordering, or introduce and populate an explicit monotonic
insertion-order column used by the is_latest query. Ensure the created_at DESC,
id DESC ordering cannot misclassify comments created within the same second.

Comment thread crates/agentflare-backend/src/item.rs
Comment thread crates/agentflare-backend/src/item.rs Outdated
Comment thread src/mcp_server/item.rs
Comment on lines +147 to +154
pub(crate) fn resolve_item_id(
&self,
conn: &Connection,
id_or_seq: &str,
) -> Result<String, ErrorData> {
let project = self.resolve_project(conn)?;
agentflare_backend::item::resolve_id(conn, Some(&project.id), id_or_seq)
.map_err(map_backend_err)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Normalize #<sequence_id> before backend resolution.

Line 153 forwards #42 unchanged, but resolve_id only parses raw integers and otherwise treats it as a canonical ID. All resolved mutation actions therefore reject the documented #-prefixed form. Strip one leading # before delegation and add regression coverage.

Proposed fix
 pub(crate) fn resolve_item_id(
     &self,
     conn: &Connection,
     id_or_seq: &str,
 ) -> Result<String, ErrorData> {
     let project = self.resolve_project(conn)?;
-    agentflare_backend::item::resolve_id(conn, Some(&project.id), id_or_seq)
+    let id_or_seq = id_or_seq.strip_prefix('#').unwrap_or(id_or_seq);
+    agentflare_backend::item::resolve_id(conn, Some(&project.id), id_or_seq)
         .map_err(map_backend_err)
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
pub(crate) fn resolve_item_id(
&self,
conn: &Connection,
id_or_seq: &str,
) -> Result<String, ErrorData> {
let project = self.resolve_project(conn)?;
agentflare_backend::item::resolve_id(conn, Some(&project.id), id_or_seq)
.map_err(map_backend_err)
pub(crate) fn resolve_item_id(
&self,
conn: &Connection,
id_or_seq: &str,
) -> Result<String, ErrorData> {
let project = self.resolve_project(conn)?;
let id_or_seq = id_or_seq.strip_prefix('#').unwrap_or(id_or_seq);
agentflare_backend::item::resolve_id(conn, Some(&project.id), id_or_seq)
.map_err(map_backend_err)
🤖 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/mcp_server/item.rs` around lines 147 - 154, Update resolve_item_id to
remove exactly one leading “#” from id_or_seq before calling
agentflare_backend::item::resolve_id, while leaving canonical IDs and unprefixed
sequence IDs unchanged. Add regression coverage confirming mutation resolution
accepts the documented “#<sequence_id>” form.

Comment thread src/mcp_server/types.rs
…refix, fix flaky nanoid test

Review of task/184 (item #186) found the PR didn't actually cover its own
motivating case: item_get -- the exact call from #184's bug report
(item(get, id="178")) -- was never wired to resolve_item_id, and
resolve_id's numeric parse didn't strip a leading '#', so #-prefixed
sequence ids silently fell through to the UUID passthrough branch instead
of resolving, despite both the commit message and the tool's own schema
description claiming that support.

- item_get now resolves through resolve_item_id, closing the original gap
- resolve_id strips a leading '#' before parsing as numeric
- Added the tests #184 explicitly required and that were missing: bare
  numeric, #-prefixed numeric, not-found numeric, project-scoped lookup,
  end-to-end via the item MCP tool
- Fixed a flaky test: handoff_tool_requires_recipient_and_assigns_item
  asserted a filename via item_id.to_lowercase(), which doesn't match
  production's actual AgentflareMcp::slugify() transform -- slugify also
  collapses '_' to '-', which to_lowercase() doesn't, so the assertion
  failed whenever a randomly-generated nanoid id happened to contain an
  underscore. Now asserts against the real transform.

cargo test --workspace (632 passing, 0 failed), cargo fmt --check, and
cargo clippy --workspace --all-features -D warnings all clean.
@getappz

getappz commented Jul 18, 2026

Copy link
Copy Markdown
Owner Author

Review (item #186)

Found 3 issues, all fixed in commit 113ee63:

  1. item_get was never wired up — the exact call from feat(gateway): put lean-ctx behind the gateway, rename gateway_search/execute to tool_search/tool_execute #184's bug report (item(get, id="178")) still failed. All other id-taking actions (update, delete, claim, etc.) were fixed, but item_get itself — the motivating case — was untouched.
  2. #-prefixed sequence ids didn't resolve. resolve_id's id_or_seq.parse::<i64>() fails on a leading #, so "#178" fell through to the UUID-passthrough branch instead of resolving via sequence lookup — despite both the commit message and the tool's own schema description claiming #-prefix support.
  3. Flaky test, caused by the nanoid migration: handoff_tool_requires_recipient_and_assigns_item asserted a filename via item_id.to_lowercase(), but production actually builds it via AgentflareMcp::slugify(), which also collapses _ to -. to_lowercase() doesn't, so the assertion failed whenever a randomly-generated nanoid id happened to contain an underscore. Confirmed by running the test in a loop pre-fix; 15/15 clean after.

Also added the tests #184's spec explicitly required and that were missing entirely: bare numeric, #-prefixed numeric, not-found numeric, project-scoped lookup (backend unit tests), plus an end-to-end item(get, ...) test through the actual MCP tool.

cargo test --workspace (632 passing), cargo fmt --check, cargo clippy --workspace --all-features -D warnings all clean.

One thing flagged but not fixed (out of scope for this PR): nanoid's default alphabet includes _, and Self::slugify() collapses _/-/case differences all to the same output — so two different item ids that differ only by case or underscore-vs-hyphen would slugify to the same filename stem. Low severity in practice (the actual storage path also includes a content hash, so it doesn't cause real file collisions), but worth a note for whoever next touches asset/handoff filename generation.

@getappz
getappz merged commit a99cb02 into master Jul 18, 2026
24 of 26 checks passed
@getappz
getappz deleted the task/184 branch July 18, 2026 20:02
getappz added a commit that referenced this pull request Sep 16, 2026
…paths.rs`, new crate added). This is ready to hand off. (#689)

## Status

Implemented Step 1 of #257's config-centralization plan:

- New `crates/agentflare-config` crate with `home()` (identical logic/env var to the old `paths::home()`), a new `config_dir(namespace: &str)` per the design spec (`~/.config/agentflare/<namespace>`), and `test_support::with_temp_home` (moved verbatim, including its 3 regression tests for the Windows leftover-file/thread-contention/env-cleanup flakes).
- `src/paths.rs::home()` is now a one-line wrapper (`agentflare_config::home()`); `test_support::with_temp_home` there is a re-export so the ~80 existing `crate::paths::test_support::with_temp_home` call sites are untouched. `with_temp_cwd` stayed in `paths.rs` (out of scope per the task).
- Registered the new crate in the workspace and root `Cargo.toml`.

**Design note:** the spec says `agentflare-config` should have no dependency on any existing agentflare crate, but `with_temp_home` must share `agent_registry::detect::PATH_LOCK` — using a separate mutex would reintroduce the exact `set_var` data race the original code's comments warn about (concurrent `set_var` calls on different vars are UB regardless of which lock guards which). `agent-registry` is a leaf crate (no agentflare-crate deps of its own), so this doesn't create a cycle. I judged correctness over the aspirational purity for this zero-behavior-change step; worth confirming with whoever does step 2+.

**Verification (all synchronous, sccache disabled — the ambient `sccache` wrapper in this sandbox is broken and throws spurious `EROFS` errors on `.d` file writes, unrelated to this change):**
- `cargo test -p agentflare-config` — 4/4 pass
- `cargo test -p agentflare --bin agentflare -- paths::` — 4/4 pass (including the new wrapper delegation test)
- `cargo check --workspace` — clean (only pre-existing `unsafe_code=warn` noise)
- `cargo fmt --check` and `cargo clippy --no-deps` on the new crate — clean

No concerns beyond the design-spec deviation noted above.

Agentflare-Branch: task/260-agentflare-config-crate-step-1-extract-h
Agentflare-Item: 260

Co-authored-by: shiva <shiva@gosysinfo.tech>
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.

1 participant