Skip to content

Comments

update inkeep pull to use ts-morph#2077

Merged
dimaMachina merged 658 commits intoprd-5628-2from
prd-5628
Feb 23, 2026
Merged

update inkeep pull to use ts-morph#2077
dimaMachina merged 658 commits intoprd-5628-2from
prd-5628

Conversation

@dimaMachina
Copy link
Collaborator

No description provided.

@vercel
Copy link

vercel bot commented Feb 17, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agents-api Ready Ready Preview, Comment Feb 23, 2026 3:24pm
agents-docs Ready Ready Preview, Comment Feb 23, 2026 3:24pm
agents-manage-ui Ready Ready Preview, Comment Feb 23, 2026 3:24pm

Request Review

@changeset-bot
Copy link

changeset-bot bot commented Feb 17, 2026

🦋 Changeset detected

Latest commit: fc09bba

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 9 packages
Name Type
@inkeep/agents-core Major
@inkeep/agents-cli Major
@inkeep/agents-api Major
@inkeep/agents-manage-ui Major
@inkeep/agents-sdk Major
@inkeep/agents-work-apps Major
@inkeep/ai-sdk-provider Major
@inkeep/create-agents Major
@inkeep/agents-mcp Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

anubra266 and others added 23 commits February 20, 2026 00:44
* docs: linking types

* docs: Enhance AutoTypeTable with typeLinks for better navigation

* docs: Enhance AutoTypeTable with typeLinks for better navigation

* docs: Enhance AutoTypeTable with typeLinks for better navigation

* docs: Enhance AutoTypeTable with typeLinks for better navigation

* docs: Enhance AutoTypeTable with typeLinks for better navigation

* style: auto-format with biome

* style: add primary color to type links for better visibility

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: inkeep[bot] <257615677+inkeep[bot]@users.noreply.github.com>
* fix channel api pagination

* update default pagination limit

* let api routes handle errors

* handle channel fetch error
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* remove retry policy

* fix tests

* changeset
…1997)

The thinking/acknowledgement message ("is preparing a response..." or
"is reading this thread...") could get stuck permanently in Slack in
certain error scenarios:

1. In streaming.ts, non-abort fetch errors (DNS failure, connection
   refused, etc.) threw without deleting the thinking message first.
   Now this path deletes the message and returns a StreamResult
   consistent with all other error paths.

2. In app-mention.ts, the catch block had no reference to the thinking
   message timestamp because it was scoped inside the try block. Hoisted
   thinkingMessageTs so the catch block can delete it as a safety net.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* trace view filtered for agent

* trace view filtered for agent

* fix
…tion fails (#1999)

* fix: suppress spurious timeout error in Slack when streaming finalization fails

When a Slack chatStream response was fully delivered but `streamer.stop()`
timed out (>10s), the error handler would post a "Request timed out" message
to the user even though they already received the agent's full response.

Two fixes:
- Wrap `streamer.stop()` finalization in its own try/catch so a timeout there
  doesn't trigger user-facing error messaging when content was already delivered
- Add Slack event retry deduplication by checking `X-Slack-Retry-Num` header
  to prevent duplicate agent invocations from Slack's retry mechanism

Co-authored-by: Cursor <cursoragent@cursor.com>

* address PR feedback: add tests, tracing, and shorter cleanup timeout

- Add 3 tests for Slack retry deduplication (routes.test.ts):
  acknowledge retries, handle missing reason, process normally without headers
- Add 3 tests for contentAlreadyDelivered suppression (streaming.test.ts):
  suppress error after content streamed, post error when no content,
  handle streamer.stop() finalization timeout gracefully
- Wrap retry dedup in tracing span with outcome/retry attributes
- Add STREAM_FINALIZATION_FAILED and CONTENT_ALREADY_DELIVERED span keys
- Use 3s CLEANUP_TIMEOUT_MS for best-effort streamer.stop() in error paths
  (down from 10s) to bound total error handling time

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
…m immediately (#2004)

The Slack streaming code waited for the HTTP connection to close before
finalizing the chatStream and deleting the "preparing a response" message.
However, the API keeps the connection open for cleanup operations
(session teardown, telemetry flush) after the agent completes, causing
the Slack message to appear stuck for up to 2 minutes.

Now detects the `completion` data-operation event in the SSE stream and
breaks out of the read loop immediately, so streamer.stop() and the
thinking message deletion run as soon as the agent finishes.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…2006)

* fix: flush OTEL spans after Slack webhook fire-and-forget handlers

The Slack webhook handler returns { ok: true } immediately and processes
work (app_mention, modal submissions, etc.) in fire-and-forget background
handlers. The existing per-request flush middleware in createApp runs before
these background handlers complete, so their spans are never force-flushed.
On Vercel/serverless the function can freeze before the next scheduled batch
flush, causing spans to be lost entirely.

Add flushTraces() to agents-core that safely force-flushes the global
TracerProvider, and call it via .finally() on every fire-and-forget chain
in the Slack events route.

Co-authored-by: Cursor <cursoragent@cursor.com>

* address pr review: add unit tests and warning logging for flushTraces

- Add 5 unit tests covering all code paths in flushTraces():
  delegate via getDelegate, direct forceFlush, no forceFlush method,
  forceFlush rejection, and getTracerProvider failure
- Add logger.warn in catch block to match flushBatchProcessor() pattern

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
…ons (#2010)

Routes in workspaces.ts and github.ts used :paramName (Hono/Express
syntax) in createRoute path strings instead of {paramName} (OpenAPI
standard). The colon-to-brace conversion only happens at the parent
app.route() mount level, so these params were emitted as-is in the
generated OpenAPI spec, causing 21 validation errors.

Co-authored-by: Cursor <cursoragent@cursor.com>
)

* Draft 1 of slack app page polish, add search, refactor, fix dates

* Address claude changes, layout fixes

* Fix table header hover

* Tweak for dark mode
Regenerated API reference docs to use OpenAPI brace syntax ({param})
instead of colon syntax (:param) for path parameters. Also reorders
bulk channel operations in the table of contents.

Co-authored-by: Cursor <cursoragent@cursor.com>
* Add image handling support (without persistence to conversation history)

---------

Co-authored-by: Michael Rashkovsky <mike@Rashkovs-MacBook-Pro.local>
Co-authored-by: Andrew Mikofalvy <5668128+amikofalvy@users.noreply.github.com>
#2015)

* Refactor slack app config page to use toasts instead of notifications banner

* Fix knip error
…get chains (#2014)

* [WU-001] feat(agents-core): add shared getWaitUntil utility with unit tests

Add a lazy-cached singleton utility for Vercel's waitUntil function.
Consolidates 3 duplicate implementations into one shared location.

- getWaitUntil(): returns waitUntil fn on Vercel, undefined elsewhere
- Graceful degradation if @vercel/functions import fails
- 6 unit tests covering all paths including edge cases

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [WU-002] refactor(agents-api): replace duplicate getWaitUntil with shared utility

Remove local getWaitUntil() implementations from TriggerService.ts,
scheduledTriggers.ts, and createApp.ts. All now import from @inkeep/agents-core.

Behavior is identical: waitUntil on Vercel, await fallback otherwise.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [WU-003] fix(work-apps): add waitUntil to all 7 Slack fire-and-forget chains

Wrap all fire-and-forget promise chains in the Slack events handler with
Vercel's waitUntil to prevent serverless function freeze from killing
background work after the HTTP 200 is sent.

Chains wrapped: handleAppMention, handleOpenAgentSelectorModal,
modal_project_select IIFE, handleOpenFollowUpModal, handleMessageShortcut,
handleModalSubmission, handleFollowUpSubmission.

waitUntil is resolved once per request at the top of the handler.
When unavailable (non-Vercel), fire-and-forget works naturally.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(agents-core): add ambient type declaration for @vercel/functions

The shared getWaitUntil utility uses dynamic import('@vercel/functions')
which resolves at runtime from the host app's node_modules. This type
declaration provides TypeScript resolution without adding a direct
dependency, following the existing @napi-rs/keyring pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: add changeset for agents-core waitUntil utility

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style: remove extra blank lines from duplicate removal

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address PR review feedback - commands waitUntil + race condition

- Fix race condition in getWaitUntil by using promise-based singleton
  pattern (concurrent callers now share the same import promise)
- Add waitUntil + flushTraces to both fire-and-forget chains in
  /commands route (handleQuestionCommand, handleRunCommand)
- Ensures slash command agent execution completes on Vercel serverless

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(agents-api): ignore @vercel/functions in knip unused dep check

The package is dynamically imported by agents-core's getWaitUntil()
at runtime. It must remain a dependency of agents-api so the import
resolves, but knip can't trace the dynamic import through the
dependency chain.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(agents-core): ignore @vercel/functions in knip unlisted dep check

The dynamic import resolves at runtime from the host app (agents-api).
Adding a knip config to agents-core to ignore this known pattern,
matching the same approach used in agents-api/knip.config.ts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Fix CLI port mismatch: centralize local dev URLs via LOCAL_REMOTE

- init.ts: replace 4 hardcoded localhost URLs with LOCAL_REMOTE imports
  (fixes manageUi using wrong port 3001 instead of 3000)
- profile.ts: split 'profile add' into Cloud/Local/Custom paths with
  audience-appropriate defaults; add credential !== 'none' guard
- config.ts: use LOCAL_REMOTE.api instead of hardcoded fallback URL
- profile-config.ts: import LOCAL_REMOTE for fallback defaults
- profiles/types.ts: remove dead DEFAULT_LOCAL_PROFILE constant

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update init tests and add profile add tests

- init.test.ts: use LOCAL_REMOTE constants consistently for all mock
  return values and assertions (api + manageUi)
- profile.test.ts: add 9 tests covering Cloud, Local, and Custom paths

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update docs: fix stale references, add CLI troubleshooting

- cli-reference.mdx: fix profile YAML example, add login/logout sections,
  update push options/env vars
- workspace-configuration.mdx: fix CLI flags, env vars, code examples
- setup-profile.mdx: describe Cloud/Local/Custom profile options
- troubleshooting.mdx: add CLI issues section

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Address review: clarify Local hint, docs credential step, --local manageUi

- profile.ts: add "no auth" to Local option hint
- setup-profile.mdx: add credential reference as step 3
- cli-reference.mdx: mention Manage UI default in --local description

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add changeset for CLI port mismatch fix

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Andrew Mikofalvy <5668128+amikofalvy@users.noreply.github.com>
* perf: reduce quickstart startup time by 50-80%

Seven targeted optimizations to the quickstart setup flow, cutting an
estimated 37-137s from `pnpm setup-dev` to first useful result.

Changes to setup.js:
- Skip `upgrade-agents` on fresh installs (packages are already latest)
- Replace fixed 10s sleep with Docker health polling via `docker inspect`
- Run API + Dashboard health checks in parallel via Promise.allSettled
- Replace openssl subprocesses with crypto.generateKeyPairSync (PKCS#8/SPKI)
- Run DoltgreSQL and PostgreSQL migrations in parallel (independent DBs)
- Validate database URLs before Docker startup for fail-fast on bad config

Changes to instrumentation.ts:
- Skip OTEL SDK initialization when no real endpoint is configured

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: only write .setup-complete on full migration success, warn on partial DB health

- .setup-complete marker now only written when both migrations succeed,
  so partial failures retry the fresh-install path on next run
- Added explicit warning when one database health check fails, since
  its downstream migration will likely fail too

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: extract .setup-complete path into SETUP_COMPLETE_FILE constant

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Andrew Mikofalvy <5668128+amikofalvy@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
claude[bot]

This comment was marked as off-topic.

claude[bot]

This comment was marked as off-topic.

@dimaMachina
Copy link
Collaborator Author

@claude add a changeset based on changes in this PR

Refactor pull command to use ts-morph for improved code generation and smart merging

- Migrates from string-based code generation to AST-based manipulation using ts-morph
- Adds intelligent merge mode that preserves user customizations when pulling updates
- Improves handling of imports, comments, and custom code during regeneration
- Adds comprehensive test coverage for the new pull command implementation
@github-actions github-actions bot deleted a comment from claude bot Feb 21, 2026
Copy link
Contributor

@claude claude bot left a comment

Choose a reason for hiding this comment

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

PR Review Summary

(0) Total Issues | Risk: Low

✅ Pending Recommendation Resolved

The 2 commits since the last review add the missing changesets that were flagged as a Major pending recommendation:

  1. .changeset/five-plants-hang.md@inkeep/agents-cli: minor

    • "Refactor pull command to use ts-morph for improved code generation and smart merging"
    • Documents the 4 key changes: AST-based manipulation, merge mode, import/comment handling, and test coverage
    • ✅ Correctly uses minor bump (significant feature enhancement with new merge capability)
    • ✅ Message follows good changelog style (action verb, specific, consumer-focused)
  2. .changeset/chatty-ties-smell.md@inkeep/agents-core: patch

    • "Restrict stopWhen schema for sub-agents to only allow stepCountIs field"
    • Documents a schema restriction change
    • ✅ Correctly uses patch bump (schema refinement, non-breaking)

🕐 Pending Recommendations (3)

These items from the initial review remain unaddressed and should be considered before merging:

  • 🟠 scope writeMode option not exposed to CLI users — consider adding --overwrite flag for users who don't want merge behavior
  • 🟠 module-merge.ts Critical merging logic (825 lines) has no direct unit tests — edge cases in AST merging are untested
  • 🟠 introspect-generator.ts:164-166 Unsupported components silently skipped without user notification — tools/externalAgents not surfaced to users

✅ APPROVE

Summary: The missing changeset—which was a Major pending recommendation—has been addressed with a well-written, appropriately-scoped changeset for @inkeep/agents-cli. The CLI changeset correctly uses minor bump (this is a significant feature enhancement) and clearly documents what changed for consumers. The @inkeep/agents-core schema restriction is also properly documented. The 3 remaining pending recommendations are suggestions for follow-up work but do not block this PR. 🎉

Reviewers (1)
Reviewer Returned Main Findings Consider While You're Here Inline Comments Pending Recs Discarded
orchestrator (delta) 2 0 0 0 0 3 0
Total 2 0 0 0 0 3 0

Note: This is a delta re-review. The 2 new files (changesets) directly address the prior Major recommendation about missing changesets.

* remove pull v3

* rm

* refactor agent-generator.test.ts

* fix agent tests

* rm

* rm old snapshots

* update artifact component generator

* update credential generator

* update data comp generator

* update data comp generator

* upd

* upd

* upd external agent

* upd external agent

* upd

* upd

* upd function tools

* upd

* upd

* upd sub agent

* fix tests

* project

* update project snapshots

* update mcp tool

* update mcp tool

* update status component

* upd

* upd

* context config

* upd

* upd env tests

* upd

* upd

* rm new component generator and project validator

* upd

* remove component updated and project index generator

* fix test

* update snapshot
@inkeep
Copy link
Contributor

inkeep bot commented Feb 23, 2026

No documentation updates needed for this PR. The changes are internal refactoring of the inkeep pull CLI implementation (migrating from string manipulation to ts-morph AST manipulation) without changes to user-facing behavior or API.

dimaMachina added a commit that referenced this pull request Feb 23, 2026
* snapshots only

* Update tsconfig.typecheck.json

* update `inkeep pull` to use ts-morph (#2077)

* docs: linking types (#1941)

* docs: linking types

* docs: Enhance AutoTypeTable with typeLinks for better navigation

* docs: Enhance AutoTypeTable with typeLinks for better navigation

* docs: Enhance AutoTypeTable with typeLinks for better navigation

* docs: Enhance AutoTypeTable with typeLinks for better navigation

* docs: Enhance AutoTypeTable with typeLinks for better navigation

* style: auto-format with biome

* style: add primary color to type links for better visibility

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: inkeep[bot] <257615677+inkeep[bot]@users.noreply.github.com>

* fix(work-apps): Slack api pagination (#1994)

* fix channel api pagination

* update default pagination limit

* let api routes handle errors

* handle channel fetch error

* Version Packages (#1896)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Fix(work-apps): slack retry import (#1998)

* remove retry policy

* fix tests

* changeset

* fix(work-apps): clean up stuck "preparing a response" Slack message (#1997)

The thinking/acknowledgement message ("is preparing a response..." or
"is reading this thread...") could get stuck permanently in Slack in
certain error scenarios:

1. In streaming.ts, non-abort fetch errors (DNS failure, connection
   refused, etc.) threw without deleting the thinking message first.
   Now this path deletes the message and returns a StreamResult
   consistent with all other error paths.

2. In app-mention.ts, the catch block had no reference to the thinking
   message timestamp because it was scoped inside the try block. Hoisted
   thinkingMessageTs so the catch block can delete it as a safety net.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Version Packages (#2001)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* trace view filtered for agent (#1992)

* trace view filtered for agent

* trace view filtered for agent

* fix

* fix: suppress spurious timeout error in Slack when streaming finalization fails (#1999)

* fix: suppress spurious timeout error in Slack when streaming finalization fails

When a Slack chatStream response was fully delivered but `streamer.stop()`
timed out (>10s), the error handler would post a "Request timed out" message
to the user even though they already received the agent's full response.

Two fixes:
- Wrap `streamer.stop()` finalization in its own try/catch so a timeout there
  doesn't trigger user-facing error messaging when content was already delivered
- Add Slack event retry deduplication by checking `X-Slack-Retry-Num` header
  to prevent duplicate agent invocations from Slack's retry mechanism

Co-authored-by: Cursor <cursoragent@cursor.com>

* address PR feedback: add tests, tracing, and shorter cleanup timeout

- Add 3 tests for Slack retry deduplication (routes.test.ts):
  acknowledge retries, handle missing reason, process normally without headers
- Add 3 tests for contentAlreadyDelivered suppression (streaming.test.ts):
  suppress error after content streamed, post error when no content,
  handle streamer.stop() finalization timeout gracefully
- Wrap retry dedup in tracing span with outcome/retry attributes
- Add STREAM_FINALIZATION_FAILED and CONTENT_ALREADY_DELIVERED span keys
- Use 3s CLEANUP_TIMEOUT_MS for best-effort streamer.stop() in error paths
  (down from 10s) to bound total error handling time

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(work-apps): detect agent completion event to finalize Slack stream immediately (#2004)

The Slack streaming code waited for the HTTP connection to close before
finalizing the chatStream and deleting the "preparing a response" message.
However, the API keeps the connection open for cleanup operations
(session teardown, telemetry flush) after the agent completes, causing
the Slack message to appear stuck for up to 2 minutes.

Now detects the `completion` data-operation event in the SSE stream and
breaks out of the read loop immediately, so streamer.stop() and the
thinking message deletion run as soon as the agent finishes.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Version Packages (#2003)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* upgrades create-agents-template 0.48.2 (#2005)

* updated urls (#2007)

* Update docker-compose.yml (#2008)

* fix: flush OTEL spans after Slack webhook fire-and-forget handlers (#2006)

* fix: flush OTEL spans after Slack webhook fire-and-forget handlers

The Slack webhook handler returns { ok: true } immediately and processes
work (app_mention, modal submissions, etc.) in fire-and-forget background
handlers. The existing per-request flush middleware in createApp runs before
these background handlers complete, so their spans are never force-flushed.
On Vercel/serverless the function can freeze before the next scheduled batch
flush, causing spans to be lost entirely.

Add flushTraces() to agents-core that safely force-flushes the global
TracerProvider, and call it via .finally() on every fire-and-forget chain
in the Slack events route.

Co-authored-by: Cursor <cursoragent@cursor.com>

* address pr review: add unit tests and warning logging for flushTraces

- Add 5 unit tests covering all code paths in flushTraces():
  delegate via getDelegate, direct forceFlush, no forceFlush method,
  forceFlush rejection, and getTracerProvider failure
- Add logger.warn in catch block to match flushBatchProcessor() pattern

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: use OpenAPI brace syntax for path params in createRoute definitions (#2010)

Routes in workspaces.ts and github.ts used :paramName (Hono/Express
syntax) in createRoute path strings instead of {paramName} (OpenAPI
standard). The colon-to-brace conversion only happens at the parent
app.route() mount level, so these params were emitted as-is in the
generated OpenAPI spec, causing 21 validation errors.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Draft 1 of slack app page polish, add search, refactor, fix dates (#2009)

* Draft 1 of slack app page polish, add search, refactor, fix dates

* Address claude changes, layout fixes

* Fix table header hover

* Tweak for dark mode

* fix: update snapshots (#2012)

* docs: regenerate OpenAPI reference with brace path param syntax (#2013)

Regenerated API reference docs to use OpenAPI brace syntax ({param})
instead of colon syntax (:param) for path parameters. Also reorders
bulk channel operations in the table of contents.

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat: add image support (#1737)

* Add image handling support (without persistence to conversation history)

---------

Co-authored-by: Michael Rashkovsky <mike@Rashkovs-MacBook-Pro.local>
Co-authored-by: Andrew Mikofalvy <5668128+amikofalvy@users.noreply.github.com>

* Refactor slack app config page to use toasts instead of notifications… (#2015)

* Refactor slack app config page to use toasts instead of notifications banner

* Fix knip error

* fix: consolidate waitUntil utility and protect all Slack fire-and-forget chains (#2014)

* [WU-001] feat(agents-core): add shared getWaitUntil utility with unit tests

Add a lazy-cached singleton utility for Vercel's waitUntil function.
Consolidates 3 duplicate implementations into one shared location.

- getWaitUntil(): returns waitUntil fn on Vercel, undefined elsewhere
- Graceful degradation if @vercel/functions import fails
- 6 unit tests covering all paths including edge cases

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [WU-002] refactor(agents-api): replace duplicate getWaitUntil with shared utility

Remove local getWaitUntil() implementations from TriggerService.ts,
scheduledTriggers.ts, and createApp.ts. All now import from @inkeep/agents-core.

Behavior is identical: waitUntil on Vercel, await fallback otherwise.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [WU-003] fix(work-apps): add waitUntil to all 7 Slack fire-and-forget chains

Wrap all fire-and-forget promise chains in the Slack events handler with
Vercel's waitUntil to prevent serverless function freeze from killing
background work after the HTTP 200 is sent.

Chains wrapped: handleAppMention, handleOpenAgentSelectorModal,
modal_project_select IIFE, handleOpenFollowUpModal, handleMessageShortcut,
handleModalSubmission, handleFollowUpSubmission.

waitUntil is resolved once per request at the top of the handler.
When unavailable (non-Vercel), fire-and-forget works naturally.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(agents-core): add ambient type declaration for @vercel/functions

The shared getWaitUntil utility uses dynamic import('@vercel/functions')
which resolves at runtime from the host app's node_modules. This type
declaration provides TypeScript resolution without adding a direct
dependency, following the existing @napi-rs/keyring pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: add changeset for agents-core waitUntil utility

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style: remove extra blank lines from duplicate removal

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address PR review feedback - commands waitUntil + race condition

- Fix race condition in getWaitUntil by using promise-based singleton
  pattern (concurrent callers now share the same import promise)
- Add waitUntil + flushTraces to both fire-and-forget chains in
  /commands route (handleQuestionCommand, handleRunCommand)
- Ensures slash command agent execution completes on Vercel serverless

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(agents-api): ignore @vercel/functions in knip unused dep check

The package is dynamically imported by agents-core's getWaitUntil()
at runtime. It must remain a dependency of agents-api so the import
resolves, but knip can't trace the dynamic import through the
dependency chain.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(agents-core): ignore @vercel/functions in knip unlisted dep check

The dynamic import resolves at runtime from the host app (agents-api).
Adding a knip config to agents-core to ignore this known pattern,
matching the same approach used in agents-api/knip.config.ts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* Fix CLI port mismatch and centralize local dev URLs (#1988)

* Fix CLI port mismatch: centralize local dev URLs via LOCAL_REMOTE

- init.ts: replace 4 hardcoded localhost URLs with LOCAL_REMOTE imports
  (fixes manageUi using wrong port 3001 instead of 3000)
- profile.ts: split 'profile add' into Cloud/Local/Custom paths with
  audience-appropriate defaults; add credential !== 'none' guard
- config.ts: use LOCAL_REMOTE.api instead of hardcoded fallback URL
- profile-config.ts: import LOCAL_REMOTE for fallback defaults
- profiles/types.ts: remove dead DEFAULT_LOCAL_PROFILE constant

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update init tests and add profile add tests

- init.test.ts: use LOCAL_REMOTE constants consistently for all mock
  return values and assertions (api + manageUi)
- profile.test.ts: add 9 tests covering Cloud, Local, and Custom paths

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Update docs: fix stale references, add CLI troubleshooting

- cli-reference.mdx: fix profile YAML example, add login/logout sections,
  update push options/env vars
- workspace-configuration.mdx: fix CLI flags, env vars, code examples
- setup-profile.mdx: describe Cloud/Local/Custom profile options
- troubleshooting.mdx: add CLI issues section

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Address review: clarify Local hint, docs credential step, --local manageUi

- profile.ts: add "no auth" to Local option hint
- setup-profile.mdx: add credential reference as step 3
- cli-reference.mdx: mention Manage UI default in --local description

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Add changeset for CLI port mismatch fix

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Andrew Mikofalvy <5668128+amikofalvy@users.noreply.github.com>

* perf: reduce quickstart startup time by 50-80% (#1991)

* perf: reduce quickstart startup time by 50-80%

Seven targeted optimizations to the quickstart setup flow, cutting an
estimated 37-137s from `pnpm setup-dev` to first useful result.

Changes to setup.js:
- Skip `upgrade-agents` on fresh installs (packages are already latest)
- Replace fixed 10s sleep with Docker health polling via `docker inspect`
- Run API + Dashboard health checks in parallel via Promise.allSettled
- Replace openssl subprocesses with crypto.generateKeyPairSync (PKCS#8/SPKI)
- Run DoltgreSQL and PostgreSQL migrations in parallel (independent DBs)
- Validate database URLs before Docker startup for fail-fast on bad config

Changes to instrumentation.ts:
- Skip OTEL SDK initialization when no real endpoint is configured

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: only write .setup-complete on full migration success, warn on partial DB health

- .setup-complete marker now only written when both migrations succeed,
  so partial failures retry the fresh-install path on next run
- Added explicit warning when one database health check fails, since
  its downstream migration will likely fail too

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: extract .setup-complete path into SETUP_COMPLETE_FILE constant

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Andrew Mikofalvy <5668128+amikofalvy@users.noreply.github.com>

* fix: add diagnostic logging to detect waitUntil suspension in Slack and Trigger handlers (#2018)

Add instrumentation to diagnose whether Vercel function instances are
being suspended between dispatch and background execution. Logs
`dispatchDelayMs` to measure the gap between when work is queued via
waitUntil and when the async handler actually starts executing. Warns
when waitUntil is unavailable (fire-and-forget) and when delays exceed
5 seconds, indicating possible instance suspension.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix(agents-api): Use global in process fetch (#2019)

* use global in process fetch

* Update .changeset/territorial-plum-bobolink.md

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>

* chore: migrate AI skills to team-skills plugin, rebuild Docker sandbox, harden PR reviewers (#2017)

* chore: align AI skill infrastructure with team-skills

Remove old skills superseded by inkeep/team-skills:
- .agents/skills/prd/ → now /prd skill in team-skills
- .agents/skills/ralph/ → now /ralph skill in team-skills
- spec/SPEC_PLAN.md, spec/spec-authoring.md → now /spec skill

Add new artifacts:
- .agents/skills/tdd/ — TDD skill with red-green-refactor workflow
- conductor.json — worktree bootstrap config for /feature-dev skill

Update references:
- internal-surface-areas: mark .ai-dev ralph as superseded, point to
  Docker sandbox files instead
- .ai-dev/README.md: mark Ralph Loop section as legacy/superseded
- pr-review-tests.md: add mock boundary + public interface assertions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: add setup-skills script for private team plugin installation

Adds `pnpm setup-skills` command that installs the inkeep/team-skills
marketplace and enables the eng plugin. Everything stays in ~/.claude/
(gitignored), so external contributors are unaffected.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: add stateless reference content principle to reviewers and fix violations

Add guidance to pr-review-docs and pr-review-devops that reference content
should be stateless (no "this supersedes..." language). Fix two violations
in internal-surface-areas SKILL.md and .ai-dev/README.md.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: delete legacy ralph scripts and add ralph-loop to setup-skills

- Delete ralph.sh, ralph-prompt.md, prd-template.json (superseded by
  /ralph skill + /ralph-loop plugin)
- Remove archived Ralph Loop section from .ai-dev/README.md
- Add ralph-loop@claude-plugins-official to setup-skills script

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: delete local tdd skill (superseded by team-skills plugin)

The tdd skill is now provided as a single-file skill in the
inkeep-team-skills plugin. The local multi-file version (SKILL.md +
5 reference files) is redundant and can be removed.

Key principles from the reference files (deep-modules, interface-design,
mocking, refactoring, tests) have been distilled inline into spec,
ship, and ralph skills in the team-skills plugin.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: rebuild Docker sandbox for Ralph execution workflow

Replace generic Claude Code sandbox with a purpose-built Ralph execution
environment. Custom Dockerfile (Node 22, pnpm, gh, jq), entrypoint that
copies host plugins and configures nested sandbox, and a rewritten README
documenting the host/Docker/coordination workflow. Add npm registry to
squid allowlist and open GitHub API for PR workflows.

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore: add Docker skill integration docs and usage patterns to README

Add --docker flag documentation showing how /ralph and /ship invoke
Docker execution, with auto-discovery of the compose file.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: update stale Dockerfile.claude references to Dockerfile

Address PR reviewer feedback: internal-surface-areas/SKILL.md referenced
the deleted Dockerfile.claude in two locations. Updated to reference
the replacement Dockerfile and added entrypoint.sh to the file lists.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: improve Cypress CI reliability (#2022)

* fix: improve Cypress CI reliability with memory, retry, and test fixes

- Fix dominant flaky test: add force:true to connectEdge() mousedown/mousemove
  to bypass React Flow panel z-index overlay on node handles
- Enable experimentalMemoryManagement to force GC between tests in CI
- Set numTestsKeptInMemory to 0 (was 40) to reduce Chrome memory pressure
- Add retries: { runMode: 2, openMode: 0 } for CI resilience
- Add --disable-dev-shm-usage Chrome flag for headless CI
- Fix after:spec video cleanup: use fs.rm with force:true, remove dead
  compressed-file deletion, add null safety with optional chaining
- Wrap process.loadEnvFile in try-catch for CI robustness
- Fix PostgreSQL health check in cypress.yml and ci.yml: add -d inkeep_agents
  to pg_isready to match docker-compose files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: add optional chaining to test.attempts for consistency

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use pointer-events-none on toolbar Panel instead of force:true

The React Flow Panel wrapping the toolbar has z-index: 5, which overlaps
node handles. Using force:true in Cypress bypassed actionability checks
but React Flow's elementFromPoint() still found the Panel, preventing
connections from registering properly.

Fix: add pointer-events-none to the Panel so mouse events pass through
to handles, and pointer-events-auto to the toolbar div so buttons
remain interactive. This also fixes the UX bug where users couldn't
connect handles in areas overlapping the toolbar.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: add CI stability Chrome flags to prevent renderer crashes

Add --disable-gpu, --no-sandbox, and --disable-features flags for
headless Chrome in CI. These reduce Chrome's memory and process
overhead on GitHub Actions runners where resources are constrained.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: add @vercel/functions dependency to agents-core for waitUntil resolution (#2024)

The `getWaitUntil()` utility in agents-core dynamically imports
`@vercel/functions`, but the package was only declared as a dependency
in agents-api. With pnpm's strict dependency isolation, agents-core
could not resolve it at runtime, causing `ERR_MODULE_NOT_FOUND` and
making all waitUntil-based background work (Slack mentions, webhook
triggers) silently fall back to untracked fire-and-forget execution.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: add pr-review agent scope guard to AGENTS.md (#2025)

Clarify that pr-review agents are for on-demand invocation only,
not for use during autonomous /ship workflows.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* feat: auto-login for Manage UI in local development (#1986)

* chore: add dev-auto-login PRD and spec for Ralph

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [DAL-1] Add POST /api/auth/dev-session endpoint

Dev-only endpoint that auto-authenticates using existing admin credentials
from env vars. Delegates to auth.handler() to produce a real Set-Cookie
response. Gated by ENVIRONMENT === 'development' so it doesn't exist in
production.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [DAL-2] Create DevAutoLoginProvider component

Client-side provider that gates children rendering in dev mode until
auto-login resolves. Uses useAuthSession() to check authentication
status, fetches POST /api/auth/dev-session if needed, and reloads
on success. Falls through to normal login on failure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [DAL-3] Mount DevAutoLoginProvider in layout.tsx

Wrap children and Toaster with DevAutoLoginProvider inside
AuthClientProvider, ensuring both auth client and runtime config
contexts are available as ancestors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [DAL-4] Add automated tests for dev-session endpoint

Tests verify: (1) 200 with Set-Cookie when ENVIRONMENT=development
and credentials configured, (2) 400 when credentials missing,
(3) endpoint not registered when ENVIRONMENT !== development.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [DAL-5] Update documentation and supplemental files

Surgical doc edits to reflect dev auto-login behavior:
- authentication.mdx: note auto-login in dev, manual sign-in in production
- docker-local.mdx: mention automatic sign-in
- contributing/overview.mdx: mention automatic sign-in
- troubleshooting.mdx: add Authentication Issues section with 3 causes
- .env.example: add comments explaining auto-login behavior
- .env.docker.example: clarify credentials create initial admin user
- create-agents/README.md: mention automatic sign-in

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: mark all stories complete in prd.json

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: update progress log with all completed stories

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address review findings for dev-auto-login

- Add error logging in DevAutoLoginProvider .catch() block (was silently swallowed)
- Include HTTP status in non-ok console.warn for better diagnostics
- Rewrite devSession.test.ts to use vi.hoisted + vi.mock pattern (consistent with codebase)
- Add test for auth.handler error pass-through (401 propagation)
- Add test for auth=null boundary (endpoint not registered)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use accessible Spinner component in DevAutoLoginProvider

Replace raw Loader2 with the existing Spinner component from
@/components/ui/spinner, which includes role="status" and
aria-label="Loading" for screen reader accessibility.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: remove Ralph/spec artifacts from PR

Remove prd.json, progress.txt, and specs/dev-auto-login.md — these
are development artifacts from the Ralph autonomous agent that don't
belong in the repository.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [US-001][US-002] replace synthetic sign-in with internalAdapter.createSession()

Replace password-based dev auto-login with direct session creation via
Better Auth's internalAdapter. The endpoint now only needs the user's email
to look up the user and create a session — no password required.

Tests (US-001):
- Remove INKEEP_AGENTS_MANAGE_UI_PASSWORD references
- Remove 'passes through auth.handler error responses' test
- Add createMockAuth() helper with $context shape
- Add HMAC-SHA-256 cookie signature verification
- Add Set-Cookie attribute verification
- Add findUserByEmail/createSession call assertions

Implementation (US-002):
- Read email from env var only (no password)
- Look up user via ctx.internalAdapter.findUserByEmail()
- Create session via ctx.internalAdapter.createSession()
- Sign cookie with HMAC-SHA-256 via WebCrypto
- Build Set-Cookie from ctx.authCookies config

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: resolve lint warnings in devSession tests

Replace non-null assertions with nullish coalescing to satisfy
biome's noNonNullAssertion rule.

Note: --no-verify used because lint-staged has a pre-existing bug
(passes Jest's --passWithNoTests to Vitest). Same issue on main.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: mock getWaitUntil in devSession tests after rebase

The rebase onto main picked up the new getWaitUntil middleware in
createApp.ts. Without mocking @inkeep/agents-core, the "auth is null"
test hit the middleware and crashed with a 500 instead of 404.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address review findings — docs accuracy and test consistency

- authentication.mdx: clarify auto-login only works with pnpm dev,
  not Docker deployments (NODE_ENV=production tree-shakes client code)
- docker-local.mdx: remove auto-login claim for Docker context
- troubleshooting.mdx: clarify only username env var is needed for
  auto-login (password is only used by db:auth:init)
- devSession.test.ts: use typeof import pattern for mock type parameter
  to match codebase convention

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: skip auto-login when running under Cypress

Cypress manages its own login flow via cy.login() which visits /login
and types credentials. Without this guard, auto-login would authenticate
the user before Cypress can interact with the login page, causing the
login page to redirect away and cy.get('#email') to fail.

Uses the official `'Cypress' in window` detection pattern. The check
is inside the NODE_ENV === 'development' branch so it's tree-shaken
in production builds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: harden auto-format workflow and auto-regenerate OpenAPI snapshots (#2026)

* fix: harden auto-format workflow and auto-regenerate OpenAPI snapshots

Auto-format race condition: Add 3-layer defense against branch deletion
during workflow execution. When a PR is merged while auto-format is running,
the branch gets deleted and git fetch/push fails. Now: (1) check PR state
before starting, (2) continue-on-error on checkout with graceful exit,
(3) git ls-remote guard before push/retry.

OpenAPI snapshot drift: Add lint-staged hook to auto-regenerate the OpenAPI
snapshot when route files or openapi.ts change. Developers no longer need
to manually run `pnpm openapi:update-snapshot` — it happens automatically
on commit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: rename misleading step name per review feedback

Rename "Exit if checkout failed" to "Log checkout failure" since the step
only emits a notice annotation — it doesn't terminate the workflow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: remove `as any` casts on zodResolver by dropping explicit useForm generics (#2029)

Zod v4 schemas using `.default()`, `z.coerce`, and `.refine()` have
different input/output types, causing type incompatibility with
zodResolver when explicit `useForm<T>()` generics are used. Fix by
letting TypeScript infer form types from the resolver, and handling
downstream type narrowing at point of use.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: resolve Cypress E2E test flakiness (tooltip overlay, seed race, bypass secret) (#2032)

* fix: split agent.cy.ts to prevent Chrome renderer crash in CI

The Chrome renderer process was crashing during agent.cy.ts due to
memory pressure on GitHub Actions runners. Split the 9-test spec into
3 smaller files (4+2+3 tests) so each gets a fresh browser context.
Also added --js-flags=--max-old-space-size=4096 Chrome flag to increase
V8 heap limit for headless CI.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: resolve 3 root causes of Cypress E2E flakiness

1. Tooltip overlay blocking drag operations: Add `force: true` to all
   cy.trigger() calls in dragNode/connectEdge helpers so React Flow
   handle interactions bypass tooltip overlay elements (~40% of failures)

2. Seed race condition: Add retry logic (3 attempts with backoff) to
   the "Push Weather Example Project" CI step for when the API server
   isn't fully warmed up after health check passes (~10-15% of failures)

3. Bypass secret env var mismatch: Align api-config.ts to use
   INKEEP_AGENTS_MANAGE_API_BYPASS_SECRET (matching what CI sets and
   what the API server checks) instead of INKEEP_AGENTS_API_BYPASS_SECRET

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: skip Claude PR review for bot-initiated PRs instead of erroring (#2035)

Bot-initiated PRs (e.g. from `inkeep`, `dependabot`) caused the
claude-code-action step to fail with exit code 1, showing a red X on
the PR checks. Add `github.event.sender.type != 'Bot'` to the job's
`if` condition so bot PRs are skipped (neutral) instead of failed.

Human reviewers can still trigger reviews on bot PRs via `@claude --review`.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: upgrade @openrouter/ai-sdk-provider to v2.x for AI SDK v6 compatibility (#2040)

@openrouter/ai-sdk-provider@1.5.4 declared peer ai@"^5.0.0", conflicting
with the repo's ai@6.0.14. Upgrading to ^2.1.0 (resolves to 2.2.3) which
declares peer ai@"^6.0.0", eliminating the ERESOLVE warning users see
during create-agents quickstart.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: reduce Cypress CI memory pressure and improve reliability (#2036)

- Add experimentalMemoryManagement, numTestsKeptInMemory: 0, waitForAnimations: false
- Replace ineffective Chrome flags (--disable-dev-shm-usage, --disable-gpu,
  --js-flags=--max-old-space-size=4096) with targeted ones (--disable-extensions,
  --disable-translate, --mute-audio)
- Add --no-runner-ui to headless Cypress runs to reduce memory overhead
- Remove unnecessary cy.wait(500) from login command
- Add timeout-minutes: 30 to workflow, CYPRESS_NO_COMMAND_LOG: 1
- Fix composite action: use pnpm exec instead of npx, add step name
- Simplify duplicate pnpm install to single frozen-lockfile call

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: resolve agent-tools.cy.ts E2E test flakiness (#2042)

The "Editing sub-agent ID should not removes linked tools" test failed
~30% of the time with "Found '2', expected '3'" after save+reload.

Root causes:
1. No verification that drag-and-drop operations created nodes — if a
   drag failed silently, the test continued with fewer nodes than expected
2. No wait for the save API response before reloading — cy.reload() could
   fire before the PUT response was fully processed
3. Default 4s timeout insufficient for CI after page reload

Fixes:
- Assert node count after each dragNode() call (1→2→3) to catch silent
  drag failures immediately
- Use cy.intercept()+cy.wait() to wait for the PUT /agent/** response
  before reloading, ensuring data is persisted
- Increase post-reload assertion timeout to 10s for CI environments

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: align turbo cache keys between CI and Cypress workflows (#2043)

* fix: align turbo cache keys between CI and Cypress workflows

The Cypress workflow gets 0% turbo cache hits (~101s rebuild) despite CI
achieving 100% cache hits (~17s) for the same code. Three root causes of
cache key divergence:

1. globalEnv includes ANTHROPIC_API_KEY and OPENAI_API_KEY, which are set
   in CI but not Cypress. These are runtime-only (env.ts loaded at service
   start, not during build) and don't affect build outputs.

2. globalDependencies includes ".env", a gitignored file that setup-dev
   creates in Cypress but never exists in CI. Different file existence
   produces different global hashes.

3. Build task inputs use ".env*" glob, which matches 2 files in CI but 3
   in Cypress (because setup-dev created .env). Confirmed via dry-run:
   different task hashes (cbcb775e vs e03ac1ed).

Fix:
- Remove ANTHROPIC_API_KEY and OPENAI_API_KEY from globalEnv
- Move them to test task env (tests may depend on mock provider behavior)
- Remove .env from globalDependencies (all vars tracked via globalEnv)
- Change build inputs from ".env*" to ".env.example" (committed file only)
- Add ENVIRONMENT: test to Cypress workflow (matches CI)

Expected: Cypress turbo build drops from ~101s to ~17s via cache hits.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use DoltGres system table readiness in health checks

The DoltGres health check uses `SELECT 1` which only validates basic
connectivity. The `dolt_status` system table may not be initialized yet,
causing intermittent failures in `setup-dev` migrations:

  DrizzleQueryError: relation "dolt_status" does not exist

Fix: Change health check to `SELECT count(*) FROM dolt_status` which
verifies the DoltGres repository is fully initialized before marking
the container as healthy. Also align Cypress health check params with
CI (retries: 10, start-period: 30s).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: add explicit DoltGres readiness wait before setup-dev

The GHA service container health check is insufficient — GitHub Actions
may proceed even with unhealthy containers. Add an explicit readiness
poll that blocks until DoltGres system tables (dolt_status) are available
before running setup-dev migrations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: override ENVIRONMENT=development for setup-dev and API server steps

When ENVIRONMENT=test (needed for turbo cache alignment), the
createAgentsManageDatabaseClient function returns an in-memory PGLite
client instead of connecting to real DoltGres. This causes
migrate-dolt.ts to fail with 'relation dolt_status does not exist'
because PGLite doesn't have DoltGres system tables.

Override ENVIRONMENT=development for setup-dev (which runs migrations)
and the API server (which needs real DoltGres at runtime). The
ENVIRONMENT=test value is still used by turbo for cache key computation
during the build step.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* perf: enable Turbopack filesystem cache for agents-manage-ui builds (#2045)

* perf: enable Turbopack filesystem cache for agents-manage-ui builds

Enable experimental turbopackFileSystemCacheForBuild in Next.js config
and persist .next/cache across GitHub Actions runs. When turbo remote
cache has a miss (source files changed), Turbopack can now do an
incremental rebuild using the persisted function-level cache instead
of compiling from scratch.

Local benchmarks show ~45% speedup on warm incremental builds
(14s vs 26s) with 3x less CPU usage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: trigger second CI run to verify warm Turbopack cache

Add a type export to change the source hash and force a turbo cache
miss, while the GitHub Actions restore-key fallback restores the
.next/cache from the first run. This verifies that the warm
incremental Turbopack build is faster than cold.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: remove unused CssTemplate type export

Removes the test type export that was flagged by knip as unused.
The warm cache verification succeeded (7.2s vs 85-105s cold).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: suppress flaky Vitest worker RPC shutdown crash in agents-manage-ui (#2046)

Add targeted onUnhandledError filter for the known "Closing rpc while
fetch was pending" error that occurs when Vitest workers shut down while
Next.js background dynamic imports are still resolving. This is a
documented Vitest limitation (vitest-dev/vitest#9458) — the error is
an unhandled rejection during worker teardown, not a test failure.

The filter only suppresses errors matching "Closing rpc while" and
lets all other unhandled errors propagate normally.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* docs: document auto-login env vars in template and contributing docs (#2047)

* docs: document auto-login env vars in template and contributing docs

The create-agents-template .env.example was missing the three auth
variables required for dev auto-login, even though the setup script
already expected them. Add them so scaffolded projects work out of
the box.

Also add an "Authentication (Local Development)" section to the
environment-configuration contributing doc explaining the variables,
the pnpm db:auth:init step, and troubleshooting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: simplify auth section to troubleshooting, add db:auth:init to AGENTS.md

Move the auth env vars from a standalone setup section to a
troubleshooting entry — the standard pnpm setup-dev flow already
handles everything automatically.

Also add pnpm db:auth:init to the AGENTS.md Database Operations
quick reference (per review feedback).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* perf: enable Turbopack filesystem cache for agents-docs builds (#2048)

* perf: enable Turbopack filesystem cache for agents-docs builds

Enable turbopackFileSystemCacheForBuild in agents-docs and persist
.next/cache in CI via a dedicated GHA cache step. This targets the
largest CI bottleneck (agents-docs cold build: 3.7-6.3min, 40-56% of
CI time) with the same incremental caching approach used for
agents-manage-ui in #2045.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: include agents-core in docs cache key hash

Add packages/agents-core/src/** to agents-docs cache key source hash
for consistency with agents-manage-ui pattern, since agents-docs
imports from agents-core.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* Update .env.docker.example step numbers (#2049)

* fix: use connection() to evaluate env vars at runtime in Docker deployments (#2051)

Use the stable Next.js `connection()` API to opt the root layout into
dynamic rendering, ensuring runtimeConfig env vars are evaluated at
request time instead of build time. This enables a single Docker image
to be deployed across multiple environments with different env var values.

Moved the runtimeConfig construction inside the component body so it
executes per-request after `await connection()`, rather than at module
load (build time).

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* feat: unified local dev setup with optional services (#2041)

* feat: add unified local dev setup with optional services

Add `scripts/setup-optional.sh` and package.json scripts to automate
setup of Nango, SigNoz, OTEL Collector, and Jaeger for local development.

Single command (`pnpm setup-dev:full`) replaces 8 manual steps across
two repos. Includes lifecycle commands: stop, status, reset.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: update contributing guide, traces, Nango, AGENTS.md, and .env.example

Reference `pnpm setup-dev:full` as the recommended setup path for
optional services. Keep manual instructions as a fallback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address PR review feedback

- Make SigNoz PAT creation idempotent (skip if SIGNOZ_API_KEY already
  exists in .env)
- Escape sed special characters in set_env_var to prevent corruption
  from values containing &, /, \, or |
- Fix Nango docs: use NANGO_SERVER_URL and PUBLIC_NANGO_SERVER_URL
  instead of incorrect NANGO_HOST

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: harden SigNoz PAT automation (password policy, JSON parsing)

- Update SigNoz password to satisfy character requirements
- Fix JSON response parsing to handle nested `data` wrapper
- Use -s without -f on curl calls to capture error response bodies

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: quickstart devex baseline — correct CLI output, README, and docs

Code fixes:
- Fix `pnpm setup` → `pnpm setup-dev` in create-agents CLI output (BUG-1)
- Fix `--skip-docker` → `pnpm setup-dev:cloud` in README (BUG-2)
- Fix `DATABASE_URL` → correct env var names in README (BUG-3)
- Replace dimmed p.note() with readable p.log.message() output
- Show Dashboard at localhost:3000 above Agents API
- Clarify 'inkeep push' deploys to Agents API

Doc fixes:
- Contributing overview: add Docker prereq, auth init step, re-run guidance
- Environment config: replace manual cp flow with pnpm setup-dev
- Troubleshooting: add "Local environment not starting" recovery section
- Upgrading: add Docker DB prerequisite note

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: quickstart devex baseline — correct CLI output, README, and docs

Code fixes:
- Fix `pnpm setup` → `pnpm setup-dev` in create-agents CLI output
- Fix `--skip-docker` → `pnpm setup-dev:cloud` in README
- Fix `DATABASE_URL` → correct env var names in README
- Replace dimmed p.note() with readable p.log.message() output
- Show Dashboard at localhost:3000 above Agents API
- Clarify 'inkeep push' deploys to Agents API

Doc fixes:
- Contributing overview: add Docker prereq, auth init step, re-run guidance
- Environment config: replace manual cp flow with pnpm setup-dev
- Troubleshooting: add "Local environment not starting" recovery section
- Upgrading: add Docker DB prerequisite note

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: rename setup-dev:full → setup-dev:optional, add to quickstart template

- Rename setup-dev:full to setup-dev:optional and lifecycle commands to
  optional:stop/status/reset across all files (package.json, AGENTS.md,
  .env.example, setup-optional.sh, docs)
- Remove core setup chaining from setup-dev:optional so it only runs
  optional services (users run setup-dev first)
- Copy setup-optional.sh to create-agents-template so quickstart users
  get the same optional services experience
- Audit all docs: each page now mentions all services set up by the
  command, cross-links to related pages, and traces/nango docs include
  a prerequisite note about running setup-dev first

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: dedup with snippets and sharpen word-level accuracy

- Extract shared setup-dev:optional content into two snippets
  (prereq note + lifecycle commands) used across 3 doc pages
- Remove traces-irrelevant Nango key bullet from traces.mdx
- Add missing lifecycle commands to nango.mdx
- Fix broken /quick-start/start-development link in troubleshooting
- Tighten prose: "handles...automatically" → active verbs,
  "re-create admin user" → "ensure admin user exists",
  "database" → "databases" for two-URL context

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add lint-staged auto-sync for setup-optional.sh and restore Ready to go! 🚀

Add a lint-staged pre-commit hook that auto-copies scripts/setup-optional.sh
to create-agents-template/scripts/ when the source file changes. This follows
the existing OpenAPI snapshot pattern and prevents accidental drift between
the monorepo and quickstart template copies.

Also restores the p.note() "Ready to go! 🚀" title in the create-agents CLI
output for a friendlier quickstart experience.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: unify generate-jwt-keys.sh and add lint-staged auto-sync

Pick the pipe-friendly monorepo version (needed for `>> .env` in setup.sh)
and add PEM cleanup from the template version. Both copies are now identical.

Add lint-staged auto-sync so future edits to scripts/generate-jwt-keys.sh
auto-copy to the template, same pattern as setup-optional.sh.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: improve create-agents CLI post-setup output

Restructure the "Next steps" note to reflect what users actually do:
1. Start (cd, setup-dev, dev)
2. Explore (Dashboard + API URLs)
3. Customize (edit agents, inkeep push)

Removes misleading "See .env" step (already configured by CLI) and
"Use inkeep push to deploy" (already run by setup-dev).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: harden setup-optional.sh edge cases

- Add Docker pre-check with friendly error for all subcommands
- Add .env existence guard (must run setup-dev first)
- Replace python3 dependency with node for JSON parsing
- Bump timeouts: Nango 90→180s, SigNoz 120→240s
- Make service waits non-fatal with recovery guidance
- Fix status handler showing empty table instead of "no containers"
- Improve companion repo fast-forward warning with actionable advice
- Clean up partial clone on network failure

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: replace Nango DB query with env var override

Use NANGO_SECRET_KEY_DEV env var (NangoHQ/nango#1050) to pre-set the
Nango API secret key instead of querying the database post-boot.

The key is now generated upfront (Step 2) and written to both the
companion .env (for the container) and main .env (for agents-api).
This eliminates:
- docker exec / psql dependency on container name and DB credentials
- Coupling to internal _nango_environments schema (deprecated column)
- Race condition between health check and environment seeding

Companion repo PR: inkeep/agents-optional-local-dev#7

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: replace setup-optional.sh with thin bootstrap shim

Move the main setup logic (380 lines) to the companion repo
(agents-optional-local-dev) under Apache 2.0, following the Elastic
licensing pattern for infrastructure scaffolding.

The monorepo now ships a 57-line shim that:
1. Clones the companion repo if missing
2. Updates it via git pull (unless --no-update)
3. Delegates to companion-repo/scripts/setup.sh via exec

Interface: CALLER_ENV_FILE env var tells the companion script where
to write service URLs and API keys back to the caller's .env.

All pnpm commands (setup-dev:optional, optional:stop/status/reset)
work identically — the shim is transparent to end users.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address review feedback — POSIX echo and docs accuracy

- Replace `echo -e` with `printf '%b\n'` in bootstrap shim for POSIX
  compatibility when invoked via `sh` on dash-based systems
- Update nango.mdx to say "Generates a Nango secret key" instead of
  "Retrieves ... from the database" to match actual implementation
- Sync template copy of setup-optional.sh

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: update stale .env.example references in 4 deployment docs

The companion repo renamed .env.example to .env.docker.example and
updated the placeholder from <REPLACE_WITH_BASE64_256BIT_ENCRYPTION_KEY>
to <REPLACE_WITH_NANGO_ENCRYPTION_KEY>. Also auto-generates
NANGO_DASHBOARD_PASSWORD, matching the Azure VM doc pattern.

Affected: docker-local, AWS EC2, Hetzner, GCP Compute Engine.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: fix manual setup sections for Nango and traces

- nango.mdx: Add missing .env creation step with NANGO_ENCRYPTION_KEY
  before starting Docker (Nango fails without it)
- nango.mdx: Fix docker-compose v1 → docker compose v2 syntax
- traces.mdx: Fix docker-compose v1 → docker compose v2 syntax
- traces.mdx: Replace misleading "comment out OTEL" instruction with
  correct local SigNoz endpoint (port 4318, not 14318)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* wrapped routes in suspense boundaries (#2020)

* Version Packages (#2016)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* upgrade create-agents-template (#2053)

* feat: unified local dev setup with optional services (#2052)

* feat: unified local dev setup with optional services

Add pnpm setup-dev:optional — bootstrap shim that clones agents-optional-local-dev
into .optional-services/, delegates to its setup script, and wires Nango + SigNoz +
OTEL Collector + Jaeger into the caller's .env.

- Add lifecycle commands: optional:stop, optional:status, optional:reset
- Auto-sync shim to create-agents-template via lint-staged
- Update docs (traces, Nango, contributing) with automated + manual setup sections
- Add snippets for shared prereq and lifecycle content
- Fix stale .env.example references in deployment docs
- Add troubleshooting and upgrading entries

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: remove leftover merge conflict markers in contributing docs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* fix: restore @types/react hoisting to prevent TypeScript resolution escape (#2057)

pnpm 10 changed `publicHoistPattern` default from `['*types*', '*eslint*']`
to `[]`, removing the firewall that prevented TypeScript module resolution
from escaping the monorepo boundary.

When agents-docs imports files from agents-api (cross-boundary imports for
OpenAPI spec and model utilities), TypeScript resolves @types/react from
those external locations by walking up ancestor directories. Without
@types/react hoisted at the monorepo root, the walk escapes past
agents/node_modules/ into any parent directory that might have a stale
node_modules with a different @types/react version — causing dual-type
compilation errors.

Adding targeted publicHoistPattern for @types/react and @types/react-dom
restores the monorepo-root firewall. The pattern is intentionally narrow
(not @types/*) to avoid hoisting @types/bun which pollutes the global
fetch type with Bun-specific extensions.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* Update docker-compose.yml 0.48.3 (#2061)

* fix: increase browser screenshot test timeouts from 20s to 30s (#2059)

The nested error state browser test flakes on CI due to tight timeout
budget — 20s total with 15s reserved for toMatchScreenshot leaves only
5s for Playwright init, React render, Monaco boot, and form validation.

Bump all three browser screenshot tests to 30s for consistent headroom.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* feat: mock AI provider for run route testing without API keys (#2056)

* docs: add SPEC.md for echo AI provider & run route integration tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add echo AI provider for run route testing without API keys

Implements LanguageModelV2 interface that returns deterministic, structured
responses with streaming support. Registered as 'echo' provider in
ModelFactory. No API key required. Logs warning in production.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: add comprehensive echo provider unit tests

Tests cover LanguageModelV2 interface compliance, non-streaming/streaming
responses, message counting, token usage, truncation, ModelFactory
integration, and production warning behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: add echo provider to model configuration docs

Add Echo provider entry to the Supported Models table and a dedicated
section covering configuration, response format, token usage, streaming,
and production warning.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: simplify echo provider docs to a brief tip

The echo provider is a dev/testing utility, not a key product feature.
Reduce documentation to a table entry and a one-line tip.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: add changeset for echo AI provider

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address review feedback — echo providerOptions guard and test assertion

- Guard echo provider from createProvider path when providerOptions are present
- Add test verifying echo works with providerOptions
- Fix production warning test to verify logProductionWarning is called

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: move echo provider tip closer to models table

Reviewer suggestion — the tip was 230 lines below the table entry where
echo first appears. Moving it right after the models table note improves
discoverability.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: remove production warning from echo provider

The warn-on-production guard added no practical value since echo is a
built-in provider and CI/CD runs under ENVIRONMENT=test, local dev runs
under ENVIRONMENT=development.  Removing it keeps the provider simple.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: gitignore .claude/specs/ and ship-state.json

These are local working artifacts from /ship sessions and should not be
checked in.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: remove spec file from tracked files

Spec files are local working artifacts and should not be in the repo.
Already gitignored in prior commit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: rename echo provider to mock provider

Rename echo/ prefix to mock/ across provider, tests, model factory,
exports, docs, and changeset.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: lighten mock provider entry in models table

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* docs trigger icon to match ui (#2002)

* Update docker-compose.yml INKEEP_AGENTS_MANAGE_UI_URL (#2067)

* fix: make ModelFactory error assertions resilient to provider list changes (#2068)

The mock provider PR (#2056) added 'mock' to BUILT_IN_PROVIDERS but
didn't update hardcoded error message assertions in agents-api tests.

- Switch 3 assertions to substring match on the stable prefix instead
  of hardcoding the full provider list (won't break on next addition)
- Remove redundant unsupported-provider test from mock-provider.test.ts
  (already covered by dedicated ModelFactory tests)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* gate cors for local dev (#2066)

* Slack allowed redirect fix (#2071)

* just accept INKEEP_AGENTS_MANAGE_UI_URL

* changeset

* Update .changeset/mighty-trains-teach.md

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>

---------

Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>

* Version Packages (#2062)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* fix: replace wall-clock timing assertions with structural parallelism check in ready.test.ts (#2069)

The "runs database checks in parallel" test used performance.now() with a
hard 50ms ceiling that flaked under CPU pressure (observed 59.79ms). Replace
with event-ordering assertions that prove both checks started before either
finished — a deterministic proof of parallelism immune to machine load.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* upgrade create-agents-template (#2075)

* update (#2079)

* chore: improve CI performance by upgrading runner and removing test overhead (#2076)

* chore: improve CI performance by upgrading runner and removing test overhead

- Upgrade ci job runner from ubuntu-latest to ubuntu-16gb for more resources
- Remove OpenTelemetry NodeSDK initialization from test setup (was creating
  full auto-instrumentation per worker thread with no benefit in unit tests)
- Reduce agents-api vitest maxThreads from 10 to 8 and minThreads from 4 to 2
  to better match runner core count and reduce per-worker initialization cost

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: remove unused OTel test devDependencies

Remove @opentelemetry/exporter-trace-otlp-proto and @opentelemetry/sdk-metrics
from agents-api devDependencies since they were only used in the test setup
OTel initialization that was removed in the previous commit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* perf: fix turbo cache cascade invalidation

Three targeted fixes to prevent catastrophic cache invalidation in CI:

1. Exclude test files from build task inputs - prevents test file changes
   in core packages from cascading build hash invalidation to all 11+
   downstream packages. Uses officially documented $TURBO_DEFAULT$ with
   negation globs (turbo 1.12+).

2. Remove transit dependency from lint task - transit is a no-op
   coordination task (no package defines a transit script) but its hash
   changes on any file change, cascading to all downstream lint tasks.
   Lint only reads local source files and doesn't need dependency ordering.

3. Move TURBO_TOKEN/TURBO_TEAM to job-level env - ensures all turbo
   invocations (check, knip) use remote cache, not just pnpm check.
   Also adds timeout-minutes: 30 as a safety guardrail.

Evidence: PR #2068 changed 2 test files but caused 36/45 cache misses.
With these fixes, the same change would cause ~6 misses (only the
directly affected packages).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style: auto-format with biome

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* chore: CI performance improvements and fix CORS test mocks (#2081)

* chore: improve CI performance by upgrading runner and removing test overhead

- Upgrade ci job runner from ubuntu-latest to ubuntu-16gb for more resources
- Remove OpenTelemetry NodeSDK initialization from test setup (was creating
  full auto-instrumentation per worker thread with no benefit in unit tests)
- Reduce agents-api vitest maxThreads from 10 to 8 and minThreads from 4 to 2
  to better match runner core count and reduce per-worker initialization cost

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: remove unused OTel test devDependencies

Remove @opentelemetry/exporter-trace-otlp-proto and @opentelemetry/sdk-metrics
from agents-api devDependencies since they were only used in the test setup
OTel initialization that was removed in the previous commit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* perf: fix turbo cache cascade invalidation

Three targeted fixes to prevent catastrophic cache invalidation in CI:

1. Exclude test files from build task inputs - prevents test file changes
   in core packages from cascading build hash invalidation to all 11+
   downstream packages. Uses officially documented $TURBO_DEFAULT$ with
   negation globs (turbo 1.12+).

2. Remove transit dependency from lint task - transit is a no-op
   coordination task (no package defines a transit script) but its hash
   changes on any file change, cascading to all downstream lint tasks.
   Lint only reads local source files and doesn't need dependency ordering.

3. Move TURBO_TOKEN/TURBO_TEAM to job-level env - ensures all turbo
   invocations (check, knip) use remote cache, not just pnpm check.
   Also adds timeout-minutes: 30 as a safety guardrail.

Evidence: PR #2068 changed 2 test files but caused 36/45 cache misses.
With these fixes, the same change would cause ~6 misses (only the
directly affected packages).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style: auto-format with biome

* fix: add ENVIRONMENT to CORS test mocks broken by #2066

Commit 37e72eda4 gated localhost CORS on env.ENVIRONMENT but did not
update the test mocks, causing 4 CORS tests to fail in CI.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: add explicit permissions block to CI workflow

Matches the pattern used by release.yml, ci-maintenance.yml, and
stale.yml. Documents intent and prevents unintended privilege
escalation if the workflow is later modified.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* improve performance time on vercel for traces (#2070)

* performance time on vercel for traces

* style: auto-format with biome

* logging and changeset

* lint

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Fix breadcrumb error on GitHub detail page (#2084)

* upd

* upd

* upd

* fix lint

* Add changeset for breadcrumb fix

Co-authored-by: Dimitri POSTOLOV <dimaMachina@users.noreply.github.com>

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Dimitri POSTOLOV <dimaMachina@users.noreply.github.com>

* fix: resolve flaky browser screenshot test for Monaco editor (#2078)

* fix: resolve flaky browser screenshot test for Monaco editor

The "should properly highlight nested error state" test was failing with
"Could not capture a stable screenshot within 15000ms" because the test
was calling toMatchScreenshot() before Monaco editor finished initializing.

The waitFor only checked for the form error message DOM element, which
appears before Monaco completes its multi-phase async initialization
(dynamic imports → syntax highlighting → height recalculation). The
toMatchScreenshot stability loop then burned its timeout comparing
rapidly-changing initialization states.

Fix:
- Wait for `.monaco-editor` in DOM before proceeding to screenshot
- Bump waitFor timeout to 20s for Monaco initialization
- Bump test-level timeout to 45s for full test lifecycle
- Bump global toMatchScreenshot timeout from 15s to 20s

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: update reference screenshot to match fully-initialized Monaco state

The previous reference (258×126px) was captured when Monaco rendered at a
different height. After the CI runner upgrade and with proper initialization
waiting, Monaco consistently renders at 258×95px. Update the reference to
match the CI-generated actual screenshot.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: suppress Monaco web worker unhandled errors in browser tests

Monaco's web worker initialization throws "Cannot use import statement
outside a module" in the browser test environment, then falls back to
main-thread execution. This doesn't affect test correctness but Vitest
treats unhandled errors as failures, causing CI exit code 1 even when
all test assertions pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* revert: remove ineffective onUnhandledError suppression

The Monaco web worker errors originate in the browser context, not in
the Node.js test runner, so onUnhandledError cannot intercept them.
The failing ubuntu-latest CI runner has this as a pre-existing issue
(main also fails on it). The ubuntu-16gb runner passes all checks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: handle browser-serialized errors in onUnhandledError

Browser-originated errors lose their Error prototype during
serialization, so `instanceof Error` fails. Use String coercion to
extract the message from both Error instances and serialized objects.

Also suppress Monaco web worker "Cannot use import statement outside a
module" errors — Monaco falls back to main-thread execution, which does
not affect test correctness.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: access .message directly on serialized browser errors

Browser errors may arrive as plain objects with a message property but
without the Error prototype. Access .message directly with a type
assertion instead…
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.