alysis-code 0.13.0__py3-none-any.whl
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.
- alysis_code/__init__.py +3 -0
- alysis_code/__main__.py +4 -0
- alysis_code/_build_info.py +14 -0
- alysis_code/account_login.py +468 -0
- alysis_code/agent/README.md +35 -0
- alysis_code/agent/__init__.py +11 -0
- alysis_code/agent/acceptance_contract.py +2217 -0
- alysis_code/agent/blast_radius.py +1403 -0
- alysis_code/agent/cache_keepalive.py +227 -0
- alysis_code/agent/completion_certificate.py +366 -0
- alysis_code/agent/completion_gate.py +306 -0
- alysis_code/agent/empty_response_stall.py +403 -0
- alysis_code/agent/errors.py +28 -0
- alysis_code/agent/llm_calls.py +475 -0
- alysis_code/agent/mutation_classification.py +227 -0
- alysis_code/agent/prompt_context.py +2508 -0
- alysis_code/agent/read_ledger.py +253 -0
- alysis_code/agent/regression_baseline.py +642 -0
- alysis_code/agent/reproduction_first.py +610 -0
- alysis_code/agent/sensitive_output.py +629 -0
- alysis_code/agent/session.py +3218 -0
- alysis_code/agent/steering.py +191 -0
- alysis_code/agent/subagent_execution.py +5177 -0
- alysis_code/agent/subagent_workspace.py +666 -0
- alysis_code/agent/tools_assembly.py +4728 -0
- alysis_code/agent/turn/__init__.py +101 -0
- alysis_code/agent/turn/core.py +8483 -0
- alysis_code/agent/turn/events.py +113 -0
- alysis_code/agent/turn/exploration.py +590 -0
- alysis_code/agent/turn/interventions.py +65 -0
- alysis_code/agent/turn/read_cache.py +420 -0
- alysis_code/agent/turn/snapshot.py +179 -0
- alysis_code/agent/turn_contract.py +661 -0
- alysis_code/agent/turn_path.py +129 -0
- alysis_code/agent/verification.py +2885 -0
- alysis_code/agent/verification_commands.py +512 -0
- alysis_code/agent/verification_evidence.py +738 -0
- alysis_code/agent_loop.py +693 -0
- alysis_code/agent_runtimes/__init__.py +51 -0
- alysis_code/agent_runtimes/base.py +114 -0
- alysis_code/agent_runtimes/builtins.py +129 -0
- alysis_code/agent_runtimes/codex_cli.py +664 -0
- alysis_code/agent_runtimes/host.py +263 -0
- alysis_code/agent_runtimes/registry.py +64 -0
- alysis_code/agent_runtimes/service.py +150 -0
- alysis_code/agentbox_client.py +416 -0
- alysis_code/agentbox_integration.py +310 -0
- alysis_code/alysis_cloud.py +152 -0
- alysis_code/approval_scope.py +276 -0
- alysis_code/assets/README.md +33 -0
- alysis_code/assets/__init__.py +126 -0
- alysis_code/assets/asset_read_core.py +281 -0
- alysis_code/assets/budget_allocator.py +456 -0
- alysis_code/assets/comprehender.py +759 -0
- alysis_code/assets/index.py +654 -0
- alysis_code/assets/ingestion.py +275 -0
- alysis_code/assets/legacy_migration.py +413 -0
- alysis_code/assets/models.py +263 -0
- alysis_code/assets/ocr.py +239 -0
- alysis_code/assets/owl/ascii/f-000.txt +13 -0
- alysis_code/assets/owl/ascii/f-001.txt +13 -0
- alysis_code/assets/owl/ascii/f-002.txt +13 -0
- alysis_code/assets/owl/ascii/f-003.txt +13 -0
- alysis_code/assets/owl/ascii/f-004.txt +13 -0
- alysis_code/assets/owl/ascii/f-005.txt +13 -0
- alysis_code/assets/owl/ascii/f-006.txt +13 -0
- alysis_code/assets/owl/ascii/f-007.txt +13 -0
- alysis_code/assets/owl/ascii/f-008.txt +13 -0
- alysis_code/assets/owl/ascii/f-009.txt +13 -0
- alysis_code/assets/owl/ascii/f-010.txt +13 -0
- alysis_code/assets/owl/ascii/f-011.txt +13 -0
- alysis_code/assets/owl/ascii/f-012.txt +13 -0
- alysis_code/assets/owl/ascii/f-013.txt +13 -0
- alysis_code/assets/owl/ascii/f-014.txt +13 -0
- alysis_code/assets/owl/ascii/f-015.txt +13 -0
- alysis_code/assets/owl/ascii/f-016.txt +13 -0
- alysis_code/assets/owl/ascii/f-017.txt +13 -0
- alysis_code/assets/owl/ascii/f-018.txt +13 -0
- alysis_code/assets/owl/ascii/f-019.txt +13 -0
- alysis_code/assets/owl/ascii/f-020.txt +13 -0
- alysis_code/assets/owl/index.html +98 -0
- alysis_code/assets/owl/show-owl.sh +761 -0
- alysis_code/assets/paths.py +49 -0
- alysis_code/assets/plan_binding.py +326 -0
- alysis_code/assets/planner_context.py +466 -0
- alysis_code/assets/planner_tools.py +184 -0
- alysis_code/assets/prompts.py +101 -0
- alysis_code/assets/replanner_context.py +239 -0
- alysis_code/assets/surface.py +521 -0
- alysis_code/assets/untrusted_content.py +48 -0
- alysis_code/assets/usage_logger.py +94 -0
- alysis_code/assets/worker_mirror.py +428 -0
- alysis_code/assets/worker_section.py +303 -0
- alysis_code/assets/worker_tools.py +468 -0
- alysis_code/atomic_io.py +83 -0
- alysis_code/auth_diagnostics.py +272 -0
- alysis_code/background_runner.py +366 -0
- alysis_code/branding.py +270 -0
- alysis_code/budget_policy.py +390 -0
- alysis_code/build_identity.py +465 -0
- alysis_code/builtin_hooks/__init__.py +7 -0
- alysis_code/builtin_hooks/notify_done_windows.py +65 -0
- alysis_code/bwrap_etc.py +76 -0
- alysis_code/cancellation.py +41 -0
- alysis_code/capabilities.py +137 -0
- alysis_code/chatgpt_codex_static_provider.py +133 -0
- alysis_code/cli.py +51 -0
- alysis_code/cli_impl/__init__.py +1 -0
- alysis_code/cli_impl/assets_cli.py +537 -0
- alysis_code/cli_impl/assets_modal.py +412 -0
- alysis_code/cli_impl/chat/__init__.py +156 -0
- alysis_code/cli_impl/chat/commands.py +2616 -0
- alysis_code/cli_impl/chat/loop.py +4508 -0
- alysis_code/cli_impl/chat/mid_turn_policy.py +125 -0
- alysis_code/cli_impl/chat/rendering.py +444 -0
- alysis_code/cli_impl/chat/state.py +124 -0
- alysis_code/cli_impl/chat_resume.py +830 -0
- alysis_code/cli_impl/chat_slash_completer.py +258 -0
- alysis_code/cli_impl/commands/__init__.py +11 -0
- alysis_code/cli_impl/commands/_shared.py +89 -0
- alysis_code/cli_impl/commands/auth.py +623 -0
- alysis_code/cli_impl/commands/chat_resume_helpers.py +1531 -0
- alysis_code/cli_impl/commands/chat_state.py +158 -0
- alysis_code/cli_impl/commands/chat_status.py +1248 -0
- alysis_code/cli_impl/commands/chat_terminal.py +942 -0
- alysis_code/cli_impl/commands/chat_tui_panels.py +1018 -0
- alysis_code/cli_impl/commands/cli_common.py +1223 -0
- alysis_code/cli_impl/commands/cli_surface.py +77 -0
- alysis_code/cli_impl/commands/config.py +131 -0
- alysis_code/cli_impl/commands/conventions.py +85 -0
- alysis_code/cli_impl/commands/execution_helpers.py +350 -0
- alysis_code/cli_impl/commands/extensions.py +401 -0
- alysis_code/cli_impl/commands/forge.py +1282 -0
- alysis_code/cli_impl/commands/forge_asset_view.py +121 -0
- alysis_code/cli_impl/commands/forge_helpers.py +1215 -0
- alysis_code/cli_impl/commands/hooks.py +737 -0
- alysis_code/cli_impl/commands/ide_bridge.py +31 -0
- alysis_code/cli_impl/commands/mcp.py +700 -0
- alysis_code/cli_impl/commands/profile.py +453 -0
- alysis_code/cli_impl/commands/prompt_helpers.py +307 -0
- alysis_code/cli_impl/commands/report.py +88 -0
- alysis_code/cli_impl/commands/root.py +1118 -0
- alysis_code/cli_impl/commands/sandbox.py +184 -0
- alysis_code/cli_impl/commands/server.py +54 -0
- alysis_code/cli_impl/commands/sessions.py +252 -0
- alysis_code/cli_impl/commands/skills.py +404 -0
- alysis_code/cli_impl/commands/startup.py +946 -0
- alysis_code/cli_impl/commands/tools.py +335 -0
- alysis_code/cli_impl/commands/update.py +364 -0
- alysis_code/cli_impl/commands/welcome.py +972 -0
- alysis_code/cli_impl/config_menu.py +3882 -0
- alysis_code/cli_impl/forge.py +4509 -0
- alysis_code/cli_impl/forge_recovery.py +485 -0
- alysis_code/cli_impl/setup_wizard.py +2409 -0
- alysis_code/cli_impl/tui/__init__.py +58 -0
- alysis_code/cli_impl/tui/app.py +4551 -0
- alysis_code/cli_impl/tui/config.py +32 -0
- alysis_code/cli_impl/tui/config_flow.py +2754 -0
- alysis_code/cli_impl/tui/config_overlay.py +566 -0
- alysis_code/cli_impl/tui/content.py +78 -0
- alysis_code/cli_impl/tui/footer.py +218 -0
- alysis_code/cli_impl/tui/forge_status.py +136 -0
- alysis_code/cli_impl/tui/markdown.py +244 -0
- alysis_code/cli_impl/tui/owl.py +109 -0
- alysis_code/cli_impl/tui/plan_meta.py +477 -0
- alysis_code/cli_impl/tui/setup_app.py +519 -0
- alysis_code/cli_impl/tui/setup_flow.py +1622 -0
- alysis_code/cli_impl/tui/state.py +101 -0
- alysis_code/cli_impl/tui/subagent_identity.py +66 -0
- alysis_code/cli_impl/tui/subagent_panel.py +186 -0
- alysis_code/cli_impl/tui/surface.py +796 -0
- alysis_code/cli_impl/tui/transcript.py +514 -0
- alysis_code/cli_impl/tui/update_prompt.py +79 -0
- alysis_code/cli_impl/tui/workspace_guard.py +384 -0
- alysis_code/clipboard.py +172 -0
- alysis_code/code_review.py +1211 -0
- alysis_code/compaction/__init__.py +28 -0
- alysis_code/compaction/conversation_compactor.py +2932 -0
- alysis_code/compaction/importance.py +177 -0
- alysis_code/compaction/settings.py +297 -0
- alysis_code/compaction/tool_output_offload.py +447 -0
- alysis_code/config.py +3509 -0
- alysis_code/conflict_auto_resolver.py +895 -0
- alysis_code/context/__init__.py +1 -0
- alysis_code/context/tool_schema_budgeter.py +220 -0
- alysis_code/crash_diagnostics.py +282 -0
- alysis_code/custom_tools/README.md +34 -0
- alysis_code/custom_tools/__init__.py +43 -0
- alysis_code/custom_tools/discovery.py +903 -0
- alysis_code/custom_tools/runtime.py +1516 -0
- alysis_code/custom_tools/session.py +227 -0
- alysis_code/custom_tools/trust.py +232 -0
- alysis_code/diff_paths.py +113 -0
- alysis_code/direction_change.py +293 -0
- alysis_code/dispatch_timing.py +306 -0
- alysis_code/durable_service_manager.py +1236 -0
- alysis_code/edit_discipline.py +659 -0
- alysis_code/error_text.py +73 -0
- alysis_code/execution_budget.py +411 -0
- alysis_code/execution_context.py +915 -0
- alysis_code/execution_deadline.py +1065 -0
- alysis_code/execution_shared.py +1904 -0
- alysis_code/extensions/README.md +30 -0
- alysis_code/extensions/__init__.py +93 -0
- alysis_code/extensions/activation.py +138 -0
- alysis_code/extensions/install.py +1436 -0
- alysis_code/extensions/manifest.py +487 -0
- alysis_code/extensions/models.py +74 -0
- alysis_code/extensions/paths.py +56 -0
- alysis_code/extensions/registry.json +4 -0
- alysis_code/extensions/registry.py +52 -0
- alysis_code/extensions/state.py +83 -0
- alysis_code/extensions/workspace_trust.py +101 -0
- alysis_code/failed_task_evidence.py +369 -0
- alysis_code/failure_category.py +315 -0
- alysis_code/feedback_report.py +1647 -0
- alysis_code/file_classification.py +485 -0
- alysis_code/forge.py +2064 -0
- alysis_code/forge_completion.py +362 -0
- alysis_code/forge_events.py +475 -0
- alysis_code/frontmatter_utils.py +95 -0
- alysis_code/git_evidence.py +1181 -0
- alysis_code/git_ops.py +560 -0
- alysis_code/git_safe.py +62 -0
- alysis_code/git_worktrees.py +190 -0
- alysis_code/hooks/README.md +33 -0
- alysis_code/hooks/__init__.py +67 -0
- alysis_code/hooks/audit.py +171 -0
- alysis_code/hooks/config.py +225 -0
- alysis_code/hooks/dispatcher.py +1110 -0
- alysis_code/hooks/models.py +447 -0
- alysis_code/hooks/trust.py +202 -0
- alysis_code/host_actions.py +543 -0
- alysis_code/host_browser.py +103 -0
- alysis_code/ide/__init__.py +5 -0
- alysis_code/ide/activity_events.py +399 -0
- alysis_code/ide/approvals.py +337 -0
- alysis_code/ide/artifacts.py +153 -0
- alysis_code/ide/browser_egress_proxy.py +1076 -0
- alysis_code/ide/cdp_websocket_transport.py +1192 -0
- alysis_code/ide/change_ledger.py +1721 -0
- alysis_code/ide/context_blocks.py +979 -0
- alysis_code/ide/event_stream.py +531 -0
- alysis_code/ide/forge_protocol.py +3112 -0
- alysis_code/ide/forge_request_ledger.py +737 -0
- alysis_code/ide/health.py +965 -0
- alysis_code/ide/managed_browser.py +2251 -0
- alysis_code/ide/management_protocol.py +3414 -0
- alysis_code/ide/mcp_oauth_coordinator.py +744 -0
- alysis_code/ide/mcp_oauth_lifecycle.py +1504 -0
- alysis_code/ide/prompt_queue.py +1070 -0
- alysis_code/ide/protocol.py +191 -0
- alysis_code/ide/resumable_swarm.py +1543 -0
- alysis_code/ide/session_search.py +295 -0
- alysis_code/ide/stdio_bridge.py +9935 -0
- alysis_code/ide/structured_state.py +1579 -0
- alysis_code/ide/swarm_protocol.py +816 -0
- alysis_code/integration_gate.py +506 -0
- alysis_code/interactive_input_guard.py +39 -0
- alysis_code/interactive_plan_mode.py +26 -0
- alysis_code/internal_artifacts.py +179 -0
- alysis_code/knowledge_base.py +1409 -0
- alysis_code/knowledge_capture.py +1190 -0
- alysis_code/knowledge_librarian.py +605 -0
- alysis_code/language_policy.py +34 -0
- alysis_code/litellm_static_provider.py +535 -0
- alysis_code/llm/__init__.py +1 -0
- alysis_code/llm/anthropic_messages.py +2288 -0
- alysis_code/llm/base.py +71 -0
- alysis_code/llm/cache_capabilities.py +985 -0
- alysis_code/llm/cache_control_blocks.py +244 -0
- alysis_code/llm/cache_policy.py +388 -0
- alysis_code/llm/factory.py +373 -0
- alysis_code/llm/gemini_generate_content.py +2652 -0
- alysis_code/llm/gemini_interactions.py +739 -0
- alysis_code/llm/metadata.py +450 -0
- alysis_code/llm/openai_compat.py +2947 -0
- alysis_code/llm/openai_responses.py +2604 -0
- alysis_code/llm/protocols.py +609 -0
- alysis_code/llm/provider_limits.py +525 -0
- alysis_code/llm/request_plan.py +389 -0
- alysis_code/llm/request_shape.py +238 -0
- alysis_code/llm/streaming.py +108 -0
- alysis_code/llm/temperature_compat.py +78 -0
- alysis_code/llm/types.py +195 -0
- alysis_code/llm/usage_normalization.py +222 -0
- alysis_code/llm_error_display.py +315 -0
- alysis_code/logging_redaction.py +326 -0
- alysis_code/managed_host_deadline.py +196 -0
- alysis_code/mcp/README.md +33 -0
- alysis_code/mcp/__init__.py +24 -0
- alysis_code/mcp/client.py +1137 -0
- alysis_code/mcp/config.py +597 -0
- alysis_code/mcp/errors.py +113 -0
- alysis_code/mcp/forge_scope.py +154 -0
- alysis_code/mcp/jsonrpc.py +214 -0
- alysis_code/mcp/manager.py +2308 -0
- alysis_code/mcp/models.py +666 -0
- alysis_code/mcp/oauth.py +972 -0
- alysis_code/mcp/oauth_runtime.py +310 -0
- alysis_code/mcp/oauth_store.py +276 -0
- alysis_code/mcp/prompts.py +329 -0
- alysis_code/mcp/resources.py +295 -0
- alysis_code/mcp/roots.py +106 -0
- alysis_code/mcp/server_requests.py +75 -0
- alysis_code/mcp/token_store.py +859 -0
- alysis_code/mcp/transport_http.py +1338 -0
- alysis_code/mcp/transport_stdio.py +1267 -0
- alysis_code/mcp/untrusted_content.py +119 -0
- alysis_code/merge_conflict_reviewer.py +729 -0
- alysis_code/model_catalog/__init__.py +1 -0
- alysis_code/model_catalog/chatgpt_codex_subscription_snapshot.json +186 -0
- alysis_code/model_catalog/litellm_model_prices_snapshot.json +44715 -0
- alysis_code/model_catalog/litellm_model_prices_snapshot.meta.json +17 -0
- alysis_code/model_metadata_policy.py +223 -0
- alysis_code/model_metadata_utils.py +103 -0
- alysis_code/model_registry.py +1420 -0
- alysis_code/model_router.py +147 -0
- alysis_code/permission_policy.py +1016 -0
- alysis_code/personas.py +451 -0
- alysis_code/pipeline_facts.py +233 -0
- alysis_code/plan_assistant.py +4763 -0
- alysis_code/plan_mode.py +393 -0
- alysis_code/plan_reconciliation.py +1228 -0
- alysis_code/plan_repair.py +652 -0
- alysis_code/plan_validation.py +1099 -0
- alysis_code/planning_constraints.py +904 -0
- alysis_code/policy.py +95 -0
- alysis_code/preview_server.py +457 -0
- alysis_code/process_reaping.py +566 -0
- alysis_code/profile_presets.py +1834 -0
- alysis_code/profiles.py +666 -0
- alysis_code/provider_auth/__init__.py +29 -0
- alysis_code/provider_auth/base.py +99 -0
- alysis_code/provider_auth/openai_codex.py +951 -0
- alysis_code/provider_auth/registry.py +76 -0
- alysis_code/provider_auth/store.py +125 -0
- alysis_code/provider_diagnostics.py +1209 -0
- alysis_code/provider_model_catalog.py +685 -0
- alysis_code/provider_telemetry.py +1699 -0
- alysis_code/provider_url.py +75 -0
- alysis_code/reasoning_contracts.py +911 -0
- alysis_code/remote_sync.py +350 -0
- alysis_code/replanning.py +1195 -0
- alysis_code/repo_scan.py +1152 -0
- alysis_code/request_estimation.py +296 -0
- alysis_code/review_gate.py +617 -0
- alysis_code/run_lock.py +1141 -0
- alysis_code/run_outcome.py +58 -0
- alysis_code/run_provenance.py +774 -0
- alysis_code/run_state.py +445 -0
- alysis_code/runtime_artifacts.py +116 -0
- alysis_code/runtime_context_features.py +78 -0
- alysis_code/runtime_kind.py +52 -0
- alysis_code/safety/__init__.py +11 -0
- alysis_code/safety/mcp_sanitize.py +29 -0
- alysis_code/safety/safe_http.py +297 -0
- alysis_code/safety/subagent_report.py +184 -0
- alysis_code/sandbox_doctor.py +682 -0
- alysis_code/sandbox_runner.py +1025 -0
- alysis_code/sandbox_settings.py +423 -0
- alysis_code/serialized_paths.py +355 -0
- alysis_code/server/__init__.py +3 -0
- alysis_code/server/app.py +367 -0
- alysis_code/server/auth.py +34 -0
- alysis_code/server/job_config.py +30 -0
- alysis_code/server/settings.py +215 -0
- alysis_code/server/store.py +193 -0
- alysis_code/server/worker_runner.py +657 -0
- alysis_code/service_persistence.py +355 -0
- alysis_code/session_artifacts.py +108 -0
- alysis_code/session_metrics.py +331 -0
- alysis_code/session_store.py +624 -0
- alysis_code/skills/README.md +34 -0
- alysis_code/skills/__init__.py +104 -0
- alysis_code/skills/conventions.py +84 -0
- alysis_code/skills/discovery.py +176 -0
- alysis_code/skills/eval_models.py +232 -0
- alysis_code/skills/eval_runner.py +372 -0
- alysis_code/skills/evals.py +1344 -0
- alysis_code/skills/install.py +293 -0
- alysis_code/skills/loader.py +118 -0
- alysis_code/skills/matching.py +103 -0
- alysis_code/skills/models.py +71 -0
- alysis_code/skills/paths.py +56 -0
- alysis_code/skills/prompting.py +500 -0
- alysis_code/skills/scaffold.py +142 -0
- alysis_code/skills/state.py +441 -0
- alysis_code/skills/transactions.py +125 -0
- alysis_code/skills/validation.py +304 -0
- alysis_code/step_budget.py +238 -0
- alysis_code/subagent_labels.py +49 -0
- alysis_code/subagents.py +1072 -0
- alysis_code/surface/__init__.py +80 -0
- alysis_code/surface/base.py +305 -0
- alysis_code/surface/console.py +387 -0
- alysis_code/surface/events.py +372 -0
- alysis_code/surface/hidden_surface.py +529 -0
- alysis_code/surface/noop_surface.py +219 -0
- alysis_code/surface/rich_surface.py +1555 -0
- alysis_code/surface/styles.py +67 -0
- alysis_code/surface/theme.py +455 -0
- alysis_code/surface/types.py +100 -0
- alysis_code/swarm_backend.py +926 -0
- alysis_code/swarm_orchestrator.py +4020 -0
- alysis_code/swarm_scheduler.py +441 -0
- alysis_code/swarm_trace.py +429 -0
- alysis_code/swarm_worker.py +2119 -0
- alysis_code/swarm_write_guard.py +348 -0
- alysis_code/task_dependencies.py +170 -0
- alysis_code/task_readiness.py +992 -0
- alysis_code/task_scope.py +2148 -0
- alysis_code/terminal_manager.py +762 -0
- alysis_code/terminal_ownership.py +460 -0
- alysis_code/text_normalization.py +30 -0
- alysis_code/token_budget.py +97 -0
- alysis_code/tools/README.md +34 -0
- alysis_code/tools/__init__.py +1 -0
- alysis_code/tools/artifacts.py +127 -0
- alysis_code/tools/availability.py +188 -0
- alysis_code/tools/fs.py +1456 -0
- alysis_code/tools/git.py +461 -0
- alysis_code/tools/history.py +229 -0
- alysis_code/tools/http_timeout.py +78 -0
- alysis_code/tools/image_generation.py +552 -0
- alysis_code/tools/registry.py +2936 -0
- alysis_code/tools/repo_map.py +476 -0
- alysis_code/tools/search.py +563 -0
- alysis_code/tools/shell.py +135 -0
- alysis_code/tools/symbols.py +1350 -0
- alysis_code/tools/test_discovery.py +643 -0
- alysis_code/tools/web.py +482 -0
- alysis_code/tools/web_search.py +2012 -0
- alysis_code/tools/web_search_dashscope.py +557 -0
- alysis_code/tools/web_search_ddgs.py +221 -0
- alysis_code/tools/web_search_provider_adapters.py +1429 -0
- alysis_code/tools/web_search_tavily.py +194 -0
- alysis_code/updates.py +933 -0
- alysis_code/usage_tracker.py +1990 -0
- alysis_code/verification_command_analysis.py +1004 -0
- alysis_code/verification_contract.py +574 -0
- alysis_code/verification_failure_summary.py +273 -0
- alysis_code/verification_repair.py +385 -0
- alysis_code/verify_gate.py +3129 -0
- alysis_code/web_research.py +1872 -0
- alysis_code/web_search_adapters.py +66 -0
- alysis_code/web_search_policy.py +27 -0
- alysis_code/workspace_binding.py +389 -0
- alysis_code/workspace_binding_ui.py +408 -0
- alysis_code/workspace_context.py +273 -0
- alysis_code/workspace_isolation.py +138 -0
- alysis_code/workspace_provisioning.py +455 -0
- alysis_code-0.13.0.dist-info/METADATA +507 -0
- alysis_code-0.13.0.dist-info/RECORD +458 -0
- alysis_code-0.13.0.dist-info/WHEEL +4 -0
- alysis_code-0.13.0.dist-info/entry_points.txt +3 -0
- alysis_code-0.13.0.dist-info/licenses/LICENSE +176 -0
- alysis_code-0.13.0.dist-info/licenses/NOTICE +4 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from ..forge import RunPaths
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def asset_store_dir(run_paths: RunPaths) -> Path:
|
|
9
|
+
return run_paths.asset_store_dir
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def asset_raw_dir(run_paths: RunPaths, asset_id: str) -> Path:
|
|
13
|
+
return run_paths.assets_raw_dir / asset_id
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def asset_raw_path(run_paths: RunPaths, asset_id: str, original_filename: str) -> Path:
|
|
17
|
+
return asset_raw_dir(run_paths, asset_id) / original_filename
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def asset_extracted_text_path(run_paths: RunPaths, asset_id: str) -> Path:
|
|
21
|
+
return run_paths.assets_extracted_dir / f"{asset_id}.txt"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def asset_thumbnail_path(run_paths: RunPaths, asset_id: str) -> Path:
|
|
25
|
+
return run_paths.assets_extracted_dir / f"{asset_id}.thumb.png"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def asset_preview_path(run_paths: RunPaths, asset_id: str) -> Path:
|
|
29
|
+
return run_paths.assets_extracted_dir / f"{asset_id}.preview.png"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def asset_comprehension_dir(run_paths: RunPaths, asset_id: str) -> Path:
|
|
33
|
+
return run_paths.assets_comprehensions_dir / asset_id
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def asset_comprehension_version_path(
|
|
37
|
+
run_paths: RunPaths,
|
|
38
|
+
asset_id: str,
|
|
39
|
+
version: int,
|
|
40
|
+
) -> Path:
|
|
41
|
+
return asset_comprehension_dir(run_paths, asset_id) / f"v{version}.json"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def asset_comprehension_current_path(run_paths: RunPaths, asset_id: str) -> Path:
|
|
45
|
+
return asset_comprehension_dir(run_paths, asset_id) / "current.json"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def repo_rel(root: Path, path: Path) -> str:
|
|
49
|
+
return path.resolve().relative_to(root.resolve()).as_posix()
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from collections.abc import Iterable
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from .models import AssetError
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(frozen=True)
|
|
12
|
+
class AssetBriefingEntry:
|
|
13
|
+
asset_id: str
|
|
14
|
+
rationale: str
|
|
15
|
+
expected_use: str
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass(frozen=True)
|
|
19
|
+
class TaskAssetBriefing:
|
|
20
|
+
primary: list[AssetBriefingEntry]
|
|
21
|
+
may_need: list[AssetBriefingEntry]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
_ASSET_INTENT_RE = re.compile(
|
|
25
|
+
r"\b(?:asset|attach(?:ed|ment)?|brief|design|image|mockup|note|pdf|"
|
|
26
|
+
r"screenshot|spec|uploaded|wireframe)\b",
|
|
27
|
+
re.IGNORECASE,
|
|
28
|
+
)
|
|
29
|
+
_SINGLE_ASSET_REFERENCE_RE = re.compile(
|
|
30
|
+
r"\b(?:asset|attach(?:ed|ment)?|brief|image|mockup|pdf|screenshot|uploaded|wireframe)\b",
|
|
31
|
+
re.IGNORECASE,
|
|
32
|
+
)
|
|
33
|
+
_WORD_RE = re.compile(r"[a-z0-9][a-z0-9_-]*", re.IGNORECASE)
|
|
34
|
+
_TOKEN_STOPWORDS = frozenset(
|
|
35
|
+
{
|
|
36
|
+
"and",
|
|
37
|
+
"for",
|
|
38
|
+
"from",
|
|
39
|
+
"into",
|
|
40
|
+
"the",
|
|
41
|
+
"this",
|
|
42
|
+
"that",
|
|
43
|
+
"task",
|
|
44
|
+
"use",
|
|
45
|
+
"using",
|
|
46
|
+
"with",
|
|
47
|
+
}
|
|
48
|
+
)
|
|
49
|
+
_IMPLICIT_ASSET_LIMIT = 3
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def parse_task_asset_briefing(payload: Any | None) -> TaskAssetBriefing | None:
|
|
53
|
+
if payload is None:
|
|
54
|
+
return None
|
|
55
|
+
if not isinstance(payload, dict):
|
|
56
|
+
raise AssetError("asset_briefing must be an object")
|
|
57
|
+
_reject_unknown_keys(payload, allowed={"primary", "may_need"}, field="asset_briefing")
|
|
58
|
+
return TaskAssetBriefing(
|
|
59
|
+
primary=_parse_entries(payload.get("primary"), field="asset_briefing.primary"),
|
|
60
|
+
may_need=_parse_entries(payload.get("may_need"), field="asset_briefing.may_need"),
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def serialize_task_asset_briefing(briefing: TaskAssetBriefing | None) -> dict[str, Any] | None:
|
|
65
|
+
if briefing is None:
|
|
66
|
+
return None
|
|
67
|
+
return {
|
|
68
|
+
"primary": [_entry_to_dict(entry) for entry in briefing.primary],
|
|
69
|
+
"may_need": [_entry_to_dict(entry) for entry in briefing.may_need],
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def collect_referenced_asset_ids(plan: dict[str, Any]) -> set[str]:
|
|
74
|
+
referenced: set[str] = set()
|
|
75
|
+
for task in plan.get("tasks") or []:
|
|
76
|
+
if not isinstance(task, dict):
|
|
77
|
+
continue
|
|
78
|
+
briefing = task_asset_briefing(task)
|
|
79
|
+
if briefing is None:
|
|
80
|
+
continue
|
|
81
|
+
referenced.update(entry.asset_id for entry in briefing.primary)
|
|
82
|
+
referenced.update(entry.asset_id for entry in briefing.may_need)
|
|
83
|
+
return referenced
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def task_asset_briefing(task: dict[str, Any]) -> TaskAssetBriefing | None:
|
|
87
|
+
return parse_task_asset_briefing(task.get("asset_briefing"))
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def task_asset_briefing_for_execution(
|
|
91
|
+
task: dict[str, Any],
|
|
92
|
+
*,
|
|
93
|
+
records: Iterable[Any],
|
|
94
|
+
) -> TaskAssetBriefing | None:
|
|
95
|
+
briefing = task_asset_briefing(task)
|
|
96
|
+
if briefing is not None and (briefing.primary or briefing.may_need):
|
|
97
|
+
return briefing
|
|
98
|
+
return infer_implicit_task_asset_briefing(task=task, records=records)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def infer_implicit_task_asset_briefing(
|
|
102
|
+
*,
|
|
103
|
+
task: dict[str, Any],
|
|
104
|
+
records: Iterable[Any],
|
|
105
|
+
) -> TaskAssetBriefing | None:
|
|
106
|
+
active_records = [
|
|
107
|
+
record
|
|
108
|
+
for record in records
|
|
109
|
+
if getattr(record, "deleted_at", None) is None
|
|
110
|
+
and not bool(getattr(record, "pinned", False))
|
|
111
|
+
]
|
|
112
|
+
if not active_records:
|
|
113
|
+
return None
|
|
114
|
+
task_text = _task_text(task)
|
|
115
|
+
if not task_text:
|
|
116
|
+
return None
|
|
117
|
+
has_asset_intent = bool(_ASSET_INTENT_RE.search(task_text))
|
|
118
|
+
has_single_asset_reference = bool(_SINGLE_ASSET_REFERENCE_RE.search(task_text))
|
|
119
|
+
scored: list[tuple[int, int, Any]] = []
|
|
120
|
+
for index, record in enumerate(active_records):
|
|
121
|
+
score = _asset_match_score(
|
|
122
|
+
task_text=task_text,
|
|
123
|
+
record=record,
|
|
124
|
+
single_active_asset=len(active_records) == 1,
|
|
125
|
+
has_asset_intent=has_asset_intent,
|
|
126
|
+
has_single_asset_reference=has_single_asset_reference,
|
|
127
|
+
)
|
|
128
|
+
if _asset_score_is_relevant(score=score, has_asset_intent=has_asset_intent):
|
|
129
|
+
scored.append((score, index, record))
|
|
130
|
+
if not scored:
|
|
131
|
+
return None
|
|
132
|
+
scored.sort(key=lambda item: (-item[0], item[1]))
|
|
133
|
+
entries = [
|
|
134
|
+
AssetBriefingEntry(
|
|
135
|
+
asset_id=str(getattr(record, "id", "") or "").strip(),
|
|
136
|
+
rationale=_implicit_asset_rationale(record),
|
|
137
|
+
expected_use="Read this asset before executing; it supplies task requirements or constraints.",
|
|
138
|
+
)
|
|
139
|
+
for _score, _index, record in scored[:_IMPLICIT_ASSET_LIMIT]
|
|
140
|
+
if str(getattr(record, "id", "") or "").strip()
|
|
141
|
+
]
|
|
142
|
+
if not entries:
|
|
143
|
+
return None
|
|
144
|
+
return TaskAssetBriefing(primary=entries, may_need=[])
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def bind_asset_to_matching_tasks(
|
|
148
|
+
*,
|
|
149
|
+
plan: dict[str, Any],
|
|
150
|
+
record: Any,
|
|
151
|
+
active_records: Iterable[Any],
|
|
152
|
+
) -> list[str]:
|
|
153
|
+
tasks = plan.get("tasks")
|
|
154
|
+
if not isinstance(tasks, list):
|
|
155
|
+
return []
|
|
156
|
+
active = [
|
|
157
|
+
item
|
|
158
|
+
for item in active_records
|
|
159
|
+
if getattr(item, "deleted_at", None) is None and not bool(getattr(item, "pinned", False))
|
|
160
|
+
]
|
|
161
|
+
bound_task_ids: list[str] = []
|
|
162
|
+
for task in tasks:
|
|
163
|
+
if not isinstance(task, dict):
|
|
164
|
+
continue
|
|
165
|
+
if _task_references_asset(task, str(getattr(record, "id", "") or "")):
|
|
166
|
+
continue
|
|
167
|
+
try:
|
|
168
|
+
current = task_asset_briefing(task)
|
|
169
|
+
except AssetError:
|
|
170
|
+
continue
|
|
171
|
+
if current is not None and (current.primary or current.may_need):
|
|
172
|
+
continue
|
|
173
|
+
inferred = infer_implicit_task_asset_briefing(task=task, records=active)
|
|
174
|
+
if inferred is None or not any(
|
|
175
|
+
entry.asset_id == str(getattr(record, "id", "") or "").strip()
|
|
176
|
+
for entry in inferred.primary
|
|
177
|
+
):
|
|
178
|
+
continue
|
|
179
|
+
task["asset_briefing"] = serialize_task_asset_briefing(inferred)
|
|
180
|
+
task_id = str(task.get("id") or "").strip()
|
|
181
|
+
if task_id:
|
|
182
|
+
bound_task_ids.append(task_id)
|
|
183
|
+
return bound_task_ids
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def _parse_entries(payload: Any, *, field: str) -> list[AssetBriefingEntry]:
|
|
187
|
+
if payload is None:
|
|
188
|
+
return []
|
|
189
|
+
if not isinstance(payload, list):
|
|
190
|
+
raise AssetError(f"{field} must be an array")
|
|
191
|
+
out: list[AssetBriefingEntry] = []
|
|
192
|
+
for index, raw_entry in enumerate(payload):
|
|
193
|
+
entry_field = f"{field}[{index}]"
|
|
194
|
+
if not isinstance(raw_entry, dict):
|
|
195
|
+
raise AssetError(f"{entry_field} must be an object")
|
|
196
|
+
_reject_unknown_keys(
|
|
197
|
+
raw_entry,
|
|
198
|
+
allowed={"asset_id", "rationale", "expected_use"},
|
|
199
|
+
field=entry_field,
|
|
200
|
+
)
|
|
201
|
+
asset_id = _required_string(raw_entry.get("asset_id"), field=f"{entry_field}.asset_id")
|
|
202
|
+
rationale = _required_string(raw_entry.get("rationale"), field=f"{entry_field}.rationale")
|
|
203
|
+
expected_use = _required_string(
|
|
204
|
+
raw_entry.get("expected_use"),
|
|
205
|
+
field=f"{entry_field}.expected_use",
|
|
206
|
+
)
|
|
207
|
+
out.append(
|
|
208
|
+
AssetBriefingEntry(
|
|
209
|
+
asset_id=asset_id,
|
|
210
|
+
rationale=rationale,
|
|
211
|
+
expected_use=expected_use,
|
|
212
|
+
)
|
|
213
|
+
)
|
|
214
|
+
return out
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def _entry_to_dict(entry: AssetBriefingEntry) -> dict[str, str]:
|
|
218
|
+
return {
|
|
219
|
+
"asset_id": entry.asset_id,
|
|
220
|
+
"rationale": entry.rationale,
|
|
221
|
+
"expected_use": entry.expected_use,
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def _required_string(value: Any, *, field: str) -> str:
|
|
226
|
+
if not isinstance(value, str):
|
|
227
|
+
raise AssetError(f"{field} must be a string")
|
|
228
|
+
text = value.strip()
|
|
229
|
+
if not text:
|
|
230
|
+
raise AssetError(f"{field} must be non-empty")
|
|
231
|
+
return text
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def _reject_unknown_keys(payload: dict[str, Any], *, allowed: set[str], field: str) -> None:
|
|
235
|
+
unknown = sorted(set(payload) - allowed)
|
|
236
|
+
if unknown:
|
|
237
|
+
raise AssetError(f"{field} contains unsupported keys: {', '.join(unknown)}")
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def _task_text(task: dict[str, Any]) -> str:
|
|
241
|
+
parts = [
|
|
242
|
+
str(task.get("id") or ""),
|
|
243
|
+
str(task.get("title") or ""),
|
|
244
|
+
str(task.get("description") or ""),
|
|
245
|
+
]
|
|
246
|
+
acceptance = task.get("acceptance_criteria")
|
|
247
|
+
if isinstance(acceptance, list):
|
|
248
|
+
parts.extend(str(item or "") for item in acceptance)
|
|
249
|
+
scopes = [task.get("estimated_files"), task.get("write_scope")]
|
|
250
|
+
for scope in scopes:
|
|
251
|
+
if isinstance(scope, list):
|
|
252
|
+
parts.extend(str(item or "") for item in scope)
|
|
253
|
+
return "\n".join(parts)
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def _asset_match_score(
|
|
257
|
+
*,
|
|
258
|
+
task_text: str,
|
|
259
|
+
record: Any,
|
|
260
|
+
single_active_asset: bool,
|
|
261
|
+
has_asset_intent: bool,
|
|
262
|
+
has_single_asset_reference: bool,
|
|
263
|
+
) -> int:
|
|
264
|
+
folded_task = task_text.casefold()
|
|
265
|
+
asset_id = str(getattr(record, "id", "") or "").strip().casefold()
|
|
266
|
+
title = str(getattr(record, "title", "") or "").strip()
|
|
267
|
+
filename = str(getattr(record, "original_filename", "") or "").strip()
|
|
268
|
+
description = str(getattr(record, "description", "") or "").strip()
|
|
269
|
+
stored_path = str(getattr(record, "stored_path", "") or "").strip()
|
|
270
|
+
fields = [title, filename, description, stored_path]
|
|
271
|
+
score = 0
|
|
272
|
+
if asset_id and asset_id in folded_task:
|
|
273
|
+
score += 20
|
|
274
|
+
for field in fields:
|
|
275
|
+
folded = field.casefold()
|
|
276
|
+
if folded and folded in folded_task:
|
|
277
|
+
score += 8
|
|
278
|
+
for token in _asset_tokens(title):
|
|
279
|
+
if token in folded_task:
|
|
280
|
+
score += 4
|
|
281
|
+
for token in _asset_tokens(filename):
|
|
282
|
+
if token in folded_task:
|
|
283
|
+
score += 4
|
|
284
|
+
for token in _asset_tokens(description):
|
|
285
|
+
if token in folded_task:
|
|
286
|
+
score += 2
|
|
287
|
+
if has_single_asset_reference and single_active_asset:
|
|
288
|
+
score += 8
|
|
289
|
+
if has_asset_intent and score >= 4:
|
|
290
|
+
score += 2
|
|
291
|
+
return score
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def _asset_score_is_relevant(*, score: int, has_asset_intent: bool) -> bool:
|
|
295
|
+
if score >= 8:
|
|
296
|
+
return True
|
|
297
|
+
return has_asset_intent and score > 0
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def _asset_tokens(text: str) -> set[str]:
|
|
301
|
+
normalized = re.sub(r"[./\\_-]+", " ", str(text or "").casefold())
|
|
302
|
+
tokens = set()
|
|
303
|
+
for token in _WORD_RE.findall(normalized):
|
|
304
|
+
if len(token) <= 2 or token in _TOKEN_STOPWORDS:
|
|
305
|
+
continue
|
|
306
|
+
tokens.add(token)
|
|
307
|
+
return tokens
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
def _implicit_asset_rationale(record: Any) -> str:
|
|
311
|
+
title = str(getattr(record, "title", "") or "").strip()
|
|
312
|
+
if title:
|
|
313
|
+
return f'Task text references an attached or named asset matching "{title}".'
|
|
314
|
+
return "Task text references an attached or named asset matching this record."
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def _task_references_asset(task: dict[str, Any], asset_id: str) -> bool:
|
|
318
|
+
if not asset_id:
|
|
319
|
+
return False
|
|
320
|
+
try:
|
|
321
|
+
briefing = task_asset_briefing(task)
|
|
322
|
+
except AssetError:
|
|
323
|
+
return False
|
|
324
|
+
if briefing is None:
|
|
325
|
+
return False
|
|
326
|
+
return any(entry.asset_id == asset_id for entry in [*briefing.primary, *briefing.may_need])
|