Skip to content

fix: route help command through kernel registry instead of hardcoded list#58

Merged
AkshajSinghal merged 5 commits into
TruFoundation:mainfrom
ekowi:fix/help-uses-kernel-registry
Jun 9, 2026
Merged

fix: route help command through kernel registry instead of hardcoded list#58
AkshajSinghal merged 5 commits into
TruFoundation:mainfrom
ekowi:fix/help-uses-kernel-registry

Conversation

@ekowi

@ekowi ekowi commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

What

Removes the hardcoded help handler in _handle_local_command() so the
help command is dispatched by TruKernel to run_help(), which reads
the live registry dynamically.

Why

The old handler returned a static string that omitted plugin-registered
commands (e.g. gstatus) and would go stale as new commands were added.

Changes

  • trushell/cli.py: removed hardcoded help block from _handle_local_command
  • tests/test_help_docs.py: added 2 new tests + fixed 1 pre-existing broken test

Tests

All 3 tests in test_help_docs.py pass. No regressions introduced.

Closes #49

Summary by CodeRabbit

  • Bug Fixes

    • Help now lists all registered commands via the kernel’s help path; local handling no longer intercepts "help"
    • CLI invocation normalization improved for consistent command parsing
  • Tests

    • Added tests covering help behavior and command registration
    • Skipped flaky CSV view and navigation tests on Windows to stabilize CI
  • Chores

    • CI publishing workflow updated for release-based PyPI publishing

@AkshajSinghal

AkshajSinghal commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

Nice work @ekowi. The in-memory DB and mocked APIs make the tests actually usable.

Just two quick things: skip the emoji tests on Windows so CI doesn’t red-ball, and let’s merge this into python-ci.yml instead of having a separate file. Keep it clean.

Fix that and it's good to go!

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bc282c6b-4b33-439a-89bd-d1d07596c818

📥 Commits

Reviewing files that changed from the base of the PR and between d0fb96e and 366fbe3.

📒 Files selected for processing (2)
  • tests/test_data.py
  • tests/test_nav.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/test_data.py
  • tests/test_nav.py

📝 Walkthrough

Walkthrough

Remove local help interception so kernel help is used, normalize only the first CLI token to lowercase, skip flaky tests on Windows, and add a release-gated PyPI publish job in the python-ci workflow.

Changes

Help Command Delegation to Kernel

Layer / File(s) Summary
CLI help delegation and argument normalization
trushell/cli.py
Lowercase only sys.argv[1] before execution and removed the _handle_local_command() branch for help, so help returns "unhandled" and falls through to kernel handling.
Help command registry coverage tests
tests/test_help_docs.py
Extended mocked kernel with an _import_module importer; added tests checking run_help("") lists registry commands (including plugin commands) and _handle_local_command("help", ...) returns "unhandled".

Windows Platform Test Skipping

Layer / File(s) Summary
CSV view tests Windows skip
tests/test_data.py
Imported sys and pytest; decorated CSV view tests (test_run_csv_view_empty_file, test_run_csv_view_shows_limited_rows, test_run_csv_view_short_rows_are_padded) with pytest.mark.skipif(sys.platform == "win32", ...).
Navigation test Windows skip
tests/test_nav.py
Imported sys and pytest; decorated test_run_jump_multiple_matches with pytest.mark.skipif(sys.platform == "win32", ...).

CI Workflow PyPI Publishing Consolidation

Layer / File(s) Summary
PyPI publish job in python-ci.yml
.github/workflows/python-ci.yml
Added pypi-publish job that triggers on release published events, uses pypi environment with id-token: write, sets up Python 3.12, builds the package, and publishes to PyPI.

Sequence Diagram

sequenceDiagram
  participant CLI as app_with_lower
  participant Local as _handle_local_command
  participant Kernel as get_kernel()/run_help
  CLI->>Local: call with argv[1] lowercased
  Local->>Kernel: returns "unhandled" for "help"
  CLI->>Kernel: execute_command / run_help("") (kernel lists registry commands)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

A rabbit hops through branches light,
Small fixes here, a CI flight,
Help now calls the kernel true,
Tests skip Windows, builds publish too,
Hooray! 🐇✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes scope-related changes: Windows test skips for CSV and nav tests due to path handling issues, and workflow consolidation (removing workflow.yml, updating python-ci.yml). The workflow consolidation and Windows test skip additions address reviewer feedback but extend beyond the core fix of issue #49. Consider separating workflow changes and test environment fixes into distinct PRs.
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: removing hardcoded help handling to route through kernel registry.
Linked Issues check ✅ Passed The PR successfully addresses issue #49 by removing the hardcoded help handler from _handle_local_command() so help routes through the kernel's run_help() with live registry.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/test_data.py (1)

19-28: ⚠️ Potential issue | 🟠 Major

Fix Windows path handling in run_csv_view instead of skipping the test

tests/test_data.py skips test_run_csv_view_* on win32, but trushell/commands/data.py parses the argument with shlex.split(args or ""). With the default posix=True behavior, unquoted Windows paths like C:\Users\temp\file.csv get mangled (backslashes stripped/treated as escapes), leading to Path(arguments[0]) pointing to a non-existent path—so the skip is masking a real Windows failure.

Update run_csv_view to treat args as a single file path (e.g., strip surrounding quotes and pass directly to Path(...)), or use shlex.split(..., posix=False) only if tokenization is truly required. Then remove the Windows skip (or temporarily pass file_path.as_posix() in the tests to validate behavior while fixing production).

🤖 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 `@tests/test_data.py` around lines 19 - 28, The test skip hides a Windows-only
bug in run_csv_view: the function currently does shlex.split(args or "") with
default posix=True which mangles unquoted Windows paths; fix run_csv_view in
trushell/commands/data.py by treating the incoming args as a single pathname
(e.g., trim surrounding quotes and pass directly to Path) or, if you really need
tokenization, call shlex.split(args or "", posix=False) so backslashes are
preserved; update the code path that builds Path(arguments[0]) to use the
corrected parsing logic (function run_csv_view) so Windows paths resolve
correctly and then remove the platform skip in tests.
🧹 Nitpick comments (1)
tests/test_nav.py (1)

27-39: ⚡ Quick win

Consider whether path normalization could avoid the skip.

The skip is reasonable for CI stability, but the underlying issue is that str(first) and str(second) (with Windows backslashes) may not match the paths as rendered in Rich's exported text due to escaping differences.

If you want to enable the test on Windows in the future, consider normalizing paths before comparison (e.g., converting both to POSIX format or using a regex pattern that accepts both forward and back slashes).

💡 Potential future enhancement to enable Windows testing
 def test_run_jump_multiple_matches(tmp_path, monkeypatch):
     first = tmp_path / "src"
     first.mkdir()
     second = tmp_path / "my_src"
     second.mkdir()
     (tmp_path / "docs").mkdir()
     monkeypatch.chdir(tmp_path)
 
     result = run_jump("src")
     assert "Multiple matches found. Please be more specific." in result
-    assert str(first) in result
-    assert str(second) in result
+    # Normalize paths for cross-platform comparison
+    assert first.as_posix() in result.replace("\\", "/")
+    assert second.as_posix() in result.replace("\\", "/")
🤖 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 `@tests/test_nav.py` around lines 27 - 39, Normalize the paths produced by
run_jump and the expected paths in the test_run_jump_multiple_matches assertion
so Windows backslashes don't break the comparison: update the test to compare
normalized forms (e.g., use first.as_posix()/second.as_posix() or apply
.replace("\\", "/") to both the result and expected strings) or normalize the
result from run_jump before asserting; reference the test name
test_run_jump_multiple_matches and the run_jump call along with variables first
and second when making the change.
🤖 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 @.github/workflows/python-ci.yml:
- Around line 57-71: Replace floating action refs with pinned commit SHAs for
actions/checkout, actions/setup-python, and pypa/gh-action-pypi-publish used in
the Publish to PyPI job; specifically update the checkout step (currently using
actions/checkout@v4) to include persist-credentials: false and point to the
official v4 commit SHA, and pin actions/setup-python@v5 and
pypa/gh-action-pypi-publish@release/v1 to their respective commit SHAs so the
Build package and Publish to PyPI steps use immutable action references.
- Around line 45-49: The workflow currently never triggers releases, so update
the workflow triggers to include a release event that allows the pypi-publish
job to run; specifically add an on: release: types: [published] (or include
release alongside existing push/pull_request) so the job guarded by if:
github.event_name == 'release' && github.event.action == 'published' and the
pypi-publish job name "pypi-publish" will be executed when a release is
published.

---

Outside diff comments:
In `@tests/test_data.py`:
- Around line 19-28: The test skip hides a Windows-only bug in run_csv_view: the
function currently does shlex.split(args or "") with default posix=True which
mangles unquoted Windows paths; fix run_csv_view in trushell/commands/data.py by
treating the incoming args as a single pathname (e.g., trim surrounding quotes
and pass directly to Path) or, if you really need tokenization, call
shlex.split(args or "", posix=False) so backslashes are preserved; update the
code path that builds Path(arguments[0]) to use the corrected parsing logic
(function run_csv_view) so Windows paths resolve correctly and then remove the
platform skip in tests.

---

Nitpick comments:
In `@tests/test_nav.py`:
- Around line 27-39: Normalize the paths produced by run_jump and the expected
paths in the test_run_jump_multiple_matches assertion so Windows backslashes
don't break the comparison: update the test to compare normalized forms (e.g.,
use first.as_posix()/second.as_posix() or apply .replace("\\", "/") to both the
result and expected strings) or normalize the result from run_jump before
asserting; reference the test name test_run_jump_multiple_matches and the
run_jump call along with variables first and second when making the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 969dc8b0-e2fe-40c7-ac97-233059fd3810

📥 Commits

Reviewing files that changed from the base of the PR and between f448592 and fe510fb.

📒 Files selected for processing (5)
  • .github/workflows/python-ci.yml
  • .github/workflows/workflow.yml
  • tests/test_data.py
  • tests/test_nav.py
  • trushell/cli.py
💤 Files with no reviewable changes (1)
  • .github/workflows/workflow.yml

Comment thread .github/workflows/python-ci.yml Outdated
Comment on lines +57 to +71
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Install build tools
run: python -m pip install --upgrade build

- name: Build package
run: python -m build

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE=".github/workflows/python-ci.yml"
echo "== File: $FILE =="
nl -ba "$FILE" | sed -n '1,140p'

Repository: TruFoundation/TruShell

Length of output: 171


🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE=".github/workflows/python-ci.yml"
echo "== File: $FILE =="
cat -n "$FILE" | sed -n '45,95p'

Repository: TruFoundation/TruShell

Length of output: 968


🌐 Web query:

actions/checkout persist-credentials default value

💡 Result:

The default value for the persist-credentials input in the actions/checkout GitHub Action is true [1][2][3]. When set to true (the default), the action configures the authentication token or SSH key with the local git configuration [1][4]. This allows subsequent steps in your workflow to run authenticated git commands (such as git fetch or git push) automatically [2][5]. The action ensures security by removing these credentials during the post-job cleanup phase [2][5]. If you wish to disable this behavior, you can explicitly set persist-credentials to false [2][4].

Citations:


Pin actions to commit SHAs and disable checkout credential persistence in the PyPI release publish job

  • The publish job uses floating action refs (actions/checkout@v4, actions/setup-python@v5, pypa/gh-action-pypi-publish@release/v1), weakening supply-chain guarantees.
  • actions/checkout@v4 is run without persist-credentials: false (default is true), so checkout auth credentials may persist beyond what the build/publish steps require.
Suggested hardening
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@<full_sha_for_v4>
+        with:
+          persist-credentials: false
@@
-        uses: actions/setup-python@v5
+        uses: actions/setup-python@<full_sha_for_v5>
@@
-        uses: pypa/gh-action-pypi-publish@release/v1
+        uses: pypa/gh-action-pypi-publish@<full_sha_for_release_v1>
🧰 Tools
🪛 zizmor (1.25.2)

[warning] 57-57: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 57-57: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 60-60: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 71-71: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 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 @.github/workflows/python-ci.yml around lines 57 - 71, Replace floating
action refs with pinned commit SHAs for actions/checkout, actions/setup-python,
and pypa/gh-action-pypi-publish used in the Publish to PyPI job; specifically
update the checkout step (currently using actions/checkout@v4) to include
persist-credentials: false and point to the official v4 commit SHA, and pin
actions/setup-python@v5 and pypa/gh-action-pypi-publish@release/v1 to their
respective commit SHAs so the Build package and Publish to PyPI steps use
immutable action references.

Source: Linters/SAST tools

@ekowi ekowi force-pushed the fix/help-uses-kernel-registry branch from fe510fb to 16d31f4 Compare June 9, 2026 01:33

@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

♻️ Duplicate comments (2)
.github/workflows/python-ci.yml (2)

57-71: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Pin actions to commit SHAs and disable credential persistence.

The publish job has supply-chain and credential-hygiene issues:

  • Actions use floating refs (@v4, @v5, @release/v1) instead of pinned commit SHAs.
  • actions/checkout defaults to persist-credentials: true, leaving checkout credentials available to subsequent steps unnecessarily.
🔒 Suggested hardening
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@<commit_sha_for_v4>
+        with:
+          persist-credentials: false

       - name: Set up Python
-        uses: actions/setup-python@v5
+        uses: actions/setup-python@<commit_sha_for_v5>
         with:
           python-version: '3.12'

       - name: Publish to PyPI
-        uses: pypa/gh-action-pypi-publish@release/v1
+        uses: pypa/gh-action-pypi-publish@<commit_sha_for_release_v1>
🤖 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 @.github/workflows/python-ci.yml around lines 57 - 71, Pin the GitHub Actions
references and disable credential persistence: replace floating refs for
actions/checkout, actions/setup-python and pypa/gh-action-pypi-publish with
specific commit SHAs (use the latest verified SHAs) and add persist-credentials:
false to the actions/checkout step to prevent checkout credentials leaking to
subsequent steps; ensure any other action refs in this workflow are similarly
pinned and that publish steps only run with least-privilege credentials.

Source: Linters/SAST tools


3-8: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Add release trigger so the pypi-publish job can execute.

The workflow only triggers on push and pull_request events. The pypi-publish job at line 49 is guarded by if: github.event_name == 'release' && github.event.action == 'published', so it will never run.

🔧 Proposed fix
 on:
   push:
     branches: [main]
   pull_request:
     branches: [main]
+  release:
+    types: [published]

Then simplify the job condition:

-    if: github.event_name == 'release' && github.event.action == 'published'
+    if: github.event_name == 'release'
🤖 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 @.github/workflows/python-ci.yml around lines 3 - 8, The workflow only
triggers on push/pull_request so the pypi-publish job never runs; update the
workflow's top-level on: to include a release trigger (e.g., add release: with
types: [published]) so GitHub will fire on published releases, then simplify the
pypi-publish job's guard (the job named pypi-publish) to rely on
github.event_name == 'release' (or remove the redundant action check) so the job
executes when a release is published.
🧹 Nitpick comments (1)
trushell/cli.py (1)

37-37: 💤 Low value

Consider using spread syntax for cleaner list construction.

The list concatenation [first] + rest can be simplified using spread syntax [first, *rest].

♻️ Proposed refactor
-            raw = " ".join([first] + rest)
+            raw = " ".join([first, *rest])
🤖 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 `@trushell/cli.py` at line 37, Replace the list concatenation used to build the
raw command string in trushell/cli.py: instead of constructing the list with
[first] + rest (where first and rest are the parsed command parts) use Python's
unpacking syntax [first, *rest] to produce a cleaner, more idiomatic list before
joining into raw; update the expression that sets the variable raw to build the
list with unpacking and leave the surrounding join logic unchanged.
🤖 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 `@tests/test_data.py`:
- Around line 49-70: The test's skip reason is incorrect and its padding
assertion is fragile; update the skip reason for
test_run_csv_view_short_rows_are_padded to reflect that Windows path formatting
is not the reason (or remove the skip if irrelevant), and replace the loose
assert "  " in output with a deterministic check that run_csv_view output
contains three columns per row (i.e., the short second row was padded to 3
cells) — for example, inspect the table row string(s) produced by run_csv_view
and assert the presence of an explicit empty/padded cell in the third column or
assert the expected number of column separators so the test directly verifies
padding implemented in data.run_csv_view (refer to run_csv_view and the padding
behavior in data.py lines ~61-64).
- Line 19: Update the skip reason on the pytest.mark.skipif in
tests/test_data.py to accurately describe the failure: explain that run_csv_view
uses shlex.split which mangles Windows backslash paths (e.g., C:\tmp\file ->
C:tmpfile), causing Path(...).exists() to fail and tests (like those asserting
rendered output in run_csv_view) to report "File '...' not found." rather than
the expected warning/table; reference run_csv_view and the related tests (e.g.,
test_run_csv_view_file_not_found / other run_csv_view assertions) in the reason
string so it's clear why the tests are skipped on Windows.

---

Duplicate comments:
In @.github/workflows/python-ci.yml:
- Around line 57-71: Pin the GitHub Actions references and disable credential
persistence: replace floating refs for actions/checkout, actions/setup-python
and pypa/gh-action-pypi-publish with specific commit SHAs (use the latest
verified SHAs) and add persist-credentials: false to the actions/checkout step
to prevent checkout credentials leaking to subsequent steps; ensure any other
action refs in this workflow are similarly pinned and that publish steps only
run with least-privilege credentials.
- Around line 3-8: The workflow only triggers on push/pull_request so the
pypi-publish job never runs; update the workflow's top-level on: to include a
release trigger (e.g., add release: with types: [published]) so GitHub will fire
on published releases, then simplify the pypi-publish job's guard (the job named
pypi-publish) to rely on github.event_name == 'release' (or remove the redundant
action check) so the job executes when a release is published.

---

Nitpick comments:
In `@trushell/cli.py`:
- Line 37: Replace the list concatenation used to build the raw command string
in trushell/cli.py: instead of constructing the list with [first] + rest (where
first and rest are the parsed command parts) use Python's unpacking syntax
[first, *rest] to produce a cleaner, more idiomatic list before joining into
raw; update the expression that sets the variable raw to build the list with
unpacking and leave the surrounding join logic unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f3c87c56-2bed-4da5-8a88-90ec62424199

📥 Commits

Reviewing files that changed from the base of the PR and between fe510fb and 16d31f4.

📒 Files selected for processing (6)
  • .github/workflows/python-ci.yml
  • .github/workflows/workflow.yml
  • tests/test_data.py
  • tests/test_help_docs.py
  • tests/test_nav.py
  • trushell/cli.py
💤 Files with no reviewable changes (1)
  • .github/workflows/workflow.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/test_help_docs.py

@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.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 2

♻️ Duplicate comments (2)
.github/workflows/python-ci.yml (2)

57-71: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Pin actions to commit SHAs and disable credential persistence.

The publish job has supply-chain and credential-hygiene issues:

  • Actions use floating refs (@v4, @v5, @release/v1) instead of pinned commit SHAs.
  • actions/checkout defaults to persist-credentials: true, leaving checkout credentials available to subsequent steps unnecessarily.
🔒 Suggested hardening
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@<commit_sha_for_v4>
+        with:
+          persist-credentials: false

       - name: Set up Python
-        uses: actions/setup-python@v5
+        uses: actions/setup-python@<commit_sha_for_v5>
         with:
           python-version: '3.12'

       - name: Publish to PyPI
-        uses: pypa/gh-action-pypi-publish@release/v1
+        uses: pypa/gh-action-pypi-publish@<commit_sha_for_release_v1>
🤖 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 @.github/workflows/python-ci.yml around lines 57 - 71, Pin the GitHub Actions
references and disable credential persistence: replace floating refs for
actions/checkout, actions/setup-python and pypa/gh-action-pypi-publish with
specific commit SHAs (use the latest verified SHAs) and add persist-credentials:
false to the actions/checkout step to prevent checkout credentials leaking to
subsequent steps; ensure any other action refs in this workflow are similarly
pinned and that publish steps only run with least-privilege credentials.

Source: Linters/SAST tools


3-8: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Add release trigger so the pypi-publish job can execute.

The workflow only triggers on push and pull_request events. The pypi-publish job at line 49 is guarded by if: github.event_name == 'release' && github.event.action == 'published', so it will never run.

🔧 Proposed fix
 on:
   push:
     branches: [main]
   pull_request:
     branches: [main]
+  release:
+    types: [published]

Then simplify the job condition:

-    if: github.event_name == 'release' && github.event.action == 'published'
+    if: github.event_name == 'release'
🤖 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 @.github/workflows/python-ci.yml around lines 3 - 8, The workflow only
triggers on push/pull_request so the pypi-publish job never runs; update the
workflow's top-level on: to include a release trigger (e.g., add release: with
types: [published]) so GitHub will fire on published releases, then simplify the
pypi-publish job's guard (the job named pypi-publish) to rely on
github.event_name == 'release' (or remove the redundant action check) so the job
executes when a release is published.
🧹 Nitpick comments (1)
trushell/cli.py (1)

37-37: 💤 Low value

Consider using spread syntax for cleaner list construction.

The list concatenation [first] + rest can be simplified using spread syntax [first, *rest].

♻️ Proposed refactor
-            raw = " ".join([first] + rest)
+            raw = " ".join([first, *rest])
🤖 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 `@trushell/cli.py` at line 37, Replace the list concatenation used to build the
raw command string in trushell/cli.py: instead of constructing the list with
[first] + rest (where first and rest are the parsed command parts) use Python's
unpacking syntax [first, *rest] to produce a cleaner, more idiomatic list before
joining into raw; update the expression that sets the variable raw to build the
list with unpacking and leave the surrounding join logic unchanged.
🤖 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 `@tests/test_data.py`:
- Around line 49-70: The test's skip reason is incorrect and its padding
assertion is fragile; update the skip reason for
test_run_csv_view_short_rows_are_padded to reflect that Windows path formatting
is not the reason (or remove the skip if irrelevant), and replace the loose
assert "  " in output with a deterministic check that run_csv_view output
contains three columns per row (i.e., the short second row was padded to 3
cells) — for example, inspect the table row string(s) produced by run_csv_view
and assert the presence of an explicit empty/padded cell in the third column or
assert the expected number of column separators so the test directly verifies
padding implemented in data.run_csv_view (refer to run_csv_view and the padding
behavior in data.py lines ~61-64).
- Line 19: Update the skip reason on the pytest.mark.skipif in
tests/test_data.py to accurately describe the failure: explain that run_csv_view
uses shlex.split which mangles Windows backslash paths (e.g., C:\tmp\file ->
C:tmpfile), causing Path(...).exists() to fail and tests (like those asserting
rendered output in run_csv_view) to report "File '...' not found." rather than
the expected warning/table; reference run_csv_view and the related tests (e.g.,
test_run_csv_view_file_not_found / other run_csv_view assertions) in the reason
string so it's clear why the tests are skipped on Windows.

---

Duplicate comments:
In @.github/workflows/python-ci.yml:
- Around line 57-71: Pin the GitHub Actions references and disable credential
persistence: replace floating refs for actions/checkout, actions/setup-python
and pypa/gh-action-pypi-publish with specific commit SHAs (use the latest
verified SHAs) and add persist-credentials: false to the actions/checkout step
to prevent checkout credentials leaking to subsequent steps; ensure any other
action refs in this workflow are similarly pinned and that publish steps only
run with least-privilege credentials.
- Around line 3-8: The workflow only triggers on push/pull_request so the
pypi-publish job never runs; update the workflow's top-level on: to include a
release trigger (e.g., add release: with types: [published]) so GitHub will fire
on published releases, then simplify the pypi-publish job's guard (the job named
pypi-publish) to rely on github.event_name == 'release' (or remove the redundant
action check) so the job executes when a release is published.

---

Nitpick comments:
In `@trushell/cli.py`:
- Line 37: Replace the list concatenation used to build the raw command string
in trushell/cli.py: instead of constructing the list with [first] + rest (where
first and rest are the parsed command parts) use Python's unpacking syntax
[first, *rest] to produce a cleaner, more idiomatic list before joining into
raw; update the expression that sets the variable raw to build the list with
unpacking and leave the surrounding join logic unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f3c87c56-2bed-4da5-8a88-90ec62424199

📥 Commits

Reviewing files that changed from the base of the PR and between fe510fb and 16d31f4.

📒 Files selected for processing (6)
  • .github/workflows/python-ci.yml
  • .github/workflows/workflow.yml
  • tests/test_data.py
  • tests/test_help_docs.py
  • tests/test_nav.py
  • trushell/cli.py
💤 Files with no reviewable changes (1)
  • .github/workflows/workflow.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/test_help_docs.py
🛑 Comments failed to post (2)
tests/test_data.py (2)

19-19: ⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check if there are CI logs or issues documenting the Windows failures for these specific tests.

# Search for Windows-related test failure documentation
rg -i -C 3 "test_run_csv_view.*windows|windows.*test_run_csv_view" --type md

# Check for any existing CI configuration mentioning Windows
fd -e yml -e yaml . .github/workflows --exec rg -l "windows|win32" {}

Repository: TruFoundation/TruShell

Length of output: 48


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the test file around the skipped tests
echo "=== tests/test_data.py (lines 1-120) ==="
nl -ba tests/test_data.py | sed -n '1,120p'

echo
echo "=== Find skip reason string occurrences ==="
rg -n "Windows path formatting breaks tmp_path assertions" -S . || true

echo
echo "=== Find win32 usage ==="
rg -n "win32" tests -S || true
rg -n "sys\.platform\s*==\s*[\"']win32[\"']" -S . || true

echo
echo "=== Look for tmp_path assertions in these tests ==="
rg -n "tmp_path" tests/test_data.py -n || true
rg -n "assert.*path|path.*assert|os\.path|Path\(" tests/test_data.py -S || true

echo
echo "=== Check GitHub workflows for windows runners ==="
fd -e yml -e yaml . .github/workflows | head -n 50
fd -e yml -e yaml . .github/workflows --exec rg -n "windows|win32" {} || true

Repository: TruFoundation/TruShell

Length of output: 168


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== tests/test_data.py (lines 1-120) ==="
cat -n tests/test_data.py | sed -n '1,120p'

echo
echo "=== Find skip reason string occurrences ==="
rg -n "Windows path formatting breaks tmp_path assertions" -S . || true

echo
echo "=== Find win32 usage ==="
rg -n "win32" tests -S || true
rg -n 'sys\.platform\s*==\s*["'\'']win32["'\'']' -S . || true

echo
echo "=== Look for tmp_path/path assertions in tests/test_data.py ==="
rg -n "tmp_path" tests/test_data.py -S || true
rg -n "assert.*path|path.*assert|os\.path|Path\(" tests/test_data.py -S || true

echo
echo "=== Check GitHub workflows for windows runners ==="
fd -e yml -e yaml . .github/workflows | head -n 100
fd -e yml -e yaml . .github/workflows --exec rg -n "windows|win32" {} || true

Repository: TruFoundation/TruShell

Length of output: 5586


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Locate run_csv_view implementation ==="
fd -t f "data.py" trushell tests || true
# Find function definition
rg -n "def run_csv_view" -S trushell || true
rg -n "run_csv_view\(" -S trushell | head -n 50

echo
echo "=== Show surrounding code for run_csv_view ==="
# Pick the most likely file discovered above; fallback to a search for 'run_csv_view' file(s)
files=$(rg -l "def run_csv_view" -S trushell || true)
echo "Files: $files"
for f in $files; do
  echo "--- $f ---"
  # show function body area (first ~120 lines from match)
  awk 'NR>=FNR{ }' /dev/null
  # Use sed around the first match line
  ln=$(rg -n "def run_csv_view" -S "$f" | head -n1 | cut -d: -f1)
  start=$((ln-5)); end=$((ln+160))
  sed -n "${start},${end}p" "$f"
done

echo
echo "=== Open .github/workflows/python-ci.yml ==="
if [ -f .github/workflows/python-ci.yml ]; then
  sed -n '1,220p' .github/workflows/python-ci.yml | cat -n
else
  echo "python-ci.yml not found"
fi

echo
echo "=== Search for windows in workflow ==="
rg -n "windows|win32" .github/workflows/python-ci.yml || true

Repository: TruFoundation/TruShell

Length of output: 5052


🏁 Script executed:

python3 - <<'PY'
import shlex
samples = [
    r"C:\tmp\empty.csv",
    r"C:\Users\me\test\users.csv",
    r"\\server\share\file.csv",
    r"C:\t\u\empty.csv",
]
for s in samples:
    print("INPUT:", s)
    try:
        print("SPLIT:", shlex.split(s))
    except Exception as e:
        print("ERROR:", e)
    print("-"*40)
PY

Repository: TruFoundation/TruShell

Length of output: 461


🏁 Script executed:

#!/bin/bash
set -euo pipefail
cat -n tests/test_nav.py | sed -n '1,120p'

Repository: TruFoundation/TruShell

Length of output: 1783


Fix the Windows skip reason text in tests/test_data.py

  • The skipped tests don’t assert on tmp_path formatting; they only assert on run_csv_view’s rendered output (e.g., “Warning: File is empty.” / headers/rows).
  • The likely Windows failure is that run_csv_view() calls shlex.split(args), which mangles Windows backslash paths (e.g., C:\tmp\empty.csv becomes C:tmpempty.csv), so Path(...).exists() fails and the output becomes “File '...' not found.” instead of the expected warning/table.
  • test_run_csv_view_file_not_found isn’t skipped because it passes a simple relative filename (missing_file.csv) without Windows separators.
🤖 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 `@tests/test_data.py` at line 19, Update the skip reason on the
pytest.mark.skipif in tests/test_data.py to accurately describe the failure:
explain that run_csv_view uses shlex.split which mangles Windows backslash paths
(e.g., C:\tmp\file -> C:tmpfile), causing Path(...).exists() to fail and tests
(like those asserting rendered output in run_csv_view) to report "File '...' not
found." rather than the expected warning/table; reference run_csv_view and the
related tests (e.g., test_run_csv_view_file_not_found / other run_csv_view
assertions) in the reason string so it's clear why the tests are skipped on
Windows.

49-70: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Verify the skip reason for this test as well.

Like the other skipped tests, test_run_csv_view_short_rows_are_padded does not assert on path formatting—it asserts on CSV content (A, B, C, 1, 3) and whitespace to verify padding. The skip reason "Windows path formatting breaks tmp_path assertions" does not match the actual test logic.

Additionally, the assertion assert " " in output (Line 70) is somewhat fragile because Rich table output naturally contains whitespace for formatting. It doesn't specifically verify that the short row (row 2 with only 2 cells) was padded to 3 cells. However, given that the upstream contract (data.py:61-64) guarantees padding by extending short rows with empty strings, the test should pass if the function works correctly.

🤖 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 `@tests/test_data.py` around lines 49 - 70, The test's skip reason is incorrect
and its padding assertion is fragile; update the skip reason for
test_run_csv_view_short_rows_are_padded to reflect that Windows path formatting
is not the reason (or remove the skip if irrelevant), and replace the loose
assert "  " in output with a deterministic check that run_csv_view output
contains three columns per row (i.e., the short second row was padded to 3
cells) — for example, inspect the table row string(s) produced by run_csv_view
and assert the presence of an explicit empty/padded cell in the third column or
assert the expected number of column separators so the test directly verifies
padding implemented in data.run_csv_view (refer to run_csv_view and the padding
behavior in data.py lines ~61-64).

@ekowi

ekowi commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

Summary of Changes

Core Fix (Issue #49)

Removed the hardcoded help handler in _handle_local_command() inside trushell/cli.py. Previously, typing help returned a static string that was out of sync with the actual command registry — plugin-registered commands like gstatus were never listed. Now help falls through to "unhandled" and is dispatched by TruKernel to run_help() in commands/core.py, which reads the live registry dynamically.

Tests

  • Fixed pre-existing broken test test_run_help_prints_docstring_for_known_command — the fake kernel was missing _import_module, causing it to always fall through to "No detailed help available"
  • Added test_run_help_lists_all_registry_commands — verifies plugin-registered commands appear in help output
  • Added test_handle_local_command_does_not_intercept_help — regression guard against re-introducing the hardcoded handler

Maintainer Feedback

  • Added @pytest.mark.skipif(win32) to 4 tests that fail on Windows due to shlex.split() mangling backslash paths and Rich table rendering escaped paths
  • Merged workflow.yml (PyPI publish) into python-ci.yml and deleted the separate file
  • Added missing release: types: [published] trigger to python-ci.yml so the pypi-publish job can actually run on releases
  • Simplified pypi-publish job condition from github.event_name == 'release' && github.event.action == 'published' to github.event_name == 'release' (redundant since trigger already filters)
  • Corrected Windows skip reason text to accurately describe root cause (shlex.split() backslash mangling / Rich path rendering)

Out of Scope (noted for follow-up)

  • GitHub Actions supply chain hardening (pin to commit SHAs, persist-credentials: false) — pre-existing across the repo

@AkshajSinghal

Copy link
Copy Markdown
Collaborator

Great work @ekowi!

@AkshajSinghal AkshajSinghal merged commit 8425b0b into TruFoundation:main Jun 9, 2026
5 checks passed
@ekowi ekowi deleted the fix/help-uses-kernel-registry branch June 9, 2026 03:57
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.

help command lists only manifest commands, not showtasks / addtask etc.

2 participants