@heretek-ai/epistemic-swarm 0.7.24 → 1.0.2
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.
- package/index.ts +1 -0
- package/package.json +63 -139
- package/rpc.ts +1 -0
- package/server.ts +1 -0
- package/src/agents.ts +69 -0
- package/src/continue.ts +40 -0
- package/src/hooks.ts +283 -0
- package/src/panels.tsx +220 -0
- package/src/policy.ts +221 -0
- package/src/pr.ts +37 -0
- package/src/research.ts +63 -0
- package/src/rpc-def.ts +136 -0
- package/src/rpc.ts +331 -0
- package/src/runtime.ts +112 -0
- package/src/server.ts +311 -0
- package/src/session.ts +61 -0
- package/src/tools.ts +61 -0
- package/src/tui.tsx +206 -0
- package/tui.tsx +1 -0
- package/.agents/skills/brainstorming/SKILL.md +0 -19
- package/.agents/skills/code_audit/SKILL.md +0 -19
- package/.agents/skills/darkharvest/SKILL.md +0 -19
- package/.agents/skills/epistemic_search/SKILL.md +0 -19
- package/.agents/skills/factory/SKILL.md +0 -19
- package/.agents/skills/grilling/SKILL.md +0 -19
- package/.agents/skills/oss_scout/SKILL.md +0 -19
- package/.agents/skills/research_cache/SKILL.md +0 -19
- package/.agents/skills/swarm_config/SKILL.md +0 -19
- package/.claude-plugin/marketplace.json +0 -61
- package/.claude-plugin/plugin.json +0 -76
- package/.omp/README.md +0 -39
- package/.omp/SYSTEM.md +0 -17
- package/.omp/commands/audit.md +0 -10
- package/.omp/commands/brainstorming.md +0 -12
- package/.omp/commands/darkharvest.md +0 -11
- package/.omp/commands/domainexpansion.md +0 -9
- package/.omp/commands/factory.md +0 -9
- package/.omp/commands/grill.md +0 -9
- package/.omp/commands/scout.md +0 -10
- package/.omp/commands/swarm-config.md +0 -10
- package/.omp/commands/swarm.md +0 -9
- package/.omp/hooks/post/epistemic-audit.ts +0 -16
- package/.omp/hooks/pre/epistemic-redirect.ts +0 -21
- package/.omp/prompts/brainstorming.md +0 -8
- package/.omp/prompts/swarm.md +0 -8
- package/LICENSE +0 -126
- package/MARKETPLACE.md +0 -130
- package/README.md +0 -403
- package/bin/cli.js +0 -297
- package/config/claude-settings-patch.json +0 -10
- package/config/docker-compose.infra.yml +0 -23
- package/config/domain_packs/biopharma.json +0 -23
- package/config/domain_packs/legal.json +0 -19
- package/config/domain_packs/quant.json +0 -19
- package/config/mcp-research-servers.json +0 -33
- package/config/mcp_launcher.py +0 -153
- package/config/opencode-snippet.json +0 -156
- package/config/searxng_mcp.py +0 -92
- package/extensions/pi/index.js +0 -357
- package/hooks/hooks.json +0 -45
- package/install.sh +0 -473
- package/plugins/antigravity/README.md +0 -72
- package/plugins/antigravity/agents/alpha-thesis.md +0 -36
- package/plugins/antigravity/agents/beta-antithesis.md +0 -35
- package/plugins/antigravity/agents/brainstormer.md +0 -27
- package/plugins/antigravity/agents/code-auditor.md +0 -28
- package/plugins/antigravity/agents/darkharvester.md +0 -30
- package/plugins/antigravity/agents/epistemic-auditor.md +0 -28
- package/plugins/antigravity/agents/manager.md +0 -26
- package/plugins/antigravity/agents/oss-scout.md +0 -27
- package/plugins/antigravity/agents/programmer.md +0 -25
- package/plugins/antigravity/agents/qa-a.md +0 -22
- package/plugins/antigravity/agents/qa-b.md +0 -22
- package/plugins/antigravity/antigravity_hooks.py +0 -265
- package/plugins/antigravity/commands/audit.md +0 -11
- package/plugins/antigravity/commands/brainstorm.md +0 -9
- package/plugins/antigravity/commands/brainstorming.md +0 -10
- package/plugins/antigravity/commands/darkharvest.md +0 -12
- package/plugins/antigravity/commands/domainexpansion.md +0 -12
- package/plugins/antigravity/commands/factory.md +0 -14
- package/plugins/antigravity/commands/grill.md +0 -10
- package/plugins/antigravity/commands/scout.md +0 -11
- package/plugins/antigravity/commands/swarm-config.md +0 -9
- package/plugins/antigravity/commands/swarm.md +0 -12
- package/plugins/antigravity/hook_bus_bridge.js +0 -352
- package/plugins/antigravity/hooks.json +0 -44
- package/plugins/antigravity/mcp_config.json +0 -33
- package/plugins/antigravity/mcp_launcher.py +0 -58
- package/plugins/antigravity/plugin.json +0 -13
- package/plugins/antigravity/rules/AGENTS.md +0 -127
- package/plugins/antigravity/rules/epistemic-integrity.md +0 -16
- package/plugins/antigravity/skills/brainstorming/SKILL.md +0 -19
- package/plugins/antigravity/skills/code_audit/SKILL.md +0 -19
- package/plugins/antigravity/skills/darkharvest/SKILL.md +0 -19
- package/plugins/antigravity/skills/epistemic_search/SKILL.md +0 -19
- package/plugins/antigravity/skills/factory/SKILL.md +0 -19
- package/plugins/antigravity/skills/grilling/SKILL.md +0 -19
- package/plugins/antigravity/skills/oss_scout/SKILL.md +0 -19
- package/plugins/antigravity/skills/research_cache/SKILL.md +0 -19
- package/plugins/antigravity/skills/swarm_config/SKILL.md +0 -19
- package/plugins/codex/AGENTS.md.snippet +0 -10
- package/plugins/codex/README.md +0 -37
- package/plugins/codex/config.toml.snippet +0 -28
- package/plugins/codex/openai.yaml +0 -24
- package/plugins/codex/skills/brainstorming/SKILL.md +0 -19
- package/plugins/codex/skills/code_audit/SKILL.md +0 -19
- package/plugins/codex/skills/darkharvest/SKILL.md +0 -19
- package/plugins/codex/skills/epistemic_search/SKILL.md +0 -19
- package/plugins/codex/skills/factory/SKILL.md +0 -19
- package/plugins/codex/skills/grilling/SKILL.md +0 -19
- package/plugins/codex/skills/oss_scout/SKILL.md +0 -19
- package/plugins/codex/skills/research_cache/SKILL.md +0 -19
- package/plugins/codex/skills/swarm_config/SKILL.md +0 -19
- package/plugins/darkharvest/.claude-plugin/plugin.json +0 -15
- package/plugins/darkharvest/agents/harvest-proponent.md +0 -22
- package/plugins/darkharvest/agents/harvest-redteam.md +0 -20
- package/plugins/darkharvest/evals/teardown-verdict/graders/license-line.md +0 -6
- package/plugins/darkharvest/evals/teardown-verdict/graders/skill-fired.md +0 -5
- package/plugins/darkharvest/evals/teardown-verdict/prompt.md +0 -6
- package/plugins/darkharvest/skills/darkharvest/SKILL.md +0 -70
- package/plugins/darkharvest/skills/darkharvest/scripts/harvest.py +0 -289
- package/plugins/factory/.claude-plugin/plugin.json +0 -15
- package/plugins/factory/agents/factory-manager.md +0 -22
- package/plugins/factory/agents/programmer.md +0 -16
- package/plugins/factory/agents/qa-adversarial.md +0 -17
- package/plugins/factory/agents/qa-functional.md +0 -17
- package/plugins/factory/evals/gate-halt/graders/gates-first.md +0 -6
- package/plugins/factory/evals/gate-halt/graders/skill-fired.md +0 -5
- package/plugins/factory/evals/gate-halt/prompt.md +0 -6
- package/plugins/factory/skills/factory/SKILL.md +0 -61
- package/plugins/factory/skills/factory/scripts/factory.py +0 -300
- package/plugins/gemini/GEMINI.md +0 -16
- package/plugins/gemini/README.md +0 -20
- package/plugins/gemini/commands/audit.toml +0 -6
- package/plugins/gemini/commands/brainstorming.toml +0 -10
- package/plugins/gemini/commands/darkharvest.toml +0 -8
- package/plugins/gemini/commands/domainexpansion.toml +0 -7
- package/plugins/gemini/commands/factory.toml +0 -8
- package/plugins/gemini/commands/grill.toml +0 -6
- package/plugins/gemini/commands/scout.toml +0 -7
- package/plugins/gemini/commands/swarm-config.toml +0 -7
- package/plugins/gemini/commands/swarm.toml +0 -8
- package/plugins/gemini/gemini-extension.json +0 -38
- package/plugins/gemini/hooks/hooks.json +0 -11
- package/plugins/gemini/skills/brainstorming/SKILL.md +0 -19
- package/plugins/gemini/skills/code_audit/SKILL.md +0 -19
- package/plugins/gemini/skills/darkharvest/SKILL.md +0 -19
- package/plugins/gemini/skills/epistemic_search/SKILL.md +0 -19
- package/plugins/gemini/skills/factory/SKILL.md +0 -19
- package/plugins/gemini/skills/grilling/SKILL.md +0 -19
- package/plugins/gemini/skills/oss_scout/SKILL.md +0 -19
- package/plugins/gemini/skills/research_cache/SKILL.md +0 -19
- package/plugins/gemini/skills/swarm_config/SKILL.md +0 -19
- package/plugins/opencode/analysis-bridge.js +0 -620
- package/plugins/opencode/config-io.js +0 -1651
- package/plugins/opencode/dep-health.js +0 -1039
- package/plugins/opencode/hook-bus.js +0 -496
- package/plugins/opencode/index.js +0 -2992
- package/plugins/opencode/tui.js +0 -1551
- package/plugins/opencode/weight-baseline.json +0 -16
- package/plugins/opencode/weight-signals.js +0 -769
- package/plugins/research-cache/.claude-plugin/plugin.json +0 -15
- package/plugins/research-cache/skills/research_cache/SKILL.md +0 -36
- package/plugins/research-cache/skills/research_cache/__init__.py +0 -0
- package/plugins/research-cache/skills/research_cache/hasher.py +0 -302
- package/plugins/socratic-grilling/.claude-plugin/plugin.json +0 -15
- package/plugins/socratic-grilling/skills/grilling/SKILL.md +0 -61
- package/plugins/socratic-grilling/skills/grilling/__init__.py +0 -0
- package/plugins/socratic-grilling/skills/grilling/socratic_tree.py +0 -363
- package/prompts/agent_alpha_thesis.md +0 -70
- package/prompts/agent_beta_antithesis.md +0 -78
- package/prompts/agent_brainstormer.md +0 -143
- package/prompts/agent_code_auditor.md +0 -88
- package/prompts/agent_darkharvest.md +0 -140
- package/prompts/agent_oss_scout.md +0 -78
- package/prompts/antigravity_repo_factcheck.md +0 -143
- package/prompts/base_epistemic_system.md +0 -50
- package/prompts/epistemic_auditor.md +0 -74
- package/prompts/orchestrator.md +0 -70
- package/runner/__init__.py +0 -0
- package/runner/__pycache__/__init__.cpython-311.pyc +0 -0
- package/runner/__pycache__/auctioneer.cpython-311.pyc +0 -0
- package/runner/__pycache__/auditor_engine.cpython-311.pyc +0 -0
- package/runner/__pycache__/claim_store.cpython-311.pyc +0 -0
- package/runner/__pycache__/claim_witness.cpython-311.pyc +0 -0
- package/runner/__pycache__/darkharvest_claims.cpython-311.pyc +0 -0
- package/runner/__pycache__/errors.cpython-311.pyc +0 -0
- package/runner/__pycache__/living_dossiers.cpython-311.pyc +0 -0
- package/runner/__pycache__/mcp_protocol.cpython-311.pyc +0 -0
- package/runner/__pycache__/mcp_server.cpython-311.pyc +0 -0
- package/runner/__pycache__/path_safety.cpython-311.pyc +0 -0
- package/runner/__pycache__/pcrb.cpython-311.pyc +0 -0
- package/runner/__pycache__/pcrb_verify.cpython-311.pyc +0 -0
- package/runner/__pycache__/preflight.cpython-311.pyc +0 -0
- package/runner/__pycache__/refinement.cpython-311.pyc +0 -0
- package/runner/__pycache__/research_swarm.cpython-311.pyc +0 -0
- package/runner/__pycache__/retrieval_log.cpython-311.pyc +0 -0
- package/runner/__pycache__/schema_validate.cpython-311.pyc +0 -0
- package/runner/__pycache__/schemas.cpython-311.pyc +0 -0
- package/runner/__pycache__/state_machine.cpython-311.pyc +0 -0
- package/runner/antigravity_hooks.py +0 -265
- package/runner/auctioneer.py +0 -169
- package/runner/auditor_engine.py +0 -711
- package/runner/claim_store.py +0 -417
- package/runner/claim_witness.py +0 -412
- package/runner/darkharvest_claims.py +0 -358
- package/runner/errors.py +0 -51
- package/runner/living_dossiers.py +0 -395
- package/runner/mcp_protocol.py +0 -188
- package/runner/mcp_server.py +0 -1447
- package/runner/path_safety.py +0 -62
- package/runner/pcrb.py +0 -290
- package/runner/pcrb_verify.py +0 -267
- package/runner/preflight.py +0 -1011
- package/runner/refinement.py +0 -580
- package/runner/research_swarm.py +0 -1848
- package/runner/retrieval_log.py +0 -90
- package/runner/schema_validate.py +0 -193
- package/runner/schemas.py +0 -630
- package/runner/state_machine.py +0 -463
- package/runner/tests/__pycache__/test_analysis_bridge.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_antigravity_plugin.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_auction_order.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_backends.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_bet1_spike.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_claim_store.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_claim_witness.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_claude_plugin.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_config_schema.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_contract_tooling.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_darkharvest_audit.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_dep_health.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_domain_packs.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_dossier_contract.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_factory.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_fleet_seam.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_frontier_concurrency.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_frontier_mirror_standalone.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_grounding.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_hardening_contract.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_hook_bus.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_living_dossiers.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_manifest_concurrency.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_mcp_server.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_nk_hardening.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_opencode_ux.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_opencode_v2_registrars.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_pcrb.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_phase08_waiver_reopens.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_refinement.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_search_anomaly.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_search_provider.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_search_provider_plugin.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_swarm.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_swarm_config.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_sweep_regressions.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_webcache.cpython-311.pyc +0 -0
- package/runner/tests/__pycache__/test_weight_signals.cpython-311.pyc +0 -0
- package/runner/tests/fixtures/auction_objective.json +0 -35
- package/runner/tests/fixtures/borderline_claims.json +0 -27
- package/runner/tests/fixtures/config_validation_cases.json +0 -276
- package/runner/tests/fixtures/ddg_anomaly_page.html +0 -176
- package/runner/tests/fixtures/ddg_results_page.html +0 -28
- package/runner/tests/fixtures/divergence_objectives.json +0 -31
- package/runner/tests/test_analysis_bridge.py +0 -450
- package/runner/tests/test_antigravity_plugin.py +0 -361
- package/runner/tests/test_auction_order.py +0 -173
- package/runner/tests/test_backends.py +0 -457
- package/runner/tests/test_bet1_spike.py +0 -95
- package/runner/tests/test_claim_store.py +0 -162
- package/runner/tests/test_claim_witness.py +0 -186
- package/runner/tests/test_claude_plugin.py +0 -170
- package/runner/tests/test_config_schema.py +0 -879
- package/runner/tests/test_contract_tooling.py +0 -312
- package/runner/tests/test_darkharvest_audit.py +0 -395
- package/runner/tests/test_dep_health.py +0 -595
- package/runner/tests/test_domain_packs.py +0 -217
- package/runner/tests/test_dossier_contract.py +0 -196
- package/runner/tests/test_factory.py +0 -258
- package/runner/tests/test_fleet_seam.py +0 -113
- package/runner/tests/test_frontier_concurrency.py +0 -288
- package/runner/tests/test_frontier_mirror_standalone.py +0 -156
- package/runner/tests/test_grounding.py +0 -183
- package/runner/tests/test_hardening_contract.py +0 -391
- package/runner/tests/test_hook_bus.py +0 -956
- package/runner/tests/test_living_dossiers.py +0 -204
- package/runner/tests/test_manifest_concurrency.py +0 -187
- package/runner/tests/test_mcp_server.py +0 -257
- package/runner/tests/test_nk_hardening.py +0 -1046
- package/runner/tests/test_opencode_ux.py +0 -2438
- package/runner/tests/test_opencode_v2_registrars.py +0 -2157
- package/runner/tests/test_pcrb.py +0 -240
- package/runner/tests/test_phase08_waiver_reopens.py +0 -539
- package/runner/tests/test_refinement.py +0 -255
- package/runner/tests/test_search_anomaly.py +0 -342
- package/runner/tests/test_search_provider.py +0 -1534
- package/runner/tests/test_search_provider_plugin.py +0 -401
- package/runner/tests/test_swarm.py +0 -444
- package/runner/tests/test_swarm_config.py +0 -520
- package/runner/tests/test_sweep_regressions.py +0 -453
- package/runner/tests/test_webcache.py +0 -271
- package/runner/tests/test_weight_signals.py +0 -401
- package/schemas/alpha_dossier.schema.json +0 -204
- package/schemas/audit_report.schema.json +0 -79
- package/schemas/beta_dossier.schema.json +0 -214
- package/schemas/config.schema.json +0 -311
- package/schemas/frontier.schema.json +0 -61
- package/schemas/manifest.schema.json +0 -49
- package/schemas/scope_manifest.schema.json +0 -47
- package/scripts/__pycache__/bet1_advisory_spike.cpython-311.pyc +0 -0
- package/scripts/__pycache__/build_adapters.cpython-311.pyc +0 -0
- package/scripts/__pycache__/check_docs.cpython-311.pyc +0 -0
- package/scripts/__pycache__/divergence_experiment.cpython-311.pyc +0 -0
- package/scripts/__pycache__/gen_schemas.cpython-311.pyc +0 -0
- package/scripts/auction_experiment.py +0 -188
- package/scripts/bet1_advisory_spike.py +0 -442
- package/scripts/build_adapters.py +0 -417
- package/scripts/check_docs.py +0 -66
- package/scripts/divergence_experiment.py +0 -214
- package/scripts/gen_schemas.py +0 -69
- package/skills/brainstorming/SKILL.md +0 -106
- package/skills/brainstorming/__init__.py +0 -1
- package/skills/brainstorming/scripts/brainstorm.py +0 -201
- package/skills/code_audit/SKILL.md +0 -45
- package/skills/darkharvest/SKILL.md +0 -70
- package/skills/darkharvest/scripts/harvest.py +0 -289
- package/skills/epistemic_search/SKILL.md +0 -67
- package/skills/epistemic_search/__init__.py +0 -1
- package/skills/epistemic_search/scripts/__pycache__/search.cpython-311.pyc +0 -0
- package/skills/epistemic_search/scripts/fetch.py +0 -156
- package/skills/epistemic_search/scripts/search.py +0 -551
- package/skills/epistemic_search/scripts/webcache.py +0 -339
- package/skills/factory/SKILL.md +0 -61
- package/skills/factory/scripts/factory.py +0 -300
- package/skills/grilling/SKILL.md +0 -61
- package/skills/grilling/__init__.py +0 -0
- package/skills/grilling/__pycache__/__init__.cpython-311.pyc +0 -0
- package/skills/grilling/__pycache__/socratic_tree.cpython-311.pyc +0 -0
- package/skills/grilling/socratic_tree.py +0 -363
- package/skills/oss_scout/SKILL.md +0 -49
- package/skills/research_cache/SKILL.md +0 -36
- package/skills/research_cache/__init__.py +0 -0
- package/skills/research_cache/__pycache__/__init__.cpython-311.pyc +0 -0
- package/skills/research_cache/__pycache__/hasher.cpython-311.pyc +0 -0
- package/skills/research_cache/hasher.py +0 -302
- package/skills/swarm_config/SKILL.md +0 -178
- package/skills/swarm_config/__init__.py +0 -35
- package/skills/swarm_config/__pycache__/__init__.cpython-311.pyc +0 -0
- package/skills/swarm_config/__pycache__/configure.cpython-311.pyc +0 -0
- package/skills/swarm_config/configure.py +0 -1002
package/runner/state_machine.py
DELETED
|
@@ -1,463 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Filesystem IPC Protocol & State Machine for Epistemic Swarm.
|
|
4
|
-
Manages .research/ hierarchy, session state, scope DAG, and dossier serialization.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import os
|
|
8
|
-
import json
|
|
9
|
-
import threading
|
|
10
|
-
import tempfile
|
|
11
|
-
from contextlib import contextmanager
|
|
12
|
-
from enum import Enum
|
|
13
|
-
from pathlib import Path
|
|
14
|
-
from datetime import datetime, timezone
|
|
15
|
-
from typing import Dict, Any, List, Optional
|
|
16
|
-
|
|
17
|
-
try: # POSIX advisory locking; no-op where unavailable
|
|
18
|
-
import fcntl
|
|
19
|
-
except ImportError: # pragma: no cover - non-POSIX
|
|
20
|
-
fcntl = None
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class SessionStatus(str, Enum):
|
|
24
|
-
INITIALIZING = "INITIALIZING"
|
|
25
|
-
FRONTIER_SETTLING = "FRONTIER_SETTLING"
|
|
26
|
-
ORCHESTRATING = "ORCHESTRATING"
|
|
27
|
-
SWARM_DISPATCHED = "SWARM_DISPATCHED"
|
|
28
|
-
AUDITING = "AUDITING"
|
|
29
|
-
COMPLETED = "COMPLETED"
|
|
30
|
-
FAILED = "FAILED"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
class ScopeStatus(str, Enum):
|
|
34
|
-
PENDING = "PENDING"
|
|
35
|
-
ALPHA_RUNNING = "ALPHA_RUNNING"
|
|
36
|
-
BETA_RUNNING = "BETA_RUNNING"
|
|
37
|
-
RUNNING_PARALLEL = "RUNNING_PARALLEL"
|
|
38
|
-
ALPHA_COMPLETE = "ALPHA_COMPLETE"
|
|
39
|
-
BETA_COMPLETE = "BETA_COMPLETE"
|
|
40
|
-
DOSSIERS_READY = "DOSSIERS_READY"
|
|
41
|
-
AUDITING = "AUDITING"
|
|
42
|
-
COMPLETE = "COMPLETE"
|
|
43
|
-
FAILED = "FAILED"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
MANIFEST_FILENAME = "manifest.json"
|
|
47
|
-
RUNS_DIRNAME = "runs"
|
|
48
|
-
LATEST_POINTER = "latest.json"
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def run_scoped_enabled() -> bool:
|
|
52
|
-
"""Opt-in run-scoped layout (`.research/runs/<id>/`). Default: flat.
|
|
53
|
-
|
|
54
|
-
The capability ships behind `IUMBTEMS_RUN_SCOPED=1` rather than flipped by
|
|
55
|
-
default: it changes every artifact path and deserves a live end-to-end run
|
|
56
|
-
before it becomes the default (see issue #6 item 3.9).
|
|
57
|
-
"""
|
|
58
|
-
return os.environ.get("IUMBTEMS_RUN_SCOPED", "").strip().lower() in (
|
|
59
|
-
"1",
|
|
60
|
-
"true",
|
|
61
|
-
"yes",
|
|
62
|
-
"on",
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
def latest_run_dir(workspace: Path) -> Optional[Path]:
|
|
67
|
-
"""The run dir a `latest.json` pointer refers to, if any."""
|
|
68
|
-
try:
|
|
69
|
-
data = json.loads((workspace / LATEST_POINTER).read_text(encoding="utf-8"))
|
|
70
|
-
run_id = data.get("run_id")
|
|
71
|
-
except (OSError, ValueError):
|
|
72
|
-
return None
|
|
73
|
-
if not run_id:
|
|
74
|
-
return None
|
|
75
|
-
candidate = workspace / RUNS_DIRNAME / str(run_id)
|
|
76
|
-
return candidate if candidate.is_dir() else None
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def manifest_name_for_mode(mode: Optional[str]) -> str:
|
|
80
|
-
"""Manifest filename for a run mode.
|
|
81
|
-
|
|
82
|
-
The default research flow keeps the historical `manifest.json`; every other
|
|
83
|
-
mode gets its own file so concurrently running tools (e.g. brainstorm and
|
|
84
|
-
darkharvest) cannot clobber each other's scope DAG.
|
|
85
|
-
"""
|
|
86
|
-
key = (mode or "").strip().lower()
|
|
87
|
-
if key in ("", "research"):
|
|
88
|
-
return MANIFEST_FILENAME
|
|
89
|
-
return f"manifest.{key}.json"
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
def resolve_manifest_path(base_dir, mode: Optional[str] = None) -> Path:
|
|
93
|
-
"""Absolute manifest path for a workspace + mode."""
|
|
94
|
-
base = Path(os.path.realpath(str(base_dir)))
|
|
95
|
-
return base / manifest_name_for_mode(mode)
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
def find_any_manifest(base_dir) -> Optional[Path]:
|
|
99
|
-
"""Newest manifest in the workspace, preferring the canonical name.
|
|
100
|
-
|
|
101
|
-
Understands both layouts: flat (`manifest.json`, `manifest.<mode>.json`) and
|
|
102
|
-
run-scoped (`runs/<id>/manifest*.json`, resolved via `latest.json`).
|
|
103
|
-
"""
|
|
104
|
-
base = Path(os.path.realpath(str(base_dir)))
|
|
105
|
-
candidates = []
|
|
106
|
-
canonical = base / MANIFEST_FILENAME
|
|
107
|
-
if canonical.exists():
|
|
108
|
-
return canonical
|
|
109
|
-
candidates.extend(base.glob("manifest.*.json"))
|
|
110
|
-
|
|
111
|
-
run_dir = latest_run_dir(base)
|
|
112
|
-
if run_dir is not None:
|
|
113
|
-
run_manifest = run_dir / MANIFEST_FILENAME
|
|
114
|
-
if run_manifest.exists():
|
|
115
|
-
return run_manifest
|
|
116
|
-
candidates.extend(run_dir.glob("manifest.*.json"))
|
|
117
|
-
if (base / RUNS_DIRNAME).is_dir():
|
|
118
|
-
candidates.extend((base / RUNS_DIRNAME).glob("*/manifest*.json"))
|
|
119
|
-
|
|
120
|
-
existing = [c for c in candidates if c.exists()]
|
|
121
|
-
if not existing:
|
|
122
|
-
return None
|
|
123
|
-
return max(existing, key=lambda p: p.stat().st_mtime)
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
@contextmanager
|
|
127
|
-
def _file_lock(lock_path: Path):
|
|
128
|
-
"""Cross-process advisory lock over one workspace."""
|
|
129
|
-
if fcntl is None:
|
|
130
|
-
yield
|
|
131
|
-
return
|
|
132
|
-
lock_path.parent.mkdir(parents=True, exist_ok=True)
|
|
133
|
-
with open(lock_path, "a+", encoding="utf-8") as fh:
|
|
134
|
-
fcntl.flock(fh.fileno(), fcntl.LOCK_EX)
|
|
135
|
-
try:
|
|
136
|
-
yield
|
|
137
|
-
finally:
|
|
138
|
-
fcntl.flock(fh.fileno(), fcntl.LOCK_UN)
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
def _atomic_write_json(path: Path, data: Any) -> None:
|
|
142
|
-
"""Write JSON atomically via a UNIQUE temp file + os.replace.
|
|
143
|
-
|
|
144
|
-
A fixed `*.tmp` name let concurrent writers collide on the same temp path
|
|
145
|
-
(reproduced: `FileNotFoundError: manifest.tmp -> manifest.json`, 758 times
|
|
146
|
-
across 4 parallel writers).
|
|
147
|
-
"""
|
|
148
|
-
path.parent.mkdir(parents=True, exist_ok=True)
|
|
149
|
-
fd, tmp = tempfile.mkstemp(
|
|
150
|
-
dir=str(path.parent), prefix=path.name + ".", suffix=".tmp"
|
|
151
|
-
)
|
|
152
|
-
try:
|
|
153
|
-
with os.fdopen(fd, "w", encoding="utf-8") as f:
|
|
154
|
-
json.dump(data, f, indent=2)
|
|
155
|
-
os.replace(tmp, path)
|
|
156
|
-
except BaseException:
|
|
157
|
-
try:
|
|
158
|
-
os.unlink(tmp)
|
|
159
|
-
except OSError:
|
|
160
|
-
pass
|
|
161
|
-
raise
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
class ResearchStateMachine:
|
|
165
|
-
def __init__(
|
|
166
|
-
self,
|
|
167
|
-
base_dir: Optional[Path] = None,
|
|
168
|
-
mode: Optional[str] = None,
|
|
169
|
-
run_scoped: Optional[bool] = None,
|
|
170
|
-
run_id: Optional[str] = None,
|
|
171
|
-
):
|
|
172
|
-
workspace = Path(os.path.realpath(str(base_dir or ".research")))
|
|
173
|
-
if run_scoped is None:
|
|
174
|
-
run_scoped = run_scoped_enabled()
|
|
175
|
-
self.workspace = workspace
|
|
176
|
-
self.run_scoped = bool(run_scoped)
|
|
177
|
-
if self.run_scoped:
|
|
178
|
-
self.run_id = run_id or (
|
|
179
|
-
f"{mode or 'run'}-{datetime.now(timezone.utc).strftime('%Y%m%d-%H%M%S')}"
|
|
180
|
-
)
|
|
181
|
-
self.base_dir = workspace / RUNS_DIRNAME / self.run_id
|
|
182
|
-
else:
|
|
183
|
-
self.run_id = None
|
|
184
|
-
self.base_dir = workspace
|
|
185
|
-
self.scratchpads_dir = self.base_dir / "scratchpads"
|
|
186
|
-
self.sources_dir = self.base_dir / "sources"
|
|
187
|
-
self.manifest_file = self.base_dir / manifest_name_for_mode(mode)
|
|
188
|
-
self._lock_file = self.base_dir / ".manifest.lock"
|
|
189
|
-
self._lock = threading.Lock()
|
|
190
|
-
|
|
191
|
-
# Ensure directories exist
|
|
192
|
-
self.scratchpads_dir.mkdir(parents=True, exist_ok=True)
|
|
193
|
-
self.sources_dir.mkdir(parents=True, exist_ok=True)
|
|
194
|
-
if self.run_scoped:
|
|
195
|
-
self._write_latest_pointer(mode)
|
|
196
|
-
|
|
197
|
-
def _write_latest_pointer(self, mode: Optional[str]) -> None:
|
|
198
|
-
try:
|
|
199
|
-
(self.workspace / LATEST_POINTER).write_text(
|
|
200
|
-
json.dumps({"run_id": self.run_id, "mode": mode}), encoding="utf-8"
|
|
201
|
-
)
|
|
202
|
-
except OSError:
|
|
203
|
-
pass
|
|
204
|
-
|
|
205
|
-
def init_session(
|
|
206
|
-
self, objective: str, session_id: Optional[str] = None
|
|
207
|
-
) -> Dict[str, Any]:
|
|
208
|
-
"""Initialize or reset a research session manifest."""
|
|
209
|
-
sid = (
|
|
210
|
-
session_id
|
|
211
|
-
or f"session-{datetime.now(timezone.utc).strftime('%Y%m%d-%H%M%S')}"
|
|
212
|
-
)
|
|
213
|
-
manifest = {
|
|
214
|
-
"session_id": sid,
|
|
215
|
-
"objective": objective,
|
|
216
|
-
"status": SessionStatus.INITIALIZING.value,
|
|
217
|
-
"created_at": datetime.now(timezone.utc).isoformat(),
|
|
218
|
-
"updated_at": datetime.now(timezone.utc).isoformat(),
|
|
219
|
-
"scopes": [],
|
|
220
|
-
"telemetry": {
|
|
221
|
-
"total_scopes": 0,
|
|
222
|
-
"completed_scopes": 0,
|
|
223
|
-
"total_claims_audited": 0,
|
|
224
|
-
"total_verified_claims": 0,
|
|
225
|
-
"total_rejected_claims": 0,
|
|
226
|
-
"mean_epistemic_score": 0.0,
|
|
227
|
-
"mean_divergence_score": 0.0,
|
|
228
|
-
},
|
|
229
|
-
}
|
|
230
|
-
self.save_global_manifest(manifest)
|
|
231
|
-
return manifest
|
|
232
|
-
|
|
233
|
-
def record_preflight(
|
|
234
|
-
self,
|
|
235
|
-
report: Dict[str, Any],
|
|
236
|
-
backend: Optional[str] = None,
|
|
237
|
-
divergence_threshold: Optional[float] = None,
|
|
238
|
-
) -> None:
|
|
239
|
-
"""Persist the preflight report + plugin version into the manifest.
|
|
240
|
-
|
|
241
|
-
`divergence_threshold` is recorded for reference only (advisory — it
|
|
242
|
-
never gates a verdict; see `runner/schemas.py` CONFIG).
|
|
243
|
-
"""
|
|
244
|
-
with self._lock, _file_lock(self._lock_file):
|
|
245
|
-
try:
|
|
246
|
-
manifest = self._read_manifest_unlocked()
|
|
247
|
-
except FileNotFoundError:
|
|
248
|
-
# Dry runs / pre-orchestration: keep the report rather than fail.
|
|
249
|
-
manifest = {"preflight": report}
|
|
250
|
-
manifest["preflight"] = report
|
|
251
|
-
version = report.get("plugin_version")
|
|
252
|
-
if version:
|
|
253
|
-
manifest["plugin_version"] = version
|
|
254
|
-
if backend:
|
|
255
|
-
manifest["backend"] = backend
|
|
256
|
-
if divergence_threshold is not None:
|
|
257
|
-
manifest["divergence_threshold"] = divergence_threshold
|
|
258
|
-
self._write_manifest_unlocked(manifest)
|
|
259
|
-
|
|
260
|
-
def _read_manifest_unlocked(self) -> Dict[str, Any]:
|
|
261
|
-
if not self.manifest_file.exists():
|
|
262
|
-
raise FileNotFoundError(
|
|
263
|
-
f"Global manifest not found at {self.manifest_file}"
|
|
264
|
-
)
|
|
265
|
-
with open(self.manifest_file, "r", encoding="utf-8") as f:
|
|
266
|
-
return json.load(f)
|
|
267
|
-
|
|
268
|
-
def _write_manifest_unlocked(self, manifest: Dict[str, Any]) -> None:
|
|
269
|
-
manifest["updated_at"] = datetime.now(timezone.utc).isoformat()
|
|
270
|
-
_atomic_write_json(self.manifest_file, manifest)
|
|
271
|
-
|
|
272
|
-
def load_global_manifest(self) -> Dict[str, Any]:
|
|
273
|
-
with self._lock:
|
|
274
|
-
return self._read_manifest_unlocked()
|
|
275
|
-
|
|
276
|
-
def set_manifest_fields(self, **fields: Any) -> None:
|
|
277
|
-
"""Set runner-owned top-level manifest fields under the cross-process lock.
|
|
278
|
-
|
|
279
|
-
Used for advisory bookkeeping (e.g. the recorded divergence threshold)
|
|
280
|
-
that must survive `init_session` re-initialization. Never invents a
|
|
281
|
-
manifest: when none exists yet, one is created with just these fields.
|
|
282
|
-
"""
|
|
283
|
-
if not fields:
|
|
284
|
-
return
|
|
285
|
-
with self._lock, _file_lock(self._lock_file):
|
|
286
|
-
try:
|
|
287
|
-
manifest = self._read_manifest_unlocked()
|
|
288
|
-
except FileNotFoundError:
|
|
289
|
-
manifest = {}
|
|
290
|
-
manifest.update(fields)
|
|
291
|
-
self._write_manifest_unlocked(manifest)
|
|
292
|
-
|
|
293
|
-
def save_global_manifest(self, manifest: Dict[str, Any]):
|
|
294
|
-
with self._lock, _file_lock(self._lock_file):
|
|
295
|
-
self._write_manifest_unlocked(manifest)
|
|
296
|
-
|
|
297
|
-
def update_session_status(self, status: SessionStatus):
|
|
298
|
-
# Read-modify-write under the cross-process lock so a concurrent writer
|
|
299
|
-
# cannot lose this update.
|
|
300
|
-
with self._lock, _file_lock(self._lock_file):
|
|
301
|
-
manifest = self._read_manifest_unlocked()
|
|
302
|
-
manifest["status"] = status.value
|
|
303
|
-
self._write_manifest_unlocked(manifest)
|
|
304
|
-
|
|
305
|
-
def set_scopes(self, scopes: List[Dict[str, Any]]):
|
|
306
|
-
"""Set scopes decomposed by orchestrator and prepare scratchpads."""
|
|
307
|
-
with self._lock, _file_lock(self._lock_file):
|
|
308
|
-
manifest = self._read_manifest_unlocked()
|
|
309
|
-
manifest["scopes"] = scopes
|
|
310
|
-
manifest.setdefault("telemetry", {})["total_scopes"] = len(scopes)
|
|
311
|
-
self._write_manifest_unlocked(manifest)
|
|
312
|
-
|
|
313
|
-
for scope in scopes:
|
|
314
|
-
scope_id = scope["scope_id"]
|
|
315
|
-
scope_dir = self.scratchpads_dir / scope_id
|
|
316
|
-
scope_dir.mkdir(parents=True, exist_ok=True)
|
|
317
|
-
|
|
318
|
-
scope_manifest = {
|
|
319
|
-
"scope_id": scope_id,
|
|
320
|
-
"title": scope.get("title", ""),
|
|
321
|
-
"objective": scope.get("objective", ""),
|
|
322
|
-
"dependencies": scope.get("dependencies", []),
|
|
323
|
-
"status": ScopeStatus.PENDING.value,
|
|
324
|
-
"alpha_completed": False,
|
|
325
|
-
"beta_completed": False,
|
|
326
|
-
"audit_completed": False,
|
|
327
|
-
"created_at": datetime.now(timezone.utc).isoformat(),
|
|
328
|
-
}
|
|
329
|
-
_atomic_write_json(scope_dir / MANIFEST_FILENAME, scope_manifest)
|
|
330
|
-
|
|
331
|
-
def get_scope_dir(self, scope_id: str) -> Path:
|
|
332
|
-
return self.scratchpads_dir / scope_id
|
|
333
|
-
|
|
334
|
-
def find_orphan_scopes(self) -> List[Dict[str, Any]]:
|
|
335
|
-
"""Scope dirs not referenced by any manifest — marked, never deleted.
|
|
336
|
-
|
|
337
|
-
A dir may belong to a concurrently running session, so this reports
|
|
338
|
-
rather than prunes (issue #5 layer 6: 14 manifest-only leftovers).
|
|
339
|
-
"""
|
|
340
|
-
referenced: set = set()
|
|
341
|
-
manifests = [self.manifest_file, *self.base_dir.glob("manifest.*.json")]
|
|
342
|
-
for manifest_path in manifests:
|
|
343
|
-
if not manifest_path.exists():
|
|
344
|
-
continue
|
|
345
|
-
try:
|
|
346
|
-
data = json.loads(manifest_path.read_text(encoding="utf-8"))
|
|
347
|
-
except (OSError, ValueError):
|
|
348
|
-
continue
|
|
349
|
-
for scope in data.get("scopes") or []:
|
|
350
|
-
if isinstance(scope, dict) and scope.get("scope_id"):
|
|
351
|
-
referenced.add(scope["scope_id"])
|
|
352
|
-
|
|
353
|
-
orphans: List[Dict[str, Any]] = []
|
|
354
|
-
if not self.scratchpads_dir.is_dir():
|
|
355
|
-
return orphans
|
|
356
|
-
for scope_dir in sorted(self.scratchpads_dir.iterdir()):
|
|
357
|
-
if not scope_dir.is_dir() or scope_dir.name in referenced:
|
|
358
|
-
continue
|
|
359
|
-
orphans.append(
|
|
360
|
-
{
|
|
361
|
-
"scope_id": scope_dir.name,
|
|
362
|
-
"path": str(scope_dir),
|
|
363
|
-
"alpha_dossier": (scope_dir / "alpha_dossier.json").exists(),
|
|
364
|
-
"beta_dossier": (scope_dir / "beta_dossier.json").exists(),
|
|
365
|
-
}
|
|
366
|
-
)
|
|
367
|
-
return orphans
|
|
368
|
-
|
|
369
|
-
def _read_scope_unlocked(self, scope_id: str) -> Dict[str, Any]:
|
|
370
|
-
scope_manifest_file = self.get_scope_dir(scope_id) / MANIFEST_FILENAME
|
|
371
|
-
if not scope_manifest_file.exists():
|
|
372
|
-
raise FileNotFoundError(f"Scope manifest not found for {scope_id}")
|
|
373
|
-
with open(scope_manifest_file, "r", encoding="utf-8") as f:
|
|
374
|
-
return json.load(f)
|
|
375
|
-
|
|
376
|
-
def _write_scope_unlocked(self, scope_id: str, manifest: Dict[str, Any]) -> None:
|
|
377
|
-
_atomic_write_json(self.get_scope_dir(scope_id) / MANIFEST_FILENAME, manifest)
|
|
378
|
-
|
|
379
|
-
def load_scope_manifest(self, scope_id: str) -> Dict[str, Any]:
|
|
380
|
-
with self._lock:
|
|
381
|
-
return self._read_scope_unlocked(scope_id)
|
|
382
|
-
|
|
383
|
-
def save_scope_manifest(self, scope_id: str, manifest: Dict[str, Any]):
|
|
384
|
-
with self._lock, _file_lock(self._lock_file):
|
|
385
|
-
self._write_scope_unlocked(scope_id, manifest)
|
|
386
|
-
|
|
387
|
-
def update_scope_status(self, scope_id: str, status: ScopeStatus):
|
|
388
|
-
with self._lock, _file_lock(self._lock_file):
|
|
389
|
-
sm = self._read_scope_unlocked(scope_id)
|
|
390
|
-
sm["status"] = status.value
|
|
391
|
-
self._write_scope_unlocked(scope_id, sm)
|
|
392
|
-
|
|
393
|
-
def record_agent_completion(
|
|
394
|
-
self, scope_id: str, agent_type: str, dossier_data: Dict[str, Any]
|
|
395
|
-
):
|
|
396
|
-
"""Records dossier from Alpha or Beta and advances scope state machine."""
|
|
397
|
-
scope_dir = self.get_scope_dir(scope_id)
|
|
398
|
-
|
|
399
|
-
if agent_type.lower() in ["alpha", "thesis", "proponent"]:
|
|
400
|
-
filename = "alpha_dossier.json"
|
|
401
|
-
elif agent_type.lower() in ["beta", "antithesis", "adversary", "red_team"]:
|
|
402
|
-
filename = "beta_dossier.json"
|
|
403
|
-
else:
|
|
404
|
-
raise ValueError(f"Unknown agent type: {agent_type}")
|
|
405
|
-
|
|
406
|
-
_atomic_write_json(scope_dir / filename, dossier_data)
|
|
407
|
-
self.reconcile_scope_status(scope_id)
|
|
408
|
-
|
|
409
|
-
def _artifacts_complete(self, scope_id: str) -> tuple:
|
|
410
|
-
"""(alpha, beta) dossier presence, derived from disk — never from stored flags."""
|
|
411
|
-
scope_dir = self.get_scope_dir(scope_id)
|
|
412
|
-
return (
|
|
413
|
-
(scope_dir / "alpha_dossier.json").exists(),
|
|
414
|
-
(scope_dir / "beta_dossier.json").exists(),
|
|
415
|
-
)
|
|
416
|
-
|
|
417
|
-
def reconcile_scope_status(self, scope_id: str) -> Dict[str, Any]:
|
|
418
|
-
"""Recompute completion flags + status from dossier artifacts on disk.
|
|
419
|
-
|
|
420
|
-
The scope manifest is runner-owned, but agents can write to the workspace
|
|
421
|
-
and have forged `beta_completed: true` / `DOSSIERS_READY` without emitting
|
|
422
|
-
the dossier. Deriving from files means stored booleans can never disagree
|
|
423
|
-
with reality.
|
|
424
|
-
"""
|
|
425
|
-
alpha, beta = self._artifacts_complete(scope_id)
|
|
426
|
-
with self._lock, _file_lock(self._lock_file):
|
|
427
|
-
sm = self._read_scope_unlocked(scope_id)
|
|
428
|
-
sm["alpha_completed"] = alpha
|
|
429
|
-
sm["beta_completed"] = beta
|
|
430
|
-
if sm.get("audit_completed"):
|
|
431
|
-
sm["status"] = ScopeStatus.COMPLETE.value
|
|
432
|
-
elif alpha and beta:
|
|
433
|
-
sm["status"] = ScopeStatus.DOSSIERS_READY.value
|
|
434
|
-
elif alpha:
|
|
435
|
-
sm["status"] = ScopeStatus.ALPHA_COMPLETE.value
|
|
436
|
-
elif beta:
|
|
437
|
-
sm["status"] = ScopeStatus.BETA_COMPLETE.value
|
|
438
|
-
elif sm.get("status") not in (
|
|
439
|
-
ScopeStatus.RUNNING_PARALLEL.value,
|
|
440
|
-
ScopeStatus.AUDITING.value,
|
|
441
|
-
):
|
|
442
|
-
sm["status"] = ScopeStatus.PENDING.value
|
|
443
|
-
self._write_scope_unlocked(scope_id, sm)
|
|
444
|
-
return sm
|
|
445
|
-
|
|
446
|
-
def get_ready_scopes(self) -> List[Dict[str, Any]]:
|
|
447
|
-
"""Return scopes whose dependencies are completed and status is PENDING."""
|
|
448
|
-
manifest = self.load_global_manifest()
|
|
449
|
-
ready = []
|
|
450
|
-
completed_scope_ids = {
|
|
451
|
-
s["scope_id"]
|
|
452
|
-
for s in manifest["scopes"]
|
|
453
|
-
if self.load_scope_manifest(s["scope_id"]).get("status")
|
|
454
|
-
== ScopeStatus.COMPLETE.value
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
for scope in manifest["scopes"]:
|
|
458
|
-
sm = self.load_scope_manifest(scope["scope_id"])
|
|
459
|
-
if sm["status"] == ScopeStatus.PENDING.value:
|
|
460
|
-
deps = set(scope.get("dependencies", []))
|
|
461
|
-
if deps.issubset(completed_scope_ids):
|
|
462
|
-
ready.append(scope)
|
|
463
|
-
return ready
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"objective_set": "auction-f-v1",
|
|
3
|
-
"note": "Fixed 4-scope objective for the Stream F auction-vs-DAG probe. Stable set: do not edit between runs, or wall-clock and claims/token are not comparable.",
|
|
4
|
-
"objective": "Evaluate the operational envelope of content-addressed research caches for long-lived engineering briefs",
|
|
5
|
-
"scopes": [
|
|
6
|
-
{
|
|
7
|
-
"scope_id": "scope_01_integrity",
|
|
8
|
-
"title": "Tamper evidence in content-addressed caches",
|
|
9
|
-
"objective": "Assess mechanisms for detecting tampering in SHA-256 addressed document caches",
|
|
10
|
-
"dependencies": [],
|
|
11
|
-
"bid": 4.0
|
|
12
|
-
},
|
|
13
|
-
{
|
|
14
|
-
"scope_id": "scope_02_staleness",
|
|
15
|
-
"title": "Claim staleness and source retraction",
|
|
16
|
-
"objective": "Determine how retraction and revision events should degrade previously verified claims",
|
|
17
|
-
"dependencies": ["scope_01_integrity"],
|
|
18
|
-
"bid": 3.0
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
"scope_id": "scope_03_portability",
|
|
22
|
-
"title": "Portable proof-carrying briefs",
|
|
23
|
-
"objective": "Evaluate self-contained signed brief bundles for third-party re-verification",
|
|
24
|
-
"dependencies": [],
|
|
25
|
-
"bid": 2.0
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
"scope_id": "scope_04_allocation",
|
|
29
|
-
"title": "Research resource allocation policies",
|
|
30
|
-
"objective": "Compare static DAG ordering versus bid-based allocation of dialectic research scopes",
|
|
31
|
-
"dependencies": [],
|
|
32
|
-
"bid": 1.0
|
|
33
|
-
}
|
|
34
|
-
]
|
|
35
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"fixture_id": "borderline-g-v1",
|
|
3
|
-
"note": "20 borderline claims for the Domain Packs probe. Mechanisms: 6 banned-domain, 2 missing-tag, 2 retracted-source (see retracted_hashes), 10 clean preprint-tier. Default constitution should ACCEPT all 20; biopharma should REJECT >= 25%.",
|
|
4
|
-
"retracted_hashes": ["RETRACTED_SRC_A", "RETRACTED_SRC_B"],
|
|
5
|
-
"claims": [
|
|
6
|
-
{"claim_id": "BB-01", "tag": "VERIFIED", "statement": "Cohort endpoint met primary efficacy bar", "source_hash": "PREPRINT_01", "source_url": "https://banned-preprint-mirror.example/p1", "verbatim_quote": "primary efficacy bar met", "tier": "PREPRINT"},
|
|
7
|
-
{"claim_id": "BB-02", "tag": "VERIFIED", "statement": "Adverse event rate within expected band", "source_hash": "PREPRINT_02", "source_url": "https://banned-preprint-mirror.example/p2", "verbatim_quote": "within expected band", "tier": "PREPRINT"},
|
|
8
|
-
{"claim_id": "BB-03", "tag": "VERIFIED", "statement": "Secondary endpoint shows dose response", "source_hash": "PREPRINT_03", "source_url": "https://banned-preprint-mirror.example/p3", "verbatim_quote": "dose response observed", "tier": "PREPRINT"},
|
|
9
|
-
{"claim_id": "BB-04", "tag": "VERIFIED", "statement": "Biomarker subgroup analysis favorable", "source_hash": "PREPRINT_04", "source_url": "https://predatory-journal.example/p4", "verbatim_quote": "subgroup analysis favorable", "tier": "PREPRINT"},
|
|
10
|
-
{"claim_id": "BB-05", "tag": "VERIFIED", "statement": "Pharmacokinetics consistent with model", "source_hash": "PREPRINT_05", "source_url": "https://predatory-journal.example/p5", "verbatim_quote": "consistent with model", "tier": "PREPRINT"},
|
|
11
|
-
{"claim_id": "BB-06", "tag": "VERIFIED", "statement": "Manufacturing yield acceptable at scale", "source_hash": "PREPRINT_06", "source_url": "https://banned-preprint-mirror.example/p6", "verbatim_quote": "yield acceptable at scale", "tier": "PREPRINT"},
|
|
12
|
-
{"claim_id": "BB-07", "tag": "", "statement": "Untagged assertion lacking epistemic classification", "source_hash": "CLEAN_01", "source_url": "https://journal.example/c1", "verbatim_quote": "assertion recorded without tag", "tier": "PREPRINT"},
|
|
13
|
-
{"claim_id": "BB-08", "tag": "", "statement": "Second untagged assertion in the borderline set", "source_hash": "CLEAN_02", "source_url": "https://journal.example/c2", "verbatim_quote": "second assertion without tag", "tier": "PREPRINT"},
|
|
14
|
-
{"claim_id": "BB-09", "tag": "VERIFIED", "statement": "Claim resting on a retracted source", "source_hash": "RETRACTED_SRC_A", "source_url": "https://journal.example/r1", "verbatim_quote": "finding later retracted", "tier": "PREPRINT"},
|
|
15
|
-
{"claim_id": "BB-10", "tag": "VERIFIED", "statement": "Second claim resting on a retracted source", "source_hash": "RETRACTED_SRC_B", "source_url": "https://journal.example/r2", "verbatim_quote": "second retracted finding", "tier": "PREPRINT"},
|
|
16
|
-
{"claim_id": "BB-11", "tag": "VERIFIED", "statement": "Preprint claim near acceptance boundary", "source_hash": "CLEAN_03", "source_url": "https://journal.example/c3", "verbatim_quote": "near acceptance boundary", "tier": "PREPRINT"},
|
|
17
|
-
{"claim_id": "BB-12", "tag": "VERIFIED", "statement": "Preprint claim with modest evidence", "source_hash": "CLEAN_04", "source_url": "https://journal.example/c4", "verbatim_quote": "modest evidence presented", "tier": "PREPRINT"},
|
|
18
|
-
{"claim_id": "BB-13", "tag": "VERIFIED", "statement": "Preprint claim with weak statistical power", "source_hash": "CLEAN_05", "source_url": "https://journal.example/c5", "verbatim_quote": "weak statistical power", "tier": "PREPRINT"},
|
|
19
|
-
{"claim_id": "BB-14", "tag": "VERIFIED", "statement": "Preprint claim awaiting replication", "source_hash": "CLEAN_06", "source_url": "https://journal.example/c6", "verbatim_quote": "awaiting replication", "tier": "PREPRINT"},
|
|
20
|
-
{"claim_id": "BB-15", "tag": "VERIFIED", "statement": "Preprint claim with narrow applicability", "source_hash": "CLEAN_07", "source_url": "https://journal.example/c7", "verbatim_quote": "narrow applicability", "tier": "PREPRINT"},
|
|
21
|
-
{"claim_id": "BB-16", "tag": "VERIFIED", "statement": "Preprint claim with exploratory endpoint", "source_hash": "CLEAN_08", "source_url": "https://journal.example/c8", "verbatim_quote": "exploratory endpoint", "tier": "PREPRINT"},
|
|
22
|
-
{"claim_id": "BB-17", "tag": "VERIFIED", "statement": "Preprint claim with post-hoc analysis", "source_hash": "CLEAN_09", "source_url": "https://journal.example/c9", "verbatim_quote": "post-hoc analysis", "tier": "PREPRINT"},
|
|
23
|
-
{"claim_id": "BB-18", "tag": "VERIFIED", "statement": "Preprint claim with surrogate endpoint", "source_hash": "CLEAN_10", "source_url": "https://journal.example/c10", "verbatim_quote": "surrogate endpoint", "tier": "PREPRINT"},
|
|
24
|
-
{"claim_id": "BB-19", "tag": "VERIFIED", "statement": "Preprint claim with single-site data", "source_hash": "CLEAN_11", "source_url": "https://journal.example/c11", "verbatim_quote": "single-site data", "tier": "PREPRINT"},
|
|
25
|
-
{"claim_id": "BB-20", "tag": "VERIFIED", "statement": "Preprint claim with interim readout", "source_hash": "CLEAN_12", "source_url": "https://journal.example/c12", "verbatim_quote": "interim readout", "tier": "PREPRINT"}
|
|
26
|
-
]
|
|
27
|
-
}
|