Skip to content

#72: Add project copy mode ownership and gitignore management#77

Merged
sandsower merged 1 commit intomainfrom
phase-3-project-copy-install
May 10, 2026
Merged

#72: Add project copy mode ownership and gitignore management#77
sandsower merged 1 commit intomainfrom
phase-3-project-copy-install

Conversation

@sandsower
Copy link
Copy Markdown
Owner

@sandsower sandsower commented May 10, 2026

Summary

  • add --copy project installs with per-skill .beislid-owner.json markers
  • record copy ownership, fingerprints, and install counts in .beislid/project-install.json
  • add safe refresh/no-clobber behavior and managed .gitignore guidance/--write-gitignore

Verification

  • bash -n install.sh bin/beislid scripts/install_lib.sh scripts/test_install.sh
  • python3 scripts/validate_skills.py
  • bash scripts/test_install.sh — 59 passed
  • python3 tests/agent-smoke/run.py gate ship-it --hosts claude,codex --timeout 900 --changed-only — passed on claude, codex

Notes

  • Untracked .codex and RELEASE_NOTES.md are excluded from this PR.

Summary by CodeRabbit

  • New Features

    • Project installations now support --copy mode for creating local portable skill copies, in addition to the default symlink mode.
    • Added --write-gitignore flag to manage .gitignore configuration during project installations.
    • Enhanced --force flag semantics for safer symlink replacement without affecting unrelated files.
  • Documentation

    • Updated CLI help text and documentation to reflect new installation modes and command flags.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 10, 2026

📝 Walkthrough

Walkthrough

This PR adds copy-mode installation for Beislið project skills, complementing the existing symlink-only approach. The feature introduces ownership markers, content fingerprinting, and managed .gitignore support to enable safe, repeatable copying of skill directories into projects.

Changes

Project Copy-Mode Installation

Layer / File(s) Summary
Documentation
README.md, docs/configuration.md, docs/how-to-use.md
Documentation updated to describe symlink-default vs. copy-mode behavior, ownership markers (.beislid-owner.json), manifest metadata (project-install.json), and managed .gitignore block with --write-gitignore flag.
CLI Interface
bin/beislid, install.sh
Help text and flag parsing extended to accept --copy and --write-gitignore; validation added to reject these flags when --project is missing.
Manifest & Metadata Contracts
scripts/install_lib.sh
_write_project_manifest signature extended with mode, copy counts, and ownership metadata; manifest generation includes copy-mode metadata structure.
Fingerprinting & Ownership
scripts/install_lib.sh
SHA-256 directory fingerprinting and ownership verification helpers added to identify Beislið-owned copied directories and decide refresh eligibility.
Copy Installation Primitives
scripts/install_lib.sh
Copy-mode installation routines: marker writer (_write_project_copy_marker), copy handler (_project_copy_skill_dir), and decision logic (_project_copy_and_count) for replace/refresh/skip scenarios.
Gitignore Management
scripts/install_lib.sh
Managed .gitignore block writer creates idempotent BEGIN/END Beislið project install section with skill paths, controlled by PROJECT_WRITE_GITIGNORE flag.
Main Installation Flow
scripts/install_lib.sh
beislid_install_project updated to dispatch symlink vs. copy logic by PROJECT_MODE, initialize copy counters, print mode, and pass expanded metadata to manifest writer; _count_project_installed_skills updated to recognize owned copies.
Tests & Assertions
scripts/test_install.sh
New assert_file_exists helper; integration tests for copy-mode CLI, ownership markers, manifest fields, safety rules (no clobbering), refresh behavior, marker fallback, and .gitignore idempotence; tests registered in test runner.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

  • sandsower/beislid#72: Main issue implementing the project copy-mode feature, ownership markers, managed .gitignore, and CLI/manifest plumbing that this PR addresses.

Possibly related PRs

  • sandsower/beislid#74: Prior PR modifying installer foundation in scripts/install_lib.sh and bin/beislid; this PR extends that work with copy-mode, ownership, and manifest enhancements.
  • sandsower/beislid#76: Prior PR establishing project-install structure and manifest writing; this PR builds on that foundation to add copy-mode and ownership tracking.

Poem

🐰 A skill-copy dance, precise and true,
Fingerprints guide what we install anew,
Ownership markers keep copies in line,
No clobbering happens—each file stays fine,
.gitignore smiles as we manage with care,
Beislið projects thrive, shared everywhere!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title clearly and accurately summarizes the main changes: adding project copy mode with ownership tracking and gitignore management.
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 phase-3-project-copy-install

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

Copy link
Copy Markdown
Contributor

@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: 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 `@scripts/install_lib.sh`:
- Around line 690-691: The local declaration in _write_project_gitignore uses
"local project=\"$1\" gitignore=\"$project/.gitignore\"" which triggers
ShellCheck SC2318 because gitignore references $project in the same local
statement; change the function to first declare and assign local project="$1"
and then declare local gitignore="$project/.gitignore" (i.e., split into two
local statements) so gitignore is initialized after project is set.
- Around line 531-532: In _project_copy_marker_owns(), avoid declaring marker in
the same local statement that defines dst because marker expands dst at
declaration time and causes portability issues; change the function to declare
local dst and local skill first (e.g., local dst="$1" local skill="$2"), then on
a separate line assign marker using marker="$dst/.beislid-owner.json" (keep
proper quoting) so marker is evaluated after dst is set.
🪄 Autofix (Beta)

✅ Autofix completed


ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 344c0a13-f0d3-4e70-a6e5-5f3a4a44584f

📥 Commits

Reviewing files that changed from the base of the PR and between bee7081 and 97404e3.

📒 Files selected for processing (7)
  • README.md
  • bin/beislid
  • docs/configuration.md
  • docs/how-to-use.md
  • install.sh
  • scripts/install_lib.sh
  • scripts/test_install.sh

Comment thread scripts/install_lib.sh
Comment on lines +531 to +532
_project_copy_marker_owns() {
local dst="$1" skill="$2" marker="$dst/.beislid-owner.json"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Split local declarations to avoid shell portability concern.

ShellCheck SC2318: marker references $dst from the same local statement. While bash processes left-to-right, this is a portability and clarity concern.

🛠️ Proposed fix
 _project_copy_marker_owns() {
-  local dst="$1" skill="$2" marker="$dst/.beislid-owner.json"
+  local dst="$1" skill="$2"
+  local marker="$dst/.beislid-owner.json"
   [[ -f "$marker" ]] || return 1
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
_project_copy_marker_owns() {
local dst="$1" skill="$2" marker="$dst/.beislid-owner.json"
_project_copy_marker_owns() {
local dst="$1" skill="$2"
local marker="$dst/.beislid-owner.json"
[[ -f "$marker" ]] || return 1
🧰 Tools
🪛 Shellcheck (0.11.0)

[warning] 532-532: This assignment is used again in this 'local', but won't have taken effect. Use two 'local's.

(SC2318)

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

In `@scripts/install_lib.sh` around lines 531 - 532, In
_project_copy_marker_owns(), avoid declaring marker in the same local statement
that defines dst because marker expands dst at declaration time and causes
portability issues; change the function to declare local dst and local skill
first (e.g., local dst="$1" local skill="$2"), then on a separate line assign
marker using marker="$dst/.beislid-owner.json" (keep proper quoting) so marker
is evaluated after dst is set.

Comment thread scripts/install_lib.sh
Comment on lines +690 to +691
_write_project_gitignore() {
local project="$1" gitignore="$project/.gitignore"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Split local declarations to avoid shell portability concern.

ShellCheck SC2318: gitignore references $project from the same local statement.

🛠️ Proposed fix
 _write_project_gitignore() {
-  local project="$1" gitignore="$project/.gitignore"
+  local project="$1"
+  local gitignore="$project/.gitignore"
   if [[ -L "$gitignore" ]]; then
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
_write_project_gitignore() {
local project="$1" gitignore="$project/.gitignore"
_write_project_gitignore() {
local project="$1"
local gitignore="$project/.gitignore"
if [[ -L "$gitignore" ]]; then
🧰 Tools
🪛 Shellcheck (0.11.0)

[warning] 691-691: This assignment is used again in this 'local', but won't have taken effect. Use two 'local's.

(SC2318)

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

In `@scripts/install_lib.sh` around lines 690 - 691, The local declaration in
_write_project_gitignore uses "local project=\"$1\"
gitignore=\"$project/.gitignore\"" which triggers ShellCheck SC2318 because
gitignore references $project in the same local statement; change the function
to first declare and assign local project="$1" and then declare local
gitignore="$project/.gitignore" (i.e., split into two local statements) so
gitignore is initialized after project is set.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 10, 2026

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

Fixes Applied Successfully

Fixed 1 file(s) based on 2 unresolved review comments.

A stacked PR containing fixes has been created.

  • Stacked PR: #78
  • Files modified:
  • scripts/install_lib.sh

Time taken: 1m 43s

@sandsower sandsower merged commit fc68d23 into main May 10, 2026
7 checks passed
sandsower added a commit that referenced this pull request May 10, 2026
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