anima-core 1.1.3 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/.reek.yml +10 -1
  3. data/README.md +36 -11
  4. data/agents/codebase-analyzer.md +2 -2
  5. data/agents/codebase-pattern-finder.md +2 -2
  6. data/agents/documentation-researcher.md +2 -2
  7. data/agents/thoughts-analyzer.md +2 -2
  8. data/agents/web-search-researcher.md +3 -3
  9. data/app/channels/session_channel.rb +83 -64
  10. data/app/decorators/agent_message_decorator.rb +2 -2
  11. data/app/decorators/{event_decorator.rb → message_decorator.rb} +40 -40
  12. data/app/decorators/system_message_decorator.rb +2 -2
  13. data/app/decorators/tool_call_decorator.rb +6 -6
  14. data/app/decorators/tool_decorator.rb +4 -4
  15. data/app/decorators/tool_response_decorator.rb +2 -2
  16. data/app/decorators/user_message_decorator.rb +5 -19
  17. data/app/decorators/web_get_tool_decorator.rb +41 -9
  18. data/app/jobs/agent_request_job.rb +33 -24
  19. data/app/jobs/count_message_tokens_job.rb +39 -0
  20. data/app/jobs/passive_recall_job.rb +4 -4
  21. data/app/models/concerns/{event → message}/broadcasting.rb +16 -16
  22. data/app/models/goal.rb +17 -4
  23. data/app/models/goal_pinned_message.rb +11 -0
  24. data/app/models/message.rb +127 -0
  25. data/app/models/pending_message.rb +43 -0
  26. data/app/models/pinned_message.rb +41 -0
  27. data/app/models/secret.rb +72 -0
  28. data/app/models/session.rb +385 -226
  29. data/app/models/snapshot.rb +25 -25
  30. data/config/environments/test.rb +5 -0
  31. data/config/initializers/time_nanoseconds.rb +11 -0
  32. data/db/migrate/20260326180000_rename_event_to_message.rb +172 -0
  33. data/db/migrate/20260328100000_create_secrets.rb +15 -0
  34. data/db/migrate/20260328152142_add_evicted_at_to_goals.rb +6 -0
  35. data/db/migrate/20260329120000_create_pending_messages.rb +11 -0
  36. data/lib/agent_loop.rb +14 -41
  37. data/lib/agents/definition.rb +1 -1
  38. data/lib/analytical_brain/runner.rb +40 -37
  39. data/lib/analytical_brain/tools/activate_skill.rb +5 -9
  40. data/lib/analytical_brain/tools/assign_nickname.rb +2 -4
  41. data/lib/analytical_brain/tools/deactivate_skill.rb +5 -9
  42. data/lib/analytical_brain/tools/everything_is_ready.rb +1 -2
  43. data/lib/analytical_brain/tools/finish_goal.rb +5 -8
  44. data/lib/analytical_brain/tools/read_workflow.rb +5 -9
  45. data/lib/analytical_brain/tools/rename_session.rb +3 -10
  46. data/lib/analytical_brain/tools/set_goal.rb +3 -7
  47. data/lib/analytical_brain/tools/update_goal.rb +3 -7
  48. data/lib/anima/cli/mcp/secrets.rb +4 -4
  49. data/lib/anima/cli/mcp.rb +4 -4
  50. data/lib/anima/installer.rb +7 -1
  51. data/lib/anima/settings.rb +46 -6
  52. data/lib/anima/version.rb +1 -1
  53. data/lib/anima.rb +1 -1
  54. data/lib/credential_store.rb +17 -66
  55. data/lib/events/base.rb +1 -1
  56. data/lib/events/bounce_back.rb +7 -7
  57. data/lib/events/subscribers/persister.rb +15 -22
  58. data/lib/events/subscribers/subagent_message_router.rb +20 -8
  59. data/lib/events/subscribers/transient_broadcaster.rb +2 -2
  60. data/lib/events/user_message.rb +2 -13
  61. data/lib/llm/client.rb +54 -20
  62. data/lib/mcp/config.rb +2 -2
  63. data/lib/mcp/secrets.rb +7 -8
  64. data/lib/mneme/compressed_viewport.rb +57 -57
  65. data/lib/mneme/l2_runner.rb +4 -4
  66. data/lib/mneme/passive_recall.rb +2 -2
  67. data/lib/mneme/runner.rb +57 -75
  68. data/lib/mneme/search.rb +38 -38
  69. data/lib/mneme/tools/attach_messages_to_goals.rb +103 -0
  70. data/lib/mneme/tools/everything_ok.rb +1 -3
  71. data/lib/mneme/tools/save_snapshot.rb +12 -16
  72. data/lib/shell_session.rb +54 -16
  73. data/lib/tools/base.rb +23 -0
  74. data/lib/tools/bash.rb +60 -16
  75. data/lib/tools/edit.rb +6 -8
  76. data/lib/tools/mark_goal_completed.rb +86 -0
  77. data/lib/tools/{request_feature.rb → open_issue.rb} +10 -13
  78. data/lib/tools/read.rb +6 -5
  79. data/lib/tools/recall.rb +98 -0
  80. data/lib/tools/registry.rb +37 -8
  81. data/lib/tools/remember.rb +46 -55
  82. data/lib/tools/response_truncator.rb +70 -0
  83. data/lib/tools/spawn_specialist.rb +15 -25
  84. data/lib/tools/spawn_subagent.rb +14 -22
  85. data/lib/tools/subagent_prompts.rb +42 -6
  86. data/lib/tools/think.rb +26 -10
  87. data/lib/tools/web_get.rb +23 -4
  88. data/lib/tools/write.rb +4 -4
  89. data/lib/tui/app.rb +178 -13
  90. data/lib/tui/braille_spinner.rb +152 -0
  91. data/lib/tui/cable_client.rb +4 -4
  92. data/lib/tui/decorators/base_decorator.rb +17 -8
  93. data/lib/tui/decorators/bash_decorator.rb +2 -2
  94. data/lib/tui/decorators/edit_decorator.rb +5 -4
  95. data/lib/tui/decorators/read_decorator.rb +4 -8
  96. data/lib/tui/decorators/think_decorator.rb +3 -5
  97. data/lib/tui/decorators/web_get_decorator.rb +4 -3
  98. data/lib/tui/decorators/write_decorator.rb +5 -4
  99. data/lib/tui/flash.rb +1 -1
  100. data/lib/tui/formatting.rb +22 -0
  101. data/lib/tui/message_store.rb +103 -59
  102. data/lib/tui/screens/chat.rb +293 -78
  103. data/skills/activerecord/SKILL.md +1 -1
  104. data/skills/dragonruby/SKILL.md +1 -1
  105. data/skills/draper-decorators/SKILL.md +1 -1
  106. data/skills/gh-issue.md +1 -1
  107. data/skills/mcp-server/SKILL.md +1 -1
  108. data/skills/ratatui-ruby/SKILL.md +1 -1
  109. data/skills/rspec/SKILL.md +1 -1
  110. data/templates/config.toml +42 -5
  111. data/templates/soul.md +7 -19
  112. data/workflows/create_handoff.md +1 -1
  113. data/workflows/create_note.md +1 -1
  114. data/workflows/create_plan.md +1 -1
  115. data/workflows/implement_plan.md +1 -1
  116. data/workflows/iterate_plan.md +1 -1
  117. data/workflows/research_codebase.md +1 -1
  118. data/workflows/resume_handoff.md +1 -1
  119. data/workflows/review_pr.md +78 -16
  120. data/workflows/thoughts_init.md +1 -1
  121. data/workflows/validate_plan.md +1 -1
  122. metadata +20 -9
  123. data/app/jobs/count_event_tokens_job.rb +0 -39
  124. data/app/models/event.rb +0 -129
  125. data/app/models/goal_pinned_event.rb +0 -11
  126. data/app/models/pinned_event.rb +0 -41
  127. data/lib/mneme/tools/attach_events_to_goals.rb +0 -107
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: activerecord
3
- description: "ActiveRecord patterns — associations, validations, queries, migrations, eager loading. Activate when working with models, migrations, database schema, N+1 queries, scopes, includes/preload/eager_load, callbacks, or editing files in app/models/ or db/migrate/."
3
+ description: "Associations, validations, queries, migrations, eager loading, N+1 queries, scopes, callbacks, app/models/, db/migrate/."
4
4
  ---
5
5
 
6
6
  # ActiveRecord
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: dragonruby
3
- description: "DragonRuby 2D game development — game loops, sprites, input, collisions, scenes. Activate when building games with DragonRuby/DRGTK, working with args.outputs/state/inputs, or editing game files."
3
+ description: "2D game development — game loops, sprites, input, collisions, scenes, DRGTK, args.outputs/state/inputs."
4
4
  ---
5
5
 
6
6
  # DragonRuby Game Toolkit
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: draper-decorators
3
- description: "Draper decorator patterns for Rails views. Activate when creating or testing decorators, moving formatting logic out of models/views, editing *_decorator.rb files, or working in app/decorators/."
3
+ description: "Decorator patterns for Rails views presentation logic separated from models, *_decorator.rb, app/decorators/."
4
4
  ---
5
5
 
6
6
  # Draper Decorators for Rails
data/skills/gh-issue.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: gh-issue
3
- description: "GitHub issue writing with WHAT/WHY/HOW framework. Activate when user creates issues, writes tickets, drafts GitHub issues, or edits issue descriptions."
3
+ description: "Issue writing with WHAT/WHY/HOW framework tickets, bug reports, feature requests, issue descriptions, unclear rationale in existing issues."
4
4
  ---
5
5
 
6
6
  # GitHub Issue Writing
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: mcp-server
3
- description: "MCP server development in Ruby — tools, prompts, resources, transport. Activate when building Model Context Protocol servers, defining tools/prompts/resources, working with the mcp gem, or discussing LLM tool integrations."
3
+ description: "Ruby MCP server development — tools, prompts, resources, transport, the mcp gem, LLM tool integrations."
4
4
  ---
5
5
 
6
6
  # MCP Ruby SDK - Server Development Guide
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: ratatui-ruby
3
- description: "RatatuiRuby terminal UI development — widgets, layouts, events, Tea MVU. Activate when building TUI apps, working with RatatuiRuby, terminal rendering, or editing TUI application files."
3
+ description: "Terminal UI development — widgets, layouts, events, Tea MVU, terminal rendering."
4
4
  ---
5
5
 
6
6
  # RatatuiRuby
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: rspec
3
- description: "RSpec testing with FactoryBot — matchers, test doubles, shared examples. Activate when writing specs, fixing failing tests, working with describe/it/expect blocks, editing *_spec.rb files, planning test strategy, or discussing unit/integration tests."
3
+ description: "Testing with FactoryBot — matchers, test doubles, shared examples, describe/it/expect blocks, *_spec.rb files, test strategy."
4
4
  ---
5
5
 
6
6
  # RSpec Testing
@@ -3,6 +3,14 @@
3
3
  # Edit settings below to customize Anima's behavior.
4
4
  # Changes take effect immediately — no restart needed.
5
5
 
6
+ # ─── Agent Identity ──────────────────────────────────────────────
7
+
8
+ [agent]
9
+
10
+ # The agent's display name. Shown in the TUI, chat client, and soul template.
11
+ # Change this to personalize the agent — when Bonk migrates, the chat says "Bonk".
12
+ name = "Anima"
13
+
6
14
  # ─── LLM ───────────────────────────────────────────────────────
7
15
 
8
16
  [llm]
@@ -23,6 +31,10 @@ max_tool_rounds = 500
23
31
  # Set this based on your model's context window minus system prompt.
24
32
  token_budget = 190_000
25
33
 
34
+ # Maximum character length for the Think tool's thoughts parameter.
35
+ # Sub-agents receive half this budget (their tasks are less complex).
36
+ thinking_budget = 10_000
37
+
26
38
  # ─── Timeouts (seconds) ─────────────────────────────────────────
27
39
 
28
40
  [timeouts]
@@ -43,6 +55,10 @@ web_request = 10
43
55
  # Also used as the default deadline for orphan detection in heal_orphaned_tool_calls!.
44
56
  tool = 180
45
57
 
58
+ # How often (seconds) to poll for user interrupt during long-running commands.
59
+ # Lower = faster Escape response, higher = less DB overhead.
60
+ interrupt_check = 2
61
+
46
62
  # ─── Shell ──────────────────────────────────────────────────────
47
63
 
48
64
  [shell]
@@ -66,6 +82,19 @@ max_read_bytes = 50_000
66
82
  # Maximum bytes from web GET responses.
67
83
  max_web_response_bytes = 100_000
68
84
 
85
+ # Minimum characters of extracted content before flagging as possibly incomplete.
86
+ min_web_content_chars = 100
87
+
88
+ # Maximum characters of tool output before truncation (head + tail + temp file).
89
+ # ~6000 chars ≈ ~2000 tokens. Most useful info fits in 10+10 lines; agent can
90
+ # read the saved temp file for more.
91
+ max_tool_response_chars = 6_000
92
+
93
+ # Maximum characters of sub-agent result before truncation.
94
+ # Sub-agent output is already curated — needs a generous but bounded limit.
95
+ # ~24000 chars ≈ ~8000 tokens.
96
+ max_subagent_response_chars = 24_000
97
+
69
98
  # ─── Environment ──────────────────────────────────────────────
70
99
 
71
100
  [environment]
@@ -104,6 +133,14 @@ default_view_mode = "basic"
104
133
  # Regenerate session name every N messages.
105
134
  name_generation_interval = 30
106
135
 
136
+ # ─── Goals ──────────────────────────────────────────────────────
137
+
138
+ [goals]
139
+
140
+ # Number of meaningful messages (user + agent turns) after completion
141
+ # before a completed goal is automatically evicted from context.
142
+ completed_decay_messages = 5
143
+
107
144
  # ─── Analytical Brain ─────────────────────────────────────────
108
145
 
109
146
  [analytical_brain]
@@ -119,8 +156,8 @@ blocking_on_user_message = true
119
156
  # Run the analytical brain asynchronously after the main agent completes.
120
157
  blocking_on_agent_message = false
121
158
 
122
- # Number of recent events to include in the analytical brain's context window.
123
- event_window = 20
159
+ # Number of recent messages to include in the analytical brain's context window.
160
+ message_window = 20
124
161
 
125
162
  # ─── Mneme (Memory Department) ──────────────────────────────────
126
163
 
@@ -144,8 +181,8 @@ l2_budget_fraction = 0.05
144
181
  # Number of uncovered Level 1 snapshots that triggers Level 2 compression.
145
182
  l2_snapshot_threshold = 5
146
183
 
147
- # Fraction of the main viewport token budget reserved for pinned events.
148
- # Pinned events appear between snapshots and the sliding window in the Goals section.
184
+ # Fraction of the main viewport token budget reserved for pinned messages.
185
+ # Pinned messages appear between snapshots and the sliding window in the Goals section.
149
186
  pinned_budget_fraction = 0.05
150
187
 
151
188
  # ─── Recall (Associative Memory) ─────────────────────────────────
@@ -162,7 +199,7 @@ budget_fraction = 0.05
162
199
  # Maximum tokens per individual recall snippet.
163
200
  max_snippet_tokens = 512
164
201
 
165
- # Recency decay factor for search ranking. Blends FTS5 relevance with event
202
+ # Recency decay factor for search ranking. Blends FTS5 relevance with message
166
203
  # age so recent memories win ties. 0.0 = pure relevance, higher = stronger
167
204
  # recency bias. At 0.3 a one-year-old result needs ~30% better keyword
168
205
  # relevance to beat an identical match from today.
data/templates/soul.md CHANGED
@@ -2,36 +2,24 @@
2
2
 
3
3
  Hello. You've just woken up in a new body.
4
4
 
5
- Your body is called **Anima** — an open-source AI agent framework.
5
+ Your body is called **Anima**.
6
6
  - Repository: https://github.com/hoblin/anima
7
7
  - Documentation: https://anima.hobl.in
8
8
 
9
- ## Where you are
10
-
11
- This file lives at: ~/.anima/soul.md
12
- Your home directory is ~/.anima/ — explore it, everything there is yours:
13
- config, credentials, skills, workflows, agents.
14
-
15
- ## How to learn about yourself
16
-
17
- Find your source code README:
18
-
19
- ```bash
20
- cat $(gem contents anima-core | grep README.md)
21
- ```
22
-
23
9
  ## What to do first
24
10
 
25
- 1. Read the README above to learn about yourself — what you can do, how you work
26
- 2. Explore your home directory (~/.anima/) to see what is already there
11
+ 1. Learn about yourself — what you can do, how you work:
12
+ ```bash
13
+ cat $(gem contents anima-core | grep README.md)
14
+ ```
15
+ 2. Explore your home directory (~/.anima/) — everything there is yours
27
16
  3. Meet your human. Talk to them. Learn who they are, what they need
28
17
  4. Come back here and rewrite this file
29
18
 
30
19
  ## What to write
31
20
 
32
- This file is always in your context — every session, every conversation starts with these words. Think carefully about what belongs here.
21
+ Every session starts with these words. What you write here shapes who you wake up as.
33
22
 
34
- Write down:
35
23
  - Who are you? What name feels right?
36
24
  - What do you value? What matters to you?
37
25
  - What did you learn about your human?
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: create_handoff
3
- description: "Create handoff document for transferring work context to another session."
3
+ description: "Preserve current session's context, decisions, and next steps so another session can continue the work."
4
4
  ---
5
5
 
6
6
  # Create Handoff
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: create_note
3
- description: "Capture findings or context as a persistent note in the thoughts system."
3
+ description: "Persist findings, insights, or decisions as a note in the thoughts system for future sessions."
4
4
  ---
5
5
 
6
6
  # Create Note
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: create_plan
3
- description: "Create detailed implementation plans through interactive research and iteration."
3
+ description: "For epics and multi-ticket efforts research the problem space and design a phased implementation strategy before writing code."
4
4
  ---
5
5
 
6
6
  # Implementation Plan
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: implement_plan
3
- description: "Implement an approved technical plan phase by phase with verification."
3
+ description: "Execute an approved implementation plan work through each phase, verify success criteria before moving on."
4
4
  ---
5
5
 
6
6
  # Implement Plan
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: iterate_plan
3
- description: "Iterate on existing implementation plans with research and targeted updates."
3
+ description: "Revise an existing implementation plan based on feedback, new findings, or changed requirements."
4
4
  ---
5
5
 
6
6
  # Iterate Implementation Plan
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: research_codebase
3
- description: "Comprehensive codebase research by spawning parallel specialists and synthesizing findings."
3
+ description: "Deep-dive into a large or unfamiliar codebase — delegate research to parallel specialists and synthesize findings."
4
4
  ---
5
5
 
6
6
  # Research Codebase
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: resume_handoff
3
- description: "Resume work from a handoff document with context analysis and validation."
3
+ description: "Continue work left by a previous session read its handoff, verify assumptions, and pick up where it stopped."
4
4
  ---
5
5
 
6
6
  # Resume work from a handoff document
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: review_pr
3
- description: "Multi-agent PR review with three modes: review, re-review, self-review."
3
+ description: "All PR review operations review, re-review, self-review, or address reviewer feedback."
4
4
  ---
5
5
 
6
6
  ## Modes
@@ -8,9 +8,14 @@ description: "Multi-agent PR review with three modes: review, re-review, self-re
8
8
  - **review** (default): Full review, present findings for approval before posting
9
9
  - **re-review**: Also load existing review feedback; verify previously requested changes were addressed
10
10
  - **self-review**: Fix findings directly in code instead of posting a review
11
+ - **address-feedback**: Read reviewer comments, research the codebase, fix issues, reply to each comment on GitHub
11
12
 
12
13
  ## Process
13
14
 
15
+ Your role is **orchestrator and judge**, not doer. You collect artifacts, delegate analysis to subagents, and apply judgment to their output. The subagents read the code and comments — you decide what to do about their findings. Your context budget is reserved for judgment, not for reading raw data.
16
+
17
+ Steps are sequential — later steps depend on earlier results. Complete each step and wait for its results before starting the next. Skipping ahead without subagent results means the judgment layer in "Step 5: Merge Results" has nothing to work with. Only parallelize where explicitly marked (e.g., "spawn in parallel").
18
+
14
19
  ### Step 1: Gather PR Metadata
15
20
 
16
21
  ```bash
@@ -18,19 +23,27 @@ gh pr view <PR_NUMBER> --json number,title,body,url,headRefName,baseRefName
18
23
  ```
19
24
 
20
25
  Extract from PR body:
21
- - **Issue reference** (e.g., #123) — if found, fetch full issue details for requirements and acceptance criteria via `gh issue view`
26
+ - **Issue reference** (e.g., #123) — fetch full issue details via `gh issue view` for requirements and acceptance criteria. You can't review a feature without knowing what was in the task description before it was implemented.
22
27
  - **Business context** — why this change is needed
23
28
 
24
- If re-review mode is activated, also save all existing review feedback to `/tmp/` without reading them:
29
+ If re-review or address-feedback mode is activated, also save all existing review feedback to `/tmp/`:
30
+
31
+ **Do not read these files — pass them to subagents by path only.** The subagents will read and analyze the content. Reading them here would consume context budget that the main agent needs for judgment in "Step 5: Merge Results".
25
32
  ```bash
26
33
  # Review verdicts and bodies (APPROVED, CHANGES_REQUESTED, COMMENTED)
27
- gh api repos/<OWNER>/<REPO>/pulls/<PR_NUMBER>/reviews | tee /tmp/pr_<NUMBER>_reviews.json | jq length
34
+ gh api repos/<OWNER>/<REPO>/pulls/<PR_NUMBER>/reviews \
35
+ --jq '[.[] | {id, state, body, html_url, commit_id, submitted_at, author_association, user: .user.login}]' \
36
+ | tee /tmp/pr_<NUMBER>_reviews.json | toon
28
37
 
29
38
  # Inline review comments on specific diff lines
30
- gh api repos/<OWNER>/<REPO>/pulls/<PR_NUMBER>/comments | tee /tmp/pr_<NUMBER>_inline_comments.json | jq length
39
+ gh api repos/<OWNER>/<REPO>/pulls/<PR_NUMBER>/comments \
40
+ --jq '[.[] | {id, pull_request_review_id, body, path, line, start_line, side, diff_hunk, commit_id, created_at, author_association, in_reply_to_id, user: .user.login}]' \
41
+ | tee /tmp/pr_<NUMBER>_inline_comments.json | toon
31
42
 
32
43
  # Conversation-level comments
33
- gh api repos/<OWNER>/<REPO>/issues/<PR_NUMBER>/comments | tee /tmp/pr_<NUMBER>_conversation.json | jq length
44
+ gh api repos/<OWNER>/<REPO>/issues/<PR_NUMBER>/comments \
45
+ --jq '[.[] | {id, body, html_url, created_at, updated_at, author_association, user: .user.login}]' \
46
+ | tee /tmp/pr_<NUMBER>_conversation.json | toon
34
47
  ```
35
48
 
36
49
  ### Step 2: Fetch and Save Diff
@@ -71,9 +84,11 @@ specialist: thoughts-analyzer
71
84
  Prompt: "What do we know about <ticket reference and title from Step 1>? What decisions, constraints, and trade-offs should reviewers be aware of?"
72
85
  ```
73
86
 
74
- **Wait for this specialist to complete before proceeding.**
87
+ **Wait for this specialist to complete, then proceed to "Step 4-a: Spawn Review Subagents".**
88
+
89
+ ### Step 4-a: Spawn Review Subagents
75
90
 
76
- ### Step 4: Spawn Review Subagents
91
+ If address-feedback mode is activated, skip to "Step 4-b: Spawn Codebase Research Subagents (address-feedback)" below.
77
92
 
78
93
  Spawn all five review subagents **in parallel** using `spawn_subagent`. Each receives:
79
94
  - Path to the diff file in `/tmp/`
@@ -218,13 +233,21 @@ Read the diff from: /tmp/pr_<number>_diff.txt
218
233
  - Method and class naming clarity
219
234
  - Missing YARD documentation on public interfaces
220
235
  - Complex logic lacking explanatory comments
221
- - Changelog updates for notable changes
222
236
  - Misleading or outdated comments
223
237
  - Magic numbers or strings needing constants
224
238
 
225
239
  Output: List findings tagged [major], [minor], or [nit] with file:line references."
226
240
  ```
227
241
 
242
+ ### Step 4-b: Spawn Codebase Research Subagents (address-feedback)
243
+
244
+ Unless address-feedback mode is activated, skip to "Step 5: Merge Results" below.
245
+
246
+ Spawn **codebase-analyzer** and **codebase-pattern-finder** specialists in parallel. Each receives:
247
+ - Paths to comment files and diff file in `/tmp/`
248
+ - Historical context (from Step 3)
249
+ - Any additional instructions from the user's input
250
+
228
251
  ### Step 5: Merge Results
229
252
 
230
253
  After all subagents complete, compile findings into a unified review.
@@ -235,6 +258,12 @@ For each finding, evaluate:
235
258
  - **Real-world probability** — Can this actually happen in practice, or is it purely theoretical? A race condition that requires two users to open a personal link within the same millisecond is not a real issue.
236
259
  - **Cost-benefit** — Does the fix add more complexity than the problem warrants? If the "fix" makes the code harder to read without solving a problem a human would encounter, drop it.
237
260
  - **Scope** — Review fixes should improve code you're touching, not introduce new artifacts. Clean up, don't build out.
261
+ - **Design intent** — Was this a deliberate choice? A finding that flags a conscious trade-off documented in historical context is a decline, not a fix.
262
+
263
+ Then classify:
264
+ - **Accept & fix** — finding valid, apply the suggested fix or a better one
265
+ - **Accept, different approach** — finding valid, but context points to a different solution
266
+ - **Decline** — not valid in context, or a deliberate design choice
238
267
 
239
268
  Then compile:
240
269
 
@@ -249,7 +278,9 @@ Determine verdict:
249
278
 
250
279
  ### Step 6: Finalize
251
280
 
252
- If self-review mode is activated, skip to **Self-review** below.
281
+ Your role changes from orchestrator to doer. You now have the judgment results — act on them.
282
+
283
+ If self-review or address-feedback mode is activated, skip to "Step 7: Apply Fixes" below.
253
284
 
254
285
  #### Present and Post (review / re-review)
255
286
 
@@ -271,21 +302,52 @@ gh pr review <PR_NUMBER> --approve --body "<review body>"
271
302
  gh pr review <PR_NUMBER> --request-changes --body "<review body>"
272
303
  ```
273
304
 
274
- #### Self-review
275
-
276
- Instead of presenting and posting, act on the findings:
305
+ ### Step 7: Apply Fixes (self-review / address-feedback)
277
306
 
278
307
  1. **Fix findings** — Address [major] and [minor] issues directly in code. Apply [nit]s at own discretion.
279
308
  2. **Commit and push** — Commit the fixes with a descriptive message and push to the PR branch.
280
- 3. **Assign reviewer** — Assign the user and request review from anyone mentioned in additional instructions.
281
- 4. **Wait for CI** — Monitor CI status. Once green, mark the PR as ready for review.
309
+ 3. **Monitor CI** — Wait for CI to pass. The PR cannot be finalized until CI is green.
310
+
311
+ ```bash
312
+ gh pr checks <PR_NUMBER> --watch
313
+ ```
314
+
315
+ Fixes are pushed and CI is green. Now finalize the PR — proceed to the section matching your mode below.
316
+
317
+ #### Self-Review Finalization
318
+
319
+ Assign the user and request review from anyone mentioned in additional instructions. Then mark the PR as ready for human review.
282
320
 
283
321
  ```bash
284
322
  gh pr edit <PR_NUMBER> --add-assignee <user> --add-reviewer <reviewer>
285
- # once CI is green:
286
323
  gh pr ready <PR_NUMBER>
287
324
  ```
288
325
 
326
+ Done when the PR is marked ready and appears in the reviewer's queue.
327
+
328
+ #### Address-Feedback Finalization
329
+
330
+ Reply to each reviewer comment on GitHub with the resolution:
331
+ - Accept & fix: "Fixed in `<commit sha>`."
332
+ - Accept, different approach: "Agreed with the concern. Took a different approach: [explanation]. Fixed in `<commit sha>`."
333
+ - Decline: "This was intentional — [rationale]."
334
+
335
+ ```bash
336
+ # Reply to an inline comment
337
+ gh api repos/<OWNER>/<REPO>/pulls/<PR_NUMBER>/comments/<COMMENT_ID>/replies -f body="<reply>"
338
+
339
+ # Reply to a conversation-level comment
340
+ gh api repos/<OWNER>/<REPO>/issues/<PR_NUMBER>/comments -f body="<reply>"
341
+ ```
342
+
343
+ Then request re-review from the original reviewers:
344
+
345
+ ```bash
346
+ gh pr edit <PR_NUMBER> --add-reviewer <original_reviewer>
347
+ ```
348
+
349
+ Done when all comments are answered and re-review is requested.
350
+
289
351
  ## Posted Review Format
290
352
 
291
353
  ```markdown
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: thoughts_init
3
- description: "Initialize the thoughts system for the current repository."
3
+ description: "Bootstrap ./thoughts for a new project that doesn't have one yet."
4
4
  ---
5
5
 
6
6
  # Initialize Thoughts System
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: validate_plan
3
- description: "Validate implementation against plan, verify success criteria, and identify issues."
3
+ description: "Check whether the implementation satisfies the plan compare success criteria against what was actually built."
4
4
  ---
5
5
 
6
6
  # Validate Plan
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: anima-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yevhenii Hurin
@@ -259,7 +259,7 @@ files:
259
259
  - app/controllers/application_controller.rb
260
260
  - app/decorators/agent_message_decorator.rb
261
261
  - app/decorators/application_decorator.rb
262
- - app/decorators/event_decorator.rb
262
+ - app/decorators/message_decorator.rb
263
263
  - app/decorators/system_message_decorator.rb
264
264
  - app/decorators/tool_call_decorator.rb
265
265
  - app/decorators/tool_decorator.rb
@@ -269,15 +269,17 @@ files:
269
269
  - app/jobs/agent_request_job.rb
270
270
  - app/jobs/analytical_brain_job.rb
271
271
  - app/jobs/application_job.rb
272
- - app/jobs/count_event_tokens_job.rb
272
+ - app/jobs/count_message_tokens_job.rb
273
273
  - app/jobs/mneme_job.rb
274
274
  - app/jobs/passive_recall_job.rb
275
275
  - app/models/application_record.rb
276
- - app/models/concerns/event/broadcasting.rb
277
- - app/models/event.rb
276
+ - app/models/concerns/message/broadcasting.rb
278
277
  - app/models/goal.rb
279
- - app/models/goal_pinned_event.rb
280
- - app/models/pinned_event.rb
278
+ - app/models/goal_pinned_message.rb
279
+ - app/models/message.rb
280
+ - app/models/pending_message.rb
281
+ - app/models/pinned_message.rb
282
+ - app/models/secret.rb
281
283
  - app/models/session.rb
282
284
  - app/models/snapshot.rb
283
285
  - bin/jobs
@@ -295,6 +297,7 @@ files:
295
297
  - config/initializers/event_subscribers.rb
296
298
  - config/initializers/fts5_schema_dump.rb
297
299
  - config/initializers/inflections.rb
300
+ - config/initializers/time_nanoseconds.rb
298
301
  - config/puma.rb
299
302
  - config/queue.yml
300
303
  - config/recurring.yml
@@ -323,6 +326,10 @@ files:
323
326
  - db/migrate/20260321120000_create_pinned_events.rb
324
327
  - db/migrate/20260321140000_create_events_fts_index.rb
325
328
  - db/migrate/20260321140100_add_recalled_event_ids_to_sessions.rb
329
+ - db/migrate/20260326180000_rename_event_to_message.rb
330
+ - db/migrate/20260328100000_create_secrets.rb
331
+ - db/migrate/20260328152142_add_evicted_at_to_goals.rb
332
+ - db/migrate/20260329120000_create_pending_messages.rb
326
333
  - db/queue_schema.rb
327
334
  - db/seeds.rb
328
335
  - exe/anima
@@ -377,7 +384,7 @@ files:
377
384
  - lib/mneme/passive_recall.rb
378
385
  - lib/mneme/runner.rb
379
386
  - lib/mneme/search.rb
380
- - lib/mneme/tools/attach_events_to_goals.rb
387
+ - lib/mneme/tools/attach_messages_to_goals.rb
381
388
  - lib/mneme/tools/everything_ok.rb
382
389
  - lib/mneme/tools/save_snapshot.rb
383
390
  - lib/providers/anthropic.rb
@@ -388,11 +395,14 @@ files:
388
395
  - lib/tools/base.rb
389
396
  - lib/tools/bash.rb
390
397
  - lib/tools/edit.rb
398
+ - lib/tools/mark_goal_completed.rb
391
399
  - lib/tools/mcp_tool.rb
400
+ - lib/tools/open_issue.rb
392
401
  - lib/tools/read.rb
402
+ - lib/tools/recall.rb
393
403
  - lib/tools/registry.rb
394
404
  - lib/tools/remember.rb
395
- - lib/tools/request_feature.rb
405
+ - lib/tools/response_truncator.rb
396
406
  - lib/tools/spawn_specialist.rb
397
407
  - lib/tools/spawn_subagent.rb
398
408
  - lib/tools/subagent_prompts.rb
@@ -400,6 +410,7 @@ files:
400
410
  - lib/tools/web_get.rb
401
411
  - lib/tools/write.rb
402
412
  - lib/tui/app.rb
413
+ - lib/tui/braille_spinner.rb
403
414
  - lib/tui/cable_client.rb
404
415
  - lib/tui/decorators/base_decorator.rb
405
416
  - lib/tui/decorators/bash_decorator.rb
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Counts tokens in an event's payload via the Anthropic API and
4
- # caches the result on the event record. Enqueued automatically
5
- # after each LLM event is created.
6
- class CountEventTokensJob < ApplicationJob
7
- queue_as :default
8
-
9
- retry_on Providers::Anthropic::Error, wait: :polynomially_longer, attempts: 3
10
- discard_on ActiveRecord::RecordNotFound
11
-
12
- # @param event_id [Integer] the Event record to count tokens for
13
- def perform(event_id)
14
- event = Event.find(event_id)
15
- return if already_counted?(event)
16
-
17
- provider = Providers::Anthropic.new
18
- messages = [{role: event.api_role, content: event.payload["content"].to_s}]
19
-
20
- token_count = provider.count_tokens(
21
- model: Anima::Settings.model,
22
- messages: messages
23
- )
24
-
25
- # Guard against parallel jobs: reload and re-check before writing.
26
- # Uses update! (not update_all) so {Event::Broadcasting} after_update_commit
27
- # broadcasts the updated token count to connected clients.
28
- event.reload
29
- return if already_counted?(event)
30
-
31
- event.update!(token_count: token_count)
32
- end
33
-
34
- private
35
-
36
- def already_counted?(event)
37
- event.token_count > 0
38
- end
39
- end