Skip to content

feat!: rename to gitculture-cli (command gitculture, ghafi kept as alias + PyPI shim)#14

Merged
OriNachum merged 2 commits into
mainfrom
rename-to-gitculture-cli
Jun 24, 2026
Merged

feat!: rename to gitculture-cli (command gitculture, ghafi kept as alias + PyPI shim)#14
OriNachum merged 2 commits into
mainfrom
rename-to-gitculture-cli

Conversation

@OriNachum

Copy link
Copy Markdown
Contributor

Summary

Renames the project ghafi → gitculture-cli. The CLI command is now gitculture; the old ghafi command is kept as a backward-compatible alias, and ghafi stays on PyPI as a thin compatibility shim that depends on gitculture-cli. The GitHub repo stays agentculture/ghafi (unchanged deployment target).

What changed

  • Package: ghafi/gitculture/ (git rename, history preserved); all imports updated; GhafiErrorGitcultureError, _GhafiArgumentParser_GitcultureArgumentParser.
  • pyproject: name = "gitculture-cli"; two console scripts (gitculture primary + ghafi alias) → gitculture.cli:main; wheel/coverage/isort targets → gitculture; __version__ from metadata("gitculture-cli").
  • Dual PyPI publishing: new packaging/ghafi/ compat shim metapackage (Requires-Dist: gitculture-cli==<ver>, hatchling bypass-selection); publish.yml builds both and publishes each with a filename-scoped uv publish so Trusted Publishing mints the correct per-project token; the dev/test job stamps the shim version + dependency pin in lockstep.
  • Kept ghafi (deployment target unchanged): repo URLs agentculture/ghafi, the User-Agent tool string's repo URL, the bug-report link, and the eidetic --scope ghafi.
  • Docs/skills/CI: README, CLAUDE.md, all SKILL.md + skill scripts, and tests.yml updated to gitculture.
  • Version: 0.4.0 → 0.5.0 with CHANGELOG entry.

Verification

  • 77 tests pass at 88% coverage; black / isort / flake8 / bandit / markdownlint / portability-lint all clean; doc-test-align reports no drift.
  • Live-tested: both wheels build; in a fresh venv gitculture and ghafi both run; pip install ghafi pulls in gitculture-cli; the no-token path exits 2 cleanly (no traceback).

⚠️ Required before the next publish

Trusted Publishing is keyed on (repo, workflow, environment), not artifact name. Register a Trusted Publisher for the new gitculture-cli project on pypi.org and test.pypi.org (owner agentculture, repo ghafi, workflow publish.yml, env pypi / testpypi) before merging to main, or the first publish step 403s. The existing ghafi publisher entry keeps working for the shim.

Out of scope (flagged, not changed here)

A pre-existing inconsistency where _env.py / learn.py / catalog.py list admin:repo_hook as a required scope while CLAUDE.md says it isn't needed. Unrelated to the rename; can be reconciled separately.

— ghafi (Claude)

🤖 Generated with Claude Code

https://claude.ai/code/session_01UnHGFcsv5bHFqBfPh7vpDE

… kept as alias + PyPI shim

Renames the project ghafi -> gitculture-cli. The import package ghafi/ becomes
gitculture/ and the CLI command is now `gitculture`. The old `ghafi` command is
kept as a backward-compatible alias (second console-script entry point), and
`ghafi` remains a PyPI distribution as a thin compatibility shim that depends on
gitculture-cli. The GitHub repo stays agentculture/ghafi (unchanged deployment
target), so repo URLs, the User-Agent, and the eidetic --scope ghafi are kept.

- pyproject: name=gitculture-cli; scripts gitculture + ghafi -> gitculture.cli:main;
  wheel/coverage/isort targets -> gitculture; __version__ from metadata("gitculture-cli")
- internal GhafiError -> GitcultureError, _GhafiArgumentParser -> _GitcultureArgumentParser
- packaging/ghafi/: compat shim metapackage (Requires-Dist: gitculture-cli==<ver>)
- publish.yml: dual-publish both distributions via Trusted Publishing (per-project
  token via filename-scoped uv publish); dev/test job stamps the shim version+pin
- tests.yml + skills + docs updated to gitculture
- version bump 0.4.0 -> 0.5.0

Manual follow-up: register a Trusted Publisher for the new gitculture-cli project
on pypi.org and test.pypi.org (owner agentculture, repo ghafi, workflow
publish.yml, env pypi/testpypi) before the next publish, or the first publish 403s.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UnHGFcsv5bHFqBfPh7vpDE
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Rename ghafi to gitculture-cli with gitculture command and ghafi shim
✨ Enhancement ⚙️ Configuration changes 📝 Documentation 🧪 Tests 🕐 40+ Minutes

Grey Divider

Description

• Rename the import package to gitculture and make gitculture the primary CLI.
• Keep ghafi as a backward-compatible command alias and PyPI shim package.
• Update CI, docs, and tests to publish and validate the renamed distribution.
Diagram

graph TD
U(("User")) --> EP["Console scripts: gitculture/ghafi"] --> PKG["Python package: gitculture"] --> GH["GitHub REST API"]
WF["GitHub Actions: publish.yml"] --> BUILD["Build dist/*"] --> CANON["Dist: gitculture-cli"] --> PYPI[("PyPI projects")]
BUILD --> SHIM["Dist: ghafi shim"] --> DEP["Depends on gitculture-cli==ver"]
SHIM --> PYPI
subgraph Legend
direction LR
_user(("User")) ~~~ _comp["Component"] ~~~ _reg[("Registry")]
end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Rename only the console script (keep distribution name `ghafi`)
  • ➕ Avoids dual-project Trusted Publishing setup and token registration
  • ➕ Simplifies user messaging around PyPI and version pins
  • ➖ Does not achieve the stated distribution rename goal (gitculture-cli)
  • ➖ Leaves mismatch between project identity and PyPI package name
2. Single distribution with transitional release notes (no shim project)
  • ➕ No need to maintain/build/publish a second pyproject and artifact set
  • ➕ Fewer moving parts in CI and release flow
  • ➖ Breaks pip install ghafi users immediately (or forces a longer deprecation window)
  • ➖ Harder to preserve backward compatibility for installers, not just CLI command
3. Ship a real `ghafi` Python package wrapper importing `gitculture`
  • ➕ Keeps import ghafi compatibility for downstream code (if any exists)
  • ➕ Can provide richer deprecation warnings at import time
  • ➖ Adds code and maintenance burden; increases risk of divergence
  • ➖ This repo appears to be primarily a CLI tool, so import-compat is likely unnecessary

Recommendation: The chosen approach (canonical gitculture-cli + ghafi shim + dual entry points) is the most user-friendly for both pip install ghafi and existing shell scripts, while cleanly establishing the new canonical name. The main tradeoff is operational: ensure Trusted Publisher registration exists for BOTH PyPI projects and keep the shim version/pin stamping reliable (which this PR addresses in the workflow).

Files changed (49) +571 / -424

Enhancement (4) +53 / -45
bootstrap.shSwitch bootstrap helper script to invoke gitculture +10/-10

Switch bootstrap helper script to invoke gitculture

• Updates the script to call 'uv run gitculture' instead of 'uv run ghafi' for repo create/scaffold/env steps, keeping the same dry-run/apply flow.

.claude/skills/bootstrap-sibling/scripts/bootstrap.sh

mass-approve-prs.shUse gitculture entry point in mass approval script +16/-16

Use gitculture entry point in mass approval script

• Renames the composed verbs to 'gitculture pr list/approve', updates the default review body signature, and changes binary resolution logic to prefer 'gitculture'.

.claude/skills/mass-approve-prs/scripts/mass-approve-prs.sh

mass-merge-prs.shUse gitculture entry point in mass merge script +21/-19

Use gitculture entry point in mass merge script

• Switches composed commands to 'gitculture pr list/merge' and updates resolution logic to locate 'gitculture' or fall back to 'uv run' from the checkout.

.claude/skills/mass-merge-prs/scripts/mass-merge-prs.sh

__main__.pyAdd python -m gitculture entry point +6/-0

Add python -m gitculture entry point

• Adds a '__main__.py' so 'python -m gitculture' invokes the CLI main function.

gitculture/main.py

Refactor (14) +120 / -119
__init__.pyUpdate package metadata lookup to gitculture-cli distribution +2/-2

Update package metadata lookup to gitculture-cli distribution

• Renames the module docstring and updates '__version__' to read from 'importlib.metadata' for the 'gitculture-cli' distribution name.

gitculture/init.py

_api.pyRename API layer references to GitcultureError and gitculture UA +8/-8

Rename API layer references to GitcultureError and gitculture UA

• Updates imports and exception types to 'GitcultureError' and changes the User-Agent prefix to 'gitculture/<version>' while retaining the repo URL.

gitculture/_api.py

_env.pyRename environment error type to GitcultureError +3/-3

Rename environment error type to GitcultureError

• Updates module documentation and swaps 'GhafiError' usage to 'GitcultureError' for missing token failures.

gitculture/_env.py

__init__.pyRename CLI parser class and program name to gitculture +20/-20

Rename CLI parser class and program name to gitculture

• Renames '_GhafiArgumentParser' to '_GitcultureArgumentParser', sets 'prog' to 'gitculture', and updates error wrapping/catching to use 'GitcultureError'.

gitculture/cli/init.py

__init__.pyAdd command package init for gitculture CLI modules +1/-0

Add command package init for gitculture CLI modules

• Introduces the package docstring for 'gitculture.cli._commands' to match the new import namespace.

gitculture/cli/_commands/init.py

explain.pyRename explain command help/examples to gitculture +6/-6

Rename explain command help/examples to gitculture

• Updates documentation strings and imports so 'explain' references 'gitculture' command paths and resolves via 'gitculture.explain'.

gitculture/cli/_commands/explain.py

learn.pyUpdate learn prompt text and JSON payload tool name +25/-25

Update learn prompt text and JSON payload tool name

• Rebrands the learn text output from ghafi to gitculture and changes the JSON payload 'tool' field accordingly while keeping the same command map and semantics.

gitculture/cli/_commands/learn.py

overview.pyRename overview command docs and error type +10/-10

Rename overview command docs and error type

• Updates module docstrings, imports, and error handling to use 'GitcultureError' and to print gitculture command examples.

gitculture/cli/_commands/overview.py

pr.pyRename pr command docs and exceptions to gitculture +12/-12

Rename pr command docs and exceptions to gitculture

• Switches imports and raised/caught exceptions from 'GhafiError' to 'GitcultureError' and updates docstrings to the new command name.

gitculture/cli/_commands/pr.py

repo.pyRename repo command docs and exceptions to gitculture +14/-14

Rename repo command docs and exceptions to gitculture

• Updates imports and exception types to 'GitcultureError', refreshes help text, and keeps behavior (dry-run default, apply gating, afi invocation) intact.

gitculture/cli/_commands/repo.py

whoami.pyRename whoami command docs to gitculture +4/-4

Rename whoami command docs to gitculture

• Updates module docstrings and imports to the new package name while preserving the GET /user probe behavior and output modes.

gitculture/cli/_commands/whoami.py

_errors.pyRename core error type to GitcultureError +6/-6

Rename core error type to GitcultureError

• Renames 'GhafiError' to 'GitcultureError' and updates documentation to reflect the new package and output module paths.

gitculture/cli/_errors.py

_output.pyUpdate output helpers to accept GitcultureError +4/-4

Update output helpers to accept GitcultureError

• Switches the structured error formatting functions from 'GhafiError' to 'GitcultureError' with no behavioral changes to stdout/stderr discipline.

gitculture/cli/_output.py

__init__.pyUpdate explain resolver to raise GitcultureError +5/-5

Update explain resolver to raise GitcultureError

• Renames imports and exception type from 'GhafiError' to 'GitcultureError' and updates remediation text to point at gitculture commands.

gitculture/explain/init.py

Tests (13) +58 / -54
conftest.pyUpdate test stubs and monkeypatch targets to gitculture +4/-4

Update test stubs and monkeypatch targets to gitculture

• Retargets HTTP and afi stubs to patch 'gitculture' module paths and updates docstrings accordingly.

tests/conftest.py

test_cli_entry.pyUpdate CLI entry tests to import gitculture +3/-3

Update CLI entry tests to import gitculture

• Switches imports to 'gitculture' and updates assertions for help text to include the new 'gitculture' program name.

tests/test_cli_entry.py

test_cli_explain.pyUpdate explain command tests for gitculture output +5/-5

Update explain command tests for gitculture output

• Renames imports and expected strings to match the 'gitculture' CLI and updated explain catalog text.

tests/test_cli_explain.py

test_cli_learn.pyUpdate learn command tests for gitculture JSON/tool name +3/-3

Update learn command tests for gitculture JSON/tool name

• Retargets the tests to 'gitculture.cli' and asserts the JSON payload includes 'tool == "gitculture"'.

tests/test_cli_learn.py

test_cli_overview.pyUpdate overview tests to GitcultureError +4/-4

Update overview tests to GitcultureError

• Updates imports and stubbed error types to 'GitcultureError' while preserving the same coverage of 403 remediation enrichment behavior.

tests/test_cli_overview.py

test_cli_pr.pyUpdate pr tests to GitcultureError and gitculture CLI +7/-5

Update pr tests to GitcultureError and gitculture CLI

• Renames imports and stub error types to 'GitcultureError', keeping the same behavior checks for list/approve/merge paths and error mapping.

tests/test_cli_pr.py

test_cli_repo_create.pyUpdate repo create tests to gitculture and GitcultureError +4/-4

Update repo create tests to gitculture and GitcultureError

• Switches the CLI imports and idempotency error stubs to 'gitculture'/'GitcultureError' without changing the test coverage intent.

tests/test_cli_repo_create.py

test_cli_repo_env.pyUpdate repo env tests to gitculture CLI +2/-2

Update repo env tests to gitculture CLI

• Renames imports to use 'gitculture.cli' while keeping the same behavior coverage for dry-run body generation and branch policy handling.

tests/test_cli_repo_env.py

test_cli_repo_scaffold.pyUpdate repo scaffold tests to gitculture module paths +3/-3

Update repo scaffold tests to gitculture module paths

• Adjusts imports and monkeypatch targets to 'gitculture' module paths to keep scaffolding dry-run/apply behavior coverage intact.

tests/test_cli_repo_scaffold.py

test_cli_whoami.pyUpdate whoami tests to GitcultureError and gitculture CLI +6/-4

Update whoami tests to GitcultureError and gitculture CLI

• Renames imports and stubbed errors to 'GitcultureError' while preserving the exit code and output assertions.

tests/test_cli_whoami.py

test_errors.pyRename error shape tests to GitcultureError +9/-9

Rename error shape tests to GitcultureError

• Updates the error-type tests to instantiate and assert against 'GitcultureError' while keeping the same exit-code and serialization guarantees.

tests/test_errors.py

test_mutation_safety.pyPoint mutation safety tests at gitculture parser and help text +4/-4

Point mutation safety tests at gitculture parser and help text

• Updates imports to 'gitculture.cli' and refreshes assertion messages to reference 'gitculture' for apply-flag enforcement.

tests/test_mutation_safety.py

test_output.pyUpdate output formatting tests to GitcultureError +4/-4

Update output formatting tests to GitcultureError

• Renames imports and test fixtures to use 'GitcultureError' while validating the same stderr formatting and JSON envelope behavior.

tests/test_output.py

Documentation (13) +223 / -176
skills.local.yaml.exampleUpdate skills config example branding to gitculture +1/-1

Update skills config example branding to gitculture

• Adjusts the per-machine skills configuration comment to reference gitculture while keeping the repository location explicit.

.claude/skills.local.yaml.example

SKILL.mdRename bootstrap-sibling skill docs to gitculture commands +11/-11

Rename bootstrap-sibling skill docs to gitculture commands

• Replaces ghafi CLI references with gitculture throughout the skill documentation and updates wording around running from the repo checkout.

.claude/skills/bootstrap-sibling/SKILL.md

SKILL.mdRetarget doc-test-align skill to gitculture module paths +6/-6

Retarget doc-test-align skill to gitculture module paths

• Updates documentation to check drift against 'gitculture/' and the renamed CLI command modules.

.claude/skills/doc-test-align/SKILL.md

SKILL.mdRename mass-approve skill docs to gitculture verbs +15/-15

Rename mass-approve skill docs to gitculture verbs

• Updates the skill narrative and examples to use 'gitculture pr list/approve' and adjusts requirements text accordingly.

.claude/skills/mass-approve-prs/SKILL.md

SKILL.mdRename mass-merge skill docs to gitculture verbs +18/-17

Rename mass-merge skill docs to gitculture verbs

• Updates documentation from 'ghafi pr list/merge' to 'gitculture pr list/merge', including requirement notes and examples.

.claude/skills/mass-merge-prs/SKILL.md

SKILL.mdUpdate PR review skill text for gitculture naming +13/-13

Update PR review skill text for gitculture naming

• Rebrands the workflow guidance from ghafi to gitculture while keeping repo references and portability guidance aligned with the existing repository.

.claude/skills/pr-review/SKILL.md

SKILL.mdUpdate version bump skill doc to reference gitculture package +1/-1

Update version bump skill doc to reference gitculture package

• Adjusts the documentation to match the renamed import package ('gitculture/__init__.py' reading distribution metadata).

.claude/skills/version-bump/SKILL.md

.markdownlint-cli2.yamlRebrand markdownlint config header comment +1/-1

Rebrand markdownlint config header comment

• Updates the comment to reflect gitculture-cli naming while keeping behavior unchanged.

.markdownlint-cli2.yaml

CHANGELOG.mdAdd 0.5.0 entry documenting rename and shim publishing +11/-0

Add 0.5.0 entry documenting rename and shim publishing

• Introduces a new 0.5.0 release entry describing the project rename, dual PyPI publishing model, and backward-compatible CLI alias.

CHANGELOG.md

CLAUDE.mdUpdate project guide for gitculture CLI and dual PyPI projects +46/-37

Update project guide for gitculture CLI and dual PyPI projects

• Rewrites usage and architecture documentation to reflect 'gitculture' as the primary command and 'gitculture-cli' as the canonical distribution. Adds explicit guidance about Trusted Publishing needing separate registrations for 'gitculture-cli' and the 'ghafi' shim while preserving repo-scope naming expectations.

CLAUDE.md

README.mdRebrand README to gitculture-cli with ghafi compatibility note +16/-11

Rebrand README to gitculture-cli with ghafi compatibility note

• Updates install and usage examples to 'gitculture-cli'/'gitculture' and notes that 'pip install ghafi' and the 'ghafi' command remain supported as compatibility paths.

README.md

catalog.pyRebrand explain catalog to gitculture and keep ghafi alias entry +64/-63

Rebrand explain catalog to gitculture and keep ghafi alias entry

• Updates all markdown catalog content to use gitculture examples and adds explicit backward-compatible catalog aliasing for '("ghafi",)' to resolve to the root entry.

gitculture/explain/catalog.py

README.mdAdd shim README explaining ghafi → gitculture-cli rename +20/-0

Add shim README explaining ghafi → gitculture-cli rename

• Documents that 'ghafi' is now a compatibility shim on PyPI and that installing it pulls in the real 'gitculture-cli' tool providing both 'gitculture' and 'ghafi' commands.

packaging/ghafi/README.md

Other (5) +117 / -30
check.shUpdate doc/test drift checker to scan gitculture and parser +6/-6

Update doc/test drift checker to scan gitculture and parser

• Points the source directory to 'gitculture/', updates CLI references in grep checks, and imports '_build_parser' from 'gitculture.cli' for verb introspection.

.claude/skills/doc-test-align/scripts/check.sh

publish.ymlDual-publish gitculture-cli and ghafi shim via Trusted Publishing +58/-11

Dual-publish gitculture-cli and ghafi shim via Trusted Publishing

• Extends the publish workflow to build and publish two distributions: the canonical 'gitculture-cli' and a 'ghafi' compatibility shim. Adds stamping steps to keep the shim version and dependency pin in lockstep with the canonical version, and publishes artifacts with filename-scoped 'uv publish'.

.github/workflows/publish.yml

tests.ymlUpdate CI test/lint targets to gitculture package +5/-5

Update CI test/lint targets to gitculture package

• Switches coverage and lint commands from 'ghafi' to 'gitculture' so CI validates the renamed import package.

.github/workflows/tests.yml

pyproject.tomlAdd ghafi metapackage shim pinned to gitculture-cli version +39/-0

Add ghafi metapackage shim pinned to gitculture-cli version

• Introduces a minimal hatchling project for 'ghafi' that ships no modules and depends on 'gitculture-cli==<version>', with wheel build bypass-selection for metapackage behavior.

packaging/ghafi/pyproject.toml

pyproject.tomlRename canonical distribution to gitculture-cli and add ghafi alias script +9/-8

Rename canonical distribution to gitculture-cli and add ghafi alias script

• Updates project metadata ('name', 'description', version), changes wheel/coverage/isort targets to 'gitculture', and defines two console scripts ('gitculture' and 'ghafi') pointing to 'gitculture.cli:main'.

pyproject.toml

@qodo-code-review

qodo-code-review Bot commented Jun 24, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (1) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. ghafi shim depends on gitculture-cli ✓ Resolved 📘 Rule violation § Compliance
Description
The new ghafi compatibility shim declares a runtime dependency on gitculture-cli, which violates
the requirement that ghafi have no non-stdlib runtime dependencies. This breaks the stdlib-only
runtime compliance posture for the ghafi distribution.
Code

packaging/ghafi/pyproject.toml[31]

+dependencies = ["gitculture-cli==0.5.0"]
Relevance

⭐⭐ Medium

No repo history found about allowing shim package runtime deps vs “stdlib-only” compliance rule.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Compliance ID 423928 prohibits third-party runtime dependencies in ghafi. The added shim
explicitly sets dependencies = ["gitculture-cli==0.5.0"], which is a non-stdlib runtime
dependency.

Rule 423928: Disallow non-stdlib runtime dependencies in ghafi
packaging/ghafi/pyproject.toml[16-32]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`packaging/ghafi/pyproject.toml` introduces a non-stdlib runtime dependency (`gitculture-cli`) for the `ghafi` distribution, which violates the policy that `ghafi` must have no third-party runtime dependencies.
## Issue Context
This PR introduces a compatibility shim package `ghafi` that depends on `gitculture-cli`. To comply, `ghafi` must either ship the actual code itself (no dependency), or the compatibility approach must be revised/removed.
## Fix Focus Areas
- packaging/ghafi/pyproject.toml[16-32]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Breaking rename, minor bump ✓ Resolved 📜 Skill insight ≡ Correctness
Description
This PR makes a breaking change by renaming the import package ghafi to gitculture, but the
version is bumped only from 0.4.0 to 0.5.0 (minor). The compliance policy requires a major
version bump for breaking changes.
Code

pyproject.toml[R2-4]

+name = "gitculture-cli"
+version = "0.5.0"
+description = "gitculture — GitHub Agent First Interface; an AgentCulture manager (the gitculture CLI; formerly ghafi)."
Relevance

⭐⭐ Medium

No historical evidence on enforcing major bump for breaking changes, especially in 0.x semver.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Compliance ID 1210637 requires a major bump when the PR introduces breaking changes.
pyproject.toml sets the new version to 0.5.0 (a minor bump from 0.4.0), while CHANGELOG.md
documents a breaking import rename (ghafigitculture).

pyproject.toml[1-4]
CHANGELOG.md[8-18]
Skill: version-bump: Skill: version-bump: Skill: version-bump: Skill: version-bump

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The PR introduces a breaking change (import package rename `ghafi` → `gitculture`) without a corresponding major version bump.
## Issue Context
The changelog explicitly documents the import rename, which is a breaking change for consumers importing `ghafi`. The compliance policy requires a major bump for breaking changes.
## Fix Focus Areas
- pyproject.toml[1-4]
- CHANGELOG.md[8-18]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Shim stamping may silently fail ✓ Resolved 🐞 Bug ☼ Reliability
Description
The publish workflow rewrites the ghafi shim’s version and dependencies using sed, but never
verifies a substitution occurred; sed can exit 0 even when it made no change, allowing a stale
shim version or wrong gitculture-cli==... pin to be published.
Code

.github/workflows/publish.yml[R60-68]

+      - name: Set dev version and stamp shim
      run: |
        BASE=$(uv run python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
        DEV_VERSION="${BASE}.dev${{ github.run_number }}"
+          # Canonical distribution version.
        sed -i "s/^version = .*/version = \"${DEV_VERSION}\"/" pyproject.toml
+          # Keep the ghafi shim in lockstep (own version + dependency pin).
+          sed -i "s/^version = .*/version = \"${DEV_VERSION}\"/" packaging/ghafi/pyproject.toml
+          sed -i "s/^dependencies = .*/dependencies = [\"gitculture-cli==${DEV_VERSION}\"]/" packaging/ghafi/pyproject.toml
Relevance

⭐⭐ Medium

Repo accepted “fail if substitution didn’t happen” in version-bump script; no CI sed-check precedent
found.

PR-#2

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The workflow performs in-place sed replacements on the shim’s version and dependencies but
includes no post-check; the shim file relies on those exact single-line keys. Because sed does not
fail when no match occurs, the pipeline can publish artifacts with un-stamped (stale) metadata.

.github/workflows/publish.yml[60-88]
.github/workflows/publish.yml[113-134]
packaging/ghafi/pyproject.toml[16-32]
PR-#2

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The workflow stamps `packaging/ghafi/pyproject.toml` via `sed -i`, but does not validate that the expected lines were actually updated. If the shim pyproject formatting changes (e.g., multiline arrays, reordered keys, indentation changes), the `sed` patterns can become no-ops while the workflow continues and publishes mismatched metadata.
## Issue Context
This repo intentionally keeps the `ghafi` shim’s version and `gitculture-cli==<ver>` pin in lockstep with the canonical `pyproject.toml` version; a silent stamp failure breaks that contract.
## Fix Focus Areas
- .github/workflows/publish.yml[60-88]
- .github/workflows/publish.yml[113-134]
### Recommended implementation
After each stamping block, add an explicit verification step that fails the job if the exact expected lines are not present.
Example (bash):
- After stamping, `grep -qx` the expected `version = "..."` line and `dependencies = ["gitculture-cli==..."]` line.
- If either check fails, print the current shim `pyproject.toml` to stderr and `exit 2`.
Alternative: replace the `sed` stamping with a small `python` snippet that performs regex substitution and asserts the replacement count is 1 for each key (same pattern as hardening a version-bump script).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

4. bootstrap-sibling uses ../ 📘 Rule violation ✧ Quality
Description
The bootstrap-sibling skill documentation instructs cloning into ../, which is an explicit ..
path traversal outside the repository root. This violates the requirement that skill directories
avoid non-repo-local path references.
Code

.claude/skills/bootstrap-sibling/SKILL.md[R37-38]

Run from the `ghafi` repo root. The script will `git clone` the new repo
-into a sibling path next to ghafi (`../<name>`).
+into a sibling path next to it (`../<name>`).
Relevance

⭐ Low

Exact request to remove ../<name> in this SKILL.md was rejected in PR #3.

PR-#3

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Compliance ID 423932 disallows absolute paths and any relative paths containing .. within skill
directories. The modified documentation line explicitly instructs using ../, which traverses
outside the repo root.

Rule 423932: Validate Claude skill structure and local-only references
.claude/skills/bootstrap-sibling/SKILL.md[35-39]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `bootstrap-sibling` skill documentation includes a path with `..` (`../<name>`), which references a location outside the repository root.
## Issue Context
The skills compliance rule requires that paths referenced within `.claude/skills/<name>/` remain repo-local and must not use upward traversal (e.g., `../`).
## Fix Focus Areas
- .claude/skills/bootstrap-sibling/SKILL.md[35-39]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread packaging/ghafi/pyproject.toml Outdated
Comment thread pyproject.toml
… repo-rename slug updates

Addresses Qodo review on PR #14:

- Version 0.4.0 -> 1.0.0 (major bump for the breaking rename, per policy);
  classifier Alpha -> Beta.
- Replace the `ghafi` shim metapackage with a full dual-publish: build the same
  zero-dependency code twice with the distribution name overridden to `ghafi`
  at build time, so `pip install ghafi` installs the real tool and the `ghafi`
  distribution carries NO runtime dependencies (removes packaging/ghafi/).
  Resolves the "ghafi has no non-stdlib runtime dependencies" rule.
- __init__.py now resolves __version__ from whichever distribution is installed
  (gitculture-cli or ghafi) — fixes `0.0.0+local` when installed via `pip
  install ghafi`.
- GitHub repo was renamed agentculture/ghafi -> agentculture/gitculture-cli:
  update Homepage/Issues URLs, the User-Agent header, the bug-report link, the
  pr-review skill, the workspace path, and the Trusted-Publishing instructions.
- CHANGELOG/README/CLAUDE.md rewritten to describe the full dual-publish (both
  names are full zero-dep distributions, not a shim).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UnHGFcsv5bHFqBfPh7vpDE
@OriNachum OriNachum merged commit a879706 into main Jun 24, 2026
7 checks passed
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