activegraph 1.5.0__tar.gz → 1.6.0__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.5.0/activegraph.egg-info → activegraph-1.6.0}/PKG-INFO +1 -1
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/__init__.py +1 -1
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/packs/loader.py +108 -0
- {activegraph-1.5.0 → activegraph-1.6.0/activegraph.egg-info}/PKG-INFO +1 -1
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph.egg-info/SOURCES.txt +1 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/pyproject.toml +1 -1
- activegraph-1.6.0/tests/test_manifest_warning_tier.py +171 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_promote.py +61 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_sandbox_trial.py +107 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/LICENSE +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/NOTICE +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/README.md +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/__main__.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/_signature.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/behaviors/__init__.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/behaviors/base.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/behaviors/decorators.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/cli/__init__.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/cli/main.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/cli/quickstart.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/cli/renderers.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/core/__init__.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/core/clock.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/core/event.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/core/graph.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/core/graph_store.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/core/ids.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/core/patch.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/core/view.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/errors.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/frame.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/llm/__init__.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/llm/anthropic.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/llm/cache.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/llm/embedding.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/llm/errors.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/llm/native.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/llm/openai.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/llm/parsing.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/llm/prompt.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/llm/provider.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/llm/recorded.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/llm/types.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/llm/wire.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/observability/__init__.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/observability/logging.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/observability/metrics.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/observability/migration.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/observability/otel.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/observability/prometheus.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/observability/status.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/packs/__init__.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/packs/diligence/__init__.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/packs/diligence/behaviors.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/packs/diligence/fixtures/__init__.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/packs/diligence/fixtures/companies.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/packs/diligence/object_types.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/packs/diligence/prompts/document_researcher.md +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/packs/diligence/prompts/memo_synthesizer.md +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/packs/diligence/prompts/question_generator.md +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/packs/diligence/prompts/risk_identifier.md +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/packs/diligence/settings.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/packs/diligence/tools.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/packs/manifest.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/packs/scaffold.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/policy.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/runtime/__init__.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/runtime/_live.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/runtime/behavior_graph.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/runtime/budget.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/runtime/config_errors.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/runtime/diff.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/runtime/errors.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/runtime/exec_errors.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/runtime/patterns.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/runtime/promote.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/runtime/queue.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/runtime/registration_errors.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/runtime/registry.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/runtime/runtime.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/runtime/scheduler.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/runtime/view_builder.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/sandbox/__init__.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/sandbox/_child.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/store/__init__.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/store/base.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/store/conformance.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/store/errors.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/store/falkordb.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/store/graph_conformance.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/store/memory.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/store/postgres.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/store/retention.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/store/serde.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/store/sqlite.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/store/url.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/tools/__init__.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/tools/base.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/tools/cache.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/tools/context.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/tools/decorators.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/tools/errors.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/tools/graph_query.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/tools/recorded.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/tools/web_fetch.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/trace/__init__.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/trace/causal.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph/trace/printer.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph.egg-info/dependency_links.txt +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph.egg-info/entry_points.txt +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph.egg-info/requires.txt +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/activegraph.egg-info/top_level.txt +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/setup.cfg +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_activate_after.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_causal_cross_tool.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_cli.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_cli_docs_flags.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_clock.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_compaction.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_diff.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_diligence_pack.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_diligence_with_tools.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_disable_pack.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_doc_links.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_doc_python_snippets.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_doc_site_reachable.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_embedding_provider.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_errors_format.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_event.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_falkordb_store.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_fork.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_graph.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_graph_store.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_ids.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_license.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_llm_anthropic.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_llm_behavior.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_llm_budget.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_llm_causal.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_llm_claim_extraction.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_llm_default_model.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_llm_determinism.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_llm_failure.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_llm_native_structured_output.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_llm_openai.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_llm_prompt.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_llm_provider_fixtures.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_llm_replay.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_llm_tool_loop.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_llm_trace.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_llm_trace_snapshot.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_llm_types.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_llm_wire.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_llms_txt.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_migration.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_observability_logging.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_observability_metrics.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_operate_example.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_pack_manifest.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_pack_scaffold.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_packs.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_patch.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_pattern_matcher.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_pattern_parser.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_pattern_subscriptions.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_persistence.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_postgres_store.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_quickstart.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_quickstart_snapshot.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_reason_codes_docs.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_registration_validation.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_replay.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_replay_trace_snapshot.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_requeue_unfired.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_resume_example.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_runtime.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_runtime_status.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_serde.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_store_conformance.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_store_url.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_tool_replay.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_tool_trace_snapshot.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_tools.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_trace.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_trace_accessors.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_tutorial_snippets.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_v1_0_1_patches.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_v1_0_3_behavior_failed_ux.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_v1_0_3_tool_multiturn.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_version_sync.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_view.py +0 -0
- {activegraph-1.5.0 → activegraph-1.6.0}/tests/test_wheel_completeness.py +0 -0
|
@@ -27,6 +27,9 @@ from __future__ import annotations
|
|
|
27
27
|
import copy
|
|
28
28
|
import inspect
|
|
29
29
|
import json
|
|
30
|
+
import logging
|
|
31
|
+
import sys
|
|
32
|
+
from pathlib import Path
|
|
30
33
|
from typing import TYPE_CHECKING, Any, Callable, Optional
|
|
31
34
|
|
|
32
35
|
from pydantic import BaseModel, ValidationError
|
|
@@ -309,9 +312,114 @@ def load_pack_into_runtime(
|
|
|
309
312
|
timestamp=rt.graph.clock.now(),
|
|
310
313
|
)
|
|
311
314
|
)
|
|
315
|
+
|
|
316
|
+
# ---- 6. manifest warning tier (CONTRACT v1.6 #1) ----------------------
|
|
317
|
+
_warn_on_manifest_violations(pack)
|
|
312
318
|
return True
|
|
313
319
|
|
|
314
320
|
|
|
321
|
+
# --------------------------------------------- manifest warning tier
|
|
322
|
+
# CONTRACT v1.6 #1: when a manifest.toml is discoverable next to the
|
|
323
|
+
# pack's defining modules, load_pack runs load_manifest +
|
|
324
|
+
# verify_surface and WARNs on violations — structured, once per pack
|
|
325
|
+
# per process, never an error before 2.0. Absent manifest: silent.
|
|
326
|
+
# Hash verification (content/bundle) stays host/CI territory: the
|
|
327
|
+
# loader never re-hashes a pack directory on the hot path.
|
|
328
|
+
|
|
329
|
+
_manifest_log = logging.getLogger("activegraph.packs.manifest")
|
|
330
|
+
|
|
331
|
+
# (pack name, pack version, manifest path) triples already validated
|
|
332
|
+
# this process — clean or not, the tier runs once per pack.
|
|
333
|
+
_manifest_checked: set[tuple[str, str, str]] = set()
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
def _locate_pack_manifest(pack: Pack) -> Optional[Path]:
|
|
337
|
+
"""Best-effort pack-root discovery: resolve the modules that define
|
|
338
|
+
the pack's components and walk up (while still inside the package)
|
|
339
|
+
looking for a sibling ``manifest.toml``. Returns None when the
|
|
340
|
+
pack has no discoverable manifest — which is not a violation.
|
|
341
|
+
"""
|
|
342
|
+
components: list[Any] = [getattr(b, "fn", None) for b in pack.behaviors]
|
|
343
|
+
components += [getattr(t, "fn", None) for t in pack.tools]
|
|
344
|
+
if pack.settings_schema is not EmptySettings:
|
|
345
|
+
components.append(pack.settings_schema)
|
|
346
|
+
components += [ot.schema for ot in pack.object_types]
|
|
347
|
+
|
|
348
|
+
seen_modules: set[str] = set()
|
|
349
|
+
for comp in components:
|
|
350
|
+
mod_name = getattr(comp, "__module__", None)
|
|
351
|
+
if not mod_name or mod_name == "__main__" or mod_name in seen_modules:
|
|
352
|
+
continue
|
|
353
|
+
seen_modules.add(mod_name)
|
|
354
|
+
mod_file = getattr(sys.modules.get(mod_name), "__file__", None)
|
|
355
|
+
if not mod_file:
|
|
356
|
+
continue
|
|
357
|
+
directory = Path(mod_file).resolve().parent
|
|
358
|
+
while True:
|
|
359
|
+
candidate = directory / "manifest.toml"
|
|
360
|
+
if candidate.is_file():
|
|
361
|
+
return candidate
|
|
362
|
+
# Stop once we step outside the package: the manifest
|
|
363
|
+
# lives at the pack root, and the pack root is a package.
|
|
364
|
+
if not (directory / "__init__.py").is_file():
|
|
365
|
+
break
|
|
366
|
+
if directory.parent == directory:
|
|
367
|
+
break
|
|
368
|
+
directory = directory.parent
|
|
369
|
+
return None
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
def _warn_on_manifest_violations(pack: Pack) -> None:
|
|
373
|
+
"""The warning tier itself. Never raises: a broken manifest (or a
|
|
374
|
+
bug in discovery) must not break ``load_pack`` before 2.0.
|
|
375
|
+
"""
|
|
376
|
+
try:
|
|
377
|
+
manifest_path = _locate_pack_manifest(pack)
|
|
378
|
+
if manifest_path is None:
|
|
379
|
+
return # no manifest: silent, per the Q2 schedule
|
|
380
|
+
key = (pack.name, pack.version, str(manifest_path))
|
|
381
|
+
if key in _manifest_checked:
|
|
382
|
+
return
|
|
383
|
+
_manifest_checked.add(key)
|
|
384
|
+
from activegraph.packs.manifest import (
|
|
385
|
+
PackManifestError,
|
|
386
|
+
load_manifest,
|
|
387
|
+
verify_surface,
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
try:
|
|
391
|
+
manifest = load_manifest(manifest_path)
|
|
392
|
+
verify_surface(manifest, pack)
|
|
393
|
+
except PackManifestError as err:
|
|
394
|
+
_manifest_log.warning(
|
|
395
|
+
"pack %s@%s: manifest.toml found at %s but validation "
|
|
396
|
+
"failed with %d violation(s). The pack still loads — "
|
|
397
|
+
"this stays a warning until activegraph 2.0. First "
|
|
398
|
+
"violation: %s",
|
|
399
|
+
pack.name,
|
|
400
|
+
pack.version,
|
|
401
|
+
manifest_path,
|
|
402
|
+
len(err.violations),
|
|
403
|
+
err.violations[0] if err.violations else "",
|
|
404
|
+
extra={
|
|
405
|
+
"pack": pack.name,
|
|
406
|
+
"pack_version": pack.version,
|
|
407
|
+
"manifest_path": str(manifest_path),
|
|
408
|
+
"violations": list(err.violations),
|
|
409
|
+
"reason": "pack.manifest_invalid",
|
|
410
|
+
},
|
|
411
|
+
)
|
|
412
|
+
except Exception:
|
|
413
|
+
# The tier is advisory; discovery/IO surprises are debug noise,
|
|
414
|
+
# not load failures.
|
|
415
|
+
_manifest_log.debug(
|
|
416
|
+
"manifest warning tier errored for pack %s@%s",
|
|
417
|
+
pack.name,
|
|
418
|
+
pack.version,
|
|
419
|
+
exc_info=True,
|
|
420
|
+
)
|
|
421
|
+
|
|
422
|
+
|
|
315
423
|
# ---------------------------------------------------------------- state
|
|
316
424
|
|
|
317
425
|
|
|
@@ -147,6 +147,7 @@ tests/test_llm_trace_snapshot.py
|
|
|
147
147
|
tests/test_llm_types.py
|
|
148
148
|
tests/test_llm_wire.py
|
|
149
149
|
tests/test_llms_txt.py
|
|
150
|
+
tests/test_manifest_warning_tier.py
|
|
150
151
|
tests/test_migration.py
|
|
151
152
|
tests/test_observability_logging.py
|
|
152
153
|
tests/test_observability_metrics.py
|
|
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
|
|
|
7
7
|
|
|
8
8
|
[project]
|
|
9
9
|
name = "activegraph"
|
|
10
|
-
version = "1.
|
|
10
|
+
version = "1.6.0"
|
|
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"
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"""Loader-side manifest validation, warning tier (CONTRACT v1.6 #1).
|
|
2
|
+
|
|
3
|
+
When a ``manifest.toml`` sits at the pack root, ``load_pack`` runs
|
|
4
|
+
``load_manifest`` + ``verify_surface`` and WARNs on violations —
|
|
5
|
+
structured, once per pack per process, never an error before 2.0.
|
|
6
|
+
Absent manifest: silent. All offline and deterministic.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import importlib.util
|
|
12
|
+
import logging
|
|
13
|
+
import sys
|
|
14
|
+
|
|
15
|
+
import pytest
|
|
16
|
+
|
|
17
|
+
from activegraph import Graph, Runtime
|
|
18
|
+
from activegraph.packs import loader as pack_loader
|
|
19
|
+
from activegraph.packs.manifest import compute_content_hash
|
|
20
|
+
|
|
21
|
+
PACK_INIT_TEMPLATE = '''
|
|
22
|
+
from activegraph.packs import Pack, behavior
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@behavior(name="greeter", on=["goal.created"])
|
|
26
|
+
def greeter(event, graph, ctx):
|
|
27
|
+
graph.add_object("greeting", {{"text": "hi"}})
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
pack = Pack(name="{name}", version="0.1.0", behaviors=(greeter,))
|
|
31
|
+
'''
|
|
32
|
+
|
|
33
|
+
MANIFEST_TEMPLATE = """
|
|
34
|
+
[pack]
|
|
35
|
+
name = "{name}"
|
|
36
|
+
version = "0.1.0"
|
|
37
|
+
description = "Warning-tier fixture."
|
|
38
|
+
license = ""
|
|
39
|
+
|
|
40
|
+
[pack.provenance]
|
|
41
|
+
authored_by = "agent"
|
|
42
|
+
generator = "test"
|
|
43
|
+
|
|
44
|
+
[pack.integrity]
|
|
45
|
+
content_hash = "{content_hash}"
|
|
46
|
+
|
|
47
|
+
[dependencies]
|
|
48
|
+
activegraph = ">=1.5,<2.0"
|
|
49
|
+
python-deps = []
|
|
50
|
+
|
|
51
|
+
[surface]
|
|
52
|
+
object_types = []
|
|
53
|
+
relation_types = []
|
|
54
|
+
behaviors = [{behaviors}]
|
|
55
|
+
tools = []
|
|
56
|
+
settings_schema = ""
|
|
57
|
+
|
|
58
|
+
[fixtures]
|
|
59
|
+
entrypoint = "fixtures/run_fixtures.py"
|
|
60
|
+
deterministic = true
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@pytest.fixture(autouse=True)
|
|
65
|
+
def _fresh_tier():
|
|
66
|
+
"""Each test exercises the tier from scratch: the once-per-process
|
|
67
|
+
dedupe set is process state, so tests reset it explicitly."""
|
|
68
|
+
pack_loader._manifest_checked.clear()
|
|
69
|
+
yield
|
|
70
|
+
pack_loader._manifest_checked.clear()
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _make_pack(tmp_path, name, *, declared_behaviors='"greeter"',
|
|
74
|
+
manifest=True, manifest_text=None):
|
|
75
|
+
"""Write a real pack package to disk, import it so its module has
|
|
76
|
+
a resolvable ``__file__``, and return the live Pack."""
|
|
77
|
+
root = tmp_path / name
|
|
78
|
+
root.mkdir()
|
|
79
|
+
(root / "__init__.py").write_text(PACK_INIT_TEMPLATE.format(name=name))
|
|
80
|
+
if manifest:
|
|
81
|
+
if manifest_text is None:
|
|
82
|
+
manifest_text = MANIFEST_TEMPLATE.format(
|
|
83
|
+
name=name,
|
|
84
|
+
content_hash=compute_content_hash(root),
|
|
85
|
+
behaviors=declared_behaviors,
|
|
86
|
+
)
|
|
87
|
+
(root / "manifest.toml").write_text(manifest_text)
|
|
88
|
+
spec = importlib.util.spec_from_file_location(
|
|
89
|
+
name, root / "__init__.py", submodule_search_locations=[str(root)]
|
|
90
|
+
)
|
|
91
|
+
module = importlib.util.module_from_spec(spec)
|
|
92
|
+
sys.modules[name] = module
|
|
93
|
+
try:
|
|
94
|
+
spec.loader.exec_module(module)
|
|
95
|
+
except BaseException:
|
|
96
|
+
del sys.modules[name]
|
|
97
|
+
raise
|
|
98
|
+
return module.pack
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _tier_records(caplog):
|
|
102
|
+
return [
|
|
103
|
+
r
|
|
104
|
+
for r in caplog.records
|
|
105
|
+
if r.name == "activegraph.packs.manifest"
|
|
106
|
+
and r.levelno >= logging.WARNING
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def test_matching_manifest_loads_silently(tmp_path, caplog):
|
|
111
|
+
pack = _make_pack(tmp_path, "warn_tier_clean")
|
|
112
|
+
with caplog.at_level(logging.WARNING, logger="activegraph.packs.manifest"):
|
|
113
|
+
rt = Runtime(Graph(), behaviors=[])
|
|
114
|
+
assert rt.load_pack(pack) is True
|
|
115
|
+
assert _tier_records(caplog) == []
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def test_absent_manifest_stays_silent(tmp_path, caplog):
|
|
119
|
+
pack = _make_pack(tmp_path, "warn_tier_bare", manifest=False)
|
|
120
|
+
with caplog.at_level(logging.WARNING, logger="activegraph.packs.manifest"):
|
|
121
|
+
rt = Runtime(Graph(), behaviors=[])
|
|
122
|
+
assert rt.load_pack(pack) is True
|
|
123
|
+
assert _tier_records(caplog) == []
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def test_surface_mismatch_warns_once_structured_and_still_loads(
|
|
127
|
+
tmp_path, caplog
|
|
128
|
+
):
|
|
129
|
+
# The manifest declares a behavior the Pack never registers: a
|
|
130
|
+
# real violation. The pack STILL loads — warning tier only.
|
|
131
|
+
pack = _make_pack(
|
|
132
|
+
tmp_path, "warn_tier_drift", declared_behaviors='"greeter", "ghost"'
|
|
133
|
+
)
|
|
134
|
+
with caplog.at_level(logging.WARNING, logger="activegraph.packs.manifest"):
|
|
135
|
+
rt = Runtime(Graph(), behaviors=[])
|
|
136
|
+
assert rt.load_pack(pack) is True
|
|
137
|
+
# Loaded despite the violation: the behavior dispatches.
|
|
138
|
+
rt.run_goal("check")
|
|
139
|
+
assert [
|
|
140
|
+
o for o in rt.graph.all_objects() if o.type == "greeting"
|
|
141
|
+
]
|
|
142
|
+
# A second runtime loading the same pack does not re-warn:
|
|
143
|
+
# once per pack per process.
|
|
144
|
+
rt2 = Runtime(Graph(), behaviors=[])
|
|
145
|
+
assert rt2.load_pack(pack) is True
|
|
146
|
+
|
|
147
|
+
records = _tier_records(caplog)
|
|
148
|
+
assert len(records) == 1
|
|
149
|
+
(record,) = records
|
|
150
|
+
# Structured: the record carries the machine-readable fields.
|
|
151
|
+
assert record.pack == "warn_tier_drift"
|
|
152
|
+
assert record.pack_version == "0.1.0"
|
|
153
|
+
assert record.reason == "pack.manifest_invalid"
|
|
154
|
+
assert record.manifest_path.endswith("manifest.toml")
|
|
155
|
+
assert any("ghost" in v for v in record.violations)
|
|
156
|
+
# And the human line says the pack still loads.
|
|
157
|
+
assert "still loads" in record.getMessage()
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def test_malformed_manifest_warns_never_raises(tmp_path, caplog):
|
|
161
|
+
pack = _make_pack(
|
|
162
|
+
tmp_path,
|
|
163
|
+
"warn_tier_garbage",
|
|
164
|
+
manifest_text="this is not toml [[[",
|
|
165
|
+
)
|
|
166
|
+
with caplog.at_level(logging.WARNING, logger="activegraph.packs.manifest"):
|
|
167
|
+
rt = Runtime(Graph(), behaviors=[])
|
|
168
|
+
assert rt.load_pack(pack) is True # never an error before 2.0
|
|
169
|
+
records = _tier_records(caplog)
|
|
170
|
+
assert len(records) == 1
|
|
171
|
+
assert records[0].violations # the parse failure, verbatim
|
|
@@ -819,3 +819,64 @@ def test_promote_of_unknown_types_passes_untyped(tmp_path):
|
|
|
819
819
|
n = fork.graph.add_object("freeform", {"anything": ["goes", 1]})
|
|
820
820
|
parent.promote(fork)
|
|
821
821
|
assert parent.graph.get_object(n.id).data == {"anything": ["goes", 1]}
|
|
822
|
+
|
|
823
|
+
|
|
824
|
+
# --------------------------- fork-tail removals are ordinary events
|
|
825
|
+
# The downstream residue policy (evolution pack): before promoting, a
|
|
826
|
+
# fork removes every fork-created object/relation it scaffolded so
|
|
827
|
+
# those entities read base-None/fork-None and vanish from the delta,
|
|
828
|
+
# while patches to shared state still promote. Promote must never
|
|
829
|
+
# special-case fork-tail removals — they are ordinary events
|
|
830
|
+
# (CONTRACT v1.3 #4 addendum 4d). This test is the pin.
|
|
831
|
+
|
|
832
|
+
|
|
833
|
+
def test_residue_policy_fork_tail_removal_of_fork_created_entities(tmp_path):
|
|
834
|
+
parent = _parent(tmp_path)
|
|
835
|
+
task = _task_id(parent)
|
|
836
|
+
fork = _fork_at_tip(parent)
|
|
837
|
+
|
|
838
|
+
# The fork does real work on shared state...
|
|
839
|
+
fork.graph.patch_object(task, {"status": "done"})
|
|
840
|
+
|
|
841
|
+
# ...and scaffolds trial residue: two fork-created objects, a
|
|
842
|
+
# relation between them, and a relation into shared state.
|
|
843
|
+
a = fork.graph.add_object("scaffold", {"n": 1})
|
|
844
|
+
b = fork.graph.add_object("scaffold", {"n": 2})
|
|
845
|
+
rel_ab = fork.graph.add_relation(a.id, b.id, "supports")
|
|
846
|
+
rel_task = fork.graph.add_relation(task, a.id, "tried")
|
|
847
|
+
|
|
848
|
+
# Fork tail: remove the residue with ordinary events — one
|
|
849
|
+
# explicit relation removal, then object removals whose cascade
|
|
850
|
+
# sweeps the relation into shared state.
|
|
851
|
+
fork.graph.remove_relation(rel_ab.id)
|
|
852
|
+
fork.graph.remove_object(a.id) # cascade removes rel_task too
|
|
853
|
+
fork.graph.remove_object(b.id)
|
|
854
|
+
assert fork.graph.get_relation(rel_task.id) is None
|
|
855
|
+
|
|
856
|
+
# The residue reads base-None/fork-None: not part of the delta.
|
|
857
|
+
plan = parent.promote(fork, dry_run=True)
|
|
858
|
+
assert plan.is_promotable
|
|
859
|
+
assert plan.object_creates == []
|
|
860
|
+
assert plan.relation_creates == []
|
|
861
|
+
assert plan.object_removes == []
|
|
862
|
+
assert plan.relation_removes == []
|
|
863
|
+
# The shared-state patch is the WHOLE delta, and it survives.
|
|
864
|
+
assert [o["id"] for o in plan.object_patches] == [task]
|
|
865
|
+
|
|
866
|
+
result = parent.promote(fork)
|
|
867
|
+
assert parent.graph.get_object(task).data["status"] == "done"
|
|
868
|
+
for residue_id in (a.id, b.id):
|
|
869
|
+
assert parent.graph.get_object(residue_id) is None
|
|
870
|
+
for residue_rel in (rel_ab.id, rel_task.id):
|
|
871
|
+
assert parent.graph.get_relation(residue_rel) is None
|
|
872
|
+
# And no removal events were manufactured for entities the parent
|
|
873
|
+
# never had: the promote block carries only the task patch.
|
|
874
|
+
marker = next(
|
|
875
|
+
e for e in parent.trace.events() if e.type == "promote.applied"
|
|
876
|
+
)
|
|
877
|
+
assert marker.payload["objects_patched"] == [task]
|
|
878
|
+
assert marker.payload["objects_created"] == []
|
|
879
|
+
assert marker.payload["objects_removed"] == []
|
|
880
|
+
assert marker.payload["relations_created"] == []
|
|
881
|
+
assert marker.payload["relations_removed"] == []
|
|
882
|
+
assert result.plan.is_promotable
|
|
@@ -258,3 +258,110 @@ pack = Pack(
|
|
|
258
258
|
assert report.outcome == "materialization_failed"
|
|
259
259
|
assert "undeclared" in report.detail
|
|
260
260
|
_parent_untouched(path, parent_run, n_parent)
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
REPLAY_PACK_INIT = '''
|
|
264
|
+
from activegraph.packs import Pack, behavior
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
@behavior(name="responder", on=["chat.message"])
|
|
268
|
+
def responder(event, graph, ctx):
|
|
269
|
+
graph.add_object(
|
|
270
|
+
"reply", {"to": event.payload.get("text", ""), "text": "ack"}
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
pack = Pack(name="trial_candidate", version="0.1.0", behaviors=(responder,))
|
|
275
|
+
'''
|
|
276
|
+
|
|
277
|
+
REPLAY_MANIFEST = MANIFEST_TEMPLATE.replace(
|
|
278
|
+
'behaviors = ["greeter"]', 'behaviors = ["responder"]'
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
REPLAY_SCENARIO = '''
|
|
282
|
+
from activegraph.core.event import Event
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def main(rt):
|
|
286
|
+
# The recorded input segment IS the fork's history: read it back
|
|
287
|
+
# and re-inject each input as a fresh event so the candidate's
|
|
288
|
+
# behaviors process it live inside the trial.
|
|
289
|
+
segment = [e for e in rt.trace.events() if e.type == "chat.message"]
|
|
290
|
+
for recorded in segment:
|
|
291
|
+
rt.graph.emit(
|
|
292
|
+
Event(
|
|
293
|
+
id=rt.graph.ids.event(),
|
|
294
|
+
type="chat.message",
|
|
295
|
+
payload=dict(recorded.payload),
|
|
296
|
+
actor="trial.replay",
|
|
297
|
+
frame_id=None,
|
|
298
|
+
caused_by=None,
|
|
299
|
+
timestamp=rt.graph.clock.now(),
|
|
300
|
+
)
|
|
301
|
+
)
|
|
302
|
+
rt.run_until_idle()
|
|
303
|
+
'''
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def test_recorded_segment_replay_inside_the_trial(tmp_path):
|
|
307
|
+
# THE consumer use case (evolution stage 3): fork a run, replay a
|
|
308
|
+
# recorded input segment against the fork inside the child, read
|
|
309
|
+
# failures + counts from the fork's run in the store afterward.
|
|
310
|
+
from activegraph.core.event import Event
|
|
311
|
+
|
|
312
|
+
clear_registry()
|
|
313
|
+
rt = Runtime(Graph())
|
|
314
|
+
# The parent's recorded inputs: three chat messages, no subscriber
|
|
315
|
+
# in the parent (they are raw recorded history).
|
|
316
|
+
for text in ("hello", "what's on today?", "thanks"):
|
|
317
|
+
rt.graph.emit(
|
|
318
|
+
Event(
|
|
319
|
+
id=rt.graph.ids.event(),
|
|
320
|
+
type="chat.message",
|
|
321
|
+
payload={"text": text},
|
|
322
|
+
actor="user",
|
|
323
|
+
frame_id=None,
|
|
324
|
+
caused_by=None,
|
|
325
|
+
timestamp=rt.graph.clock.now(),
|
|
326
|
+
)
|
|
327
|
+
)
|
|
328
|
+
rt.run_until_idle()
|
|
329
|
+
path = str(tmp_path / "run.db")
|
|
330
|
+
rt.save_state(path)
|
|
331
|
+
parent_run, tip, n_parent = (
|
|
332
|
+
rt.run_id,
|
|
333
|
+
rt.trace.events()[-1].id,
|
|
334
|
+
len(rt.graph.events),
|
|
335
|
+
)
|
|
336
|
+
del rt
|
|
337
|
+
|
|
338
|
+
root = tmp_path / "trial_candidate"
|
|
339
|
+
root.mkdir()
|
|
340
|
+
(root / "__init__.py").write_text(REPLAY_PACK_INIT)
|
|
341
|
+
(root / "scenario.py").write_text(REPLAY_SCENARIO)
|
|
342
|
+
content = compute_content_hash(root)
|
|
343
|
+
(root / "manifest.toml").write_text(
|
|
344
|
+
REPLAY_MANIFEST.format(content_hash=content)
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
report = run_forked_trial(
|
|
348
|
+
path,
|
|
349
|
+
parent_run_id=parent_run,
|
|
350
|
+
at_event=tip,
|
|
351
|
+
pack_source=PackSource(
|
|
352
|
+
root_dir=str(root),
|
|
353
|
+
expected_bundle_hash=compute_bundle_hash(root),
|
|
354
|
+
),
|
|
355
|
+
scenario="scenario.py",
|
|
356
|
+
)
|
|
357
|
+
assert report.outcome == "completed", report.detail
|
|
358
|
+
assert report.behavior_failures == 0
|
|
359
|
+
|
|
360
|
+
# The candidate processed exactly the recorded segment, in order,
|
|
361
|
+
# inside the fork — and the evidence is ordinary fork history.
|
|
362
|
+
fork = Runtime.load(path, run_id=report.fork_run_id, behaviors=[])
|
|
363
|
+
replies = [
|
|
364
|
+
o.data["to"] for o in fork.graph.all_objects() if o.type == "reply"
|
|
365
|
+
]
|
|
366
|
+
assert replies == ["hello", "what's on today?", "thanks"]
|
|
367
|
+
_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.5.0 → activegraph-1.6.0}/activegraph/packs/diligence/prompts/document_researcher.md
RENAMED
|
File without changes
|
{activegraph-1.5.0 → activegraph-1.6.0}/activegraph/packs/diligence/prompts/memo_synthesizer.md
RENAMED
|
File without changes
|
{activegraph-1.5.0 → activegraph-1.6.0}/activegraph/packs/diligence/prompts/question_generator.md
RENAMED
|
File without changes
|
{activegraph-1.5.0 → activegraph-1.6.0}/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
|