Skip to content

OSAC-3957: Vendor osac-ai-skills from tools/bootstrap.sh - #307

Draft
tchughesiv wants to merge 13 commits into
osac-project:mainfrom
tchughesiv:feat/OSAC-3957-osac-bootstrap-osac-ai-skills
Draft

OSAC-3957: Vendor osac-ai-skills from tools/bootstrap.sh#307
tchughesiv wants to merge 13 commits into
osac-project:mainfrom
tchughesiv:feat/OSAC-3957-osac-bootstrap-osac-ai-skills

Conversation

@tchughesiv

@tchughesiv tchughesiv commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

OSAC-3957: osac/tools/bootstrap.sh vendors osac-ai-skills and runs fan-out

Jira: https://redhat.atlassian.net/browse/OSAC-3957
Story type: Task
ADR: 0001 Decision item 2(a)

Summary

Extend osac/tools/bootstrap.sh so a fresh osac/ clone vendors osac-ai-skills, materializes OSAC skills, and links Claude/Cursor/Gemini discovery dirs without a second checkout of osac-workspace or a manual skills clone. Mirrors the OSAC-3956 consumer pattern (osac-workspace#208, osac-ai-skills#2).

Changes

  • tools/link-agent-skills.sh — consumer wrapper: resolve vendored osac-ai-skills, materialize per-skill absolute symlinks into skills/, exec vendored fan-out with PROJECT_ROOT
  • tools/test/link-agent-skills-consumer-smoke.sh — bash smoke for missing vendor, three-harness links, refuse real dirs, prune stale links
  • tools/bootstrap.sh — vendor osac-ai-skills (prefer usable ~/.osac-ai-skills), then link, then ai-workflows install.sh (link-before-install required on fresh clones)
  • .gitignore — ignore .osac-ai-skills/
  • AGENTS.md — document AI bootstrap / skill authorship in osac-ai-skills

Out of scope: declarative sibling clones / enhancement-proposals (OSAC-3958), pinned-copy for bots (OSAC-3959).

Testing

  • Unit tests: bash tools/test/link-agent-skills-consumer-smoke.sh (4 contracts)
  • Integration tests: Isolated git worktree + empty HOME full tools/bootstrap.sh — three harnesses read create-pr; --verify passes
  • Coverage: Bash smoke / verify / isolated bootstrap (no Go coverage gate for this path)

Acceptance Criteria

  • AC-1: Fresh clone of osac/ + bootstrap.sh produces working skill symlinks for Claude, Cursor, and Gemini
  • AC-2: No second checkout of osac-ai-skills (or osac-workspace) is required

Summary by CodeRabbit

  • New Features

    • Added automated setup and updates for AI-assisted workflows and skills.
    • Added support for linking skills across supported agent environments.
    • Added safeguards for missing vendors, invalid paths, existing directories, and stale links.
  • Documentation

    • Documented AI-assisted development setup and skill locations.
  • Tests

    • Added smoke tests covering installation, linking, cleanup, vendor resolution, and failure handling.
  • Chores

    • Excluded local AI skill checkouts from version control.

Assisted-by: Cursor <noreply@cursor.com>
Signed-off-by: Tommy Hughes <tohughes@redhat.com>
Assisted-by: Cursor <noreply@cursor.com>
Signed-off-by: Tommy Hughes <tohughes@redhat.com>
Assisted-by: Cursor <noreply@cursor.com>
Signed-off-by: Tommy Hughes <tohughes@redhat.com>
install.sh creates real .*/skills directories; the fan-out umbrella must
exist first so those writes land in skills/ through the symlinks.

Assisted-by: Cursor <noreply@cursor.com>
Signed-off-by: Tommy Hughes <tohughes@redhat.com>
@openshift-ci-robot

openshift-ci-robot commented Aug 12, 2026

Copy link
Copy Markdown

@tchughesiv: This pull request references OSAC-3957 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the task to target the "5.0.0" version, but no target version was set.

Details

In response to this:

OSAC-3957: osac/tools/bootstrap.sh vendors osac-ai-skills and runs fan-out

Jira: https://redhat.atlassian.net/browse/OSAC-3957
Story type: Task
ADR: 0001 Decision item 2(a)

Summary

Extend osac/tools/bootstrap.sh so a fresh osac/ clone vendors osac-ai-skills, materializes OSAC skills, and links Claude/Cursor/Gemini discovery dirs without a second checkout of osac-workspace or a manual skills clone. Mirrors the OSAC-3956 consumer pattern (osac-workspace#208, osac-ai-skills#2).

Changes

  • tools/link-agent-skills.sh — consumer wrapper: resolve vendored osac-ai-skills, materialize per-skill absolute symlinks into skills/, exec vendored fan-out with PROJECT_ROOT
  • tools/test/link-agent-skills-consumer-smoke.sh — bash smoke for missing vendor, three-harness links, refuse real dirs, prune stale links
  • tools/bootstrap.sh — vendor osac-ai-skills (prefer usable ~/.osac-ai-skills), then link, then ai-workflows install.sh (link-before-install required on fresh clones)
  • .gitignore — ignore .osac-ai-skills/
  • AGENTS.md — document AI bootstrap / skill authorship in osac-ai-skills

Out of scope: declarative sibling clones / enhancement-proposals (OSAC-3958), pinned-copy for bots (OSAC-3959).

Testing

  • Unit tests: bash tools/test/link-agent-skills-consumer-smoke.sh (4 contracts)
  • Integration tests: Isolated git worktree + empty HOME full tools/bootstrap.sh — three harnesses read create-pr; --verify passes
  • Coverage: Bash smoke / verify / isolated bootstrap (no Go coverage gate for this path)

Acceptance Criteria

  • AC-1: Fresh clone of osac/ + bootstrap.sh produces working skill symlinks for Claude, Cursor, and Gemini
  • AC-2: No second checkout of osac-ai-skills (or osac-workspace) is required

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository: osac-project/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 82104135-6c62-4c13-874c-81b1347fc092

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: osac-project/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5f65daa6-6ada-44fe-9daf-94a6a19a240b

📥 Commits

Reviewing files that changed from the base of the PR and between fef85c5 and fc557ea.

📒 Files selected for processing (3)
  • tools/bootstrap.sh
  • tools/link-agent-skills.sh
  • tools/test/link-agent-skills-consumer-smoke.sh
🚧 Files skipped from review as they are similar to previous changes (2)
  • tools/link-agent-skills.sh
  • tools/bootstrap.sh

Walkthrough

The bootstrap process now provisions osac-ai-skills, links its skills through a new wrapper, and documents the setup. Smoke tests cover vendor discovery, symlink materialization, failure handling, and stale-link cleanup.

Changes

AI skills integration

Layer / File(s) Summary
Repository provisioning and setup
tools/bootstrap.sh, AGENTS.md, .gitignore
Bootstrap validates, updates, or clones osac-ai-skills, links agent skill directories, and reports both workflow and skill installation. Setup documentation and ignore rules cover the local checkout.
Skill linking wrapper
tools/link-agent-skills.sh
The wrapper resolves a home or project-local vendor checkout, creates absolute skill symlinks, removes stale links, rejects real paths, handles flags, and delegates to the vendored fan-out script.
Wrapper validation
tools/test/link-agent-skills-consumer-smoke.sh
Smoke tests validate missing-vendor failures, skill linking, readable symlink targets, protection of real directories, and stale-link removal.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Mergeability Score: ⚪ Minimal · up to fc557

The stale-link removal behavior is covered by the smoke test, so no actionable merge-blocking risk remains beyond normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant Developer
  participant Bootstrap as tools/bootstrap.sh
  participant Wrapper as tools/link-agent-skills.sh
  participant Skills as osac-ai-skills
  Developer->>Bootstrap: run bootstrap
  Bootstrap->>Skills: validate, clone, or update checkout
  Bootstrap->>Wrapper: link agent skills
  Wrapper->>Skills: resolve skills and fan-out script
  Wrapper->>Wrapper: create and prune symlinks
  Wrapper->>Skills: delegate fan-out command
Loading

Possibly related PRs

  • osac-project/osac#102: This change extends the AI infrastructure in tools/bootstrap.sh, .gitignore, and AGENTS.md.
  • osac-project/osac#104: This change extends the AI development infrastructure in the same files.

Suggested reviewers: crystalchun, trewest

🚥 Pre-merge checks | ✅ 11
✅ Passed checks (11 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
No-Hardcoded-Secrets ✅ Passed The PR diff contains only public GitHub clone URLs, repository names, and non-secret test fixtures; scans found no credential assignments, embedded URL credentials, keys, tokens, or long encoded bl...
No-Weak-Crypto ✅ Passed The pull-request diff adds shell vendor/linking logic and test fixtures only; searches found no MD5, SHA1, DES, RC4, Blowfish, ECB, custom crypto, or secret comparisons.
No-Injection-Vectors ✅ Passed The PR adds Bash bootstrap/linking and documentation only; no SQL concatenation, shell=True, unsafe eval/exec, pickle/yaml loads, os.system, or user-data HTML sink is present.
Container-Privileges ✅ Passed The PR changes documentation, tests, and Bash vendor/link scripts; no container/Kubernetes manifests or explicit privileged, host*, SYS_ADMIN, or allowPrivilegeEscalation settings were added.
No-Sensitive-Data-In-Logs ✅ Passed PR-added logs report repository names, local paths, link paths, and operation status; no passwords, tokens, API keys, PII, session IDs, internal hostnames, or customer data are logged.
Ai-Attribution ✅ Passed AI use is documented, and all 8 PR commits include Assisted-by: Cursor; the range contains no Co-Authored-By trailers.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: vendoring osac-ai-skills through tools/bootstrap.sh.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@fullsend-ai-review

fullsend-ai-review Bot commented Aug 12, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 9:06 PM UTC · Ended 9:11 PM UTC

Commit: fef85c5 · View workflow run →

@tchughesiv
tchughesiv marked this pull request as ready for review August 12, 2026 21:10
@openshift-ci
openshift-ci Bot requested review from CrystalChun and trewest August 12, 2026 21:10
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 12, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 9:12 PM UTC · Completed 9:29 PM UTC

Commit: fef85c5 · View workflow run →

coderabbitai[bot]
coderabbitai Bot previously requested changes Aug 12, 2026

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

🤖 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 `@tools/bootstrap.sh`:
- Around line 43-53: Use one vendor validity contract across tools/bootstrap.sh
lines 43-53 and tools/link-agent-skills.sh lines 31-40: require the
project-local or home vendor directory to meet the same validity criteria,
including .git, before selecting or updating it. In bootstrap, validate the
project-local .osac-ai-skills directory before any git fetch/rebase and provide
recovery instructions when invalid; update the link-agent-skills selection logic
to apply the identical rule, or consistently support non-Git trees in both
locations.

In `@tools/test/link-agent-skills-consumer-smoke.sh`:
- Around line 10-26: Make link-agent-skills-consumer-smoke.sh self-contained by
adding minimal local fan-out fixture setup, or invoking tools/bootstrap.sh
before candidate discovery and fixture checks. Ensure a clean checkout can
execute the smoke test without prior bootstrap, while preserving the existing
WRAPPER and PROJECT_ROOT-capable fan-out validations.
🪄 Autofix

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: osac-project/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f3bfb205-458e-49fb-beab-4a49bf60da07

📥 Commits

Reviewing files that changed from the base of the PR and between a82462e and fef85c5.

📒 Files selected for processing (5)
  • .gitignore
  • AGENTS.md
  • tools/bootstrap.sh
  • tools/link-agent-skills.sh
  • tools/test/link-agent-skills-consumer-smoke.sh

Comment thread tools/bootstrap.sh Outdated
Comment thread tools/test/link-agent-skills-consumer-smoke.sh Outdated
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review

Findings

Medium

  • [protected-path] AGENTS.md — This PR modifies AGENTS.md, which is a protected governance file. The PR links to OSAC-3957 (Jira) and references ADR 0001 Decision item 2(a), providing context for the change. Human approval is always required for protected-path changes, regardless of justification.

Low

  • [error-handling-gap] tools/bootstrap.sh — The ai-workflows resolution block (line 80) checks only [[ -d "${HOME}/.ai-workflows" ]] before calling update_git_repo, without validating it is a usable git checkout. If ~/.ai-workflows is an empty or non-git directory, git fetch fails with a confusing "Fetch failed" message. This is a pre-existing pattern (not introduced by this PR) but remains a gap compared to the osac_ai_skills_vendor_ok() gate used for the new osac-ai-skills vendor.

  • [edge-case] tools/bootstrap.sh — Path resolution asymmetry: ~/.osac-ai-skills is resolved via readlink -f (line 39), but ${PROJECT_ROOT}/.osac-ai-skills is used directly (line 42). Since PROJECT_ROOT is already canonicalized via realpath, the practical impact is minimal.

  • [test-inadequate] tools/test/link-agent-skills-consumer-smoke.sh — No test exercises the zero-argument default behavior (the ARGS=(--all --with-ai-workflows) expansion at line 509). All test functions pass explicit flags (--claude, --all --with-ai-workflows).

  • [fail-open] tools/link-agent-skills.shresolve_osac_ai_skills_dir() validates OSAC_AI_SKILLS_VENDOR_DIR only for structural presence (skills/ directory and executable tools/link-agent-skills.sh), then execs that script at line 156. This is consistent with the pre-existing trust model where install.sh is already executed from unverified clones.

  • [error-handling-idiom] tools/link-agent-skills.shresolve_osac_ai_skills_dir returns its result via stdout (captured by command substitution), while sibling bootstrap.sh sets variables directly. The stdout-as-return-value pattern is idiomatic shell but diverges from the sibling script's convention.

Previous run

Review

Findings

Medium

  • [protected-path] AGENTS.md — This file is under a protected path. The PR has a linked Jira ticket (OSAC-3957) and explains the rationale for the change (documenting AI bootstrap setup). Human approval is always required for protected-path changes, regardless of context.

  • [supply-chain] tools/link-agent-skills.sh — The script execs ${VENDOR_DIR}/tools/link-agent-skills.sh, delegating control to code from a vendored clone that is updated to origin/main without SHA pinning. This is the same pattern already used for ai-workflows/install.sh (pre-existing risk), now extended to a second external repository (osac-project/osac-ai-skills). Consider pinning to a known-good commit SHA or signed tag.

Low

  • [edge-case] tools/link-agent-skills.sh — Redundant rm -f before ln -sfn in materialize_osac_skills(). The -f flag in ln -sfn already replaces existing symlinks, making the explicit removal unnecessary. The rm -f introduces a brief window where the symlink does not exist.

  • [symlink-traversal] tools/link-agent-skills.shmaterialize_osac_skills() iterates vendor/skills/*/ and creates symlinks to pwd -P-resolved paths. If the vendored repo contains a malicious symlink in skills/ pointing outside the vendor tree, it would be followed. Risk is contained (vendor repo must already be compromised). Consider validating the resolved target stays within the vendor tree.

  • [privilege-scope] tools/bootstrap.shHOME/.osac-ai-skills is preferred over the project-local clone. On shared multi-user machines, another user with write access to $HOME/.osac-ai-skills could control what code is executed. Same pattern as existing ai-workflows resolution.

  • [naming-consistency] tools/link-agent-skills.sh — Uses REPO_ROOT instead of PROJECT_ROOT (used by bootstrap.sh). The comment block at lines 17–21 explicitly documents this as intentional: REPO_ROOT is the wrapper’s internal name, while PROJECT_ROOT is the cross-repo contract name exported to the vendored fan-out (OSAC-3956). Documented and deliberate.

Previous run (2)

Review

Findings

Medium

  • [protected-path] AGENTS.md — This PR modifies AGENTS.md, which is under protected paths governance. The PR links to Jira OSAC-3957 and explains the rationale (documenting AI-assisted development bootstrap). Human approval is always required for protected-path changes, regardless of context.

Low

  • [arbitrary code execution via vendored repository] tools/bootstrap.sh:72 — The script clones osac-project/osac-ai-skills from GitHub with no commit pinning, tag verification, or signature check. This mirrors the pre-existing ai-workflows clone pattern in the same file but expands the attack surface to a second external repository.
    Remediation: Pin clone to a specific commit SHA or signed tag.

  • [arbitrary code execution via exec of vendored script] tools/link-agent-skills.sh:131exec hands full control to the vendored script with PROJECT_ROOT exported, giving write access to the repo tree. Arguments are passed through without allowlist validation.
    Remediation: Validate ARGS against an allowlist of known flags before forwarding.

  • [symlink-target-validation] tools/link-agent-skills.sh:76materialize_osac_skills creates symlinks to resolved vendor paths via pwd -P without verifying the target stays within the vendor tree. A compromised vendor repo containing a skill directory symlink to an external path would be followed.
    Remediation: After resolving the target path, verify it is still under the vendor directory: [[ "${target}" == "${vendor_skills}"/* ]] || continue.

  • [HOME-trust-boundary] tools/link-agent-skills.sh:41resolve_osac_ai_skills_dir checks ~/.osac-ai-skills before $REPO/.osac-ai-skills. In CI or shared environments where HOME may be manipulated, an attacker could place a malicious vendor checkout that takes priority.
    Remediation: In CI environments, explicitly set the vendor directory via an environment variable rather than relying on HOME-first resolution.

  • [naming-convention] tools/link-agent-skills.sh:16 — Uses REPO_ROOT internally while exporting PROJECT_ROOT for the vendor fan-out. Same directory, two names in the same file, which could confuse future maintainers.
    Remediation: Rename REPO_ROOT to PROJECT_ROOT for consistency with tools/bootstrap.sh, or add a brief comment explaining the naming choice.

  • [scope-alignment] AGENTS.md:28osac-ai-skills is now a vendored dependency but is not listed in the "External Repos" table (lines 19–26). Developers scanning that table for companion repositories will miss it.
    Remediation: Add an osac-ai-skills row to the External Repos table.


Labels: PR modifies AGENTS.md documentation and adds developer tooling scripts

Previous run (3)

Review

Findings

Medium

  • [protected-path] AGENTS.md — This PR modifies AGENTS.md, which is a protected governance file. The PR links to Jira OSAC-3957 and explains the rationale (documenting the new AI-assisted development bootstrap workflow). Human approval is required for protected-path changes regardless of context.

  • [supply chain / remote code execution] tools/link-agent-skills.sh:110 — The script execs into the vendored osac-ai-skills repository's tools/link-agent-skills.sh without integrity verification. The clone tracks origin/main with no commit pinning, tag verification, or signature checking. This follows the pre-existing pattern for flightctl/ai-workflows but doubles the unpinned external repository attack surface.
    Remediation: Consider pinning both external repos to a known-good commit SHA or signed tag.

Low

  • [dead variable] tools/bootstrap.sh:21OSAC_AI_SKILLS_DIR is set in all branches of the osac-ai-skills resolution block but never read afterward. The skill linking is delegated to tools/link-agent-skills.sh, which performs its own vendor resolution. The variable could be removed.

  • [code organization / DRY] tools/bootstrap.sh:31 — The fetch-rebase-abort block is copy-pasted for the ~/.osac-ai-skills and $PROJECT_ROOT/.osac-ai-skills branches. The existing ai-workflows section has the same duplication. Extracting an update_git_repo() helper would reduce the maintenance surface.

  • [supply chain / repository trust] tools/bootstrap.sh:67 — The osac-ai-skills repo is cloned without depth limiting or integrity verification. The osac_ai_skills_vendor_ok() validation is a minimal structural check. This follows the existing ai-workflows pattern.

  • [validation inconsistency] tools/link-agent-skills.sh:37resolve_osac_ai_skills_dir() does not check for .git while bootstrap.sh's osac_ai_skills_vendor_ok() does. The asymmetry is design-appropriate (link-agent-skills.sh doesn't need git operations), but could be documented.

Previous run (4)

Review

Findings

Medium

  • [logic-error] tools/bootstrap.sh:49 — The elif branch checking [[ -d "${PROJECT_ROOT}/.osac-ai-skills" ]] does not call osac_ai_skills_vendor_ok before attempting git fetch and git rebase. If the directory exists but is not a valid git checkout (no .git, missing skills/, or missing executable tools/link-agent-skills.sh), the git commands will fail with confusing errors. The first branch correctly gates on osac_ai_skills_vendor_ok; the second branch should do the same.
    Remediation: Add osac_ai_skills_vendor_ok "${PROJECT_ROOT}/.osac-ai-skills" to the elif condition.

  • [protected-path] AGENTS.md — This PR modifies AGENTS.md, which is a protected governance file. The PR links to Jira OSAC-3957 and explains the rationale (documenting AI-assisted development bootstrap). Human approval is required for protected-path changes regardless of context.

Low

  • [execution-of-untrusted-code] tools/link-agent-skills.sh:110 — The script execs into ${VENDOR_DIR}/tools/link-agent-skills.sh from an external repository cloned without commit pinning or integrity verification. This is consistent with the existing trust model for flightctl/ai-workflows.
    Remediation: Consider pinning the clone to a specific commit SHA or tag.

  • [execution-of-untrusted-code] tools/bootstrap.shosac_ai_skills_vendor_ok checks directory structure but does not verify repository identity (git remote URL). Consistent with the pre-existing ai-workflows pattern.

  • [naming-consistency] tools/link-agent-skills.sh — Uses REPO_ROOT for the project root while tools/bootstrap.sh uses PROJECT_ROOT. The wrapper exports PROJECT_ROOT="${REPO_ROOT}" for the downstream vendored script, but having two names for the same path in tools/ may cause confusion.

  • [error-handling-idiom] tools/bootstrap.sh — The osac-ai-skills and ai-workflows vendor sections use different guard patterns (osac_ai_skills_vendor_ok vs. bare directory-existence checks). Aligning them or extracting a shared helper would improve maintainability.

  • [edge-case] tools/link-agent-skills.sh:54rm -f before ln -sfn is redundant; ln -sfn atomically replaces existing symlinks.

  • [edge-case] tools/link-agent-skills.sh:46 — If the vendor's skills/ directory contains only exclusion-list names (bugfix, design, etc.), materialize_osac_skills silently succeeds without creating links. This is correct behavior but worth documenting.

  • [code-duplication] tools/bootstrap.sh — The clone/update/rebase stanzas are nearly identical 12-line blocks repeated for both vendors. A shared helper would reduce maintenance burden.

  • [path-resolution-inconsistency] tools/link-agent-skills.shresolve_osac_ai_skills_dir() uses cd && pwd -P while the rest of the file uses realpath. Functionally equivalent but stylistically inconsistent.

  • [header-comment-format] tools/bootstrap.sh — Step 3's parenthetical about umbrella symlinks reads as an implementation note rather than a usage comment.


Labels: PR modifies developer tooling scripts (tools/bootstrap.sh, tools/link-agent-skills.sh) and governance documentation (AGENTS.md)

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-review fullsend-ai-review Bot added requires-manual-review Review requires human judgment development This issue requires development work labels Aug 12, 2026
@omer-vishlitzky
omer-vishlitzky dismissed coderabbitai[bot]’s stale review August 12, 2026 21:29

Auto-dismissed: only Prow labels gate merging

Gate project-local .osac-ai-skills with osac_ai_skills_vendor_ok before
git update, and embed a minimal fan-out stub so the consumer smoke runs
on a clean checkout without a prior bootstrap.

Assisted-by: Cursor <noreply@cursor.com>
Signed-off-by: Tommy Hughes <tohughes@redhat.com>
@tchughesiv

tchughesiv commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

Addressed bot review feedback in 9f497b4:

  • Gate project-local .osac-ai-skills with osac_ai_skills_vendor_ok (fail with recovery if invalid)
  • Make consumer smoke self-contained via embedded fan-out stub

Left as-is / deferred:

  • Wrapper stays content-based (no .git requirement) vs bootstrap’s git-capable check — intentional
  • SHA pinning → OSAC-3959
  • AGENTS.md change is intentional AC-2 docs (needs human approval as noted)
  • Minor style/naming/duplication nits deferred

@fullsend-ai-review fullsend-ai-review Bot added the documentation Improvements or additions to documentation label Aug 12, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 12, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 10:57 PM UTC · Ended 11:01 PM UTC

Commit: 6f318ad · View workflow run →

REPO_ROOT (this wrapper's own name, osac-workspace's reference wrapper
calls it WORKSPACE_ROOT) and the exported PROJECT_ROOT are the same
directory under two names. Add a comment explaining why: PROJECT_ROOT
is a fixed cross-repo contract name the vendored osac-ai-skills fan-out
expects (OSAC-3956), not a stylistic choice, so it isn't renamed to
match REPO_ROOT.

Addresses fullsend-ai-review naming-convention finding (Round 4) on
OSAC-3957 / osac-project#307.

Assisted-by: Cursor <noreply@cursor.com>
Signed-off-by: Tommy Hughes <tohughes@redhat.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Aug 12, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 11:02 PM UTC · Completed 11:18 PM UTC

Commit: cb1dbf6 · View workflow run →

@openshift-ci

openshift-ci Bot commented Aug 12, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

Approval requirements bypassed by manually added approval.

This pull-request has been approved by: tchughesiv

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@tchughesiv
tchughesiv marked this pull request as draft August 12, 2026 23:37
auto-merge was automatically disabled August 12, 2026 23:37

Pull request was converted to draft

Signed-off-by: Tommy Hughes <tohughes@redhat.com>
@openshift-ci

openshift-ci Bot commented Aug 13, 2026

Copy link
Copy Markdown

New changes are detected. LGTM label has been removed.

@fullsend-ai-review

fullsend-ai-review Bot commented Aug 13, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 12:12 AM UTC · Completed 12:27 AM UTC

Commit: c96c1de · View workflow run →

@fullsend-ai-review fullsend-ai-review 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.

See the review comment for full details.

Comment thread tools/bootstrap.sh
@@ -21,34 +80,31 @@ AI_WORKFLOWS_DIR=""
if [[ -d "${HOME}/.ai-workflows" ]]; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[low] error-handling-gap

The ai-workflows resolution block checks only [[ -d "${HOME}/.ai-workflows" ]] before calling update_git_repo, without validating it is a usable git checkout. If ~/.ai-workflows is an empty or non-git directory, git fetch fails with a confusing 'Fetch failed' message. This is a pre-existing pattern (not introduced by this PR) but remains a gap compared to the osac_ai_skills_vendor_ok() gate used for the new vendor.

Suggested fix: Add a validation check (e.g., [[ -d "${HOME}/.ai-workflows/.git" ]]) before calling update_git_repo on the ai-workflows directory.

Comment thread tools/bootstrap.sh

# Fetch + rebase a vendored git checkout onto origin/main. Warns and continues
# on failure rather than exiting — a stale vendor is recoverable manually, and
# this runs before any skill-discovery step that depends on it.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[low] edge-case

Path resolution asymmetry: ~/.osac-ai-skills is resolved via readlink -f (line 39), but ${PROJECT_ROOT}/.osac-ai-skills is used directly (line 42). Since PROJECT_ROOT is already canonicalized via realpath, the practical impact is minimal.

#
# When $OSAC_AI_SKILLS_VENDOR_DIR is set, it is authoritative and is not
# re-validated against the two-candidate search below: bootstrap.sh sets it
# to the exact directory it already resolved (or just cloned), specifically

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[low] fail-open

resolve_osac_ai_skills_dir() validates OSAC_AI_SKILLS_VENDOR_DIR only for structural presence (skills/ directory and executable tools/link-agent-skills.sh), then execs that script at line 156. Consistent with the pre-existing trust model where install.sh is already executed from unverified clones.


ARGS=("$@")
if [[ ${#ARGS[@]} -eq 0 ]]; then
ARGS=(--all --with-ai-workflows)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[low] error-handling-idiom

resolve_osac_ai_skills_dir returns its result via stdout (captured by command substitution), while sibling bootstrap.sh sets variables directly. The stdout-as-return-value pattern is idiomatic shell but diverges from the sibling script's convention.

tchughesiv added a commit to tchughesiv/osac-workspace that referenced this pull request Aug 13, 2026
Backports two hardening fixes discovered during osac-project/osac#307's
review (the mono-repo's independent port of this same vendoring
pattern) that this reordering fix's original scope didn't cover:

- Gate the project-local ./.osac-ai-skills branch with the same
  osac_ai_skills_vendor_ok() check already used for ~/.osac-ai-skills,
  so a stale or non-git leftover directory fails with an actionable
  message instead of a confusing `git fetch` error.
- Export OSAC_AI_SKILLS_VENDOR_DIR from bootstrap.sh into
  tools/link-agent-skills.sh so the wrapper uses the exact vendor
  directory bootstrap.sh already resolved/updated/cloned, instead of
  independently re-resolving one via its own weaker, HOME-first
  search -- which could otherwise silently link skills from a stale
  vendor bootstrap.sh had already rejected.

Adds a regression test (test_vendor_override_env_var_is_authoritative)
covering both the override-wins-over-a-different-valid-vendor case and
the invalid-override-fails-loudly case.

Assisted-by: Cursor <noreply@cursor.com>
Signed-off-by: Tommy Hughes <tohughes@redhat.com>
tchughesiv added a commit to osac-project/osac-workspace that referenced this pull request Aug 13, 2026
… clone (#213)

* fix(OSAC-4039): reorder bootstrap.sh skill-linking to survive a fresh clone

ai-workflows' install.sh creates .claude/skills (and .cursor/skills,
.gemini/skills) as real directories via mkdir -p when nothing exists
yet, then link-agent-skills.sh --all refuses to replace a real
directory with the ../skills umbrella symlink -- aborting the whole
bootstrap under set -euo pipefail. Never bites on an already-
bootstrapped clone (install.sh's mkdir -p is a no-op against an
existing symlinked directory), only a from-scratch one.

Run link-agent-skills.sh --all before install.sh so the umbrella
symlinks exist first; install.sh's targeted ln -sfn calls into
.claude/skills/<workflow> then transparently follow the symlink.
Verified end-to-end on a fresh clone (zero errors/warnings, --verify
passes).

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Tommy Hughes <tohughes@redhat.com>

* fix(OSAC-4039): harden osac-ai-skills vendor resolution in bootstrap.sh

Backports two hardening fixes discovered during osac-project/osac#307's
review (the mono-repo's independent port of this same vendoring
pattern) that this reordering fix's original scope didn't cover:

- Gate the project-local ./.osac-ai-skills branch with the same
  osac_ai_skills_vendor_ok() check already used for ~/.osac-ai-skills,
  so a stale or non-git leftover directory fails with an actionable
  message instead of a confusing `git fetch` error.
- Export OSAC_AI_SKILLS_VENDOR_DIR from bootstrap.sh into
  tools/link-agent-skills.sh so the wrapper uses the exact vendor
  directory bootstrap.sh already resolved/updated/cloned, instead of
  independently re-resolving one via its own weaker, HOME-first
  search -- which could otherwise silently link skills from a stale
  vendor bootstrap.sh had already rejected.

Adds a regression test (test_vendor_override_env_var_is_authoritative)
covering both the override-wins-over-a-different-valid-vendor case and
the invalid-override-fails-loudly case.

Assisted-by: Cursor <noreply@cursor.com>
Signed-off-by: Tommy Hughes <tohughes@redhat.com>

---------

Signed-off-by: Tommy Hughes <tohughes@redhat.com>
@tchughesiv

tchughesiv commented Aug 14, 2026

Copy link
Copy Markdown
Contributor Author

Follow-up flag from OSAC-4006 review (osac-workspace#214): osac/.claude/settings.json's statusLine.command has a small edge-case gap CodeRabbit caught while reviewing a copy of this same command in osac-workspace.

jq -r '.workspace.project_dir' on a missing or null field emits the literal string "null" (not empty), which passes the existing [ -n "$dir" ] check and then tries to invoke a nonexistent null/.claude/hooks/statusline.sh path. Narrow in practice (only triggers if Claude Code ever sends malformed workspace.project_dir, which it normally doesn't), but a one-line fix:

-dir=$(printf '%s' "$input" | jq -r '.workspace.project_dir');
+dir=$(printf '%s' "$input" | jq -er '.workspace.project_dir | strings | select(length > 0)');

Fixed in osac-workspace's copy (osac-workspace#214, commit 8e943e34); not fixing here since this PR is the consolidated landing point for OSAC-4006's remaining osac/-side items and this is a pre-existing gap rather than something introduced by that work — flagging for whoever picks this back up rather than blocking on it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

development This issue requires development work do-not-merge/work-in-progress documentation Improvements or additions to documentation jira/valid-reference requires-manual-review Review requires human judgment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants