Skip to content

Refactor kit model loading and enhance workflow handling#50

Merged
ainetx merged 1 commit into
mainfrom
multi-kit-fix
Jun 19, 2026
Merged

Refactor kit model loading and enhance workflow handling#50
ainetx merged 1 commit into
mainfrom
multi-kit-fix

Conversation

@ainetx

@ainetx ainetx commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator
  • Introduced a new function load_installed_kit_model to handle loading of installed kits with improved source precedence.
  • Updated various command scripts to replace load_kit_model with load_installed_kit_model for consistency and to support new functionality.
  • Added _public_workflow_ids_from_resource to extract public workflow IDs from resources, enhancing workflow management.
  • Modified _kit_model_to_info to include workflows from both public components and resources.
  • Updated tests to validate new behavior, including handling of public components and workflows in various scenarios.
  • Enhanced error handling and reporting for kit model loading and workflow extraction.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added --kit selector option to cfs kit normalize command for choosing specific kits from multi-kit manifests; use --kit all to normalize all kits.
  • Bug Fixes

    • Fixed cfs info output to properly expose deprecated workflows and skill resources in kit details.
    • Improved kit model loading behavior for installed and registered kits.

- Introduced a new function `load_installed_kit_model` to handle loading of installed kits with improved source precedence.
- Updated various command scripts to replace `load_kit_model` with `load_installed_kit_model` for consistency and to support new functionality.
- Added `_public_workflow_ids_from_resource` to extract public workflow IDs from resources, enhancing workflow management.
- Modified `_kit_model_to_info` to include workflows from both public components and resources.
- Updated tests to validate new behavior, including handling of public components and workflows in various scenarios.
- Enhanced error handling and reporting for kit model loading and workflow extraction.

Signed-off-by: ainetx <viator@via-net.org>
@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Introduces load_installed_kit_model that merges a "core" canonical kit model with a source model, replacing load_kit_model across all callers. Extends cmd_kit_normalize with a --kit selector for multi-kit canonical sources. Replaces single-kit TOML serialization with a multi-kit equivalent. Updates adapter-info deprecated workflow derivation to combine legacy workflow files with public skill/workflow resource IDs.

Changes

Installed Kit Model, Multi-Kit Normalize, and Deprecated Workflow Exposure

Layer / File(s) Summary
load_installed_kit_model, merge, and multi-kit serialization
skills/studio/scripts/studio/utils/kit_model.py
Adds _merge_core_authoritative_model to reconcile core and source kit model resources; introduces load_installed_kit_model that conditionally merges them (or returns source/core alone on load failures); replaces kit_model_to_toml_data with kit_models_to_toml_data for list-of-models TOML output; render_canonical_manifest delegates to new render_canonical_manifest_models.
cmd_kit_normalize multi-kit --kit selector
skills/studio/scripts/studio/commands/kit.py
Adds a repeatable --kit CLI option; loads canonical models from the source, filters by selected slugs (validating unknowns, supporting "all"); blocks subset writes without --output/--dry-run/--stdout; aggregates multi-kit ambiguity reports; updates dry-run/write JSON fields (kits, kits_normalized, conditional kit) and human-readable display.
Caller migration to load_installed_kit_model
skills/studio/scripts/studio/commands/agents.py, skills/studio/scripts/studio/commands/kit.py, skills/studio/scripts/studio/commands/resolve_vars.py
Switches registered-kit metadata collection, public component conflict detection, _list_public_components, and variable/alias resolution from load_kit_model to load_installed_kit_model with kit_entry/kit_slug; expands _list_public_components manifest_source allowlist to include "core".
Adapter info deprecated workflow derivation
skills/studio/scripts/studio/commands/adapter_info.py
Adds _public_workflow_ids_from_resource helper; updates _kit_model_to_info to use load_installed_kit_model; replaces legacy-component-based workflow ID derivation with composition over model.resources; reworks _legacy_kit_detail to merge workflow frontmatter stems with public skill/workflow IDs from core_kit["resources"].
Tests and architecture documentation
architecture/features/kit-management.md, tests/test_adapter_info.py, tests/test_agents_coverage.py, tests/test_kit.py, tests/test_kit_manifest_validate.py
Updates test mocks from load_kit_model to load_installed_kit_model, serialization calls from kit_model_to_toml_data to kit_models_to_toml_data([model]), and assertions for manifest_source/workflows/workflows_deprecated fields; adds multi-kit normalize, copy-mode, and legacy-fallback scenario tests; updates architecture docs with --kit selector rules, additive deprecated workflow output spec, and multi-kit normalization steps.

Sequence Diagram(s)

sequenceDiagram
  participant CLI as cfs kit normalize
  participant cmd_kit_normalize
  participant load_canonical_models
  participant load_installed_kit_model
  participant _merge_core_authoritative_model
  participant kit_models_to_toml_data

  CLI->>cmd_kit_normalize: --kit slug1 --kit slug2
  cmd_kit_normalize->>load_canonical_models: kit source path
  load_canonical_models-->>cmd_kit_normalize: [KitModel, KitModel, ...]
  cmd_kit_normalize->>cmd_kit_normalize: filter by --kit slugs, validate unknowns
  cmd_kit_normalize->>cmd_kit_normalize: block subset write without --output/--dry-run/--stdout
  loop for each selected model
    cmd_kit_normalize->>load_installed_kit_model: kit_source, core_kit, kit_slug
    load_installed_kit_model->>_merge_core_authoritative_model: core model + source model
    _merge_core_authoritative_model-->>load_installed_kit_model: merged KitModel
    load_installed_kit_model-->>cmd_kit_normalize: merged KitModel
  end
  cmd_kit_normalize->>kit_models_to_toml_data: [merged KitModel, ...]
  kit_models_to_toml_data-->>cmd_kit_normalize: canonical TOML dict
  cmd_kit_normalize-->>CLI: JSON result {kits, kits_normalized, kit?}
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • constructorfabric/studio#30: PR #30 introduces and validates artifacts.<KIND>.* bindings for constraints resources in canonical manifests; this PR explicitly preserves those constraints-to-artifact bindings during multi-kit normalization and documents the no-inference rule for missing template/example links.
  • constructorfabric/studio#43: PR #43 changes installed/register kit model resource derivation from canonical/manifest data in kit_model.py and overlapping adapter-info/drift expectations — directly preceding the load_installed_kit_model merge logic introduced here.

Poem

🐇 Hopping through kits, one, two, or a pack,
A canonical merge keeps the core on track.
--kit all or a slug — your choice, I say!
Deprecated workflows now gracefully display.
With multi-kit TOML and merged model delight,
This bunny normalizes everything right! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 29.63% 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 'Refactor kit model loading and enhance workflow handling' accurately captures the two main changes in the PR: refactoring of kit model loading (introduction of load_installed_kit_model) and enhancement of workflow extraction/handling.
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 multi-kit-fix

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
skills/studio/scripts/studio/utils/kit_model.py (1)

1437-1499: ⚡ Quick win

Extract resource serialization to clear the static-analysis failure.

kit_models_to_toml_data is now mostly a per-resource field mapper; moving that block into a _resource_to_toml_item(resource) helper should reduce the reported cognitive complexity without changing output.

🤖 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 `@skills/studio/scripts/studio/utils/kit_model.py` around lines 1437 - 1499,
The kit_models_to_toml_data function has high cognitive complexity due to the
large block of conditional field mappings for each resource. Extract the
resource serialization logic (the inner loop that processes each resource and
all the conditional checks for resource attributes like public, description,
aliases, etc.) into a new helper function named _resource_to_toml_item that
takes a resource parameter and returns the constructed dictionary item. Then
replace the extracted code block with a call to this new helper function while
keeping the outer loop structure in kit_models_to_toml_data intact. This reduces
nesting and complexity without changing the output behavior.

Source: Linters/SAST tools

🤖 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 `@architecture/features/kit-management.md`:
- Around line 190-194: The documentation for the kit normalize CLI flow is
missing the `--stdout` option that is actually supported by the implementation.
Add `--stdout` as an alternative output option to the trigger command line
(where it shows `[--output <path>]`) and also include it in step 1 where the
parse-args description mentions `[--output <path>]`. The `--stdout` option
should be documented as a mutually exclusive alternative to `--output` for
directing normalization results to standard output instead of a file.

In `@skills/studio/scripts/studio/commands/adapter_info.py`:
- Around line 451-454: The boolean parsing for public using
bool(binding.get("public", False)) incorrectly treats non-empty strings like
"false" as truthy, causing non-public resources to be incorrectly included in
the workflows set. Replace this with strict boolean parsing that properly
handles string representations (e.g., checking if the value equals "true"
case-insensitively or is already a boolean True). Additionally, normalize the
kind casing by converting it to lowercase before checking against the set
{"skill", "workflow"} to avoid case-sensitive misses when comparing the kind
value.

In `@skills/studio/scripts/studio/utils/kit_model.py`:
- Line 1404: The artifact_bindings assignment at line 1404 uses a simple `or`
operator which causes it to discard all bindings from either core_resource or
source_resource instead of merging them. Replace this simple fallback logic with
code that properly merges artifact_bindings from both core_resource and
source_resource, combining bindings per artifact kind so that disjoint artifact
kinds from both sources are preserved in the final merged result.

---

Nitpick comments:
In `@skills/studio/scripts/studio/utils/kit_model.py`:
- Around line 1437-1499: The kit_models_to_toml_data function has high cognitive
complexity due to the large block of conditional field mappings for each
resource. Extract the resource serialization logic (the inner loop that
processes each resource and all the conditional checks for resource attributes
like public, description, aliases, etc.) into a new helper function named
_resource_to_toml_item that takes a resource parameter and returns the
constructed dictionary item. Then replace the extracted code block with a call
to this new helper function while keeping the outer loop structure in
kit_models_to_toml_data intact. This reduces nesting and complexity without
changing the output behavior.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3201a70b-be7c-4174-b22c-a4695a07704e

📥 Commits

Reviewing files that changed from the base of the PR and between 48fdbda and eda3922.

📒 Files selected for processing (10)
  • architecture/features/kit-management.md
  • skills/studio/scripts/studio/commands/adapter_info.py
  • skills/studio/scripts/studio/commands/agents.py
  • skills/studio/scripts/studio/commands/kit.py
  • skills/studio/scripts/studio/commands/resolve_vars.py
  • skills/studio/scripts/studio/utils/kit_model.py
  • tests/test_adapter_info.py
  • tests/test_agents_coverage.py
  • tests/test_kit.py
  • tests/test_kit_manifest_validate.py

Comment on lines +190 to 194
**Trigger**: User runs `cfs kit normalize <path> [--from manifest|layout|core] [--kit <slug>|--kit all] [--output <path>] [--dry-run]`

**Steps**:
1. [x] - `p1` - Parse CLI arguments (path, --from, --output, --dry-run) - `inst-normalize-parse-args`
1. [x] - `p1` - Parse CLI arguments (path, --from, repeated/comma-separated `--kit`, --output, --dry-run) - `inst-normalize-parse-args`
2. [x] - `p1` - Validate source directory or installed resource binding source exists - `inst-normalize-validate-source`

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

Normalize CLI flow docs omit the supported --stdout option.

The trigger and parse-args step no longer document --stdout, but the command implementation supports it. This creates user-facing inconsistency.

Suggested doc fix
-**Trigger**: User runs `cfs kit normalize <path> [--from manifest|layout|core] [--kit <slug>|--kit all] [--output <path>] [--dry-run]`
+**Trigger**: User runs `cfs kit normalize <path> [--from manifest|layout|core] [--kit <slug>|--kit all] [--output <path>] [--dry-run] [--stdout]`

-1. [x] - `p1` - Parse CLI arguments (path, --from, repeated/comma-separated `--kit`, --output, --dry-run) - `inst-normalize-parse-args`
+1. [x] - `p1` - Parse CLI arguments (path, --from, repeated/comma-separated `--kit`, --output, --dry-run, --stdout) - `inst-normalize-parse-args`
🤖 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 `@architecture/features/kit-management.md` around lines 190 - 194, The
documentation for the kit normalize CLI flow is missing the `--stdout` option
that is actually supported by the implementation. Add `--stdout` as an
alternative output option to the trigger command line (where it shows `[--output
<path>]`) and also include it in step 1 where the parse-args description
mentions `[--output <path>]`. The `--stdout` option should be documented as a
mutually exclusive alternative to `--output` for directing normalization results
to standard output instead of a file.

Comment on lines +451 to +454
kind = str(binding.get("kind", "") or "")
public = bool(binding.get("public", False))
if public and kind in {"skill", "workflow"}:
workflows.add(str(resource_id))

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

Use strict boolean parsing for public in legacy fallback workflow derivation.

The current coercion treats non-empty strings (for example "false") as truthy, which can incorrectly include non-public resource IDs in deprecated workflows output. Also normalize kind casing to avoid case-sensitive misses.

Proposed patch
-            kind = str(binding.get("kind", "") or "")
-            public = bool(binding.get("public", False))
-            if public and kind in {"skill", "workflow"}:
+            kind = str(binding.get("kind", "") or "").strip().lower()
+            public_value = binding.get("public", False)
+            public = public_value if isinstance(public_value, bool) else False
+            if public and kind in {"skill", "workflow"}:
                 workflows.add(str(resource_id))
🤖 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 `@skills/studio/scripts/studio/commands/adapter_info.py` around lines 451 -
454, The boolean parsing for public using bool(binding.get("public", False))
incorrectly treats non-empty strings like "false" as truthy, causing non-public
resources to be incorrectly included in the workflows set. Replace this with
strict boolean parsing that properly handles string representations (e.g.,
checking if the value equals "true" case-insensitively or is already a boolean
True). Additionally, normalize the kind casing by converting it to lowercase
before checking against the set {"skill", "workflow"} to avoid case-sensitive
misses when comparing the kind value.

Comment thread skills/studio/scripts/studio/utils/kit_model.py
@ainetx ainetx merged commit cbf990c into main Jun 19, 2026
21 checks passed
@sonarqubecloud

Copy link
Copy Markdown

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