@heretek-ai/epistemic-swarm 0.7.11 → 0.7.13
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/.claude-plugin/plugin.json +1 -1
- package/package.json +1 -1
- package/plugins/research-cache/skills/research_cache/hasher.py +56 -14
- package/prompts/agent_brainstormer.md +14 -0
- package/prompts/agent_darkharvest.md +20 -1
- 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__/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__/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__/state_machine.cpython-311.pyc +0 -0
- package/runner/auditor_engine.py +267 -80
- package/runner/darkharvest_claims.py +326 -0
- package/runner/refinement.py +74 -0
- package/runner/research_swarm.py +119 -24
- package/runner/retrieval_log.py +90 -0
- package/runner/state_machine.py +35 -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_darkharvest_audit.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_grounding.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_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_refinement.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/test_darkharvest_audit.py +290 -0
- package/runner/tests/test_grounding.py +183 -0
- package/scripts/__pycache__/bet1_advisory_spike.cpython-311.pyc +0 -0
- package/scripts/__pycache__/build_adapters.cpython-311.pyc +0 -0
- package/scripts/__pycache__/divergence_experiment.cpython-311.pyc +0 -0
- package/skills/epistemic_search/scripts/__pycache__/search.cpython-311.pyc +0 -0
- package/skills/epistemic_search/scripts/search.py +16 -0
- package/skills/epistemic_search/scripts/webcache.py +11 -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 +56 -14
- package/skills/swarm_config/__pycache__/__init__.cpython-311.pyc +0 -0
- package/skills/swarm_config/__pycache__/configure.cpython-311.pyc +0 -0
|
@@ -16,6 +16,21 @@ from xml.sax.saxutils import escape as xml_escape
|
|
|
16
16
|
USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
|
17
17
|
|
|
18
18
|
|
|
19
|
+
def _log_retrieval(kind: str, **fields) -> None:
|
|
20
|
+
"""Best-effort retrieval telemetry (see runner/retrieval_log.py)."""
|
|
21
|
+
try:
|
|
22
|
+
from pathlib import Path as _Path
|
|
23
|
+
|
|
24
|
+
root = _Path(__file__).resolve().parents[3]
|
|
25
|
+
if str(root) not in sys.path:
|
|
26
|
+
sys.path.insert(0, str(root))
|
|
27
|
+
from runner.retrieval_log import default_base_dir, log_event
|
|
28
|
+
|
|
29
|
+
log_event(default_base_dir(), kind, **fields)
|
|
30
|
+
except Exception:
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
|
|
19
34
|
class DDGLiteParser(HTMLParser):
|
|
20
35
|
"""Linear, non-backtracking HTML parser for DuckDuckGo Lite search results.
|
|
21
36
|
|
|
@@ -204,6 +219,7 @@ def search_duckduckgo(
|
|
|
204
219
|
if len(results) >= max_results:
|
|
205
220
|
break
|
|
206
221
|
|
|
222
|
+
_log_retrieval("query", query=effective_query, results=len(results))
|
|
207
223
|
return results
|
|
208
224
|
|
|
209
225
|
|
|
@@ -249,6 +249,17 @@ def cmd_archive(stdin_data):
|
|
|
249
249
|
encoding="utf-8",
|
|
250
250
|
)
|
|
251
251
|
log(f"archived {domain_of(url)} -> {digest[:16]} ({len(text)} chars)")
|
|
252
|
+
try:
|
|
253
|
+
root = Path(__file__).resolve().parents[3]
|
|
254
|
+
if str(root) not in sys.path:
|
|
255
|
+
sys.path.insert(0, str(root))
|
|
256
|
+
from runner.retrieval_log import log_event
|
|
257
|
+
|
|
258
|
+
log_event(
|
|
259
|
+
research_dir(stdin_data), "cache", url=url, hash=digest, tool="webcache"
|
|
260
|
+
)
|
|
261
|
+
except Exception:
|
|
262
|
+
pass
|
|
252
263
|
except Exception as e:
|
|
253
264
|
log(f"archive failed for {domain_of(url)}: {e}")
|
|
254
265
|
return None
|
|
Binary file
|
|
Binary file
|
|
@@ -17,6 +17,20 @@ from typing import Dict, Any, Optional, Tuple
|
|
|
17
17
|
DEFAULT_RESEARCH_DIR = ".research"
|
|
18
18
|
BASE_DIR_HELP = "Base .research directory"
|
|
19
19
|
|
|
20
|
+
|
|
21
|
+
def _log_retrieval(base_dir, kind: str, **fields) -> None:
|
|
22
|
+
"""Best-effort retrieval telemetry (see runner/retrieval_log.py)."""
|
|
23
|
+
try:
|
|
24
|
+
root = Path(__file__).resolve().parents[2]
|
|
25
|
+
if str(root) not in sys.path:
|
|
26
|
+
sys.path.insert(0, str(root))
|
|
27
|
+
from runner.retrieval_log import log_event
|
|
28
|
+
|
|
29
|
+
log_event(base_dir, kind, **fields)
|
|
30
|
+
except Exception:
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
|
|
20
34
|
class SourceHasher:
|
|
21
35
|
def __init__(self, base_dir: Optional[Path] = None):
|
|
22
36
|
target = base_dir or Path(DEFAULT_RESEARCH_DIR)
|
|
@@ -30,8 +44,14 @@ class SourceHasher:
|
|
|
30
44
|
normalized = content.strip().encode("utf-8")
|
|
31
45
|
return hashlib.sha256(normalized).hexdigest()
|
|
32
46
|
|
|
33
|
-
def store_source(
|
|
34
|
-
|
|
47
|
+
def store_source(
|
|
48
|
+
self,
|
|
49
|
+
url: str,
|
|
50
|
+
content: str,
|
|
51
|
+
title: Optional[str] = None,
|
|
52
|
+
tier: str = "WEB_DOCUMENT",
|
|
53
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
54
|
+
) -> str:
|
|
35
55
|
"""Store content and metadata content-addressed by SHA-256."""
|
|
36
56
|
content_hash = self.compute_sha256(content)
|
|
37
57
|
md_path = self.sources_dir / f"{content_hash}.md"
|
|
@@ -50,7 +70,7 @@ class SourceHasher:
|
|
|
50
70
|
"cached_at": datetime.now(timezone.utc).isoformat(),
|
|
51
71
|
"byte_size": len(content.encode("utf-8")),
|
|
52
72
|
"char_count": len(content),
|
|
53
|
-
"custom_metadata": metadata or {}
|
|
73
|
+
"custom_metadata": metadata or {},
|
|
54
74
|
}
|
|
55
75
|
with open(json_path, "w", encoding="utf-8") as f:
|
|
56
76
|
json.dump(meta, f, indent=2)
|
|
@@ -84,7 +104,9 @@ class SourceHasher:
|
|
|
84
104
|
"""
|
|
85
105
|
if not re.match(r"^[a-fA-F0-9]+$", hash_prefix):
|
|
86
106
|
return None
|
|
87
|
-
exact_path = Path(
|
|
107
|
+
exact_path = Path(
|
|
108
|
+
os.path.realpath(str(self.sources_dir / f"{hash_prefix}{extension}"))
|
|
109
|
+
)
|
|
88
110
|
if exact_path.parent != self.sources_dir:
|
|
89
111
|
return None
|
|
90
112
|
if exact_path.exists():
|
|
@@ -102,12 +124,16 @@ class SourceHasher:
|
|
|
102
124
|
def normalize_text_for_search(text: str) -> str:
|
|
103
125
|
"""Collapse whitespace and normalize typography for substring matching."""
|
|
104
126
|
# Replace smart quotes and dashes
|
|
105
|
-
text =
|
|
127
|
+
text = (
|
|
128
|
+
text.replace("“", '"').replace("”", '"').replace("‘", "'").replace("’", "'")
|
|
129
|
+
)
|
|
106
130
|
text = text.replace("—", "-").replace("–", "-")
|
|
107
131
|
# Collapse all whitespace to single spaces
|
|
108
132
|
return re.sub(r"\s+", " ", text).strip().lower()
|
|
109
133
|
|
|
110
|
-
def verify_quote(
|
|
134
|
+
def verify_quote(
|
|
135
|
+
self, content_hash: str, quote: str
|
|
136
|
+
) -> Tuple[bool, float, Optional[str]]:
|
|
111
137
|
"""
|
|
112
138
|
Verifies whether quote exists in cached document.
|
|
113
139
|
Returns: (is_verified, confidence_score, context_match)
|
|
@@ -136,7 +162,7 @@ class SourceHasher:
|
|
|
136
162
|
best_score = 0.0
|
|
137
163
|
|
|
138
164
|
for i in range(max(1, len(source_words) - window_size + 1)):
|
|
139
|
-
window = source_words[i:i + window_size]
|
|
165
|
+
window = source_words[i : i + window_size]
|
|
140
166
|
matches = sum(1 for w1, w2 in zip(quote_words, window) if w1 == w2)
|
|
141
167
|
score = matches / window_size
|
|
142
168
|
if score > best_score:
|
|
@@ -147,11 +173,17 @@ class SourceHasher:
|
|
|
147
173
|
if best_score >= 0.88:
|
|
148
174
|
return True, best_score, f"High-confidence fuzzy match ({best_score:.2f})."
|
|
149
175
|
|
|
150
|
-
return
|
|
176
|
+
return (
|
|
177
|
+
False,
|
|
178
|
+
best_score,
|
|
179
|
+
f"Verification failed. Highest word overlap: {best_score:.2f}.",
|
|
180
|
+
)
|
|
151
181
|
|
|
152
182
|
|
|
153
183
|
def main():
|
|
154
|
-
parser = argparse.ArgumentParser(
|
|
184
|
+
parser = argparse.ArgumentParser(
|
|
185
|
+
description="Epistemic Swarm Content Hasher & Quote Verifier"
|
|
186
|
+
)
|
|
155
187
|
subparsers = parser.add_subparsers(dest="command")
|
|
156
188
|
|
|
157
189
|
# Cache command
|
|
@@ -166,7 +198,9 @@ def main():
|
|
|
166
198
|
verify_parser = subparsers.add_parser("verify", help="Verify a verbatim quote")
|
|
167
199
|
verify_parser.add_argument("--hash", required=True, help="Document SHA-256 hash")
|
|
168
200
|
verify_parser.add_argument("--quote", required=True, help="Verbatim quote to check")
|
|
169
|
-
verify_parser.add_argument(
|
|
201
|
+
verify_parser.add_argument(
|
|
202
|
+
"--dir", default=DEFAULT_RESEARCH_DIR, help=BASE_DIR_HELP
|
|
203
|
+
)
|
|
170
204
|
|
|
171
205
|
# List command
|
|
172
206
|
list_parser = subparsers.add_parser("list", help="List cached sources")
|
|
@@ -182,18 +216,26 @@ def main():
|
|
|
182
216
|
if not sys.stdin.isatty():
|
|
183
217
|
content = sys.stdin.read()
|
|
184
218
|
else:
|
|
185
|
-
print(
|
|
219
|
+
print(
|
|
220
|
+
"Error: No content provided via --content or stdin.",
|
|
221
|
+
file=sys.stderr,
|
|
222
|
+
)
|
|
186
223
|
sys.exit(1)
|
|
187
|
-
h = hasher.store_source(
|
|
224
|
+
h = hasher.store_source(
|
|
225
|
+
url=args.url, content=content, title=args.title, tier=args.tier
|
|
226
|
+
)
|
|
188
227
|
print(f"[CACHED] {h} -> {args.title} ({args.url})")
|
|
228
|
+
_log_retrieval(hasher.base_dir, "cache", url=args.url, hash=h, tool="hasher")
|
|
189
229
|
|
|
190
230
|
elif args.command == "verify":
|
|
191
|
-
verified, conf, msg = hasher.verify_quote(
|
|
231
|
+
verified, conf, msg = hasher.verify_quote(
|
|
232
|
+
content_hash=args.hash, quote=args.quote
|
|
233
|
+
)
|
|
192
234
|
result = {
|
|
193
235
|
"hash": args.hash,
|
|
194
236
|
"verified": verified,
|
|
195
237
|
"confidence": conf,
|
|
196
|
-
"message": msg
|
|
238
|
+
"message": msg,
|
|
197
239
|
}
|
|
198
240
|
print(json.dumps(result, indent=2))
|
|
199
241
|
sys.exit(0 if verified else 1)
|
|
Binary file
|
|
Binary file
|