activegraph 1.7.0__tar.gz → 1.7.1__tar.gz
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.
- {activegraph-1.7.0/activegraph.egg-info → activegraph-1.7.1}/PKG-INFO +1 -1
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/__init__.py +1 -1
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/sandbox/__init__.py +82 -20
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/sandbox/_child.py +79 -13
- {activegraph-1.7.0 → activegraph-1.7.1/activegraph.egg-info}/PKG-INFO +1 -1
- {activegraph-1.7.0 → activegraph-1.7.1}/pyproject.toml +1 -1
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_sandbox_trial.py +134 -4
- {activegraph-1.7.0 → activegraph-1.7.1}/LICENSE +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/NOTICE +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/README.md +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/__main__.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/_signature.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/behaviors/__init__.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/behaviors/base.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/behaviors/decorators.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/cli/__init__.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/cli/main.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/cli/quickstart.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/cli/renderers.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/core/__init__.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/core/clock.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/core/event.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/core/graph.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/core/graph_store.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/core/ids.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/core/patch.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/core/view.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/errors.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/frame.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/llm/__init__.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/llm/anthropic.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/llm/cache.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/llm/embedding.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/llm/errors.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/llm/native.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/llm/openai.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/llm/parsing.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/llm/prompt.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/llm/provider.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/llm/recorded.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/llm/types.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/llm/wire.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/observability/__init__.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/observability/logging.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/observability/metrics.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/observability/migration.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/observability/otel.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/observability/prometheus.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/observability/status.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/packs/__init__.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/packs/diligence/__init__.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/packs/diligence/behaviors.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/packs/diligence/fixtures/__init__.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/packs/diligence/fixtures/companies.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/packs/diligence/object_types.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/packs/diligence/prompts/document_researcher.md +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/packs/diligence/prompts/memo_synthesizer.md +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/packs/diligence/prompts/question_generator.md +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/packs/diligence/prompts/risk_identifier.md +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/packs/diligence/settings.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/packs/diligence/tools.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/packs/loader.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/packs/manifest.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/packs/scaffold.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/policy.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/runtime/__init__.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/runtime/_live.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/runtime/behavior_graph.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/runtime/budget.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/runtime/config_errors.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/runtime/diff.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/runtime/errors.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/runtime/exec_errors.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/runtime/patterns.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/runtime/promote.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/runtime/queue.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/runtime/registration_errors.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/runtime/registry.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/runtime/runtime.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/runtime/scheduler.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/runtime/view_builder.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/store/__init__.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/store/base.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/store/conformance.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/store/errors.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/store/falkordb.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/store/graph_conformance.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/store/memory.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/store/postgres.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/store/retention.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/store/serde.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/store/sqlite.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/store/url.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/tools/__init__.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/tools/base.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/tools/cache.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/tools/context.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/tools/decorators.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/tools/errors.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/tools/graph_query.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/tools/recorded.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/tools/web_fetch.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/trace/__init__.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/trace/causal.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph/trace/printer.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph.egg-info/SOURCES.txt +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph.egg-info/dependency_links.txt +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph.egg-info/entry_points.txt +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph.egg-info/requires.txt +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/activegraph.egg-info/top_level.txt +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/setup.cfg +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_activate_after.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_causal_cross_tool.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_cli.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_cli_docs_flags.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_clock.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_compaction.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_diff.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_diligence_pack.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_diligence_with_tools.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_disable_pack.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_doc_links.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_doc_python_snippets.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_doc_site_reachable.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_embedding_provider.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_errors_format.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_event.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_falkordb_store.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_fork.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_graph.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_graph_store.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_ids.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_license.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_llm_anthropic.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_llm_behavior.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_llm_budget.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_llm_causal.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_llm_claim_extraction.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_llm_default_model.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_llm_determinism.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_llm_failure.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_llm_native_structured_output.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_llm_openai.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_llm_prompt.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_llm_provider_fixtures.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_llm_replay.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_llm_tool_loop.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_llm_trace.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_llm_trace_snapshot.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_llm_types.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_llm_wire.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_llms_txt.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_manifest_warning_tier.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_migration.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_observability_logging.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_observability_metrics.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_operate_example.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_pack_manifest.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_pack_scaffold.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_packs.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_patch.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_pattern_matcher.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_pattern_parser.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_pattern_subscriptions.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_persistence.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_postgres_store.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_promote.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_quickstart.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_quickstart_snapshot.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_reason_codes_docs.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_registration_validation.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_replay.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_replay_trace_snapshot.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_requeue_unfired.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_resume_example.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_runtime.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_runtime_status.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_serde.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_store_conformance.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_store_url.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_tool_replay.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_tool_trace_snapshot.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_tools.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_trace.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_trace_accessors.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_tutorial_snippets.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_v1_0_1_patches.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_v1_0_3_behavior_failed_ux.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_v1_0_3_tool_multiturn.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_version_sync.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_view.py +0 -0
- {activegraph-1.7.0 → activegraph-1.7.1}/tests/test_wheel_completeness.py +0 -0
|
@@ -59,6 +59,7 @@ pack's static gates remain the pre-execution filter.
|
|
|
59
59
|
from __future__ import annotations
|
|
60
60
|
|
|
61
61
|
import json
|
|
62
|
+
import logging
|
|
62
63
|
import os
|
|
63
64
|
import subprocess
|
|
64
65
|
import sys
|
|
@@ -66,6 +67,8 @@ from dataclasses import dataclass, field
|
|
|
66
67
|
from pathlib import Path
|
|
67
68
|
from typing import Optional
|
|
68
69
|
|
|
70
|
+
_log = logging.getLogger("activegraph.sandbox")
|
|
71
|
+
|
|
69
72
|
|
|
70
73
|
#: The closed outcome set. ``crashed`` is the implementation's one
|
|
71
74
|
#: addition over the design draft: a child that dies without a
|
|
@@ -144,6 +147,12 @@ class TrialReport:
|
|
|
144
147
|
favor of the store. Richer evidence (tracebacks, diffs) is read
|
|
145
148
|
from the fork's log directly: ``Runtime.load(store, run_id=
|
|
146
149
|
report.fork_run_id)`` then ``trace.failures()`` / ``diff()``.
|
|
150
|
+
|
|
151
|
+
``warnings`` (v1.7.1) carries any resource net that DEGRADED on
|
|
152
|
+
this platform — most notably the memory cap (RLIMIT_AS) on macOS,
|
|
153
|
+
which the Darwin kernel refuses. A degraded net is announced, never
|
|
154
|
+
silently skipped: the same strings are also folded into ``detail``,
|
|
155
|
+
and the parent logs each one.
|
|
147
156
|
"""
|
|
148
157
|
|
|
149
158
|
outcome: str
|
|
@@ -152,6 +161,7 @@ class TrialReport:
|
|
|
152
161
|
behavior_failures: int
|
|
153
162
|
detail: str
|
|
154
163
|
exit_code: Optional[int]
|
|
164
|
+
warnings: tuple[str, ...] = ()
|
|
155
165
|
|
|
156
166
|
|
|
157
167
|
class SandboxStartupError(RuntimeError):
|
|
@@ -277,22 +287,52 @@ def _run_child(
|
|
|
277
287
|
return proc.returncode, stdout, stderr, True
|
|
278
288
|
|
|
279
289
|
|
|
290
|
+
#: A representative memory cap the preflight probe applies when the
|
|
291
|
+
#: caller left ``max_rss_bytes`` unset — generous enough not to cap a
|
|
292
|
+
#: just-started child into a false ``MemoryError`` on Linux (a child
|
|
293
|
+
#: after importing activegraph sits near ~40 MiB of address space),
|
|
294
|
+
#: finite enough to actually exercise the ``setrlimit(RLIMIT_AS)`` call
|
|
295
|
+
#: that Darwin rejects. The point of the probe is to trip the platform
|
|
296
|
+
#: check, not to bound anything.
|
|
297
|
+
_PREFLIGHT_PROBE_RSS = 1024 * 2**20
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def _limits_job_block(limits: TrialLimits, *, probe: bool) -> dict[str, object]:
|
|
301
|
+
"""The ``limits`` sub-dict of a child job. ``probe=True`` fills an
|
|
302
|
+
unset ``max_rss_bytes`` with :data:`_PREFLIGHT_PROBE_RSS` so
|
|
303
|
+
preflight always exercises the RLIMIT_AS path."""
|
|
304
|
+
max_rss = limits.max_rss_bytes
|
|
305
|
+
if probe and max_rss is None:
|
|
306
|
+
max_rss = _PREFLIGHT_PROBE_RSS
|
|
307
|
+
return {
|
|
308
|
+
"max_rss_bytes": max_rss,
|
|
309
|
+
"max_events": limits.max_events,
|
|
310
|
+
"max_llm_calls": limits.max_llm_calls,
|
|
311
|
+
"cpu_seconds": int(limits.wall_clock_seconds) + 5,
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
|
|
280
315
|
def _preflight_with(
|
|
281
316
|
env: dict[str, str],
|
|
282
317
|
*,
|
|
318
|
+
limits: TrialLimits = TrialLimits(),
|
|
283
319
|
python_flags: tuple[str, ...] = (),
|
|
284
320
|
timeout: float = 30.0,
|
|
285
|
-
) ->
|
|
321
|
+
) -> tuple[str, ...]:
|
|
286
322
|
"""The preflight check against a specific ``env`` (the testable
|
|
287
|
-
seam under :func:`preflight`).
|
|
288
|
-
|
|
323
|
+
seam under :func:`preflight`). Applies a representative limits block
|
|
324
|
+
so the resource-limit path is actually exercised. Returns any
|
|
325
|
+
degradation warnings (empty when every requested net applied);
|
|
326
|
+
raises :class:`SandboxStartupError` if a child cannot start and
|
|
327
|
+
report ``preflight: ok``.
|
|
289
328
|
"""
|
|
329
|
+
job = {"preflight": True, "limits": _limits_job_block(limits, probe=True)}
|
|
290
330
|
exit_code, stdout, stderr, timed_out = _run_child(
|
|
291
|
-
|
|
331
|
+
job, env=env, wall_clock=timeout, python_flags=python_flags
|
|
292
332
|
)
|
|
293
333
|
tail = _parse_report_tail(stdout)
|
|
294
334
|
if not timed_out and exit_code == 0 and tail.get("preflight") == "ok":
|
|
295
|
-
return
|
|
335
|
+
return tuple(str(w) for w in (tail.get("warnings") or ()))
|
|
296
336
|
cause = _stderr_tail(stderr) or (
|
|
297
337
|
"child timed out" if timed_out else "no preflight tail on stdout"
|
|
298
338
|
)
|
|
@@ -301,18 +341,33 @@ def _preflight_with(
|
|
|
301
341
|
)
|
|
302
342
|
|
|
303
343
|
|
|
304
|
-
def preflight(
|
|
344
|
+
def preflight(
|
|
345
|
+
*, limits: TrialLimits = TrialLimits(), timeout: float = 30.0
|
|
346
|
+
) -> tuple[str, ...]:
|
|
305
347
|
"""Verify a trial child can START under the sandbox env on this box.
|
|
306
348
|
|
|
307
|
-
Spawns the child with a null job
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
349
|
+
Spawns the child with a null job that exercises the full startup
|
|
350
|
+
path a real trial hits — importing ``activegraph`` under the sandbox
|
|
351
|
+
env AND applying resource limits (v1.7.1: a go/no-go gate that
|
|
352
|
+
skipped limit application passed on macOS where every real trial
|
|
353
|
+
then crashed on RLIMIT_AS). No fork, no store, no candidate.
|
|
354
|
+
|
|
355
|
+
Returns a tuple of degradation warnings — empty when every net
|
|
356
|
+
applied cleanly, non-empty (and logged) when a net degraded on this
|
|
357
|
+
platform (e.g. the memory cap on macOS). Raises
|
|
358
|
+
:class:`SandboxStartupError` with the child's stderr tail if a child
|
|
359
|
+
cannot start at all. So on macOS this PASSES with a memory-net
|
|
360
|
+
warning rather than pass-then-crash; on a box that cannot import
|
|
361
|
+
activegraph it RAISES with the real cause. Consumers call it once at
|
|
362
|
+
boot to fail loud or learn what degraded before the first trial.
|
|
363
|
+
|
|
364
|
+
Pass the same ``limits`` a real trial will carry to probe that exact
|
|
365
|
+
configuration; the default probes with a representative memory cap.
|
|
314
366
|
"""
|
|
315
|
-
_preflight_with(_child_env(limits), timeout=timeout)
|
|
367
|
+
warnings = _preflight_with(_child_env(limits), limits=limits, timeout=timeout)
|
|
368
|
+
for w in warnings:
|
|
369
|
+
_log.warning("sandbox preflight: %s", w)
|
|
370
|
+
return warnings
|
|
316
371
|
|
|
317
372
|
|
|
318
373
|
def run_forked_trial(
|
|
@@ -379,12 +434,7 @@ def run_forked_trial(
|
|
|
379
434
|
for p in extra_packs
|
|
380
435
|
],
|
|
381
436
|
"scenario": scenario,
|
|
382
|
-
"limits":
|
|
383
|
-
"max_rss_bytes": limits.max_rss_bytes,
|
|
384
|
-
"max_events": limits.max_events,
|
|
385
|
-
"max_llm_calls": limits.max_llm_calls,
|
|
386
|
-
"cpu_seconds": int(limits.wall_clock_seconds) + 5,
|
|
387
|
-
},
|
|
437
|
+
"limits": _limits_job_block(limits, probe=False),
|
|
388
438
|
}
|
|
389
439
|
exit_code, stdout, stderr, timed_out = _run_child(
|
|
390
440
|
job, env=_child_env(limits), wall_clock=limits.wall_clock_seconds
|
|
@@ -418,6 +468,17 @@ def run_forked_trial(
|
|
|
418
468
|
if err_tail:
|
|
419
469
|
detail = f"{detail}; child stderr:\n{err_tail}"
|
|
420
470
|
|
|
471
|
+
# Degraded resource nets (v1.7.1): announced, never silent. A memory
|
|
472
|
+
# cap the platform refused (RLIMIT_AS on macOS) is folded into detail
|
|
473
|
+
# and logged, so a trial that ran WITHOUT the memory net it asked for
|
|
474
|
+
# is loud rather than quietly unbounded.
|
|
475
|
+
warnings = tuple(str(w) for w in (tail.get("warnings") or ()))
|
|
476
|
+
if warnings:
|
|
477
|
+
joined = "; ".join(warnings)
|
|
478
|
+
detail = f"{detail} [degraded: {joined}]" if detail else f"[degraded: {joined}]"
|
|
479
|
+
for w in warnings:
|
|
480
|
+
_log.warning("sandbox trial %s: %s", fork_run_id, w)
|
|
481
|
+
|
|
421
482
|
# The store is the record: re-read the fork run for the numbers.
|
|
422
483
|
events_appended = 0
|
|
423
484
|
behavior_failures = 0
|
|
@@ -437,4 +498,5 @@ def run_forked_trial(
|
|
|
437
498
|
behavior_failures=behavior_failures,
|
|
438
499
|
detail=detail,
|
|
439
500
|
exit_code=exit_code,
|
|
501
|
+
warnings=warnings,
|
|
440
502
|
)
|
|
@@ -22,6 +22,9 @@ from pathlib import Path
|
|
|
22
22
|
from typing import Any, Callable, Optional
|
|
23
23
|
|
|
24
24
|
|
|
25
|
+
_LIMIT_WARNINGS: list[str] = []
|
|
26
|
+
|
|
27
|
+
|
|
25
28
|
def _report(
|
|
26
29
|
outcome: str,
|
|
27
30
|
*,
|
|
@@ -39,6 +42,11 @@ def _report(
|
|
|
39
42
|
"events_appended": events_appended,
|
|
40
43
|
"behavior_failures": behavior_failures,
|
|
41
44
|
"detail": detail[:500],
|
|
45
|
+
# Degraded-limit warnings (v1.7.1): a resource net that
|
|
46
|
+
# could not be applied on this platform is announced,
|
|
47
|
+
# never silently skipped. The parent folds these into
|
|
48
|
+
# TrialReport.warnings and TrialReport.detail.
|
|
49
|
+
"warnings": list(_LIMIT_WARNINGS),
|
|
42
50
|
}
|
|
43
51
|
),
|
|
44
52
|
flush=True,
|
|
@@ -46,19 +54,67 @@ def _report(
|
|
|
46
54
|
raise SystemExit(exit_code)
|
|
47
55
|
|
|
48
56
|
|
|
49
|
-
def _apply_rlimits(limits: dict[str, Any]) ->
|
|
50
|
-
"""POSIX resource caps
|
|
51
|
-
|
|
57
|
+
def _apply_rlimits(limits: dict[str, Any]) -> list[str]:
|
|
58
|
+
"""Apply POSIX resource caps portably, returning a warning for any
|
|
59
|
+
cap that could not be set on this platform.
|
|
60
|
+
|
|
61
|
+
RLIMIT_AS (the memory net) is settable on Linux but rejected by the
|
|
62
|
+
Darwin kernel (``ValueError: current limit exceeds maximum limit``
|
|
63
|
+
— Darwin does not support address-space limiting). Rather than
|
|
64
|
+
crash (a trial child that can't start is useless) or silently skip
|
|
65
|
+
(a memory net that quietly does nothing is worse than one that
|
|
66
|
+
announces it is off), an unsettable cap DEGRADES: we record a loud
|
|
67
|
+
warning and let the wall-clock kill and event budget — which are
|
|
68
|
+
unaffected — remain the active nets. We never RAISE a hard limit
|
|
69
|
+
(that needs privilege and is what triggered the Darwin crash): the
|
|
70
|
+
target is clamped to the existing hard limit, so the call only ever
|
|
71
|
+
lowers, and the strong soft==hard cap is preserved where the kernel
|
|
72
|
+
allows it. Returns the list of degradation warnings (empty when all
|
|
73
|
+
requested caps applied).
|
|
74
|
+
"""
|
|
75
|
+
warnings: list[str] = []
|
|
52
76
|
try:
|
|
53
77
|
import resource
|
|
54
78
|
except ImportError: # pragma: no cover — Windows
|
|
55
|
-
|
|
79
|
+
if limits.get("max_rss_bytes"):
|
|
80
|
+
warnings.append(_mem_off("no `resource` module on this platform"))
|
|
81
|
+
return warnings
|
|
82
|
+
|
|
83
|
+
def _cap(kind: str, name: str, requested: int) -> None:
|
|
84
|
+
limit = getattr(resource, name)
|
|
85
|
+
_, hard = resource.getrlimit(limit)
|
|
86
|
+
target = (
|
|
87
|
+
requested
|
|
88
|
+
if hard == resource.RLIM_INFINITY
|
|
89
|
+
else min(requested, hard)
|
|
90
|
+
)
|
|
91
|
+
try:
|
|
92
|
+
resource.setrlimit(limit, (target, target))
|
|
93
|
+
except (ValueError, OSError) as e:
|
|
94
|
+
warnings.append(
|
|
95
|
+
_mem_off(f"{sys.platform}: {type(e).__name__}: {e}")
|
|
96
|
+
if kind == "memory"
|
|
97
|
+
else (
|
|
98
|
+
f"CPU cap (RLIMIT_CPU) could not be applied on "
|
|
99
|
+
f"{sys.platform}: {type(e).__name__}: {e}"
|
|
100
|
+
)
|
|
101
|
+
)
|
|
102
|
+
|
|
56
103
|
max_rss = limits.get("max_rss_bytes")
|
|
57
104
|
if max_rss:
|
|
58
|
-
|
|
105
|
+
_cap("memory", "RLIMIT_AS", max_rss)
|
|
59
106
|
cpu = limits.get("cpu_seconds")
|
|
60
107
|
if cpu:
|
|
61
|
-
|
|
108
|
+
_cap("cpu", "RLIMIT_CPU", cpu)
|
|
109
|
+
return warnings
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _mem_off(reason: str) -> str:
|
|
113
|
+
return (
|
|
114
|
+
f"memory cap (RLIMIT_AS) could not be applied ({reason}); the "
|
|
115
|
+
f"memory net is OFF for this trial — the wall-clock kill and "
|
|
116
|
+
f"event budget still bound a runaway"
|
|
117
|
+
)
|
|
62
118
|
|
|
63
119
|
|
|
64
120
|
def _materialize_pack(job: dict[str, Any]) -> Any:
|
|
@@ -138,18 +194,28 @@ def _resolve_scenario(
|
|
|
138
194
|
def main() -> None:
|
|
139
195
|
job = json.loads(sys.stdin.read())
|
|
140
196
|
|
|
141
|
-
#
|
|
142
|
-
#
|
|
143
|
-
#
|
|
144
|
-
#
|
|
145
|
-
#
|
|
197
|
+
# Apply resource limits BEFORE the preflight branch (v1.7.1): the
|
|
198
|
+
# limit-application path is exactly what varies by host (Darwin
|
|
199
|
+
# rejects RLIMIT_AS), so preflight must exercise it to be a real
|
|
200
|
+
# go/no-go gate — a null job that skipped it would pass on a box
|
|
201
|
+
# where every real trial then crashed. Degradation warnings are
|
|
202
|
+
# stashed for _report and echoed on the preflight tail.
|
|
203
|
+
_LIMIT_WARNINGS.extend(_apply_rlimits(job.get("limits", {})))
|
|
204
|
+
|
|
205
|
+
# Preflight (v1.7): a null job that proves the child could START —
|
|
206
|
+
# importing activegraph under the sandbox env succeeded (before this
|
|
207
|
+
# function ran) AND resource limits could be applied (just above).
|
|
208
|
+
# Echo the marker plus any degradation warnings and exit clean. No
|
|
209
|
+
# fork, no store, no candidate touched.
|
|
146
210
|
if job.get("preflight"):
|
|
147
|
-
print(
|
|
211
|
+
print(
|
|
212
|
+
json.dumps({"preflight": "ok", "warnings": list(_LIMIT_WARNINGS)}),
|
|
213
|
+
flush=True,
|
|
214
|
+
)
|
|
148
215
|
raise SystemExit(0)
|
|
149
216
|
|
|
150
217
|
fork_run_id = str(job["fork_run_id"])
|
|
151
218
|
initial = int(job.get("initial_events", 0))
|
|
152
|
-
_apply_rlimits(job.get("limits", {}))
|
|
153
219
|
|
|
154
220
|
def counts(rt: Any) -> tuple[int, int]:
|
|
155
221
|
return (
|
|
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
|
|
|
7
7
|
|
|
8
8
|
[project]
|
|
9
9
|
name = "activegraph"
|
|
10
|
-
version = "1.7.
|
|
10
|
+
version = "1.7.1"
|
|
11
11
|
description = "An event-sourced reactive graph runtime for long-running, auditable, agentic systems."
|
|
12
12
|
readme = "README.md"
|
|
13
13
|
requires-python = ">=3.11"
|
|
@@ -540,9 +540,9 @@ def test_child_import_crash_surfaces_the_cause_in_detail(tmp_path, monkeypatch):
|
|
|
540
540
|
|
|
541
541
|
|
|
542
542
|
def test_preflight_succeeds_on_a_working_env():
|
|
543
|
-
# Returns
|
|
544
|
-
# env — the normal case on
|
|
545
|
-
assert preflight(timeout=30.0)
|
|
543
|
+
# Returns () (no raise, no degradation) when a child can start AND
|
|
544
|
+
# apply limits under the sandbox env — the normal case on Linux.
|
|
545
|
+
assert preflight(timeout=30.0) == ()
|
|
546
546
|
|
|
547
547
|
|
|
548
548
|
def test_preflight_fails_loud_with_the_cause_on_a_restricted_env():
|
|
@@ -570,7 +570,7 @@ def test_explicit_code_channel_rescues_a_restricted_child():
|
|
|
570
570
|
python_flags=("-S",),
|
|
571
571
|
timeout=30.0,
|
|
572
572
|
)
|
|
573
|
-
|
|
573
|
+
== ()
|
|
574
574
|
)
|
|
575
575
|
|
|
576
576
|
|
|
@@ -598,3 +598,133 @@ def test_env_passthrough_still_forwards_named_vars(monkeypatch):
|
|
|
598
598
|
env = sandbox._child_env(TrialLimits(env_passthrough=("MY_TRIAL_FLAG",)))
|
|
599
599
|
assert env["MY_TRIAL_FLAG"] == "1"
|
|
600
600
|
assert "PYTHONPATH" in env
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
# ------------------- portable RLIMIT_AS (v1.7.1 macOS soak fix)
|
|
604
|
+
|
|
605
|
+
resource = pytest.importorskip("resource")
|
|
606
|
+
from activegraph.sandbox import _child # noqa: E402
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
def test_rlimit_as_applies_cleanly_on_linux():
|
|
610
|
+
# Linux shape: a settable RLIMIT_AS applies with no degradation.
|
|
611
|
+
warnings = _child._apply_rlimits(
|
|
612
|
+
{"max_rss_bytes": 1024 * 2**20, "cpu_seconds": 60}
|
|
613
|
+
)
|
|
614
|
+
assert warnings == []
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
def test_rlimit_as_rejection_degrades_not_crashes(monkeypatch):
|
|
618
|
+
# macOS shape (simulated): Darwin rejects setrlimit(RLIMIT_AS) with
|
|
619
|
+
# exactly this ValueError. The child must NOT crash and must NOT
|
|
620
|
+
# silently skip — it degrades with a loud, announced warning. This
|
|
621
|
+
# is the regression guard for the macOS rotation-1 crash.
|
|
622
|
+
real = resource.setrlimit
|
|
623
|
+
|
|
624
|
+
def darwin(which, pair):
|
|
625
|
+
if which == resource.RLIMIT_AS:
|
|
626
|
+
raise ValueError("current limit exceeds maximum limit")
|
|
627
|
+
return real(which, pair)
|
|
628
|
+
|
|
629
|
+
monkeypatch.setattr(resource, "setrlimit", darwin)
|
|
630
|
+
warnings = _child._apply_rlimits(
|
|
631
|
+
{"max_rss_bytes": 256 * 2**20, "cpu_seconds": 60}
|
|
632
|
+
)
|
|
633
|
+
assert len(warnings) == 1
|
|
634
|
+
assert "memory net is OFF" in warnings[0]
|
|
635
|
+
assert "RLIMIT_AS" in warnings[0]
|
|
636
|
+
# The CPU cap (which Darwin DOES accept) still applied — only the
|
|
637
|
+
# unsupported net degraded.
|
|
638
|
+
assert "RLIMIT_CPU" not in warnings[0]
|
|
639
|
+
|
|
640
|
+
|
|
641
|
+
def test_rlimit_never_raises_the_hard_limit(monkeypatch):
|
|
642
|
+
# The Darwin crash was setrlimit raising the hard limit; we clamp to
|
|
643
|
+
# the existing hard limit so the call only ever LOWERS. Prove the
|
|
644
|
+
# target passed to setrlimit never exceeds the current hard limit.
|
|
645
|
+
seen = {}
|
|
646
|
+
real_get = resource.getrlimit
|
|
647
|
+
monkeypatch.setattr(
|
|
648
|
+
resource, "getrlimit", lambda w: (0, 512 * 2**20) # finite hard
|
|
649
|
+
)
|
|
650
|
+
|
|
651
|
+
def capture(which, pair):
|
|
652
|
+
seen[which] = pair
|
|
653
|
+
|
|
654
|
+
monkeypatch.setattr(resource, "setrlimit", capture)
|
|
655
|
+
_child._apply_rlimits({"max_rss_bytes": 4096 * 2**20}) # ask for MORE
|
|
656
|
+
soft, hard = seen[resource.RLIMIT_AS]
|
|
657
|
+
assert soft == hard == 512 * 2**20 # clamped to existing hard, not raised
|
|
658
|
+
|
|
659
|
+
|
|
660
|
+
def test_preflight_exercises_the_limit_path():
|
|
661
|
+
# Fix 2: preflight must send a limits block so it reaches
|
|
662
|
+
# _apply_rlimits — a null job that skipped it passed on macOS where
|
|
663
|
+
# every real trial then crashed.
|
|
664
|
+
probe = sandbox._limits_job_block(TrialLimits(), probe=True)
|
|
665
|
+
assert probe["max_rss_bytes"] == sandbox._PREFLIGHT_PROBE_RSS
|
|
666
|
+
# A caller's explicit cap is probed as-is.
|
|
667
|
+
probe2 = sandbox._limits_job_block(
|
|
668
|
+
TrialLimits(max_rss_bytes=333 * 2**20), probe=True
|
|
669
|
+
)
|
|
670
|
+
assert probe2["max_rss_bytes"] == 333 * 2**20
|
|
671
|
+
# A real trial's block keeps the caller's None (no probe fill).
|
|
672
|
+
real = sandbox._limits_job_block(TrialLimits(), probe=False)
|
|
673
|
+
assert real["max_rss_bytes"] is None
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
def test_trial_report_surfaces_degraded_warning(tmp_path, monkeypatch):
|
|
677
|
+
# End-to-end parent surfacing: a child that reports a degraded net
|
|
678
|
+
# must land it in TrialReport.warnings AND detail (loud), on an
|
|
679
|
+
# otherwise-completed trial.
|
|
680
|
+
path, parent_run, tip, n_parent = _parent_store(tmp_path)
|
|
681
|
+
root, bundle = _candidate_dir(tmp_path)
|
|
682
|
+
|
|
683
|
+
degraded = "memory cap (RLIMIT_AS) could not be applied (darwin: ...); the memory net is OFF for this trial"
|
|
684
|
+
|
|
685
|
+
def fake_run_child(job, *, env, wall_clock, python_flags=()):
|
|
686
|
+
tail = {
|
|
687
|
+
"outcome": "completed",
|
|
688
|
+
"fork_run_id": job["fork_run_id"],
|
|
689
|
+
"events_appended": 1,
|
|
690
|
+
"behavior_failures": 0,
|
|
691
|
+
"detail": "",
|
|
692
|
+
"warnings": [degraded],
|
|
693
|
+
}
|
|
694
|
+
import json as _json
|
|
695
|
+
|
|
696
|
+
return 0, _json.dumps(tail), "", False
|
|
697
|
+
|
|
698
|
+
monkeypatch.setattr(sandbox, "_run_child", fake_run_child)
|
|
699
|
+
report = run_forked_trial(
|
|
700
|
+
path,
|
|
701
|
+
parent_run_id=parent_run,
|
|
702
|
+
at_event=tip,
|
|
703
|
+
pack_source=PackSource(root_dir=str(root), expected_bundle_hash=bundle),
|
|
704
|
+
scenario="scenario.py",
|
|
705
|
+
limits=TrialLimits(max_rss_bytes=256 * 2**20),
|
|
706
|
+
)
|
|
707
|
+
assert report.outcome == "completed"
|
|
708
|
+
assert report.warnings == (degraded,)
|
|
709
|
+
assert "degraded" in report.detail
|
|
710
|
+
assert "memory net is OFF" in report.detail
|
|
711
|
+
|
|
712
|
+
|
|
713
|
+
def test_real_trial_with_memory_cap_completes_on_linux(tmp_path):
|
|
714
|
+
# Integration: a real trial carrying a memory cap runs clean on
|
|
715
|
+
# Linux (the net applied, no degradation) — proving the portable
|
|
716
|
+
# path did not break the platform where RLIMIT_AS works.
|
|
717
|
+
path, parent_run, tip, n_parent = _parent_store(tmp_path)
|
|
718
|
+
root, bundle = _candidate_dir(tmp_path)
|
|
719
|
+
|
|
720
|
+
report = run_forked_trial(
|
|
721
|
+
path,
|
|
722
|
+
parent_run_id=parent_run,
|
|
723
|
+
at_event=tip,
|
|
724
|
+
pack_source=PackSource(root_dir=str(root), expected_bundle_hash=bundle),
|
|
725
|
+
scenario="scenario.py",
|
|
726
|
+
limits=TrialLimits(max_rss_bytes=1024 * 2**20, wall_clock_seconds=60),
|
|
727
|
+
)
|
|
728
|
+
assert report.outcome == "completed", report.detail
|
|
729
|
+
assert report.warnings == ()
|
|
730
|
+
_parent_untouched(path, parent_run, n_parent)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{activegraph-1.7.0 → activegraph-1.7.1}/activegraph/packs/diligence/prompts/document_researcher.md
RENAMED
|
File without changes
|
{activegraph-1.7.0 → activegraph-1.7.1}/activegraph/packs/diligence/prompts/memo_synthesizer.md
RENAMED
|
File without changes
|
{activegraph-1.7.0 → activegraph-1.7.1}/activegraph/packs/diligence/prompts/question_generator.md
RENAMED
|
File without changes
|
{activegraph-1.7.0 → activegraph-1.7.1}/activegraph/packs/diligence/prompts/risk_identifier.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|