pi-harness-runtime 1.1.161 → 1.1.162

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 (109) hide show
  1. package/harness/telegram-auth.ts +150 -0
  2. package/harness/telegram-content-filter.ts +223 -0
  3. package/package.json +1 -1
  4. package/packages/a2a-adapter/package.json +1 -1
  5. package/packages/agent-policy/package.json +1 -1
  6. package/packages/architecture-generator/package.json +1 -1
  7. package/packages/auth/package.json +1 -1
  8. package/packages/autonomous-refactor/package.json +1 -1
  9. package/packages/autonomous-runtime/package.json +1 -1
  10. package/packages/cache-strategy/package.json +1 -1
  11. package/packages/capability-registry/package.json +1 -1
  12. package/packages/checkpoint/package.json +1 -1
  13. package/packages/cli-plugin-sdk/package.json +1 -1
  14. package/packages/clipboard/package.json +1 -1
  15. package/packages/clipboard-plugin/package.json +1 -1
  16. package/packages/code-generation/package.json +1 -1
  17. package/packages/code-review/package.json +1 -1
  18. package/packages/codex-adapter/package.json +1 -1
  19. package/packages/codex-watcher/package.json +1 -1
  20. package/packages/config-capture/package.json +1 -1
  21. package/packages/context-compiler/package.json +1 -1
  22. package/packages/context-discovery/package.json +1 -1
  23. package/packages/context-manager/package.json +1 -1
  24. package/packages/cookie-sanitizer/package.json +1 -1
  25. package/packages/cost-optimizer/package.json +1 -1
  26. package/packages/dependency-analyzer/package.json +1 -1
  27. package/packages/django-plugin/package.json +1 -1
  28. package/packages/doc-generator/package.json +1 -1
  29. package/packages/evaluation-engine/package.json +1 -1
  30. package/packages/evaluation-runner/package.json +1 -1
  31. package/packages/event-bus/package.json +1 -1
  32. package/packages/event-store/package.json +1 -1
  33. package/packages/experience-replay/package.json +1 -1
  34. package/packages/feedback-collector/package.json +1 -1
  35. package/packages/file-copy-helper/package.json +1 -1
  36. package/packages/framework-detector/package.json +1 -1
  37. package/packages/framework-plugin-sdk/package.json +1 -1
  38. package/packages/frappe-plugin/package.json +1 -1
  39. package/packages/generic-web-plugin/package.json +1 -1
  40. package/packages/health-monitor/package.json +1 -1
  41. package/packages/intent-analyzer/package.json +1 -1
  42. package/packages/jev-judge/package.json +1 -1
  43. package/packages/knowledge-graph/package.json +1 -1
  44. package/packages/knowledge-retrieval/package.json +1 -1
  45. package/packages/laravel-plugin/package.json +1 -1
  46. package/packages/learning-engine/package.json +1 -1
  47. package/packages/mcp-adapter/package.json +1 -1
  48. package/packages/memory-engine/package.json +1 -1
  49. package/packages/milestone-manager/package.json +1 -1
  50. package/packages/model-registry/package.json +1 -1
  51. package/packages/nextjs-plugin/package.json +1 -1
  52. package/packages/notification/dist/adapters/telegram-adapter.d.ts.map +1 -1
  53. package/packages/notification/dist/adapters/telegram-adapter.js +17 -12
  54. package/packages/notification/dist/adapters/telegram-adapter.js.map +1 -1
  55. package/packages/notification/dist/mask-secrets.d.ts.map +1 -1
  56. package/packages/notification/dist/mask-secrets.js +9 -0
  57. package/packages/notification/dist/mask-secrets.js.map +1 -1
  58. package/packages/notification/package.json +1 -1
  59. package/packages/notification/src/adapters/telegram-adapter.ts +19 -12
  60. package/packages/notification/src/mask-secrets.ts +11 -1
  61. package/packages/observability/package.json +1 -1
  62. package/packages/okf-indexer/package.json +1 -1
  63. package/packages/paperclip-integration/package.json +1 -1
  64. package/packages/performance-optimizer/package.json +1 -1
  65. package/packages/privilege-broker/package.json +1 -1
  66. package/packages/project-analyzer/package.json +1 -1
  67. package/packages/project-bootstrap/package.json +1 -1
  68. package/packages/projection-engine/package.json +1 -1
  69. package/packages/prompt-compiler/package.json +1 -1
  70. package/packages/prompt-versioning/package.json +1 -1
  71. package/packages/provider-adapter-sdk/package.json +1 -1
  72. package/packages/provider-router/package.json +1 -1
  73. package/packages/provider-selector/package.json +1 -1
  74. package/packages/providers/package.json +1 -1
  75. package/packages/qdrant-skills/package.json +1 -1
  76. package/packages/quota-manager/package.json +1 -1
  77. package/packages/rate-limiter/package.json +1 -1
  78. package/packages/react-vite-plugin/package.json +1 -1
  79. package/packages/release-manager/package.json +1 -1
  80. package/packages/requirement-compiler/package.json +1 -1
  81. package/packages/runtime/package.json +1 -1
  82. package/packages/scheduler/package.json +1 -1
  83. package/packages/scheduler-adapter/package.json +1 -1
  84. package/packages/session/package.json +1 -1
  85. package/packages/session-api/package.json +1 -1
  86. package/packages/session-export/package.json +1 -1
  87. package/packages/shared-context/package.json +1 -1
  88. package/packages/skill-mcp-client/package.json +1 -1
  89. package/packages/skill-registry/package.json +1 -1
  90. package/packages/skills/package.json +1 -1
  91. package/packages/sprint-planner/package.json +1 -1
  92. package/packages/subscription-engine/package.json +1 -1
  93. package/packages/task-compiler/package.json +1 -1
  94. package/packages/tencentdb-memory/package.json +1 -1
  95. package/packages/tencentdb-sync/package.json +1 -1
  96. package/packages/test-data-generator/package.json +1 -1
  97. package/packages/test-generator/package.json +1 -1
  98. package/packages/todo-bd-sync/package.json +1 -1
  99. package/packages/token-estimation/package.json +1 -1
  100. package/packages/token-optimizer/package.json +1 -1
  101. package/packages/trajectory/package.json +1 -1
  102. package/packages/tui/package.json +1 -1
  103. package/packages/types/package.json +1 -1
  104. package/packages/workflow-events/package.json +1 -1
  105. package/packages/workspace-scanner/package.json +1 -1
  106. package/packages/worktree/package.json +1 -1
  107. package/packages/write-review/package.json +1 -1
  108. package/scripts/telegram-webhook-server.ts +85 -6
  109. package/scripts/tsconfig.json +9 -0
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Telegram Authorization Module
3
+ *
4
+ * Validates Telegram user access from multiple sources:
5
+ * - Environment variable (TELEGRAM_ALLOWED_USERS)
6
+ * - Key file (~/.pi-harness-runtime/keys/telegram-allowed-users.txt)
7
+ * - Legacy chat ID file (~/.pi-harness-runtime/keys/telegram-chat-id.txt)
8
+ * - Infisical (future)
9
+ *
10
+ * Priority: Environment > Key file > Legacy chat ID file
11
+ */
12
+
13
+ import { existsSync, readFileSync } from "node:fs";
14
+ import { join } from "node:path";
15
+ import { homedir } from "node:os";
16
+
17
+ const KEYS_DIR = join(homedir(), ".pi-harness-runtime", "keys");
18
+
19
+ /**
20
+ * Parse comma-separated user IDs
21
+ */
22
+ function parseUserIds(content: string): Set<number> {
23
+ const ids = new Set<number>();
24
+ const parts = content.split(",").map(s => s.trim()).filter(Boolean);
25
+
26
+ for (const part of parts) {
27
+ const num = parseInt(part, 10);
28
+ if (!isNaN(num) && num > 0) {
29
+ ids.add(num);
30
+ }
31
+ }
32
+
33
+ return ids;
34
+ }
35
+
36
+ /**
37
+ * Load allowed users from environment variable
38
+ */
39
+ function loadFromEnv(): Set<number> | null {
40
+ const envValue = process.env.TELEGRAM_ALLOWED_USERS;
41
+ if (!envValue) return null;
42
+
43
+ return parseUserIds(envValue);
44
+ }
45
+
46
+ /**
47
+ * Load allowed users from key file
48
+ */
49
+ function loadFromKeyFile(filename: string): Set<number> | null {
50
+ const filePath = join(KEYS_DIR, filename);
51
+ if (!existsSync(filePath)) return null;
52
+
53
+ try {
54
+ const content = readFileSync(filePath, "utf8").trim();
55
+ if (!content) return null;
56
+ return parseUserIds(content);
57
+ } catch {
58
+ return null;
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Get allowed Telegram user IDs from all sources
64
+ *
65
+ * Priority:
66
+ * 1. TELEGRAM_ALLOWED_USERS environment variable
67
+ * 2. telegram-allowed-users.txt key file
68
+ * 3. telegram-chat-id.txt (legacy, single user)
69
+ */
70
+ export function getAllowedUserIds(): Set<number> {
71
+ // 1. Check environment variable first (highest priority)
72
+ const fromEnv = loadFromEnv();
73
+ if (fromEnv && fromEnv.size > 0) {
74
+ return fromEnv;
75
+ }
76
+
77
+ // 2. Check dedicated allowed users file
78
+ const fromKeyFile = loadFromKeyFile("telegram-allowed-users.txt");
79
+ if (fromKeyFile && fromKeyFile.size > 0) {
80
+ return fromKeyFile;
81
+ }
82
+
83
+ // 3. Check legacy chat ID file (single user)
84
+ const fromLegacy = loadFromKeyFile("telegram-chat-id.txt");
85
+ if (fromLegacy && fromLegacy.size > 0) {
86
+ return fromLegacy;
87
+ }
88
+
89
+ // No allowed users configured
90
+ return new Set();
91
+ }
92
+
93
+ /**
94
+ * Check if a Telegram user ID is authorized
95
+ */
96
+ export function isAuthorizedUser(userId: number): boolean {
97
+ const allowed = getAllowedUserIds();
98
+ // If no allowlist is configured, deny by default (fail closed)
99
+ if (allowed.size === 0) {
100
+ return false;
101
+ }
102
+ return allowed.has(userId);
103
+ }
104
+
105
+ /**
106
+ * Validate callback query sender
107
+ * Returns true if authorized, false if unauthorized
108
+ */
109
+ export function validateSender(senderId: number): {
110
+ authorized: boolean;
111
+ reason?: string;
112
+ } {
113
+ if (isAuthorizedUser(senderId)) {
114
+ return { authorized: true };
115
+ }
116
+
117
+ // Fail closed - deny unauthorized users
118
+ return {
119
+ authorized: false,
120
+ reason: "unauthorized_user",
121
+ };
122
+ }
123
+
124
+ /**
125
+ * Get allowlist source for diagnostics
126
+ */
127
+ export function getAllowlistSource(): string {
128
+ if (process.env.TELEGRAM_ALLOWED_USERS) {
129
+ return "environment";
130
+ }
131
+
132
+ const allowedPath = join(KEYS_DIR, "telegram-allowed-users.txt");
133
+ if (existsSync(allowedPath)) {
134
+ return "key_file:telegram-allowed-users.txt";
135
+ }
136
+
137
+ const legacyPath = join(KEYS_DIR, "telegram-chat-id.txt");
138
+ if (existsSync(legacyPath)) {
139
+ return "legacy:telegram-chat-id.txt";
140
+ }
141
+
142
+ return "none";
143
+ }
144
+
145
+ /**
146
+ * Get count of allowed users (for diagnostics, not values)
147
+ */
148
+ export function getAllowedUserCount(): number {
149
+ return getAllowedUserIds().size;
150
+ }
@@ -0,0 +1,223 @@
1
+ /**
2
+ * Telegram Content Filter — Jev-Powered Sensitive Content Detection
3
+ *
4
+ * Before sending to Telegram, Jev analyzes the content to determine
5
+ * if it contains sensitive credentials that should NOT be transmitted.
6
+ *
7
+ * If Jev is unavailable or returns BLOCK, the message is:
8
+ * - Not sent to Telegram
9
+ * - Logged with safe metadata (no secrets)
10
+ * - Optionally redirected to secure alternative (TUI only)
11
+ */
12
+
13
+ import type { NotificationPayload } from "../packages/notification/dist/types.js";
14
+ import { maskString } from "../packages/notification/dist/mask-secrets.js";
15
+ import { getKey } from "./key-loader.js";
16
+
17
+ /**
18
+ * Jev judgment result for content filtering
19
+ */
20
+ export type ContentJudgment = "SEND" | "BLOCK" | "UNKNOWN";
21
+
22
+ /**
23
+ * Result of content filtering decision
24
+ */
25
+ export interface FilterResult {
26
+ /** Whether to send to Telegram */
27
+ shouldSend: boolean;
28
+ /** Jev's judgment */
29
+ judgment: ContentJudgment;
30
+ /** Reason for blocking (if blocked) */
31
+ reason?: string;
32
+ /** Confidence score (0-1) */
33
+ confidence?: number;
34
+ }
35
+
36
+ /**
37
+ * Extract text content from notification payload
38
+ */
39
+ function extractContent(payload: NotificationPayload): string {
40
+ const parts: string[] = [];
41
+
42
+ // Title
43
+ if (payload.title) {
44
+ parts.push(payload.title);
45
+ }
46
+
47
+ // Main message
48
+ if (payload.message) {
49
+ parts.push(payload.message);
50
+ }
51
+
52
+ // Details
53
+ if (payload.details) {
54
+ for (const [key, value] of Object.entries(payload.details)) {
55
+ if (typeof value === "string" && value) {
56
+ parts.push(value);
57
+ }
58
+ }
59
+ }
60
+
61
+ return parts.join("\n");
62
+ }
63
+
64
+ /**
65
+ * Simple heuristic check for obvious credentials (fallback when Jev unavailable)
66
+ */
67
+ function heuristicCheck(content: string): FilterResult {
68
+ // Check for common credential patterns
69
+ const sensitivePatterns = [
70
+ /\d+:[-A-Za-z0-9_]{35,}/, // Telegram bot token
71
+ /sk-[a-zA-Z0-9]{20,}/, // OpenAI-style keys
72
+ /[a-zA-Z0-9_-]{32,}/, // Long API keys
73
+ /Bearer\s+[a-zA-Z0-9_-]{20,}/i, // Bearer tokens
74
+ /(api[_-]?key|secret|token|password|credential)[=:\s]+[^\s]{16,}/i,
75
+ /-----BEGIN\s+(RSA|EC|OPENSSH|DSA)\s+PRIVATE\s+KEY-----/,
76
+ /infisical[_-]?(client[_-])?(secret|id)/i,
77
+ ];
78
+
79
+ let matchFound = false;
80
+ let matchType = "";
81
+
82
+ for (const pattern of sensitivePatterns) {
83
+ if (pattern.test(content)) {
84
+ matchFound = true;
85
+ // Determine what type of credential was found
86
+ if (/\d+:[-A-Za-z0-9_]{35,}/.test(content)) {
87
+ matchType = "telegram_bot_token";
88
+ } else if (/sk-[a-zA-Z0-9]{20,}/.test(content)) {
89
+ matchType = "openai_style_key";
90
+ } else if (/-----BEGIN\s+(RSA|EC|OPENSSH|DSA)\s+PRIVATE\s+KEY-----/.test(content)) {
91
+ matchType = "private_key";
92
+ } else if (/infisical/i.test(content)) {
93
+ matchType = "infisical_credential";
94
+ } else {
95
+ matchType = "api_key_or_secret";
96
+ }
97
+ break;
98
+ }
99
+ }
100
+
101
+ if (matchFound) {
102
+ return {
103
+ shouldSend: false,
104
+ judgment: "BLOCK",
105
+ reason: `Sensitive content detected: ${matchType}`,
106
+ confidence: 0.95,
107
+ };
108
+ }
109
+
110
+ return {
111
+ shouldSend: true,
112
+ judgment: "SEND",
113
+ confidence: 0.9,
114
+ };
115
+ }
116
+
117
+ /**
118
+ * Call Jev to analyze content for sensitive credentials
119
+ */
120
+ async function callJev(content: string): Promise<FilterResult | null> {
121
+ const apiKey = getKey("typesafe-api-key") || process.env.TYPESAFE_API_KEY;
122
+
123
+ if (!apiKey) {
124
+ return null; // Jev not available
125
+ }
126
+
127
+ try {
128
+ const response = await fetch("https://api.typesafe.ai/v1/jev/decide", {
129
+ method: "POST",
130
+ headers: {
131
+ "Content-Type": "application/json",
132
+ Authorization: `Bearer ${apiKey}`,
133
+ },
134
+ body: JSON.stringify({
135
+ question:
136
+ "Does this message contain any API keys, tokens, secrets, passwords, or other sensitive credentials that should NOT be sent to a third-party service like Telegram? Answer only YES or NO.",
137
+ context: {
138
+ message: content,
139
+ action: "telegram_notification",
140
+ security_level: "high",
141
+ },
142
+ }),
143
+ });
144
+
145
+ if (!response.ok) {
146
+ return null;
147
+ }
148
+
149
+ const data = (await response.json()) as {
150
+ decision?: string;
151
+ confidence?: number;
152
+ reasoning?: string;
153
+ };
154
+
155
+ const decision = data.decision?.toUpperCase() ?? "UNKNOWN";
156
+ const isSensitive = decision === "YES" || decision === "BLOCK";
157
+
158
+ return {
159
+ shouldSend: !isSensitive,
160
+ judgment: isSensitive ? "BLOCK" : "SEND",
161
+ reason: data.reasoning,
162
+ confidence: data.confidence,
163
+ };
164
+ } catch {
165
+ return null;
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Filter notification content before sending to Telegram
171
+ *
172
+ * @param payload - The notification payload
173
+ * @returns Filter result with decision
174
+ */
175
+ export async function filterTelegramContent(
176
+ payload: NotificationPayload,
177
+ ): Promise<FilterResult> {
178
+ // Extract content to analyze
179
+ const content = extractContent(payload);
180
+
181
+ // First, run heuristic check (always available)
182
+ const heuristicResult = heuristicCheck(content);
183
+ if (heuristicResult.judgment === "BLOCK") {
184
+ logFilterDecision("BLOCK", heuristicResult.reason ?? "Heuristic match", payload.jobId);
185
+ return heuristicResult;
186
+ }
187
+
188
+ // Try Jev if available
189
+ const jevResult = await callJev(content);
190
+ if (jevResult) {
191
+ if (jevResult.judgment === "BLOCK") {
192
+ logFilterDecision("BLOCK", jevResult.reason ?? "Jev judgment", payload.jobId);
193
+ }
194
+ return jevResult;
195
+ }
196
+
197
+ // Jev unavailable - use heuristic result
198
+ return heuristicResult;
199
+ }
200
+
201
+ /**
202
+ * Log filter decision securely (no content, just metadata)
203
+ */
204
+ function logFilterDecision(
205
+ decision: ContentJudgment,
206
+ reason: string,
207
+ jobId: string,
208
+ ): void {
209
+ console.warn(
210
+ `[TelegramFilter] ${decision} job=${jobId} reason=${reason} channel=telegram`,
211
+ );
212
+ }
213
+
214
+ /**
215
+ * Get safe notification version (masked) for logging
216
+ */
217
+ export function getSafeNotificationLog(payload: NotificationPayload): string {
218
+ const maskedTitle = maskString(payload.title);
219
+ const maskedMessage = maskString(payload.message);
220
+ const maskedJobId = maskString(payload.jobId);
221
+
222
+ return `event=${payload.event} job=${maskedJobId} title=${maskedTitle} message_len=${maskedMessage.length}`;
223
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-harness-runtime",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "description": "[BETA] Codex-style /usage status + autonomous coding harness for pi. Not production ready — expect breaking changes.",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/a2a-adapter",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "type": "module",
5
5
  "description": "Google Agent-to-Agent (A2A) protocol adapter for pi-harness",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/agent-policy",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "description": "Agent policy runtime for pi-harness - enforces mandatory rule delivery and mutation gating",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/architecture-generator",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "description": "Generate ADR and Mermaid diagrams from project analysis",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/auth",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "description": "pi-harness-runtime — auth",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/autonomous-refactor",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "type": "module",
5
5
  "description": "Autonomous refactoring engine",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/autonomous-runtime",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "description": "Autonomous Operations Runtime — task inbox, lease management, and worker lifecycle (RFC-0101)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/cache-strategy",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "type": "module",
5
5
  "description": "Smart caching with TTL and invalidation strategies (RFC-0022)",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/capability-registry",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "description": "Capability Registry for pi-harness-runtime — tracks model capabilities and enables capability-based routing",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/checkpoint",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "description": "Enhanced checkpoint system with incremental snapshots, diff-based storage, and recovery strategies",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/cli-plugin-sdk",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "type": "module",
5
5
  "description": "CLI Plugin SDK for pi-harness — install, list, remove, update, invoke plugins",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/clipboard",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/clipboard-plugin",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/code-generation",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "description": "Code generation pipeline for pi-harness-runtime",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/code-review",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "description": "Automated code review engine for pi-harness-runtime",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/codex-adapter",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "type": "module",
5
5
  "description": "OpenAI Codex provider adapter for pi-harness",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/codex-watcher",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "description": "Watches Codex CLI sessions and emits visible messages for PING-PONG monitoring",
5
5
  "type": "module",
6
6
  "main": "./dist/src/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moocoding/config-capture",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "description": "Auto-capture API-fetched configuration values to AGENTS.md",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/context-compiler",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "description": "Bounded context selection engine for pi-harness-runtime",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/context-discovery",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/context-manager",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "description": "Context Window Manager — prevents model context overflow via compaction and resume prompts (RFC-0010)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/cookie-sanitizer",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "description": "pi-harness-runtime — cookie sanitizer (provider-quota cookie file normaliser)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/cost-optimizer",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "description": "Cost Optimizer for pi-harness-runtime — budget tracking, forecasting, and model selection optimization",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/dependency-analyzer",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/django-plugin",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "description": "Django framework analysis — models, management commands, settings",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/doc-generator",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "description": "Auto-Doc Generator — generate documentation from source code (RFC-0014)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/evaluation-engine",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "description": "Evaluation engine for pi-harness runtime (RFC-0057)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/evaluation-runner",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "type": "module",
5
5
  "description": "Framework-agnostic evaluation framework for AI outputs (RFC-0020)",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/event-bus",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/event-store",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/experience-replay",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "description": "Experience replay for debugging and reproducibility (RFC-0059)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/feedback-collector",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "type": "module",
5
5
  "description": "Collect and aggregate human/automated feedback (RFC-0021)",
6
6
  "main": "dist/index.js",