rubik 0.1.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.
- checksums.yaml +7 -0
- data/ATTRIBUTION.md +139 -0
- data/CHANGELOG.md +236 -0
- data/LICENSE +21 -0
- data/README.md +269 -0
- data/bin/rubik +82 -0
- data/lib/rubik/adapter/base.rb +195 -0
- data/lib/rubik/adapter/c.rb +36 -0
- data/lib/rubik/adapter/crystal.rb +78 -0
- data/lib/rubik/adapter/generic.rb +86 -0
- data/lib/rubik/adapter/go.rb +36 -0
- data/lib/rubik/adapter/node.rb +146 -0
- data/lib/rubik/adapter/process.rb +78 -0
- data/lib/rubik/adapter/python.rb +30 -0
- data/lib/rubik/adapter/registry.rb +81 -0
- data/lib/rubik/adapter/ruby.rb +30 -0
- data/lib/rubik/adapter/rust.rb +36 -0
- data/lib/rubik/adapter/zig.rb +36 -0
- data/lib/rubik/adapter.rb +18 -0
- data/lib/rubik/ast/body_loader.rb +19 -0
- data/lib/rubik/ast/c_extractor.rb +114 -0
- data/lib/rubik/ast/cache_store.rb +191 -0
- data/lib/rubik/ast/extractor.rb +59 -0
- data/lib/rubik/ast/fallback_cleaner.rb +145 -0
- data/lib/rubik/ast/go_extractor.rb +148 -0
- data/lib/rubik/ast/graph.rb +272 -0
- data/lib/rubik/ast/python_extractor.rb +120 -0
- data/lib/rubik/ast/ruby_extractor.rb +260 -0
- data/lib/rubik/ast/rust_extractor.rb +127 -0
- data/lib/rubik/ast/symbol.rb +103 -0
- data/lib/rubik/ast/treesitter/base_walker.rb +109 -0
- data/lib/rubik/ast/treesitter/c_walker.rb +122 -0
- data/lib/rubik/ast/treesitter/go_walker.rb +120 -0
- data/lib/rubik/ast/treesitter/python_walker.rb +107 -0
- data/lib/rubik/ast/treesitter/rust_walker.rb +130 -0
- data/lib/rubik/ast/treesitter/typescript_walker.rb +182 -0
- data/lib/rubik/ast/treesitter/zig_walker.rb +109 -0
- data/lib/rubik/ast/treesitter_extractor.rb +93 -0
- data/lib/rubik/ast/typescript_extractor.rb +283 -0
- data/lib/rubik/ast/zig_extractor.rb +116 -0
- data/lib/rubik/ast.rb +13 -0
- data/lib/rubik/benchmark/runner.rb +224 -0
- data/lib/rubik/benchmark/synth_repo.rb +59 -0
- data/lib/rubik/benchmark.rb +9 -0
- data/lib/rubik/buffer/diff.rb +43 -0
- data/lib/rubik/buffer/manager.rb +427 -0
- data/lib/rubik/buffer/path_validator.rb +60 -0
- data/lib/rubik/buffer/snapshot.rb +99 -0
- data/lib/rubik/buffer.rb +10 -0
- data/lib/rubik/coeffects.rb +129 -0
- data/lib/rubik/concurrency/boundary.rb +74 -0
- data/lib/rubik/concurrency/dns_pool.rb +68 -0
- data/lib/rubik/concurrency/errors.rb +17 -0
- data/lib/rubik/concurrency/event_loop.rb +441 -0
- data/lib/rubik/concurrency/join.rb +55 -0
- data/lib/rubik/concurrency/process_waiter.rb +55 -0
- data/lib/rubik/concurrency/scheduler.rb +84 -0
- data/lib/rubik/concurrency/timers.rb +109 -0
- data/lib/rubik/concurrency.rb +132 -0
- data/lib/rubik/config/deep_ops.rb +80 -0
- data/lib/rubik/config/defaults.rb +248 -0
- data/lib/rubik/config/model_catalog.rb +93 -0
- data/lib/rubik/config/store.rb +155 -0
- data/lib/rubik/config.rb +216 -0
- data/lib/rubik/context/git_info.rb +84 -0
- data/lib/rubik/context/git_lister.rb +37 -0
- data/lib/rubik/context/index.rb +134 -0
- data/lib/rubik/context/repo_context_reader.rb +121 -0
- data/lib/rubik/context/scanner.rb +439 -0
- data/lib/rubik/context.rb +11 -0
- data/lib/rubik/diagnostics/collector.rb +200 -0
- data/lib/rubik/diagnostics/entry.rb +60 -0
- data/lib/rubik/diagnostics/parser.rb +107 -0
- data/lib/rubik/diagnostics.rb +10 -0
- data/lib/rubik/event_bus.rb +56 -0
- data/lib/rubik/kernel/dispatcher.rb +171 -0
- data/lib/rubik/kernel/dmesg.rb +116 -0
- data/lib/rubik/kernel/init.rb +177 -0
- data/lib/rubik/kernel/record.rb +85 -0
- data/lib/rubik/kernel/unit.rb +160 -0
- data/lib/rubik/llm/anthropic.rb +202 -0
- data/lib/rubik/llm/chunk_assembler.rb +285 -0
- data/lib/rubik/llm/client.rb +526 -0
- data/lib/rubik/llm/formatter.rb +450 -0
- data/lib/rubik/llm/message_sanitizer.rb +87 -0
- data/lib/rubik/llm/ollama.rb +167 -0
- data/lib/rubik/llm/openai.rb +21 -0
- data/lib/rubik/llm/openai_compatible.rb +216 -0
- data/lib/rubik/llm/provider.rb +125 -0
- data/lib/rubik/llm/registry.rb +336 -0
- data/lib/rubik/llm/router.rb +100 -0
- data/lib/rubik/llm.rb +18 -0
- data/lib/rubik/log.rb +38 -0
- data/lib/rubik/lsp/client.rb +475 -0
- data/lib/rubik/lsp/manager.rb +366 -0
- data/lib/rubik/lsp.rb +9 -0
- data/lib/rubik/mcp/boot_lifecycle.rb +114 -0
- data/lib/rubik/mcp/client.rb +169 -0
- data/lib/rubik/mcp/errors.rb +11 -0
- data/lib/rubik/mcp/manager.rb +619 -0
- data/lib/rubik/mcp/proxy_tool.rb +104 -0
- data/lib/rubik/mcp/transport/stdio.rb +255 -0
- data/lib/rubik/mcp.rb +12 -0
- data/lib/rubik/orchestrator/activity_log.rb +75 -0
- data/lib/rubik/orchestrator/auto_apply.rb +166 -0
- data/lib/rubik/orchestrator/budget_manager.rb +97 -0
- data/lib/rubik/orchestrator/continuation_manager.rb +161 -0
- data/lib/rubik/orchestrator/finish_message_selector.rb +55 -0
- data/lib/rubik/orchestrator/goal_ledger/drift.rb +71 -0
- data/lib/rubik/orchestrator/goal_ledger/ledger.rb +399 -0
- data/lib/rubik/orchestrator/goal_ledger/observation_projection.rb +179 -0
- data/lib/rubik/orchestrator/goal_ledger/patch.rb +268 -0
- data/lib/rubik/orchestrator/goal_ledger/schema.rb +123 -0
- data/lib/rubik/orchestrator/goal_ledger/validator.rb +361 -0
- data/lib/rubik/orchestrator/goal_ledger/verifier.rb +129 -0
- data/lib/rubik/orchestrator/goal_ledger/verify_spec.rb +50 -0
- data/lib/rubik/orchestrator/goal_ledger.rb +65 -0
- data/lib/rubik/orchestrator/goal_state.rb +184 -0
- data/lib/rubik/orchestrator/goal_wait.rb +125 -0
- data/lib/rubik/orchestrator/loop.rb +388 -0
- data/lib/rubik/orchestrator/lsp_feedback.rb +55 -0
- data/lib/rubik/orchestrator/maestro_gate.rb +65 -0
- data/lib/rubik/orchestrator/provider_recovery.rb +90 -0
- data/lib/rubik/orchestrator/provider_resolver.rb +69 -0
- data/lib/rubik/orchestrator/shell_deps.rb +85 -0
- data/lib/rubik/orchestrator/step_executor.rb +328 -0
- data/lib/rubik/orchestrator/stream_manager.rb +118 -0
- data/lib/rubik/orchestrator/subagent/activation.rb +65 -0
- data/lib/rubik/orchestrator/subagent/budget.rb +108 -0
- data/lib/rubik/orchestrator/subagent/completion.rb +61 -0
- data/lib/rubik/orchestrator/subagent/concurrency_gate.rb +37 -0
- data/lib/rubik/orchestrator/subagent/conversation_id.rb +67 -0
- data/lib/rubik/orchestrator/subagent/dependency.rb +398 -0
- data/lib/rubik/orchestrator/subagent/instance.rb +384 -0
- data/lib/rubik/orchestrator/subagent/lifecycle.rb +118 -0
- data/lib/rubik/orchestrator/subagent/messaging.rb +61 -0
- data/lib/rubik/orchestrator/subagent/narration.rb +125 -0
- data/lib/rubik/orchestrator/subagent/notices.rb +209 -0
- data/lib/rubik/orchestrator/subagent/questioner.rb +80 -0
- data/lib/rubik/orchestrator/subagent/reaper.rb +98 -0
- data/lib/rubik/orchestrator/subagent/resilience.rb +70 -0
- data/lib/rubik/orchestrator/subagent/reuse.rb +127 -0
- data/lib/rubik/orchestrator/subagent/scoped_registry.rb +79 -0
- data/lib/rubik/orchestrator/subagent/step_runner.rb +240 -0
- data/lib/rubik/orchestrator/subagent/storage_id.rb +26 -0
- data/lib/rubik/orchestrator/subagent/supervisor.rb +327 -0
- data/lib/rubik/orchestrator/subagent/transcript_formatter.rb +141 -0
- data/lib/rubik/orchestrator/subagent/type_registry.rb +199 -0
- data/lib/rubik/orchestrator/subagent_notice_inbox.rb +80 -0
- data/lib/rubik/orchestrator/tool_call_id.rb +47 -0
- data/lib/rubik/orchestrator/tool_circuit_breaker.rb +91 -0
- data/lib/rubik/orchestrator/tool_history.rb +39 -0
- data/lib/rubik/orchestrator/turn_executor/subagent_channel.rb +102 -0
- data/lib/rubik/orchestrator/turn_executor/user_channel.rb +172 -0
- data/lib/rubik/orchestrator/turn_executor.rb +376 -0
- data/lib/rubik/orchestrator.rb +11 -0
- data/lib/rubik/platform/filesystem.rb +64 -0
- data/lib/rubik/platform/io_drain.rb +53 -0
- data/lib/rubik/platform/path.rb +210 -0
- data/lib/rubik/platform/process.rb +38 -0
- data/lib/rubik/platform/sanitize.rb +157 -0
- data/lib/rubik/platform.rb +113 -0
- data/lib/rubik/plugin/dsl.rb +51 -0
- data/lib/rubik/plugin/manager.rb +247 -0
- data/lib/rubik/plugin/storage.rb +195 -0
- data/lib/rubik/plugin.rb +10 -0
- data/lib/rubik/prompt/context_builder.rb +377 -0
- data/lib/rubik/prompt/context_compactor.rb +326 -0
- data/lib/rubik/prompt/conversation_rows.rb +74 -0
- data/lib/rubik/prompt/doctrine.rb +160 -0
- data/lib/rubik/prompt/emergency_compactor.rb +81 -0
- data/lib/rubik/prompt/services.rb +60 -0
- data/lib/rubik/prompt/token_estimator.rb +63 -0
- data/lib/rubik/prompt/tool_teachings.rb +78 -0
- data/lib/rubik/prompt.rb +13 -0
- data/lib/rubik/repair/loop.rb +95 -0
- data/lib/rubik/repair.rb +8 -0
- data/lib/rubik/repl/ast_warmup.rb +129 -0
- data/lib/rubik/repl/command_context.rb +214 -0
- data/lib/rubik/repl/command_parser.rb +48 -0
- data/lib/rubik/repl/commands/agent.rb +30 -0
- data/lib/rubik/repl/commands/agent_context.rb +289 -0
- data/lib/rubik/repl/commands/agent_execution.rb +342 -0
- data/lib/rubik/repl/commands/agent_models.rb +212 -0
- data/lib/rubik/repl/commands/agent_providers.rb +232 -0
- data/lib/rubik/repl/commands/base.rb +55 -0
- data/lib/rubik/repl/commands/buffer.rb +124 -0
- data/lib/rubik/repl/commands/dmesg.rb +87 -0
- data/lib/rubik/repl/commands/lsp.rb +235 -0
- data/lib/rubik/repl/commands/mcp.rb +194 -0
- data/lib/rubik/repl/commands/plugins.rb +208 -0
- data/lib/rubik/repl/commands/pruner.rb +71 -0
- data/lib/rubik/repl/commands/session.rb +183 -0
- data/lib/rubik/repl/commands/skills.rb +111 -0
- data/lib/rubik/repl/commands/storage.rb +85 -0
- data/lib/rubik/repl/commands/subagents.rb +195 -0
- data/lib/rubik/repl/commands/system.rb +85 -0
- data/lib/rubik/repl/commands/tasks.rb +120 -0
- data/lib/rubik/repl/commands/workspace.rb +443 -0
- data/lib/rubik/repl/commands.rb +44 -0
- data/lib/rubik/repl/composition.rb +32 -0
- data/lib/rubik/repl/config_wiring.rb +142 -0
- data/lib/rubik/repl/confirmations.rb +56 -0
- data/lib/rubik/repl/hooks.rb +47 -0
- data/lib/rubik/repl/input_execution.rb +323 -0
- data/lib/rubik/repl/input_loop.rb +213 -0
- data/lib/rubik/repl/interrupt_handler.rb +217 -0
- data/lib/rubik/repl/lifecycle.rb +410 -0
- data/lib/rubik/repl/paste_support.rb +88 -0
- data/lib/rubik/repl/pending_notice_queue.rb +60 -0
- data/lib/rubik/repl/presentation.rb +132 -0
- data/lib/rubik/repl/pruner/brief.rb +101 -0
- data/lib/rubik/repl/pruner/gate.rb +279 -0
- data/lib/rubik/repl/pruner/harness.rb +236 -0
- data/lib/rubik/repl/pruner/rules.rb +316 -0
- data/lib/rubik/repl/pruner/service.rb +82 -0
- data/lib/rubik/repl/pruner.rb +39 -0
- data/lib/rubik/repl/service_catalog.rb +374 -0
- data/lib/rubik/repl/setup_factories.rb +66 -0
- data/lib/rubik/repl/shell.rb +231 -0
- data/lib/rubik/repl/step_formatter.rb +324 -0
- data/lib/rubik/repl/tee_io.rb +105 -0
- data/lib/rubik/repl/terminal_guard.rb +157 -0
- data/lib/rubik/repl/turn_recorder.rb +234 -0
- data/lib/rubik/repl.rb +14 -0
- data/lib/rubik/runtime/ast_service.rb +78 -0
- data/lib/rubik/runtime/context.rb +335 -0
- data/lib/rubik/runtime/diagnostic_engine.rb +188 -0
- data/lib/rubik/runtime/discovery.rb +342 -0
- data/lib/rubik/runtime/fiber.rb +142 -0
- data/lib/rubik/runtime/fiber_ordering.rb +52 -0
- data/lib/rubik/runtime/fiber_retry_gate.rb +84 -0
- data/lib/rubik/runtime/index_service.rb +58 -0
- data/lib/rubik/runtime/loop_service.rb +73 -0
- data/lib/rubik/runtime/manager.rb +241 -0
- data/lib/rubik/runtime/overlay_storage.rb +481 -0
- data/lib/rubik/runtime/service_definition.rb +54 -0
- data/lib/rubik/runtime/service_registration.rb +33 -0
- data/lib/rubik/runtime/task_manager.rb +302 -0
- data/lib/rubik/runtime.rb +19 -0
- data/lib/rubik/sandbox/driver/base.rb +30 -0
- data/lib/rubik/sandbox/driver/bubblewrap.rb +111 -0
- data/lib/rubik/sandbox/driver/docker.rb +113 -0
- data/lib/rubik/sandbox/driver/podman.rb +98 -0
- data/lib/rubik/sandbox/driver/process.rb +190 -0
- data/lib/rubik/sandbox/driver.rb +91 -0
- data/lib/rubik/sandbox/runner.rb +218 -0
- data/lib/rubik/sandbox/shell_resolver.rb +178 -0
- data/lib/rubik/sandbox.rb +8 -0
- data/lib/rubik/security/blocked_guidance.rb +187 -0
- data/lib/rubik/security/classifier/classifier.rb +440 -0
- data/lib/rubik/security/classifier/commands/agent-browser.yaml +9 -0
- data/lib/rubik/security/classifier/commands/apt.yaml +25 -0
- data/lib/rubik/security/classifier/commands/awk.yaml +10 -0
- data/lib/rubik/security/classifier/commands/basename.yaml +7 -0
- data/lib/rubik/security/classifier/commands/bash-classify.yaml +8 -0
- data/lib/rubik/security/classifier/commands/bash.yaml +20 -0
- data/lib/rubik/security/classifier/commands/black.yaml +12 -0
- data/lib/rubik/security/classifier/commands/brew.yaml +31 -0
- data/lib/rubik/security/classifier/commands/builtin.yaml +8 -0
- data/lib/rubik/security/classifier/commands/cargo.yaml +114 -0
- data/lib/rubik/security/classifier/commands/cat.yaml +7 -0
- data/lib/rubik/security/classifier/commands/chgrp.yaml +10 -0
- data/lib/rubik/security/classifier/commands/chmod.yaml +10 -0
- data/lib/rubik/security/classifier/commands/chown.yaml +10 -0
- data/lib/rubik/security/classifier/commands/column.yaml +7 -0
- data/lib/rubik/security/classifier/commands/comm.yaml +7 -0
- data/lib/rubik/security/classifier/commands/command.yaml +12 -0
- data/lib/rubik/security/classifier/commands/cp.yaml +7 -0
- data/lib/rubik/security/classifier/commands/crystal.yaml +63 -0
- data/lib/rubik/security/classifier/commands/curl.yaml +30 -0
- data/lib/rubik/security/classifier/commands/cut.yaml +7 -0
- data/lib/rubik/security/classifier/commands/date.yaml +10 -0
- data/lib/rubik/security/classifier/commands/df.yaml +7 -0
- data/lib/rubik/security/classifier/commands/diff.yaml +7 -0
- data/lib/rubik/security/classifier/commands/dig.yaml +7 -0
- data/lib/rubik/security/classifier/commands/dirname.yaml +7 -0
- data/lib/rubik/security/classifier/commands/docker.yaml +177 -0
- data/lib/rubik/security/classifier/commands/du.yaml +7 -0
- data/lib/rubik/security/classifier/commands/echo.yaml +7 -0
- data/lib/rubik/security/classifier/commands/env.yaml +15 -0
- data/lib/rubik/security/classifier/commands/eslint.yaml +12 -0
- data/lib/rubik/security/classifier/commands/eval.yaml +8 -0
- data/lib/rubik/security/classifier/commands/exec.yaml +12 -0
- data/lib/rubik/security/classifier/commands/expand.yaml +7 -0
- data/lib/rubik/security/classifier/commands/false.yaml +7 -0
- data/lib/rubik/security/classifier/commands/file.yaml +7 -0
- data/lib/rubik/security/classifier/commands/find.yaml +25 -0
- data/lib/rubik/security/classifier/commands/fmt.yaml +7 -0
- data/lib/rubik/security/classifier/commands/fold.yaml +7 -0
- data/lib/rubik/security/classifier/commands/free.yaml +7 -0
- data/lib/rubik/security/classifier/commands/gawk.yaml +10 -0
- data/lib/rubik/security/classifier/commands/gcloud.yaml +979 -0
- data/lib/rubik/security/classifier/commands/gh.yaml +615 -0
- data/lib/rubik/security/classifier/commands/git.yaml +524 -0
- data/lib/rubik/security/classifier/commands/glab-discussion.yaml +21 -0
- data/lib/rubik/security/classifier/commands/glab.yaml +807 -0
- data/lib/rubik/security/classifier/commands/go.yaml +44 -0
- data/lib/rubik/security/classifier/commands/gog.yaml +983 -0
- data/lib/rubik/security/classifier/commands/gradle.yaml +92 -0
- data/lib/rubik/security/classifier/commands/gradlew.yaml +92 -0
- data/lib/rubik/security/classifier/commands/grep.yaml +7 -0
- data/lib/rubik/security/classifier/commands/groups.yaml +7 -0
- data/lib/rubik/security/classifier/commands/gunzip.yaml +8 -0
- data/lib/rubik/security/classifier/commands/gws.yaml +211 -0
- data/lib/rubik/security/classifier/commands/gzip.yaml +7 -0
- data/lib/rubik/security/classifier/commands/hadolint.yaml +9 -0
- data/lib/rubik/security/classifier/commands/halt.yaml +8 -0
- data/lib/rubik/security/classifier/commands/head.yaml +7 -0
- data/lib/rubik/security/classifier/commands/helm.yaml +129 -0
- data/lib/rubik/security/classifier/commands/hostname.yaml +7 -0
- data/lib/rubik/security/classifier/commands/id.yaml +7 -0
- data/lib/rubik/security/classifier/commands/install.yaml +7 -0
- data/lib/rubik/security/classifier/commands/isort.yaml +14 -0
- data/lib/rubik/security/classifier/commands/java.yaml +35 -0
- data/lib/rubik/security/classifier/commands/javac.yaml +39 -0
- data/lib/rubik/security/classifier/commands/join.yaml +7 -0
- data/lib/rubik/security/classifier/commands/journalctl.yaml +14 -0
- data/lib/rubik/security/classifier/commands/jq.yaml +7 -0
- data/lib/rubik/security/classifier/commands/kill.yaml +7 -0
- data/lib/rubik/security/classifier/commands/killall.yaml +7 -0
- data/lib/rubik/security/classifier/commands/kubectl.yaml +211 -0
- data/lib/rubik/security/classifier/commands/less.yaml +7 -0
- data/lib/rubik/security/classifier/commands/ln.yaml +7 -0
- data/lib/rubik/security/classifier/commands/ls.yaml +7 -0
- data/lib/rubik/security/classifier/commands/make.yaml +21 -0
- data/lib/rubik/security/classifier/commands/md5sum.yaml +7 -0
- data/lib/rubik/security/classifier/commands/mise.yaml +579 -0
- data/lib/rubik/security/classifier/commands/mkdir.yaml +8 -0
- data/lib/rubik/security/classifier/commands/more.yaml +7 -0
- data/lib/rubik/security/classifier/commands/mv.yaml +7 -0
- data/lib/rubik/security/classifier/commands/mvn.yaml +83 -0
- data/lib/rubik/security/classifier/commands/mvnw.yaml +83 -0
- data/lib/rubik/security/classifier/commands/mypy.yaml +9 -0
- data/lib/rubik/security/classifier/commands/netstat.yaml +7 -0
- data/lib/rubik/security/classifier/commands/nice.yaml +11 -0
- data/lib/rubik/security/classifier/commands/nl.yaml +7 -0
- data/lib/rubik/security/classifier/commands/node.yaml +20 -0
- data/lib/rubik/security/classifier/commands/nohup.yaml +9 -0
- data/lib/rubik/security/classifier/commands/npm.yaml +71 -0
- data/lib/rubik/security/classifier/commands/npx.yaml +42 -0
- data/lib/rubik/security/classifier/commands/nslookup.yaml +7 -0
- data/lib/rubik/security/classifier/commands/paste.yaml +7 -0
- data/lib/rubik/security/classifier/commands/ping.yaml +7 -0
- data/lib/rubik/security/classifier/commands/pip.yaml +33 -0
- data/lib/rubik/security/classifier/commands/pip3.yaml +33 -0
- data/lib/rubik/security/classifier/commands/pipx.yaml +33 -0
- data/lib/rubik/security/classifier/commands/pkill.yaml +7 -0
- data/lib/rubik/security/classifier/commands/pnpm.yaml +346 -0
- data/lib/rubik/security/classifier/commands/poetry.yaml +97 -0
- data/lib/rubik/security/classifier/commands/poweroff.yaml +8 -0
- data/lib/rubik/security/classifier/commands/prettier.yaml +13 -0
- data/lib/rubik/security/classifier/commands/printenv.yaml +7 -0
- data/lib/rubik/security/classifier/commands/printf.yaml +7 -0
- data/lib/rubik/security/classifier/commands/ps.yaml +7 -0
- data/lib/rubik/security/classifier/commands/pup.yaml +882 -0
- data/lib/rubik/security/classifier/commands/pwd.yaml +7 -0
- data/lib/rubik/security/classifier/commands/pytest.yaml +7 -0
- data/lib/rubik/security/classifier/commands/python.yaml +9 -0
- data/lib/rubik/security/classifier/commands/python3.yaml +9 -0
- data/lib/rubik/security/classifier/commands/read.yaml +7 -0
- data/lib/rubik/security/classifier/commands/readlink.yaml +7 -0
- data/lib/rubik/security/classifier/commands/realpath.yaml +7 -0
- data/lib/rubik/security/classifier/commands/reboot.yaml +8 -0
- data/lib/rubik/security/classifier/commands/rev.yaml +7 -0
- data/lib/rubik/security/classifier/commands/rg.yaml +7 -0
- data/lib/rubik/security/classifier/commands/rm.yaml +8 -0
- data/lib/rubik/security/classifier/commands/rsync.yaml +12 -0
- data/lib/rubik/security/classifier/commands/rtk.yaml +140 -0
- data/lib/rubik/security/classifier/commands/ruff.yaml +29 -0
- data/lib/rubik/security/classifier/commands/rustfmt.yaml +14 -0
- data/lib/rubik/security/classifier/commands/scp.yaml +7 -0
- data/lib/rubik/security/classifier/commands/sed.yaml +14 -0
- data/lib/rubik/security/classifier/commands/seq.yaml +7 -0
- data/lib/rubik/security/classifier/commands/sh.yaml +14 -0
- data/lib/rubik/security/classifier/commands/sha1sum.yaml +7 -0
- data/lib/rubik/security/classifier/commands/sha256sum.yaml +7 -0
- data/lib/rubik/security/classifier/commands/shellcheck.yaml +10 -0
- data/lib/rubik/security/classifier/commands/shutdown.yaml +8 -0
- data/lib/rubik/security/classifier/commands/slack.yaml +113 -0
- data/lib/rubik/security/classifier/commands/sleep.yaml +8 -0
- data/lib/rubik/security/classifier/commands/snip.yaml +79 -0
- data/lib/rubik/security/classifier/commands/sort.yaml +10 -0
- data/lib/rubik/security/classifier/commands/ss.yaml +7 -0
- data/lib/rubik/security/classifier/commands/ssh.yaml +41 -0
- data/lib/rubik/security/classifier/commands/stat.yaml +7 -0
- data/lib/rubik/security/classifier/commands/stdbuf.yaml +15 -0
- data/lib/rubik/security/classifier/commands/strace.yaml +20 -0
- data/lib/rubik/security/classifier/commands/strings.yaml +11 -0
- data/lib/rubik/security/classifier/commands/sudo.yaml +24 -0
- data/lib/rubik/security/classifier/commands/systemctl.yaml +58 -0
- data/lib/rubik/security/classifier/commands/systemd-run.yaml +30 -0
- data/lib/rubik/security/classifier/commands/tac.yaml +7 -0
- data/lib/rubik/security/classifier/commands/tail.yaml +7 -0
- data/lib/rubik/security/classifier/commands/tar.yaml +25 -0
- data/lib/rubik/security/classifier/commands/tee.yaml +8 -0
- data/lib/rubik/security/classifier/commands/terraform.yaml +70 -0
- data/lib/rubik/security/classifier/commands/test.yaml +7 -0
- data/lib/rubik/security/classifier/commands/time.yaml +8 -0
- data/lib/rubik/security/classifier/commands/timeout.yaml +18 -0
- data/lib/rubik/security/classifier/commands/top.yaml +7 -0
- data/lib/rubik/security/classifier/commands/touch.yaml +8 -0
- data/lib/rubik/security/classifier/commands/tr.yaml +7 -0
- data/lib/rubik/security/classifier/commands/traceroute.yaml +7 -0
- data/lib/rubik/security/classifier/commands/true.yaml +7 -0
- data/lib/rubik/security/classifier/commands/tsc.yaml +16 -0
- data/lib/rubik/security/classifier/commands/type.yaml +7 -0
- data/lib/rubik/security/classifier/commands/uname.yaml +7 -0
- data/lib/rubik/security/classifier/commands/unexpand.yaml +7 -0
- data/lib/rubik/security/classifier/commands/uniq.yaml +7 -0
- data/lib/rubik/security/classifier/commands/unzip.yaml +10 -0
- data/lib/rubik/security/classifier/commands/uptime.yaml +7 -0
- data/lib/rubik/security/classifier/commands/uv.yaml +156 -0
- data/lib/rubik/security/classifier/commands/wait.yaml +11 -0
- data/lib/rubik/security/classifier/commands/wc.yaml +7 -0
- data/lib/rubik/security/classifier/commands/wget.yaml +7 -0
- data/lib/rubik/security/classifier/commands/whereis.yaml +7 -0
- data/lib/rubik/security/classifier/commands/which.yaml +7 -0
- data/lib/rubik/security/classifier/commands/whoami.yaml +7 -0
- data/lib/rubik/security/classifier/commands/xargs.yaml +26 -0
- data/lib/rubik/security/classifier/commands/xmllint.yaml +7 -0
- data/lib/rubik/security/classifier/commands/yarn.yaml +72 -0
- data/lib/rubik/security/classifier/commands/yes.yaml +7 -0
- data/lib/rubik/security/classifier/commands/yq.yaml +10 -0
- data/lib/rubik/security/classifier/commands/zip.yaml +8 -0
- data/lib/rubik/security/classifier/commands/zsh.yaml +14 -0
- data/lib/rubik/security/classifier/database.rb +216 -0
- data/lib/rubik/security/classifier/matcher/delegation.rb +190 -0
- data/lib/rubik/security/classifier/matcher/options.rb +245 -0
- data/lib/rubik/security/classifier/matcher/subcommands.rb +103 -0
- data/lib/rubik/security/classifier/matcher.rb +249 -0
- data/lib/rubik/security/classifier/models.rb +170 -0
- data/lib/rubik/security/classifier/parser.rb +23 -0
- data/lib/rubik/security/classifier/parsers/bash.rb +280 -0
- data/lib/rubik/security/classifier/parsers/bash_extractors.rb +221 -0
- data/lib/rubik/security/classifier/parsers/powershell.rb +185 -0
- data/lib/rubik/security/classifier/pwsh_rules.rb +224 -0
- data/lib/rubik/security/classifier.rb +25 -0
- data/lib/rubik/security/errors.rb +39 -0
- data/lib/rubik/security/guard.rb +954 -0
- data/lib/rubik/security/redactor.rb +89 -0
- data/lib/rubik/security.rb +11 -0
- data/lib/rubik/session/manager.rb +331 -0
- data/lib/rubik/session/recorder.rb +149 -0
- data/lib/rubik/session/replayer.rb +65 -0
- data/lib/rubik/session.rb +10 -0
- data/lib/rubik/skills/frontmatter.rb +41 -0
- data/lib/rubik/skills/manager.rb +223 -0
- data/lib/rubik/skills/registry.rb +64 -0
- data/lib/rubik/skills/skill.rb +33 -0
- data/lib/rubik/skills/storage.rb +77 -0
- data/lib/rubik/skills/validator.rb +116 -0
- data/lib/rubik/skills.rb +20 -0
- data/lib/rubik/storage/folding.rb +23 -0
- data/lib/rubik/storage/layout.rb +145 -0
- data/lib/rubik/storage/render.rb +97 -0
- data/lib/rubik/storage/service.rb +42 -0
- data/lib/rubik/storage/store.rb +514 -0
- data/lib/rubik/storage/transcript_indexer.rb +116 -0
- data/lib/rubik/storage/uri_reader.rb +168 -0
- data/lib/rubik/storage/vakanuvis/annal_writer.rb +92 -0
- data/lib/rubik/storage/vakanuvis/distill_gate.rb +323 -0
- data/lib/rubik/storage/vakanuvis/gate.rb +250 -0
- data/lib/rubik/storage/vakanuvis/harness.rb +421 -0
- data/lib/rubik/storage/vakanuvis/memory_steward.rb +163 -0
- data/lib/rubik/storage/vakanuvis/service.rb +69 -0
- data/lib/rubik/storage/vakanuvis/vocabulary.rb +99 -0
- data/lib/rubik/storage/vakanuvis/wiki_skeleton.rb +67 -0
- data/lib/rubik/storage/vakanuvis.rb +77 -0
- data/lib/rubik/storage.rb +29 -0
- data/lib/rubik/tools/base.rb +107 -0
- data/lib/rubik/tools/builtins/dmesg.rb +74 -0
- data/lib/rubik/tools/builtins/exec.rb +293 -0
- data/lib/rubik/tools/builtins/files.rb +354 -0
- data/lib/rubik/tools/builtins/goal_ledger.rb +89 -0
- data/lib/rubik/tools/builtins/grep.rb +281 -0
- data/lib/rubik/tools/builtins/interactive.rb +175 -0
- data/lib/rubik/tools/builtins/lifecycle.rb +359 -0
- data/lib/rubik/tools/builtins/lsp.rb +283 -0
- data/lib/rubik/tools/builtins/pruner.rb +88 -0
- data/lib/rubik/tools/builtins/runtime.rb +120 -0
- data/lib/rubik/tools/builtins/send_message.rb +109 -0
- data/lib/rubik/tools/builtins/show_file.rb +84 -0
- data/lib/rubik/tools/builtins/skill.rb +72 -0
- data/lib/rubik/tools/builtins/storage.rb +232 -0
- data/lib/rubik/tools/builtins/subagent.rb +356 -0
- data/lib/rubik/tools/builtins/subagent_lifecycle.rb +72 -0
- data/lib/rubik/tools/builtins/symbols.rb +209 -0
- data/lib/rubik/tools/builtins/synthesis.rb +314 -0
- data/lib/rubik/tools/builtins/task.rb +168 -0
- data/lib/rubik/tools/builtins/unsynthesize.rb +111 -0
- data/lib/rubik/tools/builtins/vakanuvis.rb +161 -0
- data/lib/rubik/tools/builtins.rb +30 -0
- data/lib/rubik/tools/catalog.rb +70 -0
- data/lib/rubik/tools/declaration.rb +90 -0
- data/lib/rubik/tools/diagnostic_reporter.rb +283 -0
- data/lib/rubik/tools/fuzzy_matcher.rb +172 -0
- data/lib/rubik/tools/native_search.rb +180 -0
- data/lib/rubik/tools/output.rb +54 -0
- data/lib/rubik/tools/preflight_runner.rb +209 -0
- data/lib/rubik/tools/registry.rb +247 -0
- data/lib/rubik/tools/result.rb +71 -0
- data/lib/rubik/tools/services.rb +96 -0
- data/lib/rubik/tools/truncator.rb +78 -0
- data/lib/rubik/tools/uri_resolver.rb +195 -0
- data/lib/rubik/tools.rb +14 -0
- data/lib/rubik/ui/approvals.rb +52 -0
- data/lib/rubik/ui/banner.rb +43 -0
- data/lib/rubik/ui/capability.rb +122 -0
- data/lib/rubik/ui/dialog.rb +106 -0
- data/lib/rubik/ui/diff_viewer.rb +78 -0
- data/lib/rubik/ui/frame.rb +95 -0
- data/lib/rubik/ui/markdown_stream.rb +107 -0
- data/lib/rubik/ui/panel.rb +98 -0
- data/lib/rubik/ui/renderer.rb +206 -0
- data/lib/rubik/ui/spinner.rb +120 -0
- data/lib/rubik/ui/statusline.rb +134 -0
- data/lib/rubik/ui/theme.rb +118 -0
- data/lib/rubik/ui.rb +57 -0
- data/lib/rubik/uris.rb +101 -0
- data/lib/rubik/version.rb +5 -0
- data/lib/rubik.rb +65 -0
- metadata +770 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../base"
|
|
4
|
+
require_relative "../output"
|
|
5
|
+
require_relative "../../coeffects"
|
|
6
|
+
|
|
7
|
+
module Rubik
|
|
8
|
+
module Tools
|
|
9
|
+
# Talep düzlemi (context-pruner planı 2026-10-09): maestro'nun pencere
|
|
10
|
+
# budayıcı masası. İki eylem de Pruner::Harness'e delege olur — 'prune'
|
|
11
|
+
# asenkron kuyruklanır ve deterministik makbuz döner (maestro turn'ü
|
|
12
|
+
# asla LLM bekletilmez; plan turn sınırında uygulanır), 'status' tamamen
|
|
13
|
+
# deterministiktir. Görünürlük: REQUIRES memnuniyetsizse (knob kapalı)
|
|
14
|
+
# araç model yüzünde görünmez; ROOT_ONLY_TOOLS subagent düzlemlerine
|
|
15
|
+
# (self dahil) asla kopyalanmaz — kök penceresini yalnız kök budar.
|
|
16
|
+
# Mimari sınır: tools çekirdeği repl/'e require edemez — harness sınıfı
|
|
17
|
+
# ana yükleme ağacından (repl.rb → repl/pruner) gelir, burada yalnız
|
|
18
|
+
# duck-typed çağrılır.
|
|
19
|
+
class PruneContextTool < BaseTool
|
|
20
|
+
REQUIRES = [Rubik::Coeffects::PRUNER].freeze
|
|
21
|
+
|
|
22
|
+
DECLARATION = Declaration.new(
|
|
23
|
+
name: "prune_context", aliases: ["pruner"],
|
|
24
|
+
description: "Clean the ROOT conversation window (semi-deterministic: an LLM proposes a " \
|
|
25
|
+
"keep/drop/summarize plan; the harness validates it deterministically and applies " \
|
|
26
|
+
"it at the next turn boundary — goal/task turns and recent context are always " \
|
|
27
|
+
"preserved): 'prune' (queue a forced prune now; returns a deterministic receipt, " \
|
|
28
|
+
"never blocks on the LLM), 'status' (window estimate vs ceiling, staged plan " \
|
|
29
|
+
"state, last receipt).",
|
|
30
|
+
risk: :write, archetypes: [], write_grant: false,
|
|
31
|
+
maestro_blocked: false, # vakanüvis emsali: budayıcı düzlemi kökte doğrudan
|
|
32
|
+
params_schema: {
|
|
33
|
+
type: "object",
|
|
34
|
+
properties: {
|
|
35
|
+
action: {
|
|
36
|
+
type: "string", enum: ["prune", "status"],
|
|
37
|
+
description: "Operation (default: 'status')."
|
|
38
|
+
},
|
|
39
|
+
reason: { type: "string", description: "prune: optional one-line motive recorded in dmesg." }
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
def initialize(harness = nil, runtime_context: nil)
|
|
45
|
+
super(DECLARATION)
|
|
46
|
+
@harness = harness
|
|
47
|
+
@runtime_context = runtime_context
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def execute(args = {})
|
|
51
|
+
action = (args["action"] || args[:action] || "status").to_s
|
|
52
|
+
harness = Rubik::Coeffects.resolve(@runtime_context, Rubik::Coeffects::PRUNER, @harness)
|
|
53
|
+
unless harness
|
|
54
|
+
return ToolOutput.error("Context pruner is not available: disabled by config " \
|
|
55
|
+
"(subagents.pruner.enabled=false) or the harness is not wired " \
|
|
56
|
+
"(the startup warning / dmesg has the cause).")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
begin
|
|
60
|
+
case action
|
|
61
|
+
when "prune" then harness.prune(reason: arg(args, "reason") || "maestro")
|
|
62
|
+
when "status" then harness.status_text
|
|
63
|
+
else ToolOutput.error("Unknown prune_context action '#{action}' (valid: prune, status).")
|
|
64
|
+
end
|
|
65
|
+
rescue ArgumentError => e
|
|
66
|
+
ToolOutput.error("prune_context #{action}: #{e.message}")
|
|
67
|
+
rescue StandardError => e
|
|
68
|
+
# Duck-typed dmesg halkası (tools çekirdeği repl/pruner'ı require
|
|
69
|
+
# edemez — mimari sınır): ring varsa oraya, yoksa Log'a.
|
|
70
|
+
dmesg = harness.respond_to?(:dmesg) ? harness.dmesg : nil
|
|
71
|
+
if dmesg.respond_to?(:log)
|
|
72
|
+
dmesg.log(:repl, :warn, "prune_context #{action} failed: #{e.class}: #{e.message}")
|
|
73
|
+
else
|
|
74
|
+
Rubik::Log.warn(:repl, "prune_context #{action} failed: #{e.class}: #{e.message}")
|
|
75
|
+
end
|
|
76
|
+
ToolOutput.error("prune_context #{action} failed: #{e.class}: #{e.message} — retry the call " \
|
|
77
|
+
"or inspect dmesg(subsystem: 'repl').")
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
def arg(args, key, default = nil)
|
|
84
|
+
args[key] || args[key.to_sym] || default
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../base"
|
|
4
|
+
require_relative "../output"
|
|
5
|
+
require_relative "../../coeffects"
|
|
6
|
+
|
|
7
|
+
module Rubik
|
|
8
|
+
module Tools
|
|
9
|
+
class InspectRuntimeTool < BaseTool
|
|
10
|
+
DECLARATION = Declaration.new(
|
|
11
|
+
name: "inspect_runtime", aliases: ["runtime_status", "inspect_fibers"],
|
|
12
|
+
description: "Inspect the Spatiotemporal Composability runtime state: active/pending fibers, coeffects, registered services, tools, and commands",
|
|
13
|
+
risk: :read,
|
|
14
|
+
params_schema: {
|
|
15
|
+
type: "object",
|
|
16
|
+
properties: {
|
|
17
|
+
target: { type: "string", enum: ["all", "fibers", "services", "tools", "commands", "tasks"], description: "Component to inspect (default: all)" }
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
)
|
|
21
|
+
def initialize(runtime_manager = nil, tool_registry = nil, shell = nil)
|
|
22
|
+
super(DECLARATION)
|
|
23
|
+
@runtime_manager = runtime_manager
|
|
24
|
+
@tool_registry = tool_registry
|
|
25
|
+
@shell = shell
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def execute(args = {})
|
|
29
|
+
target = (args["target"] || args[:target] || "all").to_s.downcase
|
|
30
|
+
|
|
31
|
+
lines = ["=== Rubik Spatiotemporal Runtime Diagnostics ==="]
|
|
32
|
+
|
|
33
|
+
if ["all", "services"].include?(target) && @runtime_manager
|
|
34
|
+
root_ctx = @runtime_manager.context
|
|
35
|
+
services = root_ctx.services
|
|
36
|
+
lines << "\n[Services / Coeffects Active (#{services.size})]:"
|
|
37
|
+
services.each { |k, v| lines << " • #{k.to_s.ljust(12)} -> #{v.class}" }
|
|
38
|
+
lines << " (LIFO Accumulator Depth: #{root_ctx.disposable_count} inverse disposables)"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
if ["all", "fibers"].include?(target) && @runtime_manager
|
|
42
|
+
active = @runtime_manager.active_fibers
|
|
43
|
+
pending = @runtime_manager.pending_fibers
|
|
44
|
+
failed = @runtime_manager.fibers.values.select { |f| f.state == :failed }
|
|
45
|
+
lines << "\n[Fibers (#{active.size} Active, #{pending.size} Pending, #{failed.size} Failed)]:"
|
|
46
|
+
active.each { |f| lines << " 🟢 ACTIVE : #{f.name} (injects: #{f.inject.join(', ')})" }
|
|
47
|
+
pending.each do |f|
|
|
48
|
+
missing = f.inject.reject { |dep| @runtime_manager.context.has?(dep) }
|
|
49
|
+
lines << " ⏳ PENDING: #{f.name} (waiting on: #{missing.join(', ')})"
|
|
50
|
+
end
|
|
51
|
+
failed.each { |f| lines << " 🔴 FAILED : #{f.name} (error: #{f.last_error&.message})" }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
if ["all", "tools"].include?(target) && @tool_registry
|
|
55
|
+
tools = @tool_registry.list
|
|
56
|
+
lines << "\n[Tool Registry (#{tools.size} Registered Tools)]:"
|
|
57
|
+
tools.each { |t| lines << " ⚙ #{t.name.ljust(22)} [#{t.risk}] - #{t.description[0..60]}" }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
if ["all", "commands"].include?(target) && @shell
|
|
61
|
+
cmds = @shell.commands
|
|
62
|
+
lines << "\n[REPL Bang Commands (#{cmds.size} Registered)]:"
|
|
63
|
+
cmds.sort.each { |name, meta| lines << " !#{name.ljust(16)} : #{meta[:description]}" }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
task_mgr = (Rubik::Coeffects.get(@runtime_manager.context, Rubik::Coeffects::TASK_MANAGER) if @runtime_manager&.context.respond_to?(:get))
|
|
67
|
+
task_mgr ||= @shell.task_manager if @shell.respond_to?(:task_manager)
|
|
68
|
+
|
|
69
|
+
if ["all", "tasks"].include?(target) && task_mgr
|
|
70
|
+
tasks = task_mgr.list
|
|
71
|
+
lines << "\n[Background Tasks (#{tasks.size} Tracked)]:"
|
|
72
|
+
if tasks.empty?
|
|
73
|
+
lines << " (none)"
|
|
74
|
+
else
|
|
75
|
+
tasks.each do |t|
|
|
76
|
+
dur = t.running? ? "up #{t.uptime.round(1)}s" : "#{t.status} (exit #{t.exit_code})"
|
|
77
|
+
lines << " • [#{t.id}] #{t.status.to_s.upcase} (PID #{t.pid}, #{dur}): #{t.command}"
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
lines.join("\n")
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
class ProvideServiceTool < BaseTool
|
|
87
|
+
DECLARATION = Declaration.new(
|
|
88
|
+
name: "provide_service", aliases: ["register_service", "add_service"],
|
|
89
|
+
description: "Provide a runtime service/coeffect into the root context, " \
|
|
90
|
+
"triggering reactive state transitions (Pending -> Active) for dependent fibers",
|
|
91
|
+
risk: :execute, maestro_blocked: false, # root runtime self-evolution plane (TOOLS.md maestro policy)
|
|
92
|
+
params_schema: {
|
|
93
|
+
type: "object",
|
|
94
|
+
properties: {
|
|
95
|
+
name: { type: "string", description: "Service/coeffect name (e.g. 'database', 'lsp_client', 'mock_api')" },
|
|
96
|
+
value: { type: "string", description: "Service description or initialization payload" }
|
|
97
|
+
},
|
|
98
|
+
required: ["name"]
|
|
99
|
+
}
|
|
100
|
+
)
|
|
101
|
+
def initialize(runtime_manager = nil)
|
|
102
|
+
super(DECLARATION)
|
|
103
|
+
@runtime_manager = runtime_manager
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def execute(args = {})
|
|
107
|
+
name = (args["name"] || args[:name]).to_s.strip.downcase
|
|
108
|
+
val = args["value"] || args[:value] || true
|
|
109
|
+
return ToolOutput.error("Service name cannot be empty.") if name.empty?
|
|
110
|
+
return ToolOutput.error("Runtime manager is not available.") unless @runtime_manager
|
|
111
|
+
|
|
112
|
+
@runtime_manager.provide(name, val)
|
|
113
|
+
active_count = @runtime_manager.active_fibers.size
|
|
114
|
+
pending_count = @runtime_manager.pending_fibers.size
|
|
115
|
+
|
|
116
|
+
"Service '#{name}' provided to runtime context. Reconciled fibers: #{active_count} Active, #{pending_count} Pending."
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../base"
|
|
4
|
+
require_relative "../output"
|
|
5
|
+
require_relative "subagent" # SubagentToolHelpers (supervisor resolution)
|
|
6
|
+
require_relative "../../coeffects"
|
|
7
|
+
require_relative "../../orchestrator/subagent/conversation_id"
|
|
8
|
+
|
|
9
|
+
module Rubik
|
|
10
|
+
module Tools
|
|
11
|
+
# Tool for inter-agent messaging between supervisor and subagents (Plan 94).
|
|
12
|
+
# The subagent plane rebinds this tool to the child ctx (ScopedRegistry),
|
|
13
|
+
# so a subagent messaging the maestro carries its REAL sender id; the root
|
|
14
|
+
# plane keeps the machine default sender (agent-0).
|
|
15
|
+
class SendMessageTool < BaseTool
|
|
16
|
+
include SubagentToolHelpers
|
|
17
|
+
|
|
18
|
+
DECLARATION = Declaration.new(
|
|
19
|
+
name: "send_message", aliases: ["msg_agent", "tell_subagent"],
|
|
20
|
+
description: "Send a message or instruction to another agent or subagent by its conversation ID.",
|
|
21
|
+
risk: :execute, maestro_blocked: false, # steering plane — pointing the orchestrator's workers is orchestration
|
|
22
|
+
params_schema: {
|
|
23
|
+
type: "object",
|
|
24
|
+
properties: {
|
|
25
|
+
recipient: { type: "string", description: "The recipient subagent conversation ID (e.g. 'subagent-1')" },
|
|
26
|
+
message: { type: "string", description: "The message content to deliver" },
|
|
27
|
+
steps: { type: "integer", description: "Optional additional step budget to grant alongside message" }
|
|
28
|
+
},
|
|
29
|
+
required: ["recipient", "message"]
|
|
30
|
+
}
|
|
31
|
+
)
|
|
32
|
+
def initialize(supervisor: nil, runtime_context: nil)
|
|
33
|
+
super(DECLARATION)
|
|
34
|
+
@supervisor = supervisor
|
|
35
|
+
@runtime_context = runtime_context
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def execute(args = {})
|
|
39
|
+
sup = resolve_supervisor(@supervisor, @runtime_context)
|
|
40
|
+
return ToolOutput.error("SubagentSupervisor is not available in runtime context.") unless sup
|
|
41
|
+
|
|
42
|
+
# Same model-output surface as manage_subagents: the recipient id
|
|
43
|
+
# goes through the shared dialect normalizer (B5). A multi-id list
|
|
44
|
+
# is an explicit error — a messaging tool must never silently drop
|
|
45
|
+
# recipients.
|
|
46
|
+
list = Rubik::Orchestrator::Subagent::ConversationId.normalize_list(args["recipient"] || args[:recipient])
|
|
47
|
+
return ToolOutput.error("Missing required parameter 'recipient'.") if list.empty?
|
|
48
|
+
if list.size > 1
|
|
49
|
+
return ToolOutput.error(
|
|
50
|
+
"send_message takes ONE recipient; got #{list.size} (#{list.join(', ')}). " \
|
|
51
|
+
"Send one message per recipient, or use manage_subagents for roster actions."
|
|
52
|
+
)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
recipient = list.first
|
|
56
|
+
msg = (args["message"] || args[:message]).to_s.strip
|
|
57
|
+
return ToolOutput.error("Missing required parameter 'message'.") if msg.empty?
|
|
58
|
+
|
|
59
|
+
steps = args["steps"] || args[:steps]
|
|
60
|
+
sender = subagent_sender_id
|
|
61
|
+
delivered = if sender
|
|
62
|
+
sup.send_message(recipient, msg, additional_steps: steps, _sender_id: sender)
|
|
63
|
+
else
|
|
64
|
+
sup.send_message(recipient, msg, additional_steps: steps)
|
|
65
|
+
end
|
|
66
|
+
return delivery_text(recipient) if delivered == true
|
|
67
|
+
return queued_text(recipient, steps) if delivered == :queued
|
|
68
|
+
|
|
69
|
+
ToolOutput.error(
|
|
70
|
+
"Subagent '#{recipient}' not found or no longer active. If it recently finished, redeploy it with its " \
|
|
71
|
+
"context intact: manage_subagents(action: 'redeploy', conversation_id: '#{recipient}', prompt: '<task>') " \
|
|
72
|
+
"(if the runtime reports it is still settling, retry shortly); a fresh spawn is needed only after it was reaped."
|
|
73
|
+
)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
# Subagent düzlemi (rebound araç): gönderen coeffect'i GERÇEK subagent
|
|
79
|
+
# id'sidir. Kök düzleminde sağlanmaz → Supervisor default'u kalır.
|
|
80
|
+
def subagent_sender_id
|
|
81
|
+
return nil unless @runtime_context.respond_to?(:get)
|
|
82
|
+
|
|
83
|
+
Rubik::Coeffects.get(@runtime_context, Rubik::Coeffects::SUBAGENT_SENDER_ID)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Kök alias'ına giden mesajın yanıtı kök kişisiyle konuşur ("the
|
|
87
|
+
# maestro supervisor"), alıcıyı "subagent" diye adlandırmaz.
|
|
88
|
+
def delivery_text(recipient)
|
|
89
|
+
root_alias = Rubik::Orchestrator::Subagent::ConversationId.root_alias?(recipient)
|
|
90
|
+
return "Message successfully delivered to the maestro supervisor." if root_alias
|
|
91
|
+
|
|
92
|
+
"Message successfully delivered to subagent '#{recipient}'."
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Bitmiş ama henüz reap edilmemiş alıcı: mesaj inbox'ta bekler,
|
|
96
|
+
# redeploy history'ye boşaltır (Supervisor#send_message :queued).
|
|
97
|
+
def queued_text(recipient, steps)
|
|
98
|
+
note = if steps.to_i.positive?
|
|
99
|
+
" The requested #{steps}-step grant is NOT applied to a queued message — redeploy mints a fresh budget."
|
|
100
|
+
else
|
|
101
|
+
""
|
|
102
|
+
end
|
|
103
|
+
"Subagent '#{recipient}' has finished; message QUEUED in its inbox and will be delivered when it is " \
|
|
104
|
+
"redeployed (manage_subagents action: 'redeploy', conversation_id: '#{recipient}'). It is lost if the " \
|
|
105
|
+
"subagent is reaped first.#{note}"
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../base"
|
|
4
|
+
require_relative "../output"
|
|
5
|
+
require_relative "../../coeffects"
|
|
6
|
+
require_relative "../../uris"
|
|
7
|
+
|
|
8
|
+
module Rubik
|
|
9
|
+
module Tools
|
|
10
|
+
# Kalıcı depo varlığını OKUMA aracı — iki düzlemli semantik (kullanıcı
|
|
11
|
+
# kararı 2026-09-30: subagent'ların içeriği kendi bağlamlarına
|
|
12
|
+
# yüklemesi engellenmemeli):
|
|
13
|
+
# • Kök ajan (StepExecutor): tam içerik :user_output event'iyle
|
|
14
|
+
# doğrudan KULLANICININ terminaline akar; modele yalnız kısa stub
|
|
15
|
+
# döner — "raporu göster" isteklerinde read_file + yeniden yazma
|
|
16
|
+
# iki-hop maliyetini (token ×2, yeniden biçimlendirme riski) ortadan
|
|
17
|
+
# kaldırır.
|
|
18
|
+
# • Subagent düzlemi (dispatch_subagent_tool): display kancası orada
|
|
19
|
+
# olmadığından tam içerik ajanın KENDİ bağlamına döner (read_file
|
|
20
|
+
# gibi); ekrana basım kök ajana aittir.
|
|
21
|
+
#
|
|
22
|
+
# Yalnız rubik://storage URI'leri — gerçek FS yolları read_file'ın
|
|
23
|
+
# (sandbox'lı) işi. REQUIRES sayesinde storage bağlanmamışken araç
|
|
24
|
+
# reklam edilmez (StorageTool ile aynı fail-closed gizlenme).
|
|
25
|
+
class ShowFileTool < BaseTool
|
|
26
|
+
REQUIRES = [Rubik::Coeffects::STORAGE_STORE].freeze
|
|
27
|
+
|
|
28
|
+
# Terminali sflamak yerine dürüst düşüş: büyük varlık pagine edilmeli.
|
|
29
|
+
# Satır kapısı tek başına yetmez — tek-dev-satırlık gövde (örn. depoya
|
|
30
|
+
# yazılmış minified JSON) 400 satırın altında kalır; byte kapısı eşlik
|
|
31
|
+
# eder (review-round 2 bulgusu).
|
|
32
|
+
MAX_DISPLAY_LINES = 400
|
|
33
|
+
MAX_DISPLAY_BYTES = 64 * 1024
|
|
34
|
+
|
|
35
|
+
DECLARATION = Declaration.new(
|
|
36
|
+
name: "show_file", aliases: ["show"],
|
|
37
|
+
description: "Read a stored entity (review report, plan, goal snapshot, note...) from the central " \
|
|
38
|
+
"storage database. As the ROOT agent, the full content renders DIRECTLY to the user's " \
|
|
39
|
+
"terminal and you only get a one-line stub — use it for 'show/göster' requests instead of " \
|
|
40
|
+
"read_file + re-echoing. In a subagent context the full content loads into YOUR context " \
|
|
41
|
+
"like read_file (terminal rendering is the root agent's job). Accepts rubik://storage " \
|
|
42
|
+
"URIs only, including refs form 'rubik://storage/<project>/refs/<alias>'.",
|
|
43
|
+
risk: :read,
|
|
44
|
+
params_schema: {
|
|
45
|
+
type: "object",
|
|
46
|
+
properties: {
|
|
47
|
+
path: { type: "string", description: "Storage URI: 'rubik://storage/<project>/<type>/<id>' or " \
|
|
48
|
+
"'rubik://storage/<project>/refs/<alias>'; browse via 'rubik://storage/index'" }
|
|
49
|
+
},
|
|
50
|
+
required: ["path"]
|
|
51
|
+
}
|
|
52
|
+
)
|
|
53
|
+
def initialize(runtime_context: nil)
|
|
54
|
+
super(DECLARATION)
|
|
55
|
+
@runtime_context = runtime_context
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def execute(args = {})
|
|
59
|
+
path = (args["path"] || args[:path]).to_s.strip
|
|
60
|
+
# Yalnız storage şeması: only: kapısı storage dışı her girdiyi
|
|
61
|
+
# (storagefoo, goal, düz yol...) nil düşürür — ret mesajı bugünküyle
|
|
62
|
+
# bayt-bayt aynı.
|
|
63
|
+
out = UriResolver.resolve(path, ctx: @runtime_context, only: Rubik::Uris::STORAGE)
|
|
64
|
+
if out.nil?
|
|
65
|
+
return ToolOutput.error("show_file renders rubik://storage URIs only (got '#{path[0, 80]}'). " \
|
|
66
|
+
"For filesystem paths use read_file; browse entities via 'rubik://storage/index'.")
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
return out if out.is_a?(ToolOutput) && out.error?
|
|
70
|
+
|
|
71
|
+
content = out.to_s
|
|
72
|
+
lines = content.lines.size
|
|
73
|
+
if lines > MAX_DISPLAY_LINES || content.bytesize > MAX_DISPLAY_BYTES
|
|
74
|
+
return ToolOutput.error("Entity too large to render inline (#{lines} lines / #{content.bytesize} B; " \
|
|
75
|
+
"caps: #{MAX_DISPLAY_LINES} lines / #{MAX_DISPLAY_BYTES} B). " \
|
|
76
|
+
"Use read_file with offset/limit and summarize instead.")
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
ToolOutput.display(content, stub: "Rendered #{lines} lines to the user's terminal: #{Rubik::Uris.storage_relative(path)} " \
|
|
80
|
+
"(you are not expected to know the content; ask read_file only if you must reason about it)")
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../base"
|
|
4
|
+
require_relative "../output"
|
|
5
|
+
require_relative "../../coeffects"
|
|
6
|
+
|
|
7
|
+
module Rubik
|
|
8
|
+
module Tools
|
|
9
|
+
# Level-2 progressive disclosure (agentskills.io): returns the full
|
|
10
|
+
# SKILL.md body of one skill. Read-only — skills are data and are never
|
|
11
|
+
# executed here; auxiliary scripts run through run_command like any file.
|
|
12
|
+
#
|
|
13
|
+
# Coeffect contract (AGENTS.md §2): declared via REQUIRES as
|
|
14
|
+
# defense-in-depth — production registers this tool through
|
|
15
|
+
# Skills::Manager#open_epoch!, which only runs after the skill_manager
|
|
16
|
+
# coeffect is provided, but a direct/static registration (tests, future
|
|
17
|
+
# hosts) stays PENDING (hidden from Registry#schemas) until the coeffect
|
|
18
|
+
# is satisfied — the same gate ListFilesTool uses for context_index.
|
|
19
|
+
class SkillTool < BaseTool
|
|
20
|
+
NAME = "skill"
|
|
21
|
+
REQUIRES = [Rubik::Coeffects::SKILL_MANAGER].freeze
|
|
22
|
+
|
|
23
|
+
# Not in Catalog::BUILTINS — Skills::Manager#open_epoch! registers this
|
|
24
|
+
# tool dynamically with its own ctx inverse; the declaration is real
|
|
25
|
+
# wherever the tool is registered.
|
|
26
|
+
DECLARATION = Declaration.new(
|
|
27
|
+
name: NAME,
|
|
28
|
+
description: "Load the full instructions of an agent skill by name. Available skills are listed in " \
|
|
29
|
+
"the <skills> system-prompt section. Call this before following a skill's guidance; " \
|
|
30
|
+
"files under its scripts/, references/ or assets/ directories are read with read_file " \
|
|
31
|
+
"relative to the returned skill directory.",
|
|
32
|
+
risk: :read, maestro_blocked: false,
|
|
33
|
+
params_schema: {
|
|
34
|
+
type: "object",
|
|
35
|
+
properties: {
|
|
36
|
+
name: { type: "string", description: "Skill name exactly as listed in the <skills> section" }
|
|
37
|
+
},
|
|
38
|
+
required: ["name"]
|
|
39
|
+
}
|
|
40
|
+
)
|
|
41
|
+
def initialize(manager = nil, runtime_context: nil)
|
|
42
|
+
super(DECLARATION)
|
|
43
|
+
@manager = manager
|
|
44
|
+
@runtime_context = runtime_context
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def execute(args = {})
|
|
48
|
+
manager = Rubik::Coeffects.resolve(@runtime_context, Rubik::Coeffects::SKILL_MANAGER, @manager)
|
|
49
|
+
return ToolOutput.error("Error: skills manager is not available.") unless manager
|
|
50
|
+
return ToolOutput.error("Error: skills are disabled (skills.enabled = false).") unless manager.enabled?
|
|
51
|
+
|
|
52
|
+
name = (args["name"] || args[:name]).to_s.strip
|
|
53
|
+
available = manager.all.map(&:name)
|
|
54
|
+
available_list = available.empty? ? "none" : available.join(", ")
|
|
55
|
+
return ToolOutput.error("Error: `name` is required. Available skills: #{available_list}.") if name.empty?
|
|
56
|
+
|
|
57
|
+
skill = manager.find(name)
|
|
58
|
+
return ToolOutput.error("Error: unknown skill '#{name}'. Available skills: #{available_list}.") unless skill
|
|
59
|
+
|
|
60
|
+
body = manager.body(name)
|
|
61
|
+
return ToolOutput.error("Error: SKILL.md of '#{name}' could not be read (#{skill.path}).") if body.nil?
|
|
62
|
+
|
|
63
|
+
ToolOutput.ok(<<~OUTPUT.strip)
|
|
64
|
+
Skill '#{skill.name}' (scope: #{skill.scope}, directory: #{skill.root})
|
|
65
|
+
Files referenced below (scripts/, references/, assets/) are read with read_file / run_command relative to that directory.
|
|
66
|
+
---
|
|
67
|
+
#{body}
|
|
68
|
+
OUTPUT
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|