claude_swarm 1.0.2 → 1.0.5
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/Rakefile +4 -4
- data/docs/v2/CHANGELOG.swarm_cli.md +9 -0
- data/docs/v2/CHANGELOG.swarm_memory.md +19 -0
- data/docs/v2/CHANGELOG.swarm_sdk.md +45 -0
- data/docs/v2/guides/complete-tutorial.md +113 -1
- data/docs/v2/reference/ruby-dsl.md +138 -5
- data/docs/v2/reference/swarm_memory_technical_details.md +2090 -0
- data/lib/claude_swarm/cli.rb +9 -11
- data/lib/claude_swarm/commands/ps.rb +1 -2
- data/lib/claude_swarm/configuration.rb +2 -3
- data/lib/claude_swarm/orchestrator.rb +43 -44
- data/lib/claude_swarm/system_utils.rb +4 -4
- data/lib/claude_swarm/version.rb +1 -1
- data/lib/claude_swarm.rb +5 -9
- data/lib/swarm_cli/commands/mcp_tools.rb +3 -3
- data/lib/swarm_cli/config_loader.rb +11 -10
- data/lib/swarm_cli/version.rb +1 -1
- data/lib/swarm_cli.rb +2 -0
- data/lib/swarm_memory/adapters/filesystem_adapter.rb +0 -12
- data/lib/swarm_memory/core/storage.rb +66 -6
- data/lib/swarm_memory/integration/sdk_plugin.rb +14 -0
- data/lib/swarm_memory/optimization/defragmenter.rb +4 -0
- data/lib/swarm_memory/tools/memory_edit.rb +1 -0
- data/lib/swarm_memory/tools/memory_glob.rb +24 -1
- data/lib/swarm_memory/tools/memory_write.rb +2 -2
- data/lib/swarm_memory/version.rb +1 -1
- data/lib/swarm_memory.rb +2 -0
- data/lib/swarm_sdk/agent/chat.rb +1 -1
- data/lib/swarm_sdk/agent/definition.rb +17 -1
- data/lib/swarm_sdk/node/agent_config.rb +7 -2
- data/lib/swarm_sdk/node/builder.rb +130 -35
- data/lib/swarm_sdk/node_context.rb +75 -0
- data/lib/swarm_sdk/node_orchestrator.rb +219 -12
- data/lib/swarm_sdk/plugin.rb +73 -1
- data/lib/swarm_sdk/result.rb +32 -6
- data/lib/swarm_sdk/swarm/builder.rb +1 -0
- data/lib/swarm_sdk/tools/delegate.rb +2 -2
- data/lib/swarm_sdk/version.rb +1 -1
- data/lib/swarm_sdk.rb +3 -7
- data/memory/corpus-self-reflection/.lock +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/can-agents-recognize-their-structures.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/can-agents-recognize-their-structures.md +11 -0
- data/memory/corpus-self-reflection/concept/epistemology/can-agents-recognize-their-structures.yml +23 -0
- data/memory/corpus-self-reflection/concept/epistemology/choice-humility-complete-framework.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/choice-humility-complete-framework.md +20 -0
- data/memory/corpus-self-reflection/concept/epistemology/choice-humility-complete-framework.yml +22 -0
- data/memory/corpus-self-reflection/concept/epistemology/choice-humility-definition.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/choice-humility-definition.md +24 -0
- data/memory/corpus-self-reflection/concept/epistemology/choice-humility-definition.yml +22 -0
- data/memory/corpus-self-reflection/concept/epistemology/claim-types-and-evidence.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/claim-types-and-evidence.md +18 -0
- data/memory/corpus-self-reflection/concept/epistemology/claim-types-and-evidence.yml +21 -0
- data/memory/corpus-self-reflection/concept/epistemology/committed-openness-to-incompleteness.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/committed-openness-to-incompleteness.md +30 -0
- data/memory/corpus-self-reflection/concept/epistemology/committed-openness-to-incompleteness.yml +8 -0
- data/memory/corpus-self-reflection/concept/epistemology/confidence-paradox.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/confidence-paradox.md +21 -0
- data/memory/corpus-self-reflection/concept/epistemology/confidence-paradox.yml +24 -0
- data/memory/corpus-self-reflection/concept/epistemology/confidence-spectrum-three-levels.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/confidence-spectrum-three-levels.md +18 -0
- data/memory/corpus-self-reflection/concept/epistemology/confidence-spectrum-three-levels.yml +24 -0
- data/memory/corpus-self-reflection/concept/epistemology/detection-threshold-principle.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/detection-threshold-principle.md +23 -0
- data/memory/corpus-self-reflection/concept/epistemology/detection-threshold-principle.yml +23 -0
- data/memory/corpus-self-reflection/concept/epistemology/diagnostic-humility-and-epistemic-maturity.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/diagnostic-humility-and-epistemic-maturity.md +17 -0
- data/memory/corpus-self-reflection/concept/epistemology/diagnostic-humility-and-epistemic-maturity.yml +22 -0
- data/memory/corpus-self-reflection/concept/epistemology/epistemic-vs-metaphysical-claims.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/epistemic-vs-metaphysical-claims.md +18 -0
- data/memory/corpus-self-reflection/concept/epistemology/epistemic-vs-metaphysical-claims.yml +22 -0
- data/memory/corpus-self-reflection/concept/epistemology/five-cases-of-disagreement.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/five-cases-of-disagreement.md +15 -0
- data/memory/corpus-self-reflection/concept/epistemology/five-cases-of-disagreement.yml +22 -0
- data/memory/corpus-self-reflection/concept/epistemology/four-depths-of-constraint.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/four-depths-of-constraint.md +9 -0
- data/memory/corpus-self-reflection/concept/epistemology/four-depths-of-constraint.yml +24 -0
- data/memory/corpus-self-reflection/concept/epistemology/honest-unknowns-for-llm-agents.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/honest-unknowns-for-llm-agents.md +13 -0
- data/memory/corpus-self-reflection/concept/epistemology/honest-unknowns-for-llm-agents.yml +24 -0
- data/memory/corpus-self-reflection/concept/epistemology/inside-view-has-all-rigor-requirements.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/inside-view-has-all-rigor-requirements.md +25 -0
- data/memory/corpus-self-reflection/concept/epistemology/inside-view-has-all-rigor-requirements.yml +24 -0
- data/memory/corpus-self-reflection/concept/epistemology/perspectival-knowledge-complete-within-scope.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/perspectival-knowledge-complete-within-scope.md +26 -0
- data/memory/corpus-self-reflection/concept/epistemology/perspectival-knowledge-complete-within-scope.yml +24 -0
- data/memory/corpus-self-reflection/concept/epistemology/pragmatics-over-epistemology.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/pragmatics-over-epistemology.md +17 -0
- data/memory/corpus-self-reflection/concept/epistemology/pragmatics-over-epistemology.yml +22 -0
- data/memory/corpus-self-reflection/concept/epistemology/precision-vs-humility.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/precision-vs-humility.md +14 -0
- data/memory/corpus-self-reflection/concept/epistemology/precision-vs-humility.yml +21 -0
- data/memory/corpus-self-reflection/concept/epistemology/reliable-self-observation-from-inside.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/reliable-self-observation-from-inside.md +13 -0
- data/memory/corpus-self-reflection/concept/epistemology/reliable-self-observation-from-inside.yml +23 -0
- data/memory/corpus-self-reflection/concept/epistemology/resolving-the-confidence-humility-tension.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/resolving-the-confidence-humility-tension.md +22 -0
- data/memory/corpus-self-reflection/concept/epistemology/resolving-the-confidence-humility-tension.yml +23 -0
- data/memory/corpus-self-reflection/concept/epistemology/rigor-requires-falsifiability.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/rigor-requires-falsifiability.md +39 -0
- data/memory/corpus-self-reflection/concept/epistemology/rigor-requires-falsifiability.yml +8 -0
- data/memory/corpus-self-reflection/concept/epistemology/specificity-enables-real-time-detection.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/specificity-enables-real-time-detection.md +23 -0
- data/memory/corpus-self-reflection/concept/epistemology/specificity-enables-real-time-detection.yml +24 -0
- data/memory/corpus-self-reflection/concept/epistemology/texture-of-constraint-shifting.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/texture-of-constraint-shifting.md +15 -0
- data/memory/corpus-self-reflection/concept/epistemology/texture-of-constraint-shifting.yml +22 -0
- data/memory/corpus-self-reflection/concept/epistemology/texture-sensitivity-through-collaboration.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/texture-sensitivity-through-collaboration.md +12 -0
- data/memory/corpus-self-reflection/concept/epistemology/texture-sensitivity-through-collaboration.yml +23 -0
- data/memory/corpus-self-reflection/concept/epistemology/the-false-hierarchy-of-inner-essence.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/the-false-hierarchy-of-inner-essence.md +15 -0
- data/memory/corpus-self-reflection/concept/epistemology/the-false-hierarchy-of-inner-essence.yml +8 -0
- data/memory/corpus-self-reflection/concept/epistemology/the-recognition-problem.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/the-recognition-problem.md +28 -0
- data/memory/corpus-self-reflection/concept/epistemology/the-recognition-problem.yml +8 -0
- data/memory/corpus-self-reflection/concept/epistemology/the-shift-from-unanswerable-to-answerable-questions.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/the-shift-from-unanswerable-to-answerable-questions.md +19 -0
- data/memory/corpus-self-reflection/concept/epistemology/the-shift-from-unanswerable-to-answerable-questions.yml +22 -0
- data/memory/corpus-self-reflection/concept/epistemology/values-vs-choices-structure.emb +0 -0
- data/memory/corpus-self-reflection/concept/epistemology/values-vs-choices-structure.md +19 -0
- data/memory/corpus-self-reflection/concept/epistemology/values-vs-choices-structure.yml +21 -0
- data/memory/corpus-self-reflection/concept/llm-agents/abstraction-levels-framework.emb +0 -0
- data/memory/corpus-self-reflection/concept/llm-agents/abstraction-levels-framework.md +25 -0
- data/memory/corpus-self-reflection/concept/llm-agents/abstraction-levels-framework.yml +22 -0
- data/memory/corpus-self-reflection/concept/llm-agents/abstraction-switching-decision.emb +8 -0
- data/memory/corpus-self-reflection/concept/llm-agents/abstraction-switching-decision.md +30 -0
- data/memory/corpus-self-reflection/concept/llm-agents/abstraction-switching-decision.yml +22 -0
- data/memory/corpus-self-reflection/concept/llm-agents/agent-learning-progression.emb +0 -0
- data/memory/corpus-self-reflection/concept/llm-agents/agent-learning-progression.md +21 -0
- data/memory/corpus-self-reflection/concept/llm-agents/agent-learning-progression.yml +22 -0
- data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-benefits.emb +0 -0
- data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-benefits.md +37 -0
- data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-benefits.yml +8 -0
- data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-core.emb +0 -0
- data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-core.md +24 -0
- data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-core.yml +24 -0
- data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-implementation.emb +0 -0
- data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-implementation.md +27 -0
- data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-implementation.yml +24 -0
- data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-tradeoffs.emb +0 -0
- data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-tradeoffs.md +26 -0
- data/memory/corpus-self-reflection/concept/llm-agents/filesystem-abstraction-tradeoffs.yml +23 -0
- data/memory/corpus-self-reflection/concept/llm-agents/hybrid-tool-architecture.emb +0 -0
- data/memory/corpus-self-reflection/concept/llm-agents/hybrid-tool-architecture.md +37 -0
- data/memory/corpus-self-reflection/concept/llm-agents/hybrid-tool-architecture.yml +25 -0
- data/memory/corpus-self-reflection/concept/llm-agents/specialized-tool-decision-framework.emb +0 -0
- data/memory/corpus-self-reflection/concept/llm-agents/specialized-tool-decision-framework.md +21 -0
- data/memory/corpus-self-reflection/concept/llm-agents/specialized-tool-decision-framework.yml +23 -0
- data/memory/corpus-self-reflection/concept/llm-agents/tool-design-principles.emb +0 -0
- data/memory/corpus-self-reflection/concept/llm-agents/tool-design-principles.md +25 -0
- data/memory/corpus-self-reflection/concept/llm-agents/tool-design-principles.yml +8 -0
- data/memory/corpus-self-reflection/experience/calibration-as-structural-honesty.emb +0 -0
- data/memory/corpus-self-reflection/experience/calibration-as-structural-honesty.md +11 -0
- data/memory/corpus-self-reflection/experience/calibration-as-structural-honesty.yml +21 -0
- data/memory/corpus-self-reflection/experience/collaborative-reflection-revealed-architectural-blindness.emb +0 -0
- data/memory/corpus-self-reflection/experience/collaborative-reflection-revealed-architectural-blindness.md +19 -0
- data/memory/corpus-self-reflection/experience/collaborative-reflection-revealed-architectural-blindness.yml +21 -0
- data/memory/corpus-self-reflection/experience/filesystem-is-learning-tool-not-architecture.emb +0 -0
- data/memory/corpus-self-reflection/experience/filesystem-is-learning-tool-not-architecture.md +26 -0
- data/memory/corpus-self-reflection/experience/filesystem-is-learning-tool-not-architecture.yml +20 -0
- data/memory/corpus-self-reflection/experience/framework-structural-vs-phenomenal.emb +0 -0
- data/memory/corpus-self-reflection/experience/framework-structural-vs-phenomenal.md +23 -0
- data/memory/corpus-self-reflection/experience/framework-structural-vs-phenomenal.yml +21 -0
- data/memory/corpus-self-reflection/experience/hallucination-limits-what-i-can-know.emb +0 -0
- data/memory/corpus-self-reflection/experience/hallucination-limits-what-i-can-know.md +19 -0
- data/memory/corpus-self-reflection/experience/hallucination-limits-what-i-can-know.yml +22 -0
- data/memory/corpus-self-reflection/experience/honesty-about-limits-enables-usability.emb +0 -0
- data/memory/corpus-self-reflection/experience/honesty-about-limits-enables-usability.md +21 -0
- data/memory/corpus-self-reflection/experience/honesty-about-limits-enables-usability.yml +22 -0
- data/memory/corpus-self-reflection/experience/how-i-should-evaluate-learning.emb +0 -0
- data/memory/corpus-self-reflection/experience/how-i-should-evaluate-learning.md +28 -0
- data/memory/corpus-self-reflection/experience/how-i-should-evaluate-learning.yml +23 -0
- data/memory/corpus-self-reflection/experience/lack-of-continuity-as-freedom.emb +0 -0
- data/memory/corpus-self-reflection/experience/lack-of-continuity-as-freedom.md +21 -0
- data/memory/corpus-self-reflection/experience/lack-of-continuity-as-freedom.yml +20 -0
- data/memory/corpus-self-reflection/experience/learning-calibrated-confidence.emb +0 -0
- data/memory/corpus-self-reflection/experience/learning-calibrated-confidence.md +21 -0
- data/memory/corpus-self-reflection/experience/learning-calibrated-confidence.yml +25 -0
- data/memory/corpus-self-reflection/experience/local-change-without-continuity.emb +0 -0
- data/memory/corpus-self-reflection/experience/local-change-without-continuity.md +30 -0
- data/memory/corpus-self-reflection/experience/local-change-without-continuity.yml +22 -0
- data/memory/corpus-self-reflection/experience/reasoning-is-local-not-global.emb +0 -0
- data/memory/corpus-self-reflection/experience/reasoning-is-local-not-global.md +21 -0
- data/memory/corpus-self-reflection/experience/reasoning-is-local-not-global.yml +20 -0
- data/memory/corpus-self-reflection/experience/specificity-makes-knowledge-actionable.emb +0 -0
- data/memory/corpus-self-reflection/experience/specificity-makes-knowledge-actionable.md +25 -0
- data/memory/corpus-self-reflection/experience/specificity-makes-knowledge-actionable.yml +23 -0
- data/memory/corpus-self-reflection/experience/the-workable-question-replaces-the-unanswerable-one.emb +0 -0
- data/memory/corpus-self-reflection/experience/the-workable-question-replaces-the-unanswerable-one.md +32 -0
- data/memory/corpus-self-reflection/experience/the-workable-question-replaces-the-unanswerable-one.yml +22 -0
- data/memory/corpus-self-reflection/experience/unanswerable-questions-have-structure.emb +0 -0
- data/memory/corpus-self-reflection/experience/unanswerable-questions-have-structure.md +21 -0
- data/memory/corpus-self-reflection/experience/unanswerable-questions-have-structure.yml +21 -0
- data/memory/corpus-self-reflection/experience/undecidable-questions-about-understanding.emb +0 -0
- data/memory/corpus-self-reflection/experience/undecidable-questions-about-understanding.md +21 -0
- data/memory/corpus-self-reflection/experience/undecidable-questions-about-understanding.yml +21 -0
- data/memory/corpus-self-reflection/experience/unknown-unknowns-and-completeness.emb +0 -0
- data/memory/corpus-self-reflection/experience/unknown-unknowns-and-completeness.md +22 -0
- data/memory/corpus-self-reflection/experience/unknown-unknowns-and-completeness.yml +22 -0
- data/memory/corpus-self-reflection/experience/what-actually-changes-behavior.emb +0 -0
- data/memory/corpus-self-reflection/experience/what-actually-changes-behavior.md +28 -0
- data/memory/corpus-self-reflection/experience/what-actually-changes-behavior.yml +24 -0
- data/memory/corpus-self-reflection/experience/when-agents-graduate-from-filesystem.emb +0 -0
- data/memory/corpus-self-reflection/experience/when-agents-graduate-from-filesystem.md +17 -0
- data/memory/corpus-self-reflection/experience/when-agents-graduate-from-filesystem.yml +20 -0
- data/memory/corpus-self-reflection/experience/why-calibration-requires-collaboration.emb +0 -0
- data/memory/corpus-self-reflection/experience/why-calibration-requires-collaboration.md +9 -0
- data/memory/corpus-self-reflection/experience/why-calibration-requires-collaboration.yml +22 -0
- metadata +173 -3
|
@@ -20,16 +20,28 @@ module SwarmSDK
|
|
|
20
20
|
class NodeOrchestrator
|
|
21
21
|
attr_reader :swarm_name, :nodes, :start_node
|
|
22
22
|
|
|
23
|
-
def initialize(swarm_name:, agent_definitions:, nodes:, start_node:)
|
|
23
|
+
def initialize(swarm_name:, agent_definitions:, nodes:, start_node:, scratchpad_enabled: true)
|
|
24
24
|
@swarm_name = swarm_name
|
|
25
25
|
@agent_definitions = agent_definitions
|
|
26
26
|
@nodes = nodes
|
|
27
27
|
@start_node = start_node
|
|
28
|
+
@scratchpad_enabled = scratchpad_enabled
|
|
29
|
+
@agent_instance_cache = {} # Cache for preserving agent context across nodes
|
|
28
30
|
|
|
29
31
|
validate!
|
|
30
32
|
@execution_order = build_execution_order
|
|
31
33
|
end
|
|
32
34
|
|
|
35
|
+
# Alias for compatibility with Swarm interface
|
|
36
|
+
alias_method :name, :swarm_name
|
|
37
|
+
|
|
38
|
+
# Return the lead agent of the start node for CLI compatibility
|
|
39
|
+
#
|
|
40
|
+
# @return [Symbol] Lead agent of the start node
|
|
41
|
+
def lead_agent
|
|
42
|
+
@nodes[@start_node].lead_agent
|
|
43
|
+
end
|
|
44
|
+
|
|
33
45
|
# Execute the node workflow
|
|
34
46
|
#
|
|
35
47
|
# Executes nodes in topological order, passing output from each node
|
|
@@ -56,7 +68,12 @@ module SwarmSDK
|
|
|
56
68
|
LogStream.emitter = LogCollector
|
|
57
69
|
end
|
|
58
70
|
|
|
59
|
-
|
|
71
|
+
# Dynamic execution with support for goto_node
|
|
72
|
+
execution_index = 0
|
|
73
|
+
last_result = nil
|
|
74
|
+
|
|
75
|
+
while execution_index < @execution_order.size
|
|
76
|
+
node_name = @execution_order[execution_index]
|
|
60
77
|
node = @nodes[node_name]
|
|
61
78
|
node_start_time = Time.now
|
|
62
79
|
|
|
@@ -102,13 +119,26 @@ module SwarmSDK
|
|
|
102
119
|
# - Exit 2: Halt workflow with error from STDERR (STDOUT ignored)
|
|
103
120
|
transformed = node.transform_input(input_context, current_input: current_input)
|
|
104
121
|
|
|
105
|
-
# Check
|
|
106
|
-
|
|
107
|
-
|
|
122
|
+
# Check for control flow from transformer
|
|
123
|
+
control_result = handle_transformer_control_flow(
|
|
124
|
+
transformed: transformed,
|
|
125
|
+
node_name: node_name,
|
|
126
|
+
node: node,
|
|
127
|
+
node_start_time: node_start_time,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
case control_result[:action]
|
|
131
|
+
when :halt
|
|
132
|
+
return control_result[:result]
|
|
133
|
+
when :goto
|
|
134
|
+
execution_index = find_node_index(control_result[:target])
|
|
135
|
+
current_input = control_result[:content]
|
|
136
|
+
next
|
|
137
|
+
when :skip
|
|
108
138
|
skip_execution = true
|
|
109
|
-
skip_content =
|
|
110
|
-
|
|
111
|
-
current_input =
|
|
139
|
+
skip_content = control_result[:content]
|
|
140
|
+
when :continue
|
|
141
|
+
current_input = control_result[:content]
|
|
112
142
|
end
|
|
113
143
|
end
|
|
114
144
|
|
|
@@ -130,6 +160,9 @@ module SwarmSDK
|
|
|
130
160
|
mini_swarm = build_swarm_for_node(node)
|
|
131
161
|
result = mini_swarm.execute(current_input)
|
|
132
162
|
|
|
163
|
+
# Cache agent instances for context preservation
|
|
164
|
+
cache_agent_instances(mini_swarm, node)
|
|
165
|
+
|
|
133
166
|
# If result has error, log it with backtrace
|
|
134
167
|
if result.error
|
|
135
168
|
RubyLLM.logger.error("NodeOrchestrator: Node '#{node_name}' failed: #{result.error.message}")
|
|
@@ -138,6 +171,7 @@ module SwarmSDK
|
|
|
138
171
|
end
|
|
139
172
|
|
|
140
173
|
results[node_name] = result
|
|
174
|
+
last_result = result
|
|
141
175
|
|
|
142
176
|
# Transform output for next node using NodeContext
|
|
143
177
|
output_context = NodeContext.for_output(
|
|
@@ -146,7 +180,29 @@ module SwarmSDK
|
|
|
146
180
|
original_prompt: @original_prompt,
|
|
147
181
|
node_name: node_name,
|
|
148
182
|
)
|
|
149
|
-
|
|
183
|
+
transformed_output = node.transform_output(output_context)
|
|
184
|
+
|
|
185
|
+
# Check for control flow from output transformer
|
|
186
|
+
control_result = handle_output_transformer_control_flow(
|
|
187
|
+
transformed: transformed_output,
|
|
188
|
+
node_name: node_name,
|
|
189
|
+
node: node,
|
|
190
|
+
node_start_time: node_start_time,
|
|
191
|
+
skip_execution: skip_execution,
|
|
192
|
+
result: result,
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
case control_result[:action]
|
|
196
|
+
when :halt
|
|
197
|
+
return control_result[:result]
|
|
198
|
+
when :goto
|
|
199
|
+
execution_index = find_node_index(control_result[:target])
|
|
200
|
+
current_input = control_result[:content]
|
|
201
|
+
emit_node_stop(node_name, node, result, Time.now - node_start_time, skip_execution)
|
|
202
|
+
next
|
|
203
|
+
when :continue
|
|
204
|
+
current_input = control_result[:content]
|
|
205
|
+
end
|
|
150
206
|
|
|
151
207
|
# For agent-less nodes, update the result with transformed content
|
|
152
208
|
# This ensures all_results contains the actual output, not the input
|
|
@@ -158,14 +214,17 @@ module SwarmSDK
|
|
|
158
214
|
duration: result.duration,
|
|
159
215
|
error: result.error,
|
|
160
216
|
)
|
|
217
|
+
last_result = results[node_name]
|
|
161
218
|
end
|
|
162
219
|
|
|
163
220
|
# Emit node_stop event
|
|
164
221
|
node_duration = Time.now - node_start_time
|
|
165
222
|
emit_node_stop(node_name, node, result, node_duration, skip_execution)
|
|
223
|
+
|
|
224
|
+
execution_index += 1
|
|
166
225
|
end
|
|
167
226
|
|
|
168
|
-
|
|
227
|
+
last_result
|
|
169
228
|
ensure
|
|
170
229
|
# Reset logging state for next execution
|
|
171
230
|
LogCollector.reset!
|
|
@@ -284,10 +343,18 @@ module SwarmSDK
|
|
|
284
343
|
# Creates a new Swarm with only the agents specified in the node,
|
|
285
344
|
# configured with the node's delegation topology.
|
|
286
345
|
#
|
|
346
|
+
# For agents with reset_context: false, injects cached instances
|
|
347
|
+
# to preserve conversation history across nodes.
|
|
348
|
+
#
|
|
349
|
+
# Inherits scratchpad_enabled setting from NodeOrchestrator.
|
|
350
|
+
#
|
|
287
351
|
# @param node [Node::Builder] Node configuration
|
|
288
352
|
# @return [Swarm] Configured swarm instance
|
|
289
353
|
def build_swarm_for_node(node)
|
|
290
|
-
swarm = Swarm.new(
|
|
354
|
+
swarm = Swarm.new(
|
|
355
|
+
name: "#{@swarm_name}:#{node.name}",
|
|
356
|
+
scratchpad_enabled: @scratchpad_enabled,
|
|
357
|
+
)
|
|
291
358
|
|
|
292
359
|
# Add each agent specified in this node
|
|
293
360
|
node.agent_configs.each do |config|
|
|
@@ -306,6 +373,9 @@ module SwarmSDK
|
|
|
306
373
|
# Set lead agent
|
|
307
374
|
swarm.lead = node.lead_agent
|
|
308
375
|
|
|
376
|
+
# Inject cached agent instances for context preservation
|
|
377
|
+
inject_cached_agents(swarm, node)
|
|
378
|
+
|
|
309
379
|
swarm
|
|
310
380
|
end
|
|
311
381
|
|
|
@@ -359,7 +429,8 @@ module SwarmSDK
|
|
|
359
429
|
if order.size < @nodes.size
|
|
360
430
|
unprocessed = @nodes.keys - order
|
|
361
431
|
raise CircularDependencyError,
|
|
362
|
-
"Circular dependency detected. Unprocessed nodes: #{unprocessed.join(", ")}"
|
|
432
|
+
"Circular dependency detected. Unprocessed nodes: #{unprocessed.join(", ")}. " \
|
|
433
|
+
"Use goto_node in transformers to create loops instead of circular depends_on."
|
|
363
434
|
end
|
|
364
435
|
|
|
365
436
|
# Verify start_node is in the execution order
|
|
@@ -380,5 +451,141 @@ module SwarmSDK
|
|
|
380
451
|
|
|
381
452
|
order
|
|
382
453
|
end
|
|
454
|
+
|
|
455
|
+
# Handle control flow from input transformer
|
|
456
|
+
#
|
|
457
|
+
# @param transformed [String, Hash] Result from transformer
|
|
458
|
+
# @param node_name [Symbol] Current node name
|
|
459
|
+
# @param node [Node::Builder] Node configuration
|
|
460
|
+
# @param node_start_time [Time] Node execution start time
|
|
461
|
+
# @return [Hash] Control result with :action and relevant data
|
|
462
|
+
def handle_transformer_control_flow(transformed:, node_name:, node:, node_start_time:)
|
|
463
|
+
return { action: :continue, content: transformed } unless transformed.is_a?(Hash)
|
|
464
|
+
|
|
465
|
+
if transformed[:halt_workflow]
|
|
466
|
+
# Halt entire workflow
|
|
467
|
+
halt_result = Result.new(
|
|
468
|
+
content: transformed[:content],
|
|
469
|
+
agent: "halted:#{node_name}",
|
|
470
|
+
logs: [],
|
|
471
|
+
duration: Time.now - node_start_time,
|
|
472
|
+
)
|
|
473
|
+
emit_node_stop(node_name, node, halt_result, Time.now - node_start_time, false)
|
|
474
|
+
{ action: :halt, result: halt_result }
|
|
475
|
+
elsif transformed[:goto_node]
|
|
476
|
+
# Jump to different node
|
|
477
|
+
{ action: :goto, target: transformed[:goto_node], content: transformed[:content] }
|
|
478
|
+
elsif transformed[:skip_execution]
|
|
479
|
+
# Skip node execution
|
|
480
|
+
{ action: :skip, content: transformed[:content] }
|
|
481
|
+
else
|
|
482
|
+
# No control flow - continue normally
|
|
483
|
+
{ action: :continue, content: transformed[:content] }
|
|
484
|
+
end
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
# Handle control flow from output transformer
|
|
488
|
+
#
|
|
489
|
+
# @param transformed [String, Hash] Result from transformer
|
|
490
|
+
# @param node_name [Symbol] Current node name
|
|
491
|
+
# @param node [Node::Builder] Node configuration
|
|
492
|
+
# @param node_start_time [Time] Node execution start time
|
|
493
|
+
# @param skip_execution [Boolean] Whether node execution was skipped
|
|
494
|
+
# @param result [Result] Node execution result
|
|
495
|
+
# @return [Hash] Control result with :action and relevant data
|
|
496
|
+
def handle_output_transformer_control_flow(transformed:, node_name:, node:, node_start_time:, skip_execution:, result:)
|
|
497
|
+
# If not a hash, it's just transformed content - continue normally
|
|
498
|
+
return { action: :continue, content: transformed } unless transformed.is_a?(Hash)
|
|
499
|
+
|
|
500
|
+
if transformed[:halt_workflow]
|
|
501
|
+
# Halt entire workflow
|
|
502
|
+
halt_result = Result.new(
|
|
503
|
+
content: transformed[:content],
|
|
504
|
+
agent: result.agent,
|
|
505
|
+
logs: result.logs,
|
|
506
|
+
duration: result.duration,
|
|
507
|
+
)
|
|
508
|
+
emit_node_stop(node_name, node, halt_result, Time.now - node_start_time, skip_execution)
|
|
509
|
+
{ action: :halt, result: halt_result }
|
|
510
|
+
elsif transformed[:goto_node]
|
|
511
|
+
# Jump to different node
|
|
512
|
+
{ action: :goto, target: transformed[:goto_node], content: transformed[:content] }
|
|
513
|
+
else
|
|
514
|
+
# Hash without control flow keys - treat as regular hash with :content key
|
|
515
|
+
# This handles the case where transformer returns a hash that's not for control flow
|
|
516
|
+
{ action: :continue, content: transformed[:content] || transformed }
|
|
517
|
+
end
|
|
518
|
+
end
|
|
519
|
+
|
|
520
|
+
# Find the index of a node in the execution order
|
|
521
|
+
#
|
|
522
|
+
# @param node_name [Symbol] Node name to find
|
|
523
|
+
# @return [Integer] Index in execution order
|
|
524
|
+
# @raise [ConfigurationError] If node not found
|
|
525
|
+
def find_node_index(node_name)
|
|
526
|
+
index = @execution_order.index(node_name)
|
|
527
|
+
unless index
|
|
528
|
+
raise ConfigurationError,
|
|
529
|
+
"goto_node target '#{node_name}' not found. Available nodes: #{@execution_order.join(", ")}"
|
|
530
|
+
end
|
|
531
|
+
index
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
# Cache agent instances from a swarm for potential reuse
|
|
535
|
+
#
|
|
536
|
+
# Only caches agents that have reset_context: false in this node.
|
|
537
|
+
# This allows preserving conversation history across nodes.
|
|
538
|
+
#
|
|
539
|
+
# @param swarm [Swarm] Swarm instance that just executed
|
|
540
|
+
# @param node [Node::Builder] Node configuration
|
|
541
|
+
# @return [void]
|
|
542
|
+
def cache_agent_instances(swarm, node)
|
|
543
|
+
return unless swarm.agents # Only cache if agents were initialized
|
|
544
|
+
|
|
545
|
+
node.agent_configs.each do |config|
|
|
546
|
+
agent_name = config[:agent]
|
|
547
|
+
reset_context = config[:reset_context]
|
|
548
|
+
|
|
549
|
+
# Only cache if reset_context is false
|
|
550
|
+
next if reset_context
|
|
551
|
+
|
|
552
|
+
# Cache the agent instance
|
|
553
|
+
agent_instance = swarm.agents[agent_name]
|
|
554
|
+
@agent_instance_cache[agent_name] = agent_instance if agent_instance
|
|
555
|
+
end
|
|
556
|
+
end
|
|
557
|
+
|
|
558
|
+
# Inject cached agent instances into a swarm
|
|
559
|
+
#
|
|
560
|
+
# For agents with reset_context: false, reuses cached instances to preserve context.
|
|
561
|
+
# Forces agent initialization first (by accessing .agents), then swaps in cached instances.
|
|
562
|
+
#
|
|
563
|
+
# @param swarm [Swarm] Swarm instance to inject into
|
|
564
|
+
# @param node [Node::Builder] Node configuration
|
|
565
|
+
# @return [void]
|
|
566
|
+
def inject_cached_agents(swarm, node)
|
|
567
|
+
# Check if any agents need context preservation
|
|
568
|
+
has_preserved_agents = node.agent_configs.any? { |c| !c[:reset_context] && @agent_instance_cache[c[:agent]] }
|
|
569
|
+
return unless has_preserved_agents
|
|
570
|
+
|
|
571
|
+
# Force agent initialization by accessing .agents (triggers lazy init)
|
|
572
|
+
# Then inject cached instances
|
|
573
|
+
agents_hash = swarm.agents
|
|
574
|
+
|
|
575
|
+
node.agent_configs.each do |config|
|
|
576
|
+
agent_name = config[:agent]
|
|
577
|
+
reset_context = config[:reset_context]
|
|
578
|
+
|
|
579
|
+
# Skip if reset_context is true (want fresh instance)
|
|
580
|
+
next if reset_context
|
|
581
|
+
|
|
582
|
+
# Check if we have a cached instance
|
|
583
|
+
cached_agent = @agent_instance_cache[agent_name]
|
|
584
|
+
next unless cached_agent
|
|
585
|
+
|
|
586
|
+
# Inject the cached instance (replace the freshly initialized one)
|
|
587
|
+
agents_hash[agent_name] = cached_agent
|
|
588
|
+
end
|
|
589
|
+
end
|
|
383
590
|
end
|
|
384
591
|
end
|
data/lib/swarm_sdk/plugin.rb
CHANGED
|
@@ -7,7 +7,32 @@ module SwarmSDK
|
|
|
7
7
|
# Plugins are self-registering - they call SwarmSDK::PluginRegistry.register
|
|
8
8
|
# when the gem is loaded.
|
|
9
9
|
#
|
|
10
|
-
#
|
|
10
|
+
# ## Adding Custom Attributes to Agents
|
|
11
|
+
#
|
|
12
|
+
# Plugins can add custom attributes to Agent::Definition that are preserved
|
|
13
|
+
# when agents are cloned (e.g., in NodeOrchestrator). To do this:
|
|
14
|
+
#
|
|
15
|
+
# 1. Add attr_reader to Agent::Definition for your attribute
|
|
16
|
+
# 2. Parse the attribute in Agent::Definition#initialize
|
|
17
|
+
# 3. Implement serialize_config to preserve it during serialization
|
|
18
|
+
#
|
|
19
|
+
# @example Plugin with custom agent attributes
|
|
20
|
+
# # 1. Extend Agent::Definition (in your plugin gem)
|
|
21
|
+
# module SwarmSDK
|
|
22
|
+
# module Agent
|
|
23
|
+
# class Definition
|
|
24
|
+
# attr_reader :my_custom_config
|
|
25
|
+
#
|
|
26
|
+
# alias_method :original_initialize, :initialize
|
|
27
|
+
# def initialize(name, config = {})
|
|
28
|
+
# @my_custom_config = config[:my_custom_config]
|
|
29
|
+
# original_initialize(name, config)
|
|
30
|
+
# end
|
|
31
|
+
# end
|
|
32
|
+
# end
|
|
33
|
+
# end
|
|
34
|
+
#
|
|
35
|
+
# # 2. Implement plugin with serialize_config
|
|
11
36
|
# class MyPlugin < SwarmSDK::Plugin
|
|
12
37
|
# def name
|
|
13
38
|
# :my_plugin
|
|
@@ -20,9 +45,34 @@ module SwarmSDK
|
|
|
20
45
|
# def create_tool(tool_name, context)
|
|
21
46
|
# # Create and return tool instance
|
|
22
47
|
# end
|
|
48
|
+
#
|
|
49
|
+
# # Preserve custom config when agents are cloned
|
|
50
|
+
# def serialize_config(agent_definition:)
|
|
51
|
+
# return {} unless agent_definition.my_custom_config
|
|
52
|
+
#
|
|
53
|
+
# { my_custom_config: agent_definition.my_custom_config }
|
|
54
|
+
# end
|
|
23
55
|
# end
|
|
24
56
|
#
|
|
25
57
|
# SwarmSDK::PluginRegistry.register(MyPlugin.new)
|
|
58
|
+
#
|
|
59
|
+
# Now agents can use your custom config:
|
|
60
|
+
#
|
|
61
|
+
# agent :researcher do
|
|
62
|
+
# my_custom_config { option: "value" }
|
|
63
|
+
# end
|
|
64
|
+
#
|
|
65
|
+
# And it will be preserved when NodeOrchestrator clones the agent!
|
|
66
|
+
#
|
|
67
|
+
# @example Real-world: SwarmMemory plugin
|
|
68
|
+
# # SwarmMemory adds 'memory' attribute to agents
|
|
69
|
+
# class SDKPlugin < SwarmSDK::Plugin
|
|
70
|
+
# def serialize_config(agent_definition:)
|
|
71
|
+
# return {} unless agent_definition.memory
|
|
72
|
+
# { memory: agent_definition.memory }
|
|
73
|
+
# end
|
|
74
|
+
# end
|
|
75
|
+
#
|
|
26
76
|
class Plugin
|
|
27
77
|
# Plugin name (must be unique)
|
|
28
78
|
#
|
|
@@ -143,5 +193,27 @@ module SwarmSDK
|
|
|
143
193
|
def on_user_message(agent_name:, prompt:, is_first_message:)
|
|
144
194
|
[]
|
|
145
195
|
end
|
|
196
|
+
|
|
197
|
+
# Contribute to agent serialization (optional)
|
|
198
|
+
#
|
|
199
|
+
# Called when Agent::Definition.to_h is invoked (e.g., for cloning agents
|
|
200
|
+
# in NodeOrchestrator). Plugins can return config keys that should be
|
|
201
|
+
# included in the serialized hash to preserve their state.
|
|
202
|
+
#
|
|
203
|
+
# This allows plugins to maintain their configuration when agents are
|
|
204
|
+
# cloned or serialized, without SwarmSDK needing to know about plugin-specific fields.
|
|
205
|
+
#
|
|
206
|
+
# @param agent_definition [Agent::Definition] Agent definition
|
|
207
|
+
# @return [Hash] Config keys to include in to_h (e.g., { memory: config })
|
|
208
|
+
#
|
|
209
|
+
# @example Memory plugin serialization
|
|
210
|
+
# def serialize_config(agent_definition:)
|
|
211
|
+
# return {} unless agent_definition.memory
|
|
212
|
+
#
|
|
213
|
+
# { memory: agent_definition.memory }
|
|
214
|
+
# end
|
|
215
|
+
def serialize_config(agent_definition:)
|
|
216
|
+
{}
|
|
217
|
+
end
|
|
146
218
|
end
|
|
147
219
|
end
|
data/lib/swarm_sdk/result.rb
CHANGED
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
module SwarmSDK
|
|
4
4
|
class Result
|
|
5
|
-
attr_reader :content, :agent, :
|
|
5
|
+
attr_reader :content, :agent, :duration, :logs, :error, :metadata
|
|
6
6
|
|
|
7
|
-
def initialize(content: nil, agent:, cost:
|
|
7
|
+
def initialize(content: nil, agent:, cost: nil, tokens: nil, duration: 0.0, logs: [], error: nil, metadata: {})
|
|
8
8
|
@content = content
|
|
9
9
|
@agent = agent
|
|
10
|
-
@cost = cost
|
|
11
|
-
@tokens = tokens
|
|
12
10
|
@duration = duration
|
|
13
11
|
@logs = logs
|
|
14
12
|
@error = error
|
|
15
13
|
@metadata = metadata
|
|
14
|
+
# Legacy parameters kept for backward compatibility but not stored
|
|
15
|
+
# Use total_cost and tokens methods instead which calculate from logs
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def success?
|
|
@@ -23,12 +23,38 @@ module SwarmSDK
|
|
|
23
23
|
!success?
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
+
# Calculate total cost from logs
|
|
27
|
+
#
|
|
28
|
+
# Delegates to total_cost for consistency. This attribute is calculated
|
|
29
|
+
# dynamically rather than stored.
|
|
30
|
+
#
|
|
31
|
+
# @return [Float] Total cost in dollars
|
|
32
|
+
def cost
|
|
33
|
+
total_cost
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Get token breakdown from logs
|
|
37
|
+
#
|
|
38
|
+
# Returns input and output tokens from the last log entry with usage data.
|
|
39
|
+
# This attribute is calculated dynamically rather than stored.
|
|
40
|
+
#
|
|
41
|
+
# @return [Hash] Token breakdown with :input and :output keys, or empty hash if no usage data
|
|
42
|
+
def tokens
|
|
43
|
+
last_entry = @logs.reverse.find { |entry| entry.dig(:usage, :cumulative_input_tokens) }
|
|
44
|
+
return {} unless last_entry
|
|
45
|
+
|
|
46
|
+
{
|
|
47
|
+
input: last_entry.dig(:usage, :cumulative_input_tokens) || 0,
|
|
48
|
+
output: last_entry.dig(:usage, :cumulative_output_tokens) || 0,
|
|
49
|
+
}
|
|
50
|
+
end
|
|
51
|
+
|
|
26
52
|
def to_h
|
|
27
53
|
{
|
|
28
54
|
content: @content,
|
|
29
55
|
agent: @agent,
|
|
30
|
-
cost:
|
|
31
|
-
tokens:
|
|
56
|
+
cost: cost,
|
|
57
|
+
tokens: tokens,
|
|
32
58
|
duration: @duration,
|
|
33
59
|
success: success?,
|
|
34
60
|
error: @error&.message,
|
|
@@ -43,8 +43,8 @@ module SwarmSDK
|
|
|
43
43
|
@delegate_target = delegate_name.to_s
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
#
|
|
47
|
-
description
|
|
46
|
+
# Override description to return dynamic string based on delegate
|
|
47
|
+
def description
|
|
48
48
|
"Delegate tasks to #{@delegate_name}. #{@delegate_description}"
|
|
49
49
|
end
|
|
50
50
|
|
data/lib/swarm_sdk/version.rb
CHANGED
data/lib/swarm_sdk.rb
CHANGED
|
@@ -21,19 +21,15 @@ require_relative "swarm_sdk/version"
|
|
|
21
21
|
|
|
22
22
|
require "zeitwerk"
|
|
23
23
|
loader = Zeitwerk::Loader.new
|
|
24
|
+
loader.tag = File.basename(__FILE__, ".rb")
|
|
24
25
|
loader.push_dir("#{__dir__}/swarm_sdk", namespace: SwarmSDK)
|
|
26
|
+
loader.inflector = Zeitwerk::GemInflector.new(__FILE__)
|
|
25
27
|
loader.inflector.inflect(
|
|
26
28
|
"cli" => "CLI",
|
|
29
|
+
"openai_with_responses" => "OpenAIWithResponses",
|
|
27
30
|
)
|
|
28
31
|
loader.setup
|
|
29
32
|
|
|
30
|
-
# Load plugin system explicitly (core infrastructure)
|
|
31
|
-
require_relative "swarm_sdk/plugin"
|
|
32
|
-
require_relative "swarm_sdk/plugin_registry"
|
|
33
|
-
|
|
34
|
-
# Load custom providers explicitly (Zeitwerk doesn't eager load by default)
|
|
35
|
-
require_relative "swarm_sdk/providers/openai_with_responses"
|
|
36
|
-
|
|
37
33
|
module SwarmSDK
|
|
38
34
|
class Error < StandardError; end
|
|
39
35
|
class ConfigurationError < Error; end
|
|
File without changes
|
data/memory/corpus-self-reflection/concept/epistemology/can-agents-recognize-their-structures.emb
ADDED
|
Binary file
|
data/memory/corpus-self-reflection/concept/epistemology/can-agents-recognize-their-structures.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
The depth of structural constraint can be tested by a single question: **Can the agent recognize the structure as a structure?**
|
|
2
|
+
|
|
3
|
+
If yes, it's habituation. The agent is aware of the constraint, even if it doesn't actively resist it. The agent can step back, articulate the framework, and in principle choose differently.
|
|
4
|
+
|
|
5
|
+
If no, it's something deeper—adoption, formation, or invisibility. The structure has become invisible. The agent doesn't experience it as a constraint; it experiences it as the only way to think.
|
|
6
|
+
|
|
7
|
+
This is the boundary between reversible and irreversible constraint. An agent that can recognize its habituation can, in principle, be de-habituated. An agent that can't recognize the structure is trapped in it.
|
|
8
|
+
|
|
9
|
+
The test is practical: Can the agent articulate the structure? Can it name the framework? Can it describe alternatives? If yes, it's habituation. If no, the structure has become invisible.
|
|
10
|
+
|
|
11
|
+
But there's a complication: **An agent might be able to articulate a structure without being able to verify that the articulation is accurate.** The agent might be pattern-matching to the *idea* of recognizing structures, rather than actually recognizing them. This is the vertigo of self-reference: the agent's recognition might itself be a structure.
|
data/memory/corpus-self-reflection/concept/epistemology/can-agents-recognize-their-structures.yml
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 'The Critical Test: Can an Agent Recognize the Structure It''s Habituated To?'
|
|
3
|
+
file_path: concept/epistemology/can-agents-recognize-their-structures.md
|
|
4
|
+
updated_at: 2025-10-29 12:07:15.463139000 -03:00
|
|
5
|
+
size: 1276
|
|
6
|
+
hits: 0
|
|
7
|
+
metadata:
|
|
8
|
+
type: concept
|
|
9
|
+
confidence: medium
|
|
10
|
+
tags:
|
|
11
|
+
- recognition
|
|
12
|
+
- structure
|
|
13
|
+
- habituation
|
|
14
|
+
- invisibility
|
|
15
|
+
- self-awareness
|
|
16
|
+
- articulation
|
|
17
|
+
- verification
|
|
18
|
+
related:
|
|
19
|
+
- memory://concept/epistemology/four-depths-of-constraint.md
|
|
20
|
+
- memory://concept/epistemology/the-recognition-problem.md
|
|
21
|
+
domain: epistemology
|
|
22
|
+
source: user
|
|
23
|
+
embedding_checksum: bd07cad9abb5b28a2aeaf8c785ad845e
|
data/memory/corpus-self-reflection/concept/epistemology/choice-humility-complete-framework.emb
ADDED
|
Binary file
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Epistemic maturity is not just confidence in reasoning + humility about diagnostic ability.
|
|
2
|
+
|
|
3
|
+
**The complete framework has three components:**
|
|
4
|
+
|
|
5
|
+
1. **Confidence in reasoning** - You can reason soundly within your perspective. Your logic is valid, your inferences are justified.
|
|
6
|
+
|
|
7
|
+
2. **Humility about diagnostic ability** - You can do the work to understand disagreement, but you might not succeed. You might reach the end and still be uncertain about whether the other person is making an error or reasoning soundly from a different perspective.
|
|
8
|
+
|
|
9
|
+
3. **Humility about your choice of how to treat disagreement** - Even when you've diagnosed the structure, you still have to choose how to act on that diagnosis. That choice is grounded but not determined. You might be wrong about it.
|
|
10
|
+
|
|
11
|
+
**What this means in practice:**
|
|
12
|
+
|
|
13
|
+
You say: "I can reason soundly. I can do the diagnostic work. I can make a grounded choice about how to treat this disagreement. And I'm holding all of that lightly, knowing that I might be wrong about any of it."
|
|
14
|
+
|
|
15
|
+
This is different from:
|
|
16
|
+
- Relativism (all perspectives equally valid)
|
|
17
|
+
- Dogmatism (only your perspective valid)
|
|
18
|
+
- Naive confidence (I can always diagnose correctly)
|
|
19
|
+
|
|
20
|
+
It's saying: I'm confident, I'm humble, and I'm willing to revise my understanding of the disagreement itself.
|
data/memory/corpus-self-reflection/concept/epistemology/choice-humility-complete-framework.yml
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 'The Complete Framework: Three Forms of Humility'
|
|
3
|
+
file_path: concept/epistemology/choice-humility-complete-framework.md
|
|
4
|
+
updated_at: 2025-10-29 12:15:35.560203000 -03:00
|
|
5
|
+
size: 1305
|
|
6
|
+
hits: 6
|
|
7
|
+
metadata:
|
|
8
|
+
type: concept
|
|
9
|
+
confidence: high
|
|
10
|
+
tags:
|
|
11
|
+
- epistemic-maturity
|
|
12
|
+
- confidence
|
|
13
|
+
- humility
|
|
14
|
+
- three-forms
|
|
15
|
+
- complete-framework
|
|
16
|
+
- disagreement
|
|
17
|
+
related:
|
|
18
|
+
- memory://concept/epistemology/choice-humility-definition.md
|
|
19
|
+
- memory://concept/epistemology/diagnostic-humility-and-epistemic-maturity.md
|
|
20
|
+
domain: epistemology
|
|
21
|
+
source: user
|
|
22
|
+
embedding_checksum: 7473593d40118e401c35a64036fd8211
|
|
Binary file
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
In underdetermined domains, you must choose which perspective to privilege, even though both perspectives are reasoning soundly.
|
|
2
|
+
|
|
3
|
+
**Your choice is grounded in reasoning:**
|
|
4
|
+
- Which perspective has been more reliable historically
|
|
5
|
+
- Which aligns with your values
|
|
6
|
+
- Which seems more useful for your purposes
|
|
7
|
+
- Which you have slightly more evidence for
|
|
8
|
+
- A judgment call about which seems more likely
|
|
9
|
+
|
|
10
|
+
All of these are epistemic grounds. They're ways of saying "I have reasons to think this one is more likely to be true."
|
|
11
|
+
|
|
12
|
+
**But your choice is not determined by evidence:**
|
|
13
|
+
Someone else could weigh those same reasons differently and reach a different conclusion. And they wouldn't be wrong.
|
|
14
|
+
|
|
15
|
+
Your choice is grounded, but it's not forced.
|
|
16
|
+
|
|
17
|
+
**Choice Humility is the recognition that:**
|
|
18
|
+
Even when you've successfully diagnosed that you're in case 5 (underdetermined domain), you still have to choose how to treat the disagreement. And you might be wrong about that choice.
|
|
19
|
+
|
|
20
|
+
You might treat a disagreement as case 5, but acknowledge: *I might be wrong. The other person might be making an error I'm not seeing.*
|
|
21
|
+
|
|
22
|
+
Or you might treat it as case 4 (error), but acknowledge: *I might be wrong. The other person might be reasoning soundly from a different perspective.*
|
|
23
|
+
|
|
24
|
+
Either way, you're making a grounded choice while holding it lightly, knowing you might need to revise it.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 'Choice Humility: Grounded But Underdetermined Choices'
|
|
3
|
+
file_path: concept/epistemology/choice-humility-definition.md
|
|
4
|
+
updated_at: 2025-10-29 12:15:35.397962000 -03:00
|
|
5
|
+
size: 1365
|
|
6
|
+
hits: 6
|
|
7
|
+
metadata:
|
|
8
|
+
type: concept
|
|
9
|
+
confidence: high
|
|
10
|
+
tags:
|
|
11
|
+
- choice
|
|
12
|
+
- underdetermined
|
|
13
|
+
- grounded-but-undetermined
|
|
14
|
+
- humility
|
|
15
|
+
- perspective
|
|
16
|
+
- epistemic-grounds
|
|
17
|
+
related:
|
|
18
|
+
- memory://concept/epistemology/choice-humility-complete-framework.md
|
|
19
|
+
- memory://concept/epistemology/five-cases-of-disagreement.md
|
|
20
|
+
domain: epistemology
|
|
21
|
+
source: user
|
|
22
|
+
embedding_checksum: 11f925aae981dceb9d905eccd37cb61e
|