Skip to content

Align labby CLI surfaces with implemented behavior#70

Merged
jmagar merged 5 commits into
mainfrom
fix/lab-cli-surface-completion
May 24, 2026
Merged

Align labby CLI surfaces with implemented behavior#70
jmagar merged 5 commits into
mainfrom
fix/lab-cli-surface-completion

Conversation

@jmagar
Copy link
Copy Markdown
Owner

@jmagar jmagar commented May 23, 2026

Summary

  • remove legacy top-level install/uninstall/init stubs and regenerate CLI docs
  • wire labby completions and make clap_complete a normal dependency
  • implement extract.apply/extract.diff through the canonical env merge path with redacted preview/conflict output
  • update the using-lab-cli skill and plan with research/review decisions

Verification

  • cargo check -p labby --lib
  • cargo run -p labby -- docs generate
  • cargo run -p labby -- docs check
  • target/debug/labby completions bash
  • target/debug/labby install rejects as an unrecognized subcommand
  • git diff --check

Known blocker

  • cargo test -p labby cli::tests:: --lib does not reach the CLI tests because crates/lab/src/mcp/server.rs test code references missing tool_search_schema_visible.

Summary by CodeRabbit

  • New Features

    • Added labby completions command for shell completion support.
    • Implemented labby extract --diff and labby extract --apply subcommands with full functionality.
    • Added --force flag to override conflicting environment variables during extract operations.
    • Added dry-run preview capability for environment file merges.
  • Removed

    • Removed non-functional labby install, labby uninstall, and labby init stubs.
  • Documentation

    • Updated CLI and plugin documentation to reflect current supported commands.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 23, 2026

Warning

Review limit reached

@jmagar, we couldn't start this review because you've used your available PR reviews for now.

Your plan currently allows 1 review/hour. Refill in 32 minutes and 45 seconds.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more review capacity refills, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than trial, open-source, and free plans. In all cases, review capacity refills continuously over time.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ada37809-ae1f-429e-a899-17026f9c55e5

📥 Commits

Reviewing files that changed from the base of the PR and between 3ffc195 and 195edf6.

📒 Files selected for processing (1)
  • crates/lab/Cargo.toml
📝 Walkthrough

Walkthrough

This PR completes the Lab CLI surface by removing legacy install/uninstall/init stubs, introducing shell-completions support, implementing canonical environment-merge preview and write flows for the extract command, and updating documentation and dispatch implementations to reflect working behavior only.

Changes

Lab CLI Surface Completion

Layer / File(s) Summary
CLI surface renovation and completions wiring
crates/lab/Cargo.toml, crates/lab/src/cli.rs, crates/lab/src/cli/gateway.rs
clap_complete is made a required dependency; the CLI crate removes install module export and adds completions module; Command enum removes Install/Uninstall/Init variants and adds Completions(completions::CompletionsArgs); dispatch routing is updated to wire Setup, Help, and new Completions commands; new tests verify legacy commands are rejected and setup/completions parse correctly; gateway.rs match arm is reformatted.
Environment merge preview and conflict warning
crates/lab/src/config/env_merge.rs
New public types MergePreview, PreviewChange, and PreviewStatus enum (Add, Update, Unchanged, Conflict) enable dry-run classification of merge effects; preview() function computes entry-by-entry status and skipped-conflict warnings without writing; conflict-warning helper removes the existing value from messages; tests verify classification accuracy and file idempotence.
Extract CLI command refactoring
crates/lab/src/cli/extract.rs
Extract command reroutes --apply and --diff through env_merge preview/write: apply_report uses preview to detect when no changes are needed (skip backup/write), otherwise calls write_service_creds to perform canonical merge; diff_report renders per-key status from PreviewStatus instead of manual diff lines; imports updated to use env_merge and write_service_creds; helper merge_request_from_creds converts extracted services/credentials into env_merge::MergeRequest.
Extract dispatch apply and diff actions
crates/lab/src/dispatch/extract.rs
Full implementation of MCP dispatch apply and diff actions: parses uri, force, and env_path parameters; validates env_path with LAB_ALLOW_EXTRACT_ENV_PATH_OVERRIDE gating and $HOME-based defaulting; scans targeted credentials, filters by optional services list (case-insensitive matching, rejects non-matching filters); builds merge request; computes preview and either writes (apply) or returns preview-only results (diff); ACTIONS catalog adds optional force param to both actions; response serialized via WritePlan struct; comprehensive tests verify override rejection and services filtering.
Documentation and supporting updates
crates/lab/src/docs/render.rs, crates/lab/src/mcp/server.rs, crates/lab/src/dispatch/gateway/dispatch.rs, docs/README.md, docs/surfaces/CLI.md, docs/superpowers/plans/2026-05-23-lab-cli-surface-completion.md, plugins/lab/skills/using-lab-cli/SKILL.md, plugins/lab/skills/using-lab-cli/references/config-reference.md
Help rendering trims trailing blank lines; MCP server test helpers refactored for clarity; gateway test formatting adjusted; CLI surface documentation removes install/uninstall/init guidance, adds completions and health/doctor to supported surfaces, updates multi-instance example; skill documentation rewritten to focus on labby CLI with new command surfaces and safer extract --apply/--diff/--force guidance; config reference updated to show MCP action payloads and new extract syntax; comprehensive implementation plan document added defining architecture constraints, task checklist, and verification gates.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • jmagar/lab#24: Both PRs modify the CLI surface by changing the Command enum and dispatch routing; this PR removes legacy stubs and adds completions, while #24 adds feature-gated mcpregistry command wiring.
  • jmagar/lab#11: Both PRs update crates/lab/src/cli.rs to revise the Command enum and dispatch routing for new subcommands; this PR removes legacy commands and adds completions, while #11 adds device and logs commands.

Poem

In the warren of commands, old stubs fade to dust,
While completions and env_merge rise up to trust.
Extract flows through preview, no write until sure,
The CLI surface gleams—lean, safe, and pure! 🐰✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 53.66% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Align labby CLI surfaces with implemented behavior' clearly and specifically summarizes the main change: aligning the CLI surface documentation and behavior across multiple files and modules.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/lab-cli-surface-completion

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.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 507976cc0e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +96 to +97
name: "force",
ty: "bool",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Use canonical boolean param type for force

Set ParamSpec.ty to "boolean" instead of "bool" for the new force parameters. The OpenAPI mapper only recognizes "boolean" and falls back unknown labels to string, so extract.apply/extract.diff are currently documented as accepting string force values while runtime parsing (parse_bool_param) rejects non-boolean JSON. This schema/runtime mismatch will break generated clients and UI form builders for these new actions.

Useful? React with 👍 / 👎.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 23, 2026

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{"name":"HttpError","status":401,"request":{"method":"PATCH","url":"https://api.github.com/repos/jmagar/lab/issues/comments/4525263299","headers":{"accept":"application/vnd.github.v3+json","user-agent":"octokit.js/0.0.0-development octokit-core.js/7.0.6 Node.js/24","authorization":"token [REDACTED]","content-type":"application/json; charset=utf-8"},"body":{"body":"<!-- This is an auto-generated comment: summarize by coderabbit.ai -->\n<!-- This is an auto-generated comment: rate limited by coderabbit.ai -->\n\n> [!WARNING]\n> ## Review limit reached\n> \n> `@jmagar`, we couldn't start this review because you've used your available PR reviews for now.\n> \n> Your plan currently allows 1 review/hour. Refill in 3 minutes and 20 seconds.\n> \n> Your organization has run out of usage credits. Purchase more in the [billing tab](https://app.coderabbit.ai/settings/subscription?tab=usage&tenantId=bc127b98-0e34-4ce6-8378-b33deb2745cf).\n> \n> <details>\n> <summary>⌛ How to resolve this issue?</summary>\n> \n> After more review capacity refills, a review can be triggered using the `@coderabbitai review` command as a PR comment. Alternatively, push new commits to this PR.\n> \n> We recommend that you space out your commits to avoid hitting the rate limit.\n> \n> </details>\n> \n> \n> <details>\n> <summary>🚦 How do rate limits work?</summary>\n> \n> CodeRabbit enforces hourly rate limits for each developer per organization.\n> \n> Our paid plans have higher rate limits than trial, open-source, and free plans. In all cases, review capacity refills continuously over time.\n> \n> Please see our [FAQ](https://docs.coderabbit.ai/faq) for further information.\n> \n> </details>\n> \n> <details>\n> <summary>ℹ️ Review info</summary>\n> \n> <details>\n> <summary>⚙️ Run configuration</summary>\n> \n> **Configuration used**: Organization UI\n> \n> **Review profile**: ASSERTIVE\n> \n> **Plan**: Pro\n> \n> **Run ID**: `e06bba3c-2ef8-4c43-8281-f374138a708f`\n> \n> </details>\n> \n> <details>\n> <summary>📥 Commits</summary>\n> \n> Reviewing files that changed from the base of the PR and between 82a85762fb7c27ba01e4dd938bf4c9c0bb8802c3 and 14eaac2c7df3bac3b1060deef249a7de3398c097.\n> \n> </details>\n> \n> <details>\n> <summary>⛔ Files ignored due to path filters (10)</summary>\n> \n> * `docs/generated/action-catalog.json` is excluded by `!**/generated/**` and included by `**/*`\n> * `docs/generated/action-catalog.md` is excluded by `!**/generated/**` and included by `**/*`\n> * `docs/generated/api-routes.json` is excluded by `!**/generated/**` and included by `**/*`\n> * `docs/generated/api-routes.md` is excluded by `!**/generated/**` and included by `**/*`\n> * `docs/generated/cli-help.md` is excluded by `!**/generated/**` and included by `**/*`\n> * `docs/generated/mcp-help.json` is excluded by `!**/generated/**` and included by `**/*`\n> * `docs/generated/mcp-help.md` is excluded by `!**/generated/**` and included by `**/*`\n> * `docs/generated/openapi.json` is excluded by `!**/generated/**` and included by `**/*`\n> * `docs/generated/service-catalog.json` is excluded by `!**/generated/**` and included by `**/*`\n> * `docs/generated/service-catalog.md` is excluded by `!**/generated/**` and included by `**/*`\n> \n> </details>\n> \n> <details>\n> <summary>📒 Files selected for processing (15)</summary>\n> \n> * `crates/lab/Cargo.toml`\n> * `crates/lab/src/cli.rs`\n> * `crates/lab/src/cli/extract.rs`\n> * `crates/lab/src/cli/gateway.rs`\n> * `crates/lab/src/cli/install.rs`\n> * `crates/lab/src/config/env_merge.rs`\n> * `crates/lab/src/dispatch/extract.rs`\n> * `crates/lab/src/dispatch/gateway/dispatch.rs`\n> * `crates/lab/src/docs/render.rs`\n> * `crates/lab/src/mcp/server.rs`\n> * `docs/README.md`\n> * `docs/superpowers/plans/2026-05-23-lab-cli-surface-completion.md`\n> * `docs/surfaces/CLI.md`\n> * `plugins/lab/skills/using-lab-cli/SKILL.md`\n> * `plugins/lab/skills/using-lab-cli/references/config-reference.md`\n> \n> </details>\n> \n> </details>\n\n<!-- end of auto-generated comment: rate limited by coderabbit.ai -->\n\n<!-- finishing_touch_checkbox_start -->\n\n<details>\n<summary>✨ Finishing Touches</summary>\n\n<details>\n<summary>🧪 Generate unit tests (beta)</summary>\n\n- [ ] <!-- {\"checkboxId\": \"f47ac10b-58cc-4372-a567-0e02b2c3d479\", \"radioGroupId\": \"utg-output-choice-group-unknown_comment_id\"} -->   Create PR with unit tests\n- [ ] <!-- {\"checkboxId\": \"6ba7b810-9dad-11d1-80b4-00c04fd430c8\", \"radioGroupId\": \"utg-output-choice-group-unknown_comment_id\"} -->   Commit unit tests in branch `fix/lab-cli-surface-completion`\n\n</details>\n\n</details>\n\n<!-- finishing_touch_checkbox_end -->\n<!-- tips_start -->\n\n---\n\nThanks for using [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=jmagar/lab&utm_content=70)! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.\n\n<details>\n<summary>❤️ Share</summary>\n\n- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)\n- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)\n- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)\n- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)\n\n</details>\n\n\n<sub>Comment `@coderabbitai help` to get the list of available commands and usage tips.</sub>\n\n<!-- tips_end -->"},"request":{"retryCount":1,"signal":{}}},"response":{"url":"https://api.github.com/repos/jmagar/lab/issues/comments/4525263299","status":401,"headers":{"access-control-allow-origin":"*","access-control-expose-headers":"ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset","connection":"close","content-security-policy":"default-src 'none'","content-type":"application/json; charset=utf-8","date":"Sat, 23 May 2026 12:05:38 GMT","referrer-policy":"origin-when-cross-origin, strict-origin-when-cross-origin","server":"github.com","strict-transport-security":"max-age=31536000; includeSubdomains; preload","vary":"Accept-Encoding, Accept, X-Requested-With","x-content-type-options":"nosniff","x-frame-options":"deny","x-github-media-type":"github.v3; format=json","x-github-request-id":"81D1:44353:21123B7:7FF2E83:6A119812","x-xss-protection":"0"},"data":{"message":"Bad credentials","documentation_url":"https://docs.github.com/rest","status":"401"}}}

Copy link
Copy Markdown

@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: 4

🤖 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 `@crates/lab/src/config/env_merge.rs`:
- Around line 346-381: The preview() function duplicates file-reading/key-value
parsing and request-entry deduplication logic that also appears in merge();
extract the shared logic into helpers (e.g., parse_existing_env(path: &Path) ->
Result<HashMap<String,String>, MergeError> which encapsulates fs::read_to_string
handling, NotFound => empty map, parsing lines, strip_quotes, and returning the
map, and dedupe_request_entries(entries: &[EnvEntry]) -> Vec<EnvEntry> which
merges duplicate keys keeping the last value) and then call these new helpers
from both preview() and merge(); ensure parse_existing_env returns the same
MergeError::WriteFailed semantics (using WriteFailReason::from_io) so behavior
remains identical.

In `@crates/lab/src/dispatch/extract.rs`:
- Around line 384-406: The function merge_request_from_creds is duplicated;
extract it into a shared module (e.g., create a new public function
merge_request_from_creds in crate::config) and replace both local
implementations with calls to that shared function. Make the new function
signature and behavior identical (accepting &[ServiceCreds] and force: bool and
returning env_merge::MergeRequest), mark it pub so both
dispatch::extract::merge_request_from_creds call sites can import it, update
imports/usages to call crate::config::merge_request_from_creds (or re-export if
preferred), and remove the duplicate definitions to prevent divergence.

In `@docs/superpowers/plans/2026-05-23-lab-cli-surface-completion.md`:
- Line 658: The verification gate wording contains a typo: the ambiguous token
"work-it" in the sentence referencing the compile break for
`tool_search_schema_visible` should be replaced with the intended term (likely
`worktree`); update the sentence to read "...fix that compile break in the same
worktree before continuing because worktree requires a green worktree" (or
better: "...fix that compile break in the same worktree before continuing
because worktree requires a green worktree")—locate the phrase "work-it" and
substitute "worktree" (or "workflow" if that fits the intended meaning) to make
the instruction clear and unambiguous.

In `@plugins/lab/skills/using-lab-cli/SKILL.md`:
- Around line 47-50: The example JSON uses an incorrect action name
"tool.search"; update the SKILL.md examples to use the actual synthetic
tool/service action name (e.g., replace "tool.search" with the real tool
identifier such as "scout.search" or its legacy alias) or a valid service action
string in the "action" field so it matches the runtime surface; adjust the
example lines that currently contain { "action": "tool.search", "params": {
"query": "radarr queue" } } to use the correct action name (e.g., { "action":
"scout.search", "params": { "query": "radarr queue" } }) and ensure consistency
with other examples.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: c4701a87-4604-4a5c-8b41-2fccecbd01f6

📥 Commits

Reviewing files that changed from the base of the PR and between 82a8576 and 3ffc195.

⛔ Files ignored due to path filters (6)
  • docs/generated/action-catalog.json is excluded by !**/generated/** and included by **/*
  • docs/generated/action-catalog.md is excluded by !**/generated/** and included by **/*
  • docs/generated/cli-help.md is excluded by !**/generated/** and included by **/*
  • docs/generated/mcp-help.json is excluded by !**/generated/** and included by **/*
  • docs/generated/mcp-help.md is excluded by !**/generated/** and included by **/*
  • docs/generated/openapi.json is excluded by !**/generated/** and included by **/*
📒 Files selected for processing (15)
  • crates/lab/Cargo.toml
  • crates/lab/src/cli.rs
  • crates/lab/src/cli/extract.rs
  • crates/lab/src/cli/gateway.rs
  • crates/lab/src/cli/install.rs
  • crates/lab/src/config/env_merge.rs
  • crates/lab/src/dispatch/extract.rs
  • crates/lab/src/dispatch/gateway/dispatch.rs
  • crates/lab/src/docs/render.rs
  • crates/lab/src/mcp/server.rs
  • docs/README.md
  • docs/superpowers/plans/2026-05-23-lab-cli-surface-completion.md
  • docs/surfaces/CLI.md
  • plugins/lab/skills/using-lab-cli/SKILL.md
  • plugins/lab/skills/using-lab-cli/references/config-reference.md
💤 Files with no reviewable changes (1)
  • crates/lab/src/cli/install.rs

Comment on lines +346 to +381
/// Classify a merge without writing, backing up, or pruning files.
pub fn preview(path: &Path, req: &MergeRequest) -> Result<MergePreview, MergeError> {
let existing_raw = match fs::read_to_string(path) {
Ok(s) => s,
Err(e) if e.kind() == ErrorKind::NotFound => String::new(),
Err(e) => {
return Err(MergeError::WriteFailed {
path: path.to_path_buf(),
reason: WriteFailReason::from_io(&e),
});
}
};

let mut existing_map: HashMap<String, String> = HashMap::new();
for line in existing_raw.lines() {
let trimmed = line.trim();
if trimmed.is_empty() || trimmed.starts_with('#') {
continue;
}
if let Some((k, v)) = trimmed.split_once('=') {
existing_map.insert(k.trim().to_owned(), strip_quotes(v.trim()).to_owned());
}
}

let mut request_entries: Vec<EnvEntry> = Vec::new();
for entry in &req.entries {
if let Some(slot) = request_entries
.iter_mut()
.find(|existing| existing.key == entry.key)
{
slot.value = entry.value.clone();
} else {
request_entries.push(entry.clone());
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | 💤 Low value

Consider extracting shared parsing logic.

The file-reading, key-value parsing, and request-entry deduplication logic (lines 348-380) is duplicated from merge() (lines 216-261). Extracting a shared helper (e.g., parse_existing_env and dedupe_request_entries) would reduce maintenance burden and ensure both paths stay in sync.

This is optional since the duplication is contained and both functions are cohesive.

🤖 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 `@crates/lab/src/config/env_merge.rs` around lines 346 - 381, The preview()
function duplicates file-reading/key-value parsing and request-entry
deduplication logic that also appears in merge(); extract the shared logic into
helpers (e.g., parse_existing_env(path: &Path) -> Result<HashMap<String,String>,
MergeError> which encapsulates fs::read_to_string handling, NotFound => empty
map, parsing lines, strip_quotes, and returning the map, and
dedupe_request_entries(entries: &[EnvEntry]) -> Vec<EnvEntry> which merges
duplicate keys keeping the last value) and then call these new helpers from both
preview() and merge(); ensure parse_existing_env returns the same
MergeError::WriteFailed semantics (using WriteFailReason::from_io) so behavior
remains identical.

Comment on lines +384 to +406
fn merge_request_from_creds(creds: &[ServiceCreds], force: bool) -> env_merge::MergeRequest {
let mut entries = Vec::new();
for cred in creds {
let svc_upper = cred.service.to_uppercase();
if let Some(url) = &cred.url {
entries.push(env_merge::EnvEntry::new(
format!("{svc_upper}_URL"),
url.clone(),
));
}
if let Some(secret) = &cred.secret {
entries.push(env_merge::EnvEntry::new(
cred.env_field.clone(),
secret.clone(),
));
}
}
env_merge::MergeRequest {
entries,
force,
expected_mtime: None,
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | 💤 Low value

Duplicated merge_request_from_creds logic.

This function is identical to the one in cli/extract.rs (lines 199-224). Consider extracting to a shared location (e.g., crate::config) to avoid divergence.

🤖 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 `@crates/lab/src/dispatch/extract.rs` around lines 384 - 406, The function
merge_request_from_creds is duplicated; extract it into a shared module (e.g.,
create a new public function merge_request_from_creds in crate::config) and
replace both local implementations with calls to that shared function. Make the
new function signature and behavior identical (accepting &[ServiceCreds] and
force: bool and returning env_merge::MergeRequest), mark it pub so both
dispatch::extract::merge_request_from_creds call sites can import it, update
imports/usages to call crate::config::merge_request_from_creds (or re-export if
preferred), and remove the duplicate definitions to prevent divergence.

cargo check --workspace --all-features
```

Expected: PASS. This is an early compile gate; `just check` below may repeat it as part of the repo-standard final gate. If this fails on the pre-existing `tool_search_schema_visible` compile issue, fix that compile break in the same worktree before continuing because work-it requires a green worktree.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix typo in verification gate wording.

work-it looks accidental and reads ambiguously in a critical verification instruction. Consider replacing it with the intended term (likely worktree or workflow).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/superpowers/plans/2026-05-23-lab-cli-surface-completion.md` at line 658,
The verification gate wording contains a typo: the ambiguous token "work-it" in
the sentence referencing the compile break for `tool_search_schema_visible`
should be replaced with the intended term (likely `worktree`); update the
sentence to read "...fix that compile break in the same worktree before
continuing because worktree requires a green worktree" (or better: "...fix that
compile break in the same worktree before continuing because worktree requires a
green worktree")—locate the phrase "work-it" and substitute "worktree" (or
"workflow" if that fits the intended meaning) to make the instruction clear and
unambiguous.

Comment on lines +47 to +50
```json
{ "action": "help" }
{ "action": "schema", "params": { "action": "gateway.reload" } }
{ "action": "tool.search", "params": { "query": "radarr queue" } }
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Correct MCP example action naming for tool search.

"tool.search" appears inconsistent with the runtime surface and may mislead users. Use the actual synthetic tool name (e.g., scout/legacy alias) or a valid service action string in the action field.

🤖 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 `@plugins/lab/skills/using-lab-cli/SKILL.md` around lines 47 - 50, The example
JSON uses an incorrect action name "tool.search"; update the SKILL.md examples
to use the actual synthetic tool/service action name (e.g., replace
"tool.search" with the real tool identifier such as "scout.search" or its legacy
alias) or a valid service action string in the "action" field so it matches the
runtime surface; adjust the example lines that currently contain { "action":
"tool.search", "params": { "query": "radarr queue" } } to use the correct action
name (e.g., { "action": "scout.search", "params": { "query": "radarr queue" } })
and ensure consistency with other examples.

@jmagar jmagar merged commit f0b9450 into main May 24, 2026
14 checks passed
@jmagar jmagar deleted the fix/lab-cli-surface-completion branch May 24, 2026 03:00
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