patchr 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- apps/__init__.py +2 -0
- apps/api/__init__.py +2 -0
- apps/api/main.py +652 -0
- apps/benchmarks/__init__.py +1 -0
- apps/benchmarks/main.py +20 -0
- apps/sandbox/__init__.py +1 -0
- apps/sandbox/main.py +20 -0
- apps/worker/__init__.py +2 -0
- apps/worker/main.py +15 -0
- apps/worker/verify.py +14 -0
- patchr/__init__.py +12 -0
- patchr/sdk/__init__.py +20 -0
- patchr/sdk/client.py +12 -0
- patchr-0.1.0.dist-info/METADATA +137 -0
- patchr-0.1.0.dist-info/RECORD +116 -0
- patchr-0.1.0.dist-info/WHEEL +5 -0
- patchr-0.1.0.dist-info/entry_points.txt +5 -0
- patchr-0.1.0.dist-info/licenses/LICENSE +17 -0
- patchr-0.1.0.dist-info/top_level.txt +3 -0
- picux/__init__.py +6 -0
- picux/agents/__init__.py +5 -0
- picux/agents/registry.py +204 -0
- picux/api/__init__.py +5 -0
- picux/api/service.py +5075 -0
- picux/audit/__init__.py +31 -0
- picux/audit/activity.py +97 -0
- picux/audit/observability.py +55 -0
- picux/audit/verification/__init__.py +21 -0
- picux/audit/verification/ledger.py +633 -0
- picux/benchmarks/__init__.py +5 -0
- picux/benchmarks/local.py +286 -0
- picux/config.py +140 -0
- picux/contracts/__init__.py +22 -0
- picux/contracts/handshake.py +122 -0
- picux/contracts/integration.py +385 -0
- picux/contracts/openapi.py +187 -0
- picux/contracts/protocol_map.py +152 -0
- picux/contracts/routes.py +980 -0
- picux/contracts/schema_catalog.py +125 -0
- picux/core/__init__.py +17 -0
- picux/core/models.py +148 -0
- picux/core/router.py +131 -0
- picux/core/runtime.py +42 -0
- picux/core/state_machine.py +38 -0
- picux/domains/__init__.py +2 -0
- picux/domains/bridge/HostRun.py +1104 -0
- picux/domains/bridge/__init__.py +6 -0
- picux/domains/bridge/engine.py +345 -0
- picux/domains/hunt/__init__.py +6 -0
- picux/domains/hunt/engine.py +307 -0
- picux/domains/hunt/models.py +88 -0
- picux/domains/pay/__init__.py +16 -0
- picux/domains/pay/adapters.py +607 -0
- picux/domains/pay/engine.py +950 -0
- picux/domains/pay/models.py +95 -0
- picux/domains/proxy/__init__.py +5 -0
- picux/domains/proxy/engine.py +466 -0
- picux/domains/resolve/__init__.py +5 -0
- picux/domains/resolve/engine.py +546 -0
- picux/orchestrator/__init__.py +3 -0
- picux/orchestrator/engine.py +2840 -0
- picux/portals/__init__.py +17 -0
- picux/portals/templates.py +272 -0
- picux/protocols/__init__.py +1 -0
- picux/protocols/a2a/__init__.py +6 -0
- picux/protocols/a2a/client.py +51 -0
- picux/protocols/a2a/envelope.py +132 -0
- picux/protocols/mcp/__init__.py +7 -0
- picux/protocols/mcp/client.py +69 -0
- picux/protocols/mcp/contract.py +67 -0
- picux/protocols/mcp/server.py +76 -0
- picux/sandbox/__init__.py +6 -0
- picux/sandbox/midnight_arbitrage.py +215 -0
- picux/sandbox/models.py +90 -0
- picux/sdk/__init__.py +13 -0
- picux/sdk/client.py +768 -0
- picux/sdk/external.py +245 -0
- picux/security/__init__.py +18 -0
- picux/security/auth.py +86 -0
- picux/security/config_validator.py +58 -0
- picux/security/policy.py +158 -0
- picux/security/secrets.py +144 -0
- picux/signals/__init__.py +1 -0
- picux/signals/community/__init__.py +24 -0
- picux/signals/community/adapters/__init__.py +7 -0
- picux/signals/community/adapters/reddit.py +37 -0
- picux/signals/community/adapters/shopify.py +23 -0
- picux/signals/community/adapters/web.py +23 -0
- picux/signals/community/disambiguation.py +51 -0
- picux/signals/community/intake.py +227 -0
- picux/signals/community/models.py +102 -0
- picux/signals/community/rules.py +91 -0
- picux/signals/community/scoring.py +64 -0
- picux/storage/__init__.py +41 -0
- picux/storage/agents.py +50 -0
- picux/storage/cases.py +440 -0
- picux/storage/channels.py +476 -0
- picux/storage/connectors.py +411 -0
- picux/storage/envelopes.py +137 -0
- picux/storage/escrows.py +168 -0
- picux/storage/events.py +989 -0
- picux/storage/keyspace.py +60 -0
- picux/storage/mandates.py +107 -0
- picux/storage/portals.py +222 -0
- picux/storage/postgres.py +2049 -0
- picux/storage/providers.py +148 -0
- picux/storage/proxy.py +231 -0
- picux/storage/receipts.py +131 -0
- picux/storage/signals.py +147 -0
- picux/storage/tasks.py +179 -0
- picux/tools/__init__.py +11 -0
- picux/tools/shared.py +2048 -0
- picux/verification/__init__.py +5 -0
- picux/verification/rollout.py +183 -0
- picux/workflows/__init__.py +5 -0
- picux/workflows/templates.py +74 -0
picux/audit/__init__.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Audit and observability primitives."""
|
|
2
|
+
|
|
3
|
+
from .activity import ActivityLog
|
|
4
|
+
from .observability import (
|
|
5
|
+
BRIDGE_DONE,
|
|
6
|
+
DOMAIN_METRICS,
|
|
7
|
+
HARNESS_COLLISION,
|
|
8
|
+
PAY_SETTLED,
|
|
9
|
+
RESOLVE_WIN,
|
|
10
|
+
SIGNAL_ACCEPTED,
|
|
11
|
+
TASK_CREATED,
|
|
12
|
+
TASK_DONE,
|
|
13
|
+
DomainMetrics,
|
|
14
|
+
)
|
|
15
|
+
from .verification import EvidenceArtifact, ProofOfValueRecord, VerificationLedger
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"ActivityLog",
|
|
19
|
+
"BRIDGE_DONE",
|
|
20
|
+
"DOMAIN_METRICS",
|
|
21
|
+
"DomainMetrics",
|
|
22
|
+
"EvidenceArtifact",
|
|
23
|
+
"HARNESS_COLLISION",
|
|
24
|
+
"PAY_SETTLED",
|
|
25
|
+
"ProofOfValueRecord",
|
|
26
|
+
"RESOLVE_WIN",
|
|
27
|
+
"SIGNAL_ACCEPTED",
|
|
28
|
+
"TASK_CREATED",
|
|
29
|
+
"TASK_DONE",
|
|
30
|
+
"VerificationLedger",
|
|
31
|
+
]
|
picux/audit/activity.py
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import logging
|
|
5
|
+
import time
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from picux.storage import Keyspace, PicuxPostgresStore
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger("picux.audit.activity")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ActivityLog:
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
redis,
|
|
17
|
+
*,
|
|
18
|
+
db: PicuxPostgresStore | None = None,
|
|
19
|
+
keys: Keyspace | None = None,
|
|
20
|
+
ttl: int = 60 * 60 * 24 * 30,
|
|
21
|
+
) -> None:
|
|
22
|
+
self.redis = redis
|
|
23
|
+
self.db = db
|
|
24
|
+
self.keys = keys or Keyspace()
|
|
25
|
+
self.ttl = max(3600, int(ttl))
|
|
26
|
+
|
|
27
|
+
def log(
|
|
28
|
+
self,
|
|
29
|
+
*,
|
|
30
|
+
taskId: str,
|
|
31
|
+
userId: str,
|
|
32
|
+
level: str,
|
|
33
|
+
action: str,
|
|
34
|
+
detail: str,
|
|
35
|
+
meta: dict[str, Any] | None = None,
|
|
36
|
+
) -> dict[str, Any]:
|
|
37
|
+
now = int(time.time())
|
|
38
|
+
entry = {
|
|
39
|
+
"ts": now,
|
|
40
|
+
"level": str(level or "info").upper(),
|
|
41
|
+
"action": str(action or "").strip(),
|
|
42
|
+
"detail": str(detail or "").strip(),
|
|
43
|
+
"meta": meta or {},
|
|
44
|
+
}
|
|
45
|
+
payload = json.dumps(entry, ensure_ascii=True, sort_keys=True)
|
|
46
|
+
try:
|
|
47
|
+
pipe = self.redis.pipeline()
|
|
48
|
+
pipe.rpush(self.keys.taskLog(taskId), payload)
|
|
49
|
+
pipe.expire(self.keys.taskLog(taskId), self.ttl)
|
|
50
|
+
pipe.zadd(self.keys.userLog(userId), {taskId: now})
|
|
51
|
+
pipe.expire(self.keys.userLog(userId), self.ttl)
|
|
52
|
+
pipe.execute()
|
|
53
|
+
except Exception:
|
|
54
|
+
logger.exception("activityLogWriteFailed taskId=%s", taskId)
|
|
55
|
+
|
|
56
|
+
if self.db is not None:
|
|
57
|
+
self.db.insertActivity(
|
|
58
|
+
taskId=taskId,
|
|
59
|
+
userId=userId,
|
|
60
|
+
level=entry["level"],
|
|
61
|
+
action=entry["action"],
|
|
62
|
+
detail=entry["detail"],
|
|
63
|
+
meta=entry["meta"],
|
|
64
|
+
)
|
|
65
|
+
return entry
|
|
66
|
+
|
|
67
|
+
def entries(self, taskId: str, *, limit: int = 100) -> list[dict[str, Any]]:
|
|
68
|
+
raw = self.redis.lrange(self.keys.taskLog(taskId), max(0, -int(limit)), -1)
|
|
69
|
+
out: list[dict[str, Any]] = []
|
|
70
|
+
for item in raw:
|
|
71
|
+
try:
|
|
72
|
+
parsed = json.loads(item)
|
|
73
|
+
except Exception:
|
|
74
|
+
continue
|
|
75
|
+
if isinstance(parsed, dict):
|
|
76
|
+
out.append(parsed)
|
|
77
|
+
return out
|
|
78
|
+
|
|
79
|
+
def recentTasks(self, userId: str, *, limit: int = 10) -> list[str]:
|
|
80
|
+
return [str(item) for item in self.redis.zrevrange(self.keys.userLog(userId), 0, max(0, int(limit) - 1))]
|
|
81
|
+
|
|
82
|
+
def timeline(self, taskId: str, *, includeThoughts: bool = False, limit: int = 100) -> str:
|
|
83
|
+
rows = self.entries(taskId, limit=limit)
|
|
84
|
+
lines = [f"TASK LOG: {taskId}"]
|
|
85
|
+
if not rows:
|
|
86
|
+
return "\n".join([*lines, "- no entries"])
|
|
87
|
+
for row in rows:
|
|
88
|
+
level = str(row.get("level", "INFO")).upper()
|
|
89
|
+
if level == "THOUGHT" and not includeThoughts:
|
|
90
|
+
continue
|
|
91
|
+
ts = int(row.get("ts", 0) or 0)
|
|
92
|
+
hhmm = time.strftime("%H:%M", time.gmtime(ts)) if ts else "--:--"
|
|
93
|
+
lines.append(f"{hhmm} {level} {row.get('action', 'ACTION')}: {row.get('detail', '-')}")
|
|
94
|
+
if len(lines) == 1:
|
|
95
|
+
lines.append("- no user-facing entries")
|
|
96
|
+
return "\n".join(lines)
|
|
97
|
+
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
from collections.abc import Iterable
|
|
5
|
+
|
|
6
|
+
from picux.storage import Keyspace
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
TASK_CREATED = "taskCreated"
|
|
10
|
+
TASK_DONE = "taskDone"
|
|
11
|
+
RESOLVE_WIN = "resolveWin"
|
|
12
|
+
BRIDGE_DONE = "bridgeDone"
|
|
13
|
+
PAY_SETTLED = "paySettled"
|
|
14
|
+
SIGNAL_ACCEPTED = "signalAccepted"
|
|
15
|
+
HARNESS_COLLISION = "harnessCollision"
|
|
16
|
+
|
|
17
|
+
DOMAIN_METRICS = (
|
|
18
|
+
TASK_CREATED,
|
|
19
|
+
TASK_DONE,
|
|
20
|
+
RESOLVE_WIN,
|
|
21
|
+
BRIDGE_DONE,
|
|
22
|
+
PAY_SETTLED,
|
|
23
|
+
SIGNAL_ACCEPTED,
|
|
24
|
+
HARNESS_COLLISION,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class DomainMetrics:
|
|
29
|
+
def __init__(self, redis, *, keys: Keyspace | None = None, ttl: int = 60 * 60 * 24 * 120) -> None:
|
|
30
|
+
self.redis = redis
|
|
31
|
+
self.keys = keys or Keyspace()
|
|
32
|
+
self.ttl = max(3600, int(ttl))
|
|
33
|
+
|
|
34
|
+
def inc(self, metric: str, amount: int = 1) -> None:
|
|
35
|
+
if metric not in DOMAIN_METRICS:
|
|
36
|
+
return
|
|
37
|
+
value = int(amount or 0)
|
|
38
|
+
if value <= 0:
|
|
39
|
+
return
|
|
40
|
+
key = self.keys.metric(metric)
|
|
41
|
+
pipe = self.redis.pipeline()
|
|
42
|
+
pipe.incrby(key, value)
|
|
43
|
+
pipe.expire(key, self.ttl)
|
|
44
|
+
pipe.set(f"{key}:updatedAt", str(int(time.time())), ex=self.ttl)
|
|
45
|
+
pipe.execute()
|
|
46
|
+
|
|
47
|
+
def snap(self, metrics: Iterable[str] = DOMAIN_METRICS) -> dict[str, int]:
|
|
48
|
+
out: dict[str, int] = {}
|
|
49
|
+
for metric in metrics:
|
|
50
|
+
try:
|
|
51
|
+
out[metric] = int(self.redis.get(self.keys.metric(metric)) or 0)
|
|
52
|
+
except Exception:
|
|
53
|
+
out[metric] = 0
|
|
54
|
+
return out
|
|
55
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Audit verification artifacts and proof ledger."""
|
|
2
|
+
|
|
3
|
+
from .ledger import (
|
|
4
|
+
EvidenceArtifact,
|
|
5
|
+
ProofOfValueRecord,
|
|
6
|
+
VerificationLedger,
|
|
7
|
+
canonicalHash,
|
|
8
|
+
povChainHash,
|
|
9
|
+
receiptHash,
|
|
10
|
+
receiptId,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"EvidenceArtifact",
|
|
15
|
+
"ProofOfValueRecord",
|
|
16
|
+
"VerificationLedger",
|
|
17
|
+
"canonicalHash",
|
|
18
|
+
"povChainHash",
|
|
19
|
+
"receiptHash",
|
|
20
|
+
"receiptId",
|
|
21
|
+
]
|