Skip to content

feat: add Mistral Vibe external agent plugin#4

Draft
alishakawaguchi wants to merge 9 commits into
mainfrom
mistral-plugin
Draft

feat: add Mistral Vibe external agent plugin#4
alishakawaguchi wants to merge 9 commits into
mainfrom
mistral-plugin

Conversation

@alishakawaguchi

@alishakawaguchi alishakawaguchi commented Mar 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Add Mistral Vibe as an external agent plugin for the Entire CLI, implementing the full agent binary protocol.

  • Research one-pager and verification script for Vibe's hook lifecycle, transcript format, and session storage
  • Implementation spec for lifecycle hooks mapping (Vibe native → Entire protocol)
  • Agent binary (entire-agent-mistral-vibe) with all protocol subcommands: info, detect, get-session-id, get-session-dir, resolve-session-file, read-session, write-session, read-transcript, chunk-transcript, reassemble-transcript, format-resume-command, parse-hook, install-hooks, uninstall-hooks, are-hooks-installed, get-transcript-position, extract-modified-files, extract-prompts, extract-summary
  • Hook installation writes TOML config to .vibe/config.toml and trusts the repo directory via ~/.vibe/trusted_folders.toml
  • Transcript analysis (JSONL): position tracking, file extraction from tool calls, prompt extraction, summary extraction
  • Session persistence: placeholder transcript fallback when Vibe native logs are absent (mirrors Kiro's createPlaceholderTranscript pattern)
  • E2E test harness with transcript builder fixtures, hook payload helpers, and full binary-level coverage
  • Unit tests for all agent methods, hook parsing, transcript analysis, and placeholder creation
  • Fix lifecycle RewindAfterCommit test timing: condition-based polling for condensation instead of single check

Test plan

  • Unit tests: go test ./... — 40/40 pass
  • E2E module vets cleanly: go vet -tags=e2e ./...
  • E2E lifecycle tests: SessionPersistence, RewindAfterCommit (requires full Entire CLI + Vibe binary)
  • Manual: entire enable --agent mistral-vibe in a repo with .vibe/

🤖 Generated with Claude Code

alishakawaguchi and others added 4 commits March 24, 2026 09:46
… script

Analyze Mistral Vibe (v2.6.2) for external agent protocol compatibility.
Key findings: no native hook system, but rich session management via
~/.vibe/logs/session/ with meta.json + messages.jsonl (structured JSONL).
Capabilities: transcript_analyzer=true, token_calculator=true, hooks=false.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 21de3e7235f8
Comprehensive reference for adding lifecycle hooks to Mistral Vibe's
open source codebase. Covers hook config format, payload schemas,
integration points in the agent loop, and how it maps to the Entire
CLI external agent protocol. Designed to be used as a standalone
reference by an implementing agent.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 8b8486ede423
Implement the entire-agent-mistral-vibe binary with full protocol
subcommand support (info, detect, sessions, transcripts, hooks,
transcript analysis). Add 30 E2E tests covering all subcommands
and register Mistral Vibe as an agent for shared lifecycle tests.

Updated AGENT.md to reflect verified lifecycle hooks (session_start,
user_prompt_submit, pre_tool_use, post_tool_use, turn_end) with
captured payloads from real Vibe sessions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 5cdc3adc6a68
- InstallHooks now adds the repo to ~/.vibe/trusted_folders.toml so
  Vibe reads project-level .vibe/config.toml (required for hooks to fire)
- ParseHook turn-end now globs ~/.vibe/logs/session/ to find the actual
  session directory matching the session ID prefix
- Add comprehensive unit tests for agent, hooks, and transcript analysis
  using golden JSONL data from real Vibe session captures

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: e108d2f670de

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

Cursor Bugbot has reviewed your changes and found 3 potential issues.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment @cursor review or bugbot run to trigger another review on this PR

}

return os.WriteFile(configPath, []byte(strings.Join(filteredLines, "\n")), 0o600)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

UninstallHooks leaves orphan TOML table headers in config

High Severity

UninstallHooks only filters lines containing hookMarker ("entire hooks mistral-vibe"), but the TOML section headers like [[hooks.session_start]] don't contain that marker. After filtering, orphan [[hooks.session_start]], [[hooks.user_prompt_submit]], etc. lines remain. The remaining check only handles empty or "[hooks]", so these orphan headers cause the file to be rewritten with invalid leftover TOML instead of being deleted. This leaves .vibe/config.toml in a broken state after uninstall.

Fix in Cursor Fix in Web

content := strings.Join(tomlLines, "\n")
if err := os.WriteFile(configPath, []byte(content), 0o600); err != nil {
return 0, fmt.Errorf("failed to write config.toml: %w", err)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

InstallHooks overwrites existing project config file entirely

High Severity

InstallHooks builds hook TOML lines from scratch and writes them via os.WriteFile, which truncates .vibe/config.toml. Any existing Vibe project-level configuration (model settings, custom tools, other TOML sections) in that file is silently destroyed. The Kiro agent avoids this by writing hooks to separate dedicated files rather than the main config.

Fix in Cursor Fix in Web

return a
}
return b
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unused min function is dead code

Low Severity

The min function in hooks.go is defined but never called anywhere in the codebase. On Go 1.21+ (this project uses Go 1.26), min is a builtin, so this custom definition is dead code that also shadows the builtin.

Fix in Cursor Fix in Web

alishakawaguchi and others added 5 commits March 25, 2026 15:08
…ead min

Extract duplicated session ID fallback above the switch in ParseHook,
simplify redundant sessionRef guard in ReadSession, and remove unused
min helper (builtin in Go 1.21+).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: caf6d3c50a6a
SessionPersistence: ParseHook(turn-end) returned empty SessionRef when
Vibe's native logs were absent (e.g. test envs), so the entire CLI
skipped session writing. Add ensurePlaceholderTranscript() fallback that
creates a {} file at .entire/tmp/{id}.json, matching Kiro's pattern.

RewindAfterCommit: WaitForCheckpoint only waited for checkpoint branch
advancement, but condensation runs async. Replace the single rewind-list
check with condition-based polling (30s) for the shadow point to become
logs-only.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 99e4793da14a
The entire CLI does not call write-session during hook processing.
For Kiro, captureTranscriptForStop copies the transcript into
.entire/tmp/ as a side effect of parse-hook, so a session file exists.

Vibe was returning the native log path (~/.vibe/logs/session/...)
directly as SessionRef — nothing was written to .entire/tmp/.

Add cacheTranscriptForTurnEnd which copies the native Vibe transcript
into .entire/tmp/{sessionID}.json and returns the local path. Falls
back to a {} placeholder when native logs are absent.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: cd955dffa249
Replace magic numbers (1, 2, 3) for event types with named constants
EventTypeSessionStart, EventTypeTurnStart, EventTypeTurnEnd.

Remove unused NativeToProtocolHook map and its test — the mapping was
only tested, never used in production code. Remove unused
VibeSessionMeta and VibeSessionStats types (placeholder definitions
with no consumers).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: d140fbb39172
alishakawaguchi added a commit that referenced this pull request May 7, 2026
* Fix Windows + Kiro IDE bugs in kiro external agent

Addresses entireio/cli#1054. Four user-reported symptoms on Windows + Kiro
IDE were all caused by missing platform branches in the adapter.

- IDE hook command form: emit `cmd /c "<cmd> <NUL"` on Windows so the
  parent `entire` CLI inherits a closed stdin and hook commands stop
  spinning. POSIX still uses `sh -c '<cmd> </dev/null'`. Trusted-commands
  glob and uninstall migration updated to match.
- Native session identity resolved before minting a UUID: `parse-hook`
  now prefers raw payload session/conversation IDs, then the latest IDE
  `sessionId` from `sessions.json`, then the cached Entire ID, then the
  CLI `conversation_id`. The session cache survives across `stop` so
  multi-turn IDE chats stay in one Entire session.
- Windows storage paths added to `kiroDataDir` (`%LOCALAPPDATA%`) and
  `kiroExtensionStorageDir` (`%APPDATA%`).
- Workspace-sessions cwd encoding now lowercases the drive letter and
  converts forward slashes to backslashes before base64, matching what
  Kiro IDE actually writes to disk on Windows.
- CLI conversation lookup no longer shells out to `sqlite3`; uses
  embedded modernc.org/sqlite so Windows installs without sqlite3 on
  PATH still work.
- Hook JSON files no longer HTML-escape `<` and `>` (still valid JSON,
  much more readable when inspecting `.kiro/hooks/*.kiro.hook`).
- `KIRO_DEBUG=1` env gate writes step-by-step capture diagnostics to
  `.entire/tmp/kiro-debug.log` for triaging path-resolution misses on
  user machines.
- Tests cover Windows hook emission, drive-letter and slash
  normalization, sqlite-without-binary fallback, and updated session
  lifecycle assertions (cache no longer cleared on stop).
- AGENT.md documents the new Windows form, the resolver order, the
  cache lifetime change, and the embedded-SQLite shift.
- README adds a backup install path (`entire-agent-kiro install-hooks`)
  and notes the `external_agents: true` setting required for runtime
  discovery.
- docs/investigations/ captures the multi-agent investigation that
  produced the diagnosis and proposed fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: c029e9e70480

* remove docs

* Fix multi-chat transcript miss and session-ID rekey on Kiro IDE

Addresses two issues from adversarial review:

- ensureIDETranscript ignored its session-ID parameter and always read
  the newest entry from sessions.json. In a workspace with multiple Kiro
  chats, a stop event from an older tab would checkpoint the newest
  tab's transcript instead. Fix: take the resolved IDE session ID
  through to the transcript reader and prefer it when the matching file
  exists on disk; fall back to "latest by dateCreated" only when no IDE
  session ID is supplied.
- ParseHook overwrote the cached Entire session ID on every turn with
  whatever resolveHookSessionIdentity returned, which could rekey a
  conversation mid-flight (e.g. when a native Kiro ID only became
  available by stop time) and never populated EventJSON.PreviousSessionID
  for downstream migration. Fix: track the IDE session ID in a separate
  cache file (kiro-active-ide-session) alongside the Entire session ID
  and reuse the cached Entire ID whenever the cached IDE session ID
  still matches the latest one on disk; only rekey when a genuinely new
  Kiro chat is observed, and emit the prior Entire ID via
  PreviousSessionID so consumers can merge / close out the old session.

Resolver result is now a sessionIdentity struct rather than a tuple,
which makes the rekey signal explicit at the call site.

Regression tests:
- TestEnsureIDETranscriptPrefersResolvedIDESessionOverLatest — two
  IDE sessions in one workspace, the resolver-supplied (older) ID wins.
- TestEnsureIDETranscriptFallsBackToLatestWhenIDESessionMissing —
  preserves the prior fallback when no IDE session ID is supplied.
- TestParseHookSessionIDStableAcrossTurnsInSameIDEChat — two prompts
  in the same chat share one Entire session, no PreviousSessionID.
- TestParseHookRekeysAndEmitsPreviousSessionIDOnNewKiroChat — a new
  Kiro chat tab triggers a rekey, second event carries the prior
  Entire session ID in PreviousSessionID.

AGENT.md updated to document the new resolver order and the two-file
session cache.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 369efe4bf134

* Replace global session cache with per-chat keying

Addresses both follow-ups from adversarial review #2:

1. Session resolution was based on repo-global cache files
   (`kiro-active-session` + `kiro-active-ide-session`) that any tab in
   the workspace could overwrite. With two open chats, a hook from tab A
   could resolve to tab B's session ID and emit the wrong
   previous_session_id. Replaced with deterministic per-chat resolution
   keyed off the most-recently-modified `<sessionId>.json` file in the
   IDE workspace-sessions directory:
   - The IDE writes the user prompt / assistant response to the active
     chat's transcript file before invoking the hook, so file mtime is
     the closest signal we have to "which tab fired".
   - The IDE session UUID is used directly as the Entire session ID,
     making each Kiro chat keyed deterministically for its lifetime.
   - No per-chat state file required; switching tabs naturally resolves
     to the other chat's existing stable ID without overwriting either.
   - Rekey + previous_session_id concept removed entirely — there's no
     rekey to migrate, each chat is its own independent stable session.

2. IDE transcript trimming shared one offset bucket across all chats
   (the offset file was keyed by `parsed.ConversationID`, which is
   always empty for IDE-derived transcripts). After capturing chat A,
   capturing chat B silently dropped its first N entries. Refactored
   `trimTranscriptHistory(raw, chatKey)` to take an explicit per-chat
   key; `ensureIDETranscript` passes the IDE session ID and
   `ensureCachedTranscript` passes the CLI conversation_id. Each chat
   now writes its own `kiro-transcript-offset-<key>.json` and is
   completely isolated from other chats' offsets.

Regression tests:
- TestParseHookSwitchingKiroChatTabsResolvesEachTabIndependently —
  three turns across two tabs (A → B → back to A) each resolve to
  their own stable Entire session ID with no cross-tab state.
- TestParseHookSessionIDStableAcrossTurnsInSameIDEChat —
  unchanged contract: two turns in the same chat produce the same
  session ID.
- TestEnsureIDETranscriptOffsetsAreIsolatedPerChat — capturing chat A
  then chat B preserves chat B's history (was previously dropped) and
  leaves chat A's offset bucket untouched.

Removed `kiro-active-ide-session` cache (replaced by mtime detection),
`previousSessionID` from the resolver result struct (no rekey needed),
and the obsolete TestParseHookRekeysAndEmitsPreviousSessionIDOnNewKiroChat.

AGENT.md updated to document the new per-chat keying.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: fdd6e3fabde7

* Bind IDE turn identity and isolate tool-calls per chat

Addresses both blocking findings from adversarial review #3:

1. resolveHookSessionIdentity re-resolved the IDE chat by mtime on every
   hook, so a tab switch between user-prompt-submit and stop would
   silently rebind the turn to a different chat — wrong session_id, wrong
   transcript captured, original session orphaned.

   Fix: user-prompt-submit writes the resolved IDE session ID to a new
   per-turn cache (`.entire/tmp/kiro-active-turn`). A new
   resolveStopIdentity prefers that cached binding over fresh mtime
   resolution, so the turn finalizes against whichever chat fired the
   prompt regardless of which chat became newest by mtime in between.
   The cache is cleared at end of stop so the next turn discovers
   freshly. mtime resolution is still the entry point for the very first
   prompt-submit (and as a fallback when no turn binding exists).

2. post-tool-use appended to a single repo-global tool-calls jsonl, so
   in interleaved multi-chat flows one chat's stop would consume
   another chat's tool history (and the second chat's stop would see
   nothing).

   Fix: tool-calls are now written per chat
   (`.entire/tmp/kiro-tool-calls-<sanitized-id>.jsonl`) keyed by the
   active-turn cache (or, if absent, mtime). transcript capture reads
   only the chat that's stopping. The legacy global file is preserved
   for CLI-only flows that have no IDE chat ID at all.

Regression tests:
- TestParseHookTurnIdentityStableAcrossTabSwitchBetweenPromptAndStop —
  prompt-submit in tab A, bump tab B's mtime to make B newest, stop
  must still emit chat-A's session ID.
- TestParseHookToolCallsAreIsolatedPerChat — sequential A→stop→B
  produces per-chat jsonl files; chat B's file does not contain chat
  A's tool calls and the legacy global file is never written.

AGENT.md updated to document the active-turn cache and the per-chat
tool-call file layout.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: d2a5c28b62e7

* Stop CLI conversation_id from masquerading as an IDE session

`rawSessionID` previously fell through to `conversation_id`, so a CLI
hook payload with only `conversation_id` set populated `ideSessionID`
with the CLI value. The stop path then tried `ensureIDETranscript`
first; when no `<conversation_id>.json` existed it silently fell back
to "latest IDE session" and checkpointed an unrelated IDE chat for what
was actually a CLI-only turn.

Fixes:

- Split `rawSessionID` into `rawIDESessionID` (IDE-only fields:
  `session_id`, `sessionId`, `chatSessionId`) and `rawConversationID`
  (CLI-only: `conversation_id`). `chatSessionId` is no longer a CLI
  fallback either — it references a Kiro IDE execution log and would
  point ensureCachedTranscript at the wrong row.
- `resolveHookSessionIdentity` and `resolveStopIdentity` now keep CLI
  and IDE identity sources cleanly separated. An explicit
  `conversation_id` in the payload short-circuits IDE mtime discovery
  (otherwise the resolver would still find an unrelated IDE chat by
  mtime and use it as the session).
- `captureTranscriptForStop` skips `ensureIDETranscript` entirely when
  `identity.ideSessionID == ""`, so CLI-only turns can't silently
  checkpoint another chat's transcript via the "latest IDE" fallback.

Regression test:
- TestParseHookCLIConversationIDDoesNotMasqueradeAsIDESession plants
  unrelated IDE workspace data in the same repo, then fires a CLI-only
  stop with `conversation_id`. The captured transcript must address
  `cli-conv.json`, not the IDE chat, and must not contain the IDE
  chat's content.

Addresses finding 2 from adversarial review #4.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 7507f0edbb5a

* Make CLI conversation_id beat IDE turn cache in stop and post-tool-use

Two follow-on findings from adversarial review #5:

1. resolveStopIdentity consulted the repo-global active-turn IDE cache
   before honoring an explicit CLI conversation_id in the payload. With
   an in-flight IDE turn (cache populated) and a concurrent CLI stop in
   the same repo, the CLI stop would inherit the IDE turn's session ID
   and route through ensureIDETranscript, capturing the wrong chat.

   Fix: in resolveStopIdentity, short-circuit on rawConversationID
   before reading the active-turn cache. Explicit CLI signal in the
   payload now always beats any cached IDE turn binding.

2. post-tool-use resolved its tool-calls jsonl key purely via
   activeTurnOrLatestIDESessionID, which falls back to mtime-detected
   IDE chats. CLI tool calls in a repo with any IDE workspace data
   therefore got appended to an IDE-scoped jsonl. CLI stop only clears
   the global file (key=""), so the IDE-keyed file survived and would
   later contaminate an IDE transcript.

   Fix: replace activeTurnOrLatestIDESessionID with
   resolvePostToolUseChatKey, which mirrors the resolver precedence:
   explicit IDE session ID → IDE-keyed file; explicit conversation_id →
   global file (matching where CLI stop will clear); active-turn cache
   → IDE-keyed file; mtime fallback as last resort. CLI tool calls now
   land where the matching CLI stop will read them.

Regression tests:
- TestResolveStopIdentityPrefersConversationIDOverActiveTurnCache —
  seed kiro-active-turn with an IDE chat ID, then fire a CLI stop with
  conversation_id; the CLI conv must win and the captured transcript
  must not contain the IDE chat's content.
- TestPostToolUseWithConversationIDDoesNotLeakIntoIDEChat — fire a CLI
  post-tool-use with conversation_id in a repo containing IDE workspace
  data; the IDE chat's tool-calls file must not be created and the
  global tool-calls file must contain the CLI tool call.

Addresses both findings from adversarial review #5.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 9e6c2257dee8

* Stop CLI/IDE flows from clobbering each other's stop-hook state

Two follow-on findings from adversarial review #6, both about the same
underlying problem: CLI and IDE stop paths shared too much state and
could corrupt each other under concurrent use in one repo.

1. ParseHook(stop) cleared kiro-active-turn unconditionally. CLI stops
   would delete the in-flight IDE turn binding, so the IDE's later
   post-tool-use/stop hooks would fall back to fresh mtime resolution
   and possibly finalize the wrong chat. Fix: only clear the cache
   when the stop being handled actually owns it
   (`identity.ideSessionID != ""`). CLI stops leave the IDE turn cache
   alone.

2. resolveStopIdentity, when serving an IDE turn from the active-turn
   cache, queried SQLite for "the latest CLI conversation in this
   repo" and stuffed it into conversationID. If ensureIDETranscript
   later degraded for any transient reason, the CLI fallback in
   captureTranscriptForStop would capture an unrelated CLI transcript
   under the IDE session's file. Two-part fix:
   - resolveStopIdentity no longer auto-injects an inferred CLI conv;
     conversationID stays empty unless the payload supplies it.
   - captureTranscriptForStop skips ensureCachedTranscript entirely
     when the identity is IDE-bound with no proven CLI conversation
     link. IDE-bound stops fail closed to a placeholder rather than
     silently capturing an arbitrary CLI conversation.

Regression tests:
- TestCLIStopPreservesInFlightIDETurnCache — seed kiro-active-turn,
  fire a CLI stop with conversation_id, assert the cache survives.
- TestIDEStopFromTurnCacheDoesNotInjectArbitraryConversationID — plant
  an unrelated CLI conversation in SQLite, fire an IDE stop served
  from the turn cache (no IDE workspace data so ensureIDETranscript
  fails), assert the captured transcript does NOT contain the
  unrelated CLI content.

Addresses both findings from adversarial review #6.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: b5e3658f5afc

* Owner-check active-turn cache writes and clears

Two surgical guards on `.entire/tmp/kiro-active-turn` to fix the
remaining cache-clobber findings without restructuring the cache:

1. user-prompt-submit only writes the cache when the resolved identity
   actually has an IDE session ID. CLI prompts (where ideSessionID is
   "") used to call writeActiveTurnIDESessionID(""), which deletes the
   file and stranded any in-flight IDE turn's binding.

2. stop only clears the cache when the value on disk still names this
   stop's IDE chat. Overlapping IDE turns (A prompt → B prompt → A
   stop) used to let A's stop delete B's binding because the clear was
   gated only on `identity.ideSessionID != ""`.

Regression tests:
- TestCLIPromptSubmitDoesNotClearInFlightIDETurnCache — seed an IDE
  binding, fire a CLI prompt-submit, assert binding survives.
- TestOverlappingIDEStopOnlyClearsItsOwnTurnCache — cache holds B,
  IDE stop A arrives with sessionId=chat-A, assert B's binding
  survives.

AGENT.md adds a "Concurrency limitations" section documenting the
fundamental limit of a single repo-global active-turn cache: under
truly overlapping IDE turns, A's stop has no payload signal to
distinguish it from B's, so the resolver returns whichever chat is
currently cached. The owner-check prevents cross-deletion but cannot
correct mis-resolution without a per-turn signal Kiro doesn't provide.
This is a known limitation, not a fix target.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 51d63fea90e2

* Strip KIRO_DEBUG capture diagnostics

The env-gated step-by-step logger added during the Windows path
investigation has served its purpose. captureTranscriptForStop now
collapses to its essential branching logic without the debug
plumbing — same behavior, ~70 fewer lines, no dead code paths in
normal operation.

If a similar diagnostic is needed again, structured slog logging is
the right place to add it rather than re-introducing this bespoke
file logger.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: f9b2f6086ff0

* Fix golangci-lint findings on the kiro agent

Two CI lint failures from PR #24:

1. transcript.go: `"windows"` literal had 9 occurrences in production
   code — flagged by goconst. Extracted to a const `osWindows` near
   the existing `runtimeGOOS` declaration; replaced all production
   call sites in transcript.go (3) and hooks.go (4). Test files keep
   the literal so test-only changes don't depend on a non-test const.
2. transcript.go: blank import of `modernc.org/sqlite` was missing a
   justifying comment — flagged by revive. Added a comment explaining
   it registers the "sqlite" driver consumed by `sql.Open` in
   openSQLiteDB.

`modernc.org/sqlite` is still required: openSQLiteDB calls
`sql.Open("sqlite", path)` to read Kiro's `data.sqlite3` for CLI
conversation lookup, and the blank import is the standard way to
register a database/sql driver.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: eb59aee85c49

* Approve modernc.org/mathutil license (BSD-3-Clause)

LicenseFinder couldn't auto-detect the license on `modernc.org/mathutil`
v1.7.1 — its LICENSE file contains the standard BSD-3-Clause text but no
SPDX identifier line, so the scanner reports it as "unknown" and fails
the licenses CI gate.

Confirmed manually: LICENSE file in the published module is the
canonical BSD-3-Clause text. mathutil is pulled in transitively by
modernc.org/sqlite (the embedded SQLite driver entire-agent-kiro now
uses for Kiro CLI conversation lookup so Windows installs without a
sqlite3 binary still work).

Adding a `:license` decision per LicenseFinder's documented mechanism
maps the package to BSD-3-Clause, which is already in the project's
permitted list.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: ac10cec41cfa

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Development

Successfully merging this pull request may close these issues.

1 participant