Skip to content

Make BAML agent skill installs reproducible - #3753

Merged
rossirpaulo merged 2 commits into
canaryfrom
paulo/harden-baml-agent-install
Jun 12, 2026
Merged

rossirpaulo merged 2 commits into
canaryfrom
paulo/harden-baml-agent-install

Conversation

@rossirpaulo

@rossirpaulo rossirpaulo commented Jun 12, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Make baml agent install reproducible by default by installing agent skills from the matching BAML language release asset instead of the mutable BoundaryML/baml-skill main branch.

Changes

  • Add --latest and --from install escape hatches for mutable upstream, archive URLs, local archives, and local directories.
  • Discover all skills/baml-*/SKILL.md entries from release archives, with legacy plugins/baml/skills/*/SKILL.md normalization.
  • Verify default release archives with the .sha256 sidecar before installing.
  • Add scripts/package-agent-skills to build normalized release artifacts and checksums.
  • Add a release workflow job for packaging agent skills and uploading them with the language release assets.

Validation

  • cargo test -p baml_cli agent_command -- --nocapture
  • cargo build -p baml_cli --bin baml-cli
  • shellcheck scripts/package-agent-skills
  • actionlint .github/workflows/release-baml-language.yml
  • Runtime smoke against current BoundaryML/baml-skill main using scripts/package-agent-skills and baml-cli agent install --from

Summary by CodeRabbit

  • New Features

    • Agent install now accepts --latest or --from to install skills from the main branch, a URL, a local directory, or a local .tar.gz archive (with checksum verification). Legacy skill layouts and references are auto-detected and normalized; duplicate skills are deduplicated.
  • Chores

    • Agent skills are packaged as versioned distributable tarballs and published alongside other release assets. Release workflow updated to publish these artifacts and adjust downstream publishing gates.
  • Tests

    • Install/parsing behavior and archive handling covered by new/updated tests.

@vercel

vercel Bot commented Jun 12, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
beps Ready Ready Preview, Comment Jun 12, 2026 9:32am
promptfiddle Ready Ready Preview, Comment Jun 12, 2026 9:32am
promptfiddle2 Ready Ready Preview, Comment Jun 12, 2026 9:32am

Request Review

@coderabbitai

coderabbitai Bot commented Jun 12, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a deterministic agent-skills packager and integrates it into CI releases; refactors the CLI to load skills from multiple sources and normalize legacy layouts; updates tests; and updates the release workflow to build and publish agent-skills artifacts with updated job dependencies.

Changes

Agent Skills Packaging and Release

Layer / File(s) Summary
Agent Skills Packaging Script
scripts/package-agent-skills
New Bash script validates inputs, discovers skills from direct (source/skills/*/baml-*/SKILL.md) and legacy plugin (source/plugins/baml/skills/*/SKILL.md) layouts, stages each skill with normalized frontmatter, rejects duplicates by canonical name, and creates deterministic baml-agent-skills-$version.tar.gz archives with SHA-256 checksums.
Agent CLI: load_skills entry & types
baml_language/crates/baml_cli/src/agent_command.rs
Adds --latest and --from args and new Skill/RawSkill/SkillArchivePath types. Implements source selection (latest HTTP, --from HTTP/local/tarball, or env-versioned release URL) and helpers for URL/version composition and fetching.
Agent CLI: archive parsing & normalization
baml_language/crates/baml_cli/src/agent_command.rs
Parses archive/directory entries by path (direct vs legacy), accumulates raw entries, normalizes legacy frontmatter names, rewrites internal references (baml:<legacy>/baml:* → canonical baml-..., supports baml-* wildcards), deduplicates by canonical name, and constructs final Skill records.
Agent CLI: install I/O and messaging
baml_language/crates/baml_cli/src/agent_command.rs
Uses borrowed &skill.name for temp staging and atomic directory replacement, updates final path computations, and removes "latest" wording from success output.
Agent CLI Tests & Helpers
baml_language/crates/baml_cli/src/agent_command.rs (tests)
Expands tests and helpers for direct and legacy layouts, reference rewrites, CRLF frontmatter acceptance, frontmatter mismatch errors, and a unit test for versioned_skill_archive_url_with_env.
Release Workflow: Build Agent Skills
.github/workflows/release-baml-language.yml
Adds BAML_AGENT_SKILLS_REPOSITORY env var and a build-agent-skills job that checks out agent-skills, packages them into dist/agent-skills/*.tar.gz, and uploads an agent-skills artifact; adds job to all-builds gate.
Release Workflow: Toolchain & Wrapper Publishing
.github/workflows/release-baml-language.yml
Adds publish-toolchain-release to publish toolchain assets plus dist/agent-skills/* to the GitHub release and expands publish-wrapper-release behavior; updates artifact download/upload steps accordingly.
Release Workflow: Dependency Graph Updates
.github/workflows/release-baml-language.yml
Changes publish-pkg-boundaryml-com gating to depend on publish-toolchain-release (and, when wrapper_changed, also wrapper/homebrew/aur successes); updates publish-homebrew & publish-aur to depend on publish-wrapper-release.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • BoundaryML/baml#3689: Initial baml-cli agent install implementation that this PR refactors to support multiple sources and revised parsing.
  • BoundaryML/baml#3694: Related release workflow changes to publish and gate downstream jobs around new publish jobs.

Poem

🐰 I packed the skills in tidy tar,
Rewrote names to travel far.
CLI now fetches, local or URL,
Legacy refs made canonical.
The workflow ships each careful part—hopping off to start!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.08% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately summarizes the main objective: making BAML agent skill installs reproducible by changing the default installation source from mutable upstream to immutable release assets.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch paulo/harden-baml-agent-install

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions

github-actions Bot commented Jun 12, 2026 •

Copy link
Copy Markdown

⏭️ Performance benchmarks were skipped

Perf benchmarks (CodSpeed) are opt-in on pull requests — they no longer run on every push. They always run automatically after merge to canary/main.

To run them on this PR, do any of the following, then push a commit (or re-run CI):

  • Add RUN_CODSPEED=1 to the PR description, or
  • Include run-perf or /perf in the PR title or any commit message.

@rossirpaulo
rossirpaulo marked this pull request as ready for review June 12, 2026 08:59
@vercel
vercel Bot temporarily deployed to Preview – beps June 12, 2026 08:59 Inactive
@rossirpaulo
rossirpaulo enabled auto-merge June 12, 2026 08:59
@github-actions

Copy link
Copy Markdown

No description provided.

@vercel
vercel Bot temporarily deployed to Preview – promptfiddle2 June 12, 2026 09:06 Inactive
@rossirpaulo
rossirpaulo added this pull request to the merge queue Jun 12, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

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

⚠️ Outside diff range comments (1)
baml_language/crates/baml_cli/src/agent_command.rs (1)

410-417: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

SKILL.md frontmatter parsing is LF-only.

split_frontmatter() only accepts ---\n / \n---\n, so --from on a Windows checkout or archive with CRLF SKILL.md files fails with “missing opening frontmatter marker”. The new packaging script has the same delimiter assumption, so the local package/install path breaks end-to-end on CRLF inputs.

Suggested fix
 fn split_frontmatter(content: &str) -> Result<(&str, &str)> {
     let rest = content
-        .strip_prefix("---\n")
+        .strip_prefix("---\r\n")
+        .or_else(|| content.strip_prefix("---\n"))
         .ok_or_else(|| anyhow!("SKILL.md is missing opening frontmatter marker"))?;
-    let Some((frontmatter, body)) = rest.split_once("\n---\n") else {
+    let Some((frontmatter, body)) = rest
+        .split_once("\r\n---\r\n")
+        .or_else(|| rest.split_once("\n---\n"))
+    else {
         anyhow::bail!("SKILL.md is missing closing frontmatter marker");
     };
     Ok((frontmatter, body))
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@baml_language/crates/baml_cli/src/agent_command.rs` around lines 410 - 417,
The split_frontmatter function currently matches only LF delimiters and fails on
CRLF files; update split_frontmatter to tolerate CRLF by normalizing input line
endings (replace "\r\n" with "\n" at function start) or by checking both "\n"
and "\r\n" variants for the opening ("---\n" / "---\r\n") and closing ("\n---\n"
/ "\r\n---\r\n") markers; ensure you still return the frontmatter and body as
&str slices consistently (adjust logic in split_frontmatter to operate on the
normalized string or to compute offsets so returned slices refer to the correct
underlying data).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/release-baml-language.yml:
- Around line 288-291: The all-builds job/gate is missing the build-agent-skills
job, which allows publish-pypi, publish-wrapper-release, and publish-nodejs-sdk
(which depend solely on all-builds) to run even if build-agent-skills fails;
update the workflow so the all-builds gate/job includes build-agent-skills (add
build-agent-skills as a dependency/member of all-builds) so that publish-pypi,
publish-wrapper-release, and publish-nodejs-sdk cannot proceed unless
build-agent-skills completes successfully, keeping publish-toolchain-release
(which already depends on build-agent-skills) consistent with the rest of the
pipeline.

In `@scripts/package-agent-skills`:
- Around line 144-149: The tar creation is nondeterministic because gzip embeds
timestamps and tar preserves file metadata; update the archive step that uses
COPYFILE_DISABLE and the tar invocation to produce reproducible output by (1)
exporting GZIP=-n (to strip gzip timestamps), (2) adding deterministic tar flags
like --sort=name --mtime='1970-01-01' --numeric-owner --owner=0 --group=0 (and
--no-acls/--no-xattrs if available), and (3) keeping the same archive name path
used later for sha256 generation so the resulting "$archive" and
"$archive_name.sha256" are stable across builds.
- Around line 16-26: For the option parsing branches handling --source,
--version, and --out-dir (which set source_dir, version, out_dir and then call
shift 2), add a guard to validate that a value exists in "$2" before performing
shift 2; if "$2" is empty or missing, call usage() and exit 2. Locate the blocks
that currently do: "--source) source_dir=\"${2:-}\" shift 2 ;;", "--version)
version=\"${2:-}\" shift 2 ;;", and "--out-dir) out_dir=\"${2:-}\" shift 2 ;;"
and insert a simple check (e.g., test -z "${2:-}") to handle the missing-value
case before assigning and shifting.

---

Outside diff comments:
In `@baml_language/crates/baml_cli/src/agent_command.rs`:
- Around line 410-417: The split_frontmatter function currently matches only LF
delimiters and fails on CRLF files; update split_frontmatter to tolerate CRLF by
normalizing input line endings (replace "\r\n" with "\n" at function start) or
by checking both "\n" and "\r\n" variants for the opening ("---\n" / "---\r\n")
and closing ("\n---\n" / "\r\n---\r\n") markers; ensure you still return the
frontmatter and body as &str slices consistently (adjust logic in
split_frontmatter to operate on the normalized string or to compute offsets so
returned slices refer to the correct underlying data).
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 18fc4f46-efe1-468d-a075-60fb8957361e

📥 Commits

Reviewing files that changed from the base of the PR and between c3bef22 and 48f63dc.

📒 Files selected for processing (3)
  • .github/workflows/release-baml-language.yml
  • baml_language/crates/baml_cli/src/agent_command.rs
  • scripts/package-agent-skills

Comment thread scripts/package-agent-skills Resolved
Comment thread scripts/package-agent-skills Resolved
@rossirpaulo
rossirpaulo removed this pull request from the merge queue due to a manual request Jun 12, 2026
@rossirpaulo
rossirpaulo enabled auto-merge June 12, 2026 09:12
@vercel
vercel Bot temporarily deployed to Preview – beps June 12, 2026 09:13 Inactive

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (2)
scripts/package-agent-skills (1)

136-141: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Direct-layout skill discovery is depth-mismatched and misses valid SKILL.md files.

At Line 141, find "$source_dir/skills" -mindepth 2 -maxdepth 2 ... -path '*/baml-*/SKILL.md' cannot match skills/*/baml-*/SKILL.md because those files are depth 3 under skills. This will skip direct-layout skills and can incorrectly trigger the "no BAML agent skills found" failure.

Suggested minimal fix
-  done < <(find "$source_dir/skills" -mindepth 2 -maxdepth 2 -type f -path '*/baml-*/SKILL.md' -print0 | sort -z)
+  done < <(find "$source_dir/skills" -mindepth 3 -maxdepth 3 -type f -path '*/baml-*/SKILL.md' -print0 | sort -z)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/package-agent-skills` around lines 136 - 141, The find invocation
that discovers SKILL.md uses -mindepth 2 -maxdepth 2 and -path
'*/baml-*/SKILL.md', which misses direct-layout skills located at
skills/*/baml-*/SKILL.md (depth 3). Update the find call used for skill
discovery (the one piping into the while loop that reads skill_file and calls
stage_skill) to include depth 3 results (e.g., change -mindepth/-maxdepth to 3
or remove the depth limits) or add an alternative -path clause to also match
*/*/baml-*/SKILL.md so stage_skill will be invoked for those SKILL.md files and
count will reflect them.
.github/workflows/release-baml-language.yml (1)

297-301: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Pin BAML_AGENT_SKILLS_REPOSITORY checkout to an immutable ref.

This checkout currently follows the repository default branch, so reruns for the same release version can package different skill contents. That undermines reproducibility for the versioned baml-agent-skills-*.tar.gz artifact. Please use an immutable tag or commit SHA (ideally emitted by the release plan) via ref:.

🔧 Suggested direction
       - uses: actions/checkout@v4
         with:
           repository: ${{ env.BAML_AGENT_SKILLS_REPOSITORY }}
+          ref: ${{ needs.plan.outputs.agent_skills_ref }} # immutable tag or commit SHA
           path: agent-skills-source
           persist-credentials: false
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release-baml-language.yml around lines 297 - 301, The
checkout step using actions/checkout@v4 for repository ${{
env.BAML_AGENT_SKILLS_REPOSITORY }} is not pinned to an immutable ref, causing
non-reproducible artifact contents; update the checkout step (the
actions/checkout@v4 invocation that sets path: agent-skills-source) to include a
ref: that points to an immutable tag or commit SHA emitted by the release plan
(e.g. use a new env like BAML_AGENT_SKILLS_REF or the release SHA) so the
workflow always checks out the exact revision used to build
baml-agent-skills-*.tar.gz.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In @.github/workflows/release-baml-language.yml:
- Around line 297-301: The checkout step using actions/checkout@v4 for
repository ${{ env.BAML_AGENT_SKILLS_REPOSITORY }} is not pinned to an immutable
ref, causing non-reproducible artifact contents; update the checkout step (the
actions/checkout@v4 invocation that sets path: agent-skills-source) to include a
ref: that points to an immutable tag or commit SHA emitted by the release plan
(e.g. use a new env like BAML_AGENT_SKILLS_REF or the release SHA) so the
workflow always checks out the exact revision used to build
baml-agent-skills-*.tar.gz.

In `@scripts/package-agent-skills`:
- Around line 136-141: The find invocation that discovers SKILL.md uses
-mindepth 2 -maxdepth 2 and -path '*/baml-*/SKILL.md', which misses
direct-layout skills located at skills/*/baml-*/SKILL.md (depth 3). Update the
find call used for skill discovery (the one piping into the while loop that
reads skill_file and calls stage_skill) to include depth 3 results (e.g., change
-mindepth/-maxdepth to 3 or remove the depth limits) or add an alternative -path
clause to also match */*/baml-*/SKILL.md so stage_skill will be invoked for
those SKILL.md files and count will reflect them.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 71f46635-ce1a-4d87-b02f-890b9fda0bac

📥 Commits

Reviewing files that changed from the base of the PR and between 48f63dc and ffa77d8.

📒 Files selected for processing (3)
  • .github/workflows/release-baml-language.yml
  • baml_language/crates/baml_cli/src/agent_command.rs
  • scripts/package-agent-skills

This branch was previously deployed

3 inactive deployments
Preview – promptfiddle — ffa77d8c Deployed Jun 12, 2026 by vercel[bot]
Preview – promptfiddle2 — ffa77d8c Deployed Jun 12, 2026 by vercel[bot]
Preview – beps — ffa77d8c Deployed Jun 12, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant