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.
Files changed (116) hide show
  1. apps/__init__.py +2 -0
  2. apps/api/__init__.py +2 -0
  3. apps/api/main.py +652 -0
  4. apps/benchmarks/__init__.py +1 -0
  5. apps/benchmarks/main.py +20 -0
  6. apps/sandbox/__init__.py +1 -0
  7. apps/sandbox/main.py +20 -0
  8. apps/worker/__init__.py +2 -0
  9. apps/worker/main.py +15 -0
  10. apps/worker/verify.py +14 -0
  11. patchr/__init__.py +12 -0
  12. patchr/sdk/__init__.py +20 -0
  13. patchr/sdk/client.py +12 -0
  14. patchr-0.1.0.dist-info/METADATA +137 -0
  15. patchr-0.1.0.dist-info/RECORD +116 -0
  16. patchr-0.1.0.dist-info/WHEEL +5 -0
  17. patchr-0.1.0.dist-info/entry_points.txt +5 -0
  18. patchr-0.1.0.dist-info/licenses/LICENSE +17 -0
  19. patchr-0.1.0.dist-info/top_level.txt +3 -0
  20. picux/__init__.py +6 -0
  21. picux/agents/__init__.py +5 -0
  22. picux/agents/registry.py +204 -0
  23. picux/api/__init__.py +5 -0
  24. picux/api/service.py +5075 -0
  25. picux/audit/__init__.py +31 -0
  26. picux/audit/activity.py +97 -0
  27. picux/audit/observability.py +55 -0
  28. picux/audit/verification/__init__.py +21 -0
  29. picux/audit/verification/ledger.py +633 -0
  30. picux/benchmarks/__init__.py +5 -0
  31. picux/benchmarks/local.py +286 -0
  32. picux/config.py +140 -0
  33. picux/contracts/__init__.py +22 -0
  34. picux/contracts/handshake.py +122 -0
  35. picux/contracts/integration.py +385 -0
  36. picux/contracts/openapi.py +187 -0
  37. picux/contracts/protocol_map.py +152 -0
  38. picux/contracts/routes.py +980 -0
  39. picux/contracts/schema_catalog.py +125 -0
  40. picux/core/__init__.py +17 -0
  41. picux/core/models.py +148 -0
  42. picux/core/router.py +131 -0
  43. picux/core/runtime.py +42 -0
  44. picux/core/state_machine.py +38 -0
  45. picux/domains/__init__.py +2 -0
  46. picux/domains/bridge/HostRun.py +1104 -0
  47. picux/domains/bridge/__init__.py +6 -0
  48. picux/domains/bridge/engine.py +345 -0
  49. picux/domains/hunt/__init__.py +6 -0
  50. picux/domains/hunt/engine.py +307 -0
  51. picux/domains/hunt/models.py +88 -0
  52. picux/domains/pay/__init__.py +16 -0
  53. picux/domains/pay/adapters.py +607 -0
  54. picux/domains/pay/engine.py +950 -0
  55. picux/domains/pay/models.py +95 -0
  56. picux/domains/proxy/__init__.py +5 -0
  57. picux/domains/proxy/engine.py +466 -0
  58. picux/domains/resolve/__init__.py +5 -0
  59. picux/domains/resolve/engine.py +546 -0
  60. picux/orchestrator/__init__.py +3 -0
  61. picux/orchestrator/engine.py +2840 -0
  62. picux/portals/__init__.py +17 -0
  63. picux/portals/templates.py +272 -0
  64. picux/protocols/__init__.py +1 -0
  65. picux/protocols/a2a/__init__.py +6 -0
  66. picux/protocols/a2a/client.py +51 -0
  67. picux/protocols/a2a/envelope.py +132 -0
  68. picux/protocols/mcp/__init__.py +7 -0
  69. picux/protocols/mcp/client.py +69 -0
  70. picux/protocols/mcp/contract.py +67 -0
  71. picux/protocols/mcp/server.py +76 -0
  72. picux/sandbox/__init__.py +6 -0
  73. picux/sandbox/midnight_arbitrage.py +215 -0
  74. picux/sandbox/models.py +90 -0
  75. picux/sdk/__init__.py +13 -0
  76. picux/sdk/client.py +768 -0
  77. picux/sdk/external.py +245 -0
  78. picux/security/__init__.py +18 -0
  79. picux/security/auth.py +86 -0
  80. picux/security/config_validator.py +58 -0
  81. picux/security/policy.py +158 -0
  82. picux/security/secrets.py +144 -0
  83. picux/signals/__init__.py +1 -0
  84. picux/signals/community/__init__.py +24 -0
  85. picux/signals/community/adapters/__init__.py +7 -0
  86. picux/signals/community/adapters/reddit.py +37 -0
  87. picux/signals/community/adapters/shopify.py +23 -0
  88. picux/signals/community/adapters/web.py +23 -0
  89. picux/signals/community/disambiguation.py +51 -0
  90. picux/signals/community/intake.py +227 -0
  91. picux/signals/community/models.py +102 -0
  92. picux/signals/community/rules.py +91 -0
  93. picux/signals/community/scoring.py +64 -0
  94. picux/storage/__init__.py +41 -0
  95. picux/storage/agents.py +50 -0
  96. picux/storage/cases.py +440 -0
  97. picux/storage/channels.py +476 -0
  98. picux/storage/connectors.py +411 -0
  99. picux/storage/envelopes.py +137 -0
  100. picux/storage/escrows.py +168 -0
  101. picux/storage/events.py +989 -0
  102. picux/storage/keyspace.py +60 -0
  103. picux/storage/mandates.py +107 -0
  104. picux/storage/portals.py +222 -0
  105. picux/storage/postgres.py +2049 -0
  106. picux/storage/providers.py +148 -0
  107. picux/storage/proxy.py +231 -0
  108. picux/storage/receipts.py +131 -0
  109. picux/storage/signals.py +147 -0
  110. picux/storage/tasks.py +179 -0
  111. picux/tools/__init__.py +11 -0
  112. picux/tools/shared.py +2048 -0
  113. picux/verification/__init__.py +5 -0
  114. picux/verification/rollout.py +183 -0
  115. picux/workflows/__init__.py +5 -0
  116. picux/workflows/templates.py +74 -0
@@ -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
+ ]
@@ -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
+ ]