Skip to content

chore: sync main into alpha (manual merge)#1351

Merged
markturansky merged 110 commits intoalphafrom
chore/rebase-main-to-alpha-manual
Apr 17, 2026
Merged

chore: sync main into alpha (manual merge)#1351
markturansky merged 110 commits intoalphafrom
chore/rebase-main-to-alpha-manual

Conversation

@markturansky
Copy link
Copy Markdown
Contributor

@markturansky markturansky commented Apr 17, 2026

Summary

  • Manually merges main into alpha, resolving 13 conflicted files
  • Brings alpha up to date with 109 commits from main (observability dashboard, gh wrapper, session creation docs, etc.)
  • Preserves all alpha-only features (control-plane, MCP, kubeconfig credential provider, gRPC runner)

Conflict Resolution Strategy

< /dev/null | File | Strategy |
|------|----------|
| Makefile | Combined all targets: control-plane + mcp (alpha) + observability-dashboard (main) |
| auth.py | Kept kubeconfig block (alpha) + gh wrapper install (main) |
| bridge.py | Kept both asyncio (alpha) + json (main) imports |
| pyproject.toml | Main's tighter versions + alpha's grpc/protobuf/cryptography |
| observability.py | Main's refactored end_turn with null checks |
| model.go | Main's full agent fields + BeforeCreate defaults |
| kustomization.yaml | Both control_plane (alpha) + observability (main) images |
| frontend/DEVELOPMENT.md | Both session stream (alpha) + session creation (main) docs |
| test file | Both bot token (alpha) + gh wrapper (main) tests |
| uv.lock | Taken from main |
| SKILL.md, build-deploy.yml, backend/DEVELOPMENT.md | Minor header/path differences resolved |

Test plan

  • CI passes on the PR
  • Verify no conflict markers remain (rg '<<<<<<')
  • Spot-check merged Makefile targets work

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Pre-upload workspace files (before session pod start), live model switching, scheduled sessions with edit, MCP server config at project/session, Advanced SDK options UI, new agent/skill automations (align, amber-review, pr-fixer, cypress-demo, scaffold, etc.), LDAP SRV + bind auth.
  • Improvements

    • Session status caching and SSAR caching for performance, polling gated by tab visibility, stricter token/expiration validation, improved error handling, CI/workflow and docs automation, image metadata includes commit info.

Gkrumbach07 and others added 30 commits April 2, 2026 09:22
…1153)

## Summary
- `BOT_TOKEN` was only injected into the **init container**, not the
main runner container
- The runner uses `BOT_TOKEN` to authenticate with the backend when
auto-executing `INITIAL_PROMPT` via `/agui/run`
- Without it, all sessions with an initial prompt fail with `401: User
token required`

## Root cause
The operator sets `BOT_TOKEN` from the runner token secret at line 936
(init container env), but the main runner container (line 1001+) never
receives it. `get_bot_token()` returns `None`, so the request has no
`Authorization` header.

## Fix
Inject the same `BOT_TOKEN` env var (from the runner token secret) into
the main runner container.

## Test plan
- [ ] Create a session with an initial prompt — verify it auto-executes
without 401
- [ ] Create a scheduled session — verify trigger creates session and
prompt executes
- [ ] Verify existing sessions without initial prompt are unaffected

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Bug Fixes

- Automatic execution now fetches and rebuilds authentication headers
within the retry loop instead of fetching them once before retries,
ensuring each retry attempt uses the latest token value.
- Expanded retry conditions to include authentication-related failures,
alongside previously handled error scenarios such as service
unavailability and server errors during startup.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… updates (#1155)

Bumps the npm_and_yarn group with 5 updates in the /components/frontend
directory:

| Package | From | To |
| --- | --- | --- |
| [file-type](https://github.com/sindresorhus/file-type) | `21.3.0` |
`21.3.2` |
| [next](https://github.com/vercel/next.js) | `16.1.5` | `16.2.2` |
| [minimatch](https://github.com/isaacs/minimatch) | `3.1.2` | `3.1.5` |
| [flatted](https://github.com/WebReflection/flatted) | `3.3.3` |
`3.4.2` |
| [undici](https://github.com/nodejs/undici) | `7.22.0` | `7.24.7` |

Bumps the npm_and_yarn group with 4 updates in the /docs directory:
[devalue](https://github.com/sveltejs/devalue),
[h3](https://github.com/h3js/h3),
[smol-toml](https://github.com/squirrelchat/smol-toml) and
[svgo](https://github.com/svg/svgo).
Bumps the npm_and_yarn group with 2 updates in the /e2e directory:
[lodash](https://github.com/lodash/lodash) and
[qs](https://github.com/ljharb/qs).

Updates `file-type` from 21.3.0 to 21.3.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/sindresorhus/file-type/releases">file-type's
releases</a>.</em></p>
<blockquote>
<h2>v21.3.2</h2>
<ul>
<li>Fix ZIP bomb in known-size ZIP probing (GHSA-j47w-4g3g-c36v)
a155cd7</li>
<li>Fix bound recursive BOM and ID3 detection  370ed91</li>
</ul>
<hr />
<p><a
href="https://github.com/sindresorhus/file-type/compare/v21.3.1...v21.3.2">https://github.com/sindresorhus/file-type/compare/v21.3.1...v21.3.2</a></p>
<h2>v21.3.1</h2>
<ul>
<li>Fix infinite loop in ASF parser on malformed input (<a
href="https://github.com/sindresorhus/file-type/security/advisories/GHSA-5v7r-6r5c-r473">https://github.com/sindresorhus/file-type/security/advisories/GHSA-5v7r-6r5c-r473</a>)
319abf8</li>
</ul>
<hr />
<p><a
href="https://github.com/sindresorhus/file-type/compare/v21.3.0...v21.3.1">https://github.com/sindresorhus/file-type/compare/v21.3.0...v21.3.1</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/sindresorhus/file-type/commit/e18028c3cc19441477c3459991fee9770d88c218"><code>e18028c</code></a>
21.3.2</li>
<li><a
href="https://github.com/sindresorhus/file-type/commit/a155cd71323279de173c54e8c530d300d3854fdd"><code>a155cd7</code></a>
Fix ZIP bomb in known-size ZIP probing</li>
<li><a
href="https://github.com/sindresorhus/file-type/commit/69548179cca2c0ab6a0cc93af59392f8c351cab1"><code>6954817</code></a>
Harden parser more</li>
<li><a
href="https://github.com/sindresorhus/file-type/commit/370ed9185d112eea4d989fecb843597b1d94cf09"><code>370ed91</code></a>
Fix bound recursive BOM and ID3 detection</li>
<li><a
href="https://github.com/sindresorhus/file-type/commit/d2ecea187c47b944a9c001ae7637f02baed0825a"><code>d2ecea1</code></a>
Add a few more safeguards</li>
<li><a
href="https://github.com/sindresorhus/file-type/commit/41fcff5de64cfb53da6b2b9c048ebea8213f32c2"><code>41fcff5</code></a>
Update readme</li>
<li><a
href="https://github.com/sindresorhus/file-type/commit/a8f6934ddd93c3e12cc4ecb0cfc3e8d816d4b9fd"><code>a8f6934</code></a>
Fix CI</li>
<li><a
href="https://github.com/sindresorhus/file-type/commit/ad5857e5384874e853cc9c4c29b867f1135a7c30"><code>ad5857e</code></a>
21.3.1</li>
<li><a
href="https://github.com/sindresorhus/file-type/commit/5d2fedf104dc5067b51a1f31410aa60052c74f64"><code>5d2fedf</code></a>
Harden parser</li>
<li><a
href="https://github.com/sindresorhus/file-type/commit/319abf871b50ba2fa221b4a7050059f1ae096f4f"><code>319abf8</code></a>
Fix infinite loop in ASF parser on malformed input</li>
<li>Additional commits viewable in <a
href="https://github.com/sindresorhus/file-type/compare/v21.3.0...v21.3.2">compare
view</a></li>
</ul>
</details>
<br />

Updates `next` from 16.1.5 to 16.2.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/vercel/next.js/releases">next's
releases</a>.</em></p>
<blockquote>
<h2>v16.2.2</h2>
<blockquote>
<p>[!NOTE]
This release is backporting bug fixes. It does <strong>not</strong>
include all pending features/changes on canary.</p>
</blockquote>
<h3>Core Changes</h3>
<ul>
<li>backport: Move expanded adapters docs to API reference (<a
href="https://redirect.github.com/vercel/next.js/issues/92115">#92115</a>)
(<a
href="https://redirect.github.com/vercel/next.js/issues/92129">#92129</a>)</li>
<li>Backport: TypeScript v6 deprecations for baseUrl and
moduleResolution (<a
href="https://redirect.github.com/vercel/next.js/issues/92130">#92130</a>)</li>
<li>[create-next-app] Skip interactive prompts when CLI flags are
provided (<a
href="https://redirect.github.com/vercel/next.js/issues/91840">#91840</a>)</li>
<li>next.config.js: Accept an option for serverFastRefresh (<a
href="https://redirect.github.com/vercel/next.js/issues/91968">#91968</a>)</li>
<li>Turbopack: enable server HMR for app route handlers (<a
href="https://redirect.github.com/vercel/next.js/issues/91466">#91466</a>)</li>
<li>Turbopack: exclude metadata routes from server HMR (<a
href="https://redirect.github.com/vercel/next.js/issues/92034">#92034</a>)</li>
<li>Fix CI for glibc linux builds</li>
<li>Backport: disable bmi2 in qfilter <a
href="https://redirect.github.com/vercel/next.js/issues/92177">#92177</a></li>
<li>[backport] Fix CSS HMR on Safari (<a
href="https://redirect.github.com/vercel/next.js/issues/92174">#92174</a>)</li>
</ul>
<h3>Credits</h3>
<p>Huge thanks to <a
href="https://github.com/nextjs-bot"><code>@​nextjs-bot</code></a>, <a
href="https://github.com/icyJoseph"><code>@​icyJoseph</code></a>, <a
href="https://github.com/ijjk"><code>@​ijjk</code></a>, <a
href="https://github.com/gaojude"><code>@​gaojude</code></a>, <a
href="https://github.com/wbinnssmith"><code>@​wbinnssmith</code></a>, <a
href="https://github.com/lukesandberg"><code>@​lukesandberg</code></a>,
and <a href="https://github.com/bgw"><code>@​bgw</code></a> for
helping!</p>
<h2>v16.2.1</h2>
<blockquote>
<p>[!NOTE]
This release is backporting bug fixes. It does <strong>not</strong>
include all pending features/changes on canary.</p>
</blockquote>
<h3>Core Changes</h3>
<ul>
<li>docs: post release amends (<a
href="https://redirect.github.com/vercel/next.js/issues/91715">#91715</a>)</li>
<li>docs: fix broken Activity Patterns demo link in preserving UI state
guide (<a
href="https://redirect.github.com/vercel/next.js/issues/91698">#91698</a>)</li>
<li>Fix adapter outputs for dynamic metadata routes (<a
href="https://redirect.github.com/vercel/next.js/issues/91680">#91680</a>)</li>
<li>Turbopack: fix webpack loader runner layer (<a
href="https://redirect.github.com/vercel/next.js/issues/91727">#91727</a>)</li>
<li>Fix server actions in standalone mode with
<code>cacheComponents</code> (<a
href="https://redirect.github.com/vercel/next.js/issues/91711">#91711</a>)</li>
<li>turbo-persistence: remove Unmergeable mmap advice (<a
href="https://redirect.github.com/vercel/next.js/issues/91713">#91713</a>)</li>
<li>Fix layout segment optimization: move app-page imports to
server-utility transition (<a
href="https://redirect.github.com/vercel/next.js/issues/91701">#91701</a>)</li>
<li>Turbopack: lazy require metadata and handle TLA (<a
href="https://redirect.github.com/vercel/next.js/issues/91705">#91705</a>)</li>
<li>[turbopack] Respect <code>{eval:true}</code> in worker_threads
constructors (<a
href="https://redirect.github.com/vercel/next.js/issues/91666">#91666</a>)</li>
</ul>
<h3>Credits</h3>
<p>Huge thanks to <a
href="https://github.com/icyJoseph"><code>@​icyJoseph</code></a>, <a
href="https://github.com/abhishekmardiya"><code>@​abhishekmardiya</code></a>,
<a href="https://github.com/ijjk"><code>@​ijjk</code></a>, <a
href="https://github.com/mischnic"><code>@​mischnic</code></a>, <a
href="https://github.com/unstubbable"><code>@​unstubbable</code></a>, <a
href="https://github.com/sokra"><code>@​sokra</code></a>, and <a
href="https://github.com/lukesandberg"><code>@​lukesandberg</code></a>
for helping!</p>
<h2>v16.2.1-canary.17</h2>
<h3>Core Changes</h3>
<ul>
<li>Improve revalidateTag JSDoc to include guidance about required
second parameter: <a
href="https://redirect.github.com/vercel/next.js/issues/92176">#92176</a></li>
<li>partial fallbacks: adapter support for intermediate shells: <a
href="https://redirect.github.com/vercel/next.js/issues/91902">#91902</a></li>
<li>docs: clarify id, filePath, and pathname in STATIC_FILE adapter
output: <a
href="https://redirect.github.com/vercel/next.js/issues/92227">#92227</a></li>
<li>feat: add NEXT_HASH_SALT env var for content-hash filename salting:
<a
href="https://redirect.github.com/vercel/next.js/issues/91871">#91871</a></li>
<li>Generate a CLI warning if using Rosetta 2 on Apple Silicon: <a
href="https://redirect.github.com/vercel/next.js/issues/92220">#92220</a></li>
</ul>
<h3>Misc Changes</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/vercel/next.js/commit/52faae3d94641584e13691238df5be158d0f00fb"><code>52faae3</code></a>
v16.2.2</li>
<li><a
href="https://github.com/vercel/next.js/commit/8d0f77bfa210691875c264fdf83cfee4e9ae418f"><code>8d0f77b</code></a>
Backport: <a
href="https://redirect.github.com/vercel/next.js/issues/92177">#92177</a></li>
<li><a
href="https://github.com/vercel/next.js/commit/e151e5f84285ac569cf2ec311873200511eea8b3"><code>e151e5f</code></a>
Fix CI for glibc linux builds</li>
<li><a
href="https://github.com/vercel/next.js/commit/1a319ea4dc564974371f9e7ff0f3693512fa018c"><code>1a319ea</code></a>
[backport] Fix CSS HMR on Safari (<a
href="https://redirect.github.com/vercel/next.js/issues/92174">#92174</a>)</li>
<li><a
href="https://github.com/vercel/next.js/commit/c0edad2762d309cf9125c1dee361227c0f4327d1"><code>c0edad2</code></a>
Turbopack: exclude metadata routes from server HMR (<a
href="https://redirect.github.com/vercel/next.js/issues/92034">#92034</a>)</li>
<li><a
href="https://github.com/vercel/next.js/commit/d6446990d929c5560d652ce76634b450be057b4e"><code>d644699</code></a>
Turbopack: enable server HMR for app route handlers (<a
href="https://redirect.github.com/vercel/next.js/issues/91466">#91466</a>)</li>
<li><a
href="https://github.com/vercel/next.js/commit/34de2cac2918aa570a4c12c6e3ae9ed3d70d1f7a"><code>34de2ca</code></a>
next.config.js: Accept an option for serverFastRefresh (<a
href="https://redirect.github.com/vercel/next.js/issues/91968">#91968</a>)</li>
<li><a
href="https://github.com/vercel/next.js/commit/c4779d1b085a563f39faea86f7b84d5d9adc4f72"><code>c4779d1</code></a>
[create-next-app] Skip interactive prompts when CLI flags are provided
(<a
href="https://redirect.github.com/vercel/next.js/issues/91840">#91840</a>)</li>
<li><a
href="https://github.com/vercel/next.js/commit/edcf19ae132b5853bb9f9c41888887f7830c19ad"><code>edcf19a</code></a>
Backport: TypeScript v6 deprecations for baseUrl and moduleResolution
(<a
href="https://redirect.github.com/vercel/next.js/issues/92130">#92130</a>)</li>
<li><a
href="https://github.com/vercel/next.js/commit/eee3f524e9f7b322cbd82999fb0f4b90585cc7bf"><code>eee3f52</code></a>
backport: Move expanded adapters docs to API reference (<a
href="https://redirect.github.com/vercel/next.js/issues/92115">#92115</a>)
(<a
href="https://redirect.github.com/vercel/next.js/issues/92129">#92129</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/vercel/next.js/compare/v16.1.5...v16.2.2">compare
view</a></li>
</ul>
</details>
<br />

Updates `minimatch` from 3.1.2 to 3.1.5
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/isaacs/minimatch/commit/7bba97888a27a6162983056bcce2a6e28f668712"><code>7bba978</code></a>
3.1.5</li>
<li><a
href="https://github.com/isaacs/minimatch/commit/bd259425b2ca17b42897997f93e890314155522d"><code>bd25942</code></a>
docs: add warning about ReDoS</li>
<li><a
href="https://github.com/isaacs/minimatch/commit/1a9c27c75725474dbde57db2995b6281b267756d"><code>1a9c27c</code></a>
fix partial matching of globstar patterns</li>
<li><a
href="https://github.com/isaacs/minimatch/commit/1a2e084af579731af66c221214e3ca8222c9bf23"><code>1a2e084</code></a>
3.1.4</li>
<li><a
href="https://github.com/isaacs/minimatch/commit/ae24656237c3d58067442f790ce17eff84463a47"><code>ae24656</code></a>
update lockfile</li>
<li><a
href="https://github.com/isaacs/minimatch/commit/b1003749228b2a79e1f237963a0d559ef7a0941e"><code>b100374</code></a>
limit recursion for **, improve perf considerably</li>
<li><a
href="https://github.com/isaacs/minimatch/commit/26ffeaa091b9f660833e23f42e07165b33e85c13"><code>26ffeaa</code></a>
lockfile update</li>
<li><a
href="https://github.com/isaacs/minimatch/commit/9eca892a4e5dbb20534f9f30483b85cdeee6c2eb"><code>9eca892</code></a>
lock node version to 14</li>
<li><a
href="https://github.com/isaacs/minimatch/commit/00c323b188b704e5d4bc534ecec2268cfa70a32a"><code>00c323b</code></a>
3.1.3</li>
<li><a
href="https://github.com/isaacs/minimatch/commit/30486b2048929264f44d18822891cfffa02af78b"><code>30486b2</code></a>
update CI matrix and actions</li>
<li>Additional commits viewable in <a
href="https://github.com/isaacs/minimatch/compare/v3.1.2...v3.1.5">compare
view</a></li>
</ul>
</details>
<br />

Updates `flatted` from 3.3.3 to 3.4.2
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/WebReflection/flatted/commit/3bf09091c3562e17a0647bc06710dd6097079cf7"><code>3bf0909</code></a>
3.4.2</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/885ddcc33cf9657caf38c57c7be45ae1c5272802"><code>885ddcc</code></a>
fix CWE-1321</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/0bdba705d130f00892b1b8fcc80cf4cdea0631e3"><code>0bdba70</code></a>
added flatted-view to the benchmark</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/2a02dce7c641dec31194c67663f9b0b12e62da20"><code>2a02dce</code></a>
3.4.1</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/fba4e8f2e113665da275b19cd0f695f3d98e9416"><code>fba4e8f</code></a>
Merge pull request <a
href="https://redirect.github.com/WebReflection/flatted/issues/89">#89</a>
from WebReflection/python-fix</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/5fe86485e6df7f7f34a07a2a85498bd3e17384e7"><code>5fe8648</code></a>
added &quot;when in Rome&quot; also a test for PHP</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/53517adbefe724fe472b2f9ebcdb01910d0ae3f0"><code>53517ad</code></a>
some minor improvement</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/b3e2a0c387bf446435fec45ad7f05299f012346f"><code>b3e2a0c</code></a>
Fixing recursion issue in Python too</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/c4b46dbcbf782326e54ea1b65d3ebb1dc7a23fad"><code>c4b46db</code></a>
Add SECURITY.md for security policy and reporting</li>
<li><a
href="https://github.com/WebReflection/flatted/commit/f86d071e0f70de5a7d8200198824a3f07fc9c988"><code>f86d071</code></a>
Create dependabot.yml for version updates</li>
<li>Additional commits viewable in <a
href="https://github.com/WebReflection/flatted/compare/v3.3.3...v3.4.2">compare
view</a></li>
</ul>
</details>
<br />

Updates `undici` from 7.22.0 to 7.24.7
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/nodejs/undici/releases">undici's
releases</a>.</em></p>
<blockquote>
<h2>v7.24.7</h2>
<h2>What's Changed</h2>
<ul>
<li>docs: update broken links in file &quot;Dispatcher.md&quot; by <a
href="https://github.com/samuel871211"><code>@​samuel871211</code></a>
in <a
href="https://redirect.github.com/nodejs/undici/pull/4924">nodejs/undici#4924</a></li>
<li>doc: remove unused parameter <code>redirectionLimitReached</code> by
<a
href="https://github.com/samuel871211"><code>@​samuel871211</code></a>
in <a
href="https://redirect.github.com/nodejs/undici/pull/4933">nodejs/undici#4933</a></li>
<li>test: skip flaky macOS Node 20 cookie fetch cases by <a
href="https://github.com/mcollina"><code>@​mcollina</code></a> in <a
href="https://redirect.github.com/nodejs/undici/pull/4932">nodejs/undici#4932</a></li>
<li>fix(types): align Response with DOM fetch types by <a
href="https://github.com/theamodhshetty"><code>@​theamodhshetty</code></a>
in <a
href="https://redirect.github.com/nodejs/undici/pull/4867">nodejs/undici#4867</a></li>
<li>fix(types): Fix clone method type declaration to be an instance
method rather than instance property by <a
href="https://github.com/mistval"><code>@​mistval</code></a> in <a
href="https://redirect.github.com/nodejs/undici/pull/4925">nodejs/undici#4925</a></li>
<li>test: skip IPv6 tests when IPv6 is not available by <a
href="https://github.com/mcollina"><code>@​mcollina</code></a> in <a
href="https://redirect.github.com/nodejs/undici/pull/4939">nodejs/undici#4939</a></li>
<li>fix: correctly handle multi-value rawHeaders in fetch by <a
href="https://github.com/mcollina"><code>@​mcollina</code></a> in <a
href="https://redirect.github.com/nodejs/undici/pull/4938">nodejs/undici#4938</a></li>
<li>ignore AGENTS.md by <a
href="https://github.com/mcollina"><code>@​mcollina</code></a> in <a
href="https://redirect.github.com/nodejs/undici/pull/4942">nodejs/undici#4942</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/samuel871211"><code>@​samuel871211</code></a>
made their first contribution in <a
href="https://redirect.github.com/nodejs/undici/pull/4924">nodejs/undici#4924</a></li>
<li><a href="https://github.com/mistval"><code>@​mistval</code></a> made
their first contribution in <a
href="https://redirect.github.com/nodejs/undici/pull/4925">nodejs/undici#4925</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/nodejs/undici/compare/v7.24.6...v7.24.7">https://github.com/nodejs/undici/compare/v7.24.6...v7.24.7</a></p>
<h2>v7.24.6</h2>
<h2>What's Changed</h2>
<ul>
<li>fix(test): client wasm compatible with clang 22 by <a
href="https://github.com/rozzilla"><code>@​rozzilla</code></a> in <a
href="https://redirect.github.com/nodejs/undici/pull/4909">nodejs/undici#4909</a></li>
<li>fix(mock): improve error message when intercepts are exhausted by <a
href="https://github.com/travisbreaks"><code>@​travisbreaks</code></a>
in <a
href="https://redirect.github.com/nodejs/undici/pull/4912">nodejs/undici#4912</a></li>
<li>fix(websocket): support open diagnostics over h2 by <a
href="https://github.com/mcollina"><code>@​mcollina</code></a> in <a
href="https://redirect.github.com/nodejs/undici/pull/4921">nodejs/undici#4921</a></li>
<li>fix: assume http/https scheme for scheme-less proxy env vars by <a
href="https://github.com/travisbreaks"><code>@​travisbreaks</code></a>
in <a
href="https://redirect.github.com/nodejs/undici/pull/4914">nodejs/undici#4914</a></li>
<li>fix(cache): check Authorization on request headers per RFC 9111 §3.5
by <a href="https://github.com/metalix2"><code>@​metalix2</code></a> in
<a
href="https://redirect.github.com/nodejs/undici/pull/4911">nodejs/undici#4911</a></li>
<li>fix: wrap kConnector call in try/catch to prevent client hang by <a
href="https://github.com/veeceey"><code>@​veeceey</code></a> in <a
href="https://redirect.github.com/nodejs/undici/pull/4834">nodejs/undici#4834</a></li>
<li>docs: clarify fetch and FormData pairing by <a
href="https://github.com/mcollina"><code>@​mcollina</code></a> in <a
href="https://redirect.github.com/nodejs/undici/pull/4922">nodejs/undici#4922</a></li>
<li>fix: support Connection header with connection-specific header names
per RFC 7230 by <a
href="https://github.com/mcollina"><code>@​mcollina</code></a> in <a
href="https://redirect.github.com/nodejs/undici/pull/4775">nodejs/undici#4775</a></li>
<li>fix: avoid prototype collisions in parseHeaders by <a
href="https://github.com/mcollina"><code>@​mcollina</code></a> in <a
href="https://redirect.github.com/nodejs/undici/pull/4923">nodejs/undici#4923</a></li>
<li>build(deps-dev): bump typescript from 5.9.3 to 6.0.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/nodejs/undici/pull/4926">nodejs/undici#4926</a></li>
<li>test: auto-init WPT submodule by <a
href="https://github.com/mcollina"><code>@​mcollina</code></a> in <a
href="https://redirect.github.com/nodejs/undici/pull/4930">nodejs/undici#4930</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/rozzilla"><code>@​rozzilla</code></a>
made their first contribution in <a
href="https://redirect.github.com/nodejs/undici/pull/4909">nodejs/undici#4909</a></li>
<li><a href="https://github.com/veeceey"><code>@​veeceey</code></a> made
their first contribution in <a
href="https://redirect.github.com/nodejs/undici/pull/4834">nodejs/undici#4834</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/nodejs/undici/compare/v7.24.5...v7.24.6">https://github.com/nodejs/undici/compare/v7.24.5...v7.24.6</a></p>
<h2>v7.24.5</h2>
<h2>What's Changed</h2>
<ul>
<li>Formdata tests by <a
href="https://github.com/KhafraDev"><code>@​KhafraDev</code></a> in <a
href="https://redirect.github.com/nodejs/undici/pull/4902">nodejs/undici#4902</a></li>
<li>test: add unexpected disconnect guards to more client test files by
<a href="https://github.com/samayer12"><code>@​samayer12</code></a> in
<a
href="https://redirect.github.com/nodejs/undici/pull/4844">nodejs/undici#4844</a></li>
<li>fix(cache): only apply 1-year deleteAt for immutable responses by <a
href="https://github.com/metalix2"><code>@​metalix2</code></a> in <a
href="https://redirect.github.com/nodejs/undici/pull/4913">nodejs/undici#4913</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/metalix2"><code>@​metalix2</code></a>
made their first contribution in <a
href="https://redirect.github.com/nodejs/undici/pull/4913">nodejs/undici#4913</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/nodejs/undici/compare/v7.24.4...v7.24.5">https://github.com/nodejs/undici/compare/v7.24.4...v7.24.5</a></p>
<h2>v7.24.4</h2>
<h2>What's Changed</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/nodejs/undici/commit/84f23e2a19cd0f585579c4257d801e4ec2d65dbd"><code>84f23e2</code></a>
Bumped v7.24.7 (<a
href="https://redirect.github.com/nodejs/undici/issues/4947">#4947</a>)</li>
<li><a
href="https://github.com/nodejs/undici/commit/a770b1033201984b9e8082a9bf955414bff5dc2e"><code>a770b10</code></a>
ignore AGENTS.md (<a
href="https://redirect.github.com/nodejs/undici/issues/4942">#4942</a>)</li>
<li><a
href="https://github.com/nodejs/undici/commit/6acd19beaf67c1a2d07bcd38f40d0b751a81e7cc"><code>6acd19b</code></a>
fix: correctly handle multi-value rawHeaders in fetch (<a
href="https://redirect.github.com/nodejs/undici/issues/4938">#4938</a>)</li>
<li><a
href="https://github.com/nodejs/undici/commit/1da1c747c7d6e01b93ab295e0efb86623f3c8e06"><code>1da1c74</code></a>
test: skip IPv6 tests when IPv6 is not available (<a
href="https://redirect.github.com/nodejs/undici/issues/4939">#4939</a>)</li>
<li><a
href="https://github.com/nodejs/undici/commit/04cb77327f7ada95c2e5b67424cddcb22d7bf882"><code>04cb773</code></a>
fix(types): Fix clone method type declaration to be an instance method
rather...</li>
<li><a
href="https://github.com/nodejs/undici/commit/5145a7c47080d1715b2723591def3a75b0c3ba63"><code>5145a7c</code></a>
fix(types): align Response with DOM fetch types (<a
href="https://redirect.github.com/nodejs/undici/issues/4867">#4867</a>)</li>
<li><a
href="https://github.com/nodejs/undici/commit/ec236203064cf014667a5a5900c8a467adbdf7d6"><code>ec23620</code></a>
test: skip flaky macOS Node 20 cookie fetch cases</li>
<li><a
href="https://github.com/nodejs/undici/commit/555923591b2c91935835a23efd91ffed189a9378"><code>5559235</code></a>
doc: remove unused parameter <code>redirectionLimitReached</code> (<a
href="https://redirect.github.com/nodejs/undici/issues/4933">#4933</a>)</li>
<li><a
href="https://github.com/nodejs/undici/commit/a4e4b84d42140db8128369b53120382ffaff9ce0"><code>a4e4b84</code></a>
docs: update broken links in file &quot;Dispatcher.md&quot; (<a
href="https://redirect.github.com/nodejs/undici/issues/4924">#4924</a>)</li>
<li><a
href="https://github.com/nodejs/undici/commit/38eab360daff8f72927dd6083e755ca37d6d624e"><code>38eab36</code></a>
Bumped v7.24.6 (<a
href="https://redirect.github.com/nodejs/undici/issues/4931">#4931</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/nodejs/undici/compare/v7.22.0...v7.24.7">compare
view</a></li>
</ul>
</details>
<br />

Updates `devalue` from 5.6.3 to 5.6.4
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/sveltejs/devalue/releases">devalue's
releases</a>.</em></p>
<blockquote>
<h2>v5.6.4</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p>87c1f3c: fix: reject <code>__proto__</code> keys in malformed
<code>Object</code> wrapper payloads</p>
<p>This validates the <code>&quot;Object&quot;</code> parse path and
throws when the wrapped value has an own <code>__proto__</code> key.</p>
</li>
<li>
<p>40f1db1: fix: ensure sparse array indices are integers</p>
</li>
<li>
<p>87c1f3c: fix: disallow <code>__proto__</code> keys in null-prototype
object parsing</p>
<p>This disallows <code>__proto__</code> keys in the
<code>&quot;null&quot;</code> parse path so null-prototype object
hydration cannot carry that key through parse/unflatten.</p>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/sveltejs/devalue/blob/main/CHANGELOG.md">devalue's
changelog</a>.</em></p>
<blockquote>
<h2>5.6.4</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p>87c1f3c: fix: reject <code>__proto__</code> keys in malformed
<code>Object</code> wrapper payloads</p>
<p>This validates the <code>&quot;Object&quot;</code> parse path and
throws when the wrapped value has an own <code>__proto__</code> key.</p>
</li>
<li>
<p>40f1db1: fix: ensure sparse array indices are integers</p>
</li>
<li>
<p>87c1f3c: fix: disallow <code>__proto__</code> keys in null-prototype
object parsing</p>
<p>This disallows <code>__proto__</code> keys in the
<code>&quot;null&quot;</code> parse path so null-prototype object
hydration cannot carry that key through parse/unflatten.</p>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/sveltejs/devalue/commit/6cbb3f51258e01d7769e2b3d77b6ce9ed060804b"><code>6cbb3f5</code></a>
Version Packages (<a
href="https://redirect.github.com/sveltejs/devalue/issues/133">#133</a>)</li>
<li><a
href="https://github.com/sveltejs/devalue/commit/40f1db13afdd65c8e2ebd02f684276c273ef81b0"><code>40f1db1</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/sveltejs/devalue/commit/87c1f3ce3759765a061cfe34843ecc4b0711ba8d"><code>87c1f3c</code></a>
Merge commit from fork</li>
<li>See full diff in <a
href="https://github.com/sveltejs/devalue/compare/v5.6.3...v5.6.4">compare
view</a></li>
</ul>
</details>
<br />

Updates `h3` from 1.15.5 to 1.15.11
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/h3js/h3/releases">h3's
releases</a>.</em></p>
<blockquote>
<h2>v1.15.11</h2>
<p><a
href="https://github.com/h3js/h3/compare/v1.15.10...v1.15.11">compare
changes</a></p>
<h3>🏡 Chore</h3>
<ul>
<li>Update defu to 6.1.6 (<a
href="https://github.com/h3js/h3/commit/6125485">6125485</a>)</li>
<li>Update deps (<a
href="https://github.com/h3js/h3/commit/4998dd8">4998dd8</a>)</li>
<li>Update cookie-es (<a
href="https://github.com/h3js/h3/commit/d166186">d166186</a>)</li>
</ul>
<h2>v1.15.10</h2>
<p><a
href="https://github.com/h3js/h3/compare/v1.15.9...v1.15.10">compare
changes</a></p>
<h3>🩹 Fixes</h3>
<ul>
<li>Preserve percent-encoded req.url in app event handler (<a
href="https://redirect.github.com/h3js/h3/pull/1355">#1355</a>)</li>
</ul>
<h3>❤️ Contributors</h3>
<ul>
<li>Sergio Azócar (<a
href="https://github.com/sergioazoc"><code>@​sergioazoc</code></a>)</li>
</ul>
<h2>v1.15.9</h2>
<p><a
href="https://github.com/h3js/h3/compare/v1.15.7...v1.15.9">compare
changes</a></p>
<h3>🩹 Fixes</h3>
<ul>
<li>Preserve <code>%25</code> in pathname (<a
href="https://github.com/h3js/h3/commit/1103df6">1103df6</a>)</li>
<li><strong>static:</strong> Prevent path traversal via double-encoded
dot segments (<code>%252e%252e</code>) (<a
href="https://github.com/h3js/h3/commit/c56683d">c56683d</a>)</li>
<li><strong>sse:</strong> Sanitize carriage returns in event stream data
and comments (<a
href="https://github.com/h3js/h3/commit/ba3c3fe">ba3c3fe</a>)</li>
</ul>
<h2>v1.15.8</h2>
<p><a
href="https://github.com/h3js/h3/compare/v1.15.7...v1.15.8">compare
changes</a></p>
<h3>🩹 Fixes</h3>
<ul>
<li>Preserve <code>%25</code> in pathname (<a
href="https://github.com/h3js/h3/commit/1103df6">1103df6</a>)</li>
</ul>
<h2>v1.15.7</h2>
<p><a
href="https://github.com/h3js/h3/compare/v1.15.6...v1.15.7">compare
changes</a></p>
<h3>🩹 Fixes</h3>
<ul>
<li><strong>static:</strong> Narrow path traversal check to match
<code>..</code> as a path segment only (<a
href="https://github.com/h3js/h3/commit/c049dc0">c049dc0</a>)</li>
<li><strong>app:</strong> Decode percent-encoded path segments to
prevent auth bypass (<a
href="https://github.com/h3js/h3/commit/313ea52">313ea52</a>)</li>
</ul>
<h3>💅 Refactors</h3>
<ul>
<li>Remove implicit event handler conversion warning (<a
href="https://redirect.github.com/h3js/h3/pull/1340">#1340</a>)</li>
</ul>
<h3>❤️ Contributors</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/h3js/h3/blob/v1.15.11/CHANGELOG.md">h3's
changelog</a>.</em></p>
<blockquote>
<h2>v1.15.11</h2>
<p><a
href="https://github.com/h3js/h3/compare/v1.15.10...v1.15.11">compare
changes</a></p>
<h3>🏡 Chore</h3>
<ul>
<li>Update defu to 6.1.6 (<a
href="https://github.com/h3js/h3/commit/6125485">6125485</a>)</li>
<li>Update deps (<a
href="https://github.com/h3js/h3/commit/4998dd8">4998dd8</a>)</li>
<li>Update cookie-es (<a
href="https://github.com/h3js/h3/commit/d166186">d166186</a>)</li>
</ul>
<h3>❤️ Contributors</h3>
<ul>
<li>Pooya Parsa (<a
href="https://github.com/pi0"><code>@​pi0</code></a>)</li>
</ul>
<h2>v1.15.10</h2>
<p><a
href="https://github.com/h3js/h3/compare/v1.15.9...v1.15.10">compare
changes</a></p>
<h3>🩹 Fixes</h3>
<ul>
<li>Preserve percent-encoded req.url in app event handler (<a
href="https://redirect.github.com/h3js/h3/pull/1355">#1355</a>)</li>
</ul>
<h3>🏡 Chore</h3>
<ul>
<li>Update deps (<a
href="https://github.com/h3js/h3/commit/26fec6f">26fec6f</a>)</li>
</ul>
<h3>❤️ Contributors</h3>
<ul>
<li>Pooya Parsa (<a
href="https://github.com/pi0"><code>@​pi0</code></a>)</li>
<li>Sergio Azócar (<a
href="https://github.com/sergioazoc"><code>@​sergioazoc</code></a>)</li>
</ul>
<h2>v1.15.9</h2>
<p><a
href="https://github.com/h3js/h3/compare/v1.15.7...v1.15.9">compare
changes</a></p>
<h3>🩹 Fixes</h3>
<ul>
<li>Preserve <code>%25</code> in pathname (<a
href="https://github.com/h3js/h3/commit/1103df6">1103df6</a>)</li>
<li><strong>static:</strong> Prevent path traversal via double-encoded
dot segments (<code>%252e%252e</code>) (<a
href="https://github.com/h3js/h3/commit/c56683d">c56683d</a>)</li>
<li><strong>sse:</strong> Sanitize carriage returns in event stream data
and comments (<a
href="https://github.com/h3js/h3/commit/ba3c3fe">ba3c3fe</a>)</li>
</ul>
<h3>🏡 Chore</h3>
<ul>
<li><strong>release:</strong> V1.15.8 (<a
href="https://github.com/h3js/h3/commit/e3b9c9e">e3b9c9e</a>)</li>
<li>Update deps (<a
href="https://github.com/h3js/h3/commit/23045df">23045df</a>)</li>
</ul>
<h3>❤️ Contributors</h3>
<ul>
<li>Pooya Parsa (<a
href="https://github.com/pi0"><code>@​pi0</code></a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/h3js/h3/commit/7b9f41fda6038d26a367c2a26a07ed83ee1dbaac"><code>7b9f41f</code></a>
chore(release): v1.15.11</li>
<li><a
href="https://github.com/h3js/h3/commit/d166186ed63de5a21fa4bb0aede4f4574994a3b5"><code>d166186</code></a>
chore: update cookie-es</li>
<li><a
href="https://github.com/h3js/h3/commit/4998dd8de60ddd6a182948e543143eaa56927399"><code>4998dd8</code></a>
chore: update deps</li>
<li><a
href="https://github.com/h3js/h3/commit/612548586357cbf0bad27bcb1b1615f4c40b1560"><code>6125485</code></a>
chore: update defu to 6.1.6</li>
<li><a
href="https://github.com/h3js/h3/commit/b72bb57060cf68e627575e0c350742f4fa8206fa"><code>b72bb57</code></a>
chore(release): v1.15.10</li>
<li><a
href="https://github.com/h3js/h3/commit/d8ef318fa9ce086036588443d683f97f9bb9faf8"><code>d8ef318</code></a>
remove resolutions for h3</li>
<li><a
href="https://github.com/h3js/h3/commit/26fec6ff549e646bef284b8df4e267ddb8fc0b67"><code>26fec6f</code></a>
chore: update deps</li>
<li><a
href="https://github.com/h3js/h3/commit/51ca9b3750a2a1426257c96e5a81001e3ec3bb42"><code>51ca9b3</code></a>
fix: preserve percent-encoded req.url in app event handler (<a
href="https://redirect.github.com/h3js/h3/issues/1355">#1355</a>)</li>
<li><a
href="https://github.com/h3js/h3/commit/4e8d43a7703d0d5c8bbc09748db1d8b9f3c51b42"><code>4e8d43a</code></a>
chore(release): v1.15.9</li>
<li><a
href="https://github.com/h3js/h3/commit/23045df515a67f00182b5f7ca126cbec40efda4d"><code>23045df</code></a>
chore: update deps</li>
<li>Additional commits viewable in <a
href="https://github.com/h3js/h3/compare/v1.15.5...v1.15.11">compare
view</a></li>
</ul>
</details>
<br />

Updates `smol-toml` from 1.6.0 to 1.6.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/squirrelchat/smol-toml/releases">smol-toml's
releases</a>.</em></p>
<blockquote>
<h2>v1.6.1</h2>
<p>This release addresses a minor security vulnerability where an
attacker-controlled TOML document can exploit an unrestricted recustion
and cause a stack overflow error with a document that contains thousands
of sucessive commented lines. Security advisory: <a
href="https://github.com/advisories/GHSA-v3rj-xjv7-4jmq">GHSA-v3rj-xjv7-4jmq</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/squirrelchat/smol-toml/commit/072b64fd0094b1d7d3bb1a124d282828069a7aa0"><code>072b64f</code></a>
chore: version bump</li>
<li><a
href="https://github.com/squirrelchat/smol-toml/commit/19a5dc74cb49f9fe809dd73c2b8934b4192b8393"><code>19a5dc7</code></a>
chore: upgrade dependencies and actions</li>
<li><a
href="https://github.com/squirrelchat/smol-toml/commit/f286f87778200504061a428b24d5e27ef5e1f360"><code>f286f87</code></a>
fix: don't use recursion in skipVoid</li>
<li>See full diff in <a
href="https://github.com/squirrelchat/smol-toml/compare/v1.6.0...v1.6.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `svgo` from 4.0.0 to 4.0.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/svg/svgo/releases">svgo's
releases</a>.</em></p>
<blockquote>
<h2>v4.0.1</h2>
<h2>What's Changed</h2>
<h3>Dependencies</h3>
<ul>
<li>Sets minimum version of <a
href="https://www.npmjs.com/package/sax">sax</a> (XML parser) to v1.5.0,
which improves built-in guards against entity expansion.</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li><a
href="https://svgo.dev/docs/plugins/removeEmptyContainers/">removeEmptyContainers</a>,
removed leftover <code>&lt;use&gt;</code> elements referencing an empty
container that were removed. By <a
href="https://github.com/johnkenny54"><code>@​johnkenny54</code></a> in
<a
href="https://redirect.github.com/svg/svgo/pull/2051">svg/svgo#2051</a></li>
<li><a
href="https://svgo.dev/docs/plugins/removeUnknownsAndDefaults/">removeUnknownsAndDefaults</a>,
don't remove attributes if they're referenced in attribute selectors
(CSS). By <a
href="https://github.com/SethFalco"><code>@​SethFalco</code></a> in <a
href="https://redirect.github.com/svg/svgo/pull/2144">svg/svgo#2144</a></li>
</ul>
<h3>Performance</h3>
<ul>
<li><a
href="https://svgo.dev/docs/plugins/convertPathData/">convertPathData</a>,
refactor to reduce redundant equality checks. By <a
href="https://github.com/Lorfdail"><code>@​Lorfdail</code></a> in <a
href="https://redirect.github.com/svg/svgo/pull/1764">svg/svgo#1764</a>
and <a
href="https://redirect.github.com/svg/svgo/pull/2135">svg/svgo#2135</a></li>
<li><a
href="https://svgo.dev/docs/plugins/removeHiddenElems/">removeHiddenElems</a>,
compute styles lazily. By <a
href="https://github.com/Lorfdail"><code>@​Lorfdail</code></a> in <a
href="https://redirect.github.com/svg/svgo/pull/1764">svg/svgo#1764</a>
and <a
href="https://redirect.github.com/svg/svgo/pull/2135">svg/svgo#2135</a></li>
</ul>
<h3>Other Changes</h3>
<ul>
<li>Plugins no longer include if they are enabled or disabled by
default, as this was written inconsistently. The
<code>--show-plugins</code> argument appends the presets a plugin is in
to the end of the line. By <a
href="https://github.com/viralcodex"><code>@​viralcodex</code></a> in <a
href="https://redirect.github.com/svg/svgo/pull/2174">svg/svgo#2174</a></li>
<li>Plugin/preset types to enforce the name start with
<code>preset-</code> if it is a preset (collection of plugins). By <a
href="https://github.com/SethFalco"><code>@​SethFalco</code></a> in <a
href="https://redirect.github.com/svg/svgo/pull/2178">svg/svgo#2178</a></li>
</ul>
<h2>Metrics</h2>
<p>Before and after of the browser bundle of each respective
version:</p>
<table>
<thead>
<tr>
<th></th>
<th>v4.0.0</th>
<th>v4.0.1</th>
<th>Delta</th>
</tr>
</thead>
<tbody>
<tr>
<td>svgo.browser.js</td>
<td>780.2 kB</td>
<td>781.5 kB</td>
<td>⬆️ 1.3 kB</td>
</tr>
</tbody>
</table>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/svg/svgo/commit/e691f5f85d9ff6c8f3bc75dc5150181d314b7f2d"><code>e691f5f</code></a>
Merge commit from fork</li>
<li><a
href="https://github.com/svg/svgo/commit/b1d9f1a5dd018ffcbd52b96678019ccf4312b22d"><code>b1d9f1a</code></a>
chore(deps): bump actions/upload-artifact from 6 to 7 (<a
href="https://redirect.github.com/svg/svgo/issues/2202">#2202</a>)</li>
<li><a
href="https://github.com/svg/svgo/commit/d724af1b75d9a76ffd0ff4aef95047a045deb2b6"><code>d724af1</code></a>
chore(deps): bump actions/checkout from 5 to 6 (<a
href="https://redirect.github.com/svg/svgo/issues/2195">#2195</a>)</li>
<li><a
href="https://github.com/svg/svgo/commit/4114b3236f4ee5d2e0db6506e09e2633d55bfab6"><code>4114b32</code></a>
chore(deps): bump actions/upload-artifact from 4 to 6 (<a
href="https://redirect.github.com/svg/svgo/issues/2196">#2196</a>)</li>
<li><a
href="https://github.com/svg/svgo/commit/c06d8f6899788defae9594537063c2f4307803e4"><code>c06d8f6</code></a>
chore: upgrade js-yaml and glob (<a
href="https://redirect.github.com/svg/svgo/issues/2191">#2191</a>)</li>
<li><a
href="https://github.com/svg/svgo/commit/26e86e5d722fbc1937446b23d53a1bf8e3f01e39"><code>26e86e5</code></a>
fix: remove unused &lt;use&gt; elements when deleting empty symbols (<a
href="https://redirect.github.com/svg/svgo/issues/2051">#2051</a>)</li>
<li><a
href="https://github.com/svg/svgo/commit/50c326bbff8eda6589f09504f87197b693ac6854"><code>50c326b</code></a>
perf: optimiztions to reduce regression test runtime (<a
href="https://redirect.github.com/svg/svgo/issues/2135">#2135</a>)</li>
<li><a
href="https://github.com/svg/svgo/commit/1f33cbe3aea1fd04d8272860d0356a5b107fd6cf"><code>1f33cbe</code></a>
ci: separate regression tests and write delta report (<a
href="https://redirect.github.com/svg/svgo/issues/2190">#2190</a>)</li>
<li><a
href="https://github.com/svg/svgo/commit/79a2167dc93aaff982686ec65846db714aae3e76"><code>79a2167</code></a>
ci: save test reports to artifacts (<a
href="https://redirect.github.com/svg/svgo/issues/2189">#2189</a>)</li>
<li><a
href="https://github.com/svg/svgo/commit/0ae52a02a5cc021e37d227a8d6ca68cf6ca28679"><code>0ae52a0</code></a>
chore(deps): bump actions/setup-node from 5 to 6 (<a
href="https://redirect.github.com/svg/svgo/issues/2187">#2187</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/svg/svgo/compare/v4.0.0...v4.0.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `lodash` from 4.17.23 to 4.18.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/lodash/lodash/releases">lodash's
releases</a>.</em></p>
<blockquote>
<h2>4.18.1</h2>
<h2>Bugs</h2>
<p>Fixes a <code>ReferenceError</code> issue in <code>lodash</code>
<code>lodash-es</code> <code>lodash-amd</code> and
<code>lodash.template</code> when using the <code>template</code> and
<code>fromPairs</code> functions from the modular builds. See <a
href="https://redirect.github.com/lodash/lodash/issues/6167#issuecomment-4165269769">lodash/lodash#6167</a></p>
<p>These defects were related to how lodash distributions are built from
the main branch using <a
href="https://github.com/lodash-archive/lodash-cli">https://github.com/lodash-archive/lodash-cli</a>.
When internal dependencies change inside lodash functions, equivalent
updates need to be made to a mapping in the lodash-cli. (hey, it was
ahead of its time once upon a time!). We know this, but we missed it in
the last release. It's the kind of thing that passes in CI, but fails bc
the build is not the same thing you tested.</p>
<p>There is no diff on main for this, but you can see the diffs for each
of the npm packages on their respective branches:</p>
<ul>
<li><code>lodash</code>: <a
href="https://github.com/lodash/lodash/compare/4.18.0-npm...4.18.1-npm">https://github.com/lodash/lodash/compare/4.18.0-npm...4.18.1-npm</a></li>
<li><code>lodash-es</code>: <a
href="https://github.com/lodash/lodash/compare/4.18.0-es...4.18.1-es">https://github.com/lodash/lodash/compare/4.18.0-es...4.18.1-es</a></li>
<li><code>lodash-amd</code>: <a
href="https://github.com/lodash/lodash/compare/4.18.0-amd...4.18.1-amd">https://github.com/lodash/lodash/compare/4.18.0-amd...4.18.1-amd</a></li>
<li><code>lodash.template</code><a
href="https://github.com/lodash/lodash/compare/4.18.0-npm-packages...4.18.1-npm-packages">https://github.com/lodash/lodash/compare/4.18.0-npm-packages...4.18.1-npm-packages</a></li>
</ul>
<h2>4.18.0</h2>
<h2>v4.18.0</h2>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/lodash/lodash/compare/4.17.23...4.18.0">https://github.com/lodash/lodash/compare/4.17.23...4.18.0</a></p>
<h3>Security</h3>
<p><strong><code>_.unset</code> / <code>_.omit</code></strong>: Fixed
prototype pollution via <code>constructor</code>/<code>prototype</code>
path traversal (<a
href="https://github.com/lodash/lodash/security/advisories/GHSA-f23m-r3pf-42rh">GHSA-f23m-r3pf-42rh</a>,
<a
href="https://github.com/lodash/lodash/commit/fe8d32eda854377349a4f922ab7655c8e5df9a0b">fe8d32e</a>).
Previously, array-wrapped path segments and primitive roots could bypass
the existing guards, allowing deletion of properties from built-in
prototypes. Now <code>constructor</code> and <code>prototype</code> are
blocked unconditionally as non-terminal path keys, matching
<code>baseSet</code>. Calls that previously returned <code>true</code>
and deleted the property now return <code>false</code> and leave the
target untouched.</p>
<p><strong><code>_.template</code></strong>: Fixed code injection via
<code>imports</code> keys (<a
href="https://github.com/lodash/lodash/security/advisories/GHSA-r5fr-rjxr-66jc">GHSA-r5fr-rjxr-66jc</a>,
CVE-2026-4800, <a
href="https://github.com/lodash/lodash/commit/879aaa93132d78c2f8d20c60279da9f8b21576d6">879aaa9</a>).
Fixes an incomplete patch for CVE-2021-23337. The <code>variable</code>
option was validated against <code>reForbiddenIdentifierChars</code> but
<code>importsKeys</code> was left unguarded, allowing code injection via
the same <code>Function()</code> constructor sink. <code>imports</code>
keys containing forbidden identifier characters now throw
<code>&quot;Invalid imports option passed into
_.template&quot;</code>.</p>
<h3>Docs</h3>
<ul>
<li>Add security notice for <code>_.template</code> in threat model and
API docs (<a
href="https://redirect.github.com/lodash/lodash/pull/6099">#6099</a>)</li>
<li>Document <code>lower &gt; upper</code> behavior in
<code>_.random</code> (<a
href="https://redirect.github.com/lodash/lodash/pull/6115">#6115</a>)</li>
<li>Fix quotes in <code>_.compact</code> jsdoc (<a
href="https://redirect.github.com/lodash/lodash/pull/6090">#6090</a>)</li>
</ul>
<h3><code>lodash.*</code> modular packages</h3>
<p><a
href="https://redirect.github.com/lodash/lodash/pull/6157">Diff</a></p>
<p>We have also regenerated and published a select number of the
<code>lodash.*</code> modular packages.</p>
<p>These modular packages had fallen out of sync significantly from the
minor/patch updates to lodash. Specifically, we have brought the
following packages up to parity w/ the latest lodash release because
they have had CVEs on them in the past:</p>
<ul>
<li><a
href="https://www.npmjs.com/package/lodash.orderby">lodash.orderby</a></li>
<li><a
href="https://www.npmjs.com/package/lodash.tonumber">lodash.tonumber</a></li>
<li><a
href="https://www.npmjs.com/package/lodash.trim">lodash.trim</a></li>
<li><a
href="https://www.npmjs.com/package/lodash.trimend">lodash.trimend</a></li>
<li><a
href="https://www.npmjs.com/package/lodash.sortedindexby">lodash.sortedindexby</a></li>
<li><a
href="https://www.npmjs.com/package/lodash.zipobjectdeep">lodash.zipobjectdeep</a></li>
<li><a
href="https://www.npmjs.com/package/lodash.unset">lodash.unset</a></li>
<li><a
href="https://www.npmjs.com/package/lodash.omit">lodash.omit</a></li>
<li><a
href="https://www.npmjs.com/package/lodash.template">lodash.template</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/lodash/lodash/commit/cb0b9b9212521c08e3eafe7c8cb0af1b42b6649e"><code>cb0b9b9</code></a>
release(patch): bump main to 4.18.1 (<a
href="https://redirect.github.com/lodash/lodash/issues/6177">#6177</a>)</li>
<li><a
href="https://github.com/lodash/lodash/commit/75535f57883b7225adb96de1cfc1cd4169cfcb51"><code>75535f5</code></a>
chore: prune stale advisory refs (<a
href="https://redirect.github.com/lodash/lodash/issues/6170">#6170</a>)</li>
<li><a
href="https://github.com/lodash/lodash/commit/62e91bc6a39c98d85b9ada8c44d40593deaf82a4"><code>62e91bc</code></a>
docs: remove n_ Node.js &lt; 6 REPL note from README (<a
href="https://redirect.github.com/lodash/lodash/issues/6165">#6165</a>)</li>
<li><a
href="https://github.com/lodash/lodash/commit/59be2de61f8aa9461c7856533b51d31b7d8babc4"><code>59be2de</code></a>
release(minor): bump to 4.18.0 (<a
href="https://redirect.github.com/lodash/lodash/issues/6161">#6161</a>)</li>
<li><a
href="https://github.com/lodash/lodash/commit/af634573030f979194871da7c68f79420992f53d"><code>af63457</code></a>
fix: broken tests for _.template 879aaa9</li>
<li><a
href="https://github.com/lodash/lodash/commit/1073a7693e1727e0cf3641e5f71f75ddcf8de7c0"><code>1073a76</code></a>
fix: linting issues</li>
<li><a
href="https://github.com/lodash/lodash/commit/879aaa93132d78c2f8d20c60279da9f8b21576d6"><code>879aaa9</code></a>
fix: validate imports keys in _.template</li>
<li><a
href="https://github.com/lodash/lodash/commit/fe8d32eda854377349a4f922ab7655c8e5df9a0b"><code>fe8d32e</code></a>
fix: block prototype pollution in baseUnset via constructor/prototype
traversal</li>
<li><a
href="https://github.com/lodash/lodash/commit/18ba0a32f42fd02117f096b032f89c984173462d"><code>18ba0a3</code></a>
refactor(fromPairs): use baseAssignValue for consistent assignment (<a
href="https://redirect.github.com/lodash/lodash/issues/6153">#6153</a>)</li>
<li><a
href="https://github.com/lodash/lodash/commit/b8190803d48d60b8c80ad45d39125f32fa618cb2"><code>b819080</code></a>
ci: add dist sync validation workflow (<a
href="https://redirect.github.com/lodash/lodash/issues/6137">#6137</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/lodash/lodash/compare/4.17.23...4.18.1">compare
view</a></li>
</ul>
</details>
<br />

Updates `qs` from 6.14.1 to 6.14.2
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/ljharb/qs/blob/main/CHANGELOG.md">qs's
changelog</a>.</em></p>
<blockquote>
<h2><strong>6.14.2</strong></h2>
<ul>
<li>[Fix] <code>parse</code>: mark overflow objects for indexed notation
exceeding <code>arrayLimit</code> (<a
href="https://redirect.github.com/ljharb/qs/issues/546">#546</a>)</li>
<li>[Fix] <code>arrayLimit</code> means max count, not max index, in
<code>combine</code>/<code>merge</code>/<code>parseArrayValue</code></li>
<li>[Fix] <code>parse</code>: throw on <code>arrayLimit</code> exceeded
with indexed notation when <code>throwOnLimitExceeded</code> is true (<a
href="https://redirect.github.com/ljharb/qs/issues/529">#529</a>)</li>
<li>[Fix] <code>parse</code>: enforce <code>arrayLimit</code> on
<code>comma</code>-parsed values</li>
<li>[Fix] <code>parse</code>: fix error message to reflect arrayLimit as
max index; remove extraneous comments (<a
href="https://redirect.github.com/ljharb/qs/issues/545">#545</a>)</li>
<li>[Robustness] avoid <code>.push</code>, use <code>void</code></li>
<li>[readme] document that <code>addQueryPrefix</code> does not add
<code>?</code> to empty output (<a
href="https://redirect.github.com/ljharb/qs/issues/418">#418</a>)</li>
<li>[readme] clarify <code>parseArrays</code> and
<code>arrayLimit</code> documentation (<a
href="https://redirect.github.com/ljharb/qs/issues/543">#543</a>)</li>
<li>[readme] replace runkit CI badge with shields.io check-runs
badge</li>
<li>[meta] fix changelog typo (<code>arrayLength</code> →
<code>arrayLimit</code>)</li>
<li>[actions] fix rebase workflow permissions</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/ljharb/qs/commit/bdcf0c7f82387c18ac8fabfccd2f440645cef47b"><code>bdcf0c7</code></a>
v6.14.2</li>
<li><a
href="https://github.com/ljharb/qs/commit/294db90c812ddbe7d7a35d5687c505fd21a2d6a2"><code>294db90</code></a>
[readme] document that <code>addQueryPrefix</code> does not add
<code>?</code> to empty output</li>
<li><a
href="https://github.com/ljharb/qs/commit/5c308e5516c270a78caa6f278465914090f91ec6"><code>5c308e5</code></a>
[readme] clarify <code>parseArrays</code> and <code>arrayLimit</code>
documentation</li>
<li><a
href="https://github.com/ljharb/qs/commit/6addf8cf738d529c54d91f6f3ffb6c1be91bbfdc"><code>6addf8c</code></a>
[Fix] <code>parse</code>: mark overflow objects for indexed notation
exceeding <code>arrayLimit</code></li>
<li><a
href="https://github.com/ljharb/qs/commit/cfc108f662326d6ab540f3545ef0b832baf83cdf"><code>cfc108f</code></a>
[Fix] <code>arrayLimit</code> means max count, not max index, in
<code>combine</code>/<code>merge</code>/`pars...</li>
<li><a
href="https://github.com/ljharb/qs/commit/febb64442a80e49200211fa38d3c96b58024ac77"><code>febb644</code></a>
[Fix] <code>parse</code>: throw on <code>arrayLimit</code> exceeded with
indexed notation when `thr...</li>
<li><a
href="https://github.com/ljharb/qs/commit/f6a7abff1f13d644db9b05fe4f2c98ada6bf8482"><code>f6a7abf</code></a>
[Fix] <code>parse</code>: enforce <code>arrayLimit</code> on
<code>comma</code>-parsed values</li>
<li><a
href="https://github.com/ljharb/qs/commit/fbc5206c25b4d1851cea683f02c10756c521d15a"><code>fbc5206</code></a>
[Fix] <code>parse</code>: fix error message to reflect arrayLimit as max
index; remove e...</li>
<li><a
href="https://github.com/ljharb/qs/commit/1b9a8b4e78c6aff4c22fa559107227f02fd0216a"><code>1b9a8b4</code></a>
[actions] fix rebase workflow permissions</li>
<li><a
href="https://github.com/ljharb/qs/commit/2a35775614e0fb46ac8a3060201a32a7c23a7fda"><code>2a35775</code></a>
[meta] fix changelog typo (<code>arrayLength</code> →
<code>arrayLimit</code>)</li>
<li>Additional commits viewable in <a
href="https://github.com/ljharb/qs/compare/v6.14.1...v6.14.2">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/ambient-code/platform/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…8s dashboard (#1018)

## Summary

- Moved Grafana resources (`grafana.yaml`, dashboards, RBAC) into the
`with-grafana` overlay
- Fixed Grafana Prometheus auth: init container injects SA token into
datasource config at pod startup
- Fixed PVC mount path (`/var/lib/grafana` instead of
`/var/lib/grafana/data`) so `grafana.db` persists across restarts
- Removed `GF_SECURITY_ADMIN_PASSWORD` env var that was resetting
password on every restart
- Added K8s infrastructure dashboards (cluster, nodes, namespace, pods)
- PVC is managed separately from kustomize so `make clean-observability`
preserves Grafana data

## Dashboards

| Dashboard | Screenshot | Description |
|-----------|------------|-------------|
| K8s Cluster Monitoring |
![](https://github.com/user-attachments/assets/077fac80-5995-4235-b634-c6f8d77e0e75)
| Cluster-level CPU, memory, network |
| K8s Nodes |
![](https://github.com/user-attachments/assets/342e8ccd-c9bc-4266-b2a4-29b8c5923b9e)
| Node-level resource usage |
| K8s Namespace |
![](https://github.com/user-attachments/assets/726da1b3-6390-46a6-8a3d-6fe23facd0fc)|
Namespace-level resource usage |
| K8s Pods |
![](https://github.com/user-attachments/assets/7f5ef084-d8d6-40db-9f1d-0252b0cbc281)
| Pod-level resource usage |

## Test plan

- [x] `make add-grafana` deploys without errors
- [x] `make clean-observability` removes stack but preserves PVC
- [x] Grafana password persists across pod restarts
- [x] All dashboards load and show data from Prometheus

> Note: These charts are taken from community dashboards like
https://github.com/dotdc/grafana-dashboards-kubernetes, so some data
might be missing depending on the cluster setup. I'll be addressing them
in another change request.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Introduced pre-provisioned Grafana dashboards for Kubernetes cluster
and pod monitoring, automatically deployed without manual configuration.
* Added simplified Grafana installation workflow using the `make
add-grafana` command.

* **Documentation**
  * Updated installation and cleanup instructions for Grafana.
  * Added comprehensive guide for managing and customizing dashboards.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Rahul Shetty <rashetty@redhat.com>
Co-authored-by: Jeremy Eder <jeder@redhat.com>
## Summary
The OPERATOR_IMAGE pinning step used `agentic-backend` but the actual
deployment is named `backend-api`. Fixed in all 3 deploy paths (main
push, dispatch, release).

## Test plan
- [ ] CI deploy succeeds without "deployment not found" error

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Updated deployment configuration in build and release workflows to
target the appropriate service container during environment variable
setup.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
)

## Summary

Re-fixes #1084. Kubernetes `TokenRequest` does not support non-expiring
tokens — the API server silently caps `ExpirationSeconds`, so tokens
expire regardless. The original PR offered a "No expiration" option that
was misleading.

- **Backend**: Require `expirationSeconds` (reject nil/≤0), reject
values exceeding 1 year (31536000s)
- **Frontend**: Remove "No expiration" option, extract shared
`EXPIRATION_OPTIONS` to `lib/constants.ts`, use shadcn `Select`
component
- **Tests**: 6 backend Ginkgo tests for expiration validation

## Changes

- `components/backend/handlers/permissions.go` — validate and enforce
max 1 year
- `components/backend/handlers/permissions_test.go` — expiration
validation tests
- `components/frontend/src/app/projects/[name]/keys/page.tsx` — use
shared constants, shadcn Select
- `components/frontend/src/lib/constants.ts` — shared
`EXPIRATION_OPTIONS` and `DEFAULT_EXPIRATION`
- `.gitignore` — add `.worktrees/` and `.claude/worktrees/`

## Test plan

- [x] Frontend unit tests pass (613 passed)
- [x] Backend unit tests pass (all packages)
- [x] Backend expiration validation: rejects missing, zero, negative,
>1yr; accepts 1yr and 90d
- [x] Local kind cluster deployed and manually verified
- [x] `tsc --noEmit` clean, all pre-commit hooks pass

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
  * Project keys now require an expiration time.
  * Predefined token lifetime options added with a 90-day default.

* **Improvements**
  * Maximum token lifetime capped at 1 year.
  * Token lifetime selector is disabled while creating a key.
  * “No expiration” option and related helper text removed.

* **Tests**
* Added validation tests covering expiration presence, bounds, and
accepted values.

* **Chores**
  * Minor config wording and workflow tweaks; gitignore updated.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: ambient-code[bot] <ambient-code[bot]@users.noreply.github.com>
## Summary
The trigger was posting follow-up prompts to `/run` but the runner's
AG-UI endpoint is at `/` (root). This caused 404 errors when trying to
reuse a running session.

## Test plan
- [ ] Trigger a scheduled session with reuse enabled while the session
is running — verify the follow-up prompt is sent successfully

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Refactor**
  * Updated internal request routing for improved endpoint handling.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary
Deploy fails with: `The Deployment "backend-api" is invalid:
spec.template.spec.containers[0].env[16].valueFrom: Invalid value: "":
may not be specified when value is not empty`

The manifest defined `OPERATOR_IMAGE` with `valueFrom` (ConfigMap ref),
but CI sets it as a plain `value` via `oc set env`. On the next
`kustomize apply`, K8s rejects the env var because it has both `value`
and `valueFrom` set.

## Fix
Remove the `OPERATOR_IMAGE` entry from the manifest — CI manages it
directly via `oc set env`.

## Test plan
- [ ] Deploy succeeds without the `value/valueFrom` conflict

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary
PR #1159 removed the `OPERATOR_IMAGE` env var from the backend
deployment manifest. It should stay — the manifest declares `valueFrom`
(ConfigMap ref) and CI writes the SHA tag to the ConfigMap. This keeps
the deployment declarative.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Updated backend deployment configuration to source environment
variables from ConfigMap instead of CI-based injection, providing
improved flexibility in managing operational settings.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary

Adds a daily GHA workflow that automatically detects new releases of
`claude-agent-sdk` and `anthropic` on PyPI, bumps `pyproject.toml` +
`uv.lock`, and opens a PR with an intelligent feature analysis report.

- **`scripts/sdk-version-bump.py`** — orchestrates PyPI checking,
`pyproject.toml` updates, `uv lock`, and GitHub changelog fetching
- **`scripts/sdk_report.py`** — parses release notes into structured
features with status/action/runner-relevance detection
- **`.github/workflows/sdk-version-bump.yml`** — daily 9 AM UTC schedule
+ manual `workflow_dispatch`
- **38 tests** covering parsing (both SDK changelog formats), feature
detection, report rendering, and version management

### Report format

The generated PR body includes:
- **TL;DR** — counts of migrations, opt-in features, behavior changes,
bug fixes
- **Action Items** — only migrations and opt-in checkboxes (the stuff
that needs attention)
- **Behavior Changes** — compact table
- **Collapsible details** — full feature table, bug fixes, CLI versions,
internal changes

### How it works

```
Schedule (daily) → Check PyPI → Update pyproject.toml → uv lock →
Fetch GitHub changelogs → Parse & analyze features → Create/update PR
```

One PR per bump cycle. Force-pushes to `automated/sdk-version-bump`
branch. Detects and updates existing open PRs.

## Test plan

- [x] 38 unit tests pass (`pytest scripts/tests/`)
- [ ] Manual `workflow_dispatch` run on this branch
- [ ] Verify PR body renders correctly on GitHub

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Automated daily SDK version bump workflow that creates PRs with
generated changelog-style feature analysis when updates are available
* New CLI and report generator to build human-friendly PR titles and
detailed markdown release reports

* **Documentation**
* Added bookmarks referencing the dependency automation and
feature-analysis tooling

* **Chores**
  * Ignored automated bump output directory

* **Tests**
* Added tests covering feature extraction, report rendering, and
version-bump logic
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Automated Fix by Amber Agent

This PR addresses issue #1163 using the Amber background agent.

### Changes Summary
- **Action Type:** auto-fix
- **Commit:** 9ea1a5a
- **Triggered by:** Issue label/command

### Pre-merge Checklist
- [ ] All linters pass
- [ ] All tests pass
- [ ] Changes follow project conventions (CLAUDE.md)
- [ ] No scope creep beyond issue description

### Reviewer Notes
This PR was automatically generated. Please review:
1. Code quality and adherence to standards
2. Test coverage for changes
3. No unintended side effects

---
🤖 Generated with [Amber Background
Agent](https://github.com/ambient-code/platform/blob/main/docs/amber-automation.md)

Closes #1163

---------

Co-authored-by: Amber Agent <amber@ambient-code.ai>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Jeremy Eder <jeder@redhat.com>
…1161)

## Summary
When the trigger sent a follow-up prompt to a running session, it posted
directly to the runner pod. The runner processed it, but events weren't
persisted or broadcast to the UI because the backend's AG-UI proxy was
bypassed.

Now the trigger posts to the backend's `/agui/run` endpoint using its
service account token. The backend proxy handles event persistence and
broadcasting, so the UI sees the response.

## What changed
- `sendFollowUpPrompt` now posts to
`backend-service.{ns}.svc.cluster.local:8080/api/projects/{project}/agentic-sessions/{session}/agui/run`
- Uses the pod's mounted service account token for auth
- Removed direct runner endpoint dependency (no more
`handlers.DefaultRunnerPort`)

## Test plan
- [ ] Create a scheduled session with reuse enabled
- [ ] Let it create and run a session
- [ ] Trigger again while the session is running
- [ ] Verify the follow-up prompt and response appear in the UI

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Refactor**
* Follow-up prompts now route through a centralized backend proxy; logs
now reference the backend.
* Service-to-service requests authenticate using the cluster service
account and honor a configurable backend namespace.

* **Chores**
* Added a post-deploy step to persist the operator image in cluster
configuration to ensure consistent runtime deployments.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Allow for editing scheduled sessions in the frontend.

Extract the create form into a shared ScheduledSessionForm component
that supports both create and edit modes. Add an edit page at
/projects/{name}/scheduled-sessions/{name}/edit and wire up Edit entry
points in the schedule list dropdown and detail page dropdown.

This solve an additional issue encountered where the create/delete
actions on scheduled sessions redirected back to the workspace default
page rather than the scheduled sessions page. Create, edit, and delete
all now redirect to the schedules list page
(/projects/{name}/scheduled-sessions) instead of the workspace default
view.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Users can now edit scheduled sessions after creation. An edit option
has been added to scheduled session action menus, providing a dedicated
interface for modifying session configurations including prompts,
schedules, runners, and context repositories.

* **Chores**
* Fixed file formatting and trailing whitespace in configuration files.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Jeremy Eder <jeder@redhat.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary

- Adds a new `/pr-fixer` skill at `.claude/skills/pr-fixer/SKILL.md`
- The skill triggers the `pr-fixer.yml` GitHub Actions workflow for a
given PR number, then spawns a background agent to monitor the run and
notify when complete
- Includes prerequisite validation, error handling, and background
monitoring via `gh` CLI

## Test plan

- [ ] Verify skill is discovered by Claude Code (`/pr-fixer` appears in
skill list)
- [ ] Test with a real PR number to confirm workflow dispatch and
monitoring

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary

- Bump **aiohttp** 3.13.3 → 3.13.5 (10 alerts: header injection, SSRF,
DoS)
- Bump **anthropic** 0.74.1 → 0.88.0 (2 alerts: sandbox escape, file
permissions)
- Bump **fastmcp** 2.14.3 → 2.14.6 (3 alerts: SSRF, OAuth bypass,
command injection)
- Bump **pygments** 2.19.2 → 2.20.0 (1 alert: ReDoS)
- Bump **docker/docker** 28.5.1 → 28.5.2 (latest available; v29.3.1 fix
not yet released on this module path)
- Bump **lodash-es** to >=4.18.0 via npm override in docs (2 alerts:
code injection, prototype pollution)

Addresses Dependabot alerts: #143#160

### Not fixable yet

- **docker/docker** alerts #134, #135: fix requires v29.3.1 which hasn't
been released on the `github.com/docker/docker` Go module path. Bumped
to latest available (28.5.2).

## Test plan

- [ ] Runner tests pass
- [ ] `docs` site builds (`cd docs && npm run build`)
- [ ] `ambient-api-server` builds (`cd components/ambient-api-server &&
go build ./...`)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Updated multiple project dependencies across the application stack to
maintain compatibility and system stability.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
#1142)

…ted workflow

Delete ci-failure-resolver-with-agent.yml (redundant with pr-fixer.yml)
and exclude anthropic/claude-agent-sdk from Dependabot so PR #987's
sdk-version-bump workflow is the single source of SDK updates.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Updated Dependabot configuration to exclude specific dependencies from
automated update checks.
* Removed the CI failure resolution workflow that previously analyzed
failed builds and generated automatic fixes.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary

- Restores `is_error` forwarding from `ToolResultBlock` to
`ToolCallEndEvent` in the AG-UI handler
- PR #613 (Feb 18) refactored to event-driven architecture but dropped
this field, breaking Langfuse tool error tracking since Feb 24
- 3-line fix matching the old `adapter.py` behavior (lines 836-846)

## Root Cause

`handle_tool_result_block()` in `handlers.py` reads `is_error` from the
Claude SDK's `ToolResultBlock` but never forwards it to
`ToolCallEndEvent`. The observability layer (`track_agui_event` in
`observability.py`) checks `getattr(event, "error", None)` on
`TOOL_CALL_END` events and always gets `None`, so all tool spans are
tagged `level=DEFAULT` instead of `level=ERROR`.

## Impact

- Langfuse tool error tracking broken for ~5 weeks (since Feb 24)
- Cockpit dashboard correction rate dropped from ~8% to 0.01%
- Session metrics `tool_failures_total` always reports 0
- `tool_log_correction` MCP tool still works (separate path) but only
captures explicit human corrections, not tool execution failures

## Test plan

- [ ] Verify `ToolCallEndEvent` accepts `result` and `error` fields
(confirmed via test fixtures in `conftest.py`)
- [ ] Run `pytest components/runners/ambient-runner/tests/`
- [ ] After deploy: verify Langfuse observations show `level=ERROR` on
tool failures
- [ ] Cockpit correction rate dashboard should show non-zero values
again

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary
- Adds `.github/workflows/stale.yml` using `actions/stale@v9`
- Daily scan (Midnight UTC) marks issues inactive 30+ days as `stale`,
closes after 7 more days
- Exempt labels: `pinned`, `security`, `bug`, `help-wanted`
- PRs are excluded (`days-before-pr-stale: -1`)
- Manual trigger via `workflow_dispatch`

## Dry-run analysis
27 open issues would be marked stale immediately based on real activity
dates (ignoring a March 4 bulk automation that touched most issues). 5
issues are exempt via `bug` label.

Pattern source:
https://github.com/ambient-code/reference/blob/main/docs/patterns/stale-issues.md

## Test plan
- [ ] Merge to main, then trigger manually via Actions > Close Stale
Issues > Run workflow
- [ ] Verify stale label applied to oldest inactive issues
- [ ] Verify exempt issues (`bug` label) are untouched

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary

- Adds `.claude/skills/unleash-flag/SKILL.md` — a standardized workflow
for adding workspace-scoped Unleash feature flags
- Codifies the `category.feature-name.enabled` naming convention with
standard categories (integration, runner, model, feature)
- Documents frontend gating patterns (`useWorkspaceFlag` as default,
`useFlag` as exception for cluster-scoped pages)
- Includes test mocking patterns, evaluation order, lifecycle
management, and common mistakes
- Grandfathers existing flags (`jira-write`,
`ldap.autocomplete.enabled`, `scheduled-session.reuse.enabled`)
- Follows Unleash best practices: unique naming, evaluate once, treat
flags as tech debt, fail-closed defaults

## Test plan

- [ ] Verify skill triggers on phrases like "add a feature flag", "gate
a feature", "flags.json"
- [ ] Verify skill content renders correctly in Claude Code
- [ ] Confirm naming convention and gating patterns match existing
codebase patterns

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Documentation
* Added comprehensive runbook documentation for feature flag
implementation, including detailed setup checklists, testing
requirements, and verification procedures to standardize team practices.
* Documented feature flag lifecycle phases, evaluation priority
guidelines, and troubleshooting resources with common mistakes and
recommended solutions.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary

- Split the monolithic `pr-fixer.yml` into two focused workflows with
distinct cadences
- **`triage.yml`** — daily issue discovery and session creation
- **`pr-fixer.yml`** — 30 min PR management with session reuse and
circuit breaker

## Changes

### `triage.yml` (new)
- Daily cron (8am UTC weekdays) + manual dispatch
- Queries Jira + GH issues for untriaged work (newest first, max
5/cycle)
- Creates child Implement sessions (opus) for actionable issues
- Skips Jira gracefully if MCP tool unavailable
- Labels: adds `ai-triaged` to issues, child sessions add `ai-managed`
to PRs

### `pr-fixer.yml` (rewritten)
- **fix-single**: triggered only by `@ambient-fix` PR comment (was also
label + manual)
- **fix-batch**: 30 min cron + manual dispatch, single orchestrator
session manages all `ai-managed` PRs
  - Reads frontmatter for session ID linkage
  - Checks for changes since `last_action` (ignores bot commits)
- Sends messages to existing sessions (reuse) instead of creating new
ones
  - Circuit breaker: 3 retries then `ai-needs-human` label
- Removed old matrix-based `fix-batch`/`fix-each` pattern
- Unified label: `ai-managed` (was `agent-managed`)

### Both workflows
- Use `ambient-action@v0.0.3` with inactivity timeout (`timeout: '60'` =
60s idle auto-stop)
- Model: `claude-opus-4-6`

## Test plan

- [ ] Manual dispatch `triage.yml` — verify it discovers issues and
creates sessions
- [ ] Comment `@ambient-fix` on a PR — verify `fix-single` triggers
- [ ] Manual dispatch `pr-fixer.yml` (no PR number) — verify batch
orchestrator runs
- [ ] Verify `ai-managed` label triggers batch pickup on next cycle
- [ ] Verify circuit breaker fires after 3 retries

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* PR fixer runs more frequently (every 30 minutes on weekdays), uses an
upgraded model, and includes improved session state and retry handling.
  * Concurrency controls added to coordinate fixer and triage runs.
* **New Features**
* Added an automated Issue Triage workflow to regularly or manually
triage GitHub and Jira items, label/comment, and create follow-up
investigation sessions with session summaries.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ow (#1169)

## Summary

- Fix branch name and autoPush being silently dropped when adding a
context repo in the new session creation UI
- Thread `branch` and `autoPush` parameters from `AddContextModal`
through `NewSessionView` to the create session API call
- Add 2 regression tests verifying branch/autoPush are forwarded
correctly

## Root Cause

The `NewSessionView` component's `onAddRepository` callback only
captured the `url` parameter, ignoring `branch` and `autoPush`. The
`PendingRepo` type and the `onCreateSession` callback type both lacked
these fields, so the data was lost at every layer of the pipeline. This
was introduced in PR #939 when the new session UI was created.

## Changes

| File | Change |
|------|--------|
| `components/frontend/.../new-session-view.tsx` | Added
`branch?`/`autoPush?` to `PendingRepo` type; updated `addPendingRepo`,
`handleSubmit`, and `onAddRepository` callback to thread these values |
| `components/frontend/.../new/page.tsx` | Updated config type and repo
mapping to forward `branch`/`autoPush` to the API |
| `components/frontend/.../__tests__/new-session-view.test.tsx` | Added
2 regression tests: branch+autoPush forwarded correctly, and empty
branch becomes undefined |

## Test plan

- [x] Regression test: repo added with branch "develop" and
autoPush=true flows through to `onCreateSession`
- [x] Regression test: repo added without branch results in `branch:
undefined` (not empty string)
- [x] Full frontend test suite passes (615 tests, 0 failures)
- [x] Next.js build passes with 0 errors
- [ ] Manual: Create a new session, add a repo with a specific branch,
verify the session uses that branch


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Enhanced repository configuration during session creation with
optional branch specification and auto-push toggle.

* **Tests**
  * Added test coverage for new repository configuration options.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Summary
- `make dev-env` now includes `OC_USER` and `OC_EMAIL` in the generated
`.env.local`
- Fixes 401 errors when creating workspaces from the local frontend dev
server (`make dev COMPONENT=frontend`)
- Aligns local dev setup with the kind overlay
(`frontend-test-patch.yaml`) which already sets these vars

## Root cause
The frontend proxy (`buildForwardHeaders` in `auth.ts`) uses `OC_USER`
to set the `X-Forwarded-User` header. Without it, the backend's
`forwardedIdentityMiddleware` cannot populate `userID` in the Gin
context, and `CreateProject` fails with "no user subject found in
token".

## Test plan
- [ ] Run `make kind-up LOCAL_IMAGES=true`
- [ ] Run `make dev-env` and verify `components/frontend/.env.local`
contains `OC_USER` and `OC_EMAIL`
- [ ] Run `make dev COMPONENT=frontend`
- [ ] Create a new workspace from `localhost:3000` — should succeed
(previously returned 401)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Why

The first CI run of the benchmark harness ([run
23769619685](https://github.com/ambient-code/platform/actions/runs/23769619685))
produced repeated `echo: write error: Broken pipe` warnings on stderr.
While harmless, they clutter CI logs and could mask real errors.

## Summary

- `bench_has_scenario` used process substitution (`<
<(bench_scenarios_for_mode)`) with an early `return 0` on match. When
mode is `both`, the function emits two lines (`cold`, `warm`). If the
first line matches, the reader closes the pipe before the second `echo`
completes, triggering SIGPIPE.
- Fix: capture the output in a variable first
(`scenarios=$(bench_scenarios_for_mode)`), then iterate via here-string
(`<<< "$scenarios"`). Both `echo` calls complete before iteration
begins.

## Test plan

- [x] `shellcheck` clean (same pre-existing false positives only)
- [x] `bash tests/bench-test.sh` passes 8/8
- [ ] CI run produces no broken pipe warnings


Made with [Cursor](https://cursor.com)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

This release includes internal refactoring improvements to development
tooling and does not contain any changes visible to end-users.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Robert Gregor <348865+bobbravo2@users.noreply.github.com>
Adding RHOAI with the MLflow component into the cluster. Using the same
postgresql instance, on a separate database.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* MLflow can now be provisioned automatically across dev, e2e, local and
production environments.
* MLflow deployed with multi-replica replicas, persistent artifact
storage, and database-backed metadata.

* **Chores**
* Added automated deployment flow to install platform components and
wait for resources to become ready.
* Added environment-specific MLflow DB credential examples and init
steps to create the MLflow database.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary
- Fixes the `deploy-rhoai-mlflow` GHA job failure from #1166
- The RHOAI operator CSV succeeding doesn't guarantee CRDs are
registered yet
- Adds a wait loop for
`datascienceclusters.datasciencecluster.opendatahub.io` CRD between the
operator readiness check and the DSC apply step
- Applied to both `components-build-deploy.yml` and
`prod-release-deploy.yaml`

## Test plan
- [ ] Re-run the `deploy-rhoai-mlflow` job and verify it passes
- [ ] Verify the CRD wait step logs show the CRD becoming available

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* Deployment workflows now wait (up to ~10 minutes) for a cluster CRD to
register before proceeding; the job fails with an error if the CRD never
appears.
* Deployment steps now verify the PostgreSQL database named "mlflow"
exists and create it if absent.
* **Configuration**
  * MLflow server replica count changed from 2 to 1.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…hness workflow (#1091)

<!-- acp:session_id=pr-fixer-1091-v2 source=ai-managed
last_action=2026-04-02T22:48:54Z retry_count=0 -->
## Summary

Combines [PR #845](#845)
and [PR #1045](#1045) into
a single PR, with improvements from code review.

### Runner / Dockerfile
- **Upgrades base image** from UBI 9 / Python 3.11 to **UBI 10 / Python
3.12**
- **Adds glab** (GitLab CLI) via pinned binary download
- **Pins all runner tools** with explicit `ARG` versions: gh, glab, uv,
pre-commit, gemini-cli
- **Merges gh + glab installs** into a single `RUN` layer (single ARCH
computation)
- Bumps Node.js 20 → 22, updates dnf usage for RHEL 10

### Dependencies
- Bumps claude-agent-sdk, anthropic, mcp, pydantic, ag-ui-protocol,
pytest, ruff, mcp-atlassian, workspace-mcp
- Regenerated uv.lock against current main

### Frontend
- Adds **ClaudeAgentOptions** form (Zod schema + React form) behind
`advanced-agent-options` Unleash flag
- Integrates agent options into the create-session dialog

### Freshness workflow
- New **weekly CI workflow** (`runner-tool-versions.yml`) that checks
all runner components for updates
- Fetches versions **concurrently** (background curl processes)
- Applies updates and opens a single PR when any component is outdated
- Simplified from original: 5 fetch steps → 1, 6 update steps → 1,
removed `eval` usage

### Version table

| Component | Before | After |
|-----------|--------|-------|
| Base image | UBI 9 / python-311 | UBI 10 / ubi |
| Python | 3.11 | 3.12 |
| Node.js | 20 | 22 |
| gh (GitHub CLI) | Unpinned (dnf) | `ARG GH_VERSION=2.74.0` |
| glab (GitLab CLI) | Not installed | `ARG GLAB_VERSION=1.52.0` |
| uv | Unpinned | `ARG UV_VERSION=0.7.8` |
| pre-commit | Unpinned | `ARG PRE_COMMIT_VERSION=4.2.0` |
| gemini-cli | Unpinned | `ARG GEMINI_CLI_VERSION=0.1.17` |

## Test plan

- [ ] Runner container image builds successfully with UBI 10
- [ ] `python3 --version` shows 3.12, `node --version` shows v22
- [ ] `gh version`, `glab version`, `uv --version`, `gemini --version`
all work inside the container
- [ ] CI unit tests pass (Python 3.12)
- [ ] Workflow YAML passes actionlint / GitHub Actions validation
- [ ] Frontend builds with agent options schema changes
- [ ] Agent options form renders when `advanced-agent-options` flag is
enabled
- [ ] Form is hidden when flag is off (default)

Supersedes #845 and #1045.

---
🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Summary
- Fixes the `deploy-rhoai-mlflow` GHA job that's still failing after
#1187
- The CRD wait was checking for CRD *existence* (v1 was already there),
but the DSC manifest uses **v2** which gets registered later
- Now waits for `v2` to appear in `oc api-resources` before applying
- Also includes: MLflow replicas set to 1, DB migration step for
existing PostgreSQL instances

## Root cause
The RHOAI operator registers the `DataScienceCluster` CRD with v1 first,
then updates it to include v2. The previous wait found v1 and proceeded,
but the `datasciencecluster.opendatahub.io/v2` DSC manifest failed
because v2 wasn't served yet.

## Test plan
- [ ] Re-run the `deploy-rhoai-mlflow` job and verify it passes
- [ ] Verify the v2 API wait step logs show it waiting then succeeding

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Updated deployment readiness validation to check for API availability
in release and component build workflows.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…on (#1180)

## Summary

Consolidate `amber-issue-handler.yml`, `pr-fixer.yml`, and `triage.yml`
into a single `amber-issue-handler.yml` (Amber Handler).

## Jobs

| Job | Trigger | What it does |
|-----|---------|-------------|
| `handle-issue-label` | `amber:auto-fix` label | Create session to fix
the issue |
| `handle-comment` | `@amber` on issue or PR | Create session with
user's text + context link |
| `batch-pr-fixer` | 30 min cron / manual | Orchestrator manages all
`amber:managed` PRs |

## Changes

- **`@amber` is now universal** — works on both issues and PRs, passes
the user's comment text directly with no injected instructions
- **Labels unified under `amber:` namespace**: `amber:managed`,
`amber:triaged`, `amber:needs-human`
- **Removed** `amber:refactor` and `amber:test-coverage` label triggers
- **Deleted** `pr-fixer.yml` and `triage.yml` (consolidated)
- **Per-job concurrency groups** prevent overlapping runs
- Uses `ambient-action@v0.0.3` with inactivity timeout

## Test plan

- [ ] Add `amber:auto-fix` label to an issue — verify session created
- [ ] Comment `@amber fix the typo in README` on an issue — verify
session created with that text
- [ ] Comment `@amber` on a PR — verify session created with PR context
- [ ] Manual dispatch — verify batch orchestrator runs
- [ ] Verify `amber:managed` PRs are picked up by batch cron

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Session-based automation replaces the prior PR-centric flow: issues
and @amber comments now create or reuse sessions to drive fixes and
custom prompts.
* Comment handling distinguishes simple "fix" requests from custom
prompts and links sessions via embedded session metadata.
* Batch manager advances or retires managed PRs, retrying automated
fixes and escalating stalled items to human attention.

* **Chores**
* Simplified triggers and tightened workflow permissions; removed legacy
triage and standalone PR-fixer flows.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
)

## Summary

Backend changes for auto-stopping sessions on run completion.

### stopOnRunFinished
- New CRD field: `spec.stopOnRunFinished` (boolean)
- When true, backend sets `desired-phase=Stopped` on `RUN_FINISHED`
event
- In-memory cache (`sync.Map`) avoids k8s API call for sessions without
the flag

### Activity tracking
- All AG-UI events now reset inactivity timer (was only 4 types)
- Prevents false inactivity during long tool calls
- Debounce reduced from 60s to 10s

## Test plan
- [ ] Session with `stopOnRunFinished: true` stops on run completion
- [ ] Session without it behaves unchanged
- [ ] Long-running tool calls don't trigger inactivity timeout

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added a stop-on-run-finished option for sessions (API, schema, and UI
toggle) and a details indicator showing Enabled/Disabled.

* **Behavior Changes**
* Activity timestamps update more responsively (debounce reduced to
~10s) and refresh on any non-empty event.
* Sessions configured to stop on run finish are automatically marked
stopped when a run completes.

* **Tests**
  * Removed an obsolete inactivity-event unit test.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Automated Fix by Amber Agent

This PR addresses issue #1111 using the Amber background agent.

### Changes Summary
- **Action Type:** auto-fix
- **Commit:** 0f4c012
- **Triggered by:** Issue label/command

### Pre-merge Checklist
- [ ] All linters pass
- [ ] All tests pass
- [ ] Changes follow project conventions (CLAUDE.md)
- [ ] No scope creep beyond issue description

### Reviewer Notes
This PR was automatically generated. Please review:
1. Code quality and adherence to standards
2. Test coverage for changes
3. No unintended side effects

---
🤖 Generated with [Amber Background
Agent](https://github.com/ambient-code/platform/blob/main/docs/amber-automation.md)

Closes #1111

Co-authored-by: Amber Agent <amber@ambient-code.ai>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
## Summary
- UAT cluster already has a 2TB `minio-data` PVC, but the base manifest
specifies `500Gi`
- Kubernetes rejects shrinking a PVC, causing `oc apply` to fail with:
`spec.resources.requests.storage: Forbidden: field can not be less than
previous value`
- Adds a production overlay patch to set `minio-data` PVC to `2Ti`

Fixes
https://github.com/ambient-code/platform/actions/runs/23954839404/job/69871041808

## Test plan
- [ ] Verify `kustomize build components/manifests/overlays/production`
renders `minio-data` PVC with `storage: 2Ti`
- [ ] Deploy to UAT succeeds without PVC error

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Updated production environment configuration to allocate 2Ti of
storage for MinIO object storage service.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
jeremyeder and others added 20 commits April 16, 2026 13:09
## Summary

- Proposes replacing human code reviews with an automated inner-loop
review that checks PRs against GPS governance docs + repo conventions
(CLAUDE.md, constitution, BOOKMARKS.md)
- Introduces `ambient-code:self-reviewed` label — machine-applied when
inner-loop review passes, triggers Mergify to merge without human
approval
- Reconfigures Mergify with auto-rebase, priority queues
(urgent/self-reviewed/default), and stale draft cleanup

## Test plan

- [ ] Team reviews and discusses the proposal
- [ ] Create `ambient-code:self-reviewed` label
- [ ] Build inner-loop review function (skill/hook/GHA)
- [ ] Deploy updated `.mergify.yml`
- [ ] Enable branch protection on `main`
- [ ] Validate: PR age at merge, revert rate, open PR count

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Updated internal development process documentation regarding code
review automation workflows.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary
- Adds `validate-model-manifest.py` that gates PR creation with safety
checks: valid JSON structure, required fields on every model,
default/provider-default models exist and are available, no models
removed, at least one available model per provider
- Adds auto-merge (`gh pr merge --auto --squash`) after PR creation — if
validation passes, the PR merges without human intervention
- PR body now includes the manifest diff for auditability

## Prereqs
- Auto-merge must be enabled in repo settings (Settings > General >
"Allow auto-merge")
- If branch protection requires approvals, auto-merge will queue until
approved

## Test plan
- [ ] Trigger `Model Discovery` workflow via `workflow_dispatch`
- [ ] Verify validation step passes and PR is created with diff in body
- [ ] Verify auto-merge is enabled on the created PR

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* Added manifest validation to enforce structure, required fields,
availability rules, and to block removals of existing models.
* Enhanced automated PR workflow to run validation on manifest changes,
attach a generated diff summary to PRs, and auto-approve/enable
conditional auto-merge when validation passes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Automated model discovery run.

This PR updates `components/manifests/base/core/models.json` based on
probing Vertex AI endpoints. Validation passed — safe to auto-merge.

Unleash flags are synced automatically on deploy by the
`sync-model-flags` Job.
<details><summary>Diff</summary>

```diff
diff --git a/components/manifests/base/core/models.json b/components/manifests/base/core/models.json
index c1a63cc..31f75d5 100755
--- a/components/manifests/base/core/models.json
+++ b/components/manifests/base/core/models.json
@@ -85,6 +85,62 @@
       "provider": "google",
       "available": false,
       "featureGated": true
+    },
+    {
+      "id": "claude-opus-4-7",
+      "label": "Claude Opus 4.7",
+      "vertexId": "claude-opus-4-7@default",
+      "provider": "anthropic",
+      "available": false,
+      "featureGated": true
+    },
+    {
+      "id": "gemini-2.5-flash-tts",
+      "label": "Gemini 2.5 Flash Tts",
+      "vertexId": "gemini-2.5-flash-tts@default",
+      "provider": "google",
+      "available": true,
+      "featureGated": true
+    },
+    {
+      "id": "gemini-2.5-pro-tts",
+      "label": "Gemini 2.5 Pro Tts",
+      "vertexId": "gemini-2.5-pro-tts@default",
+      "provider": "google",
+      "available": true,
+      "featureGated": true
+    },
+    {
+      "id": "gemini-3-flash-preview",
+      "label": "Gemini 3 Flash Preview",
+      "vertexId": "gemini-3-flash-preview@default",
+      "provider": "google",
+      "available": false,
+      "featureGated": true
+    },
+    {
+      "id": "gemini-3.1-flash-lite-preview",
+      "label": "Gemini 3.1 Flash Lite Preview",
+      "vertexId": "gemini-3.1-flash-lite-preview@default",
+      "provider": "google",
+      "available": false,
+      "featureGated": true
+    },
+    {
+      "id": "gemini-3.1-pro-preview",
+      "label": "Gemini 3.1 Pro Preview",
+      "vertexId": "gemini-3.1-pro-preview@default",
+      "provider": "google",
+      "available": false,
+      "featureGated": true
+    },
+    {
+      "id": "gemini-live-2.5-flash-native-audio",
+      "label": "Gemini Live 2.5 Flash Native Audio",
+      "vertexId": "gemini-live-2.5-flash-native-audio@default",
+      "provider": "google",
+      "available": true,
+      "featureGated": true
     }
   ]
 }
```
</details>

Co-authored-by: jeremyeder <1919640+jeremyeder@users.noreply.github.com>
## Summary
- Replace `AMBIENT_BOT_TOKEN` (401 bad credentials) with
`actions/create-github-app-token@v2`
- Uses the `ambient-code` GitHub App (ID 2057322) to generate fresh
installation tokens at runtime
- No token rotation needed — tokens are ephemeral and scoped to the
workflow run

## Prereqs
- `AMBIENT_APP_ID` and `AMBIENT_APP_PRIVATE_KEY` secrets must be set
(confirmed done)

## Test plan
- [ ] Merge, then trigger `Model Discovery` workflow — verify approve +
auto-merge succeed

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* Updated internal CI workflow authentication to use a generated app
token for automated PR approval, improving security and reliability of
automated processes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary

- Add `DropdownMenuSeparator` to the `+` dropdown, dividing context
actions (Add Repository, Upload File) from session options
- Add discovery dot on the `+` button — highlights new menu items using
`useLocalStorage` hook with version tracking
- Establishes the extensible pattern for per-session configuration:
boolean toggles as `DropdownMenuCheckboxItem`, form-heavy config as
`DropdownMenuItem` → `Dialog`

This PR adds no new session options — it creates the infrastructure that
PR #1326 (SDK Options) and PR #1328 (Project Intelligence) will build
on.

## Menu Pattern

```
[+] button (discovery dot when new items exist)
├── Add Repository          → existing modal
├── Upload File             → existing (PR #1282)
├── DropdownMenuSeparator
└── (future items: toggles inline, forms via modal)
```

## Test plan

- [x] Frontend test suite: 631 passed, 0 failed
- [x] Frontend build: 0 errors, 0 warnings
- [x] CodeRabbit CLI: 0 major/critical findings
- [x] Discovery dot: uses existing `useLocalStorage` hook (SSR-safe,
cross-tab sync)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

* **New Features**
* Added a visual separator in the session options dropdown menu for
improved organization.
* Introduced a discovery indicator dot on the "+" button to highlight
menu updates.
* The indicator dot automatically clears upon opening the dropdown menu.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary
- Frontend proxy routes for intelligence data call `API_SERVER_URL`,
which defaults to `http://localhost:8000`
- Inside the kind cluster, this doesn't reach the `ambient-api-server`
service
- Adds the env var to `frontend-test-patch.yaml` pointing at the
in-cluster DNS name

## Test plan
- [x] Verified manually on kind cluster — intelligence proxy route
returns data after setting this env var

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Updated frontend deployment configuration to enable API server
connectivity.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary

- Add collapsible "Advanced SDK Options" section to session creation,
gated behind `advanced-sdk-options` workspace feature flag (disabled by
default)
- Backend allowlist (22 keys) + type validation filters `sdkOptions` on
create request, serializes into `SDK_OPTIONS` env var on the CR
- Runner parses `SDK_OPTIONS` with defense-in-depth denylist (10 keys),
appends user system prompt under `## Custom Instructions` heading
- Frontend wraps existing `claude-agent-options/` form components in a
collapsible container
- SDK options drift detection integrated into `sdk-version-bump.yml`
workflow — detects field changes when SDK version bumps
- Deletes broken `daily-sdk-update.yml` (targeted nonexistent
`claude-code-runner` directory)
- Fixes command injection in `sdk-version-bump.yml` (moved `${{ }}`
expressions to `env:` blocks)

## Data Flow

```
Frontend form → sdkOptions on POST request
  → Backend: allowlist filter + type validation → JSON string
    → CR environmentVariables["SDK_OPTIONS"]
      → Runner: parse, denylist filter, merge into adapter options
        → ClaudeAgentAdapter(options)
```

## Security

- Backend allowlist: only permitted keys with valid types pass (22
allowed, 12 excluded)
- Runner denylist: blocks `cwd`, `api_key`, `mcp_servers`,
`setting_sources`, `stderr`, `resume`, `continue_conversation`,
`add_dirs`, `cli_path`, `env`
- System prompt: append-only under `## Custom Instructions` heading
- Feature flag: UI-only gate, API always accepts `sdkOptions`

## Test plan

- [x] Backend: 25 Ginkgo specs (allowlist, type validation, handler
wiring)
- [x] Runner: 32 pytest tests (parsing, denylist, system prompt merge,
adapter integration)
- [x] Frontend: 5 vitest tests (flag gate, collapse, expand) + 636 total
suite passing
- [x] Frontend build: 0 errors, 0 warnings
- [x] No `any` types in changed files
- [x] actionlint clean on all workflow files
- [x] CodeRabbit CLI: 0 findings (4 rounds, all addressed)
- [x] Drift detection: exits 0 locally (no drift with current manifest)

Supersedes #1146.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Advanced SDK Options UI in session creation (workspace feature flag).
* Session creation accepts user-provided sdkOptions, validated and
forwarded to the runtime; system prompt appends user instructions.

* **Chores**
* Removed legacy daily SDK-update workflow; added manifest-driven SDK
drift check and integration into CI.

* **Tests**
* Added unit and integration tests for SDK options parsing, validation,
merging, and frontend form behavior.

* **Documentation**
  * Added spec, plan, tasks, and generated SDK-options manifest.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
)

<!-- acp:session_id=session-8bffbb8f-1dcb-4fb0-8b0e-f4274819b6b3
source=#862 last_action=2026-04-14T17:10:30Z retry_count=0 -->

## Summary

- **Deletes** `.github/workflows/dependabot-auto-merge.yml` — the only
workflow using the security-sensitive `pull_request_target` trigger
- **Adds** a Mergify `pull_request_rule` to auto-approve Dependabot PRs
via the native `review` action
- Existing Mergify queue rules already handle merging once CI checks
pass and an approval is present

## Why

The `pull_request_target` trigger grants write permissions to forked
PRs, making it a known attack vector. Mergify's `review` action provides
the same auto-approve + auto-merge functionality without this risk.

Reference: [Mergify docs — Approve Dependabot Pull
Requests](https://docs.mergify.com/workflow/actions/review/#approve-dependabot-pull-requests)

Closes #862

## Test plan

- [ ] Verify Mergify config is valid (Mergify validates on push)
- [ ] Confirm next Dependabot PR gets auto-approved by Mergify
- [ ] Confirm auto-approved Dependabot PR enters the merge queue and
merges after CI passes

---
🤖 [Ambient
Session](https://ambient-code.apps.rosa.vteam-uat.0ksl.p3.openshiftapps.com/projects/ambient-platform-and-workflow-feedback-loop-running/sessions/session-8bffbb8f-1dcb-4fb0-8b0e-f4274819b6b3)

---------

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Jeremy Eder <jeder@redhat.com>
)

## Summary

- Adds a `pull_request_rules` entry with the `update` action so Mergify
automatically rebases non-draft, non-conflicting PRs onto `main` when
they fall behind
- Without this, PRs that pass CI go stale as other PRs merge,
accumulating conflicts that block the merge queue

## Why

Mergify's merge queue was configured but PRs were never actually merging
through it because there was no auto-rebase. Every time a PR merged to
`main`, the remaining queued PRs would fall behind and conflict —
requiring manual rebases that never happened.

## Test plan

- [ ] Mergify validates config on push (check "Configuration changed"
status)
- [ ] Observe that open PRs without conflicts get rebased automatically
after the next merge to `main`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Improved pull request management automation to keep pull requests
current with the base branch.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…#1339)

<!-- acp:session_id=session-e3506d59-e1ef-420e-8bac-032927613ca1
source=#1313 last_action=2026-04-17T00:53:26Z retry_count=0 -->

## Summary

- **Queue messages during active runs**: When a user sends a message
while the agent is busy, it is now queued via the existing session queue
(localStorage-backed) instead of being POSTed directly to the backend as
a concurrent run.
- **Auto-send on run completion**: Queued messages are automatically
sent when the current run finishes, reusing the same effect that already
handles startup queue processing.
- The existing queue UI (amber indicators, "Message queued" toast,
editable/cancellable queued message bubbles) now works correctly
end-to-end.

Closes #1313

## Changes

**`page.tsx`** (session detail page):
1. `sendChat()` — added `isRunActive` guard that routes to
`sessionQueue.addMessage()` instead of `aguiSendMessage()`
2. Queue-processing effect — added `!isRunActive` condition and
`isRunActive` dependency so queued messages are flushed when a run
finishes (not just on session startup)

## Test plan

- [ ] Start a session and send an initial message
- [ ] While the agent is running, type a follow-up message and press
Enter
- [ ] Verify the "Message queued" toast appears and the message shows as
a queued bubble
- [ ] Verify the agent continues its current run uninterrupted
- [ ] When the run finishes, verify the queued message is automatically
sent
- [ ] Queue multiple messages during a run and verify they are all sent
in order
- [ ] Verify queued messages can be edited and cancelled before they are
sent
- [ ] Verify startup queueing still works (queue messages before session
is Running)

---
🤖 [Ambient
Session](https://ambient-code.apps.rosa.vteam-uat.0ksl.p3.openshiftapps.com/projects/ambient-platform-and-workflow-feedback-loop-running/sessions/session-e3506d59-e1ef-420e-8bac-032927613ca1)

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
## Summary

- Adds Step 6 (validate frontend) to the dev-cluster skill before
providing access URLs
- Distinguishes connection refused (curl exit 7 = port-forward broken)
from HTTP errors (app unhealthy)
- Includes retry loop that auto-fixes port forwarding on connection
refused
- Never reports "cluster is ready" without confirming the frontend
actually responds

## Test plan

- [ ] Invoke dev-cluster skill — verify it validates frontend
accessibility before reporting success
- [ ] Kill port forwarding mid-session — verify skill detects and
recovers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Improvements**
  * Frontend accessibility is now verified before setup completion
* Automatic recovery from port-forwarding failures with intelligent
retry logic
* Enhanced error diagnostics guide users to troubleshoot frontend health
issues
  * Success message displays the verified local frontend URL

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
#1342)

## Summary

Analyzed 23 PRs merged since v0.2.0 and extracted 5 cross-cutting
development guidelines into CLAUDE.md Critical Conventions. Each
prevents a specific class of rework observed in recent PRs.

### Guidelines added to Critical Conventions

| Guideline | Source PRs | Rework Prevented |
|-----------|-----------|------------------|
| **Design for extensibility before adding items** | #1333#1326 | Menu
infrastructure built without pluggable pattern, downstream PR had to
rework separators |
| **Verify contracts and references** | #1325, #1329 | Hook used
nonexistent env var; script referenced old file path after restructuring
|
| **CI/CD security** | #1310, #1334, #1331 | `pull_request_target`
security hole; hardcoded tokens rotted silently |
| **Full-stack awareness** | #1282, #1289 | Existing S3 pipeline could
be reused; credential changes needed all consumers updated |
| **Separate configuration from code** | #1337 | Frontend hardcoded
localhost URL, broke kind/prod deployments |

### Also

- Renamed "Critical Context" → "Critical Conventions" with description
clarifying cross-cutting scope vs. component-specific conventions
- Included HTML triage dashboard (`docs/knowledge-finder-triage.html`)
used for HITL review

## Test plan

- [ ] Verify CLAUDE.md renders correctly and new conventions are clear
- [ ] Verify no duplication with existing conventions
- [ ] Verify HTML dashboard opens correctly in browser

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Updated development guidelines with revised conventions and
cross-cutting best practices for consistency and extensibility.
* Added new reference document for post-release item management and
workflow organization.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary
- Surfaces non-obvious conventions that were trapped in personal Claude
Code memory into checked-in docs where all contributors benefit
- Adds feature flag usage rules (`useWorkspaceFlag` not `useFlag`),
session creation menu patterns, OOTB workflow architecture, K8s
TokenRequest lifetime gotcha, and the no-new-CRDs constraint
- No code changes — docs only

## Changes
| File | What |
|------|------|
| `CLAUDE.md` | Added "No new CRDs" to Critical Conventions |
| `components/frontend/DEVELOPMENT.md` | Feature flags section + session
creation + menu patterns |
| `components/backend/DEVELOPMENT.md` | OOTB workflow architecture
(greeting vs startupPrompt, cache TTL, silent JSON failure) |
| `docs/security-standards.md` | K8s TokenRequest silent default
lifetime gotcha |

## Test plan
- [ ] Docs render correctly in GitHub markdown preview
- [ ] No conflicts with PR #1307 (claude automation overhaul)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Added cross-cutting convention clarifying Kubernetes custom resource
constraints for persistent storage.
* Documented Out-of-the-Box Workflows configuration, caching behavior,
and expected field specifications.
* Added Feature Flags usage guidelines and session creation workflow
documentation.
* Documented token lifetime security standards, including constraints
and default values.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
…ponents/ambient-api-server in the go_modules group across 1 directory (#1338)

Bumps the go_modules group with 1 update in the
/components/ambient-api-server directory:
[github.com/jackc/pgx/v5](https://github.com/jackc/pgx).

Updates `github.com/jackc/pgx/v5` from 5.6.0 to 5.9.0
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/jackc/pgx/blob/master/CHANGELOG.md">github.com/jackc/pgx/v5's
changelog</a>.</em></p>
<blockquote>
<h1>5.9.0 (March 21, 2026)</h1>
<p>This release includes a number of new features such as
SCRAM-SHA-256-PLUS support, OAuth authentication support, and
PostgreSQL protocol 3.2 support.</p>
<p>It significantly reduces the amount of network traffic when using
prepared statements (which are used automatically by
default) by avoiding unnecessary Describe Portal messages. This also
reduces local memory usage.</p>
<p>It also includes multiple fixes for potential DoS due to panic or OOM
if connected to a malicious server that sends
deliberately malformed messages.</p>
<ul>
<li>Require Go 1.25+</li>
<li>Add SCRAM-SHA-256-PLUS support (Adam Brightwell)</li>
<li>Add OAuth authentication support for PostgreSQL 18 (David
Schneider)</li>
<li>Add PostgreSQL protocol 3.2 support (Dirkjan Bussink)</li>
<li>Add tsvector type support (Adam Brightwell)</li>
<li>Skip Describe Portal for cached prepared statements reducing network
round trips</li>
<li>Make LoadTypes query easier to support on &quot;postgres-like&quot;
servers (Jelte Fennema-Nio)</li>
<li>Default empty user to current OS user matching libpq behavior
(ShivangSrivastava)</li>
<li>Optimize LRU statement cache with custom linked list and node
pooling (Mathias Bogaert)</li>
<li>Optimize date scanning by replacing regex with manual parsing
(Mathias Bogaert)</li>
<li>Optimize pgio append/set functions with direct byte shifts (Mathias
Bogaert)</li>
<li>Make RowsAffected faster (Abhishek Chanda)</li>
<li>Fix: Pipeline.Close panic when server sends multiple FATAL errors
(Varun Chawla)</li>
<li>Fix: ContextWatcher goroutine leak (Hank Donnay)</li>
<li>Fix: stdlib discard connections with open transactions in
ResetSession (Jeremy Schneider)</li>
<li>Fix: pipelineBatchResults.Exec silently swallowing lastRows
error</li>
<li>Fix: ColumnTypeLength using BPCharArrayOID instead of BPCharOID</li>
<li>Fix: TSVector text encoding returning nil for valid empty
tsvector</li>
<li>Fix: wrong error messages for Int2 and Int4 underflow</li>
<li>Fix: Numeric nil Int pointer dereference with Valid: true</li>
<li>Fix: reversed strings.ContainsAny arguments in
Numeric.ScanScientific</li>
<li>Fix: message length parsing on 32-bit platforms</li>
<li>Fix: FunctionCallResponse.Decode mishandling of signed result
size</li>
<li>Fix: returning wrong error in configTLS when DecryptPEMBlock fails
(Maxim Motyshen)</li>
<li>Fix: misleading ParseConfig error when default_query_exec_mode is
invalid (Skarm)</li>
<li>Fix: missed Unwatch in Pipeline error paths</li>
<li>Clarify too many failed acquire attempts error message</li>
<li>Better error wrapping with context and SQL statement (Aneesh
Makala)</li>
<li>Enable govet and ineffassign linters (Federico Guerinoni)</li>
<li>Guard against various malformed binary messages (arrays, hstore,
multirange, protocol messages)</li>
<li>Fix various godoc comments (ferhat elmas)</li>
<li>Fix typos in comments (Oleksandr Redko)</li>
</ul>
<h1>5.8.0 (December 26, 2025)</h1>
<ul>
<li>Require Go 1.24+</li>
<li>Remove golang.org/x/crypto dependency</li>
<li>Add OptionShouldPing to control ResetSession ping behavior
(ilyam8)</li>
<li>Fix: Avoid overflow when MaxConns is set to MaxInt32</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/jackc/pgx/commit/b4d8e62b6616d0c09c5021500363de0c56e01631"><code>b4d8e62</code></a>
Release v5.9.0</li>
<li><a
href="https://github.com/jackc/pgx/commit/c227cd4f76fa2b1a47c0156621e05c076f4cf5c9"><code>c227cd4</code></a>
Bump minimum Go version from 1.24 to 1.25</li>
<li><a
href="https://github.com/jackc/pgx/commit/f492c14836d7d442e8103b09f2c0c74a80c56347"><code>f492c14</code></a>
Use reflect.TypeFor instead of reflect.TypeOf for static types</li>
<li><a
href="https://github.com/jackc/pgx/commit/ad8fb08d3f1a36c0e475c9f80dc9bb19d075d8e2"><code>ad8fb08</code></a>
Use sync.WaitGroup.Go to simplify goroutine spawning</li>
<li><a
href="https://github.com/jackc/pgx/commit/303377376df43ba3d1a99728eaa9f9a6bcaab767"><code>3033773</code></a>
Remove go1.26 build tag from synctest test</li>
<li><a
href="https://github.com/jackc/pgx/commit/83ffb3c2220737cf11c7dd88c80be9166753102f"><code>83ffb3c</code></a>
Validate multirange element count against source length before
allocating</li>
<li><a
href="https://github.com/jackc/pgx/commit/828f2147a2d4355e5cf4beac0f542f9c6bbd6709"><code>828f214</code></a>
Fix message length parsing on 32-bit platforms</li>
<li><a
href="https://github.com/jackc/pgx/commit/e196a39add04a887b20a0aac58b7be333273a03a"><code>e196a39</code></a>
Add fuzz test for SQL lexer in sanitize package</li>
<li><a
href="https://github.com/jackc/pgx/commit/7f969f8da50be0dba69f509f9a30f1084d0feabf"><code>7f969f8</code></a>
Rename TraceQueryute to traceExecute</li>
<li><a
href="https://github.com/jackc/pgx/commit/ab523919740a5d83f7613adc3604192f5f653bc4"><code>ab52391</code></a>
Use single Stat snapshot in checkMinConns</li>
<li>Additional commits viewable in <a
href="https://github.com/jackc/pgx/compare/v5.6.0...v5.9.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/jackc/pgx/v5&package-manager=go_modules&previous-version=5.6.0&new-version=5.9.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/ambient-code/platform/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…update (#1323)

Bumps the npm_and_yarn group with 1 update in the /components/frontend
directory: [dompurify](https://github.com/cure53/DOMPurify).
Bumps the npm_and_yarn group with 1 update in the /docs directory:
[dompurify](https://github.com/cure53/DOMPurify).

Updates `dompurify` from 3.3.3 to 3.4.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/cure53/DOMPurify/releases">dompurify's
releases</a>.</em></p>
<blockquote>
<h2>DOMPurify 3.4.0</h2>
<p><strong>Most relevant changes:</strong></p>
<ul>
<li>Fixed a problem with <code>FORBID_TAGS</code> not winning over
<code>ADD_TAGS</code>, thanks <a
href="https://github.com/kodareef5"><code>@​kodareef5</code></a></li>
<li>Fixed several minor problems and typos regarding MathML attributes,
thanks <a
href="https://github.com/DavidOliver"><code>@​DavidOliver</code></a></li>
<li>Fixed <code>ADD_ATTR</code>/<code>ADD_TAGS</code> function leaking
into subsequent array-based calls, thanks <a
href="https://github.com/1Jesper1"><code>@​1Jesper1</code></a></li>
<li>Fixed a missing <code>SAFE_FOR_TEMPLATES</code> scrub in
<code>RETURN_DOM</code> path, thanks <a
href="https://github.com/bencalif"><code>@​bencalif</code></a></li>
<li>Fixed a prototype pollution via
<code>CUSTOM_ELEMENT_HANDLING</code>, thanks <a
href="https://github.com/trace37labs"><code>@​trace37labs</code></a></li>
<li>Fixed an issue with <code>ADD_TAGS</code> function form bypassing
<code>FORBID_TAGS</code>, thanks <a
href="https://github.com/eddieran"><code>@​eddieran</code></a></li>
<li>Fixed an issue with <code>ADD_ATTR</code> predicates skipping URI
validation, thanks <a
href="https://github.com/christos-eth"><code>@​christos-eth</code></a></li>
<li>Fixed an issue with <code>USE_PROFILES</code> prototype pollution,
thanks <a
href="https://github.com/christos-eth"><code>@​christos-eth</code></a></li>
<li>Fixed an issue leading to possible mXSS via Re-Contextualization,
thanks <a
href="https://github.com/researchatfluidattacks"><code>@​researchatfluidattacks</code></a>
and others</li>
<li>Fixed an issue with closing tags leading to possible mXSS, thanks <a
href="https://github.com/frevadiscor"><code>@​frevadiscor</code></a></li>
<li>Fixed a problem with the type dentition patcher after Node version
bump</li>
<li>Fixed freezing BS runs by reducing the tested browsers array</li>
<li>Bumped several dependencies where possible</li>
<li>Added needed files for OpenSSF scorecard checks</li>
</ul>
<p><strong>Published Advisories are here:</strong>
<a
href="https://github.com/cure53/DOMPurify/security/advisories?state=published">https://github.com/cure53/DOMPurify/security/advisories?state=published</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/cure53/DOMPurify/commit/5b16e0b892e82b1779d62b9928b43c4c4ff290b9"><code>5b16e0b</code></a>
Getting 3.x branch ready for 3.4.0 release (<a
href="https://redirect.github.com/cure53/DOMPurify/issues/1250">#1250</a>)</li>
<li>See full diff in <a
href="https://github.com/cure53/DOMPurify/compare/3.3.3...3.4.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `dompurify` from 3.3.3 to 3.4.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/cure53/DOMPurify/releases">dompurify's
releases</a>.</em></p>
<blockquote>
<h2>DOMPurify 3.4.0</h2>
<p><strong>Most relevant changes:</strong></p>
<ul>
<li>Fixed a problem with <code>FORBID_TAGS</code> not winning over
<code>ADD_TAGS</code>, thanks <a
href="https://github.com/kodareef5"><code>@​kodareef5</code></a></li>
<li>Fixed several minor problems and typos regarding MathML attributes,
thanks <a
href="https://github.com/DavidOliver"><code>@​DavidOliver</code></a></li>
<li>Fixed <code>ADD_ATTR</code>/<code>ADD_TAGS</code> function leaking
into subsequent array-based calls, thanks <a
href="https://github.com/1Jesper1"><code>@​1Jesper1</code></a></li>
<li>Fixed a missing <code>SAFE_FOR_TEMPLATES</code> scrub in
<code>RETURN_DOM</code> path, thanks <a
href="https://github.com/bencalif"><code>@​bencalif</code></a></li>
<li>Fixed a prototype pollution via
<code>CUSTOM_ELEMENT_HANDLING</code>, thanks <a
href="https://github.com/trace37labs"><code>@​trace37labs</code></a></li>
<li>Fixed an issue with <code>ADD_TAGS</code> function form bypassing
<code>FORBID_TAGS</code>, thanks <a
href="https://github.com/eddieran"><code>@​eddieran</code></a></li>
<li>Fixed an issue with <code>ADD_ATTR</code> predicates skipping URI
validation, thanks <a
href="https://github.com/christos-eth"><code>@​christos-eth</code></a></li>
<li>Fixed an issue with <code>USE_PROFILES</code> prototype pollution,
thanks <a
href="https://github.com/christos-eth"><code>@​christos-eth</code></a></li>
<li>Fixed an issue leading to possible mXSS via Re-Contextualization,
thanks <a
href="https://github.com/researchatfluidattacks"><code>@​researchatfluidattacks</code></a>
and others</li>
<li>Fixed an issue with closing tags leading to possible mXSS, thanks <a
href="https://github.com/frevadiscor"><code>@​frevadiscor</code></a></li>
<li>Fixed a problem with the type dentition patcher after Node version
bump</li>
<li>Fixed freezing BS runs by reducing the tested browsers array</li>
<li>Bumped several dependencies where possible</li>
<li>Added needed files for OpenSSF scorecard checks</li>
</ul>
<p><strong>Published Advisories are here:</strong>
<a
href="https://github.com/cure53/DOMPurify/security/advisories?state=published">https://github.com/cure53/DOMPurify/security/advisories?state=published</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/cure53/DOMPurify/commit/5b16e0b892e82b1779d62b9928b43c4c4ff290b9"><code>5b16e0b</code></a>
Getting 3.x branch ready for 3.4.0 release (<a
href="https://redirect.github.com/cure53/DOMPurify/issues/1250">#1250</a>)</li>
<li>See full diff in <a
href="https://github.com/cure53/DOMPurify/compare/3.3.3...3.4.0">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/ambient-code/platform/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jeremy Eder <jeder@redhat.com>
## Summary

- Adds a `pre-pull-images` job to the release pipeline using the [Red
Hat DevSpaces
kubernetes-image-puller](https://catalog.redhat.com/en/software/containers/devspaces/imagepuller-rhel9)
- The job runs after `merge-manifests` and gates `deploy-to-openshift`,
so every cluster node has new images cached before rollout begins
- Eliminates the slow first-session-after-upgrade caused by cold
container pulls
- New nodes are covered automatically via the DaemonSet (Kubernetes
schedules a puller pod on join, plus the puller recreates the DaemonSet
hourly)

## What changed

**New manifests** (`components/manifests/components/image-puller/`):
- `namespace.yaml` — dedicated `acp-image-puller` namespace
- `rbac.yaml` — ServiceAccount + ClusterRole for DaemonSet management
- `configmap.yaml` — image puller configuration (caching interval,
resource limits, pull secrets)
- `deployment.yaml` — the image puller using
`registry.redhat.io/devspaces/imagepuller-rhel9@sha256:e4a0286...`

**Modified workflow** (`.github/workflows/prod-release-deploy.yaml`):
- New `pre-pull-images` job that:
  1. Applies image puller infrastructure
2. Creates pull secrets from existing `REDHAT_*` and `QUAY_*` GHA
secrets
3. Builds the image list automatically from the build matrix + release
tag
  4. Patches the ConfigMap and restarts the puller
5. Waits for the DaemonSet to report all nodes ready (10min timeout,
warns and proceeds)
- `deploy-to-openshift` now depends on `pre-pull-images`

## Pipeline dependency graph

```
release
  ├── build (per arch × component)
  │     └── merge-manifests (per component)
  │           └── pre-pull-images ──┐     ← NEW
  │                                 ├── deploy-to-openshift
  └── deploy-rhoai-mlflow (parallel)
```

## Test plan

- [ ] Trigger a release with `force_build_all: true` and verify
`pre-pull-images` job completes
- [ ] Confirm DaemonSet reports all nodes ready before
`deploy-to-openshift` starts
- [ ] Verify images are cached: `oc get daemonset -n acp-image-puller`
shows desired == ready
- [ ] Scale up a new node and confirm it gets a puller pod automatically
- [ ] Verify no impact on partial builds (subset `components` input)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added image pre-pulling mechanism to the production deployment
pipeline for improved deployment performance and reliability.
* Introduced monitoring and alerting for the image-puller component,
including warnings for unavailability and critical alerts for deployment
failures.

* **Infrastructure**
* Updated production deployment workflow to execute image pre-pull
operations before deployment begins.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
## Summary

- **E2E Docker layer caching:** Replace plain `docker build` with
`docker/build-push-action@v7` using GHA cache. Reads layers from the
components-build-deploy workflow's cache scopes (`frontend-amd64`, etc.)
so E2E gets warm layers from the last main build. Expected savings: 3-5
min.
- **E2E kind binary caching:** Cache the kind binary between runs with
`actions/cache@v4`. Pin version in env var for cache key stability. ~15s
saved per run.
- **Lint golangci-lint consolidation:** Replace two sequential
golangci-lint passes (default + test tags) with a single pass using
`--build-tags=test` (superset). ~30s saved.
- **Unit tests pipx:** Replace uncached `pip install junit2html` with
`pipx run junit2html` (pre-installed on GHA runners). ~10s saved.

**Current PR wall-clock P50:** ~10.4m (E2E bottleneck)
**Expected PR wall-clock P50:** ~5-7m

## Test plan

- [ ] Verify E2E workflow runs successfully with cached builds on a PR
that changes component code
- [ ] Verify E2E workflow still pulls `:latest` for unchanged components
- [ ] Verify lint workflow passes with single golangci-lint pass
- [ ] Verify unit-tests backend job generates HTML report via pipx
- [ ] Confirm GHA cache scopes don't conflict with
components-build-deploy

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Chores**
* CI workflows tightened: actions pinned to specific commits, E2E image
handling changed to conditional build-or-pull steps with cache-aware
builds, added a step to show built images, and introduced caching for
the cluster binary to speed E2E runs
  * Linting consolidated into a single, more efficient pass
* Unit-test reporting updated to avoid repeated installs and speed up
report generation

* **Documentation**
* Added CI improvements plan and design specification detailing changes
and validation steps
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
<!-- acp:session_id=session-efdfb38a-94d3-40ae-b1b3-49997399b4db
source=#1345 last_action=2026-04-17T04:10:28Z retry_count=0 -->

## Summary

- Add a `detect-changes` job (using `dorny/paths-filter@v4`, already
used in unit-tests/e2e/lint workflows) to skip the expensive kind
cluster build (~10-15 min) when PRs only touch docs, CI workflows, or
spec files
- Make `test-local-dev-simulation` conditional on component file changes
(Dockerfiles, manifests, backend, operator, frontend, runners, CLI,
public-api, Makefile, tests)
- Add a `ci-gate` job that always runs to aggregate results — handles
skipped `test-local-dev-simulation` gracefully for Mergify
- Update `.mergify.yml` to reference the single `Local Dev CI Gate`
check instead of individual `validate-manifests` +
`test-local-dev-simulation` checks
- Add `workflow_dispatch` trigger so the full suite can still be run
manually

Closes #1345

## Test plan

- [ ] Verify CI passes on this PR (the workflow itself should trigger
since it touches `.github/workflows/test-local-dev.yml`)
- [ ] Verify a docs-only or CI-only PR skips `test-local-dev-simulation`
while `Local Dev CI Gate` still succeeds
- [ ] Verify Mergify can queue PRs using the new `Local Dev CI Gate`
check

---
🤖 [Ambient
Session](https://ambient-code.apps.rosa.vteam-uat.0ksl.p3.openshiftapps.com/projects/ambient-platform-and-workflow-feedback-loop-running/sessions/session-efdfb38a-94d3-40ae-b1b3-49997399b4db)

---------

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Jeremy Eder <jeder@redhat.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
## Summary

- Adds automated CodeRabbit review analysis that runs on every release
to track agent development quality over time
- Mines 971 Critical+Major review comments across 169 PRs to identify
recurring patterns and coverage gaps
- Proposes 5 new CLAUDE.md conventions and 4 hookify rules derived from
the top uncovered patterns
- Integrates into the release pipeline as a parallel job that opens a
triage PR per release

## What's included

### Triage pipeline (`scripts/coderabbit-triage/`)
- `fetch.sh` — extracts CodeRabbit comments per release via `gh api`
- `parse.py` — parses structured comment format, filters to
Critical+Major
- `analyze.py` — clusters patterns by title similarity, ranks by impact,
checks coverage gaps
- `report.py` — generates markdown trend summary with deltas across
releases
- `triage.html` — interactive dashboard for bulk pattern review and
export
- `metrics/` — persistent per-release JSON snapshots for trend tracking

### GHA integration
- `coderabbit-triage` job added to `prod-release-deploy.yaml`, runs
parallel with build
- Opens a PR with metrics + guardrail recommendations per release
- Appends triage summary to GitHub Release notes

### New conventions (from initial analysis)
- **Image references must match across the stack** (9x, 6 Critical)
- **Reconcile, don't create-or-skip AlreadyExists** (6x, 1 Critical)
- **Never silently swallow partial failures** (6x)
- **Namespace-scope shared state keys** (6x, 1 Critical)
- **Containers must run under restricted SecurityContext** (3x)

### Noise reduction
- `.coderabbit.yaml` path_instructions updated to prioritize
Critical/Major severity

## Test plan

- [x] Backfill pipeline ran successfully: 1,394 comments fetched, 971
Critical+Major parsed
- [x] Per-release pipeline tested for v0.2.0: 176 comments, 143
actionable, 125 patterns
- [x] Report generation verified with trend deltas
- [x] Triage dashboard loads and renders at `localhost:8766/triage.html`
- [x] actionlint passes on workflow changes (only pre-existing
shellcheck info warnings)
- [ ] Verify triage job runs in next release pipeline execution

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added CodeRabbit triage dashboard for visualizing code review patterns
and detecting uncovered best practices with interactive filtering and
recommendations.
* Introduced automated triage reporting integrated into release
workflows for pattern analysis and metrics.

* **Documentation**
* Expanded engineering conventions covering Kubernetes deployments,
resource reconciliation, error propagation, namespace isolation, and
container security hardening.

* **Chores**
* Updated code review prioritization rules and AI-assisted editing
configurations for enhanced feedback quality.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary

- Bumps 4 vulnerable Python dependencies in
`components/runners/ambient-runner/uv.lock`
- Resolves all 4 open Dependabot security alerts

## Changes

| Package | From | To | Alert |
|---------|------|----|-------|
| authlib | 1.6.6 | 1.6.11 | CSRF via cache |
| Mako | 1.3.10 | 1.3.11 | Path traversal via double-slash URI |
| python-multipart | 0.0.22 | 0.0.26 | CVE-2026-40347 — DoS via large
preamble |
| pytest | 9.0.2 | 9.0.3 | CVE-2025-71176 — tmpdir handling |

## Test plan

- [x] `uv lock --upgrade-package` succeeded for all 4 packages
- [x] Lock file resolves cleanly (210 packages)
- [ ] CI runner tests pass

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Ambient Code Bot <bot@ambient-code.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@netlify
Copy link
Copy Markdown

netlify bot commented Apr 17, 2026

Deploy Preview for cheerful-kitten-f556a0 canceled.

Name Link
🔨 Latest commit 6a1743c
🔍 Latest deploy log https://app.netlify.com/projects/cheerful-kitten-f556a0/deploys/69e28167e28a3a0009f0302e

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 17, 2026

📝 Walkthrough

Walkthrough

Adds repository-wide agent/skill definitions and CI automations; introduces S3-backed session pre-uploads, model-switching, MCP server config, SDK options UI, scheduled sessions, LDAP SRV/bind support, SSAR and agent-status caching, observability build targets, and multiple frontend/backend API and tests.

Changes

Cohort / File(s) Summary
Agent/Skill & Command Specs
.claude/agents/..., .claude/skills/..., .claude/commands/*.md
Added multiple agent/skill spec files (convention-eval, backend-review, frontend-review, operator-review, runner-review, security-review, align, amber-review, cypress-demo, dev-cluster, memory, pr-fixer, scaffold, unleash-flag, etc.) and eval fixtures. Removed legacy speckit and several command docs.
Assistant Hooks & Settings
.claude/settings.json, .claude/agents (removed)
Added assistant hooks (PreToolUse/PostToolUse/Stop) and removed the .claude/agents pointer file.
Backend: Session & File Uploads
components/backend/handlers/file_uploads.go, .../file_uploads_test.go, components/backend/storage/s3.go, .../s3_test.go, components/backend/types/session.go, components/backend/routes.go
Implemented S3 client, S3-backed pre-upload PUT/GET/DELETE handlers with RBAC/size/path checks, unit tests, session types extended for MCP/SdkOptions/stop-on-run-finished, and new routes.
Backend: Sessions & Model Switching
components/backend/handlers/sessions.go, sessions_sdk_options_test.go
Added SDK option validation/filtering, caching for agent status derivation, Create/UpdateSession MCPServers handling, SwitchModel runtime handler (CR patch + runner sync) and related tests.
Backend: MCP Server Management
components/backend/handlers/project_mcp.go
Added handlers for project-scoped MCP server GET/PUT to store/read ProjectSettings.spec.mcpServers.
Backend: SSAR Cache & Middleware
components/backend/handlers/ssar_cache.go, middleware.go, ssar_cache_bench_test.go
Added concurrent, TTLed SSAR cache with eviction, middleware consults cache for K8s SSAR checks, and benchmarks/tests.
Backend: LDAP & S3 Integration
components/backend/ldap/*, components/backend/main.go
Refactored LDAP client for SRV discovery, bind DN/password, custom CA; startup guards on missing credentials. Added S3 config loading and startup initialization.
Backend: Agent Model & Events
components/ambient-api-server/plugins/agents/model.go, plugins/sessions/model.go, plugins/sessions/integration_test.go, agui_store.go
Extended Agent and Session LLM defaults/fields (model, temp, max tokens, metadata). Changed defaults to claude-sonnet-4-6. Bounded tail-reading of large session event logs (2MB).
Frontend: Scheduled Sessions & Forms
components/frontend/src/app/projects/.../scheduled-sessions/*
Added ScheduledSessionForm, create/edit pages, cron preview/next-run, validation, workflows, repo autoPush/branch support, stop-on-run-finished toggle, and related UI.
Frontend: Live Model & Session UI
components/frontend/src/app/.../sessions/*, components/frontend/src/components/live-model-selector.tsx, file-viewer.tsx, task-transcript-viewer.tsx
Added LiveModelSelector component and integration, polling gated by isActive, queued-message/run-active gating, kept tabs mounted to preserve state, and multiple UI adjustments.
Frontend: Advanced SDK Options & Editors
components/frontend/src/components/claude-agent-options/*, advanced-sdk-options.tsx
Comprehensive agent options form and sub-editors (agents, hooks, MCP servers editor, key/value, string list, thinking, sandbox, plugins, output format), dirty-tracking and save/discard flows, and tests.
Frontend: File Upload Flow
components/frontend/src/app/api/.../upload/route.ts, components/frontend/src/components/__tests__/create-session-dialog-files.test.tsx
Added preUploadFileToS3 helper and upload fallback for 409 Conflict to call backend pre-upload endpoint; tests for file attach behavior and size limit.
Docker & Build
Makefile, components/*/Dockerfile
Added GIT_COMMIT build-arg and org.opencontainers.image.revision label across images; Makefile additions for observability dashboard, screenshots, docs-lint targets, and kind install improvements.
CI/CD Workflows
.github/workflows/*.yml, .github/scripts/*
Large workflow refactor: added sdd-preflight, sdk-version-bump, runner-tool-versions, pr-merge-review, pull-reviews, screenshots, docs-lint, stale, test-local-dev changes; removed several legacy workflows; added model manifest validation script and adjusted model discovery path.
Repo Config & Tooling
.coderabbit.yaml, .mergify.yml, .github/dependabot.yml, .mcp.json, .gitignore
Updated CodeRabbit review rules, Mergify gates, Dependabot ignores, added MCP server entries, and expanded .gitignore for Claude worktrees and sdk-bump output.
Docs & Governance
CLAUDE.md, BOOKMARKS.md, .specify/*, components/*/DEVELOPMENT.md
Added runner constitution/spec, SDD manifest, updated CLAUDE.md conventions and BOOKMARKS, documented feature-flag and OOTB workflows, and simplified memory constitution.
Testing & Validation
components/backend/handlers/*_test.go, components/frontend/src/**/__tests__/*, .github/scripts/validate-model-manifest.py
Added benchmarks/tests for agent-status, SSAR cache, file-upload keys, permissions validation, sessions SDK options; frontend unit tests updated/added; added manifest validator script.
Deps & Tooling Versions
components/frontend/package.json, .github/scripts/model-discovery.py, components/*/go.mod
Updated Next.js/dompurify/file-type, moved model manifest path to components/manifests/base/core/models.json, bumped multiple Go deps (grpc/protobuf/genproto) and Go toolchain to 1.25 in components.ambient-* modules.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Frontend
    participant Backend as Backend API
    participant K8s as Kubernetes API
    participant S3 as S3 (MinIO)
    participant Runner as Runner Service

    rect rgba(100, 200, 100, 0.5)
    Note over Client,Backend: Pre-upload file (PUT) with SSAR
    Client->>Backend: PUT /agentic-sessions/:sessionName/file-uploads/*path (body)
    Backend->>Backend: compute SSAR cache key
    Backend->>K8s: SelfSubjectAccessReview (if cache miss)
    K8s-->>Backend: allowed / denied
    alt allowed
        Backend->>Backend: validate path, size
        Backend->>S3: PutObject(namespace/session/key)
        S3-->>Backend: success
        Backend-->>Client: 200 OK (filename,size)
    else denied
        Backend-->>Client: 403 Forbidden
    end
    end
Loading
sequenceDiagram
    participant Client as Frontend
    participant Backend as Backend API
    participant K8s as Kubernetes API
    participant Runner as Runner Pod

    rect rgba(100, 150, 200, 0.5)
    Note over Client,Runner: Model switch flow
    Client->>Backend: POST /agentic-sessions/:sessionName/model { model }
    Backend->>K8s: GET AgenticSession CR
    K8s-->>Backend: spec.llmSettings.model
    Backend->>K8s: PATCH AgenticSession CR (set new model)
    K8s-->>Backend: patched
    Backend->>Runner: POST /model (runner endpoint)
    alt Runner accepts
        Runner-->>Backend: 200 OK
        Backend-->>Client: 200 OK
    else Runner rejects/fails
        Backend->>K8s: PATCH AgenticSession CR (revert model)
        Backend-->>Client: 500 Error
    end
    end
Loading
sequenceDiagram
    participant Runner as Runner Pod
    participant Backend as Backend API
    participant K8s as Kubernetes API

    rect rgba(200, 150, 100, 0.5)
    Note over Runner,Backend: Run-finished -> optional stop
    Runner->>Backend: stream event RUN_FINISHED
    Backend->>Backend: persistStreamedEvent -> update last-activity
    Backend->>Backend: check stopOnRunFinished cache
    alt cache miss or true
        Backend->>K8s: GET AgenticSession CR
        K8s-->>Backend: spec.stopOnRunFinished: true
        Backend->>K8s: PATCH annotations (desired-phase=Stopped)
        K8s-->>Backend: patched
        Backend->>Backend: cache stopOnRunFinished=true
    else cached false
        Backend-->>Runner: no action
    end
    end
Loading
✨ 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 chore/rebase-main-to-alpha-manual
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch chore/rebase-main-to-alpha-manual

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

Note

Due to the large number of review comments, Critical severity comments were prioritized as inline comments.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (6)
.github/workflows/unit-tests.yml (1)

1-47: ⚠️ Potential issue | 🟠 Major

Add explicit permissions block to scope workflow privileges.

No permissions key is defined, so the workflow inherits the repository default (often write-all). These jobs only need contents: read (checkout) and actions: write (artifact upload). Scoping permissions limits blast radius if a dependency is compromised.

🔒 Suggested fix
 name: Unit Tests

 on:
   push:
     branches: [main]
     # ...
+
+permissions:
+  contents: read
+  actions: write
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/unit-tests.yml around lines 1 - 47, Add a top-level
permissions block to the Unit Tests workflow to explicitly scope privileges: set
permissions.contents to read (for actions/checkout) and permissions.actions to
write (for artifact upload), and keep other permissions at minimal required
(omit or set to none). Place this permissions mapping at the root of the
workflow YAML (alongside name, on, concurrency) so it applies to all jobs;
reference the workflow "Unit Tests" and the existing inputs
test_label/default_namespace and concurrency group to locate where to insert it.
.github/workflows/docs.yml (1)

23-61: ⚠️ Potential issue | 🟠 Major

Pin action versions to commit SHAs.

All actions in this workflow use semantic version tags (@v4, @v5, @v6) instead of immutable commit SHAs. As per coding guidelines, action versions must be pinned to SHA to prevent supply-chain attacks.

🔒 Recommended SHA pins for current action versions
       - name: Checkout
-        uses: actions/checkout@v6
+        uses: actions/checkout@a81bbbf8298c0fa03ea29cdc473d45769f953675  # v6.0.0
 
       - name: Setup Node.js
-        uses: actions/setup-node@v4
+        uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af  # v4.1.0
 
       - name: Setup Pages
-        uses: actions/configure-pages@v5
+        uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b  # v5.0.0
 
       - name: Upload artifact
-        uses: actions/upload-pages-artifact@v4
+        uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa  # v4.0.0
 
       - name: Deploy to GitHub Pages
-        uses: actions/deploy-pages@v4
+        uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e  # v4.0.5

Note: Verify these SHAs match your desired versions before applying.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/docs.yml around lines 23 - 61, Replace the mutable
semantic tags with immutable commit SHAs for each GitHub Action usage to satisfy
pinning policy: update actions/checkout@v6, actions/setup-node@v4,
actions/configure-pages@v5, actions/upload-pages-artifact@v4, and
actions/deploy-pages@v4 to their corresponding commit SHA pins (e.g.,
actions/checkout@<sha>), ensuring you fetch and verify the correct SHAs from
each action’s repository and replace only the tag portion while leaving the rest
of the step (inputs like node-version, cache, working-directory, paths, and step
ids) unchanged.
.github/workflows/lint.yml (2)

145-149: ⚠️ Potential issue | 🟠 Major

Pin golangci-lint binary version instead of using latest.

The action itself is pinned to a SHA, but version: latest still allows the golangci-lint binary to drift, breaking unrelated PRs without any workflow change. Use an explicit version (e.g., version: v1.60.3) instead.

This applies to all four occurrences in the file (lines 145-149, 184-188, 223-227, 262-266).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/lint.yml around lines 145 - 149, Replace the unstable
"version: latest" entries for the golangci-lint action with a pinned release
(for example "version: v1.60.3") wherever the action is used; locate the
golangci/golangci-lint-action@1e7e51e77 blocks (the four occurrences) and change
their "version:" keys from "latest" to the chosen explicit version string so the
golangci-lint binary no longer drifts across runs.

144-149: ⚠️ Potential issue | 🟠 Major

Restore separate lint passes for default and test-tagged builds.

The --build-tags=test single-pass approach excludes components/backend/handlers/k8s_clients_for_request_prod.go, which is constrained with //go:build !test. Keep both the default build and the --build-tags=test passes to ensure all production and test code paths are linted.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/lint.yml around lines 144 - 149, The lint workflow
currently runs a single golangci-lint step with args "--build-tags=test", which
skips files guarded by "//go:build !test" (e.g.,
k8s_clients_for_request_prod.go); restore two separate lint passes instead: add
one step (keep the existing name Run golangci-lint or similar) that omits
"--build-tags" (default build) and a second step that includes "args:
--timeout=5m --build-tags=test" so both default and test-tagged builds are
linted; ensure both steps use the same uses/version and working-directory
settings as the current step.
components/frontend/src/components/chat/ChatInputBox.tsx (1)

619-650: ⚠️ Potential issue | 🟠 Major

Keep an accessible name when the labels collapse on mobile.

On small screens, the Agents / Commands text is display: none, so these controls degrade into icon-only buttons with no stable accessible label. Add aria-label (and ideally title) to both buttons before hiding the text.

Suggested fix
-                      <Button variant="outline" size="sm" className="h-7 gap-1.5" disabled={agents.length === 0}>
+                      <Button
+                        variant="outline"
+                        size="sm"
+                        className="h-7 gap-1.5"
+                        disabled={agents.length === 0}
+                        aria-label={`Agents${agents.length > 0 ? ` (${agents.length})` : ""}`}
+                        title="Agents"
+                      >
                         <Users className="h-3.5 w-3.5" />
                         <span className="hidden sm:inline">Agents</span>
@@
-                      <Button variant="outline" size="sm" className="h-7 gap-1.5" disabled={commands.length === 0}>
+                      <Button
+                        variant="outline"
+                        size="sm"
+                        className="h-7 gap-1.5"
+                        disabled={commands.length === 0}
+                        aria-label={`Commands${commands.length > 0 ? ` (${commands.length})` : ""}`}
+                        title="Commands"
+                      >
                         <Terminal className="h-3.5 w-3.5" />
                         <span className="hidden sm:inline">Commands</span>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/frontend/src/components/chat/ChatInputBox.tsx` around lines 619 -
650, The Agents and Commands popover Buttons lose their visible labels on small
screens, so add stable accessible names: add aria-label and title props to the
two Button elements used as PopoverTrigger (the Button with Users icon that
checks agents.length and the Button with Terminal icon that checks
commands.length). Use descriptive labels like "Open agents menu" and "Open
commands menu" (or similar), ensuring you add them to the Button components that
control agentsPopoverOpen and commandsPopoverOpen so the icon-only buttons
remain accessible when the span text is hidden.
components/frontend/src/app/projects/[name]/sessions/[sessionName]/page.tsx (1)

340-365: ⚠️ Potential issue | 🟠 Major

Drain queued messages one run at a time.

After Line 352, the first aguiSendMessage() can start a new run, but this loop keeps sending the rest of unsentMessages immediately. That bypasses the new isRunActive guard in sendChat() and can reorder or reject queued follow-ups.

Suggested fix
   useEffect(() => {
     const phase = session?.status?.phase;
     const unsentMessages = sessionQueue.messages.filter(m => !m.sentAt);

     if (phase === "Running" && !isRunActive && unsentMessages.length > 0) {
       const processMessages = async () => {
-        for (const messageItem of unsentMessages) {
-          try {
-            await aguiSendMessage(messageItem.content);
-            sessionQueue.markMessageSent(messageItem.id);
-            // Small delay between messages to avoid overwhelming the system
-            await new Promise(resolve => setTimeout(resolve, 100));
-          } catch (err) {
-            toast.error(err instanceof Error ? err.message : "Failed to send queued message");
-          }
-        }
+        const [messageItem] = unsentMessages;
+        try {
+          await aguiSendMessage(messageItem.content);
+          sessionQueue.markMessageSent(messageItem.id);
+        } catch (err) {
+          toast.error(err instanceof Error ? err.message : "Failed to send queued message");
+        }
       };

       processMessages();
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/frontend/src/app/projects/`[name]/sessions/[sessionName]/page.tsx
around lines 340 - 365, The current useEffect drains all unsentMessages in a
loop which allows the first aguiSendMessage() to start a run and then
immediately sends subsequent queued messages, bypassing the isRunActive guard in
sendChat(); change the logic to only process the next single unsent message
(e.g. take unsentMessages[0]), await aguiSendMessage(message.content), call
sessionQueue.markMessageSent(message.id), handle errors as before, and do not
loop—allow the effect to re-run when isRunActive or sessionQueue.messages
changes so each run is drained one-at-a-time; reference functions/variables:
useEffect, aguiSendMessage, sessionQueue.markMessageSent, sendChat, isRunActive,
unsentMessages.
🟠 Major comments (22)
.github/dependabot.yml-9-11 (1)

9-11: ⚠️ Potential issue | 🟠 Major

Avoid blanket-ignore for core SDK dependencies

Ignoring anthropic and claude-agent-sdk entirely means Dependabot will never surface security/compatibility fixes for them. Prefer ignoring only major updates if noise control is the goal.

Suggested safer Dependabot config
-    ignore:
-      - dependency-name: "anthropic"
-      - dependency-name: "claude-agent-sdk"
+    ignore:
+      - dependency-name: "anthropic"
+        update-types:
+          - "version-update:semver-major"
+      - dependency-name: "claude-agent-sdk"
+        update-types:
+          - "version-update:semver-major"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/dependabot.yml around lines 9 - 11, The dependabot config currently
blanket-ignores the core SDK dependencies "anthropic" and "claude-agent-sdk",
which suppresses all security and minor/patch updates; change the ignore entries
to only ignore major version updates (e.g., add update-types:
["version-update:semver-major"]) for the dependency-name values "anthropic" and
"claude-agent-sdk" so Dependabot will still surface patch and
minor/compatibility/security fixes while avoiding noisy major-version bumps.
components/backend/handlers/oauth.go-74-80 (1)

74-80: ⚠️ Potential issue | 🟠 Major

Broadened Gmail scopes are over-privileged by default

Line 74–80 now requests read/modify/compose scopes for all Google OAuth flows. That’s a significant privilege expansion versus send-only and should not be unconditional. Please gate expanded scopes behind a feature flag/config and keep the default to minimum required scopes.

Proposed direction (default minimal scopes + opt-in expanded scopes)
@@
 		return &OAuthProvider{
@@
-			Scopes: []string{
+			scopes := []string{
 				"openid",
 				"https://www.googleapis.com/auth/userinfo.email",
 				"https://www.googleapis.com/auth/userinfo.profile",
 				"https://www.googleapis.com/auth/drive",
 				"https://www.googleapis.com/auth/drive.readonly",
 				"https://www.googleapis.com/auth/drive.file",
-				// Gmail scopes for gmail:send permission level (cumulative in workspace-mcp)
-				// Includes: readonly, organize (labels+modify), drafts (compose), and send
-				"https://www.googleapis.com/auth/gmail.readonly",
-				"https://www.googleapis.com/auth/gmail.labels",
-				"https://www.googleapis.com/auth/gmail.modify",
-				"https://www.googleapis.com/auth/gmail.compose",
 				"https://www.googleapis.com/auth/gmail.send",
-			},
+			}
+			if os.Getenv("GOOGLE_GMAIL_EXPANDED_SCOPES") == "true" {
+				scopes = append(scopes,
+					"https://www.googleapis.com/auth/gmail.readonly",
+					"https://www.googleapis.com/auth/gmail.labels",
+					"https://www.googleapis.com/auth/gmail.modify",
+					"https://www.googleapis.com/auth/gmail.compose",
+				)
+			}
+			return &OAuthProvider{
+				Name:         "google",
+				ClientID:     clientID,
+				ClientSecret: clientSecret,
+				TokenURL:     "https://oauth2.googleapis.com/token",
+				Scopes:       scopes,
+			}, nil
-		}, nil

Based on learnings: "Gate new features behind Unleash feature flags; use /unleash-flag to set up new flags" and "Separate configuration from code; externalize via env vars, ConfigMaps, manifests, or feature flags; if a value varies across environments or changes over time, it is config, not code".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/backend/handlers/oauth.go` around lines 74 - 80, The Gmail OAuth
scope list in components/backend/handlers/oauth.go is currently requesting broad
read/modify/compose scopes unconditionally; change the code that constructs the
Gmail scopes (the slice containing
"https://www.googleapis.com/auth/gmail.readonly", "gmail.labels",
"gmail.modify", "gmail.compose", "gmail.send") so the default set is the minimal
send-only scopes and the expanded readonly/labels/modify/compose scopes are only
appended when an explicit opt-in config/feature flag is enabled (use Unleash via
the existing /unleash-flag integration or an env var). Locate the scope
construction in the OAuth handler (where the Gmail scope slice is defined) and
implement gating logic: read the flag/env var, and only include the extra scopes
when enabled; ensure logging notes when expanded scopes are granted.
components/backend/handlers/integration_validation.go-137-141 (1)

137-141: ⚠️ Potential issue | 🟠 Major

Return a generic request-construction error to clients (don’t expose wrapped parse details).

At Line 140, %w can surface raw URL parse internals to user-facing responses via TestJiraConnection. Keep the external error generic.

Suggested fix
-	if !sawHTTPResponse && lastReqErr != nil {
-		return false, fmt.Errorf("failed to create request: %w", lastReqErr)
-	}
+	if !sawHTTPResponse && lastReqErr != nil {
+		return false, fmt.Errorf("failed to create request")
+	}

As per coding guidelines: "Do not log, error, or return tokens in responses; use len(token) for logging and provide generic messages to users".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/backend/handlers/integration_validation.go` around lines 137 -
141, The current return in the block checking sawHTTPResponse and lastReqErr
uses fmt.Errorf("%w") which can expose internal parse details to callers (e.g.
TestJiraConnection); change it to return a generic error message (e.g.
fmt.Errorf("failed to create request")) without wrapping lastReqErr, and if you
need the underlying error for diagnostics, log lastReqErr internally (using the
existing logger) rather than returning it. Update the code around the
sawHTTPResponse/lastReqErr check to remove the %w wrapping and perform internal
logging of lastReqErr instead.
.mcp.json-5-5 (1)

5-5: ⚠️ Potential issue | 🟠 Major

Pin MCP server package versions; avoid @latest in committed config.

Lines 5 and 9 use floating package tags (@upstash/context7-mcp@latest and deepwiki-mcp@latest). This weakens reproducibility and increases supply-chain risk because upstream changes can alter behavior without any change to this repository.

Recommend pinning to specific versions:

Proposed changes
-      "args": ["-y", "@upstash/context7-mcp@latest"]
+      "args": ["-y", "@upstash/context7-mcp@<pinned-version>"]

-      "args": ["-y", "deepwiki-mcp@latest"]
+      "args": ["-y", "deepwiki-mcp@<pinned-version>"]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.mcp.json at line 5, Replace floating `@latest` tags in the .mcp.json "args"
array with explicit, pinned versions to ensure reproducible builds: update the
entries referencing "@upstash/context7-mcp@latest" and "deepwiki-mcp@latest" to
specific semver pins (e.g., `@upstash/context7-mcp`@x.y.z and deepwiki-mcp@a.b.c),
verify those versions exist and run any install/test commands to confirm
compatibility, then commit the updated .mcp.json.
.github/workflows/stale.yml-16-16 (1)

16-16: 🛠️ Refactor suggestion | 🟠 Major

Pin actions/stale to commit SHA 5bef64f19d7facfb25b37b414482c7164d639639.

Change uses: actions/stale@v9 to uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 for supply-chain security and reproducibility.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/stale.yml at line 16, Update the GitHub Actions workflow
step referencing the stale action by replacing the floating tag
"actions/stale@v9" with the specific commit SHA
"actions/stale@5bef64f19d7facfb25b37b414482c7164d639639" to pin the dependency;
locate the usage of actions/stale in the workflow (the line containing uses:
actions/stale@v9) and change it to uses:
actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 to ensure supply-chain
stability and reproducible runs.
components/ambient-api-server/plugins/agents/model.go-46-51 (1)

46-51: ⚠️ Potential issue | 🟠 Major

Zero-value check can override intentional user settings.

LlmTemperature == 0 is indistinguishable from "temperature explicitly set to 0" (valid for deterministic output). Same issue with LlmMaxTokens.

Consider using pointer fields (*float64, *int32) to distinguish nil (unset) from zero (explicit), or move defaults entirely to GORM's default tag and remove the BeforeCreate logic for these fields.

🛠️ Option: use pointers to distinguish unset from zero
 type Agent struct {
     // ...
-    LlmTemperature       float64 `json:"llm_temperature"        gorm:"default:0.7"`
-    LlmMaxTokens         int32   `json:"llm_max_tokens"         gorm:"default:4000"`
+    LlmTemperature       *float64 `json:"llm_temperature"        gorm:"default:0.7"`
+    LlmMaxTokens         *int32   `json:"llm_max_tokens"         gorm:"default:4000"`
 }

 func (d *Agent) BeforeCreate(tx *gorm.DB) error {
     d.ID = api.NewID()
     if d.LlmModel == "" {
         d.LlmModel = "claude-sonnet-4-6"
     }
-    if d.LlmTemperature == 0 {
-        d.LlmTemperature = 0.7
-    }
-    if d.LlmMaxTokens == 0 {
-        d.LlmMaxTokens = 4000
-    }
+    // Let GORM default tag handle nil→default conversion
     return nil
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/ambient-api-server/plugins/agents/model.go` around lines 46 - 51,
The current zero-value checks in the model (checking LlmTemperature == 0 and
LlmMaxTokens == 0) can overwrite an explicit user-provided 0; update the model
to distinguish "unset" from explicit zero by changing the field types to
pointers (e.g., LlmTemperature *float64, LlmMaxTokens *int) and adjust any
constructor/BeforeCreate logic to check for nil instead of zero, assign the
desired defaults when nil, and update any usages of LlmTemperature/LlmMaxTokens
elsewhere to dereference safely; alternatively, if you prefer DB-side defaults,
remove the BeforeCreate defaulting code and add GORM `default` tags to the
LlmTemperature and LlmMaxTokens fields so explicit zeros are preserved.
.github/workflows/sdk-version-bump.yml-52-63 (1)

52-63: ⚠️ Potential issue | 🟠 Major

Exit code capture fails due to shell default behavior.

GitHub Actions run: steps use set -e by default. If python scripts/sdk-version-bump.py returns exit code 2 (updates available), the step fails before EXIT_CODE=$? executes.

🐛 Proposed fix
       run: |
-          python scripts/sdk-version-bump.py --check-only --package "$PACKAGE_ARG"
-          EXIT_CODE=$?
+          EXIT_CODE=0
+          python scripts/sdk-version-bump.py --check-only --package "$PACKAGE_ARG" || EXIT_CODE=$?
 
           if [ "$EXIT_CODE" -eq 2 ]; then
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/sdk-version-bump.yml around lines 52 - 63, The step fails
to capture non-zero exit codes because GitHub Actions uses set -e; update the
run block so the python invocation doesn't abort the script (e.g., run the
command with "|| true" or insert "set +e" before it), then assign EXIT_CODE=$?
and keep the existing logic that writes "updates_available=true/false" to
GITHUB_OUTPUT; ensure you reference the python script name
(scripts/sdk-version-bump.py), the EXIT_CODE variable and the existing
conditional branch that echoes to "$GITHUB_OUTPUT" so the step can inspect and
act on the script's exit code instead of being terminated early.
.github/workflows/docs-lint.yml-8-12 (1)

8-12: ⚠️ Potential issue | 🟠 Major

Scope the job token explicitly.

This job only reads repo contents, but without an explicit permissions: block it inherits the default GITHUB_TOKEN scope. Please lock it down to read-only here.

Suggested fix
 jobs:
   lint:
     name: Lint Documentation
     runs-on: ubuntu-latest
     timeout-minutes: 5
+    permissions:
+      contents: read

As per coding guidelines, ".github/workflows/**/*.{yml,yaml}: Pin action versions to SHA. Verify secrets are not exposed and permissions are scoped."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/docs-lint.yml around lines 8 - 12, The lint job (jobs.lint
/ name: Lint Documentation) is inheriting full GITHUB_TOKEN scope; add an
explicit permissions block to restrict the token to read-only repository
contents (e.g., permissions: contents: read) and ensure the job-level
GITHUB_TOKEN uses that scoped permission; also review any referenced actions in
this workflow and pin them to SHA to comply with the repository policy.
components/frontend/src/components/claude-agent-options/_components/plugins-editor.tsx-22-25 (1)

22-25: ⚠️ Potential issue | 🟠 Major

Add an accessible name to the remove button.

This icon-only control has no label, so screen-reader users won't know what it does.

Suggested fix
-          <Button type="button" variant="ghost" size="icon" className="h-8 w-8 shrink-0" onClick={() => { ids.current.splice(i, 1); onChange(value.filter((_, j) => j !== i)); }}><Trash2 className="h-3 w-3" /></Button>
+          <Button
+            type="button"
+            variant="ghost"
+            size="icon"
+            className="h-8 w-8 shrink-0"
+            aria-label={plugin.path ? `Remove plugin ${plugin.path}` : "Remove plugin"}
+            onClick={() => {
+              ids.current.splice(i, 1);
+              onChange(value.filter((_, j) => j !== i));
+            }}
+          >
+            <Trash2 className="h-3 w-3" />
+          </Button>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@components/frontend/src/components/claude-agent-options/_components/plugins-editor.tsx`
around lines 22 - 25, The remove Button (the Button element wrapping the Trash2
icon) is missing an accessible name; add an aria-label (or title) to that Button
— e.g., aria-label="Remove plugin" or a dynamic label like aria-label={`Remove
plugin ${i + 1}`} — so screen readers announce its purpose, and keep the
existing onClick handler and classes (the Button with onClick that splices
ids.current and calls onChange).
components/backend/main.go-147-155 (1)

147-155: ⚠️ Potential issue | 🟠 Major

Don't bake an environment-specific LDAP base DN into the binary.

Falling back to cn=users,cn=accounts,dc=ipa,dc=redhat,dc=com makes LDAP resolution silently wrong anywhere outside that exact directory layout. This should be explicit config, not a code default.

Suggested fix
-		ldapBaseDN := getEnvOrDefault("LDAP_BASE_DN", "cn=users,cn=accounts,dc=ipa,dc=redhat,dc=com")
+		ldapBaseDN := os.Getenv("LDAP_BASE_DN")
 		ldapGroupBaseDN := os.Getenv("LDAP_GROUP_BASE_DN") // optional, derived from LDAP_BASE_DN if empty
 		ldapBindDN := os.Getenv("LDAP_BIND_DN")
 		ldapBindPassword := os.Getenv("LDAP_BIND_PASSWORD")
 		ldapCACertPath := os.Getenv("LDAP_CA_CERT_PATH")
-		if ldapBindDN == "" || ldapBindPassword == "" {
+		if ldapBaseDN == "" {
+			log.Printf("LDAP disabled: missing LDAP_BASE_DN")
+		} else if ldapBindDN == "" || ldapBindPassword == "" {
 			log.Printf("LDAP disabled: missing bind credentials")
 		} else if ldapClient, err := ldap.NewClient(ldapURL, ldapSRVDomain, ldapBaseDN, ldapGroupBaseDN, ldapBindDN, ldapBindPassword, ldapCACertPath); err != nil {

Based on learnings: Separate configuration from code; externalize via env vars, ConfigMaps, manifests, or feature flags; if a value varies across environments or changes over time, it is config, not code

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/backend/main.go` around lines 147 - 155, The code currently
hardcodes a fallback LDAP base DN via getEnvOrDefault("LDAP_BASE_DN",
"cn=users,cn=accounts,dc=ipa,dc=redhat,dc=com"), which bakes
environment-specific config into the binary; replace this by removing the
hardcoded default and forcing explicit configuration: change the logic around
ldapBaseDN to read LDAP_BASE_DN without a baked fallback (use os.Getenv or a
config loader), validate that ldapBaseDN is non-empty at startup and fail fast
with a clear log/error if missing, and update any places referencing ldapBaseDN,
ldapGroupBaseDN, and NewClient(...) to rely on the explicit config provided at
runtime (or document/require LDAP_BASE_DN via env/ConfigMap/manifest) so
different environments supply their own DN.
.github/workflows/test-local-dev.yml-278-294 (1)

278-294: ⚠️ Potential issue | 🟠 Major

Local Dev CI Gate can pass when prerequisites never ran successfully.

The gate does not include detect-changes in needs, and it only blocks on failure. If detect-changes errors, test-local-dev-simulation becomes skipped and this required gate still goes green; cancelled upstream results also pass today.

Suggested fix
   ci-gate:
     name: Local Dev CI Gate
     runs-on: ubuntu-latest
-    needs: [validate-manifests, test-local-dev-simulation]
+    needs: [detect-changes, validate-manifests, test-local-dev-simulation]
     if: always()
     timeout-minutes: 1
     steps:
       - name: Check results
         run: |
+          echo "detect-changes: ${{ needs.detect-changes.result }}"
           echo "validate-manifests: ${{ needs.validate-manifests.result }}"
           echo "test-local-dev-simulation: ${{ needs.test-local-dev-simulation.result }}"
-          if [ "${{ needs.validate-manifests.result }}" == "failure" ] || \
-             [ "${{ needs.test-local-dev-simulation.result }}" == "failure" ]; then
+          if [ "${{ needs.detect-changes.result }}" != "success" ] || \
+             [ "${{ needs.validate-manifests.result }}" != "success" ] || \
+             { [ "${{ needs.test-local-dev-simulation.result }}" != "success" ] && \
+               [ "${{ needs.test-local-dev-simulation.result }}" != "skipped" ]; }; then
             echo "One or more required checks failed"
             exit 1
           fi
           echo "All checks passed or were appropriately skipped"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/test-local-dev.yml around lines 278 - 294, The CI gate job
ci-gate should also depend on detect-changes and must treat any non-success
upstream result as a failure; update the needs array to include detect-changes
and modify the "Check results" step (the shell logic in that step) to fail when
any of the required jobs' results is not "success" (or explicitly check for
"failure", "skipped", or "cancelled") instead of only checking for "failure" so
skipped/cancelled upstream jobs can't silently let the gate pass.
.github/workflows/test-local-dev.yml-22-26 (1)

22-26: ⚠️ Potential issue | 🟠 Major

Pin the new action refs to immutable SHAs.

This adds mutable refs for required CI (actions/checkout@v6 and dorny/paths-filter@v4). Version tags can change behavior without diff visibility. GitHub Actions must be pinned to commit SHAs per .github/workflows/**/*.{yml,yaml} requirements.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/test-local-dev.yml around lines 22 - 26, Replace the
mutable action tags with immutable commit SHAs: locate the uses entries
referencing actions/checkout@v6 and dorny/paths-filter@v4 and change them to the
corresponding full commit SHAs (e.g., actions/checkout@<commit-sha> and
dorny/paths-filter@<commit-sha>), ensuring you pick the SHA for the exact
version you expect; commit the change so the workflow uses those pinned SHAs
instead of the floating tags.
.github/workflows/screenshots.yml-24-30 (1)

24-30: ⚠️ Potential issue | 🟠 Major

Pin actions to commit SHAs for supply-chain security.

Mutable version tags and branches expose workflows to upstream compromise. Per coding guidelines, all action versions must be pinned to SHA:

  • Line 24: actions/checkout@v6actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
  • Line 27: kubeflow/pipelines/.github/actions/github-disk-cleanup@masterkubeflow/pipelines/.github/actions/github-disk-cleanup@ab1231a5c32c688bcb62314e467011b586aee796
  • Line 30: actions/setup-node@v6actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f
  • Line 118: actions/upload-artifact@v6actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/screenshots.yml around lines 24 - 30, Replace mutable
action version tags with the provided commit SHAs to pin dependencies: update
"actions/checkout@v6" to
"actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd", update
"kubeflow/pipelines/.github/actions/github-disk-cleanup@master" to
"kubeflow/pipelines/.github/actions/github-disk-cleanup@ab1231a5c32c688bcb62314e467011b586aee796",
update "actions/setup-node@v6" to
"actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f", and also pin
"actions/upload-artifact@v6" to
"actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f" wherever it
appears.
Makefile-233-236 (1)

233-236: ⚠️ Potential issue | 🟠 Major

This target now depends on a directory outside the checkout.

Line 235 uses cd ../observability/dashboard, which escapes the repo root. make build-observability-dashboard will fail in CI and fresh clones unless everyone also has a sibling observability checkout. Point this at the in-repo dashboard path instead.

Based on learnings Verify contracts and references before building on assumptions (env vars exist, paths are correct, URLs are reachable); after moving anything, grep scripts, workflows, manifests, and configs

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Makefile` around lines 233 - 236, The Makefile target
build-observability-dashboard currently cd's to a sibling repo path
("../observability/dashboard"), which escapes the checkout; change the target to
use the in-repo dashboard directory (replace the "../observability/dashboard"
reference used in the command under the build-observability-dashboard target
with the repository-local path like "observability/dashboard" or
"./observability/dashboard") so CI and fresh clones don’t require an external
checkout, and then grep/update any scripts, workflows or manifests that assumed
the old path to ensure consistency.
.github/workflows/sdd-preflight.yml-82-94 (1)

82-94: ⚠️ Potential issue | 🟠 Major

Don’t stop at the first matching managed path.

Line 92 makes the first matching glob authoritative. If a file matches both a warn component and an enforce component, the earlier match wins and the violation is silently downgraded. Please collect all matches, or at least let enforce take precedence over warn.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/sdd-preflight.yml around lines 82 - 94, The current inner
loop breaks on the first match, making the first matching pattern in
PATTERN_FILE authoritative and allowing an enforce to be silently downgraded by
an earlier warn; update the logic in the inner while that reads regex/comp/mode
(the loop using regex, comp, mode and reading PATTERN_FILE) to collect all
matches for a given changed_file rather than breaking on the first match: either
remove the break and append a row for every match (adding to VIOLATIONS when
mode="enforce" and to WARNINGS when mode!="enforce"), or track booleans (e.g.,
found_enforce/found_warn) during the inner loop and after it finishes, if
found_enforce is true add an enforce VIOLATION row (taking precedence), else if
found_warn add a WARNING row; ensure you still skip empty changed_file entries
and preserve the existing row formatting logic.
Makefile-1283-1283 (1)

1283-1283: ⚠️ Potential issue | 🟠 Major

kind local image sync still skips the control-plane image.

Line 1283 adds the dashboard image, but $(CONTROL_PLANE_IMAGE) is still missing from _kind-load-images. make kind-up LOCAL_IMAGES=true / kind-rebuild will keep using the stale control-plane image, so local testing won’t exercise control-plane changes from this merge.

Minimal fix
-	`@for` img in $(BACKEND_IMAGE) $(FRONTEND_IMAGE) $(OPERATOR_IMAGE) $(RUNNER_IMAGE) $(STATE_SYNC_IMAGE) $(PUBLIC_API_IMAGE) $(API_SERVER_IMAGE) $(MCP_IMAGE) $(OBSERVABILITY_DASHBOARD_IMAGE); do \
+	`@for` img in $(BACKEND_IMAGE) $(FRONTEND_IMAGE) $(OPERATOR_IMAGE) $(RUNNER_IMAGE) $(STATE_SYNC_IMAGE) $(PUBLIC_API_IMAGE) $(API_SERVER_IMAGE) $(CONTROL_PLANE_IMAGE) $(MCP_IMAGE) $(OBSERVABILITY_DASHBOARD_IMAGE); do \

Based on learnings Image references must match across the stack; after changing an image name or tag, grep all overlays, workflows, and ConfigMaps

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Makefile` at line 1283, The for-loop that populates images for the
_kind-load-images target omits $(CONTROL_PLANE_IMAGE), so local kind image sync
still uses a stale control-plane image; update the loop in the Makefile (the
invocation listing $(BACKEND_IMAGE) $(FRONTEND_IMAGE) ...
$(OBSERVABILITY_DASHBOARD_IMAGE)) to also include $(CONTROL_PLANE_IMAGE) so that
_kind-load-images (and make kind-up LOCAL_IMAGES=true / kind-rebuild) loads the
control-plane image from local builds.
.github/workflows/components-build-deploy.yml-209-215 (1)

209-215: ⚠️ Potential issue | 🟠 Major

Pin action versions to SHAs across all workflow jobs.

Four locations use floating tags (actions/checkout@v6, redhat-actions/openshift-tools-installer@v1) instead of pinned SHAs. Per repo policy, replace:

  • actions/checkout@v6de0fac2e4500dabe0009e67214ff5f5447ce83dd
  • redhat-actions/openshift-tools-installer@v1144527c7d98999f2652264c048c7a9bd103f8a82

Locations: 209–215, 330–336, 357–363, 435–440

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/components-build-deploy.yml around lines 209 - 215,
Replace the floating GitHub Action tags with the provided SHAs wherever they
appear in this workflow: change uses: actions/checkout@v6 to uses:
actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd and change uses:
redhat-actions/openshift-tools-installer@v1 to uses:
redhat-actions/openshift-tools-installer@144527c7d98999f2652264c048c7a9bd103f8a82;
update each occurrence (the four blocks that currently reference
actions/checkout and redhat-actions/openshift-tools-installer) so all jobs use
the pinned SHAs instead of floating tags.
components/backend/handlers/sessions.go-543-546 (1)

543-546: ⚠️ Potential issue | 🟠 Major

Namespace the agent-status cache key.

This cache is keyed only by session.Metadata["name"]. Two namespaces can have the same session name, so one project can receive another project's cached AgentStatus.

Suggested fix
 func enrichAgentStatus(session *types.AgenticSession) {
@@
 	name, _ := session.Metadata["name"].(string)
 	if name == "" {
 		return
 	}
+	project := session.Spec.Project
+	if project == "" {
+		if ns, ok := session.Metadata["namespace"].(string); ok {
+			project = ns
+		}
+	}
+	cacheKey := fmt.Sprintf("%s/%s", project, name)

 	// Check cache
 	agentStatusCache.RLock()
-	if entry, ok := agentStatusCache.entries[name]; ok && time.Now().Before(entry.expiresAt) {
+	if entry, ok := agentStatusCache.entries[cacheKey]; ok && time.Now().Before(entry.expiresAt) {
 		agentStatusCache.RUnlock()
 		if entry.status != "" {
 			session.Status.AgentStatus = types.StringPtr(entry.status)
@@
 	// Store in cache
 	agentStatusCache.Lock()
-	agentStatusCache.entries[name] = agentStatusCacheEntry{
+	agentStatusCache.entries[cacheKey] = agentStatusCacheEntry{
 		status:    derived,
 		expiresAt: time.Now().Add(agentStatusCacheTTL),
 	}

As per coding guidelines: Namespace-scope shared state keys by including namespace/project prefix in cache keys and status entries

Also applies to: 582-605

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/backend/handlers/sessions.go` around lines 543 - 546, The cache
currently keys agentStatusCache.entries only by session.Metadata["name"],
causing cross-namespace collisions; change all places that read/write
agentStatusCache (the entries map and any helpers around agentStatusCacheEntry)
to use a namespaced key like namespace + "/" + name (e.g.,
session.Metadata["namespace"] + "/" + session.Metadata["name"]) and update
agentStatusCacheEntry to include a Namespace field if needed so stored entries
carry their namespace; ensure every lookup, set, and delete (including the code
blocks that build and access keys around agentStatusCache and
agentStatusCacheEntry) uses this composite key to prevent cross-project leaks.
components/frontend/src/app/projects/[name]/sessions/[sessionName]/components/settings/mcp-servers-panel.tsx-69-72 (1)

69-72: ⚠️ Potential issue | 🟠 Major

These MCP writes can clobber each other.

Every handler rebuilds the next payload from session?.spec?.mcpServers, which is stale until the parent session query catches up. A quick disable/add/remove sequence can therefore drop the previous change because each PUT sends a full config object.

Use an optimistic local config (or the latest mutation variables) as the write base, and block further edits while the mutation is pending.

Also applies to: 89-137

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@components/frontend/src/app/projects/`[name]/sessions/[sessionName]/components/settings/mcp-servers-panel.tsx
around lines 69 - 72, Current handlers build PUT payloads from the stale
session?.spec?.mcpServers (via currentConfig/customServers/disabledServers),
which lets concurrent edits clobber each other; fix by introducing an optimistic
local state (e.g., mcpLocalConfig state) that mirrors MCPServersConfig and
update that state synchronously inside your add/remove/toggle handlers before
calling the mutation, use that local state as the base for the mutation payload
instead of session?.spec?.mcpServers, and disable further edits while the
mutation is pending (track mutation status) so handlers like the
addCustomServer/removeCustomServer/toggleDisabledServer use and update
mcpLocalConfig and pending flag to avoid races.
components/frontend/src/app/projects/[name]/scheduled-sessions/_components/scheduled-session-form.tsx-184-198 (1)

184-198: ⚠️ Potential issue | 🟠 Major

Re-run the default-model effect when the runner changes.

handleRunnerTypeChange() resets model, but this effect only watches modelsData?.defaultModel. If the next runner/provider resolves to the same default model id, the effect does not fire and the form stays blank.

Suggested fix
-  }, [modelsData?.defaultModel, form, isEdit, initialData]);
+  }, [selectedRunnerType, modelsData, form, isEdit, initialData]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@components/frontend/src/app/projects/`[name]/scheduled-sessions/_components/scheduled-session-form.tsx
around lines 184 - 198, The default-model useEffect (the block that reads
modelsData?.defaultModel and calls form.setValue("model", ...)) must also re-run
when the selected runner/provider changes because handleRunnerTypeChange()
resets the model; update the effect's dependency array to include the
runner/runnerType state used by handleRunnerTypeChange (or the provider id) so
the effect will run after runner changes and re-apply modelsData.defaultModel or
the preserved initialData value via form.setValue; keep the existing edit-mode
check (isEdit and initialData.sessionTemplate.llmSettings?.model) and the model
existence check when adding this dependency.
.github/workflows/prod-release-deploy.yaml-577-579 (1)

577-579: ⚠️ Potential issue | 🟠 Major

Add deploy-rhoai-mlflow to the deploy chain.

Line 579 leaves the new prerequisite job out of deploy-to-openshift.needs, so the main deployment can start before the RHOAI/MLflow operators, CRDs, and secret are ready. That makes the new ordering ineffective and introduces a race.

Suggested fix
-    needs: [release, merge-manifests, pre-pull-images]
+    needs: [release, merge-manifests, pre-pull-images, deploy-rhoai-mlflow]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/prod-release-deploy.yaml around lines 577 - 579, The
deploy-to-openshift job's needs list is missing the new prerequisite job
deploy-rhoai-mlflow; update the deploy-to-openshift job definition so its needs
array includes deploy-rhoai-mlflow (alongside release, merge-manifests,
pre-pull-images) to ensure deploy-rhoai-mlflow completes before
deploy-to-openshift runs. Ensure you reference the deploy-to-openshift job block
and add the string "deploy-rhoai-mlflow" into its needs array.
.github/workflows/prod-release-deploy.yaml-459-467 (1)

459-467: ⚠️ Potential issue | 🟠 Major

Pin action versions to SHA instead of moving tags.

Lines 460, 465, and 587 use unpinned tags (v6, v1) that can change without notice, weakening supply-chain integrity and violating the workflow policy. Replace with immutable SHAs (e.g., actions/checkout@a5ac7e51b41094c7423fa3007db8d8cda0e50436 for v6).

  • actions/checkout@v6 → checkout by SHA
  • redhat-actions/openshift-tools-installer@v1 → install by SHA
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/prod-release-deploy.yaml around lines 459 - 467, The
workflow uses mutable action tags (actions/checkout@v6 and
redhat-actions/openshift-tools-installer@v1); replace each occurrence with the
corresponding immutable commit SHAs (e.g., actions/checkout@<checkout_SHA> and
redhat-actions/openshift-tools-installer@<installer_SHA>) so the workflow pins
exact revisions; update every place these actions are referenced (including the
checkout step and the oc installer step and the other occurrence near line 587)
and keep the existing with: blocks (ref: ${{ needs.release.outputs.new_tag }}
and oc: latest) unchanged.
🟡 Minor comments (4)
components/frontend/src/components/__tests__/create-session-dialog-files.test.tsx-126-135 (1)

126-135: ⚠️ Potential issue | 🟡 Minor

Fragile selector and silent pass if button not found.

The remove button lookup relies on a CSS class (.bg-muted\\/50) which may change with styling. More critically, wrapping the click in if (removeButtons.length > 0) silently passes if the button isn't found—test won't catch a regression.

Suggested fix
-    const removeButtons = screen.getAllByRole('button').filter(
-      btn => btn.querySelector('svg') && btn.closest('.bg-muted\\/50')
-    );
-    if (removeButtons.length > 0) {
-      fireEvent.click(removeButtons[0]);
-      await waitFor(() => {
-        expect(screen.queryByText(/removeme\.txt/)).toBeNull();
-      });
-    }
+    // Use accessible name or test-id for the remove button
+    const removeButton = screen.getByRole('button', { name: /remove/i });
+    fireEvent.click(removeButton);
+    await waitFor(() => {
+      expect(screen.queryByText(/removeme\.txt/)).toBeNull();
+    });

If the component lacks an accessible name, consider adding aria-label="Remove file" to the remove button.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@components/frontend/src/components/__tests__/create-session-dialog-files.test.tsx`
around lines 126 - 135, The test uses a fragile CSS-based filter and silently
skips the click when no button is found; update the test to assert and target
the remove button via accessibility instead: replace the
screen.getAllByRole(...).filter(...) logic with a role query that matches an
accessible name (e.g. getByRole('button', { name: /remove file|remove/i }) or
getAllByRole and find by name), remove the if (removeButtons.length > 0) guard
so the test fails if the button is missing, then call fireEvent.click on the
found button and await the existing waitFor(...) that asserts the file text is
gone; if the component lacks an accessible name, add aria-label="Remove file" to
the remove button in the component so the test can reliably select it.
components/backend/websocket/agui_proxy.go-1010-1015 (1)

1010-1015: ⚠️ Potential issue | 🟡 Minor

Cache doesn't invalidate on spec changes.

If stopOnRunFinished is initially false and gets cached, subsequent updates to enable it won't take effect until the cache entry expires (~1hr via cleanupStaleSessions). Edge case, but could be confusing if users toggle the setting mid-session.

Consider clearing the cache entry when the session spec is updated, or accepting this as intentional behavior to avoid API churn.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/backend/websocket/agui_proxy.go` around lines 1010 - 1015, The
cache check in agui_proxy.go (stopOnRunFinishedCache.Load(sessionName)) can
block updates to the session spec from taking effect; modify the session
update/watch logic to invalidate the cached entry when the session's spec
changes by calling stopOnRunFinishedCache.Delete(sessionName) (or equivalent)
whenever the Session resource is updated (e.g., in your session update handler
or k8s watch event processing path), so toggling stopOnRunFinished mid-session
will be honored immediately.
.github/workflows/amber-issue-handler.yml-91-91 (1)

91-91: ⚠️ Potential issue | 🟡 Minor

Pin action to commit SHA to prevent tag hijacking.

ambient-code/ambient-action@v0.0.5 at lines 91, 294, 365, 445 uses a mutable tag. Per coding guidelines, pin to commit SHA: 3f01516d00ba5628f210f9390a98970b5567c835

Replace with: ambient-code/ambient-action@3f01516d00ba5628f210f9390a98970b5567c835

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/amber-issue-handler.yml at line 91, Replace the mutable
tag reference "ambient-code/ambient-action@v0.0.5" with the provided commit SHA
"ambient-code/ambient-action@3f01516d00ba5628f210f9390a98970b5567c835" wherever
it appears (e.g., the usages currently showing
"ambient-code/ambient-action@v0.0.5"); update all occurrences to pin to the
commit SHA to prevent tag hijacking.
components/frontend/src/app/projects/[name]/scheduled-sessions/[scheduledSessionName]/edit/page.tsx-13-29 (1)

13-29: ⚠️ Potential issue | 🟡 Minor

Missing error state handling.

The component checks isLoading and !scheduledSession but doesn't handle the error state from useScheduledSession. A failed fetch will show "Scheduled session not found" instead of an appropriate error message.

Proposed fix
-  const { data: scheduledSession, isLoading } = useScheduledSession(projectName, scheduledSessionName);
+  const { data: scheduledSession, isLoading, error } = useScheduledSession(projectName, scheduledSessionName);

   if (isLoading) {
     return (
       <div className="flex items-center justify-center min-h-[400px]">
         <Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
       </div>
     );
   }

+  if (error) {
+    return (
+      <div className="flex items-center justify-center min-h-[400px]">
+        <p className="text-destructive">Failed to load scheduled session</p>
+      </div>
+    );
+  }
+
   if (!scheduledSession) {

As per coding guidelines: "Verify loading/error states and error handling in React Query hooks."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@components/frontend/src/app/projects/`[name]/scheduled-sessions/[scheduledSessionName]/edit/page.tsx
around lines 13 - 29, The component currently only handles isLoading and a
missing scheduledSession, but ignores the error returned by useScheduledSession;
update the hook destructuring to include error (e.g., const { data:
scheduledSession, isLoading, error } = useScheduledSession(...)) and add an
early render branch that checks error and displays an appropriate error message
(use error.message or a friendly fallback) before falling back to the "Scheduled
session not found" case so failed fetches show the actual error rather than the
not-found UI.

Comment on lines +204 to +207
deploy-rhoai-mlflow:
runs-on: ubuntu-latest
needs: [build-matrix]
if: always() && !cancelled() && (github.event_name == 'push' && github.ref == 'refs/heads/main' || github.event_name == 'workflow_dispatch')
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.

⚠️ Potential issue | 🔴 Critical

Gate deploy-rhoai-mlflow on successful build/deploy prerequisites.

With needs: [build-matrix] plus always(), this job can still oc apply, oc exec, create the MLflow DB, and patch secrets after build or merge-manifests fail. That turns a broken push into a partial cluster mutation.

Minimal fix
-  deploy-rhoai-mlflow:
-    runs-on: ubuntu-latest
-    needs: [build-matrix]
-    if: always() && !cancelled() && (github.event_name == 'push' && github.ref == 'refs/heads/main' || github.event_name == 'workflow_dispatch')
+  deploy-rhoai-mlflow:
+    runs-on: ubuntu-latest
+    needs: [merge-manifests]
+    if: !cancelled() && (github.event_name == 'push' && github.ref == 'refs/heads/main' || github.event_name == 'workflow_dispatch')
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/components-build-deploy.yml around lines 204 - 207, The
deploy-rhoai-mlflow job is currently guarded by always() which lets it run even
when its prerequisite job(s) fail; update the job conditional to require
successful prerequisites instead of always(): remove always() and add a check
that the needed job(s) succeeded (e.g., require needs.build-matrix.result ==
'success' or include any other prerequisite like needs.merge-manifests.result ==
'success' if applicable) while keeping the existing event checks
(github.event_name == 'push' && github.ref == 'refs/heads/main' ||
github.event_name == 'workflow_dispatch'); reference the job name
deploy-rhoai-mlflow and the existing needs: [build-matrix] / if: condition to
locate where to change the condition.


jobs:
preel:
uses: ambient-code/pull-reviews/.github/workflows/review.yml@main
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.

⚠️ Potential issue | 🔴 Critical

Pin the reusable workflow to a SHA.

The workflow reference uses @main instead of a pinned SHA. As per coding guidelines, action versions must be pinned to SHA for security and reproducibility.

🔒 Proposed fix to pin workflow reference

Example (replace with actual SHA):

-    uses: ambient-code/pull-reviews/.github/workflows/review.yml@main
+    uses: ambient-code/pull-reviews/.github/workflows/review.yml@abc123def456...

To get the current SHA of main:

#!/bin/bash
gh api repos/ambient-code/pull-reviews/commits/main --jq '.sha'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/pull-reviews.yml at line 14, The reusable workflow
reference currently uses the floating tag "uses:
ambient-code/pull-reviews/.github/workflows/review.yml@main"; replace the
"@main" suffix with the repository commit SHA for the desired revision (pin the
workflow to that SHA) so the action is immutable and reproducible—obtain the SHA
from the remote (e.g., the repo's main branch commit) and update the string
"uses: ambient-code/pull-reviews/.github/workflows/review.yml@<SHA>"
accordingly.

Comment on lines +14 to +24
uses: ambient-code/pull-reviews/.github/workflows/review.yml@main
with:
s3_bucket: pull-reviews
gcp_project_id: ambient-code-platform
gcp_region: us-east5
gcp_workload_identity_provider: projects/888214980327/locations/global/workloadIdentityPools/github/providers/ambient-code-github-actions
secrets:
S3_ENDPOINT: ${{ secrets.S3_ENDPOINT }}
S3_ACCESS_KEY_ID: ${{ secrets.S3_ACCESS_KEY_ID }}
S3_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_ACCESS_KEY }}
CDN_BASE_URL: ${{ secrets.CDN_BASE_URL }}
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.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Fetch and display the reusable workflow definition
gh api repos/ambient-code/pull-reviews/contents/.github/workflows/review.yml \
  --jq '.content' | base64 -d

Repository: ambient-code/platform

Length of output: 3763


Fix parameter mismatch and remove unused S3 secrets; pin external workflow to commit SHA.

The external workflow accepts gcs_bucket (not s3_bucket) and uses Google Cloud Storage with Vertex AI, not S3. The S3 secrets passed here—S3_ENDPOINT, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, CDN_BASE_URL—are unused by the external workflow and should be removed. Additionally, pin the external workflow call to a commit SHA instead of @main, and verify that the external workflow's action versions are similarly pinned per security guidelines.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/pull-reviews.yml around lines 14 - 24, Change the workflow
invocation to pass the correct storage parameter and remove unused S3 secrets:
replace the input key s3_bucket with gcs_bucket (matching the external
workflow’s expected input), drop the unused secrets S3_ENDPOINT,
S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, and CDN_BASE_URL from the secrets block,
and pin the external workflow referenced by uses:
ambient-code/pull-reviews/.github/workflows/review.yml@main to a specific commit
SHA (and ensure action versions referenced inside that external workflow are
likewise pinned).

Comment on lines +69 to +82
// Validate and sanitize path
sub := strings.TrimPrefix(c.Param("path"), "/")
if sub == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "File path required"})
return
}
workspaceBase := "/workspace/file-uploads"
validationPath := filepath.Join(workspaceBase, sub)
if !pathutil.IsPathWithinBase(validationPath, workspaceBase) {
log.Printf("PreUploadFile: path traversal attempt detected - path=%q", sub)
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid path: must be within file-uploads directory"})
return
}
filePath := filepath.ToSlash(sub)
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.

⚠️ Potential issue | 🔴 Critical

Normalize separators before validating the upload path.

Line 82 and Line 270 convert backslashes after the traversal check. On Linux, filepath treats ..\foo as a normal filename during validation, so this can pass IsPathWithinBase and then become ../foo in the stored key. That opens a traversal bypass for any downstream hydration that uses slash-separated paths.

Suggested fix
-	sub := strings.TrimPrefix(c.Param("path"), "/")
+	sub := strings.TrimPrefix(strings.ReplaceAll(c.Param("path"), "\\", "/"), "/")
 	if sub == "" {
 		c.JSON(http.StatusBadRequest, gin.H{"error": "File path required"})
 		return
 	}
-	workspaceBase := "/workspace/file-uploads"
-	validationPath := filepath.Join(workspaceBase, sub)
-	if !pathutil.IsPathWithinBase(validationPath, workspaceBase) {
+	filePath := path.Clean(sub)
+	if filePath == "." || filePath == ".." || strings.HasPrefix(filePath, "../") {
 		log.Printf("PreUploadFile: path traversal attempt detected - path=%q", sub)
 		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid path: must be within file-uploads directory"})
 		return
 	}
-	filePath := filepath.ToSlash(sub)

Add path to the imports and apply the same normalization in DeletePreUploadedFile.

Also applies to: 257-270

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/backend/handlers/file_uploads.go` around lines 69 - 82, Normalize
and clean the requested path before doing the traversal check: in the
PreUploadFile handler (and likewise in DeletePreUploadedFile) convert
backslashes to slashes and run path.Clean on the trimmed param (use the path
package), then trim any leading "/" from that cleaned value into the variable
sub before composing validationPath and calling pathutil.IsPathWithinBase;
ensure filePath is derived from the same cleaned sub. Add the path import and
apply the identical normalization logic in both PreUploadFile and
DeletePreUploadedFile so validation and stored keys use the same canonical path.

Comment on lines +313 to +349
// Ensure the caller has at least list permission on agenticsessions in the namespace.
// Check the SSAR cache first to avoid hitting the K8s API on every request.
token, _, _, _ := extractRequestToken(c)
cacheKey := ssarCacheKey(token, projectHeader, "list", "vteam.ambient-code", "agenticsessions")

if cachedAllowed, found := globalSSARCache.check(cacheKey); found {
if !cachedAllowed {
c.JSON(http.StatusForbidden, gin.H{"error": "Unauthorized to access project"})
c.Abort()
return
}
// Cache hit — allowed, skip SSAR call
} else {
// Cache miss — perform SSAR and cache the result
ssar := &authv1.SelfSubjectAccessReview{
Spec: authv1.SelfSubjectAccessReviewSpec{
ResourceAttributes: &authv1.ResourceAttributes{
Group: "vteam.ambient-code",
Resource: "agenticsessions",
Verb: "list",
Namespace: projectHeader,
},
},
},
}
res, err := reqK8s.AuthorizationV1().SelfSubjectAccessReviews().Create(c.Request.Context(), ssar, v1.CreateOptions{})
if err != nil {
log.Printf("validateProjectContext: SSAR failed for %s: %v", projectHeader, err)
if errors.IsUnauthorized(err) {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Token expired or invalid"})
} else {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to perform access review"})
}
c.Abort()
return
}
if !res.Status.Allowed {
c.JSON(http.StatusForbidden, gin.H{"error": "Unauthorized to access project"})
c.Abort()
return
res, err := reqK8s.AuthorizationV1().SelfSubjectAccessReviews().Create(c.Request.Context(), ssar, v1.CreateOptions{})
if err != nil {
log.Printf("validateProjectContext: SSAR failed for %s: %v", projectHeader, err)
if errors.IsUnauthorized(err) {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Token expired or invalid"})
} else {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to perform access review"})
}
c.Abort()
return
}
globalSSARCache.store(cacheKey, res.Status.Allowed)
if !res.Status.Allowed {
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.

⚠️ Potential issue | 🔴 Critical

Do not authorize requests from a stale global SSAR cache.

A cache-hit true now bypasses the live SSAR completely, so RBAC revokes or token expiry/revocation can keep passing middleware until the cache entry ages out. A cache-hit false has the opposite problem and can keep newly granted users locked out. This needs invalidation tied to authz changes, or the cache cannot be the sole gate here.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/backend/handlers/middleware.go` around lines 313 - 349, The
current logic trusts globalSSARCache.check(cacheKey) unconditionally, which
allows stale allow/deny decisions to bypass live RBAC checks; fix by making
cache entries time-bound and validating freshness before skipping the live SSAR:
change globalSSARCache to store a timestamp with each entry and update the
middleware call (where ssarCacheKey, extractRequestToken, globalSSARCache.check,
and globalSSARCache.store are used) to treat stale entries as misses (i.e.,
perform reqK8s.AuthorizationV1().SelfSubjectAccessReviews().Create and then
store the new allowed value plus timestamp); ensure the cacheKey still includes
the request token so per-token entries are kept distinct.

Comment on lines +113 to +171
// connect dials an LDAP server (discovered via SRV or explicit URL) and performs an authenticated bind.
func (c *Client) connect() (*goldap.Conn, error) {
conn, err := goldap.DialURL(c.url, goldap.DialWithTLSConfig(&tls.Config{
MinVersion: tls.VersionTLS12,
InsecureSkipVerify: c.skipTLSVerify, //nolint:gosec // controlled by LDAP_SKIP_TLS_VERIFY env var for dev
}), goldap.DialWithDialer(&net.Dialer{Timeout: defaultConnTimeout}))
conn, err := c.dial()
if err != nil {
return nil, fmt.Errorf("ldap dial %s: %w", c.url, err)
return nil, err
}

if c.bindDN != "" {
if err := conn.Bind(c.bindDN, c.bindPassword); err != nil {
conn.Close()
return nil, fmt.Errorf("ldap bind: %w", err)
}
}

return conn, nil
}

// dial connects to an LDAP server. If srvDomain is configured, it discovers
// servers via DNS SRV records (_ldap._tcp.<domain>) and tries each in
// priority/weight order using LDAPS (port 636). Falls back to the explicit URL.
func (c *Client) dial() (*goldap.Conn, error) {
dialOpts := []goldap.DialOpt{
goldap.DialWithTLSConfig(c.tlsConfig),
goldap.DialWithDialer(&net.Dialer{Timeout: defaultConnTimeout}),
}

if c.srvDomain == "" {
conn, err := goldap.DialURL(c.url, dialOpts...)
if err != nil {
return nil, fmt.Errorf("ldap dial %s: %w", c.url, err)
}
return conn, nil
}

_, addrs, err := net.LookupSRV("ldap", "tcp", c.srvDomain)
if err != nil || len(addrs) == 0 {
if c.url != "" {
conn, dialErr := goldap.DialURL(c.url, dialOpts...)
if dialErr != nil {
return nil, fmt.Errorf("ldap SRV lookup failed (%v) and fallback dial %s failed: %w", err, c.url, dialErr)
}
return conn, nil
}
return nil, fmt.Errorf("ldap SRV lookup _ldap._tcp.%s: %w", c.srvDomain, err)
}

// SRV records return port 389 (plain LDAP); connect on 636 for LDAPS.
var lastErr error
for _, addr := range addrs {
host := strings.TrimSuffix(addr.Target, ".")
url := fmt.Sprintf("ldaps://%s:636", host)
conn, dialErr := goldap.DialURL(url, dialOpts...)
if dialErr != nil {
lastErr = fmt.Errorf("ldap dial %s: %w", url, dialErr)
continue
}
return conn, nil
}
return nil, fmt.Errorf("ldap all SRV targets for %s failed, last error: %w", c.srvDomain, lastErr)
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.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's examine the full ldap/client.go file to understand initialization and validation
fd -name "client.go" components/backend/ldap/

Repository: ambient-code/platform

Length of output: 295


🏁 Script executed:

# Find the complete file
find components/backend -name "client.go" -path "*ldap*"

Repository: ambient-code/platform

Length of output: 98


🏁 Script executed:

# Search more broadly
find . -name "*.go" -path "*ldap*" | head -20

Repository: ambient-code/platform

Length of output: 179


🏁 Script executed:

# Check for ldap files in backend
find components/backend -type f -name "*.go" | grep -i ldap

Repository: ambient-code/platform

Length of output: 173


🏁 Script executed:

# Read the full ldap/client.go file
cat -n components/backend/ldap/client.go

Repository: ambient-code/platform

Length of output: 15113


🏁 Script executed:

# Also check the test file to understand expected behavior
cat -n components/backend/ldap/client_test.go

Repository: ambient-code/platform

Length of output: 10950


🏁 Script executed:

# Check how the LDAP client is used in handlers
cat -n components/backend/handlers/ldap.go

Repository: ambient-code/platform

Length of output: 3643


🌐 Web query:

go-ldap library DialURL ldap:// vs ldaps:// scheme handling TLS enforcement

💡 Result:

The go-ldap library (github.com/go-ldap/ldap/v3, latest v3.4.13 as of 2026-03) handles ldap:// and ldaps:// schemes in DialURL as follows: - ldap:// uses plain TCP connection (port 389 by default), no TLS enforced. Dial("tcp", host:port). - ldaps:// uses TLS connection from the start (port 636 by default), with a default tls.Config{ServerName: host} passed to DialTLS. TLS is enforced by the scheme. DialURL signature: func DialURL(addr string, opts ...DialOpt) (*Conn, error). Options like DialWithTLSConfig allow custom TLS config for ldaps:// or forcing TLS on ldap://. No automatic STARTTLS on ldap://; use Conn.StartTLS manually after plain connect for opportunistic TLS upgrade. Source code confirms scheme-based routing to Dial vs DialTLS (v3.0.3+ unchanged in recent versions). Custom dialers/options added in v3.1.4+ (PR#249). Default ldaps:// enforces TLS but uses system cert pool (InsecureSkipVerify=false implicitly); customize via opts for CA/client certs.

Citations:


Require secure transport before bind, and respect SRV-discovered endpoints.

If bindDN is set and the fallback url is plain ldap:// (not ldaps://), conn.Bind() executes over unencrypted TCP, exposing credentials in cleartext. The DialWithTLSConfig option does not enforce TLS on the ldap:// scheme alone—you would need to call StartTLS() first.

Additionally, the SRV discovery path ignores the returned port (typically 389) and forces ldaps://host:636, which breaks standard LDAP SRV deployments that use StartTLS on port 389 (e.g., IPA).

Either require LDAPS for authenticated binds (validate url scheme or reject plain LDAP when bindDN is set), or respect the SRV port and use StartTLS for plain LDAP.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/backend/ldap/client.go` around lines 113 - 171, The connect/dial
logic must ensure binds never occur over plain LDAP and must respect SRV ports:
update dial() to use the actual SRV record Port instead of always forcing :636
and to choose ldaps:// when the SRV port is 636 (or when c.url has scheme
ldaps), otherwise dial plain ldap://host:port and return that connection; then
in connect() before calling conn.Bind() detect if the connection is plain LDAP
(scheme ldap or port 389) and either perform conn.StartTLS(c.tlsConfig) and
check for error, or if StartTLS is unsupported and c.bindDN != "" reject with an
error requiring LDAPS; also when using goldap.DialURL only pass
DialWithTLSConfig for ldaps:// connections (use StartTLS for plain ldap://) so
credentials are never sent in cleartext.

"lucide-react": "^0.542.0",
"marked": "^17.0.4",
"next": "16.1.5",
"next": "16.2.3",
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.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

python - <<'PY'
import json, re, pathlib
p = pathlib.Path("components/frontend/package.json")
data = json.loads(p.read_text())

next_v = data["dependencies"].get("next", "")
eslint_v = data["devDependencies"].get("eslint-config-next", "")

def major(v: str):
    m = re.search(r"\d+", v)
    return int(m.group()) if m else None

nmaj, emaj = major(next_v), major(eslint_v)
print(f"next={next_v} (major={nmaj})")
print(f"eslint-config-next={eslint_v} (major={emaj})")
print("RESULT=MATCH" if nmaj == emaj else "RESULT=MISMATCH")
PY

Repository: ambient-code/platform

Length of output: 140


🏁 Script executed:

# Check if there are CI configuration files indicating build status
fd -t f '\.(yml|yaml|json)$' -E node_modules -E dist | grep -E '(github|gitlab|circle|travis|jenkinsfile|tsconfig|eslintrc|next\.config)'

Repository: ambient-code/platform

Length of output: 292


🌐 Web query:

Next.js 16 eslint-config-next 15 compatibility

💡 Result:

eslint-config-next version 15 is not compatible with Next.js 16. Next.js 16 requires eslint-config-next version 16.x, which uses ESLint's new flat config format by default. Legacy (v15) configs are not backwards compatible in v16. Key changes in Next.js 16: - next lint command removed; use ESLint CLI directly (e.g., npx eslint .). - eslint option removed from next.config.js. - eslint-config-next v16 defaults to flat config (eslint.config.js/mjs), no longer supports legacy .eslintrc format without migration. To use with Next.js 16: 1. Upgrade to eslint-config-next@16 (latest 16.2.3 as of 2026-04-17). 2. Migrate config using codemod: npx @next/codemod@latest next-lint-to-eslint-cli . 3. Example flat config: import coreWebVitals from 'eslint-config-next/core-web-vitals'; import typescript from 'eslint-config-next/typescript'; const eslintConfig = [ ...coreWebVitals, ...typescript, ]; export default eslintConfig; Issue #84772 shows a Next.js 16 beta project with eslint-config-next 15.5.4, but post-release, v16 config is required for full compatibility, especially with flat config migration.

Citations:


🏁 Script executed:

# Check the actual Next.js version requirements for eslint-config-next
if [ -f components/frontend/package.json ]; then
  echo "=== package.json devDependencies context ===" && \
  sed -n '70,85p' components/frontend/package.json
fi

Repository: ambient-code/platform

Length of output: 588


🏁 Script executed:

# Look for build scripts and lint configuration
if [ -f components/frontend/package.json ]; then
  echo "=== Build scripts ===" && \
  jq '.scripts | select(. != null)' components/frontend/package.json 2>/dev/null || \
  grep -A 5 '"scripts"' components/frontend/package.json
fi

Repository: ambient-code/platform

Length of output: 320


🏁 Script executed:

# Check for ESLint configuration
fd -t f '\.eslintrc*' components/frontend/ 2>/dev/null || echo "No .eslintrc found"

Repository: ambient-code/platform

Length of output: 47


Upgrade eslint-config-next to v16 and migrate ESLint configuration for Next.js 16 compatibility.

Next.js 16 introduced a breaking change: eslint-config-next v15 is incompatible with Next.js 16. Line 47 upgrades next to 16.2.3, but Line 79 keeps eslint-config-next at 15.5.2. Version 15 uses legacy .eslintrc format; version 16 requires flat config (eslint.config.js). This mismatch will cause lint failures.

Required changes:

  1. Upgrade eslint-config-next to 16.2.3 (Line 79)
  2. Migrate ESLint config using: npx @next/codemod@latest next-lint-to-eslint-cli .
  3. Ensure eslint.config.js exists with flat config format
Proposed fix
-    "eslint-config-next": "15.5.2",
+    "eslint-config-next": "16.2.3",

Then run ESLint flat config migration codemod.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/frontend/package.json` at line 47, Package.json currently upgrades
"next" to 16.2.3 but leaves "eslint-config-next" at 15.5.2; update the
dependency "eslint-config-next" to 16.2.3 in package.json, then migrate the
project's ESLint setup from legacy .eslintrc to the flat config required by
Next.js 16 by running the codemod npx `@next/codemod`@latest
next-lint-to-eslint-cli . and create an eslint.config.js flat config (ensure
rules/plugins from the old .eslintrc are ported into the new eslint.config.js)
so linting aligns with Next 16.

Comment on lines +20 to +25
}: {
title: string;
icon: React.ElementType;
defaultOpen?: boolean;
badge?: string;
children: React.ReactNode;
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.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE='components/frontend/src/components/claude-agent-options/_components/section.tsx'

printf '== file header ==\n'
sed -n '1,30p' "$FILE"

printf '\n== React namespace usages ==\n'
rg -n 'React\.(ElementType|ReactNode)' "$FILE"

printf '\n== react imports ==\n'
rg -n 'from "react"' "$FILE" || true

Repository: ambient-code/platform

Length of output: 1019


Import the React types or TypeScript will fail to compile.

React.ElementType and React.ReactNode reference a namespace that isn't imported. With only import { useState } from "react", this will break the build.

Suggested fix
-import { useState } from "react";
+import { useState, type ElementType, type ReactNode } from "react";
@@
 }: {
   title: string;
-  icon: React.ElementType;
+  icon: ElementType;
   defaultOpen?: boolean;
   badge?: string;
-  children: React.ReactNode;
+  children: ReactNode;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@components/frontend/src/components/claude-agent-options/_components/section.tsx`
around lines 20 - 25, The props type uses React.ElementType and React.ReactNode
but only useState is imported; add the React type imports so TypeScript
compiles. Update the top import to include the types (e.g., import type {
ElementType, ReactNode } from "react") or import React itself, and then change
the prop annotations to reference ElementType and ReactNode (the symbols to look
for: React.ElementType, React.ReactNode in the section component props
definition and the useState import).

@markturansky
Copy link
Copy Markdown
Contributor Author

strange test failure:

go: module ../ambient-api-server requires go >= 1.25.0 (running go 1.24.4; GOTOOLCHAIN=local)
Error: Process completed with exit code 1.

when the existing main branch go version is 1.25

https://github.com/ambient-code/platform/blob/main/components/ambient-api-server/go.mod#L3

Brings alpha up to date with main. Key conflict resolutions:
- Makefile: combined control-plane, mcp, and observability-dashboard targets
- auth.py: kept kubeconfig credential provider + gh wrapper from both branches
- bridge.py: kept both asyncio and json imports
- pyproject.toml: main's tighter dep versions + alpha's grpc/protobuf/cryptography
- observability.py: main's refactored end_turn with null checks
- agents/model.go: main's full agent fields with BeforeCreate defaults
- kustomization.yaml: kept both control_plane and observability images
- DEVELOPMENT.md: kept both session stream docs and session creation docs
- test file: kept both bot token tests and gh wrapper tests
- uv.lock: taken from main

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@markturansky markturansky force-pushed the chore/rebase-main-to-alpha-manual branch from 717a0aa to 6a1743c Compare April 17, 2026 18:52
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
Makefile (2)

1283-1293: ⚠️ Potential issue | 🟠 Major

Load the control-plane image into kind here too.

build-all and push-all include $(CONTROL_PLANE_IMAGE), but _kind-load-images does not. With LOCAL_IMAGES=true or make kind-rebuild, the cluster can keep running a stale control-plane image even after a local rebuild.

💡 Suggested fix
-	`@for` img in $(BACKEND_IMAGE) $(FRONTEND_IMAGE) $(OPERATOR_IMAGE) $(RUNNER_IMAGE) $(STATE_SYNC_IMAGE) $(PUBLIC_API_IMAGE) $(API_SERVER_IMAGE) $(MCP_IMAGE) $(OBSERVABILITY_DASHBOARD_IMAGE); do \
+	`@for` img in $(BACKEND_IMAGE) $(FRONTEND_IMAGE) $(OPERATOR_IMAGE) $(RUNNER_IMAGE) $(STATE_SYNC_IMAGE) $(PUBLIC_API_IMAGE) $(API_SERVER_IMAGE) $(CONTROL_PLANE_IMAGE) $(MCP_IMAGE) $(OBSERVABILITY_DASHBOARD_IMAGE); do \

Based on learnings: Image references must match across the stack; after changing an image name or tag, grep all overlays, workflows, and ConfigMaps.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Makefile` around lines 1283 - 1293, The kind image-loading loop omits
$(CONTROL_PLANE_IMAGE) so local rebuilds can leave the cluster running a stale
control-plane image; update the image list used by the loop (the list containing
$(BACKEND_IMAGE) $(FRONTEND_IMAGE) ... $(OBSERVABILITY_DASHBOARD_IMAGE)) to also
include $(CONTROL_PLANE_IMAGE), or add an explicit load step for
$(CONTROL_PLANE_IMAGE) in the same `_kind-load-images` flow, ensuring the same
tag/name semantics and the same save/tag/load logic are applied to
`$(CONTROL_PLANE_IMAGE)`.

690-705: ⚠️ Potential issue | 🟠 Major

Makefile preflight gate is out of sync with module requirements.

Multiple modules require Go 1.25.0 (operator, public-api, ambient-control-plane, ambient-api-server, ambient-cli), but the preflight check only gates >= 1.21. This allows make preflight and make dev COMPONENT=backend to pass on Go 1.24, then fail immediately when building components requiring 1.25.

Update the Makefile threshold from 1.21 to 1.25 (or derive it from the maximum go directive across all go.mod files to stay in sync automatically).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Makefile` around lines 690 - 705, The Makefile preflight Go-version check
(the shell block gated by NEED_GO that computes GVER, GMAJ, GMIN and sets
FAILED) is using a 1.21 minimum; update it to require Go >= 1.25 by changing the
comparison logic (the test that currently checks GMAJ/GMIN against 1 and 21) to
check against 1 and 25, or better yet introduce a MIN_GO_MAJOR/MIN_GO_MINOR
constant and compare GMAJ/GMIN to those so the threshold (used by the
NEED_GO/GVER/GMAJ/GMIN/FAILED block) can be kept in sync or derived from go.mod
files automatically. Ensure the error messages and install hints still show the
required version (>= 1.25) when printing the red failure strings.
🧹 Nitpick comments (4)
.github/workflows/prod-release-deploy.yaml (4)

760-770: Add error handling for triage scripts.

If any script (fetch.sh, parse.py, analyze.py, report.py) fails, subsequent steps proceed with missing/corrupt data. Add set -e or explicit error checks:

        run: |
+         set -euo pipefail
          PREV_TAG=$(git tag --list 'v*.*.*' --sort=-version:refname | grep -v "^${NEW_TAG}$" | head -1)

          echo "Analyzing CodeRabbit reviews for ${NEW_TAG} (since ${PREV_TAG})..."
          bash fetch.sh --repo "${REPO}" --release "${NEW_TAG}" --since "${PREV_TAG}"

Also consider adding || exit 1 after critical commands if set -e isn't desired.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/prod-release-deploy.yaml around lines 760 - 770, Add
strict error handling so failures in fetch.sh, parse.py, analyze.py or report.py
stop the job: enable "set -euo pipefail" at the top of the run block (or add
"set -e" at minimum) and/or append "|| exit 1" to each critical command that
uses PREV_TAG/NEW_TAG (the PREV_TAG computation, bash fetch.sh --repo "${REPO}"
--release "${NEW_TAG}" --since "${PREV_TAG}", python3 parse.py
"data/${NEW_TAG}", python3 analyze.py "data/${NEW_TAG}" metrics/, python3
report.py metrics/ --release "${NEW_TAG}" > ../../triage-summary.md) so any
nonzero exit aborts the workflow and prevents downstream steps from running with
missing/corrupt data.

455-458: Add explicit permissions block.

This job lacks a permissions block, inheriting workflow defaults. Scope it minimally:

  deploy-rhoai-mlflow:
    runs-on: ubuntu-latest
    needs: [release]
+   permissions:
+     contents: read
    steps:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/prod-release-deploy.yaml around lines 455 - 458, The
deploy-rhoai-mlflow job currently inherits workflow defaults and must declare an
explicit permissions block: add a minimal permissions mapping under the job name
deploy-rhoai-mlflow that grants only the specific GitHub token scopes required
for deployment (e.g., contents: read or write, id-token: write, packages:
read/write, or other minimal scopes your deploy steps use) and set all other
permissions to none; update the job definition around the deploy-rhoai-mlflow
block to include this permissions: { ... } entry so the workflow no longer
relies on inherited defaults.

796-804: Shell variable expansion in release notes may corrupt formatting.

The heredoc uses unquoted ${TRIAGE} which can break if the triage summary contains special characters, backticks, or unbalanced quotes. Consider using a temp file approach:

      - name: Append triage summary to release notes
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NEW_TAG: ${{ needs.release.outputs.new_tag }}
        run: |
          EXISTING_BODY=$(gh release view "${NEW_TAG}" --json body -q .body)
-         TRIAGE=$(cat triage-summary.md)
-
-         gh release edit "${NEW_TAG}" \
-           --notes "${EXISTING_BODY}
-
-         ---
-         ## CodeRabbit Triage Summary
-         ${TRIAGE}"
+         {
+           echo "$EXISTING_BODY"
+           echo ""
+           echo "---"
+           echo "## CodeRabbit Triage Summary"
+           cat triage-summary.md
+         } > combined-notes.md
+         gh release edit "${NEW_TAG}" --notes-file combined-notes.md
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/prod-release-deploy.yaml around lines 796 - 804, The
current approach injects ${TRIAGE} directly into --notes which risks corrupting
formatting; instead create a temporary file (via mktemp), write the combined
content (include EXISTING_BODY, a separator, "## CodeRabbit Triage Summary", and
the contents of triage-summary.md / TRIAGE) into that temp file without
additional shell expansion, then call gh release edit "${NEW_TAG}" --notes-file
"$TMP" (or equivalent) and remove the temp file; update the block that builds
EXISTING_BODY/TRIAGE and the gh release edit invocation to use the temp-file
approach so special characters/backticks/quotes in TRIAGE do not break the
release notes.

560-560: Document DB_HOST format expectation or add validation.

The code assumes DB_HOST from postgresql-credentials is a short service name (e.g., postgresql), correctly appending .ambient-code.svc.cluster.local to form the FQDN. Current manifests follow this pattern consistently. However, there's no validation or documentation preventing someone from storing a full FQDN in db.host, which would result in a malformed URI (e.g., postgresql.ambient-code.svc.cluster.local.ambient-code.svc.cluster.local). Either add a check to strip the suffix if present, or document the expected format explicitly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/prod-release-deploy.yaml at line 560, The ENCODED_URI
construction currently appends ".ambient-code.svc.cluster.local" to DB_HOST
which breaks if DB_HOST already contains the full FQDN; update the workflow to
detect and normalize DB_HOST before building ENCODED_URI: if DB_HOST ends with
".ambient-code.svc.cluster.local" strip that suffix (or otherwise validate/exit)
so ENCODED_URI is always a correct FQDN, and also add a short comment
documenting that DB_HOST should be a short service name or a normalized host;
reference the ENCODED_URI variable and the DB_HOST input from
postgresql-credentials when implementing this check.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/prod-release-deploy.yaml:
- Around line 459-467: Replace the floating action versions with pinned SHAs:
update the two steps that use actions/checkout@v6 and
redhat-actions/openshift-tools-installer@v1 to reference the exact commit SHAs
(the same pinning style used in pre-pull-images and coderabbit-triage). Locate
the steps by the uses entries "actions/checkout" and
"redhat-actions/openshift-tools-installer" and replace the version tags with the
corresponding full SHA strings so the workflow pins those actions to immutable
commits.
- Around line 581-589: Replace the floating action versions with SHA-pinned refs
for the two steps: change uses: actions/checkout@v6 in the "Checkout code from
release tag" step to the corresponding commit SHA
(actions/checkout@<commit-sha>) and change uses:
redhat-actions/openshift-tools-installer@v1 in the "Install oc" step to that
action's specific commit SHA
(redhat-actions/openshift-tools-installer@<commit-sha>); update the workflow to
use those exact SHAs so the "Checkout code from release tag" and "Install oc"
steps no longer reference floating tags.
- Around line 173-192: The "Generate Loading Tips" step commits changes to
components/frontend/src/lib/loading-tips.ts but never pushes them, so the
subsequent tag created will not include that commit; after the git commit in the
Generate Loading Tips step, push the commit to the repository (e.g., git push
origin HEAD) so the new commit is on the branch before the workflow's "Create
Tag" step runs (or alternatively reorder to tag and push tags only after pushing
the commit); update the step that runs python3 scripts/generate-loading-tips.py
and the block that does git config/git add/git commit to include a git push of
HEAD so the tag created later includes the updated loading-tips.ts.
- Around line 416-421: The current oc patch uses inline JSON which can break if
image names contain quotes or backslashes; update the step that patches the
acp-image-puller-config ConfigMap to JSON-encode the IMAGES value safely (the
value from steps.image-list.outputs.images) using jq (or similar) and pass the
encoded payload to oc patch instead of embedding the raw string; specifically
change the oc patch invocation that sets data.IMAGES to build the JSON with jq
-n --arg v ... '{data:{IMAGES:$v}}' (or equivalent) so the IMAGES value is
properly escaped before calling oc patch.

In `@Makefile`:
- Around line 233-236: The build-all invocation pulls in the
build-observability-dashboard target which unconditionally cds into
../observability/dashboard (target build-observability-dashboard) that doesn't
exist in fresh clones; update the Makefile to either (A) provision the
observability/dashboard as a git submodule and document initializing it, or (B)
add a guard around inclusion/execution so build-all only depends on
build-observability-dashboard if the ../observability/dashboard directory exists
(check with test -d or an ifeq in the Makefile) and otherwise skip or emit a
clear info message—modify the build-all dependency list and the
build-observability-dashboard target to perform the existence check and avoid
failing on fresh clones.

---

Outside diff comments:
In `@Makefile`:
- Around line 1283-1293: The kind image-loading loop omits
$(CONTROL_PLANE_IMAGE) so local rebuilds can leave the cluster running a stale
control-plane image; update the image list used by the loop (the list containing
$(BACKEND_IMAGE) $(FRONTEND_IMAGE) ... $(OBSERVABILITY_DASHBOARD_IMAGE)) to also
include $(CONTROL_PLANE_IMAGE), or add an explicit load step for
$(CONTROL_PLANE_IMAGE) in the same `_kind-load-images` flow, ensuring the same
tag/name semantics and the same save/tag/load logic are applied to
`$(CONTROL_PLANE_IMAGE)`.
- Around line 690-705: The Makefile preflight Go-version check (the shell block
gated by NEED_GO that computes GVER, GMAJ, GMIN and sets FAILED) is using a 1.21
minimum; update it to require Go >= 1.25 by changing the comparison logic (the
test that currently checks GMAJ/GMIN against 1 and 21) to check against 1 and
25, or better yet introduce a MIN_GO_MAJOR/MIN_GO_MINOR constant and compare
GMAJ/GMIN to those so the threshold (used by the NEED_GO/GVER/GMAJ/GMIN/FAILED
block) can be kept in sync or derived from go.mod files automatically. Ensure
the error messages and install hints still show the required version (>= 1.25)
when printing the red failure strings.

---

Nitpick comments:
In @.github/workflows/prod-release-deploy.yaml:
- Around line 760-770: Add strict error handling so failures in fetch.sh,
parse.py, analyze.py or report.py stop the job: enable "set -euo pipefail" at
the top of the run block (or add "set -e" at minimum) and/or append "|| exit 1"
to each critical command that uses PREV_TAG/NEW_TAG (the PREV_TAG computation,
bash fetch.sh --repo "${REPO}" --release "${NEW_TAG}" --since "${PREV_TAG}",
python3 parse.py "data/${NEW_TAG}", python3 analyze.py "data/${NEW_TAG}"
metrics/, python3 report.py metrics/ --release "${NEW_TAG}" >
../../triage-summary.md) so any nonzero exit aborts the workflow and prevents
downstream steps from running with missing/corrupt data.
- Around line 455-458: The deploy-rhoai-mlflow job currently inherits workflow
defaults and must declare an explicit permissions block: add a minimal
permissions mapping under the job name deploy-rhoai-mlflow that grants only the
specific GitHub token scopes required for deployment (e.g., contents: read or
write, id-token: write, packages: read/write, or other minimal scopes your
deploy steps use) and set all other permissions to none; update the job
definition around the deploy-rhoai-mlflow block to include this permissions: {
... } entry so the workflow no longer relies on inherited defaults.
- Around line 796-804: The current approach injects ${TRIAGE} directly into
--notes which risks corrupting formatting; instead create a temporary file (via
mktemp), write the combined content (include EXISTING_BODY, a separator, "##
CodeRabbit Triage Summary", and the contents of triage-summary.md / TRIAGE) into
that temp file without additional shell expansion, then call gh release edit
"${NEW_TAG}" --notes-file "$TMP" (or equivalent) and remove the temp file;
update the block that builds EXISTING_BODY/TRIAGE and the gh release edit
invocation to use the temp-file approach so special characters/backticks/quotes
in TRIAGE do not break the release notes.
- Line 560: The ENCODED_URI construction currently appends
".ambient-code.svc.cluster.local" to DB_HOST which breaks if DB_HOST already
contains the full FQDN; update the workflow to detect and normalize DB_HOST
before building ENCODED_URI: if DB_HOST ends with
".ambient-code.svc.cluster.local" strip that suffix (or otherwise validate/exit)
so ENCODED_URI is always a correct FQDN, and also add a short comment
documenting that DB_HOST should be a short service name or a normalized host;
reference the ENCODED_URI variable and the DB_HOST input from
postgresql-credentials when implementing this check.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a1750a13-0e57-44d2-bb93-447108202ec5

📥 Commits

Reviewing files that changed from the base of the PR and between 717a0aa and 6a1743c.

⛔ Files ignored due to path filters (2)
  • components/ambient-cli/go.sum is excluded by !**/*.sum, !**/go.sum
  • components/ambient-control-plane/go.sum is excluded by !**/*.sum, !**/go.sum
📒 Files selected for processing (14)
  • .github/workflows/components-build-deploy.yml
  • .github/workflows/prod-release-deploy.yaml
  • .gitignore
  • Makefile
  • components/ambient-api-server/Dockerfile
  • components/ambient-api-server/plugins/agents/model.go
  • components/ambient-api-server/plugins/sessions/integration_test.go
  • components/ambient-api-server/plugins/sessions/model.go
  • components/ambient-cli/go.mod
  • components/ambient-control-plane/Dockerfile
  • components/ambient-control-plane/go.mod
  • components/ambient-sdk/go-sdk/go.mod
  • components/backend/DEVELOPMENT.md
  • components/frontend/DEVELOPMENT.md
✅ Files skipped from review due to trivial changes (5)
  • components/ambient-control-plane/Dockerfile
  • components/ambient-sdk/go-sdk/go.mod
  • .gitignore
  • components/backend/DEVELOPMENT.md
  • .github/workflows/components-build-deploy.yml
🚧 Files skipped from review as they are similar to previous changes (6)
  • components/ambient-api-server/plugins/sessions/integration_test.go
  • components/ambient-api-server/plugins/sessions/model.go
  • components/ambient-cli/go.mod
  • components/ambient-api-server/Dockerfile
  • components/frontend/DEVELOPMENT.md
  • components/ambient-api-server/plugins/agents/model.go

Comment on lines +173 to +192
- name: Generate Loading Tips
run: |
LATEST_TAG="${{ steps.get_latest_tag.outputs.latest_tag }}"
NEW_TAG="${{ steps.next_version.outputs.new_tag }}"
REPO="${{ github.repository }}"
OUTPUT="components/frontend/src/lib/loading-tips.ts"

python3 scripts/generate-loading-tips.py "$NEW_TAG" "$LATEST_TAG" "$REPO" "$OUTPUT"

# Commit the updated loading tips so the frontend build includes them
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add "$OUTPUT"
if git diff --cached --quiet; then
echo "No loading tips changes to commit"
else
git commit -m "chore(frontend): update loading tips for ${NEW_TAG}

Auto-generated release tips highlighting contributors and changes."
fi
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.

⚠️ Potential issue | 🟠 Major

Loading tips commit is never pushed, so the tag won't include it.

The step commits the updated loading-tips.ts locally but never pushes. The subsequent "Create Tag" step tags the current HEAD, which on a fresh checkout is the branch tip—not your new commit. The frontend image build (which checks out the tag) will therefore miss these changes.

Either push before tagging or reorder to commit + push + tag:

          else
            git commit -m "chore(frontend): update loading tips for ${NEW_TAG}

          Auto-generated release tips highlighting contributors and changes."
+           git push origin HEAD
          fi

Alternatively, consider generating tips as a separate pre-release workflow that lands on main before the release runs.

📝 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
- name: Generate Loading Tips
run: |
LATEST_TAG="${{ steps.get_latest_tag.outputs.latest_tag }}"
NEW_TAG="${{ steps.next_version.outputs.new_tag }}"
REPO="${{ github.repository }}"
OUTPUT="components/frontend/src/lib/loading-tips.ts"
python3 scripts/generate-loading-tips.py "$NEW_TAG" "$LATEST_TAG" "$REPO" "$OUTPUT"
# Commit the updated loading tips so the frontend build includes them
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add "$OUTPUT"
if git diff --cached --quiet; then
echo "No loading tips changes to commit"
else
git commit -m "chore(frontend): update loading tips for ${NEW_TAG}
Auto-generated release tips highlighting contributors and changes."
fi
- name: Generate Loading Tips
run: |
LATEST_TAG="${{ steps.get_latest_tag.outputs.latest_tag }}"
NEW_TAG="${{ steps.next_version.outputs.new_tag }}"
REPO="${{ github.repository }}"
OUTPUT="components/frontend/src/lib/loading-tips.ts"
python3 scripts/generate-loading-tips.py "$NEW_TAG" "$LATEST_TAG" "$REPO" "$OUTPUT"
# Commit the updated loading tips so the frontend build includes them
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add "$OUTPUT"
if git diff --cached --quiet; then
echo "No loading tips changes to commit"
else
git commit -m "chore(frontend): update loading tips for ${NEW_TAG}
Auto-generated release tips highlighting contributors and changes."
git push origin HEAD
fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/prod-release-deploy.yaml around lines 173 - 192, The
"Generate Loading Tips" step commits changes to
components/frontend/src/lib/loading-tips.ts but never pushes them, so the
subsequent tag created will not include that commit; after the git commit in the
Generate Loading Tips step, push the commit to the repository (e.g., git push
origin HEAD) so the new commit is on the branch before the workflow's "Create
Tag" step runs (or alternatively reorder to tag and push tags only after pushing
the commit); update the step that runs python3 scripts/generate-loading-tips.py
and the block that does git config/git add/git commit to include a git push of
HEAD so the tag created later includes the updated loading-tips.ts.

Comment on lines +416 to +421
- name: Update image puller ConfigMap with new images
run: |
oc patch configmap acp-image-puller-config \
-n acp-image-puller \
--type merge \
-p "{\"data\":{\"IMAGES\":\"${{ steps.image-list.outputs.images }}\"}}"
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.

⚠️ Potential issue | 🟡 Minor

JSON injection risk in ConfigMap patch.

If any image name/tag contains characters like " or \, the inline JSON will break. Use jq to safely encode the value:

      - name: Update image puller ConfigMap with new images
        run: |
-         oc patch configmap acp-image-puller-config \
-           -n acp-image-puller \
-           --type merge \
-           -p "{\"data\":{\"IMAGES\":\"${{ steps.image-list.outputs.images }}\"}}"
+         IMAGES='${{ steps.image-list.outputs.images }}'
+         PATCH=$(jq -n --arg images "$IMAGES" '{"data":{"IMAGES":$images}}')
+         oc patch configmap acp-image-puller-config \
+           -n acp-image-puller \
+           --type merge \
+           -p "$PATCH"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/prod-release-deploy.yaml around lines 416 - 421, The
current oc patch uses inline JSON which can break if image names contain quotes
or backslashes; update the step that patches the acp-image-puller-config
ConfigMap to JSON-encode the IMAGES value safely (the value from
steps.image-list.outputs.images) using jq (or similar) and pass the encoded
payload to oc patch instead of embedding the raw string; specifically change the
oc patch invocation that sets data.IMAGES to build the JSON with jq -n --arg v
... '{data:{IMAGES:$v}}' (or equivalent) so the IMAGES value is properly escaped
before calling oc patch.

Comment on lines +459 to +467
- name: Checkout code from release tag
uses: actions/checkout@v6
with:
ref: ${{ needs.release.outputs.new_tag }}

- name: Install oc
uses: redhat-actions/openshift-tools-installer@v1
with:
oc: latest
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.

⚠️ Potential issue | 🟠 Major

Pin actions to SHA per coding guidelines.

Both actions/checkout@v6 and redhat-actions/openshift-tools-installer@v1 should be pinned to SHA. Elsewhere in this file (e.g., pre-pull-images and coderabbit-triage), the same actions are properly pinned.

      - name: Checkout code from release tag
-       uses: actions/checkout@v6
+       uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          ref: ${{ needs.release.outputs.new_tag }}

      - name: Install oc
-       uses: redhat-actions/openshift-tools-installer@v1
+       uses: redhat-actions/openshift-tools-installer@144527c7d98999f2652264c048c7a9bd103f8a82 # v1
        with:
          oc: latest

As per coding guidelines: "Pin action versions to SHA."

📝 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
- name: Checkout code from release tag
uses: actions/checkout@v6
with:
ref: ${{ needs.release.outputs.new_tag }}
- name: Install oc
uses: redhat-actions/openshift-tools-installer@v1
with:
oc: latest
- name: Checkout code from release tag
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ needs.release.outputs.new_tag }}
- name: Install oc
uses: redhat-actions/openshift-tools-installer@144527c7d98999f2652264c048c7a9bd103f8a82 # v1
with:
oc: latest
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/prod-release-deploy.yaml around lines 459 - 467, Replace
the floating action versions with pinned SHAs: update the two steps that use
actions/checkout@v6 and redhat-actions/openshift-tools-installer@v1 to reference
the exact commit SHAs (the same pinning style used in pre-pull-images and
coderabbit-triage). Locate the steps by the uses entries "actions/checkout" and
"redhat-actions/openshift-tools-installer" and replace the version tags with the
corresponding full SHA strings so the workflow pins those actions to immutable
commits.

Comment on lines 581 to +589
- name: Checkout code from release tag
uses: actions/checkout@v6
with:
ref: ${{ needs.release.outputs.new_tag }}

- name: Install oc
uses: redhat-actions/oc-installer@v1
uses: redhat-actions/openshift-tools-installer@v1
with:
oc_version: 'latest'
oc: latest
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.

⚠️ Potential issue | 🟠 Major

Pin actions to SHA.

Same issue as deploy-rhoai-mlflow—use SHA-pinned versions:

      - name: Checkout code from release tag
-       uses: actions/checkout@v6
+       uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          ref: ${{ needs.release.outputs.new_tag }}

      - name: Install oc
-       uses: redhat-actions/openshift-tools-installer@v1
+       uses: redhat-actions/openshift-tools-installer@144527c7d98999f2652264c048c7a9bd103f8a82 # v1
        with:
          oc: latest

As per coding guidelines: "Pin action versions to SHA."

📝 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
- name: Checkout code from release tag
uses: actions/checkout@v6
with:
ref: ${{ needs.release.outputs.new_tag }}
- name: Install oc
uses: redhat-actions/oc-installer@v1
uses: redhat-actions/openshift-tools-installer@v1
with:
oc_version: 'latest'
oc: latest
- name: Checkout code from release tag
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ needs.release.outputs.new_tag }}
- name: Install oc
uses: redhat-actions/openshift-tools-installer@144527c7d98999f2652264c048c7a9bd103f8a82 # v1
with:
oc: latest
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/prod-release-deploy.yaml around lines 581 - 589, Replace
the floating action versions with SHA-pinned refs for the two steps: change
uses: actions/checkout@v6 in the "Checkout code from release tag" step to the
corresponding commit SHA (actions/checkout@<commit-sha>) and change uses:
redhat-actions/openshift-tools-installer@v1 in the "Install oc" step to that
action's specific commit SHA
(redhat-actions/openshift-tools-installer@<commit-sha>); update the workflow to
use those exact SHAs so the "Checkout code from release tag" and "Install oc"
steps no longer reference floating tags.

Comment thread Makefile
Comment on lines +233 to +236
build-observability-dashboard: ## Build observability dashboard image
@echo "$(COLOR_BLUE)▶$(COLOR_RESET) Building observability-dashboard with $(CONTAINER_ENGINE)..."
@cd ../observability/dashboard && $(CONTAINER_ENGINE) build $(PLATFORM_FLAG) $(BUILD_FLAGS) \
-t $(OBSERVABILITY_DASHBOARD_IMAGE) .
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.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Dashboard-related paths tracked in this repo:\n'
fd -td 'observability|dashboard' . | sort || true

printf '\nMakefile references:\n'
rg -n '\.\./observability/dashboard|build-observability-dashboard|build-all' Makefile

printf '\nPotential callers of build-all / dashboard build:\n'
rg -n 'build-all|build-observability-dashboard|kind-rebuild|LOCAL_IMAGES=true'

Repository: ambient-code/platform

Length of output: 5368


build-observability-dashboard requires external sibling checkout.

Makefile line 235 invokes cd ../observability/dashboard, which is not present in this repository. Since build-all (line 168) includes this target unconditionally, it will fail on fresh clones. This breaks documented workflows: make kind-up LOCAL_IMAGES=true (line 862) and make kind-rebuild (line 1062) both depend on build-all.

Either provision the external dashboard source as a git submodule/sibling, or conditionally include build-observability-dashboard in build-all with a guard checking for the directory's existence.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Makefile` around lines 233 - 236, The build-all invocation pulls in the
build-observability-dashboard target which unconditionally cds into
../observability/dashboard (target build-observability-dashboard) that doesn't
exist in fresh clones; update the Makefile to either (A) provision the
observability/dashboard as a git submodule and document initializing it, or (B)
add a guard around inclusion/execution so build-all only depends on
build-observability-dashboard if the ../observability/dashboard directory exists
(check with test -d or an ifeq in the Makefile) and otherwise skip or emit a
clear info message—modify the build-all dependency list and the
build-observability-dashboard target to perform the existence check and avoid
failing on fresh clones.

@markturansky
Copy link
Copy Markdown
Contributor Author

all builds fixed and all tests pass. the failure is boundary/file limit. merging.

@markturansky markturansky merged commit 57e956b into alpha Apr 17, 2026
52 of 53 checks passed
@markturansky markturansky deleted the chore/rebase-main-to-alpha-manual branch April 17, 2026 19:19
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.