Conversation
Adds the FR-1.0 master reference file (8 Appendix A tables: Selection Catalogue, Node-Role, Functional-Layer Composition, Stack-Storage Compatibility, Package Source Defaults, Pinned Version, Supported Hardware, Constraint/Co-Requisite), derived by hand from src/main/samples/catalogs/**/*.json and src/repo_manager/input/repo_manager_config.yml (plus src/repo_manager's expected_versions map for AMD/ROCm and BeeGFS planned-status evidence). Every row carries support_status and file-level provenance. Adds SKILL.md: the shared FR-2 Selection Catalogue support_status gate, written as a channel-agnostic decision procedure rather than code, so a browser-based AI assistant (FR-5.1) can apply it without executing Python. Catalog Generation, Catalog Editing's Pre-Edit Gate, and the Analysis skills read master_reference_file.md and follow SKILL.md directly. Story: ER-BSM-001-master-reference-file Signed-off-by: venu <236371043+Venu-p1@users.noreply.github.com>
Every shipped sample catalog under src/main/samples/catalogs/**/*.json carries catalog.schema_version (integer, currently 2), but catalog_schema.json did not declare that property while using additionalProperties: false at the catalog level. As a result all 22 shipped catalogs failed catalog_manager.py's validate command against their own schema for this reason alone. Discovered while implementing ER-BSM-001-catalog-generation-skill, whose acceptance criteria require the skill's generated output to validate against this schema using the existing catalog_manager.py validate CLI (no new schema-validation code is introduced by that skill). Story: ER-BSM-001-catalog-generation-skill Signed-off-by: venu <236371043+Venu-p1@users.noreply.github.com>
…ivity layer Adds SKILL.md: a channel-agnostic decision procedure implementing FR-1.1 and FR-2 of ER-BSM-001-nersc-ai-skills-catalog-authoring. It runs the Appendix B selection interview in dependency order, applies the master-reference Selection Catalogue gate at every decision point, filters storage options by the Stack-Storage Compatibility table with default pre-selection, rejects Kubernetes+aarch64, expands the Functional-Layer Composition table into concrete functional layers, resolves package sources/versions from A.5/A.6 with no-fabrication handling for unresolved packages, and validates output by shelling out to the existing catalog_manager.py validate CLI (no new schema_gate.py file, per user direction). Adds shared/connectivity_layer.md: the FR-3 online/offline fallback procedure (prefer Red Hat Compatibility Matrix / upstream docs / live package repos / local RPM repos; disclose fallback to master reference file on timeout/unreachable/malformed data). Packaged as a single shared instructions file referenced by this skill and reusable as-is by the future ER-BSM-001-analysis-skills Story, per that Story's resolved Open Question. Story: ER-BSM-001-catalog-generation-skill Signed-off-by: venu <236371043+Venu-p1@users.noreply.github.com>
…ills Adds impact_analysis.md: traces functional-layer-to-package references within a single catalog (direct blast radius), then attempts an online transitive-dependency lookup via the shared connectivity layer, falling back to catalog/master-reference-only scope with explicit disclosure when unavailable (FR-3.1). Adds compatibility_analysis.md: cross-references a package/version against the Red Hat Compatibility Matrix and upstream documentation when reachable (citing the specific source), falling back to A.1/A.6/ A.8 master-reference constraints only, with disclosure, when unavailable (FR-3.2). Adds trusted_source_policy.md: the shared FR-3 trusted-source- restriction fragment both skills reference (never an open-ended web search or unofficial mirror; report unresolved rather than broaden the search), plus the NFR-4/Req-SEC-I-5 audit-logging contract -- a plain text append to analysis/degraded_mode_audit.log when file-system access is available, disclosure-text-only otherwise. No new Python. Story: ER-BSM-001-analysis-skills Signed-off-by: venu <236371043+Venu-p1@users.noreply.github.com>
src/build_stream/ai_skills/analysis/degraded_mode_audit.log is an append-only operational artifact written by the analysis skills per analysis/trusted_source_policy.md's audit-logging contract, not source content. Story: ER-BSM-001-analysis-skills Signed-off-by: venu <236371043+Venu-p1@users.noreply.github.com>
… impact Rewrites impact_analysis.md per the post-review FR-1 Enhancement (R1-R8): - R1: attempt local dnf metadata, then the package's own repo, then upstream docs, before falling back to the master reference file -- "absent from A.6" is no longer a reason to stop early. - R2: distinguish "removed from the catalog" from "actually removed from a built node" when another catalog package still requires it. - R3: accept a target at the package, group, functional-layer, or OS level. - R4/R5: four impact tiers (package/role/cluster/user), each tagged with its evidence class (repo-metadata/upstream-doc/catalog/inferred). - R6: pinned-vs-latest version comparison when no pin exists. - R7: Critical/High/Medium/Low severity rubric. - R8: customer-facing summary leads the report. Also updates the two shared fragments both analysis skills depend on: - shared/connectivity_layer.md: clarifies the fallback trigger is an actual lookup failure, never merely "absent from one table"; notes the local Omnia-repo read as reachability under the existing "local system RPM repositories" class, not a new source class. - analysis/trusted_source_policy.md: adds the architecture-mismatch operator-choice flow and two new audit-log reason= values (arch-mismatch, operator-declined-proxy). Real reproduction on this host's subscribed RHEL 10.2 BaseOS/AppStream repos (dnf repoquery --whatrequires iproute) motivated this change and is used as the rewritten worked example. Story: ER-BSM-001-analysis-skills Signed-off-by: venu <236371043+Venu-p1@users.noreply.github.com>
…g engine Implements the Semantic Catalog Diff and Human-Readable Changelog Story (ER-BSM-001-diff-changelog-skill, FR-4.1/FR-4.2): - differ.py: deterministic op-list diff/patch engine. build_ops() computes a self-contained forward or reverse op-list purely from two Schema 2.0 catalogs; apply_patch() applies one; diff_catalogs() computes both directions and verifies the reversibility invariant (current + forward_diff == future, future + reverse_diff == current) exactly, raising ReversibilityError rather than returning a best-effort result if it doesn't hold. Rejects legacy Schema 1.0 (PascalCase 'Catalog' root) input with an actionable error. - report_renderer.py: builds a human-readable summary from the forward diff, a plain-English changelog, and (via Jinja2, optional) a rich HTML report -- always a separate artifact from the machine-readable diff, never merged into it. Implements the two compatibility/dependency warnings this Story's offline scope actually supports, from the master reference file's A.8 table: CON-004 (Kubernetes RPM/image/repo version-pin agreement) and CON-007 (shared-group removal affecting another functional layer). - catalog_manager.py: new `diff` subcommand wiring the above together, reusing the existing schema-validation gate (validator.py) for the schema-invalid-catalog rejection scenario. - diff_changelog/changelog_generator.md: channel-agnostic skill instructions that invoke the CLI above rather than hand-diffing catalogs, following the same "reuse an existing tool via CLI" pattern as the catalog-generation Story's schema-validation step. Verified against the real shipped RHEL 10.0/10.2 service_k8s_x86_64 sample catalogs: 198-operation forward/reverse diff pair reconstructs both catalogs exactly; identical catalogs produce an empty diff pair (not an error); a synthetic kubelet minor-version bump correctly triggers CON-004. Story: ER-BSM-001-diff-changelog-skill Signed-off-by: venu <236371043+Venu-p1@users.noreply.github.com>
cmd_add and cmd_delete wrote the mutated catalog to disk unconditionally,
then ran schema validation only afterward for reporting -- an invalid
edit was already persisted to the file by the time the [ERROR] lines
printed. Reorder both commands to validate the in-memory result first
and only write when there are no schema errors (unchanged behavior when
no --schema is given, or when validation passes/only has warnings).
Found while assessing whether ER-BSM-001-catalog-editing-skill's FR-1
("the skill SHALL reject the edit ... AND the catalog file SHALL remain
unmodified") could reuse these existing commands -- as written, they
could not have satisfied that requirement.
Verified: upsert_packages() + validate_catalog() on a package with an
empty sources list produces schema errors, and the reordered write-only-
if-no-errors logic leaves the target file's content byte-for-byte
unchanged (MD5 verified before/after).
Story: ER-BSM-001-catalog-editing-skill
Signed-off-by: venu <236371043+Venu-p1@users.noreply.github.com>
Implements ER-BSM-001-catalog-editing-skill (FR-1.2, FR-1.3, FR-6.1, FR-5.1): - edit_catalog.md: single-catalog editing (add/remove a package, pin a version, correct metadata), reusing catalog_manager.py's add/ delete commands (now validate-before-write). Verified end-to-end on a real catalog: adding curl to service_k8s_x86_64.json (10.2) lands it in the correct group with the correct OS-version pin, and every other package/group/functionallayer entry compares dict-equal to the pre-edit catalog. - bulk_edit_catalog.md: cross-catalog bulk edits with per-catalog schema-validation failure isolation. For edits add/delete already covers, isolation is free (each catalog is a separate read-validate- write cycle). For structural field edits with no dedicated CLI verb (e.g. a base_os group's os_version bump), documents and verifies the same validate-before-write pattern directly via the existing catalog_io/validator functions. Verified with two real catalogs, one deliberately missing a required field: the valid one's os_version updates on disk, the invalid one is left byte-for-byte unmodified (MD5-verified) with its specific violation reported. - pre_edit_gate.md: the shared approve/decline/skip orchestration both editing skills call before applying anything (FR-6.1 has no apply path that skips this). Written as channel-agnostic instructions, not a Python state machine -- this is conversational orchestration (run analysis, present findings, wait for approval), not a deterministic invariant like the diff engine. Covers per-catalog differentiated flagging for bulk edits and wires to ER-BSM-001-analysis-skills (Impact/Compatibility Analysis) and ER-BSM-001-diff-changelog-skill (post-approval changelog update). Story: ER-BSM-001-catalog-editing-skill Signed-off-by: venu <236371043+Venu-p1@users.noreply.github.com>
… control Verified write_catalog() (used by every catalog_manager.py command) has no code-level path-boundary check -- a path-traversal write into /etc/ succeeds today with no restriction. Per decision, this Story does not add a guard to that shared function (it's used well beyond this Story's scope). Instead, edit_catalog.md and bulk_edit_catalog.md now state explicitly that the write-path boundary (NFR-2, Req-SEC-I-1/I-4) is an instruction-level control the skill itself must enforce until a code-level guard exists -- not a guarantee the underlying tool provides. Story: ER-BSM-001-catalog-editing-skill Signed-off-by: venu <236371043+Venu-p1@users.noreply.github.com>
Seven real gaps surfaced by actually exercising the catalog generation, editing, and diff/changelog skills, fixed together since most touch the same shared instruction files: - catalog_generation/SKILL.md: add "Step 4b - Group Package Composition Resolution". A.3 only records which groups a role includes, never which packages each group actually contains -- only shipped catalog JSON has that. When no shipped catalog matched the requested stack/arch/os_version, the skill was silently borrowing an unrelated stack's catalog (observed: a Slurm catalog request fell back to service_k8s_x86_64.json) instead of disclosing the gap. Verified against real shipped-catalog data first: most shared groups (common_pks, admin_debug_group, ldms_group, ...) have exactly one component-set across all 22 shipped catalogs (safe to reuse any instance); baseos_group has 3 variants differing only by one architecture-specific image_build_<arch> key (closest-match-by-axis with disclosure, not a blind pick). No shipped instance at all -> refuse and ask, never substitute or fabricate. - catalog_generation/SKILL.md: add Step 9 (always ask about additional packages/custom functional roles) and Step 4a (how to apply that answer) -- custom group/role naming validated against A.2's layer-naming pattern (verified: all 24 shipped functional layers follow <role>_rhel_<os_version>_<architecture> with no exception), with baseos_group called out as the one real exception (the group name itself never varies by arch/stack/OS version, unlike its layer). - master_reference/SKILL.md: add a Step 0 to the Selection Catalogue gate so a presented menu only ever lists supported options -- planned/unsupported options no longer appear as noise in the interview, only reactively if the operator names one. - shared/working_directory.md (new): shared scratch-file convention (mktemp -d, copy out only after validation, clean up always) used by catalog_generation's draft catalog, changelog_generator's default diff/changelog outputs, and pre_edit_gate's pre-edit snapshot. - pre_edit_gate.md: since edit_catalog.md/bulk_edit_catalog.md overwrite a catalog in place, take a pre-edit snapshot into the working directory *before* applying the edit so changelog_generator.md still has a "before" state to diff against afterward -- verified end-to-end with a real add + snapshot diff. - report_renderer.py/catalog_manager.py/changelog_report.html.j2: add detect_os_version_cutover() to collapse a whole-catalog OS-version re-cut (e.g. 10.0 -> 10.2) into one consolidated summary line instead of dozens of near-identical per-package "changed" rows and per-group CON-007 warnings that all say the same thing. Verified against the real 10.0/10.2 service_k8s_x86_64 sample catalogs: 187 package rows collapse to 1 line, 21 duplicate CON-007 warnings collapse to 1 informational note, with the full old->new layer-name mapping still shown; identical-catalog and real-content-change cases are unaffected (regression-tested). Signed-off-by: venu <236371043+Venu-p1@users.noreply.github.com>
Venu-p1
marked this pull request as ready for review
September 28, 2026 06:58
Venu-p1
requested review from
Rajeshkumar-s2,
RvishankarOMnia,
VenkateswaraVatam,
abhishek-sa1 and
snarthan
as code owners
September 28, 2026 06:58
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR Title
feat(catalog_skills): add catalog generation, analysis, editing, and diff/changelog skills
PR Description
Description of the Solution
Implements a comprehensive suite of AI skills for catalog management under ER-BSM-001, including master reference file, catalog generation, impact/compatibility analysis, catalog editing with pre-edit gate, and reversible diff/changelog engine. Adds Python tooling for catalog diff/patch operations and fixes schema validation issues.
Related Issue
Changes
Component (
src/build_stream/ai_skills/master_reference)Component (
src/build_stream/ai_skills/catalog_generation)Component (
src/build_stream/ai_skills/analysis)Component (
src/build_stream/ai_skills/catalog_editing)Component (
src/build_stream/ai_skills/diff_changelog)Component (
src/repo_manager/plugins/module_utils/catalog)diffsubcommand and implement validate-before-write for add/delete commandsComponent (
src/repo_manager/schemas)Component (
.gitignore)Files Changed
.gitignoresrc/build_stream/ai_skills/analysis/compatibility_analysis.mdsrc/build_stream/ai_skills/analysis/impact_analysis.mdsrc/build_stream/ai_skills/analysis/trusted_source_policy.mdsrc/build_stream/ai_skills/catalog_editing/bulk_edit_catalog.mdsrc/build_stream/ai_skills/catalog_editing/edit_catalog.mdsrc/build_stream/ai_skills/catalog_editing/pre_edit_gate.mdsrc/build_stream/ai_skills/catalog_generation/SKILL.mdsrc/build_stream/ai_skills/diff_changelog/changelog_generator.mdsrc/build_stream/ai_skills/master_reference/SKILL.mdsrc/build_stream/ai_skills/master_reference/master_reference_file.mdsrc/build_stream/ai_skills/shared/connectivity_layer.mdsrc/repo_manager/plugins/module_utils/catalog/catalog_manager.pysrc/repo_manager/plugins/module_utils/catalog/differ.pysrc/repo_manager/plugins/module_utils/catalog/report_renderer.pysrc/repo_manager/plugins/module_utils/catalog/templates/changelog_report.html.j2src/repo_manager/schemas/catalog_schema.jsonTesting
Backward Compatibility
Suggested Reviewers
@abhishek-sa1@VenkateswaraVatam@RvishankarOMnia@snarthan@Rajeshkumar-s2