Skip to content
This repository was archived by the owner on Aug 12, 2026. It is now read-only.

feat(agents): join from template generation - #323

Open
neekolas wants to merge 1 commit into
otr-devfrom
06-22-agent_join_with_a_generation
Open

feat(agents): join from template generation#323
neekolas wants to merge 1 commit into
otr-devfrom
06-22-agent_join_with_a_generation

Conversation

@neekolas

@neekolas neekolas commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR lets POST /api/v2/agents/join start an assistant from an in-progress agent template generation. Callers can now pass a generationId instead of waiting for generation to complete and then passing templateId.

The join handler validates that the generation exists and belongs to the joining account, then dispatches convos-assistants with template: null, the original caller ownerAccountId, and the forwarded generationId. Existing templateId joins and bare joins are left unchanged.

What changed

  • Added optional generationId support to the agents join request schema.
  • Enforced templateId and generationId as mutually exclusive inputs.
  • Added generationId to the strict assistant dispatch envelope so generation-based joins do not fail dispatch validation.
  • Added generation lookup and ownership checks:
    • missing generation returns 404 GENERATION_NOT_FOUND
    • foreign generation returns 403 GENERATION_FORBIDDEN
    • lookup failure returns 500 GENERATION_LOOKUP_FAILED
  • Kept the generation path template-agnostic: it does not read generation status or templateId, so pending generations can be used to start provisioning.
  • Preserved the existing templateId + options.onboarding=agent-builder rejection while allowing generationId + options.onboarding=agent-builder.
  • Added a regression test proving agent API key callers can fetch draft template details by id, which is the downstream resolution path the assistants workflow relies on.
  • Stabilized a telemetry metrics test that was flaky in the full parallel DB-backed suite by using a non-colliding batch id and waiting for async failed-forward cleanup to become observable.
  • Included the design doc for this change under docs/plans/2026-06-22-generation-id-join-design.md.

Verification

  • DATABASE_URL='postgres://postgres:convos@localhost:5432/postgres?sslmode=disable' pnpm test tests/agents-join.test.ts tests/agent-templates.detail.test.ts tests/invites.test.ts tests/notifications-webhook-account-guard.test.ts
  • DATABASE_URL='postgres://postgres:convos@localhost:5432/postgres?sslmode=disable' pnpm test tests/telemetry-metrics.test.ts tests/telemetry-dedup.test.ts
  • DATABASE_URL='postgres://postgres:convos@localhost:5432/postgres?sslmode=disable' pnpm run test:local
    • 143 test files passed
    • 1,237 tests passed
    • 1 skipped
  • pnpm run check
    • tsc --noEmit
    • prettier --check .
    • eslint .
  • git diff --check

Notes

This PR only covers the convos-backend side of generation-based joins. The convos-assistants workflow that polls generation progress and resolves the final template remains out of scope for this branch.


View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.

Note

Add generationId support to POST /v2/agents/join as an alternative to templateId

  • Extends the join handler in join.ts to accept an optional generationId (UUID) in the request body, mutually exclusive with templateId.
  • When generationId is provided, the handler looks up the generation, enforces ownership (returns 404/403/500 on failure), and forwards generationId with template: null to the assistants service dispatch.
  • Adds a __setGenerationFinderForTests seam mirroring the existing template finder override, with full test coverage in agents-join.test.ts.
  • Behavioral Change: requests supplying both templateId and generationId now return 400 INVALID_REQUEST.

Macroscope summarized 6c10495.

Summary by CodeRabbit

  • New Features
    • Agents can now be joined using a generation ID as an alternative to a template ID (with request validation and correct forwarding during dispatch).
    • Draft agent templates are now accessible to callers authenticated via an agent API key, while remaining hidden from non-admin reader authentication.
  • Bug Fixes
    • Improved handling for invalid or unauthorized generation IDs, including clearer error responses when generations are missing or not owned by the caller.

Copy link
Copy Markdown
Collaborator Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@claude

claude Bot commented Jun 22, 2026

Copy link
Copy Markdown

Claude finished @neekolas's task —— View job


Code Review Complete ✅

I've completed a thorough review of this PR. Overall, this is excellent work — the implementation is clean, well-tested, and follows established patterns. The design doc is comprehensive and the code matches the spec precisely.


Summary

This PR successfully adds generationId support to the agents join endpoint, enabling parallel agent provisioning with template generation. The implementation is sound, well-tested (1,237 tests passing), and maintains backward compatibility with existing flows.


Strengths 🎯

Architecture & Design

  • Excellent design doc (docs/plans/2026-06-22-generation-id-join-design.md) — comprehensive, addresses edge cases, documents invariants
  • Clean separation of concerns: Generation path is parallel to template path, not intertwined
  • Template-agnostic approach: Correctly doesn't read status or templateId from generation row
  • Follows established patterns: Mirrors __setTemplateFinderForTests pattern for test seams

Security

  • Ownership validation is correct: generation.ownerAccountId !== joiningUserAccountId → 403
  • Fail-closed approach: Missing generation → 404 before dispatch
  • Proper error handling: DB throws → 500 without dispatching
  • Mutual exclusivity enforced: templateId + generationId → 400

Testing

  • Comprehensive coverage: All acceptance criteria covered
  • Edge cases tested: Missing generation, foreign ownership, DB errors, non-UUID inputs
  • Regression protection: Existing templateId tests remain green
  • Smart async fix: telemetry-metrics.test.ts now uses vi.waitFor for async assertions (line 228-234)

Code Quality

  • Type safety: Proper TypeScript types for GenerationRow and GenerationFinder
  • Schema validation: .strict() on dispatchBodySchema forces explicit field addition
  • Error messages: Clear, actionable error codes (GENERATION_NOT_FOUND, GENERATION_FORBIDDEN, etc.)
  • Logging: Sanitized logging follows existing patterns (logs generationId, never slug)

Issues & Recommendations

🟡 Minor Issues

1. Missing JSDoc for Test Seam (join.ts:42-46)

The exported __setGenerationFinderForTests function lacks documentation. While it mirrors the template finder pattern, exported functions should have JSDoc comments.

Recommendation:

/**
 * Test seam: overrides generation lookup. Pass null to restore default Prisma lookup.
 * Mirrors __setTemplateFinderForTests pattern. Not used in production.
 */
export function __setGenerationFinderForTests(
  finder: GenerationFinder | null,
): void {
  _generationFinder = finder ?? defaultGenerationFinder;
}

2. Design Doc Typo (line 363)

The verification command references incorrect test filename:

pnpm test -- tests/agent-templates-detail.test.ts   # adjust to actual filename

Should be: tests/agent-templates.detail.test.ts (note the period)

3. Markdown Linting (design doc line 140)

The flow diagram code block is missing a language identifier, which violates markdownlint MD040.

Fix: Change ``` to ```text


🔵 Suggestions for Future Consideration

1. Generation Status Edge Cases

The implementation correctly ignores generation.status, but consider documenting what happens when:

  • A failed generation is used to start an agent (provisioning succeeds, but workflow will eventually fail)
  • A done generation with no templateId (data corruption scenario)

Current behavior is correct (fail-open at backend, workflow handles cleanup), but explicit documentation in code comments would help future maintainers.

2. Telemetry Test Stability

The telemetry test fix (using vi.waitFor + unique BATCH_ID) is good, but consider:

  • Adding a timeout to vi.waitFor for faster failure detection
  • Documenting why the BATCH_ID was changed (to avoid collision in parallel runs)

3. Error Message Consistency

The GENERATION_FORBIDDEN message ("Not authorized to use this generation") is less friendly than it could be. Consider: "This template generation belongs to another account"

Not blocking — current wording is acceptable and matches TEMPLATE_FORBIDDEN.


Detailed Code Analysis

src/api/v2/agents/handlers/join.ts

Lines 20-23: Type definitions are clean

type GenerationRow = Awaited<ReturnType<typeof prisma.agentTemplateGeneration.findUnique>>;
type GenerationFinder = (id: string) => Promise<GenerationRow>;

✅ Good use of Awaited and Prisma return types

Lines 97, 110-114: Schema changes are correct

generationId: z.string().uuid().optional(),
// ...
.refine(
  (b) => !(b.templateId !== undefined && b.generationId !== undefined),
  { message: "Provide at most one of templateId or generationId", path: ["generationId"] }
)

✅ UUID validation, mutual exclusivity properly enforced

Lines 565-607: Generation resolution logic

  • ✅ Proper try/catch for DB errors
  • ✅ Null check → 404
  • ✅ Ownership validation → 403
  • ✅ Does NOT read status or templateId (correctly template-agnostic)
  • ✅ Logging includes context (generationId, ownerAccountId, callerAccountId)

Lines 664-666: Dispatch body construction

if (generationId !== undefined) {
  dispatchBody.generationId = generationId;
}

✅ Only adds field when present, keeps dispatch minimal

Lines 175: Schema extension

generationId: z.string().uuid().optional(),

✅ Added to dispatchBodySchema.strict() — prevents 500s

tests/agents-join.test.ts

Lines 83-108: baseGeneration factory is well-structured
✅ Sensible defaults, supports overrides

Lines 1009-1187: Generation test coverage is excellent

  • ✅ 404 for missing generation
  • ✅ 403 for foreign generation
  • ✅ 500 for lookup failure
  • ✅ Dispatch body shape validation
  • agent-builder option forwarding
  • ✅ Direct-add inboxId response

Lines 351-368, 370-382: Input validation tests
✅ Both templateId + generationId → 400
✅ Non-UUID generationId → 400

tests/agent-templates.detail.test.ts

Lines 235-271: Draft template API key access test
This is the critical regression anchor for the assistants workflow's resolution path.

test("returns a draft template to an agent API key caller", async () => {
  // ... creates draft owned by API_KEY_DRAFT_OWNER_ID
  const reader = await readDetail({ path: `/api/v2/agent-templates/${draft.id}` });
  expect(reader.response.status).toBe(404); // Hidden from regular auth
  
  const response = await fetch(`${baseURL}/api/v2/agent-templates/${draft.id}`,
    { headers: agentKeyHeaders() }
  );
  expect(response.status).toBe(200); // Visible to API key
  expect(body.status).toBe("draft");
});

Excellent addition — locks in the downstream resolution behavior

tests/telemetry-metrics.test.ts

Lines 33, 228-234: Async test fix

const BATCH_ID = "77777777-7777-4777-8777-777777777777"; // Changed from previous value

// ...
test("forward failure → 502 and batch NOT recorded", async () => {
  vi.mocked(forwardMetrics).mockResolvedValue(false);
  const res = await post(makeApp()).send(makeBody());
  expect(res.status).toBe(502);
  await vi.waitFor(async () => {
    expect(await prisma.telemetryBatch.findUnique({
      where: { batchId: BATCH_ID }
    })).toBeNull();
  });
});

✅ Proper async handling with vi.waitFor
✅ Unique BATCH_ID prevents parallel test collisions


Security Review ✅

Ownership Validation

  • Generation ownership check at join.ts:591-606
  • Template ownership check unchanged (join.ts:519-534)
  • ownerAccountId always populated from joining user (join.ts:457-465)

Input Validation

  • ✅ UUID format enforced (Zod .uuid())
  • ✅ Mutual exclusivity validated before DB lookup
  • ✅ DB errors caught and mapped to 500 (no information leakage)

Authorization

  • ✅ Handler protected by authMiddleware + requireAccount (mentioned in join.ts:443)
  • ✅ Defense-in-depth check at join.ts:458-465

Performance Considerations ✅

  • No N+1 queries: Single findUnique for generation lookup
  • Early validation: Schema validation happens before DB hit
  • Minimal dispatch body: generationId only added when present
  • No blocking operations: Generation path doesn't wait for template resolution
  • Efficient test mocking: Uses test seams instead of real DB for fast tests

Test Coverage Assessment ✅

New Functionality Coverage

  • ✅ Generation validation (404, 403, 500 cases)
  • ✅ Dispatch body shape with generationId
  • agent-builder option forwarding
  • ✅ Direct-add flow with generation
  • ✅ Mutual exclusivity validation
  • ✅ Non-UUID rejection

Regression Coverage

  • ✅ Bare join unchanged
  • templateId resolution unchanged
  • templateId + agent-builder rejection preserved
  • ✅ Direct-add registration unchanged
  • ✅ Draft template API key access (new anchor test)

Edge Cases Covered

  • ✅ Missing generation
  • ✅ Foreign ownership
  • ✅ DB lookup failure
  • ✅ Malformed UUID
  • ✅ Both templateId and generationId supplied

Coverage assessment: Excellent — all acceptance criteria and edge cases tested


Verdict

✅ Approve with Minor Suggestions

This is production-ready code. The three minor issues identified (missing JSDoc, design doc typo, markdown linting) are non-blocking and can be addressed in a follow-up if desired.

Why This Is Good Work

  1. Follows the spec precisely: Implementation matches design doc exactly
  2. Maintains invariants: .strict() schema, ownerAccountId always populated
  3. Excellent test coverage: All paths tested, regressions prevented
  4. Clean architecture: Parallel paths, not intertwined
  5. Security-conscious: Ownership validation, fail-closed approach
  6. Well-documented: Design doc + code comments
  7. Passes all checks: 1,237 tests passing, linters clean

Recommended Next Steps

  1. Merge as-is — the minor issues don't block functionality
  2. (Optional) Address the three minor issues in a follow-up
  3. Monitor production for any edge cases not covered in tests
  4. Ensure convos-assistants workflow changes are aligned with this implementation

Questions for Consideration

  1. Monitoring: Will you add metrics for generationId join success/failure rates?
  2. Cleanup: Is orphaned-member cleanup on generation failure being tracked separately? (Noted as out of scope in design doc)
  3. Documentation: Should the public API docs be updated to reflect the new generationId parameter?

Great work on this feature! The implementation quality is high and the testing is thorough. 🎉


@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

POST /v2/agents/join now accepts generationId (UUID) as a mutually exclusive alternative to templateId. The handler validates ownership, dispatches with template: null and the forwarded generationId, and returns 403/404/500 for ownership/missing/error cases. A design document, test seams, and full test coverage are added. Draft template access via agent API key is also validated. A telemetry test is fixed to poll asynchronously.

Changes

generationId join support and draft template visibility

Layer / File(s) Summary
Design specification
docs/plans/2026-06-22-generation-id-join-design.md
Documents validation rules (mutual exclusivity, UUID format), dispatch semantics (template: null, .strict() schema), ownership invariants, acceptance criteria, edge cases, and regression anchors.
Handler types, schemas, seam, and generationId resolution
src/api/v2/agents/handlers/join.ts
Adds GenerationRow/GenerationFinder types, an injectable test seam (__setGenerationFinderForTests), generationId UUID field with mutual-exclusivity refinement in the request schema, generationId in dispatchBodySchema, and the resolution branch enforcing ownership (403/404/500) before forwarding generationId in the dispatch payload.
Join handler tests for generationId flows
tests/agents-join.test.ts
Adds baseGeneration factory, afterEach seam reset, validation rejection tests for mutual exclusivity and non-UUID inputs, and resolution tests covering all error paths plus happy-path dispatch shape (null template, generationId forwarding, onboarding option, inboxId response).
Draft template visibility via agent API key
tests/agent-templates.detail.test.ts
Adds API_KEY_DRAFT_OWNER_ID, extends template cleanup, wires agent assets API key override in setup/teardown, and adds a test confirming draft templates are visible to agentKeyHeaders() callers but hidden from reader auth.

Telemetry test async fix

Layer / File(s) Summary
Async batch-absence assertion and BATCH_ID bump
tests/telemetry-metrics.test.ts
Updates BATCH_ID to a new UUID value and replaces the direct findUnique null assertion with a vi.waitFor polling loop to handle asynchronous persistence in the forward-failure test.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • xmtplabs/convos-backend#221: Modifies the same join.ts handler and agents-join.test.ts to rework templateId-driven resolution and upstream dispatch payload construction — directly adjacent to the generationId branch added here.
  • xmtplabs/convos-backend#269: Adjusts agent-templates test authentication setup by overriding the agent assets API key for test suites — the same API-key override mechanism used in this PR's draft template visibility tests.
  • xmtplabs/convos-backend#305: Hardens the assistant dispatch envelope Zod validation in join.ts — the same .strict() dispatchBodySchema that this PR extends with generationId.

Poem

🐇 A generation ID hops into view,
No templateId needed—just a UUID will do!
I check ownership first, with a 403 guard,
Then forward generationId—review is not hard.
The dispatch goes out with template: null inside,
And the inbox awaits on the bright server side! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(agents): join from template generation' directly and clearly summarizes the main change: enabling agents to be joined using a generation ID from an in-progress template generation process.
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.

✏️ 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 06-22-agent_join_with_a_generation

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 markdownlint-cli2 (0.22.1)
docs/plans/2026-06-22-generation-id-join-design.md

markdownlint-cli2 v0.22.1 (markdownlint v0.40.0)
Error: Unable to use configuration file '/coderabbit-0.markdownlint-cli2.jsonc'; ENOENT: no such file or directory, open '/coderabbit-0.markdownlint-cli2.jsonc'
at throwForConfigurationFile (file:///usr/local/lib/node_modules/markdownlint-cli2/markdownlint-cli2.mjs:48:9)
at readOptionsOrConfig (file:///usr/local/lib/node_modules/markdownlint-cli2/markdownlint-cli2.mjs:169:5)
at async main (file:///usr/local/lib/node_modules/markdownlint-cli2/markdownlint-cli2.mjs:927:21)
at async file:///usr/local/lib/node_modules/markdownlint-cli2/markdownlint-cli2-bin.mjs:14:22 {
[cause]: Error: ENOENT: no such file or directory, open '/coderabbit-0.markdownlint-cli2.jsonc'
at async open (node:internal/fs/promises:640:25)
at async Object.readFile (node:internal/fs/promises:1287:14)
at async readOptionsOrConfig (file:///usr/local/lib/node_modules/markdownlint-cli2/markdownlint-cli2.mjs:141:17)
at async main (file:///usr/local/lib/node_modules/markdownlint-cli2/markdownlint-cli2.mjs:927:21)
at async file:///usr/local/lib/node_modules/markdownlint-cli2/markdownlint-cli2-bin.mjs:14:22 {
errno: -2,
code: 'ENOENT',
syscall: 'open',
path: '/coderabbit-0.markdownlint-cli2.jsonc'
}
}


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.

@neekolas
neekolas marked this pull request as ready for review June 22, 2026 22:31
@neekolas
neekolas requested a review from a team as a code owner June 22, 2026 22:31
@macroscopeapp

macroscopeapp Bot commented Jun 22, 2026

Copy link
Copy Markdown

Approvability

Verdict: Needs human review

New feature adding generationId as an alternative join path, enabling parallel agent provisioning with template generation. The implementation is well-tested but introduces new runtime behavior. All changed files are owned by @xmtplabs/engineering, warranting their review.

No code changes detected at 6c10495. Prior analysis still applies.

You can customize Macroscope's approvability policy. Learn more.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/api/v2/agents/handlers/join.ts (1)

42-47: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add JSDoc for the new exported test seam.

__setGenerationFinderForTests is exported but undocumented; adding a short JSDoc block keeps exported API intent clear.

As per coding guidelines: “Add JSDoc comments for public APIs.”

📝 Suggested fix
+/**
+ * Overrides generation lookup in tests. Pass `null` to restore default Prisma lookup.
+ */
 export function __setGenerationFinderForTests(
   finder: GenerationFinder | null,
 ): void {
   _generationFinder = finder ?? defaultGenerationFinder;
 }
🤖 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/api/v2/agents/handlers/join.ts` around lines 42 - 47, The exported
function __setGenerationFinderForTests lacks JSDoc documentation which is
required for all public APIs per the coding guidelines. Add a JSDoc comment
block directly above the function definition that briefly describes its purpose
as a test seam for setting the GenerationFinder instance, including parameter
and return type documentation.

Source: Coding guidelines

🤖 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 `@docs/plans/2026-06-22-generation-id-join-design.md`:
- Line 363: The test command in the verification steps at line 363 references an
incorrect test file path `tests/agent-templates-detail.test.ts`. Update the
command to use the correct filename `tests/agent-templates.detail.test.ts` (note
the period before 'detail' instead of hyphen). Change the pnpm test command to
reference the actual test file path that exists in this PR.
- Line 140: The fenced code block in the flow diagram documentation (starting
with "POST /v2/agents/join") is missing a language identifier after the opening
triple backticks, which violates markdownlint rule MD040. Add "text" as the
language identifier to the opening fence (change ``` to ```text) to make the
code block compliant with markdown linting standards.

---

Nitpick comments:
In `@src/api/v2/agents/handlers/join.ts`:
- Around line 42-47: The exported function __setGenerationFinderForTests lacks
JSDoc documentation which is required for all public APIs per the coding
guidelines. Add a JSDoc comment block directly above the function definition
that briefly describes its purpose as a test seam for setting the
GenerationFinder instance, including parameter and return type documentation.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 235a1946-e79c-41b8-8764-8abbd4a3eaa7

📥 Commits

Reviewing files that changed from the base of the PR and between 54e7d46 and acc360d.

📒 Files selected for processing (5)
  • docs/plans/2026-06-22-generation-id-join-design.md
  • src/api/v2/agents/handlers/join.ts
  • tests/agent-templates.detail.test.ts
  • tests/agents-join.test.ts
  • tests/telemetry-metrics.test.ts

resolves **no** template, leaving `resolvedTemplate = null` and forwarding
`generationId` in the dispatch body.

```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add a language identifier to the fenced flow diagram block.

Line 140 opens a fenced code block without a language tag, which triggers markdownlint MD040.

📝 Suggested fix
-```
+```text
 POST /v2/agents/join { conversationId, generationId, options:{onboarding:"agent-builder"} }
   │
   ├─ bodySchema: at-most-one(templateId, generationId); exactly-one(slug, conversationId)
@@
       → detail.ts serves it (draft OK for isApiKeyListener)   ← this spec only CONFIRMS this works
-```
+```
📝 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
```
🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 140-140: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 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 `@docs/plans/2026-06-22-generation-id-join-design.md` at line 140, The fenced
code block in the flow diagram documentation (starting with "POST
/v2/agents/join") is missing a language identifier after the opening triple
backticks, which violates markdownlint rule MD040. Add "text" as the language
identifier to the opening fence (change ``` to ```text) to make the code block
compliant with markdown linting standards.

Source: Linters/SAST tools

pnpm test -- tests/agents-join.test.ts

# Detail-handler regression (draft + API-key):
pnpm test -- tests/agent-templates-detail.test.ts # adjust to actual filename

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the test command filename in verification steps.

Line 363 references tests/agent-templates-detail.test.ts, but the test file path in this PR is tests/agent-templates.detail.test.ts.

📝 Suggested fix
-pnpm test -- tests/agent-templates-detail.test.ts   # adjust to actual filename
+pnpm test -- tests/agent-templates.detail.test.ts
📝 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
pnpm test -- tests/agent-templates-detail.test.ts # adjust to actual filename
pnpm test -- tests/agent-templates.detail.test.ts
🤖 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 `@docs/plans/2026-06-22-generation-id-join-design.md` at line 363, The test
command in the verification steps at line 363 references an incorrect test file
path `tests/agent-templates-detail.test.ts`. Update the command to use the
correct filename `tests/agent-templates.detail.test.ts` (note the period before
'detail' instead of hyphen). Change the pnpm test command to reference the
actual test file path that exists in this PR.

Co-authored-by: Claude <noreply@anthropic.com>
@neekolas
neekolas force-pushed the 06-22-agent_join_with_a_generation branch from acc360d to 6c10495 Compare June 23, 2026 01:40

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/api/v2/agents/handlers/join.ts (1)

20-24: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Align the new generation-finder seam with the repo’s TypeScript function-signature conventions.

The newly added finder uses a positional parameter and explicit return type on the exported setter. Please switch this seam to object-argument style and inferred returns for consistency with src rules.

♻️ Suggested refactor
-type GenerationFinder = (id: string) => Promise<GenerationRow>;
+type GenerationFinder = (args: { id: string }) => Promise<GenerationRow>;

-const defaultGenerationFinder: GenerationFinder = (id) =>
-  prisma.agentTemplateGeneration.findUnique({ where: { id } });
+const defaultGenerationFinder: GenerationFinder = ({ id }) =>
+  prisma.agentTemplateGeneration.findUnique({ where: { id } });

-export function __setGenerationFinderForTests(
-  finder: GenerationFinder | null,
-): void {
+export function __setGenerationFinderForTests(
+  finder: GenerationFinder | null,
+) {
   _generationFinder = finder ?? defaultGenerationFinder;
 }

-      generation = await _generationFinder(generationId);
+      generation = await _generationFinder({ id: generationId });

As per coding guidelines, src/**/*.{ts,tsx} should use object parameter syntax and avoid explicit function return types when inference is sufficient.

Also applies to: 27-28, 42-46, 568-568

🤖 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/api/v2/agents/handlers/join.ts` around lines 20 - 24, The
GenerationFinder type definition uses positional parameter syntax and explicit
return type which conflicts with the repository's TypeScript conventions.
Refactor the GenerationFinder type (and any other similar function signatures
referenced in lines 27-28, 42-46, and 568) to use object-argument style (passing
arguments as an object with named properties instead of positional parameters)
and remove the explicit Promise return type to allow TypeScript to infer it
automatically. This ensures consistency with the codebase's typing conventions
for src/**/*.{ts,tsx} files.

Source: Coding guidelines

🤖 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.

Nitpick comments:
In `@src/api/v2/agents/handlers/join.ts`:
- Around line 20-24: The GenerationFinder type definition uses positional
parameter syntax and explicit return type which conflicts with the repository's
TypeScript conventions. Refactor the GenerationFinder type (and any other
similar function signatures referenced in lines 27-28, 42-46, and 568) to use
object-argument style (passing arguments as an object with named properties
instead of positional parameters) and remove the explicit Promise return type to
allow TypeScript to infer it automatically. This ensures consistency with the
codebase's typing conventions for src/**/*.{ts,tsx} files.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d12653b7-1b7d-4585-9a38-912e9fc71bbd

📥 Commits

Reviewing files that changed from the base of the PR and between acc360d and 6c10495.

📒 Files selected for processing (5)
  • docs/plans/2026-06-22-generation-id-join-design.md
  • src/api/v2/agents/handlers/join.ts
  • tests/agent-templates.detail.test.ts
  • tests/agents-join.test.ts
  • tests/telemetry-metrics.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/agents-join.test.ts

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant