Skip to content

fix: corrige 3 travamentos no startup e runtime (v0.17.0)#8

Merged
Edwardmaster7 merged 23 commits into
Edwardmaster7:mainfrom
mat-dgruber:feat/skills-v0.17.0
May 27, 2026
Merged

fix: corrige 3 travamentos no startup e runtime (v0.17.0)#8
Edwardmaster7 merged 23 commits into
Edwardmaster7:mainfrom
mat-dgruber:feat/skills-v0.17.0

Conversation

@mat-dgruber

@mat-dgruber mat-dgruber commented May 26, 2026

Copy link
Copy Markdown

Resumo

Corrige 3 cenários de travamento (hang/freeze) que impediam o uso normal do OpenClaude, especialmente no macOS com Bun runtime.

Problemas corrigidos

1. Deadlock no File Watcher do Bun (fs.watch)

O Bun tem um bug conhecido no PathWatcherManager (oven-sh/bun#27469): quando um watcher é fechado na thread principal enquanto a thread de File Watcher entrega eventos, ambas as threads ficam presas em __ulock_wait2. Isso era gatilhado pelo chokidar ao monitorar settings e skills.

Fix: usePolling: true no chokidar quando detectado runtime Bun. Sem FSWatcher = sem deadlock.

Arquivos: src/utils/settings/changeDetector.ts, src/utils/skills/skillChangeDetector.ts

2. Travamento no Keychain do macOS

O comando security find-generic-password podia travar indefinidamente quando o keychain estava bloqueado ou o securityd sobrecarregado. As chamadas não tinham timeout.

Fix: timeout: 1500ms em todas as 4 chamadas ao keychain.

Arquivos: src/utils/auth.ts, src/utils/secureStorage/macOsKeychainStorage.ts

3. Detecção de IDE com N chamadas síncronas

A função getVSCodeIDECommandByParentProcess() fazia até 20 chamadas síncronas ao ps para caminhar a árvore de processos. Se qualquer chamada demorasse, o event loop travava.

Fix: Substituído por getAncestorCommandsAsync() — uma única chamada shell com timeout de 3s.

Arquivos: src/utils/ide.ts, src/utils/genericProcessUtils.ts

Detalhes adicionais

  • Documentação completa em docs/fix-hang-v0.17.0.md
  • Version bump para 0.17.0

Checklist

  • Build passa (npm run build)
  • Testado no macOS com Bun runtime
  • Documentação adicionada
  • Sem regressões observadas

🤖 Generated with OpenClaude

Summary by Sourcery

Resolve multiple startup and runtime hangs while deepening Buddy integration with feedback and Stoneage features, and updating docs, stats, and achievements for the new behaviors.

New Features:

  • Integrate Buddy with the Stoneage token-compression mode, including reactions, XP rewards, token-saving stats, memories, and related achievements.
  • Enhance Buddy with feedback-aware behaviors such as feedback-based moods, contextual feedback tips, reactions to corrections/undos, and XP/achievement tracking for confirmed rules.
  • Extend Buddy stats, achievements, and /buddy stats output to track token savings and feedback rule confirmations, and expose richer session information.
  • Add feedback-driven tips and observer reactions that surface learned feedback rules based on recent activity and context.
  • Reuse the gradient startup screen rendering inside the Ink UI header instead of only printing it directly to stdout, and adjust when it is shown based on fullscreen mode.

Bug Fixes:

  • Work around Bun's fs.watch deadlock by switching chokidar to polling mode under Bun for settings and skill change detection, preventing hangs on large trees or git operations.
  • Prevent macOS keychain operations from hanging the process by adding timeouts to all security-based credential reads and lock checks.
  • Avoid IDE detection freezes on startup by replacing multiple synchronous ps calls with a single asynchronous ancestor-process scan with a bounded timeout.
  • Reduce chances of REPL and observer-related hangs by scanning a bounded window of recent messages for tool results and task completions instead of relying on only the last message.
  • Prevent the startup logo from briefly flashing and disappearing in fullscreen environments by skipping the initial stdout logo when alternate screen mode is enabled.

Enhancements:

  • Refine Buddy mood logic to incorporate async feedback quality signals while preserving existing error-rate and activity-based moods.
  • Improve Buddy observer behavior to grant XP and code-review tips based on the latest successful Bash run, and to more robustly track stats and memories.
  • Normalize and clarify Buddy docs tables for XP sources, levels, moods, outfits, diagnostics, tips, easter eggs, seasonal events, memories, achievements, and observer behavior, adding entries for Stoneage and feedback-related features.
  • Expose startup screen text generation as a reusable function so it can be rendered both in the CLI bootstrap and inside the UI header.
  • Update dependency versions (including ws and uuid) and bump the package version to 0.17.0.

Documentation:

  • Update Buddy feature documentation to describe feedback-driven behavior, Stoneage integration, new stats, achievements, moods, and observer reactions.
  • Add a dedicated docs/fix-hang-v0.17.0.md document detailing the three main hang scenarios and their mitigations in this release.

Tests:

  • Add Bun tests for Stoneage config flag handling, including default mode selection, env overrides, file permissions, symlink safety, and size limits.
  • Add tests for Buddy feedback integration to ensure observer reactions and XP/stat updates occur when feedback is detected or confirmed.
  • Add tests for feedback-tip generation in Buddy skills to validate behavior with and without stored feedback rules.

mat-dgruber and others added 23 commits May 25, 2026 17:30
Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
Add getFeedbackMood() helper that scans memory files for feedback rules
and derives emotional state from their average score. Integrated into
the getMood() priority chain between sonolento and error-rate checks.

Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
Add 3 new achievements based on totalFeedbackConfirms thresholds:
- feedback-aprendiz at 5 confirms
- feedback-mestre at 15 confirms
- feedback-sabio at 30 confirms

Includes test suite covering unlock/lock boundary conditions.

Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
- Import FeedbackDetectionResult type
- Add correction, undo, and confirm reply arrays
- Accept optional feedbackResult in fireCompanionObserver
- React to detected feedback with deterministic replies and memory
- Export notifyFeedbackConfirm (+2 XP, stats, reply)
- Export notifyFeedbackRuleCreated (stats increment)

Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
Show feedback rules and confirmations count when non-zero, with
separator line for visual consistency.

Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
Notify buddy and grant +2 XP when user confirms a feedback pattern
via /feedback confirm. Appends buddy reaction to confirmation message.

Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
… grant

- Moved feedback reaction block before bash success handler to avoid
  early returns from git status checks silently skipping feedback
- Unified XP grant + stat increment in single saveGlobalConfig callback
  to avoid race conditions between separate writes

Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
- Add getLastDetectedFeedback()/clearLastDetectedFeedback() to feedbackHook.ts
- Store last detected result in module-level variable after detection
- REPL.tsx reads and passes feedbackResult to fireCompanionObserver
- Clear after use to prevent stale reactions

Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
- Feedback XP source (+2 on /feedback confirm)
- Feedback moods (orgulhoso/preocupado/neutro)
- Feedback tip skill (getFeedbackTip)
- 3 new achievements (Aprendiz/Mestre/Sábio)
- Feedback stats in /buddy stats
- Updated reactions table

Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
…itions

- Scan recent messages (last 10) instead of only last message
- Find tool results and task completions across the full sequence
- Remove unused oldInfo variable from notifyFeedbackConfirm
- Add stoneageFirst memory trigger
- Add stoneage.test.ts and stoneage-hooks.test.ts

Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
- Bump ws to ^8.21.0
- Add uuid ^11.1.1 override to fix gaxios subdependency vulnerability
- Update bun.lock

Co-Authored-By: OpenClaude (gemini-3.1-pro-preview) <openclaude@gitlawb.com>
…rnate screen mode

The startup logo was previously printed synchronously to `stdout` during CLI startup.
When the Ink UI subsequently initialized in fullscreen/alternate screen mode, it would
switch to the alternate screen buffer, instantly clearing the terminal and causing the
logo to flash and vanish.

This fixes the issue by skipping the stdout print if `isFullscreenEnvEnabled()` is true.
We preserve the standard React `LogoV2` component which mounts immediately and shows the
logo correctly within the interactive REPL without any performance or flickering issues.
…rnate screen mode

The startup logo was previously printed synchronously to `stdout` during CLI startup.
When the Ink UI subsequently initialized in fullscreen/alternate screen mode, it would
switch to the alternate screen buffer, instantly clearing the terminal and causing the
logo to flash and vanish.

This fixes the issue by:
1. Skipping the stdout print if `isFullscreenEnvEnabled()` is true.
2. Rendering the gradient startup logo natively inside Ink (via `<Ansi>` within `Messages.tsx`)
   so it persists at the top of the chat history, seamlessly replacing the old LogoV2 box
   without the flickering artifact.
…ender

useMainLoopModel() subscribes to AppState + GrowthBook refresh → triggers
forceRerender → text memo invalidates → loop. LogoHeader now memoizes
getStartupScreenText() once (detectProvider auto-resolves via env vars).

Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
…> for Logo

The previous commit moved the startup logo into the main React tree using `<Ansi>`.
Because the gradient logo consists of hundreds of discrete color ansi-spans,
the Ink Ansi parser choked on initialization trying to shred and convert the
raw codes into hundreds of Yoga flex leaves, locking the CPU and freezing the CLI.

Replaced `<Ansi>` with the dedicated `<RawAnsi>` component which bypasses the
parser entirely, acting as a fixed-bounds (width=62) Yoga leaf and streaming
the raw escape strings straight to stdout.

Co-Authored-By: OpenClaude (gemini-3.1-pro-preview) <openclaude@gitlawb.com>
…<RawAnsi> for Logo"

This reverts commit e595d9d5c69b5bc6108732bfebcfaad2a1dc00f4.
…ite re-render"

This reverts commit 16ae1a5adbd9cc66936123c03cdde561ae8e9b68.
- fs.watch deadlock no Bun: fallback para chokidar com usePolling
  quando detectado runtime Bun (oven-sh/bun#27469)
- Keychain macOS sem timeout: adiciona timeout 1.5s em todas as
  chamadas ao `security find-generic-password`
- Detecção de IDE travando: substitui N chamadas síncronas por
  getAncestorCommandsAsync único com timeout 3s
- Adiciona documentação detalhada em docs/fix-hang-v0.17.0.md

Co-Authored-By: OpenClaude (mimo-v2.5-pro) <openclaude@gitlawb.com>
@sourcery-ai

sourcery-ai Bot commented May 26, 2026

Copy link
Copy Markdown

Reviewer's Guide

Implements v0.17.0 stability fixes for startup/runtime hangs (Bun file watching, macOS keychain, IDE detection), enriches the Buddy companion system with stoneage + feedback integration, and refactors startup screen rendering while adding tests and dependency bumps.

Sequence diagram for new buddy feedback integration and reactions

sequenceDiagram
  actor User
  participant REPL as REPL
  participant FeedbackHook as feedbackHook
  participant Observer as fireCompanionObserver
  participant Config as config

  User->>REPL: message (correction/undo)
  REPL->>FeedbackHook: detectAndLogFeedback(input, messages, sessionId)
  FeedbackHook-->>FeedbackHook: set lastDetectedFeedback
  FeedbackHook-->>REPL: FeedbackDetectionResult

  Note over REPL: Later, at end of query loop
  REPL->>FeedbackHook: getLastDetectedFeedback()
  FeedbackHook-->>REPL: FeedbackDetectionResult
  REPL->>Observer: fireCompanionObserver(messages, onReaction, feedbackResult)
  Observer->>Config: saveGlobalConfig(update companionMemory)
  Observer-->>REPL: onReaction(buddy reaction)
  REPL->>FeedbackHook: clearLastDetectedFeedback()
  FeedbackHook-->>REPL: (cleared)

  Note over User,REPL: On /feedback confirm
  User->>REPL: /feedback confirm
  REPL->>Observer: notifyFeedbackConfirm(buddyName)
  Observer->>Config: saveGlobalConfig(update xp, totalFeedbackConfirms)
  Observer-->>REPL: buddy reaction text
Loading

File-Level Changes

Change Details Files
Avoid Bun fs.watch deadlocks by switching chokidar-based settings/skills watchers to polling when running under Bun.
  • Introduce Bun runtime detection and polling constants for change detectors.
  • Enable chokidar usePolling with a fixed interval instead of native fs.watch under Bun.
src/utils/settings/changeDetector.ts
src/utils/skills/skillChangeDetector.ts
Prevent macOS keychain hangs by adding timeouts around all security-related keychain operations.
  • Add timeout options to synchronous security invocations for API key retrieval and secure storage reads.
  • Add timeout to async execFile-based keychain reads and to security show-keychain-info used for lock detection.
src/utils/auth.ts
src/utils/secureStorage/macOsKeychainStorage.ts
Remove synchronous, multi-ps process tree walking for VS Code IDE detection in favor of a single async ancestor command query with timeout.
  • Refactor getVSCodeIDECommandByParentProcess to async and use getAncestorCommandsAsync with a bounded depth.
  • Propagate async usage to getVSCodeIDECommand to avoid blocking the event loop during IDE detection.
src/utils/ide.ts
src/utils/genericProcessUtils.ts
Integrate the Buddy companion with Stoneage token compression and feedback learning, including new moods, achievements, stats, observer behavior, and feedback command reactions.
  • Track stoneage activations, tokens saved, and related achievements and memories in companion stats.
  • Extend observer to scan recent messages, react to stoneage and feedback events, and centralize bash success handling.
  • Add async feedback-based mood calculation using auto-mem feedback rules and expose new feedback tips.
  • Wire feedback detection state from the REPL into the observer and enhance /feedback confirm to notify the buddy and grant XP.
  • Expose new stats fields through the buddy command and extend config and memory trigger types accordingly.
src/buddy/observer.ts
src/buddy/achievements.ts
src/buddy/mood.ts
src/buddy/skills.ts
src/commands/buddy/buddy.tsx
src/utils/config.ts
src/buddy/memory.ts
src/hooks/feedbackHook.ts
src/screens/REPL.tsx
src/commands/feedback/feedback.ts
docs/buddy.md
Refactor startup screen rendering to be reusable text generation, and avoid double-printing when fullscreen Ink UI is enabled.
  • Split startup screen into a pure getStartupScreenText generator used by both CLI and Ink logo header.
  • Guard CLI startup screen printing behind a fullscreen environment check.
  • Simplify LogoHeader to render startup text directly with Ansi and StatusNotices.
src/components/StartupScreen.ts
src/components/Messages.tsx
src/entrypoints/cli.tsx
Document the three startup/runtime hang fixes and add focused tests around stoneage config and buddy feedback integration/skills.
  • Add a dedicated v0.17.0 hang-fix document describing Bun watcher, keychain, and IDE fixes.
  • Introduce Bun-based tests for stoneage flag handling, buddy-feedback integration, and feedback tips.
  • Update buddy documentation tables to include stoneage, feedback stats, moods, achievements, and observer behavior.
docs/fix-hang-v0.17.0.md
docs/buddy.md
src/hooks/stoneage-hooks.test.ts
src/buddy/feedback-integration.test.ts
src/buddy/skills.test.ts
src/buddy/achievements.test.ts
src/buddy/stoneage.test.ts
Bump package version and adjust selected dependencies/overrides for v0.17.0.
  • Increment package version from 0.16.0 to 0.17.0.
  • Update ws dependency to latest 8.x and add uuid override to keep it current.
package.json
bun.lock

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

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

Hey - I've found 2 issues, and left some high level feedback:

  • Now that companionStats includes totalTokensSaved, totalFeedbackRules and totalFeedbackConfirms, make sure every place that creates or resets companionStats initializes these fields to 0 so achievements/moods/UI never see undefined values.
  • The stoneage tracking in fireCompanionObserver is purely based on /\bstoneage\b/i in user text; consider wiring this to the actual stoneage activation path so that stats and achievements can’t be incremented accidentally just by mentioning the word in normal conversation.
  • With getMood becoming async and doing a filesystem-backed feedback scan, double-check all call sites await it and consider a stricter internal timeout/fallback so /buddy and related commands can’t be noticeably delayed if the memory directory is large or slow.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Now that `companionStats` includes `totalTokensSaved`, `totalFeedbackRules` and `totalFeedbackConfirms`, make sure every place that creates or resets `companionStats` initializes these fields to `0` so achievements/moods/UI never see `undefined` values.
- The stoneage tracking in `fireCompanionObserver` is purely based on `/\bstoneage\b/i` in user text; consider wiring this to the actual stoneage activation path so that stats and achievements can’t be incremented accidentally just by mentioning the word in normal conversation.
- With `getMood` becoming async and doing a filesystem-backed feedback scan, double-check all call sites await it and consider a stricter internal timeout/fallback so `/buddy` and related commands can’t be noticeably delayed if the memory directory is large or slow.

## Individual Comments

### Comment 1
<location path="src/buddy/observer.ts" line_range="337-346" />
<code_context>
+    )
+    onReaction(`${companion.name} ${reply}`)
+
+    // Save feedback reaction memory
+    const currentCompanion = getCompanion()
+    if (currentCompanion) {
+      saveGlobalConfig(curr => ({
+        ...curr,
+        companionMemory: [
+          ...(curr.companionMemory ?? []),
+          {
+            timestamp: Date.now(),
+            trigger: 'feedbackDetected',
+            text: `Feedback ${feedbackResult.type} detectado: ${feedbackResult.message}`,
+          },
+        ],
+      }))
+    }
</code_context>
<issue_to_address>
**suggestion (performance):** Appending every feedback event to `companionMemory` without any cap can bloat the config over time.

Because this array is persisted in the global config, heavy feedback usage will create an ever-growing structure in memory and on disk. Consider enforcing a maximum length (e.g., keep only the last N entries) or moving these logs to a separate append-only storage so the main config stays small and fast to read/write.

Suggested implementation:

```typescript
  // ─── Feedback Reactions ───────────────────────────────────────────────
  if (feedbackResult?.detected) {
    const replies = feedbackResult.type === 'undo' ? FEEDBACK_UNDO_REPLIES : FEEDBACK_CORRECTION_REPLIES
    const reply = pickDeterministic(
      replies,
      `feedback-${feedbackResult.type}-${Date.now()}`,
    )
    onReaction(`${companion.name} ${reply}`)

    // Save feedback reaction memory with a bounded history to avoid unbounded growth
    const currentCompanion = getCompanion()
    if (currentCompanion) {
      saveGlobalConfig(curr => {
        const nextMemory = [
          ...(curr.companionMemory ?? []),
          {
            timestamp: Date.now(),
            trigger: 'feedbackDetected',
            text: `Feedback ${feedbackResult.type} detectado: ${feedbackResult.message}`,
          },
        ]

        // Keep only the latest N entries to prevent config bloat
        const MAX_COMPANION_MEMORY_ENTRIES = 100
        const slicedMemory =
          nextMemory.length > MAX_COMPANION_MEMORY_ENTRIES
            ? nextMemory.slice(nextMemory.length - MAX_COMPANION_MEMORY_ENTRIES)
            : nextMemory

        return {
          ...curr,
          companionMemory: slicedMemory,
        }
      })
    }

```

```typescript
      totalErrors: curr.companionStats?.totalErrors ?? 0,

```

If there is already a shared configuration/constants module for limits, you may want to:
1. Extract `MAX_COMPANION_MEMORY_ENTRIES = 100` into that module and import it here instead of defining it inline.
2. Optionally make the cap configurable via the global config schema if you expect to tune this value per-user or environment.
</issue_to_address>

### Comment 2
<location path="docs/buddy.md" line_range="619-628" />
<code_context>
+
+---
+
+## Integracao Stoneage
+
+O Buddy e integrado ao **Stoneage**, o modo de compressao de tokens do OpenClaw. Quando voce ativa o stoneage, o companion:
+
+1. **Reage** com frases tematicas pre-historicas
+2. **Ganha XP** (+0.5 por ativacao)
+3. **Rastreia tokens economizados** em `/buddy stats`
+4. **Desbloqueia conquistas** ao atingir milestones
+
+### Conquistas Stoneage
+
+| Emoji | Conquista         | Descricao                         | Condicao     |
+| ----- | ----------------- | --------------------------------- | ------------ |
+| 🪨    | Primeiro Contato  | Ativar stoneage pela primeira vez | 1 ativacao   |
+| 🔥    | Economia de Fogo  | Economizar 1000 tokens estimados  | 1000 tokens  |
+| 🦣    | Mamute de Ouro    | Economizar 10000 tokens estimados | 10000 tokens |
+| ⛏️  | Mestre das Pedras | Ativar stoneage 50 vezes          | 25000 tokens |
+
+### Reacoes do Companion
</code_context>
<issue_to_address>
**suggestion (typo):** Corrigir acentuação em português na seção de integração com Stoneage.

Há vários termos sem acentuação nessa seção (`Integracao`, `e integrado`, `compressao`, `Reacoes`, `Descricao`, `Condicao`, `ativacao` etc.). Padronize para o PT-BR com acentos, como no restante da documentação, para manter consistência e evitar aparência de erro de digitação.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/buddy/observer.ts
Comment on lines +337 to +346
// Save feedback reaction memory
const currentCompanion = getCompanion()
if (currentCompanion) {
saveGlobalConfig(curr => ({
...curr,
companionMemory: [
...(curr.companionMemory ?? []),
{
timestamp: Date.now(),
trigger: 'feedbackDetected',

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (performance): Appending every feedback event to companionMemory without any cap can bloat the config over time.

Because this array is persisted in the global config, heavy feedback usage will create an ever-growing structure in memory and on disk. Consider enforcing a maximum length (e.g., keep only the last N entries) or moving these logs to a separate append-only storage so the main config stays small and fast to read/write.

Suggested implementation:

  // ─── Feedback Reactions ───────────────────────────────────────────────
  if (feedbackResult?.detected) {
    const replies = feedbackResult.type === 'undo' ? FEEDBACK_UNDO_REPLIES : FEEDBACK_CORRECTION_REPLIES
    const reply = pickDeterministic(
      replies,
      `feedback-${feedbackResult.type}-${Date.now()}`,
    )
    onReaction(`${companion.name} ${reply}`)

    // Save feedback reaction memory with a bounded history to avoid unbounded growth
    const currentCompanion = getCompanion()
    if (currentCompanion) {
      saveGlobalConfig(curr => {
        const nextMemory = [
          ...(curr.companionMemory ?? []),
          {
            timestamp: Date.now(),
            trigger: 'feedbackDetected',
            text: `Feedback ${feedbackResult.type} detectado: ${feedbackResult.message}`,
          },
        ]

        // Keep only the latest N entries to prevent config bloat
        const MAX_COMPANION_MEMORY_ENTRIES = 100
        const slicedMemory =
          nextMemory.length > MAX_COMPANION_MEMORY_ENTRIES
            ? nextMemory.slice(nextMemory.length - MAX_COMPANION_MEMORY_ENTRIES)
            : nextMemory

        return {
          ...curr,
          companionMemory: slicedMemory,
        }
      })
    }
      totalErrors: curr.companionStats?.totalErrors ?? 0,

If there is already a shared configuration/constants module for limits, you may want to:

  1. Extract MAX_COMPANION_MEMORY_ENTRIES = 100 into that module and import it here instead of defining it inline.
  2. Optionally make the cap configurable via the global config schema if you expect to tune this value per-user or environment.

Comment thread docs/buddy.md
Comment on lines +619 to +628
## Integracao Stoneage

O Buddy e integrado ao **Stoneage**, o modo de compressao de tokens do OpenClaw. Quando voce ativa o stoneage, o companion:

1. **Reage** com frases tematicas pre-historicas
2. **Ganha XP** (+0.5 por ativacao)
3. **Rastreia tokens economizados** em `/buddy stats`
4. **Desbloqueia conquistas** ao atingir milestones

### Conquistas Stoneage

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (typo): Corrigir acentuação em português na seção de integração com Stoneage.

Há vários termos sem acentuação nessa seção (Integracao, e integrado, compressao, Reacoes, Descricao, Condicao, ativacao etc.). Padronize para o PT-BR com acentos, como no restante da documentação, para manter consistência e evitar aparência de erro de digitação.

@Edwardmaster7 Edwardmaster7 merged commit 908642a into Edwardmaster7:main May 27, 2026
1 check 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.

2 participants