Skip to content

Record Kiro Crew sessions and nest their sub-agents - #1149

Merged
realtonyyoung merged 11 commits into
mainfrom
tonyyoung/ai-3189-kiro-crew-capture
Sep 25, 2026
Merged

realtonyyoung merged 11 commits into
mainfrom
tonyyoung/ai-3189-kiro-crew-capture

Conversation

@realtonyyoung

@realtonyyoung realtonyyoung commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

No GitHub issue — AI-3189 · AI-3190 · AI-3191

What & why

Kiro Crew runs the installed kiro-cli under agent profiles it regenerates at every start, keeping only ~/.kiro/hooks/*.sh as user hooks and reading skills only from ~/.kiro/crew/skills, so no Crew session reached Capacitor. When Crew is present, kcap setup and kcap plugin install --kiro now write an executable ~/.kiro/hooks/kcap-spawn.sh wrapping kcap hook --kiro, and copy kcap's skills into Crew's skills root; plugin remove --kiro undoes both. The Kiro hook and kcap import --kiro also send each session's Crew parent and children, joined from Crew's sub-agent records, session map and each Kiro session's creation time, so the server can nest sub-agents (server half: kurrent-io/kcap-server#2056).

Where to look

Crew writes a sub-agent's session id about a second after its first prompt, so the hook waits up to 1.5 s for it, but only when KIROCREW_SPAWNED=1 (Crew sets it on every kiro-cli it launches). A plain Kiro session never waits. A hook script kcap did not write is never overwritten or deleted, and the upgrade-time refresh never restores a hook or skills the user deleted.

Verification

  • Live, against Kiro Crew and kiro-cli 2.24.0: after a Crew restart its profiles carry the agentSpawn hook, and a chat and its sub-agent each appeared in Capacitor.
  • Published NativeAOT binary, run against Crew fixtures and a local capture server: the chat's hook sent subagent_session_ids naming its child, and the child's hook sent parent_session_id.
  • Tests:
    • the installed script runs with a PATH lacking kcap and with a hostile install directory, which is not executed;
    • a chat that moved sessions resolves to the session current at spawn;
    • importing a chat with 65 sub-agents names all 65 across two session-starts.

🤖 Generated with Claude Code

realtonyyoung and others added 2 commits September 24, 2026 15:00
Crew rebuilds its agent profiles at every gateway start and keeps only
~/.kiro/hooks/*.sh, so kcap.json's hook never reaches a Crew session.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Crew records the child's session id about a second after its first
prompt, and a one-prompt sub-agent fires agentSpawn only once, so the
hook waits briefly for any session Crew has not mapped to a chat.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@linear-code

linear-code Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

AI-3189

AI-3191

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Capture Kiro Crew sessions and nest sub-agents

✨ Enhancement 🐞 Bug fix 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Installs executable Kiro Crew capture hooks and skills through setup and plugin workflows.
• Resolves Crew sub-agent parents for live hooks and historical imports.
• Adds coverage for installation, delayed state, path overrides, and cleanup.
Diagram

graph TD
    A["Setup and Plugin"] -->|install| B["Crew Installer"] -->|writes| C["Spawn Hook"] -->|calls| D["Kiro Hook"] -->|resolves| E["Parent Resolver"] -->|reads| F[("Crew State")]
    G["Kiro Import"] -->|resolves| E
    D -->|posts| H["Capacitor API"]
    G -->|posts| H
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Modify generated Crew profiles
  • ➕ Could reuse Kiro's existing hook configuration directly.
  • ➕ Avoids maintaining a separate shell wrapper.
  • ➖ Crew regenerates profiles on every gateway start.
  • ➖ Depends on internal profile formats and loses changes after restarts.
2. Infer parents server-side
  • ➕ Centralizes nesting logic outside the CLI.
  • ➕ Avoids delaying the local hook while Crew writes state.
  • ➖ The server cannot access Crew's local session map and sub-agent records.
  • ➖ Would require additional identifiers or a later reconciliation protocol.
3. Asynchronous parent reconciliation
  • ➕ Removes the bounded wait from the session-start hook.
  • ➕ Could associate children after Crew finishes persisting state.
  • ➖ Requires durable retry state and a new parent-update API.
  • ➖ Introduces temporarily un-nested sessions and more lifecycle complexity.

Recommendation: The PR's approach is preferred: installing into Crew's stable hook and skills locations survives profile regeneration, while local state joins provide the only available parent relationship. The ownership marker, bounded polling budget, graceful malformed-state handling, and symmetric removal keep the workaround controlled; asynchronous reconciliation is only justified if the 1.5-second hook delay becomes operationally significant.

Files changed (21) +900 / -23

Enhancement (8) +362 / -10
KiroCrewHookInstaller.csAdd the owned Kiro Crew hook installer +83/-0

Add the owned Kiro Crew hook installer

• Adds rendering, idempotent installation, executable permissions, ownership detection, and safe removal for the Crew agentSpawn shell wrapper. The generated script falls back to the install-time kcap directory when Crew's PATH cannot resolve it.

src/Capacitor.Cli.Core/Harness/Kiro/KiroCrewHookInstaller.cs

KiroCrewParentResolver.csResolve Crew sub-agent parent sessions +77/-0

Resolve Crew sub-agent parent sessions

• Joins recent Crew sub-agent state or tombstone records with the chat session map. It tolerates missing or malformed files, recognizes current and discarded chat sessions, and prevents self-parenting.

src/Capacitor.Cli.Core/Harness/Kiro/KiroCrewParentResolver.cs

KiroCrewPaths.csModel Kiro Crew filesystem paths +41/-0

Model Kiro Crew filesystem paths

• Defines Crew roots for hooks, skills, sub-agent records, and session mappings. It supports KIROCREW_HOME while retaining Crew's fixed hook location under the user's .kiro directory.

src/Capacitor.Cli.Core/Harness/Kiro/KiroCrewPaths.cs

KiroHarness.csExpose Kiro Crew through the Kiro harness +13/-4

Expose Kiro Crew through the Kiro harness

• Extends the Kiro harness with Crew path resolution and environment override handling. Isolated harness construction keeps Crew state beneath the supplied Kiro root.

src/Capacitor.Cli.Core/Harness/Kiro/KiroHarness.cs

CodingAgentsStep.csInstall Crew hooks and skills during setup +85/-4

Install Crew hooks and skills during setup

• Adds Crew paths, installers, results, and setup handlers to the coding-agents step. Installation respects Kiro hook and skill skip options and reports whether Crew assets changed.

src/Capacitor.Cli/Commands/CodingAgentsStep.cs

PluginCommand.csManage Crew assets in Kiro plugin workflows +51/-1

Manage Crew assets in Kiro plugin workflows

• Installs or refreshes the Crew hook and skills when Crew is present, including installations discovered after the original Kiro setup. Removal deletes only kcap-owned hooks and reports Crew cleanup failures.

src/Capacitor.Cli/Commands/PluginCommand.cs

SetupCommand.csWire Crew paths and installers into setup and imports +8/-1

Wire Crew paths and installers into setup and imports

• Passes detected Crew hook and skills locations into setup, configures the executable hook installer, and supplies Crew state paths to Kiro imports.

src/Capacitor.Cli/Commands/SetupCommand.cs

KiroImportSource.csNest imported Crew sub-agent sessions +4/-0

Nest imported Crew sub-agent sessions

• Accepts Crew path metadata and adds parent_session_id to imported session-start payloads when the imported Kiro session belongs to a Crew sub-agent.

src/Capacitor.Cli/Harness/Kiro/KiroImportSource.cs

Bug fix (1) +32 / -0
KiroHookCommand.csAttach Crew parents to live session starts +32/-0

Attach Crew parents to live session starts

• Resolves and forwards parent_session_id for Crew sub-agents. When Crew has not persisted the child session yet, the hook polls for up to 1.5 seconds while preserving at least half of its remaining processing budget.

src/Capacitor.Cli/Commands/Harness/KiroHookCommand.cs

Tests (11) +502 / -9
KiroCrewHookInstallerTests.csTest Crew hook installation and execution +81/-0

Test Crew hook installation and execution

• Covers event headers, executable permissions, idempotency, ownership-safe removal, PATH fallback, argument forwarding, and unchanged standard input.

test/Capacitor.Cli.Core.Tests.Unit/Harness/Kiro/KiroCrewHookInstallerTests.cs

KiroCrewParentResolverTests.csTest Crew parent-session resolution +87/-0

Test Crew parent-session resolution

• Covers active and finished sub-agents, dashed and dashless identifiers, delayed session records, chat-session detection, self-parent prevention, and malformed state.

test/Capacitor.Cli.Core.Tests.Unit/Harness/Kiro/KiroCrewParentResolverTests.cs

KiroCrewPathsTests.csTest Crew filesystem path resolution +27/-0

Test Crew filesystem path resolution

• Verifies default and overridden Crew roots, the fixed hooks location, relocated skills, and isolated harness behavior.

test/Capacitor.Cli.Core.Tests.Unit/Harness/Kiro/KiroCrewPathsTests.cs

KiroCrewSessionStartParentTests.csVerify live Crew session nesting end to end +122/-0

Verify live Crew session nesting end to end

• Drives the real Kiro hook against representative Crew state and verifies parent_session_id reaches the session-start API. It also covers delayed state persistence, top-level Crew chats, and plain Kiro sessions.

test/Capacitor.Cli.Tests.Integration/KiroCrewSessionStartParentTests.cs

KiroImportSourceImportTests.csProvide Crew paths to Kiro import integration tests +2/-1

Provide Crew paths to Kiro import integration tests

• Updates Kiro import construction for the new Crew-aware dependency while retaining replay no-op coverage.

test/Capacitor.Cli.Tests.Integration/KiroImportSourceImportTests.cs

CodingAgentsStepTests.csTest Crew setup installation behavior +54/-0

Test Crew setup installation behavior

• Verifies setup installs Crew hooks and skills when available, counts the hook as an installed integration, honors hook opt-out, and avoids Crew skills when Crew is absent.

test/Capacitor.Cli.Tests.Unit/Commands/CodingAgentsStepTests.cs

ImportDiscoveryAgeTests.csUpdate Kiro discovery tests for Crew paths +1/-1

Update Kiro discovery tests for Crew paths

• Supplies the new Crew dependency when constructing the Kiro import source for discovery timestamp tests.

test/Capacitor.Cli.Tests.Unit/Commands/ImportDiscoveryAgeTests.cs

ImportVisibilityTests.csUpdate Kiro visibility tests for Crew-aware imports +4/-4

Update Kiro visibility tests for Crew-aware imports

• Passes Crew paths into Kiro import sources across visibility and routed-source test cases.

test/Capacitor.Cli.Tests.Unit/Commands/ImportVisibilityTests.cs

PluginCommandKiroCrewTests.csTest Crew plugin installation, refresh, and removal +120/-0

Test Crew plugin installation, refresh, and removal

• Covers conditional installation, install-time kcap resolution, post-install Crew discovery, preservation of removed Kiro skills during refresh, and symmetric cleanup.

test/Capacitor.Cli.Tests.Unit/Commands/PluginCommandKiroCrewTests.cs

ReplayChildContentCapabilityTests.csUpdate replay capability tests for Crew-aware imports +1/-1

Update replay capability tests for Crew-aware imports

• Provides Crew paths to the Kiro import source used by cross-vendor replay capability tests.

test/Capacitor.Cli.Tests.Unit/Commands/ReplayChildContentCapabilityTests.cs

KiroImportSourceTests.csUpdate Kiro import unit tests for Crew paths +3/-2

Update Kiro import unit tests for Crew paths

• Constructs Kiro import sources with isolated Crew layouts while preserving discovery and session-filter coverage.

test/Capacitor.Cli.Tests.Unit/Harness/Kiro/KiroImportSourceTests.cs

Documentation (1) +4 / -4
AgentsSkillsInstaller.csDocument Kiro Crew as a skills installation target +4/-4

Document Kiro Crew as a skills installation target

• Updates installer documentation to include Crew's dedicated skills root and clarify that shared kcap skills reach all supported vendor-specific locations.

src/Capacitor.Cli.Core/AgentsSkillsInstaller.cs

@qodo-code-review

qodo-code-review Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Crew hook overwrites user scripts ✓ Resolved 🐞 Bug ≡ Correctness
Description
KiroCrewHookInstaller.Install writes its rendered body whenever an existing kcap-spawn.sh
differs, without first checking for kcap's ownership marker. During setup, plugin installation, or
refresh, a user-authored hook at the fixed path is replaced, and subsequent plugin removal deletes
the replacement instead of restoring the original even though removal preserves unowned scripts.
Code

src/Capacitor.Cli.Core/Harness/Kiro/KiroCrewHookInstaller.cs[R51-53]

+            Directory.CreateDirectory(Path.GetDirectoryName(scriptPath)!);
+            File.WriteAllText(scriptPath, body);
+            EnsureExecutable(scriptPath);
Relevance

●●● Strong

Installation overwrites unowned user hooks despite removal explicitly protecting them.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Only an exact byte-for-byte body match avoids the write; every other existing file reaches
File.WriteAllText. By contrast, Remove calls IsInstalled and refuses to delete a file without
the ownership marker, showing that ownership is intended to govern destructive handling but is not
checked before installation overwrites the file.

src/Capacitor.Cli.Core/Harness/Kiro/KiroCrewHookInstaller.cs[30-35]
src/Capacitor.Cli.Core/Harness/Kiro/KiroCrewHookInstaller.cs[44-66]
src/Capacitor.Cli/Commands/PluginCommand.cs[1723-1731]
src/Capacitor.Cli.Core/Harness/Kiro/KiroCrewHookInstaller.cs[44-53]
src/Capacitor.Cli.Core/Harness/Kiro/KiroCrewHookInstaller.cs[61-66]
src/Capacitor.Cli/Commands/SetupCommand.cs[800-803]

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

## Issue description
`KiroCrewHookInstaller.Install` overwrites an existing `kcap-spawn.sh` when its contents differ from the rendered body, even if the file was not created by kcap. This contradicts the ownership protection used during removal and destroys a user's hook during setup, plugin installation, or refresh.

## Fix Focus Areas
- src/Capacitor.Cli.Core/Harness/Kiro/KiroCrewHookInstaller.cs[38-58]
- src/Capacitor.Cli/Commands/CodingAgentsStep.cs[365-380]
- src/Capacitor.Cli/Commands/PluginCommand.cs[1730-1737]

## Recommended Fix
Before creating or replacing the script, check whether an existing file contains the exact kcap ownership marker using `IsInstalled`. If the file exists but is unowned, leave it unchanged and return a distinct collision outcome rather than calling `File.WriteAllText`; update setup and plugin-installation callers to surface an actionable warning for that outcome. Retain the current creation and update behavior only when the script is absent or already carries the kcap ownership marker.

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


2. Crew hook runs injected commands ✓ Resolved 🐞 Bug ⛨ Security
Description
KiroCrewHookInstaller.Render embeds kcapDir in double-quoted shell source while escaping only
literal double quotes, leaving dollar signs, backticks, and backslashes subject to shell
interpretation. When Crew’s original PATH lacks kcap, the fallback evaluates the
installer-resolved directory, so command substitutions execute and the altered value may prevent the
hook from reaching the installed binary.
Code

src/Capacitor.Cli.Core/Harness/Kiro/KiroCrewHookInstaller.cs[R19-21]

+        var fallback = string.IsNullOrEmpty(kcapDir)
+            ? ""
+            : $"command -v kcap >/dev/null 2>&1 || PATH=\"{kcapDir.Replace("\"", "\\\"")}:$PATH\"\n";
Relevance

●●● Strong

Unescaped shell metacharacters create command injection in the generated hook fallback.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Both installation paths resolve kcap from the installer process’s PATH and pass its parent
directory directly to the renderer. The renderer interpolates that directory into a /bin/sh
double-quoted assignment while replacing only double quotes, even though double quotes still permit
command substitution and other interpretation; the existing test confirms that this fallback is
evaluated when Crew’s PATH does not contain kcap, allowing shell-sensitive installation
directory names to reach the generated command unchanged.

src/Capacitor.Cli.Core/Harness/Kiro/KiroCrewHookInstaller.cs[14-27]
src/Capacitor.Cli/Commands/PluginCommand.cs[1723-1731]
src/Capacitor.Cli/Commands/SetupCommand.cs[797-803]
src/Capacitor.Cli.Core/Setup/BinaryProbe.cs[38-76]
test/Capacitor.Cli.Core.Tests.Unit/Harness/Kiro/KiroCrewHookInstallerTests.cs[53-79]
src/Capacitor.Cli.Core/Harness/Kiro/KiroCrewHookInstaller.cs[18-27]
src/Capacitor.Cli/Commands/PluginCommand.cs[1723-1730]
src/Capacitor.Cli/Commands/SetupCommand.cs[800-803]

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 generated POSIX shell wrapper injects the resolved `kcapDir` into a double-quoted `PATH` assignment after escaping only double quotes. Valid directory characters such as dollar signs, backticks, and backslashes can therefore be expanded or interpreted when Crew evaluates the fallback; for example, a directory such as `/tmp/$(command)` can execute `command` and alter the path used to locate `kcap`.

## Fix Focus Areas
- src/Capacitor.Cli.Core/Harness/Kiro/KiroCrewHookInstaller.cs[18-27]
- src/Capacitor.Cli/Commands/PluginCommand.cs[1723-1731]
- test/Capacitor.Cli.Core.Tests.Unit/Harness/Kiro/KiroCrewHookInstallerTests.cs[53-80]

## Recommended Fix
Encode `kcapDir` as a POSIX single-quoted shell literal, escaping embedded single quotes with the standard close-quote, escaped-quote, reopen sequence; alternatively, avoid interpolating a shell path by executing a safely quoted absolute `kcap` path. Add execution tests covering command-substitution syntax, dollar signs, backticks, backslashes, spaces, and quotes in the installation directory, and assert that running the generated script neither executes substituted commands nor fails to launch the installed binary.

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


3. Kiro children remain top-level ✗ Dismissed 🔗 Cross-repo conflict ≡ Correctness
Description
KiroHookCommand and KiroImportSource send parent_session_id, but the pinned kcap-server
request DTO omits that field and its Kiro handler appends only SessionStarted without an adoption
event. When this CLI runs against the current server, the extra field is silently ignored and
one-prompt Crew children receive no later hook retry, so both live and imported sessions remain
unparented.
Code

src/Capacitor.Cli/Commands/Harness/KiroHookCommand.cs[R252-254]

+        if (await ResolveCrewParentAsync(dashedSessionId, budget) is { } parent) {
+            forwarded["parent_session_id"] = parent;
+        }
Relevance

●● Moderate

The client-server contract appears incomplete, but the PR explicitly anticipates a coordinated
server-side change.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The PR adds the parent field to both live and import requests. The pinned server's complete Kiro
request record has no corresponding property, its handler constructs and appends only
SessionStarted, and the existing read-model nesting path requires a separate adoption event.

kcap-cli -> kcap-server
src/Capacitor.Cli/Commands/Harness/KiroHookCommand.cs[252-254]
src/Capacitor.Cli/Harness/Kiro/KiroImportSource.cs[231-240]
External repo: kurrent-io/kcap-server, src/Capacitor.Api.Public.Abstractions/Hooks/KiroSessionStartHook.cs [5-28]
External repo: kurrent-io/kcap-server, src/Capacitor.Api.Public/Hooks/KiroHookHandlers.cs [45-99]
External repo: kurrent-io/kcap-server, src/Capacitor.Server.Services/ReadModels/SessionProjector.cs [125-144]
External repo: kurrent-io/kcap-server, src/Capacitor.Server.Services/ReadModels/SessionProjector.cs [1935-1948]

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 CLI now sends `parent_session_id` to the Kiro session-start endpoint, but the pinned kcap-server neither binds nor processes that field. Release the server-side request and adoption support before or together with this CLI change so successful requests do not lose Crew parent links.

## Fix Focus Areas
- src/Capacitor.Cli/Commands/Harness/KiroHookCommand.cs[252-254]
- src/Capacitor.Cli/Harness/Kiro/KiroImportSource.cs[234-234]
- /cross_repos/kcap-server/src/Capacitor.Api.Public.Abstractions/Hooks/KiroSessionStartHook.cs[5-28]
- /cross_repos/kcap-server/src/Capacitor.Api.Public/Hooks/KiroHookHandlers.cs[45-99]

## Recommended Fix
Add `parent_session_id` to kcap-server's Kiro session-start contract and have the handler append the vendor-neutral subagent-adoption event through the existing adoption writer, with canonicalized child and parent IDs. Deploy that compatible server change before releasing this CLI, or capability-gate the CLI feature until the server advertises support.

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


View high (1)
4. Ordinary prompts incur Crew delays ✓ Resolved 🐞 Bug ➹ Performance
Description
ResolveCrewParentAsync waits up to 1.5 seconds and repeatedly scans Crew records whenever the
session is absent from Crew’s map. Every prompt in an ordinary Kiro session triggers this path when
Crew is installed, delaying hook completion and reducing the budget available for memory retrieval,
posting, and watcher startup.
Code

src/Capacitor.Cli/Commands/Harness/KiroHookCommand.cs[R135-138]

+        if (KiroCrewParentResolver.ParentOf(crew, dashedSessionId) is { } parent) return parent;
+        if (KiroCrewParentResolver.IsChatSession(crew, dashedSessionId)) return null;
+
+        var wait     = TimeSpan.FromTicks(Math.Min(CrewParentWait.Ticks, budget.Remaining.Ticks / 2));
Relevance

●● Moderate

The wait is intentional for delayed Crew records, though repeated scans can materially consume
ordinary hook budget.

PR-#790

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new resolver enters its retry loop for every valid session whenever Crew’s root exists unless
the session is already present in Crew files. Kiro’s agent-spawn event runs on every prompt, and
each retry synchronously enumerates and parses up to 256 sub-agent records before the remaining hook
work can begin.

src/Capacitor.Cli/Commands/Harness/KiroHookCommand.cs[131-145]
src/Capacitor.Cli/Commands/Harness/KiroHookCommand.cs[252-258]
src/Capacitor.Cli.Core/Harness/Kiro/KiroCrewParentResolver.cs[38-57]

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

## Issue description
Ordinary Kiro sessions wait and repeatedly scan Crew state on every prompt whenever the Crew root exists, even though they can never acquire a Crew parent.

## Fix Focus Areas
- src/Capacitor.Cli/Commands/Harness/KiroHookCommand.cs[131-145]
- src/Capacitor.Cli.Core/Harness/Kiro/KiroCrewParentResolver.cs[38-57]

## Recommended Fix
Add a reliable, inexpensive signal that identifies hook invocations originating from Kiro Crew and only perform the delayed parent-resolution loop for those invocations. Ordinary Kiro hooks should bypass the wait immediately, while Crew sub-agents should retain the bounded retry needed for late state writes.

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



Remediation recommended

5. Plugin tests build temp paths directly ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
Env constructs the fake executable path with Path.Combine(BinDir.Path, "kcap") instead of the
injected fixture's PathTo helper. Every plugin test obtaining this environment carries a temporary
path assembled outside the required abstraction.
Code

test/Capacitor.Cli.Tests.Unit/Commands/PluginCommandKiroCrewTests.cs[29]

+            ResolveMcpBinaryPath = () => Path.Combine(BinDir.Path, "kcap")
Relevance

●●● Strong

Recent precedent favors fixture path helpers instead of direct temporary-root path construction.

PR-#935
PR-#685

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 2767472 explicitly requires paths below a TempDir root to use members such as PathTo and
flags direct Path.Combine(tmp.Path, ...). The changed environment factory directly combines
BinDir.Path with the executable name.

Rule 2767472: Use TempDir helper for all temporary filesystem state in tests
test/Capacitor.Cli.Tests.Unit/Commands/PluginCommandKiroCrewTests.cs[14-15]
test/Capacitor.Cli.Tests.Unit/Commands/PluginCommandKiroCrewTests.cs[17-30]

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 plugin test environment constructs a path beneath the injected `TempDir` by combining its raw root path directly.

## Fix Focus Areas
- test/Capacitor.Cli.Tests.Unit/Commands/PluginCommandKiroCrewTests.cs[17-30]

## Recommended Fix
Replace `Path.Combine(BinDir.Path, "kcap")` with `BinDir.PathTo("kcap")` so all paths beneath the temporary fixture use its path helpers.

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


6. Hook tests skip the subprocess limit ✓ Resolved 📘 Rule violation ▣ Testability
Description
Script_reaches_kcap_from_the_install_time_directory_with_stdin_intact starts a real child process,
but KiroCrewHookInstallerTests has no ParallelLimiter<SubprocessLimit> annotation. Under the
suite's concurrent execution, this process runs outside the shared subprocess budget used to control
process-heavy tests.
Code

test/Capacitor.Cli.Core.Tests.Unit/Harness/Kiro/KiroCrewHookInstallerTests.cs[R68-71]

+        var psi = new ProcessStartInfo(Script) { RedirectStandardInput = true, UseShellExecute = false };
+        psi.Environment["PATH"] = "/usr/bin:/bin";
+
+        using var process = Process.Start(psi)!;
Relevance

●●● Strong

Recent precedent requires shared subprocess limiting for tests launching real child processes.

PR-#1102
PR-#977

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 2808212 requires test classes that launch real child processes to use the shared subprocess
limiter. The changed test creates a ProcessStartInfo, calls Process.Start, and waits for that
child while its class lacks the required annotation.

Rule 2808212: Use ParallelLimiter<SubprocessLimit> for test classes running real subprocesses
test/Capacitor.Cli.Core.Tests.Unit/Harness/Kiro/KiroCrewHookInstallerTests.cs[6-7]
test/Capacitor.Cli.Core.Tests.Unit/Harness/Kiro/KiroCrewHookInstallerTests.cs[68-74]

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 new hook installer fixture launches a real shell process without participating in the test suite's shared subprocess concurrency limit.

## Fix Focus Areas
- test/Capacitor.Cli.Core.Tests.Unit/Harness/Kiro/KiroCrewHookInstallerTests.cs[6-7]
- test/Capacitor.Cli.Core.Tests.Unit/Harness/Kiro/KiroCrewHookInstallerTests.cs[68-74]

## Recommended Fix
Annotate `KiroCrewHookInstallerTests` with `[ParallelLimiter<SubprocessLimit>]` so its real child-process test draws from the shared subprocess pool.

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


7. Hook tests bypass temp helpers ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
KiroCrewHookInstallerTests directly creates directories and writes files beneath Tmp instead of
using CreateDir, CreateFile, or CreateExecutable. The user-script and fake-executable cases
therefore bypass the fixture's required filesystem abstraction whenever those tests arrange their
temporary state.
Code

test/Capacitor.Cli.Core.Tests.Unit/Harness/Kiro/KiroCrewHookInstallerTests.cs[R35-36]

+        Directory.CreateDirectory(Path.GetDirectoryName(Script)!);
+        await File.WriteAllTextAsync(Script, "#!/bin/sh\n# event: agentSpawn\necho mine\n");
Relevance

●●● Strong

Recent repository precedent accepts replacing direct temporary filesystem operations with fixture
helpers.

PR-#731
PR-#935

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 2767472 requires all temporary filesystem state under a TempDir to be created through its
helpers. These tests derive paths from Tmp but call Directory.CreateDirectory and
File.WriteAllTextAsync directly.

Rule 2767472: Use TempDir helper for all temporary filesystem state in tests
test/Capacitor.Cli.Core.Tests.Unit/Harness/Kiro/KiroCrewHookInstallerTests.cs[7-9]
test/Capacitor.Cli.Core.Tests.Unit/Harness/Kiro/KiroCrewHookInstallerTests.cs[35-36]
test/Capacitor.Cli.Core.Tests.Unit/Harness/Kiro/KiroCrewHookInstallerTests.cs[59-64]

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 new hook installer tests perform direct directory creation and file writes under the injected `TempDir`, contrary to the required temporary-filesystem helper pattern.

## Fix Focus Areas
- test/Capacitor.Cli.Core.Tests.Unit/Harness/Kiro/KiroCrewHookInstallerTests.cs[35-36]
- test/Capacitor.Cli.Core.Tests.Unit/Harness/Kiro/KiroCrewHookInstallerTests.cs[59-64]

## Recommended Fix
Replace direct `Directory` and `File` setup with `Tmp.CreateDir`, `Tmp.CreateFile`, and `Tmp.CreateExecutable`, retaining `PathTo` only for entries that the code under test must create or that must initially be absent.

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


View medium (3)
8. Kiro Crew setup stays undocumented ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
InstallKiroCrewAsync adds hook and skill installation to plugin install --kiro, while removal
now deletes both, but README.md still describes only the standard Kiro agent integration. Users
following the documented Kiro install and removal commands are not told about the Crew files
created, the restart requirement, or the corresponding cleanup.
Code

src/Capacitor.Cli/Commands/PluginCommand.cs[1699]

+        await InstallKiroCrewAsync(refreshOnly, installSkills: !args.Contains("--skip-kiro-skills"));
Relevance

●●● Strong

Documented Kiro commands gain undocumented Crew files, restart requirements, and removal behavior.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 2270057 requires README updates when an existing documented command gains new user-visible
behavior. The changed install flow invokes Crew setup, while the current Kiro documentation only
describes cloning the default agent, standard Kiro skills, and their removal.

Rule 2270057: Keep CLI documentation in README.md in sync with user-facing CLI changes
src/Capacitor.Cli/Commands/PluginCommand.cs[1699-1699]
src/Capacitor.Cli/Commands/PluginCommand.cs[1723-1741]
README.md[1584-1592]

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 user-facing behavior of `plugin install --kiro`, `plugin remove --kiro`, and setup now includes Kiro Crew hooks and skills, but the relevant README sections still describe only the standard Kiro integration.

## Fix Focus Areas
- README.md[1584-1595]
- src/Capacitor.Cli/Commands/PluginCommand.cs[1699-1742]

## Recommended Fix
Update the README's Kiro CLI documentation to explain when Crew hooks and skills are installed, where they are written, the restart requirement, how skip options apply, and what removal cleans up.

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


9. Parent tests bypass temp helpers ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
SeedSessionMap and SeedSubagent directly create and populate paths that KiroCrewPaths derives
from Tmp.Path. Every parent-resolution test using these seed methods consequently constructs its
temporary Crew state outside the fixture helpers.
Code

test/Capacitor.Cli.Core.Tests.Unit/Harness/Kiro/KiroCrewParentResolverTests.cs[R24-28]

+        var dir = Path.Combine(Crew.SubagentsDir, id);
+        Directory.CreateDirectory(dir);
+        var sessionField = sessionId is null ? "" : $", \"session_id\": \"{sessionId}\"";
+        File.WriteAllText(Path.Combine(dir, file),
+            $"{{\"id\": \"{id}\", \"agent\": \"kirocrew-research\", \"parent_session\": \"{Chat}\", \"status\": \"running\"{sessionField}}}");
Relevance

●●● Strong

Direct filesystem operations under injected temporary roots violate the established fixture-helper
convention.

PR-#731
PR-#935

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 2767472 prohibits direct Directory, File, and Path.Combine operations for state below a
TempDir. Crew is rooted under Tmp.Path, and both seed helpers directly create and write
beneath that root.

Rule 2767472: Use TempDir helper for all temporary filesystem state in tests
test/Capacitor.Cli.Core.Tests.Unit/Harness/Kiro/KiroCrewParentResolverTests.cs[8-14]
test/Capacitor.Cli.Core.Tests.Unit/Harness/Kiro/KiroCrewParentResolverTests.cs[16-28]
src/Capacitor.Cli.Core/Harness/Kiro/KiroCrewPaths.cs[12-14]

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 parent resolver tests create directories and JSON files directly beneath the injected `TempDir` rather than using its creation helpers.

## Fix Focus Areas
- test/Capacitor.Cli.Core.Tests.Unit/Harness/Kiro/KiroCrewParentResolverTests.cs[16-29]
- test/Capacitor.Cli.Core.Tests.Unit/Harness/Kiro/KiroCrewParentResolverTests.cs[80-82]

## Recommended Fix
Express Crew-relative locations as segments beneath `Tmp`, then use `Tmp.CreateDir` and `Tmp.CreateFile` for the session map, sub-agent records, and malformed JSON fixture.

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


10. Older sub-agents lose nesting ✓ Resolved 🐞 Bug ≡ Correctness
Description
FindParentChat searches only the 256 sub-agent directories with the newest directory modification
times, regardless of which historical Kiro session is being imported. Once more records exist,
importing an older child outside that window cannot resolve its still-present parent record and
sends it as an unparented session.
Code

src/Capacitor.Cli.Core/Harness/Kiro/KiroCrewParentResolver.cs[R42-44]

+            dirs = new DirectoryInfo(crew.SubagentsDir).EnumerateDirectories()
+                .OrderByDescending(d => d.LastWriteTimeUtc)
+                .Take(MaxSubagentsScanned)
Relevance

●● Moderate

The bounded scan can miss valid historical parents, but the limit may be an intentional performance
safeguard.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The resolver orders directories by directory mtime and truncates them before examining state.json
or tombstone.json. Both the live hook and historical importer add parent_session_id only when
this resolver succeeds, with no fallback for records excluded by the limit.

src/Capacitor.Cli.Core/Harness/Kiro/KiroCrewParentResolver.cs[38-60]
src/Capacitor.Cli/Harness/Kiro/KiroImportSource.cs[228-236]
src/Capacitor.Cli/Commands/Harness/KiroHookCommand.cs[252-254]

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

## Issue description
Parent resolution truncates the sub-agent directory list before locating the requested session, so older historical sessions cannot be nested after enough sub-agents accumulate.

## Fix Focus Areas
- src/Capacitor.Cli.Core/Harness/Kiro/KiroCrewParentResolver.cs[11-12]
- src/Capacitor.Cli.Core/Harness/Kiro/KiroCrewParentResolver.cs[38-60]
- src/Capacitor.Cli/Harness/Kiro/KiroImportSource.cs[231-236]

## Recommended Fix
Do not apply the recent-record limit to historical parent resolution. Either scan all records during import, maintain a session-ID index, or provide separate bounded live and complete import lookup modes so older children remain resolvable without making the live hook unbounded.

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


Grey Divider

Context sources
✅ Compliance rules (platform): 64 rules
✅ Cross-repo context — repo relationships
  Explored: repo: kurrent-io/kcap-server (sha: f72f7c54) — View relationship
Review mode: 🧠 Deep: This is a broad, behavior-changing integration spanning installers, CLI commands, filesystem discovery, asynchronous hook timing, session-parent resolution, imports, and multiple independent code paths with substantial defect density.

Grey Divider

Tip of the day
💡 Did you know, you can enable the Remediation agent and Qodo fixes findings in a dedicated fix PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread src/Capacitor.Cli/Commands/PluginCommand.cs
Comment thread test/Capacitor.Cli.Core.Tests.Unit/Harness/Kiro/KiroCrewHookInstallerTests.cs Outdated
Comment thread test/Capacitor.Cli.Core.Tests.Unit/Harness/Kiro/KiroCrewParentResolverTests.cs Outdated
Comment thread test/Capacitor.Cli.Tests.Unit/Commands/PluginCommandKiroCrewTests.cs Outdated
Comment thread src/Capacitor.Cli/Commands/Harness/KiroHookCommand.cs Outdated
Comment thread src/Capacitor.Cli.Core/Harness/Kiro/KiroCrewParentResolver.cs Outdated
Comment thread src/Capacitor.Cli.Core/Harness/Kiro/KiroCrewHookInstaller.cs
Comment thread src/Capacitor.Cli.Core/Harness/Kiro/KiroCrewHookInstaller.cs Outdated
Comment thread src/Capacitor.Cli/Commands/Harness/KiroHookCommand.cs
realtonyyoung and others added 9 commits September 24, 2026 15:41
A marker beside the script tells a Crew installed since kcap from a hook
the user deleted, which the npm-upgrade refresh must not bring back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A chat can move to a new Kiro session after spawning a child, so the
parent is the newest mapped session created before the child started.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Crew delivers each child's result to the parent as a new prompt, so the
parent's hook links a one-prompt child recorded before the parent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Assigning strings into a JsonArray throws in the published binary even
though it compiles and passes unit tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Crew sets KIROCREW_SPAWNED on every kiro-cli it runs; without that gate a
plain Kiro session paid the wait on every prompt once Crew was installed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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