Skip to content

refactor: remove dead code and consolidate duplicated extension wiring#24

Merged
ezynda3 merged 8 commits into
masterfrom
audit-cleanup
May 7, 2026
Merged

refactor: remove dead code and consolidate duplicated extension wiring#24
ezynda3 merged 8 commits into
masterfrom
audit-cleanup

Conversation

@ezynda3

@ezynda3 ezynda3 commented May 7, 2026

Copy link
Copy Markdown
Contributor

Description

Read-only audit-driven cleanup of the repository. Removes ~1,300 lines
of unreferenced code, eliminates two long-standing duplication clusters,
and tightens one godoc-level dependency-name leak in the public SDK.
No behavioural change — kit --version / kit --help and the full
test suite (go test -race ./...) produce identical output before and
after.

The audit was scoped to cmd/, internal/, and pkg/kit/. Findings
were verified against go vet, staticcheck -checks=all, and
golang.org/x/tools/cmd/deadcode before any deletion.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactor / cleanup (no behavioural change)

What changed

Dead code removed (3 entire files, ~1,300 lines):

  • internal/models/pool.goProviderPool was never wired into
    kitsetup.SetupAgent or any agent constructor.
  • internal/ui/debug_logger.goCLIDebugLogger was unreachable;
    debug routing goes through internal/tools/buffered_logger.go.
  • internal/ui/tool_approval_input.gotea.Model never instantiated;
    approvals are handled inline in model.go.

Plus targeted deletions in:

  • internal/extensions/subagent.goSpawnSubagent subprocess
    implementation + helpers (production code routes through
    kit.Kit.Subagent in-process). Types stay; they're exposed to
    extensions via Yaegi symbols.
  • internal/extensions/manifest.go — six package-level helpers that
    duplicated *Installer methods. Tests rewritten to exercise the live
    Installer methods, which fixes a latent path-resolution
    inconsistency between manifestPathForScope (hard-coded paths) and
    Installer.manifestPath (respects projectGitRoot).
  • internal/ui/style/enhanced.go, block_renderer.go,
    render/blocks.go, commands/commands.go, style/themes.go,
    style/styles.go, cli.go, message_items.go,
    prompts/loader.go, models/cache_options.go, extensions/installer.go,
    cmd/root.go — individual unused functions and constructors. Each
    has zero non-test references; tests that existed only to exercise the
    dead code were either rewritten to test the live equivalent or
    dropped.

Duplication consolidated:

  • New internal/extbridge/ package — collapses the SDK→extension event
    and subagent translation that was copy-pasted in three places
    (cmd/root.go × 2, internal/acpserver/session.go × 1). Both
    sdkEventToSubagentEvent and the ~35-line SpawnSubagent closure
    now live in one place; SDK event-schema changes only need to be made
    once.
  • New cmd/extension_context.go buildInteractiveExtensionContext
    helper — collapses two near-identical 400-line extensions.Context
    literal expressions in runNormalMode. Each call site now sets only
    the three Print* fields that differ between the startup-buffering
    phase and the runtime-routing phase. cmd/root.go shrank from 2,225
    lines to 1,463 lines. All function fields remain anonymous closure
    literals to preserve the AGENTS.md "function field bug" guarantee
    for Yaegi.

SDK godoc fix:

  • pkg/kit/events.go:151FinishReason* constants no longer mention
    the underlying LLM library by name in their godoc. Per AGENTS.md
    "No Dependency Name Leakage", dependency names must not appear in
    comments on exported SDK symbols.

Verification

  • go build ./... — clean
  • go vet ./... — clean
  • go test -race ./internal/... ./pkg/... ./cmd/... — all packages pass
  • staticcheck -checks=all ./... — clean except for pre-existing
    ST1000/ST1003/ST1020-22 stylistic nits that were already on
    master
  • Smoke-tested kit --version and kit --help — output identical
  • golang.org/x/tools/cmd/deadcode — remaining hits are all public SDK
    surface (pkg/kit/, pkg/extensions/test/) or symbols intentionally
    retained for Yaegi/test-only use; documented in the audit report

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • My changes generate no new warnings (go vet, staticcheck)
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

Additional information

Out of scope for this PR (audit recommended discussion before changing):

  • internal/auth/credentials.go Set*Credentials / validate*
    test-only, but plausibly future SDK exposure. Left untouched.
  • internal/extensions/runner.go normalizeContext — 259-line nil-check
    chain. Refactor risk around the AGENTS.md "function field bug"; left
    for a focused follow-up.
  • cmd/root.go runNormalMode and internal/ui/model.go AppModel.Update
    mega-functions — flagged medium-risk in the audit; out of scope here.
  • pkg/kit/kit.go viper-singleton TODO — genuine architecture work.
  • SDK exposing internal/extensions types in exported signatures — an
    architectural decision; recommend discussing before action.

Files added:

  • cmd/extension_context.go
  • internal/extbridge/extbridge.go
  • .kit/prompts/code-audit.md (the audit prompt itself; harmless local
    asset, can be dropped on request)

Summary by CodeRabbit

Release Notes

  • Refactor
    • Consolidated extension context initialization and session management for improved reliability.
    • Streamlined template loading with internal deduplication of conflicting prompts.
    • Simplified UI rendering components and consolidated block rendering logic.
    • Removed redundant internal APIs and helper functions.

ezynda3 added 6 commits May 7, 2026 12:20
Removes ~600 lines of unreferenced code surfaced by deadcode + manual
audit (none of it reachable from production code paths or test setup):

- internal/models/pool.go: ProviderPool was never wired into kitsetup
  or the agent; the global pool singleton had zero callers.
- internal/ui/debug_logger.go: CLIDebugLogger was unreachable; debug
  routing goes through internal/tools/buffered_logger.go instead.
- internal/ui/tool_approval_input.go: tea.Model never instantiated;
  approvals are handled inline in model.go.
- internal/ui/cli.go: DisplayAssistantMessage / DisplayCancellation /
  GetDebugLogger had zero callers (the *WithModel variant is what
  event_handler.go uses).
- internal/ui/style/enhanced.go: Style{Card,Header,Subheader,Muted,
  Success,Error,Warning,Info} + Create{Separator,ProgressBar} — none
  used. CreateBadge stays (used by model.go).
- internal/ui/style/themes.go: RefreshThemeRegistry — never called.
- internal/ui/block_renderer.go: With{FullWidth,MarginTop,Padding{Left,
  Right},Background,Foreground,Width} — option helpers nobody calls.
- internal/ui/render/blocks.go: UserBlock, ToolBlock — replaced by
  inline rendering elsewhere; the test for UserBlock was rewritten to
  directly exercise HighlightFileTokens (which is what the test really
  cared about).
- internal/ui/commands/commands.go: GetAllCommandNames — no callers.
- internal/ui/message_items.go: NewTextMessageItem,
  NewSystemMessageItem + the entire SystemMessageItem type — model.go
  uses NewStyledMessageItem instead.
- internal/prompts/loader.go: Deduplicate — the loader does dedup
  internally; standalone helper was unused.
- internal/models/cache_options.go: mergeProviderOptions + its
  test-only consumer.
- internal/extensions/installer.go: Installer.GetInstalledPackages —
  intended for a 'kit ext list' command that was never built.
- internal/extensions/manifest.go: saveManifestToScope,
  saveManifestToPath, GetGlobalManifest, GetProjectManifest,
  addEntryToManifest, removeEntryFromManifest — package-level
  duplicates of *Installer methods. Tests rewritten to exercise the
  live Installer methods instead, which fixes a latent path-resolution
  inconsistency between manifestPathForScope and Installer.manifestPath
  (the former hard-coded paths, the latter respects projectGitRoot).
- internal/extensions/subagent.go: SpawnSubagent + helpers
  (generateSubagentID, findKitBinary, subagentJSONOutput). The
  subprocess-spawn implementation is unreachable; production code
  routes through kit.Kit.Subagent (in-process). Types
  (SubagentConfig/Result/Handle/etc.) and the SubagentHandle methods
  remain because they are exposed to extensions via Yaegi symbols and
  the Context.SpawnSubagent field.
- cmd/root.go: LoadConfigWithEnvSubstitution — one-line wrapper around
  kit.LoadConfigWithEnvSubstitution with zero callers.

go test -race ./... passes.
The same ~40-line block — building a kit.SubagentConfig, wrapping
OnEvent through sdkEventToSubagentEvent, calling kitInstance.Subagent,
and translating the SDK result into extensions.SubagentResult — was
copy-pasted three times:

  * cmd/root.go (interactive TUI Context, line 1148)
  * cmd/root.go (post-SessionStart runtime Context, line 1446)
  * internal/acpserver/session.go (ACP server Context, line 154)

A separate sdkEventToSubagentEvent function was duplicated byte-for-byte
between cmd/root.go and internal/acpserver/session.go.

Both are now consolidated in a new internal/extbridge package which is
the only module-internal home that can legitimately import both
pkg/kit/ (the public SDK) and internal/extensions/. cmd/ and
internal/acpserver/ both import it, so SDK-event-to-extension-event
schema changes only have one site to update.

Also fixes pkg/kit/events.go godoc comment that named the underlying
LLM library, per AGENTS.md 'No Dependency Name Leakage' rule for
exported SDK symbols.

go test -race ./... passes.
The previous runNormalMode contained two nearly-identical 400-line
extensions.Context literal expressions:

  * the startup-time literal (cmd/root.go:853-1307) that buffered
    Print* calls into startupExtensionMessages
  * the runtime literal (cmd/root.go:1311-1605) that routed Print*
    through appInstance.PrintFromExtension

Every other field — Compact, SendMultimodalMessage, the four prompt
factories, all 25+ data-access fields, all four bridge phases — was
duplicated byte-for-byte. Maintainers had to remember to update both
copies whenever an extension Context field was added.

cmd/root.go is now 1463 lines (was 2225). The new helper lives in
cmd/extension_context.go (455 lines, mostly the closures verbatim) and
returns an extensions.Context with every field populated except
Print/PrintInfo/PrintError, which each call site sets afterwards to
match its phase. This preserves AGENTS.md's 'function field bug'
guarantee — all assignments remain anonymous closure literals.

Output of 'kit --version' / 'kit --help' unchanged. Full test suite
passes.
The TestUserBlockHighlightsFileTokens test was rewritten to call
HighlightFileTokens directly (UserBlock was deleted in the dead-code
sweep). That left testTypography with no callers, so staticcheck U1000
flagged it.
@mark-iii-labs-huly

Copy link
Copy Markdown

Connected to Huly®: KIT-25

@coderabbitai

coderabbitai Bot commented May 7, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@ezynda3 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 20 minutes and 14 seconds before requesting another review.

To continue reviewing without waiting, purchase usage credits in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7f4af2b2-4aac-4e2c-96ef-8ea9ebf3683d

📥 Commits

Reviewing files that changed from the base of the PR and between 65054fe and 2016570.

📒 Files selected for processing (3)
  • cmd/extension_context.go
  • internal/extensions/installer_test.go
  • internal/ui/render/blocks_test.go
📝 Walkthrough

Walkthrough

This PR refactors extension context wiring by introducing a centralized builder function and subagent spawning bridge; consolidates manifest management from package-level to instance methods; removes a subagent subprocess implementation; and cleans up deprecated UI and configuration loader APIs across multiple files.

Changes

Extension Context & Subagent Spawning Bridge

Layer / File(s) Summary
Subagent Bridge Interface
internal/extbridge/extbridge.go
New bridge package converts between Kit SDK Event types and extension SubagentEvent variants via SDKEventToSubagentEvent; SpawnSubagent wraps extension config into Kit config, translates events, and converts results back to extension types.
Context Builder
cmd/extension_context.go
buildInteractiveExtensionContext assembles a complete extensions.Context with all callbacks wired: printing, editor/widget updates, prompt/overlay flows, subagent spawning via the bridge, tree/skill/template operations, and model resolution.
Extension Context Integration
cmd/root.go, internal/acpserver/session.go
runNormalMode replaces inline context setup with two-phase context building; ACP session delegates subagent spawning to extbridge.SpawnSubagent instead of manual kit.SubagentConfig construction.
Removed Config Loader
cmd/root.go
Exported LoadConfigWithEnvSubstitution wrapper is removed (delegated responsibility no longer needed at exported level).

Manifest & Installer Refactoring

Layer / File(s) Summary
Manifest Persistence Layer
internal/extensions/manifest.go
Unexported helpers for manifest file writing/directory creation (saveManifestToScope, saveManifestToPath) and mutation (addEntryToManifest, removeEntryFromManifest) are removed; loading and lookup remain.
Subagent Implementation Removal
internal/extensions/subagent.go
Subprocess execution logic (JSON output parsing, binary lookup, timeout enforcement, event/output callbacks) removed; imports for bufio, json, exec, strings, atomic removed. Public SpawnSubagent function delegated to bridge.
Installer Instance Methods
internal/extensions/installer.go, internal/extensions/installer_test.go
GetInstalledPackages public method removed; tests refactored to use instance-method APIs (installer.loadManifest, installer.saveManifest, installer.addToManifest, installer.removeFromManifest) instead of package-level helpers.
Manifest Test Fixtures
internal/extensions/installer_test.go
Test cases updated to construct Installer instances with explicit roots and write manifest files directly to disk paths; FindInManifest test invokes path resolver directly.

UI & Configuration API Cleanup

Layer / File(s) Summary
CLI & Debug Logging
internal/ui/cli.go
Removed GetDebugLogger() and DisplayAssistantMessage(message) methods; assistant message rendering now only via DisplayAssistantMessageWithModel(message, modelName).
Command Helpers
internal/ui/commands/commands.go
Removed exported GetAllCommandNames() helper for command completion/validation.
Prompt & Theme APIs
internal/prompts/loader.go, internal/ui/style/themes.go, internal/ui/style/styles.go
Removed Deduplicate function from loader (moved into LoadAll as internal deduplication); removed RefreshThemeRegistry and BaseStyle exported functions. Template collision tracking now internal to LoadAll.
Message & Block Rendering
internal/ui/message_items.go, internal/ui/render/blocks.go, internal/ui/render/blocks_test.go
Removed NewTextMessageItem constructor and SystemMessageItem type; removed ToolBlock rendering function. Test updated to directly test HighlightFileTokens without UserBlock dependency.
Block Rendering Options
internal/ui/block_renderer.go
Removed WithFullWidth() rendering option constructor (full-width behavior remains enforced internally).
Model Caching
internal/models/cache_options.go, internal/models/cache_options_test.go
Removed mergeProviderOptions helper and maps import; removed TestMergeProviderOptions test. Caching logic streamlined to single path.
Style Detection
internal/ui/style/enhanced.go
IsDarkBackground() function relocated/re-organized; functionality preserved, definition moved after DefaultTheme().
Documentation
.kit/prompts/code-audit.md
New read-only audit prompt document defining repository mapping, dead-code hunting, duplication detection, boundary violation checks, refactor opportunities, and structured report format without file modifications.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

This PR involves substantial structural changes across extension context wiring (new builder + bridge), manifest persistence refactoring (package-level to instance methods), removal of subagent subprocess implementation (225 lines), and cleanup of multiple deprecated UI/configuration APIs. The changes span heterogeneous file types and introduce new inter-module dependencies (extbridge bridge), requiring careful verification of control flow, event translation semantics, manifest operation correctness across test cases, and validation that removed APIs are no longer referenced in the codebase.


🐰 A rabbit hops through refactored code with glee,
New bridges span where subagents flow free,
Manifest methods now bundled tight,
UI clutter swept from sight,
The warren runs clean, efficient, and spry! 🌿✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% 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 title accurately describes the main changes: removing dead code and consolidating duplicated extension wiring across the codebase.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch audit-cleanup

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 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: 1

🧹 Nitpick comments (3)
internal/extensions/installer_test.go (1)

348-355: ⚡ Quick win

Prefer t.Setenv over manual os.Setenv/os.Unsetenv.

If the test exits early (panic or t.Fatal before the defer is registered), XDG_DATA_HOME leaks to subsequent tests in the same process. t.Setenv (Go 1.17+) restores automatically on cleanup, even on panic.

♻️ Proposed refactor
-	if err := os.Setenv("XDG_DATA_HOME", tempDir); err != nil {
-		t.Fatalf("Setenv() error = %v", err)
-	}
-	defer func() {
-		if err := os.Unsetenv("XDG_DATA_HOME"); err != nil {
-			t.Logf("Unsetenv() error = %v", err)
-		}
-	}()
+	t.Setenv("XDG_DATA_HOME", tempDir)
🤖 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 `@internal/extensions/installer_test.go` around lines 348 - 355, Replace the
manual os.Setenv/os.Unsetenv pattern in the test with t.Setenv to ensure
automatic cleanup on test failure or panic: instead of calling
os.Setenv("XDG_DATA_HOME", tempDir) and deferring os.Unsetenv, call
t.Setenv("XDG_DATA_HOME", tempDir) (remove the defer block) so the testing
framework restores the environment variable automatically; update the test in
installer_test.go where these calls appear accordingly.
cmd/extension_context.go (1)

219-243: 💤 Low value

Reuse the parsed provider/model instead of parsing twice.

models.ParseModelString(modelString) is called once at line 220 and again at line 228 for the same input. Reusing the first result keeps the two branches consistent and trims an avoidable parse.

♻️ Proposed tweak
-			// Notify TUI so it updates model in status bar.
-			p, m, _ := models.ParseModelString(modelString)
-			appInstance.NotifyModelChanged(p, m)
+			// Notify TUI so it updates model in status bar.
+			newProvider, newModel, _ := models.ParseModelString(modelString)
+			appInstance.NotifyModelChanged(newProvider, newModel)
@@
-			// Update usage tracker with new model info for correct token counting.
-			if usageTracker != nil {
-				newProvider, newModel, _ := models.ParseModelString(modelString)
-				if newProvider != "unknown" && newModel != "unknown" && newProvider != "ollama" {
+			// Update usage tracker with new model info for correct token counting.
+			if usageTracker != nil {
+				if newProvider != "unknown" && newModel != "unknown" && newProvider != "ollama" {
🤖 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 `@cmd/extension_context.go` around lines 219 - 243, The second call to
models.ParseModelString(modelString) is redundant; reuse the previously parsed
values p and m (from p, m, _ := models.ParseModelString(modelString)) when
updating the usage tracker instead of parsing again into newProvider/newModel.
Replace uses of newProvider/newModel with p/m in the usageTracker branch and
keep the Anthropic OAuth check using p (provider) to set isOAuth, then call
usageTracker.UpdateModelInfo(modelInfo, p, isOAuth).
cmd/root.go (1)

845-883: ⚡ Quick win

Avoid building the interactive extension context twice.

The two buildInteractiveExtensionContext calls take identical extensionContextDeps; the only delta is the three Print* fields. Re-running the entire builder right after EmitSessionStart re-allocates every closure for fields you don't change. Just rebind the three print routes and re-set the context.

♻️ Proposed simplification
-		extCtx := buildInteractiveExtensionContext(extensionContextDeps{
-			ctx:          ctx,
-			cwd:          cwd,
-			modelName:    modelName,
-			interactive:  positionalPrompt == "",
-			kitInstance:  kitInstance,
-			appInstance:  appInstance,
-			usageTracker: usageTracker,
-		})
-		extCtx.Print = func(text string) {
-			// Capture messages during startup, print after startup banner.
-			startupExtensionMessages = append(startupExtensionMessages, text)
-		}
-		extCtx.PrintInfo = func(text string) {
-			startupExtensionMessages = append(startupExtensionMessages, text)
-		}
-		extCtx.PrintError = func(text string) {
-			startupExtensionMessages = append(startupExtensionMessages, text)
-		}
-		kitInstance.Extensions().SetContext(extCtx)
-		kitInstance.Extensions().EmitSessionStart()
-
-		// Restore normal print functions for runtime use.
-		extCtx = buildInteractiveExtensionContext(extensionContextDeps{
-			ctx:          ctx,
-			cwd:          cwd,
-			modelName:    modelName,
-			interactive:  positionalPrompt == "",
-			kitInstance:  kitInstance,
-			appInstance:  appInstance,
-			usageTracker: usageTracker,
-		})
-		extCtx.Print = func(text string) { appInstance.PrintFromExtension("", text) }
-		extCtx.PrintInfo = func(text string) { appInstance.PrintFromExtension("info", text) }
-		extCtx.PrintError = func(text string) { appInstance.PrintFromExtension("error", text) }
-		kitInstance.Extensions().SetContext(extCtx)
+		extCtx := buildInteractiveExtensionContext(extensionContextDeps{
+			ctx:          ctx,
+			cwd:          cwd,
+			modelName:    modelName,
+			interactive:  positionalPrompt == "",
+			kitInstance:  kitInstance,
+			appInstance:  appInstance,
+			usageTracker: usageTracker,
+		})
+		// Phase 1: buffer extension prints during SessionStart so they
+		// land after the startup banner.
+		extCtx.Print = func(text string) { startupExtensionMessages = append(startupExtensionMessages, text) }
+		extCtx.PrintInfo = func(text string) { startupExtensionMessages = append(startupExtensionMessages, text) }
+		extCtx.PrintError = func(text string) { startupExtensionMessages = append(startupExtensionMessages, text) }
+		kitInstance.Extensions().SetContext(extCtx)
+		kitInstance.Extensions().EmitSessionStart()
+
+		// Phase 2: route extension prints through the running app.
+		extCtx.Print = func(text string) { appInstance.PrintFromExtension("", text) }
+		extCtx.PrintInfo = func(text string) { appInstance.PrintFromExtension("info", text) }
+		extCtx.PrintError = func(text string) { appInstance.PrintFromExtension("error", text) }
+		kitInstance.Extensions().SetContext(extCtx)
🤖 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 `@cmd/root.go` around lines 845 - 883, The code builds the same extension
context twice with buildInteractiveExtensionContext around EmitSessionStart,
causing unnecessary re-allocation; instead, build extCtx once, set the
startup-print closures (using startupExtensionMessages) before
kitInstance.Extensions().EmitSessionStart(), call SetContext and
EmitSessionStart, then simply rebind extCtx.Print, extCtx.PrintInfo and
extCtx.PrintError to appInstance.PrintFromExtension(...) and call
kitInstance.Extensions().SetContext(extCtx) again—i.e., remove the second
buildInteractiveExtensionContext call and only mutate the three Print* fields on
the existing extCtx.
🤖 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 `@cmd/extension_context.go`:
- Line 50: Several extensions.Context fields are assigned bare method/function
references which must be replaced with anonymous closure literals that forward
arguments; replace assignments like PrintBlock:
appInstance.PrintBlockFromExtension, GetChildren: kitInstance.GetChildren,
GetAvailableSkills: kitInstance.DiscoverSkillsForExtension,
ParseTemplate/RenderTemplate/ParseArguments/SimpleParseArguments,
ResolveModelChain and CheckModelAvailable with func(...) { return
<original>(...) } literals that accept the same parameters and return the same
results so the values crossing the Yaegi boundary (via
kitInstance.Extensions().SetContext(...)) are concrete closures rather than bare
references.

---

Nitpick comments:
In `@cmd/extension_context.go`:
- Around line 219-243: The second call to models.ParseModelString(modelString)
is redundant; reuse the previously parsed values p and m (from p, m, _ :=
models.ParseModelString(modelString)) when updating the usage tracker instead of
parsing again into newProvider/newModel. Replace uses of newProvider/newModel
with p/m in the usageTracker branch and keep the Anthropic OAuth check using p
(provider) to set isOAuth, then call usageTracker.UpdateModelInfo(modelInfo, p,
isOAuth).

In `@cmd/root.go`:
- Around line 845-883: The code builds the same extension context twice with
buildInteractiveExtensionContext around EmitSessionStart, causing unnecessary
re-allocation; instead, build extCtx once, set the startup-print closures (using
startupExtensionMessages) before kitInstance.Extensions().EmitSessionStart(),
call SetContext and EmitSessionStart, then simply rebind extCtx.Print,
extCtx.PrintInfo and extCtx.PrintError to appInstance.PrintFromExtension(...)
and call kitInstance.Extensions().SetContext(extCtx) again—i.e., remove the
second buildInteractiveExtensionContext call and only mutate the three Print*
fields on the existing extCtx.

In `@internal/extensions/installer_test.go`:
- Around line 348-355: Replace the manual os.Setenv/os.Unsetenv pattern in the
test with t.Setenv to ensure automatic cleanup on test failure or panic: instead
of calling os.Setenv("XDG_DATA_HOME", tempDir) and deferring os.Unsetenv, call
t.Setenv("XDG_DATA_HOME", tempDir) (remove the defer block) so the testing
framework restores the environment variable automatically; update the test in
installer_test.go where these calls appear accordingly.
🪄 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

Run ID: 1393a7d6-fab4-42ee-945d-537a6e35f9ec

📥 Commits

Reviewing files that changed from the base of the PR and between 7cf38b3 and 65054fe.

📒 Files selected for processing (25)
  • .kit/prompts/code-audit.md
  • cmd/extension_context.go
  • cmd/root.go
  • internal/acpserver/session.go
  • internal/extbridge/extbridge.go
  • internal/extensions/installer.go
  • internal/extensions/installer_test.go
  • internal/extensions/manifest.go
  • internal/extensions/subagent.go
  • internal/models/cache_options.go
  • internal/models/cache_options_test.go
  • internal/models/pool.go
  • internal/prompts/loader.go
  • internal/ui/block_renderer.go
  • internal/ui/cli.go
  • internal/ui/commands/commands.go
  • internal/ui/debug_logger.go
  • internal/ui/message_items.go
  • internal/ui/render/blocks.go
  • internal/ui/render/blocks_test.go
  • internal/ui/style/enhanced.go
  • internal/ui/style/styles.go
  • internal/ui/style/themes.go
  • internal/ui/tool_approval_input.go
  • pkg/kit/events.go
💤 Files with no reviewable changes (16)
  • internal/models/pool.go
  • internal/ui/debug_logger.go
  • internal/ui/style/enhanced.go
  • internal/models/cache_options_test.go
  • internal/ui/tool_approval_input.go
  • internal/models/cache_options.go
  • internal/prompts/loader.go
  • internal/ui/block_renderer.go
  • internal/ui/commands/commands.go
  • internal/ui/style/styles.go
  • internal/ui/style/themes.go
  • internal/ui/message_items.go
  • internal/extensions/subagent.go
  • internal/extensions/installer.go
  • internal/extensions/manifest.go
  • internal/ui/cli.go

Comment thread cmd/extension_context.go Outdated
ezynda3 added 2 commits May 7, 2026 13:00
Per AGENTS.md 'Yaegi function field bug', named function/method
references assigned to extensions.Context fields return zero values
across the interpreter boundary. The two SetContext literals in
runNormalMode (now consolidated in buildInteractiveExtensionContext)
inherited 9 bare references that need to be anonymous closure literals:

  PrintBlock, GetChildren, GetAvailableSkills, ParseTemplate,
  RenderTemplate, ParseArguments, SimpleParseArguments,
  ResolveModelChain, CheckModelAvailable

Each is now wrapped as 'func(args) ret { return <orig>(args) }'.
Behaviour unchanged in regular Go; Yaegi extensions that consume these
fields will now see callable closures instead of zero values.

Verified with go test -race ./...
Addresses two CodeRabbit feedback items on PR #24:

* Docstring coverage warning (was 57.14%, threshold 80%): adds godoc
  comments to the four test functions added or substantially rewritten
  in this PR — TestLoadAndSaveManifest, TestAddAndRemoveFromManifest,
  TestFindInManifest, TestHighlightFileTokensInjectsANSI.
* Quick-win nitpick: replaces the manual os.Setenv/os.Unsetenv +
  defer pattern in TestFindInManifest with t.Setenv, which restores
  the env var automatically on cleanup even on panic or t.Fatal.

go test -race ./... still passes.
@ezynda3

ezynda3 commented May 7, 2026

Copy link
Copy Markdown
Contributor Author

@CodeRabbit have a quick look please

@coderabbitai

coderabbitai Bot commented May 7, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@ezynda3 Sure! I'll review the changes in PR #24 right away.

[review]

@ezynda3 ezynda3 merged commit c4a2b0f into master May 7, 2026
3 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