From 7be3b910f4fc434d9c40ec78181e6c7df2d04486 Mon Sep 17 00:00:00 2001 From: "firat.sertgoz" Date: Mon, 6 Apr 2026 19:45:26 +0300 Subject: [PATCH 1/7] [codex] Label migration PRs with DB MIGRATION (#1967) * Add DB MIGRATION PR label * Broaden DB MIGRATION label coverage * chore(ci): address DB MIGRATION label review feedback --- .github/labeler.yml | 10 ++++++++-- .github/scripts/create-labels.sh | 3 +++ .github/workflows/pr-label-scope.yml | 9 ++++++++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index fd7da0be2f..6ac08552b0 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,5 +1,5 @@ -# Scope labels for actions/labeler@v6 -# Maps file path globs to scope labels. Multiple labels can apply per PR. +# Labels for actions/labeler@v6 +# Maps file path globs to labels. Multiple labels can apply per PR. "scope: agent": - changed-files: @@ -164,3 +164,9 @@ - any-glob-to-any-file: - Cargo.toml - Cargo.lock + +"DB MIGRATION": + - changed-files: + - any-glob-to-any-file: + - migrations/** + - src/db/libsql_migrations.rs diff --git a/.github/scripts/create-labels.sh b/.github/scripts/create-labels.sh index 66f07ea9ce..6b6d10d3cd 100755 --- a/.github/scripts/create-labels.sh +++ b/.github/scripts/create-labels.sh @@ -62,6 +62,9 @@ create "scope: ci" "546E7A" "CI/CD workflows" create "scope: docs" "78909C" "Documentation" create "scope: dependencies" "90A4AE" "Dependency updates" +echo "==> Creating coordination labels..." +create "DB MIGRATION" "C62828" "PR adds or modifies PostgreSQL or libSQL migration definitions" + echo "==> Creating workflow labels..." create "skip-regression-check" "9E9E9E" "Acknowledged: fix without regression test" diff --git a/.github/workflows/pr-label-scope.yml b/.github/workflows/pr-label-scope.yml index 1c3885612e..b8a282472b 100644 --- a/.github/workflows/pr-label-scope.yml +++ b/.github/workflows/pr-label-scope.yml @@ -6,13 +6,20 @@ on: permissions: contents: read + issues: write pull-requests: write jobs: scope: runs-on: ubuntu-latest steps: - - uses: actions/labeler@v5 + - name: Ensure DB MIGRATION label exists + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REPO: ${{ github.repository }} + run: gh label create "DB MIGRATION" --repo "$REPO" --color C62828 --description "PR adds or modifies PostgreSQL or libSQL migration definitions" --force + + - uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5 with: configuration-path: .github/labeler.yml sync-labels: false # additive only — never remove scope labels From 6f7575de5ce93f2cd0208e89296e9234ec2a058d Mon Sep 17 00:00:00 2001 From: "firat.sertgoz" Date: Wed, 8 Apr 2026 11:06:15 +0300 Subject: [PATCH 2/7] Fix Telegram UTF-16 message splitting (#1961) * Fix Telegram UTF-16 message splitting * fix: bump telegram channel registry version --- channels-src/telegram/src/lib.rs | 94 +++++++++++++++++++++++++------- registry/channels/telegram.json | 2 +- 2 files changed, 76 insertions(+), 20 deletions(-) diff --git a/channels-src/telegram/src/lib.rs b/channels-src/telegram/src/lib.rs index f34ed68aa7..42f3c28659 100644 --- a/channels-src/telegram/src/lib.rs +++ b/channels-src/telegram/src/lib.rs @@ -363,6 +363,26 @@ const TELEGRAM_STATUS_MAX_CHARS: usize = 600; /// Telegram's hard limit for message text length. const TELEGRAM_MAX_MESSAGE_LEN: usize = 4096; +fn utf16_code_unit_len(text: &str) -> usize { + text.encode_utf16().count() +} + +fn prefix_within_utf16_limit(text: &str, max_units: usize) -> usize { + let mut units = 0; + let mut end = 0; + + for (byte_idx, ch) in text.char_indices() { + let ch_units = ch.len_utf16(); + if units + ch_units > max_units { + break; + } + units += ch_units; + end = byte_idx + ch.len_utf8(); + } + + end +} + fn truncate_status_message(input: &str, max_chars: usize) -> String { let mut iter = input.chars(); let truncated: String = iter.by_ref().take(max_chars).collect(); @@ -373,7 +393,7 @@ fn truncate_status_message(input: &str, max_chars: usize) -> String { } } -/// Split a long message into chunks that fit within Telegram's 4096-char limit. +/// Split a long message into chunks that fit within Telegram's 4096 UTF-16-unit limit. /// /// Tries to split at the most natural boundary available (in priority order): /// 1. Double newline (paragraph break) @@ -382,7 +402,7 @@ fn truncate_status_message(input: &str, max_chars: usize) -> String { /// 4. Word boundary (space) /// 5. Hard cut at the limit (last resort for pathological input) fn split_message(text: &str) -> Vec { - if text.chars().count() <= TELEGRAM_MAX_MESSAGE_LEN { + if utf16_code_unit_len(text) <= TELEGRAM_MAX_MESSAGE_LEN { return vec![text.to_string()]; } @@ -390,13 +410,8 @@ fn split_message(text: &str) -> Vec { let mut remaining = text; while !remaining.is_empty() { - // Count chars to find the byte offset for our window. - let window_bytes = remaining - .char_indices() - .take(TELEGRAM_MAX_MESSAGE_LEN) - .last() - .map(|(byte_idx, ch)| byte_idx + ch.len_utf8()) - .unwrap_or(remaining.len()); + // Find the longest UTF-8 prefix that fits within Telegram's UTF-16 limit. + let window_bytes = prefix_within_utf16_limit(remaining, TELEGRAM_MAX_MESSAGE_LEN); if window_bytes >= remaining.len() { // Remainder fits entirely. @@ -404,10 +419,24 @@ fn split_message(text: &str) -> Vec { break; } + if window_bytes == 0 { + // Defensive fallback: make progress even if a future caller uses a + // smaller limit than a single scalar value can fit within. + let first_char_len = remaining + .chars() + .next() + .map(|ch| ch.len_utf8()) + .unwrap_or(remaining.len()); + chunks.push(remaining[..first_char_len].to_string()); + remaining = &remaining[first_char_len..]; + continue; + } + let window = &remaining[..window_bytes]; // 1. Double newline — best paragraph boundary - let split_at = window.rfind("\n\n") + let split_at = window + .rfind("\n\n") // 2. Single newline .or_else(|| window.rfind('\n')) // 3. Sentence-ending punctuation followed by space. @@ -417,9 +446,9 @@ fn split_message(text: &str) -> Vec { .or_else(|| { let bytes = window.as_bytes(); // Search backwards for '. ', '! ', '? ' - (1..bytes.len()).rev().find(|&i| { - matches!(bytes[i - 1], b'.' | b'!' | b'?') && bytes[i] == b' ' - }) + (1..bytes.len()) + .rev() + .find(|&i| matches!(bytes[i - 1], b'.' | b'!' | b'?') && bytes[i] == b' ') }) // 4. Word boundary (last space) .or_else(|| window.rfind(' ')) @@ -427,7 +456,11 @@ fn split_message(text: &str) -> Vec { .unwrap_or(window_bytes); // Avoid empty chunks (e.g. text starting with \n\n). - let split_at = if split_at == 0 { window_bytes } else { split_at }; + let split_at = if split_at == 0 { + window_bytes + } else { + split_at + }; // Trim whitespace at chunk boundaries for clean Telegram display. // Note: this drops leading/trailing spaces at split points, which is @@ -1321,7 +1354,13 @@ fn send_response( for (i, chunk) in chunks.into_iter().enumerate() { // Try Markdown, fall back to plain text on parse errors - let result = send_message(chat_id, &chunk, reply_to, Some("Markdown"), message_thread_id); + let result = send_message( + chat_id, + &chunk, + reply_to, + Some("Markdown"), + message_thread_id, + ); let msg_id = match result { Ok(id) => { @@ -2150,6 +2189,10 @@ export!(TelegramChannel); mod tests { use super::*; + fn utf16_len(text: &str) -> usize { + text.encode_utf16().count() + } + #[test] fn test_split_message_short() { let text = "Hello, world!"; @@ -2177,7 +2220,7 @@ mod tests { let chunks = split_message(&text); assert!(chunks.len() > 1, "expected multiple chunks"); for chunk in &chunks { - assert!(chunk.chars().count() <= TELEGRAM_MAX_MESSAGE_LEN); + assert!(utf16_len(chunk) <= TELEGRAM_MAX_MESSAGE_LEN); } // Rejoined chunks must equal the original text exactly. let rejoined = chunks.join(" "); @@ -2193,7 +2236,7 @@ mod tests { assert!(text.len() > TELEGRAM_MAX_MESSAGE_LEN); let chunks = split_message(&text); for chunk in &chunks { - assert!(chunk.chars().count() <= TELEGRAM_MAX_MESSAGE_LEN); + assert!(utf16_len(chunk) <= TELEGRAM_MAX_MESSAGE_LEN); } } @@ -2223,7 +2266,7 @@ mod tests { let chunks = split_message(&text); assert!(chunks.len() >= 2); for chunk in &chunks { - assert!(chunk.chars().count() <= TELEGRAM_MAX_MESSAGE_LEN); + assert!(utf16_len(chunk) <= TELEGRAM_MAX_MESSAGE_LEN); } // Rejoined must preserve all characters let rejoined: String = chunks.concat(); @@ -2240,12 +2283,25 @@ mod tests { let chunks = split_message(&text); assert!(chunks.len() >= 2); for chunk in &chunks { - assert!(chunk.chars().count() <= TELEGRAM_MAX_MESSAGE_LEN); + assert!(utf16_len(chunk) <= TELEGRAM_MAX_MESSAGE_LEN); // Every char should be a complete emoji assert!(chunk.chars().all(|c| c == '\u{1F600}')); } } + #[test] + fn test_split_message_exact_utf16_limit_for_surrogate_pairs() { + let emoji = "\u{1F600}"; // 😀 + let text = emoji.repeat(TELEGRAM_MAX_MESSAGE_LEN); + + let chunks = split_message(&text); + + assert_eq!(chunks.len(), 2); + assert!(chunks + .iter() + .all(|chunk| utf16_len(chunk) <= TELEGRAM_MAX_MESSAGE_LEN)); + } + #[test] fn test_clean_message_text() { // Without bot_username: strips any leading @mention diff --git a/registry/channels/telegram.json b/registry/channels/telegram.json index 52f66ce306..267d9c18c3 100644 --- a/registry/channels/telegram.json +++ b/registry/channels/telegram.json @@ -2,7 +2,7 @@ "name": "telegram", "display_name": "Telegram Channel", "kind": "channel", - "version": "0.2.5", + "version": "0.2.6", "wit_version": "0.3.0", "description": "Talk to your agent through a Telegram bot", "keywords": [ From f0db0a3d3fcb0d31c03bd85eb19d83d225f2df84 Mon Sep 17 00:00:00 2001 From: Henry Park Date: Wed, 8 Apr 2026 21:18:45 -0700 Subject: [PATCH 3/7] chore: bump registry versions for github tool, whatsapp and telegram channels Co-Authored-By: Claude Opus 4.6 (1M context) --- registry/channels/telegram.json | 2 +- registry/channels/whatsapp.json | 2 +- registry/tools/github.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/registry/channels/telegram.json b/registry/channels/telegram.json index 267d9c18c3..12d4a42c19 100644 --- a/registry/channels/telegram.json +++ b/registry/channels/telegram.json @@ -2,7 +2,7 @@ "name": "telegram", "display_name": "Telegram Channel", "kind": "channel", - "version": "0.2.6", + "version": "0.2.7", "wit_version": "0.3.0", "description": "Talk to your agent through a Telegram bot", "keywords": [ diff --git a/registry/channels/whatsapp.json b/registry/channels/whatsapp.json index be3faf0dc9..3831d4bb62 100644 --- a/registry/channels/whatsapp.json +++ b/registry/channels/whatsapp.json @@ -2,7 +2,7 @@ "name": "whatsapp", "display_name": "WhatsApp Channel", "kind": "channel", - "version": "0.2.0", + "version": "0.2.1", "wit_version": "0.3.0", "description": "Talk to your agent through WhatsApp", "keywords": [ diff --git a/registry/tools/github.json b/registry/tools/github.json index 5af2452360..c6805374ea 100644 --- a/registry/tools/github.json +++ b/registry/tools/github.json @@ -2,7 +2,7 @@ "name": "github", "display_name": "GitHub", "kind": "tool", - "version": "0.2.2", + "version": "0.2.3", "wit_version": "0.3.0", "description": "GitHub integration for repositories, issues, pull requests, search, branches, file writes, releases, and workflows", "keywords": [ From 92388b7a5caa85a68efd0c6c04133378b28e62c7 Mon Sep 17 00:00:00 2001 From: Henry Park Date: Fri, 10 Apr 2026 16:19:17 -0700 Subject: [PATCH 4/7] revert: undo 2 main-only commits to unblock staging-promote merge (#2297) Reverts: - 6f7575de Fix Telegram UTF-16 message splitting (#1961) - 7be3b910 [codex] Label migration PRs with DB MIGRATION (#1967) Keeps f0db0a3d (registry version bumps) intact. These changes were made directly on main and conflict with staging-promote. Both already exist in staging and will flow back to main via the promote merge. Co-authored-by: Claude Opus 4.6 (1M context) --- .github/labeler.yml | 10 +-- .github/scripts/create-labels.sh | 3 - .github/workflows/pr-label-scope.yml | 9 +-- channels-src/telegram/src/lib.rs | 94 ++++++---------------------- 4 files changed, 22 insertions(+), 94 deletions(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index 6ac08552b0..fd7da0be2f 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,5 +1,5 @@ -# Labels for actions/labeler@v6 -# Maps file path globs to labels. Multiple labels can apply per PR. +# Scope labels for actions/labeler@v6 +# Maps file path globs to scope labels. Multiple labels can apply per PR. "scope: agent": - changed-files: @@ -164,9 +164,3 @@ - any-glob-to-any-file: - Cargo.toml - Cargo.lock - -"DB MIGRATION": - - changed-files: - - any-glob-to-any-file: - - migrations/** - - src/db/libsql_migrations.rs diff --git a/.github/scripts/create-labels.sh b/.github/scripts/create-labels.sh index 6b6d10d3cd..66f07ea9ce 100755 --- a/.github/scripts/create-labels.sh +++ b/.github/scripts/create-labels.sh @@ -62,9 +62,6 @@ create "scope: ci" "546E7A" "CI/CD workflows" create "scope: docs" "78909C" "Documentation" create "scope: dependencies" "90A4AE" "Dependency updates" -echo "==> Creating coordination labels..." -create "DB MIGRATION" "C62828" "PR adds or modifies PostgreSQL or libSQL migration definitions" - echo "==> Creating workflow labels..." create "skip-regression-check" "9E9E9E" "Acknowledged: fix without regression test" diff --git a/.github/workflows/pr-label-scope.yml b/.github/workflows/pr-label-scope.yml index b8a282472b..1c3885612e 100644 --- a/.github/workflows/pr-label-scope.yml +++ b/.github/workflows/pr-label-scope.yml @@ -6,20 +6,13 @@ on: permissions: contents: read - issues: write pull-requests: write jobs: scope: runs-on: ubuntu-latest steps: - - name: Ensure DB MIGRATION label exists - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - REPO: ${{ github.repository }} - run: gh label create "DB MIGRATION" --repo "$REPO" --color C62828 --description "PR adds or modifies PostgreSQL or libSQL migration definitions" --force - - - uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5 + - uses: actions/labeler@v5 with: configuration-path: .github/labeler.yml sync-labels: false # additive only — never remove scope labels diff --git a/channels-src/telegram/src/lib.rs b/channels-src/telegram/src/lib.rs index 5abeb7dde5..c19b4790b8 100644 --- a/channels-src/telegram/src/lib.rs +++ b/channels-src/telegram/src/lib.rs @@ -363,26 +363,6 @@ const TELEGRAM_STATUS_MAX_CHARS: usize = 600; /// Telegram's hard limit for message text length. const TELEGRAM_MAX_MESSAGE_LEN: usize = 4096; -fn utf16_code_unit_len(text: &str) -> usize { - text.encode_utf16().count() -} - -fn prefix_within_utf16_limit(text: &str, max_units: usize) -> usize { - let mut units = 0; - let mut end = 0; - - for (byte_idx, ch) in text.char_indices() { - let ch_units = ch.len_utf16(); - if units + ch_units > max_units { - break; - } - units += ch_units; - end = byte_idx + ch.len_utf8(); - } - - end -} - fn truncate_status_message(input: &str, max_chars: usize) -> String { let mut iter = input.chars(); let truncated: String = iter.by_ref().take(max_chars).collect(); @@ -393,7 +373,7 @@ fn truncate_status_message(input: &str, max_chars: usize) -> String { } } -/// Split a long message into chunks that fit within Telegram's 4096 UTF-16-unit limit. +/// Split a long message into chunks that fit within Telegram's 4096-char limit. /// /// Tries to split at the most natural boundary available (in priority order): /// 1. Double newline (paragraph break) @@ -402,7 +382,7 @@ fn truncate_status_message(input: &str, max_chars: usize) -> String { /// 4. Word boundary (space) /// 5. Hard cut at the limit (last resort for pathological input) fn split_message(text: &str) -> Vec { - if utf16_code_unit_len(text) <= TELEGRAM_MAX_MESSAGE_LEN { + if text.chars().count() <= TELEGRAM_MAX_MESSAGE_LEN { return vec![text.to_string()]; } @@ -410,8 +390,13 @@ fn split_message(text: &str) -> Vec { let mut remaining = text; while !remaining.is_empty() { - // Find the longest UTF-8 prefix that fits within Telegram's UTF-16 limit. - let window_bytes = prefix_within_utf16_limit(remaining, TELEGRAM_MAX_MESSAGE_LEN); + // Count chars to find the byte offset for our window. + let window_bytes = remaining + .char_indices() + .take(TELEGRAM_MAX_MESSAGE_LEN) + .last() + .map(|(byte_idx, ch)| byte_idx + ch.len_utf8()) + .unwrap_or(remaining.len()); if window_bytes >= remaining.len() { // Remainder fits entirely. @@ -419,24 +404,10 @@ fn split_message(text: &str) -> Vec { break; } - if window_bytes == 0 { - // Defensive fallback: make progress even if a future caller uses a - // smaller limit than a single scalar value can fit within. - let first_char_len = remaining - .chars() - .next() - .map(|ch| ch.len_utf8()) - .unwrap_or(remaining.len()); - chunks.push(remaining[..first_char_len].to_string()); - remaining = &remaining[first_char_len..]; - continue; - } - let window = &remaining[..window_bytes]; // 1. Double newline — best paragraph boundary - let split_at = window - .rfind("\n\n") + let split_at = window.rfind("\n\n") // 2. Single newline .or_else(|| window.rfind('\n')) // 3. Sentence-ending punctuation followed by space. @@ -446,9 +417,9 @@ fn split_message(text: &str) -> Vec { .or_else(|| { let bytes = window.as_bytes(); // Search backwards for '. ', '! ', '? ' - (1..bytes.len()) - .rev() - .find(|&i| matches!(bytes[i - 1], b'.' | b'!' | b'?') && bytes[i] == b' ') + (1..bytes.len()).rev().find(|&i| { + matches!(bytes[i - 1], b'.' | b'!' | b'?') && bytes[i] == b' ' + }) }) // 4. Word boundary (last space) .or_else(|| window.rfind(' ')) @@ -456,11 +427,7 @@ fn split_message(text: &str) -> Vec { .unwrap_or(window_bytes); // Avoid empty chunks (e.g. text starting with \n\n). - let split_at = if split_at == 0 { - window_bytes - } else { - split_at - }; + let split_at = if split_at == 0 { window_bytes } else { split_at }; // Trim whitespace at chunk boundaries for clean Telegram display. // Note: this drops leading/trailing spaces at split points, which is @@ -1391,13 +1358,7 @@ fn send_response( for (i, chunk) in chunks.into_iter().enumerate() { // Try Markdown, fall back to plain text on parse errors - let result = send_message( - chat_id, - &chunk, - reply_to, - Some("Markdown"), - message_thread_id, - ); + let result = send_message(chat_id, &chunk, reply_to, Some("Markdown"), message_thread_id); let msg_id = match result { Ok(id) => { @@ -2260,10 +2221,6 @@ export!(TelegramChannel); mod tests { use super::*; - fn utf16_len(text: &str) -> usize { - text.encode_utf16().count() - } - #[test] fn test_split_message_short() { let text = "Hello, world!"; @@ -2291,7 +2248,7 @@ mod tests { let chunks = split_message(&text); assert!(chunks.len() > 1, "expected multiple chunks"); for chunk in &chunks { - assert!(utf16_len(chunk) <= TELEGRAM_MAX_MESSAGE_LEN); + assert!(chunk.chars().count() <= TELEGRAM_MAX_MESSAGE_LEN); } // Rejoined chunks must equal the original text exactly. let rejoined = chunks.join(" "); @@ -2307,7 +2264,7 @@ mod tests { assert!(text.len() > TELEGRAM_MAX_MESSAGE_LEN); let chunks = split_message(&text); for chunk in &chunks { - assert!(utf16_len(chunk) <= TELEGRAM_MAX_MESSAGE_LEN); + assert!(chunk.chars().count() <= TELEGRAM_MAX_MESSAGE_LEN); } } @@ -2337,7 +2294,7 @@ mod tests { let chunks = split_message(&text); assert!(chunks.len() >= 2); for chunk in &chunks { - assert!(utf16_len(chunk) <= TELEGRAM_MAX_MESSAGE_LEN); + assert!(chunk.chars().count() <= TELEGRAM_MAX_MESSAGE_LEN); } // Rejoined must preserve all characters let rejoined: String = chunks.concat(); @@ -2354,25 +2311,12 @@ mod tests { let chunks = split_message(&text); assert!(chunks.len() >= 2); for chunk in &chunks { - assert!(utf16_len(chunk) <= TELEGRAM_MAX_MESSAGE_LEN); + assert!(chunk.chars().count() <= TELEGRAM_MAX_MESSAGE_LEN); // Every char should be a complete emoji assert!(chunk.chars().all(|c| c == '\u{1F600}')); } } - #[test] - fn test_split_message_exact_utf16_limit_for_surrogate_pairs() { - let emoji = "\u{1F600}"; // 😀 - let text = emoji.repeat(TELEGRAM_MAX_MESSAGE_LEN); - - let chunks = split_message(&text); - - assert_eq!(chunks.len(), 2); - assert!(chunks - .iter() - .all(|chunk| utf16_len(chunk) <= TELEGRAM_MAX_MESSAGE_LEN)); - } - #[test] fn test_clean_message_text() { // Without bot_username: strips any leading @mention From fda376768eca2503be0b14e0cf2f32ed4d84d074 Mon Sep 17 00:00:00 2001 From: "ironclaw-ci[bot]" <266877842+ironclaw-ci[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 17:32:43 -0700 Subject: [PATCH 5/7] chore: release (#2075) Co-authored-by: ironclaw-ci[bot] <266877842+ironclaw-ci[bot]@users.noreply.github.com> --- CHANGELOG.md | 123 ++++++++++++++++++++++++++++ Cargo.lock | 6 +- Cargo.toml | 6 +- crates/ironclaw_common/CHANGELOG.md | 24 ++++++ crates/ironclaw_common/Cargo.toml | 2 +- crates/ironclaw_engine/Cargo.toml | 2 +- crates/ironclaw_safety/CHANGELOG.md | 24 ++++++ crates/ironclaw_safety/Cargo.toml | 2 +- 8 files changed, 180 insertions(+), 9 deletions(-) create mode 100644 crates/ironclaw_common/CHANGELOG.md create mode 100644 crates/ironclaw_safety/CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md index bbff30ee16..589ee6d9bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,129 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.25.0](https://github.com/nearai/ironclaw/compare/ironclaw-v0.24.0...ironclaw-v0.25.0) - 2026-04-11 + +### Added + +- *(tools)* production-grade coding tools, file history, and skills ([#2025](https://github.com/nearai/ironclaw/pull/2025)) +- add extensible deployment profiles (IRONCLAW_PROFILE) ([#2203](https://github.com/nearai/ironclaw/pull/2203)) +- *(skills)* commitments system — active intake for personal AI assistant ([#1736](https://github.com/nearai/ironclaw/pull/1736)) +- add native Composio tool for third-party app integrations ([#920](https://github.com/nearai/ironclaw/pull/920)) +- *(gateway)* extract gateway frontend into ironclaw_gateway crate with widget system ([#1725](https://github.com/nearai/ironclaw/pull/1725)) +- *(railway)* build staging target with pre-bundled WASM extensions ([#2219](https://github.com/nearai/ironclaw/pull/2219)) +- *(docker)* pre-bundle WASM extensions in staging image ([#2210](https://github.com/nearai/ironclaw/pull/2210)) +- *(tui)* ship TUI in default binary ([#2195](https://github.com/nearai/ironclaw/pull/2195)) +- *(admin)* admin tool policy to disable tools for users ([#2154](https://github.com/nearai/ironclaw/pull/2154)) +- *(web)* add scroll-to-bottom arrow in gateway chat ([#2202](https://github.com/nearai/ironclaw/pull/2202)) +- unified tool dispatch + schema-validated workspace ([#2049](https://github.com/nearai/ironclaw/pull/2049)) +- *(workspace)* admin system prompt shared with all users ([#2109](https://github.com/nearai/ironclaw/pull/2109)) +- *(engine)* restage skill repair learning loop on staging ([#1962](https://github.com/nearai/ironclaw/pull/1962)) +- *(tui)* port full-featured Ratatui terminal UI onto staging ([#1973](https://github.com/nearai/ironclaw/pull/1973)) +- *(slack)* implement on_broadcast and fix message tool hints ([#2113](https://github.com/nearai/ironclaw/pull/2113)) +- *(i18n)* add Korean translation, fix zh-CN drift, and prevent future drift via pre-commit hook ([#2065](https://github.com/nearai/ironclaw/pull/2065)) +- NEAR AI MCP server ([#2009](https://github.com/nearai/ironclaw/pull/2009)) +- *(test)* dual-mode live/replay test harness with LLM judge ([#2039](https://github.com/nearai/ironclaw/pull/2039)) +- add AWS Bedrock embeddings provider ([#1568](https://github.com/nearai/ironclaw/pull/1568)) +- *(ownership)* centralized ownership model with typed identities, DB-backed pairing, and OwnershipCache ([#1898](https://github.com/nearai/ironclaw/pull/1898)) +- *(tools)* persistent per-user tool permission system ([#1911](https://github.com/nearai/ironclaw/pull/1911)) +- *(engine)* Unified Thread-Capability-CodeAct execution engine (v2 architecture) ([#1557](https://github.com/nearai/ironclaw/pull/1557)) +- *(auth)* direct OAuth/social login with Google, GitHub, Apple, and NEAR wallet ([#1798](https://github.com/nearai/ironclaw/pull/1798)) +- Add ACP (Agent Client Protocol) job mode for delegating to any compatible coding agent ([#1600](https://github.com/nearai/ironclaw/pull/1600)) +- *(workspace)* metadata-driven indexing/hygiene, document versioning, and patch ([#1723](https://github.com/nearai/ironclaw/pull/1723)) +- *(jobs)* per-job MCP server filtering and max_iterations cap ([#1243](https://github.com/nearai/ironclaw/pull/1243)) +- *(config)* unify all settings to DB > env > default priority ([#1722](https://github.com/nearai/ironclaw/pull/1722)) +- *(telegram)* add sendVoice support for audio/ogg attachments ([#1314](https://github.com/nearai/ironclaw/pull/1314)) +- *(setup)* build ironclaw-worker Docker image in setup wizard ([#1757](https://github.com/nearai/ironclaw/pull/1757)) + +### Fixed + +- *(ci)* bump 5 channel versions + fix lifetime desync in panics check ([#2300](https://github.com/nearai/ironclaw/pull/2300)) +- *(test)* case-insensitive hint matching in TraceLlm step_matches ([#2292](https://github.com/nearai/ironclaw/pull/2292)) +- *(v2)* tool naming, auth gates, schema flatten, WASM traps, workspace race ([#2209](https://github.com/nearai/ironclaw/pull/2209)) +- *(ci)* resolve 4 staging test failures ([#2273](https://github.com/nearai/ironclaw/pull/2273)) +- *(docker)* copy profiles/ into build stages ([#2289](https://github.com/nearai/ironclaw/pull/2289)) +- *(engine)* mission cron scheduling + timezone propagation ([#1944](https://github.com/nearai/ironclaw/pull/1944)) ([#1957](https://github.com/nearai/ironclaw/pull/1957)) +- *(oauth)* use localhost for redirect URI when bound to 0.0.0.0 ([#2247](https://github.com/nearai/ironclaw/pull/2247)) +- *(bridge)* sanitize auth_url on engine v2 path ([#2206](https://github.com/nearai/ironclaw/pull/2206)) ([#2215](https://github.com/nearai/ironclaw/pull/2215)) +- *(docs)* explain in more details `activation` block & installation steps for skills ([#2216](https://github.com/nearai/ironclaw/pull/2216)) +- *(docker)* consume CACHE_BUST arg so BuildKit invalidates cache +- *(gateway)* suppress duplicate text response during auth flow and unify extension config modal ([#2172](https://github.com/nearai/ironclaw/pull/2172)) +- *(agent)* stop intercepting bare yes/no/always as approval when nothing pending ([#2178](https://github.com/nearai/ironclaw/pull/2178)) +- *(ci)* resolve 3 staging test failures ([#2207](https://github.com/nearai/ironclaw/pull/2207)) +- *(wasm)* upgrade Wasmtime to 43.0.1 and restore CI ([#2224](https://github.com/nearai/ironclaw/pull/2224)) +- fix(auth) first-pass Gmail OAuth auth prompt in chat ([#2038](https://github.com/nearai/ironclaw/pull/2038)) +- *(db)* repair V6 migration checksum and guard against re-modification ([#1328](https://github.com/nearai/ironclaw/pull/1328)) ([#2101](https://github.com/nearai/ironclaw/pull/2101)) +- *(ci)* target wasm32-wasip2 in WASM build script ([#2175](https://github.com/nearai/ironclaw/pull/2175)) +- *(test)* use canonical extension name in setup submit test ([#2158](https://github.com/nearai/ironclaw/pull/2158)) +- fix (skills) installs for invalid catalog names ([#2040](https://github.com/nearai/ironclaw/pull/2040)) +- universal engine-version tool visibility filtering ([#2132](https://github.com/nearai/ironclaw/pull/2132)) +- *(ownership)* remove silent cross-tenant credential fallback ([#2099](https://github.com/nearai/ironclaw/pull/2099)) +- *(e2e)* canonicalize extension names + fix remaining test failures ([#2129](https://github.com/nearai/ironclaw/pull/2129)) +- *(ownership)* unify ownership checks via Owned trait and fix mission visibility bug ([#2126](https://github.com/nearai/ironclaw/pull/2126)) +- *(web)* intercept approval text input in chat ([#2124](https://github.com/nearai/ironclaw/pull/2124)) +- *(staging)* repair 4 categories of CI test failures ([#2091](https://github.com/nearai/ironclaw/pull/2091)) +- *(web)* emit Done after response — SSE ordering fix ([#2079](https://github.com/nearai/ironclaw/pull/2079)) ([#2104](https://github.com/nearai/ironclaw/pull/2104)) +- *(tools)* gate claude_code and acp modes behind enabled flags ([#2003](https://github.com/nearai/ironclaw/pull/2003)) +- *(acp)* propagate follow-up prompt failures as job errors ([#1981](https://github.com/nearai/ironclaw/pull/1981)) +- color for tools use ([#2096](https://github.com/nearai/ironclaw/pull/2096)) +- *(registry)* use canonical underscore names in manifests to fix WASM install ([#2029](https://github.com/nearai/ironclaw/pull/2029)) +- *(safety)* add credential patterns and sensitive path blocklist ([#1675](https://github.com/nearai/ironclaw/pull/1675)) +- *(channels)* allow telegram wasm channel name ([#2051](https://github.com/nearai/ironclaw/pull/2051)) +- *(staging)* repair broken test build and macOS-incompatible SSRF tests ([#2064](https://github.com/nearai/ironclaw/pull/2064)) +- honor auto-approve tools in engine v2 ([#2013](https://github.com/nearai/ironclaw/pull/2013)) +- *(bridge)* sanitize orphaned tool results in v2 adapter ([#1975](https://github.com/nearai/ironclaw/pull/1975)) +- *(docker)* ensure ironclaw runtime home exists ([#1918](https://github.com/nearai/ironclaw/pull/1918)) +- *(agent)* prevent self-repair notification spam for stuck jobs ([#1867](https://github.com/nearai/ironclaw/pull/1867)) +- *(self-repair)* skip built-in tools in broken tool detection and repair ([#1991](https://github.com/nearai/ironclaw/pull/1991)) +- unblock bootstrap ownership on dynamic_tools ([#2005](https://github.com/nearai/ironclaw/pull/2005)) +- *(llm)* invert reasoning default — unknown models skip think/final tags ([#1952](https://github.com/nearai/ironclaw/pull/1952)) +- *(llm)* add sanitize_tool_messages to OpenAiCodexProvider ([#1971](https://github.com/nearai/ironclaw/pull/1971)) +- update CLI help snapshots for --auto-approve and acp command ([#1966](https://github.com/nearai/ironclaw/pull/1966)) +- *(docker)* switch to glibc to fix libSQL segfault on DB reopen ([#1930](https://github.com/nearai/ironclaw/pull/1930)) +- *(db)* swap V16/V17 to match production PG (document_versions before user_identities) ([#1931](https://github.com/nearai/ironclaw/pull/1931)) +- *(db)* keep V15=conversation_source_channel to match production PG ([#1928](https://github.com/nearai/ironclaw/pull/1928)) +- *(db)* resolve V15 migration numbering conflict ([#1923](https://github.com/nearai/ironclaw/pull/1923)) +- *(routines)* add bounded retry for transient lightweight failures ([#1471](https://github.com/nearai/ironclaw/pull/1471)) +- *(relay)* thread responses under original message in Slack channels ([#1848](https://github.com/nearai/ironclaw/pull/1848)) +- *(worker)* Improve command execution parameter validation ([#1692](https://github.com/nearai/ironclaw/pull/1692)) +- *(telegram)* auto-generate webhook secret during setup ([#1536](https://github.com/nearai/ironclaw/pull/1536)) +- *(builder)* accept inline-table and object-map dependency formats from LLM ([#1748](https://github.com/nearai/ironclaw/pull/1748)) +- *(gemini)* preserve and echo thoughtSignature for Gemini 3.x function calls ([#1752](https://github.com/nearai/ironclaw/pull/1752)) +- *(relay)* route async Slack messages to correct channel instead of DMs ([#1845](https://github.com/nearai/ironclaw/pull/1845)) +- *(security)* block cross-channel approval thread hijacking ([#1590](https://github.com/nearai/ironclaw/pull/1590)) +- *(builder)* add approval context propagation for sub-tool execution ([#1125](https://github.com/nearai/ironclaw/pull/1125)) + +### Other + +- trigger ironclaw-dind image build ([#2190](https://github.com/nearai/ironclaw/pull/2190)) +- add amazon tutorial ([#2261](https://github.com/nearai/ironclaw/pull/2261)) +- Create QA Bug Report issue template ([#2228](https://github.com/nearai/ironclaw/pull/2228)) +- [codex] Stabilize auth readiness and gate flows ([#2050](https://github.com/nearai/ironclaw/pull/2050)) +- Add mintlify docs ([#2189](https://github.com/nearai/ironclaw/pull/2189)) +- [codex] allow private local llm endpoints ([#1955](https://github.com/nearai/ironclaw/pull/1955)) +- *(ci)* add Dependabot and pin GitHub Actions by SHA ([#2043](https://github.com/nearai/ironclaw/pull/2043)) +- Fix routine Telegram notification summaries ([#2033](https://github.com/nearai/ironclaw/pull/2033)) +- *(channels)* add Slack E2E tests, integration tests, and smoke runner ([#2042](https://github.com/nearai/ironclaw/pull/2042)) +- *(engine)* rename ENGINE_V2_TRACE to IRONCLAW_RECORD_TRACE ([#2114](https://github.com/nearai/ironclaw/pull/2114)) +- fix multi-tenant inference latency (per-conversation locking + workspace indexing) ([#2127](https://github.com/nearai/ironclaw/pull/2127)) +- Improve channel onboarding and Telegram pairing flow ([#2103](https://github.com/nearai/ironclaw/pull/2103)) +- *(e2e)* expand SSE resilience coverage ([#1897](https://github.com/nearai/ironclaw/pull/1897)) +- add Telegram E2E tests and Rust integration tests ([#2037](https://github.com/nearai/ironclaw/pull/2037)) +- (fix) WASM channel HTTP SSRF protections ([#1976](https://github.com/nearai/ironclaw/pull/1976)) +- Ignore default model override and empty WASM polls ([#1914](https://github.com/nearai/ironclaw/pull/1914)) +- *(workspace)* add direct regression tests for scoped_to_user rebinding ([#1652](https://github.com/nearai/ironclaw/pull/1652)) ([#1875](https://github.com/nearai/ironclaw/pull/1875)) +- Fix turn cost footer and per-turn usage accounting ([#1951](https://github.com/nearai/ironclaw/pull/1951)) +- Publish ironclaw-worker image from Dockerfile.worker ([#1979](https://github.com/nearai/ironclaw/pull/1979)) +- [codex] Move safety benches into ironclaw_safety crate ([#1954](https://github.com/nearai/ironclaw/pull/1954)) +- Fix bootstrap paths and webhook defaults +- Only tag :latest/:version on release, allow :staging via manual dispatch [skip-regression-check] ([#1925](https://github.com/nearai/ironclaw/pull/1925)) +- Add Docker Hub workflow and optimize Dockerfile for size ([#1886](https://github.com/nearai/ironclaw/pull/1886)) +- *(e2e)* add agent loop recovery coverage ([#1854](https://github.com/nearai/ironclaw/pull/1854)) +- disable cooldown in gateway webhook workflow test ([#1889](https://github.com/nearai/ironclaw/pull/1889)) +- Expand GitHub WASM tool surface ([#1884](https://github.com/nearai/ironclaw/pull/1884)) +- *(e2e)* cover chat approval parity across channels ([#1858](https://github.com/nearai/ironclaw/pull/1858)) +- add routine coverage for issue 1781 ([#1856](https://github.com/nearai/ironclaw/pull/1856)) + ## [0.24.0](https://github.com/nearai/ironclaw/compare/ironclaw-v0.23.0...ironclaw-v0.24.0) - 2026-03-31 ### Added diff --git a/Cargo.lock b/Cargo.lock index dabcba57f8..448ae23b2c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3866,7 +3866,7 @@ dependencies = [ [[package]] name = "ironclaw" -version = "0.24.0" +version = "0.25.0" dependencies = [ "aes-gcm", "agent-client-protocol", @@ -3976,7 +3976,7 @@ dependencies = [ [[package]] name = "ironclaw_common" -version = "0.1.0" +version = "0.2.0" dependencies = [ "chrono-tz", "serde", @@ -4017,7 +4017,7 @@ dependencies = [ [[package]] name = "ironclaw_safety" -version = "0.2.0" +version = "0.2.1" dependencies = [ "aho-corasick", "criterion", diff --git a/Cargo.toml b/Cargo.toml index 4130032581..444473d7c6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ exclude = [ [package] name = "ironclaw" -version = "0.24.0" +version = "0.25.0" edition = "2024" rust-version = "1.92" description = "Secure personal AI assistant that protects your data and expands its capabilities on the fly" @@ -113,12 +113,12 @@ cron = "0.13" jsonschema = { version = "0.45", default-features = false } # Shared types -ironclaw_common = { path = "crates/ironclaw_common", version = "0.1.0" } +ironclaw_common = { path = "crates/ironclaw_common", version = "0.2.0" } # Safety/sanitization ironclaw_engine = { path = "crates/ironclaw_engine", version = "0.1.0" } ironclaw_gateway = { path = "crates/ironclaw_gateway", version = "0.1.0" } -ironclaw_safety = { path = "crates/ironclaw_safety", version = "0.2.0" } +ironclaw_safety = { path = "crates/ironclaw_safety", version = "0.2.1" } ironclaw_skills = { path = "crates/ironclaw_skills", version = "0.1.0" } ironclaw_tui = { path = "crates/ironclaw_tui", version = "0.1.0", optional = true } regex = "1" diff --git a/crates/ironclaw_common/CHANGELOG.md b/crates/ironclaw_common/CHANGELOG.md new file mode 100644 index 0000000000..370d584502 --- /dev/null +++ b/crates/ironclaw_common/CHANGELOG.md @@ -0,0 +1,24 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [0.2.0](https://github.com/nearai/ironclaw/compare/ironclaw_common-v0.1.0...ironclaw_common-v0.2.0) - 2026-04-11 + +### Added + +- *(tui)* port full-featured Ratatui terminal UI onto staging ([#1973](https://github.com/nearai/ironclaw/pull/1973)) +- *(engine)* Unified Thread-Capability-CodeAct execution engine (v2 architecture) ([#1557](https://github.com/nearai/ironclaw/pull/1557)) +- *(jobs)* per-job MCP server filtering and max_iterations cap ([#1243](https://github.com/nearai/ironclaw/pull/1243)) + +### Fixed + +- *(engine)* mission cron scheduling + timezone propagation ([#1944](https://github.com/nearai/ironclaw/pull/1944)) ([#1957](https://github.com/nearai/ironclaw/pull/1957)) + +### Other + +- Improve channel onboarding and Telegram pairing flow ([#2103](https://github.com/nearai/ironclaw/pull/2103)) diff --git a/crates/ironclaw_common/Cargo.toml b/crates/ironclaw_common/Cargo.toml index 2308ff9c41..641fdffbcc 100644 --- a/crates/ironclaw_common/Cargo.toml +++ b/crates/ironclaw_common/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ironclaw_common" -version = "0.1.0" +version = "0.2.0" edition = "2024" rust-version = "1.92" description = "Shared types and utilities for the IronClaw workspace" diff --git a/crates/ironclaw_engine/Cargo.toml b/crates/ironclaw_engine/Cargo.toml index 726b59a3a1..93b6eff66c 100644 --- a/crates/ironclaw_engine/Cargo.toml +++ b/crates/ironclaw_engine/Cargo.toml @@ -16,7 +16,7 @@ dist = false [dependencies] async-trait = "0.1" cron = "0.13" -ironclaw_common = { path = "../ironclaw_common", version = "0.1.0" } +ironclaw_common = { path = "../ironclaw_common", version = "0.2.0" } ironclaw_skills = { path = "../ironclaw_skills", version = "0.1.0", default-features = false } chrono = { version = "0.4", features = ["serde"] } monty = { git = "https://github.com/pydantic/monty.git", rev = "7a0d4b75b72e6ddacafaf36e26486186cdb6eb68" } diff --git a/crates/ironclaw_safety/CHANGELOG.md b/crates/ironclaw_safety/CHANGELOG.md new file mode 100644 index 0000000000..19b761f866 --- /dev/null +++ b/crates/ironclaw_safety/CHANGELOG.md @@ -0,0 +1,24 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [0.2.1](https://github.com/nearai/ironclaw/compare/ironclaw_safety-v0.2.0...ironclaw_safety-v0.2.1) - 2026-04-11 + +### Added + +- *(engine)* Unified Thread-Capability-CodeAct execution engine (v2 architecture) ([#1557](https://github.com/nearai/ironclaw/pull/1557)) + +### Fixed + +- *(safety)* add credential patterns and sensitive path blocklist ([#1675](https://github.com/nearai/ironclaw/pull/1675)) +- *(security)* safety layer bypass via output truncation [HIGH] ([#1851](https://github.com/nearai/ironclaw/pull/1851)) + +### Other + +- *(e2e)* expand SSE resilience coverage ([#1897](https://github.com/nearai/ironclaw/pull/1897)) +- [codex] Move safety benches into ironclaw_safety crate ([#1954](https://github.com/nearai/ironclaw/pull/1954)) diff --git a/crates/ironclaw_safety/Cargo.toml b/crates/ironclaw_safety/Cargo.toml index c275fb4d1b..3aaf66f7c7 100644 --- a/crates/ironclaw_safety/Cargo.toml +++ b/crates/ironclaw_safety/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ironclaw_safety" -version = "0.2.0" +version = "0.2.1" edition = "2024" rust-version = "1.92" description = "Prompt injection defense, input validation, secret leak detection, and safety policy enforcement" From be6de43f8ed8be57847161d3d30e0c4a71870575 Mon Sep 17 00:00:00 2001 From: Henry Park Date: Fri, 10 Apr 2026 17:59:51 -0700 Subject: [PATCH 6/7] =?UTF-8?q?fix(ci):=20unblock=20v0.25.0=20release=20?= =?UTF-8?q?=E2=80=94=20fix=20tag=20filter=20and=20publish=20config=20(#230?= =?UTF-8?q?6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The release pipeline broke when ironclaw_engine was added (Apr 2) with a monty git dependency that blocks crates.io publishing. Additionally, sub-crate tags (ironclaw_tui-v0.1.0) were triggering cargo-dist builds and stealing the "Latest" badge from the main release. - Narrow release.yml tag pattern to `ironclaw-v*` so only the main binary release tags trigger cargo-dist (not sub-crate tags) - Configure release-plz to skip crates.io publish for ironclaw (publish = false) while still creating git tags for cargo-dist - Mark ironclaw_engine, ironclaw_tui, ironclaw_gateway as non-publishable (release = false) in release-plz.toml - Add publish = false to tui and gateway Cargo.toml - Remove version fields from non-publishable path deps in root Cargo.toml Co-authored-by: Claude Opus 4.6 (1M context) --- .github/workflows/release.yml | 2 +- Cargo.toml | 6 +++--- crates/ironclaw_gateway/Cargo.toml | 1 + crates/ironclaw_tui/Cargo.toml | 1 + release-plz.toml | 26 ++++++++++++++++++++++++++ 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b237d28665..3085884d08 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -41,7 +41,7 @@ permissions: on: push: tags: - - '**[0-9]+.[0-9]+.[0-9]+*' + - 'ironclaw-v[0-9]+.[0-9]+.[0-9]+*' jobs: # Run 'dist plan' (or host) to determine what tasks we need to do diff --git a/Cargo.toml b/Cargo.toml index 444473d7c6..fdc0ef1e37 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -116,11 +116,11 @@ jsonschema = { version = "0.45", default-features = false } ironclaw_common = { path = "crates/ironclaw_common", version = "0.2.0" } # Safety/sanitization -ironclaw_engine = { path = "crates/ironclaw_engine", version = "0.1.0" } -ironclaw_gateway = { path = "crates/ironclaw_gateway", version = "0.1.0" } +ironclaw_engine = { path = "crates/ironclaw_engine" } +ironclaw_gateway = { path = "crates/ironclaw_gateway" } ironclaw_safety = { path = "crates/ironclaw_safety", version = "0.2.1" } ironclaw_skills = { path = "crates/ironclaw_skills", version = "0.1.0" } -ironclaw_tui = { path = "crates/ironclaw_tui", version = "0.1.0", optional = true } +ironclaw_tui = { path = "crates/ironclaw_tui", optional = true } regex = "1" aho-corasick = "1" diff --git a/crates/ironclaw_gateway/Cargo.toml b/crates/ironclaw_gateway/Cargo.toml index 0eaa87881e..04e55cadbe 100644 --- a/crates/ironclaw_gateway/Cargo.toml +++ b/crates/ironclaw_gateway/Cargo.toml @@ -5,6 +5,7 @@ edition = "2024" rust-version = "1.92" description = "Gateway frontend assets, layout configuration, and widget extension system for IronClaw" license = "MIT OR Apache-2.0" +publish = false [package.metadata.dist] dist = false diff --git a/crates/ironclaw_tui/Cargo.toml b/crates/ironclaw_tui/Cargo.toml index d81bffa221..df6289548b 100644 --- a/crates/ironclaw_tui/Cargo.toml +++ b/crates/ironclaw_tui/Cargo.toml @@ -8,6 +8,7 @@ authors = ["NEAR AI "] license = "MIT OR Apache-2.0" homepage = "https://github.com/nearai/ironclaw" repository = "https://github.com/nearai/ironclaw" +publish = false [features] default = ["clipboard"] diff --git a/release-plz.toml b/release-plz.toml index e8e0670fce..b140099382 100644 --- a/release-plz.toml +++ b/release-plz.toml @@ -1,2 +1,28 @@ [workspace] +# GitHub Releases are created by cargo-dist (release.yml), not release-plz. +# release-plz only creates git tags and publishes to crates.io. git_release_enable = false + +# ── Main binary ───────────────────────────────────────────── +# Cannot publish to crates.io because ironclaw_engine depends on `monty` +# (git-only, not on crates.io). Still create git tags so cargo-dist builds +# binaries and creates GitHub Releases. +[[package]] +name = "ironclaw" +publish = false + +# ── Internal crates (not useful standalone) ───────────────── +[[package]] +name = "ironclaw_engine" +publish = false +release = false + +[[package]] +name = "ironclaw_tui" +publish = false +release = false + +[[package]] +name = "ironclaw_gateway" +publish = false +release = false From 72829dbb014d653874f6470ccb066fa1d859fd07 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 18:49:57 -0700 Subject: [PATCH 7/7] chore: update WASM artifact SHA256 checksums [skip ci] (#2308) Co-authored-by: github-actions[bot] --- registry/channels/discord.json | 4 ++-- registry/channels/feishu.json | 4 ++-- registry/channels/slack.json | 4 ++-- registry/channels/telegram.json | 4 ++-- registry/channels/whatsapp.json | 4 ++-- registry/tools/composio.json | 7 ++++++- registry/tools/github.json | 4 ++-- 7 files changed, 18 insertions(+), 13 deletions(-) diff --git a/registry/channels/discord.json b/registry/channels/discord.json index 8b9c0d4340..4b011ea9e1 100644 --- a/registry/channels/discord.json +++ b/registry/channels/discord.json @@ -18,8 +18,8 @@ }, "artifacts": { "wasm32-wasip2": { - "url": "https://github.com/nearai/ironclaw/releases/download/ironclaw-v0.24.0/channel-discord-0.2.2-wasm32-wasip2.tar.gz", - "sha256": "b126e4af7a8079a7178b5ae03f1b44c8eab02fa209fb102346e3be661428aece" + "url": "https://github.com/nearai/ironclaw/releases/download/ironclaw-v0.25.0/channel-discord-0.2.3-wasm32-wasip2.tar.gz", + "sha256": "d4249629881f0107d0944ab78c7aeb5b3d161393db6ac828815719b14b80fc83" } }, "auth_summary": { diff --git a/registry/channels/feishu.json b/registry/channels/feishu.json index 65bed7baf0..10a85286c7 100644 --- a/registry/channels/feishu.json +++ b/registry/channels/feishu.json @@ -19,8 +19,8 @@ }, "artifacts": { "wasm32-wasip2": { - "sha256": "393d2d5d8766ace574e3a4978d47d5976548a3e862a80ba42a456f2f457e45cf", - "url": "https://github.com/nearai/ironclaw/releases/download/ironclaw-v0.24.0/channel-feishu-0.1.4-wasm32-wasip2.tar.gz" + "sha256": "e3ebd9a7942d8ab7b38a2219474b64b0f495e9e540c5df1d7b25e663ec8b30b7", + "url": "https://github.com/nearai/ironclaw/releases/download/ironclaw-v0.25.0/channel-feishu-0.2.0-wasm32-wasip2.tar.gz" } }, "auth_summary": { diff --git a/registry/channels/slack.json b/registry/channels/slack.json index c08343938a..07dd48ea12 100644 --- a/registry/channels/slack.json +++ b/registry/channels/slack.json @@ -18,8 +18,8 @@ }, "artifacts": { "wasm32-wasip2": { - "url": "https://github.com/nearai/ironclaw/releases/download/ironclaw-v0.24.0/channel-slack-0.2.2-wasm32-wasip2.tar.gz", - "sha256": "38a06480456fe15e5003792c2309d56f38b544f8ea7c90ab7baf451438a082de" + "url": "https://github.com/nearai/ironclaw/releases/download/ironclaw-v0.25.0/channel-slack-0.3.0-wasm32-wasip2.tar.gz", + "sha256": "b700d4ab29fe69ac8a86f709d8f735b7ac6db3c7e9d94e63e33a4a69899192e7" } }, "auth_summary": { diff --git a/registry/channels/telegram.json b/registry/channels/telegram.json index 87291884ba..07868756cb 100644 --- a/registry/channels/telegram.json +++ b/registry/channels/telegram.json @@ -18,8 +18,8 @@ }, "artifacts": { "wasm32-wasip2": { - "url": "https://github.com/nearai/ironclaw/releases/download/v0.20.0/channel-telegram-0.2.5-wasm32-wasip2.tar.gz", - "sha256": "1ef20a538f55b379e049356e4d6758006251846bc3365ceaa1c87eba8379a329" + "url": "https://github.com/nearai/ironclaw/releases/download/ironclaw-v0.25.0/channel-telegram-0.2.8-wasm32-wasip2.tar.gz", + "sha256": "0fe74589b0367d085efdab395d95ec34ac274d46f498cecc1d62f313caf9cc96" } }, "auth_summary": { diff --git a/registry/channels/whatsapp.json b/registry/channels/whatsapp.json index 0e18151be5..de9348f8e1 100644 --- a/registry/channels/whatsapp.json +++ b/registry/channels/whatsapp.json @@ -18,8 +18,8 @@ }, "artifacts": { "wasm32-wasip2": { - "url": "https://github.com/nearai/ironclaw/releases/download/v0.18.0/whatsapp-0.2.0-wasm32-wasip2.tar.gz", - "sha256": "feb9194719d9bed796b070ab4dc30348dbfb5d3dec56f9f21e02d14137abab01" + "url": "https://github.com/nearai/ironclaw/releases/download/ironclaw-v0.25.0/channel-whatsapp-0.2.2-wasm32-wasip2.tar.gz", + "sha256": "88c539f28dc0ebd06acf359614cc63fb0f3508241be4c70fe0f46cbc9bfcd73a" } }, "auth_summary": { diff --git a/registry/tools/composio.json b/registry/tools/composio.json index 4db3680b92..e3166db3c4 100644 --- a/registry/tools/composio.json +++ b/registry/tools/composio.json @@ -17,7 +17,12 @@ "capabilities": "composio-tool.capabilities.json", "crate_name": "composio-tool" }, - "artifacts": {}, + "artifacts": { + "wasm32-wasip2": { + "sha256": "f8de24313bdb9ff1d70796267feb7ea33c876e52167b040f9831900e90936688", + "url": "https://github.com/nearai/ironclaw/releases/download/ironclaw-v0.25.0/tool-composio-0.1.0-wasm32-wasip2.tar.gz" + } + }, "auth_summary": { "method": "manual", "provider": "Composio", diff --git a/registry/tools/github.json b/registry/tools/github.json index c6805374ea..3c5d9ce144 100644 --- a/registry/tools/github.json +++ b/registry/tools/github.json @@ -21,8 +21,8 @@ }, "artifacts": { "wasm32-wasip2": { - "url": "https://github.com/nearai/ironclaw/releases/download/ironclaw-v0.22.0/tool-github-0.2.2-wasm32-wasip2.tar.gz", - "sha256": "70b55af593193d8fa495c0f702ea23284d83a624124f8a5f7564916ec5032c3f" + "url": "https://github.com/nearai/ironclaw/releases/download/ironclaw-v0.25.0/tool-github-0.2.3-wasm32-wasip2.tar.gz", + "sha256": "f0b1daab4a9f978d1638e7d83569db02b1733b3916cddfc5be0993b16c49927c" } }, "auth_summary": {