pi-harness-runtime 1.1.395 → 1.1.397

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 (210) hide show
  1. package/AGENTS.md +64 -8
  2. package/package.json +1 -1
  3. package/packages/a2a-adapter/package.json +1 -1
  4. package/packages/agent-policy/package.json +1 -1
  5. package/packages/architecture-generator/package.json +1 -1
  6. package/packages/auth/package.json +1 -1
  7. package/packages/autonomous-refactor/package.json +1 -1
  8. package/packages/autonomous-runtime/package.json +1 -1
  9. package/packages/cache-strategy/package.json +1 -1
  10. package/packages/capability-registry/package.json +1 -1
  11. package/packages/checkpoint/package.json +1 -1
  12. package/packages/cli-plugin-sdk/package.json +1 -1
  13. package/packages/clipboard/package.json +1 -1
  14. package/packages/clipboard-plugin/package.json +1 -1
  15. package/packages/code-generation/package.json +1 -1
  16. package/packages/code-review/package.json +1 -1
  17. package/packages/codex-adapter/package.json +1 -1
  18. package/packages/codex-watcher/package.json +1 -1
  19. package/packages/config-capture/package.json +1 -1
  20. package/packages/connection-runtime/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/contracts/dist/workspace-env-format.d.ts +24 -0
  25. package/packages/contracts/dist/workspace-env-format.js +41 -1
  26. package/packages/contracts/dist/workspace-env.js +7 -4
  27. package/packages/contracts/package.json +1 -1
  28. package/packages/contracts/src/workspace-env-format.ts +38 -1
  29. package/packages/contracts/src/workspace-env.ts +8 -3
  30. package/packages/contracts/test/workspace-env.test.ts +48 -0
  31. package/packages/cookie-sanitizer/package.json +1 -1
  32. package/packages/cost-optimizer/package.json +1 -1
  33. package/packages/dependency-analyzer/package.json +1 -1
  34. package/packages/django-plugin/package.json +1 -1
  35. package/packages/doc-generator/package.json +1 -1
  36. package/packages/durable-review/package.json +1 -1
  37. package/packages/e2e-tester/package.json +1 -1
  38. package/packages/evaluation-engine/package.json +1 -1
  39. package/packages/evaluation-runner/package.json +1 -1
  40. package/packages/event-bus/package.json +1 -1
  41. package/packages/event-sink/package.json +1 -1
  42. package/packages/event-store/package.json +1 -1
  43. package/packages/experience-replay/package.json +1 -1
  44. package/packages/feedback-collector/package.json +1 -1
  45. package/packages/file-copy-helper/package.json +1 -1
  46. package/packages/framework-detector/package.json +1 -1
  47. package/packages/framework-plugin-sdk/package.json +1 -1
  48. package/packages/frappe-plugin/package.json +1 -1
  49. package/packages/generic-web-plugin/package.json +1 -1
  50. package/packages/health-monitor/package.json +1 -1
  51. package/packages/intent-analyzer/package.json +1 -1
  52. package/packages/jev-judge/package.json +1 -1
  53. package/packages/knowledge-graph/package.json +1 -1
  54. package/packages/knowledge-retrieval/package.json +1 -1
  55. package/packages/laravel-plugin/package.json +1 -1
  56. package/packages/learning-engine/package.json +1 -1
  57. package/packages/logging/README.md +41 -6
  58. package/packages/logging/dist/classification.d.ts +65 -0
  59. package/packages/logging/dist/classification.d.ts.map +1 -0
  60. package/packages/logging/dist/classification.js +155 -0
  61. package/packages/logging/dist/classification.js.map +1 -0
  62. package/packages/logging/dist/config.d.ts +9 -0
  63. package/packages/logging/dist/config.d.ts.map +1 -1
  64. package/packages/logging/dist/config.js +40 -3
  65. package/packages/logging/dist/config.js.map +1 -1
  66. package/packages/logging/dist/index.d.ts +9 -1
  67. package/packages/logging/dist/index.d.ts.map +1 -1
  68. package/packages/logging/dist/index.js +10 -1
  69. package/packages/logging/dist/index.js.map +1 -1
  70. package/packages/logging/dist/ingest/schema.d.ts +60 -0
  71. package/packages/logging/dist/ingest/schema.d.ts.map +1 -0
  72. package/packages/logging/dist/ingest/schema.js +245 -0
  73. package/packages/logging/dist/ingest/schema.js.map +1 -0
  74. package/packages/logging/dist/installation.d.ts +32 -0
  75. package/packages/logging/dist/installation.d.ts.map +1 -0
  76. package/packages/logging/dist/installation.js +64 -0
  77. package/packages/logging/dist/installation.js.map +1 -0
  78. package/packages/logging/dist/sensitive-keys.d.ts +12 -0
  79. package/packages/logging/dist/sensitive-keys.d.ts.map +1 -0
  80. package/packages/logging/dist/sensitive-keys.js +39 -0
  81. package/packages/logging/dist/sensitive-keys.js.map +1 -0
  82. package/packages/logging/dist/server/credentials.d.ts +85 -0
  83. package/packages/logging/dist/server/credentials.d.ts.map +1 -0
  84. package/packages/logging/dist/server/credentials.js +147 -0
  85. package/packages/logging/dist/server/credentials.js.map +1 -0
  86. package/packages/logging/dist/server/http.d.ts +36 -0
  87. package/packages/logging/dist/server/http.d.ts.map +1 -0
  88. package/packages/logging/dist/server/http.js +139 -0
  89. package/packages/logging/dist/server/http.js.map +1 -0
  90. package/packages/logging/dist/server/index-store.d.ts +95 -0
  91. package/packages/logging/dist/server/index-store.d.ts.map +1 -0
  92. package/packages/logging/dist/server/index-store.js +190 -0
  93. package/packages/logging/dist/server/index-store.js.map +1 -0
  94. package/packages/logging/dist/server/index.d.ts +22 -0
  95. package/packages/logging/dist/server/index.d.ts.map +1 -0
  96. package/packages/logging/dist/server/index.js +15 -0
  97. package/packages/logging/dist/server/index.js.map +1 -0
  98. package/packages/logging/dist/server/keys.d.ts +22 -0
  99. package/packages/logging/dist/server/keys.d.ts.map +1 -0
  100. package/packages/logging/dist/server/keys.js +24 -0
  101. package/packages/logging/dist/server/keys.js.map +1 -0
  102. package/packages/logging/dist/server/outbox-worker.d.ts +55 -0
  103. package/packages/logging/dist/server/outbox-worker.d.ts.map +1 -0
  104. package/packages/logging/dist/server/outbox-worker.js +95 -0
  105. package/packages/logging/dist/server/outbox-worker.js.map +1 -0
  106. package/packages/logging/dist/server/outbox.d.ts +112 -0
  107. package/packages/logging/dist/server/outbox.d.ts.map +1 -0
  108. package/packages/logging/dist/server/outbox.js +247 -0
  109. package/packages/logging/dist/server/outbox.js.map +1 -0
  110. package/packages/logging/dist/server/service.d.ts +83 -0
  111. package/packages/logging/dist/server/service.d.ts.map +1 -0
  112. package/packages/logging/dist/server/service.js +144 -0
  113. package/packages/logging/dist/server/service.js.map +1 -0
  114. package/packages/logging/dist/shipper.d.ts +20 -4
  115. package/packages/logging/dist/shipper.d.ts.map +1 -1
  116. package/packages/logging/dist/shipper.js +31 -5
  117. package/packages/logging/dist/shipper.js.map +1 -1
  118. package/packages/logging/dist/singleton.d.ts.map +1 -1
  119. package/packages/logging/dist/singleton.js +3 -0
  120. package/packages/logging/dist/singleton.js.map +1 -1
  121. package/packages/logging/dist/types.d.ts +28 -1
  122. package/packages/logging/dist/types.d.ts.map +1 -1
  123. package/packages/logging/dist/types.js +8 -0
  124. package/packages/logging/dist/types.js.map +1 -1
  125. package/packages/logging/package.json +1 -1
  126. package/packages/logging/src/classification.ts +175 -0
  127. package/packages/logging/src/config.ts +60 -3
  128. package/packages/logging/src/index.ts +45 -1
  129. package/packages/logging/src/ingest/schema.ts +295 -0
  130. package/packages/logging/src/installation.ts +76 -0
  131. package/packages/logging/src/sensitive-keys.ts +40 -0
  132. package/packages/logging/src/server/credentials.ts +198 -0
  133. package/packages/logging/src/server/http.ts +170 -0
  134. package/packages/logging/src/server/index-store.ts +242 -0
  135. package/packages/logging/src/server/index.ts +56 -0
  136. package/packages/logging/src/server/keys.ts +32 -0
  137. package/packages/logging/src/server/outbox-worker.ts +124 -0
  138. package/packages/logging/src/server/outbox.ts +316 -0
  139. package/packages/logging/src/server/service.ts +196 -0
  140. package/packages/logging/src/shipper.ts +54 -8
  141. package/packages/logging/src/singleton.ts +3 -0
  142. package/packages/logging/src/types.ts +29 -1
  143. package/packages/logging/test/classification.test.ts +137 -0
  144. package/packages/logging/test/identity-transport.test.ts +197 -0
  145. package/packages/logging/test/ingest-schema.test.ts +184 -0
  146. package/packages/logging/test/integration.test.ts +9 -4
  147. package/packages/logging/test/log-http.test.ts +246 -0
  148. package/packages/logging/test/server.test.ts +444 -0
  149. package/packages/logging/test/shipper.test.ts +11 -11
  150. package/packages/logging/test/spool.test.ts +4 -1
  151. package/packages/mcp-adapter/package.json +1 -1
  152. package/packages/memory-engine/package.json +1 -1
  153. package/packages/milestone-manager/package.json +1 -1
  154. package/packages/model-registry/package.json +1 -1
  155. package/packages/nextjs-plugin/package.json +1 -1
  156. package/packages/notification/package.json +1 -1
  157. package/packages/observability/package.json +1 -1
  158. package/packages/okf-indexer/package.json +1 -1
  159. package/packages/paperclip-integration/package.json +1 -1
  160. package/packages/performance-optimizer/package.json +1 -1
  161. package/packages/permission-mode/package.json +1 -1
  162. package/packages/privilege-broker/package.json +1 -1
  163. package/packages/project-analyzer/package.json +1 -1
  164. package/packages/project-bootstrap/package.json +1 -1
  165. package/packages/projection-engine/package.json +1 -1
  166. package/packages/prompt-compiler/package.json +1 -1
  167. package/packages/prompt-versioning/package.json +1 -1
  168. package/packages/provider-adapter-sdk/package.json +1 -1
  169. package/packages/provider-router/package.json +1 -1
  170. package/packages/provider-selector/package.json +1 -1
  171. package/packages/providers/package.json +1 -1
  172. package/packages/qdrant-skills/package.json +1 -1
  173. package/packages/quota-manager/package.json +1 -1
  174. package/packages/rate-limiter/package.json +1 -1
  175. package/packages/react-vite-plugin/package.json +1 -1
  176. package/packages/relay/package.json +1 -1
  177. package/packages/release-manager/package.json +1 -1
  178. package/packages/requirement-compiler/package.json +1 -1
  179. package/packages/runtime/package.json +1 -1
  180. package/packages/scheduler/package.json +1 -1
  181. package/packages/scheduler-adapter/package.json +1 -1
  182. package/packages/session/package.json +1 -1
  183. package/packages/session-api/package.json +1 -1
  184. package/packages/session-export/package.json +1 -1
  185. package/packages/shared-context/package.json +1 -1
  186. package/packages/skill-mcp-client/package.json +1 -1
  187. package/packages/skill-registry/package.json +1 -1
  188. package/packages/skills/package.json +1 -1
  189. package/packages/sprint-planner/package.json +1 -1
  190. package/packages/subscription-engine/package.json +1 -1
  191. package/packages/task-compiler/package.json +1 -1
  192. package/packages/telegram/package.json +1 -1
  193. package/packages/tencentdb-memory/package.json +1 -1
  194. package/packages/tencentdb-sync/package.json +1 -1
  195. package/packages/test-data-generator/package.json +1 -1
  196. package/packages/test-generator/package.json +1 -1
  197. package/packages/todo-bd-sync/package.json +1 -1
  198. package/packages/token-estimation/package.json +1 -1
  199. package/packages/token-optimizer/package.json +1 -1
  200. package/packages/trajectory/package.json +1 -1
  201. package/packages/tui/package.json +1 -1
  202. package/packages/types/package.json +1 -1
  203. package/packages/voice-api/package.json +1 -1
  204. package/packages/webmcp-tester/package.json +1 -1
  205. package/packages/wiki/package.json +1 -1
  206. package/packages/workflow-events/package.json +1 -1
  207. package/packages/workspace-scanner/package.json +1 -1
  208. package/packages/worktree/package.json +1 -1
  209. package/packages/write-review/package.json +1 -1
  210. package/scripts/unified-webhook-server.ts +86 -81
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/doc-generator",
3
- "version": "1.1.395",
3
+ "version": "1.1.397",
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": "@moocoding/durable-review",
3
- "version": "1.1.395",
3
+ "version": "1.1.397",
4
4
  "description": "SQLite-backed durable reviewer using @earendil-works/pi-durable",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/e2e-tester",
3
- "version": "1.1.395",
3
+ "version": "1.1.397",
4
4
  "description": "WebMCP-powered E2E testing for pi-harness - natural language test scenarios",
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.395",
3
+ "version": "1.1.397",
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.395",
3
+ "version": "1.1.397",
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.395",
3
+ "version": "1.1.397",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/event-sink",
3
- "version": "1.1.395",
3
+ "version": "1.1.397",
4
4
  "type": "module",
5
5
  "description": "Atomic event sourcing with SQLite transactions for pi-harness",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/event-store",
3
- "version": "1.1.395",
3
+ "version": "1.1.397",
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.395",
3
+ "version": "1.1.397",
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.395",
3
+ "version": "1.1.397",
4
4
  "type": "module",
5
5
  "description": "Collect and aggregate human/automated feedback (RFC-0021)",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moocoding/file-copy-helper",
3
- "version": "1.1.395",
3
+ "version": "1.1.397",
4
4
  "description": "Injects cp/sudo cp rule when user asks to mimic/copy files",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/framework-detector",
3
- "version": "1.1.395",
3
+ "version": "1.1.397",
4
4
  "description": "Framework detection system for pi-harness-runtime",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/framework-plugin-sdk",
3
- "version": "1.1.395",
3
+ "version": "1.1.397",
4
4
  "description": "Framework plugin SDK for pi-harness-runtime",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/frappe-plugin",
3
- "version": "1.1.395",
3
+ "version": "1.1.397",
4
4
  "description": "Frappe/ERPNext framework analysis — DocTypes, hooks, bench sites, site config",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/generic-web-plugin",
3
- "version": "1.1.395",
3
+ "version": "1.1.397",
4
4
  "description": "Generic web framework analysis — REST/GraphQL endpoints, OpenAPI, auth",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/health-monitor",
3
- "version": "1.1.395",
3
+ "version": "1.1.397",
4
4
  "type": "module",
5
5
  "description": "Health monitoring and auto-healing",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/intent-analyzer",
3
- "version": "1.1.395",
3
+ "version": "1.1.397",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/jev-judge",
3
- "version": "1.1.395",
3
+ "version": "1.1.397",
4
4
  "description": "Jev Judge - Structured decision model for agent routing, E2E testing, and automated decisions",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/knowledge-graph",
3
- "version": "1.1.395",
3
+ "version": "1.1.397",
4
4
  "description": "Knowledge Graph extraction and provenance linking for SKILL.md files",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/knowledge-retrieval",
3
- "version": "1.1.395",
3
+ "version": "1.1.397",
4
4
  "description": "Knowledge retrieval via TencentDB-Agent-Memory MCP (RFC-0105)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/laravel-plugin",
3
- "version": "1.1.395",
3
+ "version": "1.1.397",
4
4
  "description": "Laravel framework analysis — artisan commands, Eloquent models, Blade",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/learning-engine",
3
- "version": "1.1.395",
3
+ "version": "1.1.397",
4
4
  "description": "Learning engine for extracting lessons from runtime execution (RFC-0058)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -3,17 +3,26 @@
3
3
  Centralized structured application logging for pi-harness.
4
4
 
5
5
  ```text
6
- producer -> redact -> sample -> buffer -> R2 -> webhook -> local spool
6
+ client: producer -> classify -> redact -> sample -> buffer -> webhook -> local spool
7
+ server: POST /api/logs -> authenticate -> validate -> durable outbox -> 202
8
+ |
9
+ v
10
+ worker -> R2 -> done
7
11
  ```
8
12
 
13
+ - **Classification**: an event allowlist decides what may leave the machine. Prompts,
14
+ responses, command output and the catch-all `harness.log` mirror stay local.
9
15
  - **Redaction**: credential-looking keys, bearer tokens, JWTs and long token runs are
10
16
  replaced; strings are truncated and structures are depth limited.
11
17
  - **Sampling**: minimum level, a deterministic sample rate for `debug` records and a
12
18
  per source+event rate limit. Errors are never sampled away.
13
19
  - **Buffering**: bounded in-memory buffer; when it is full the least severe record is
14
20
  dropped and the drop is counted.
15
- - **Delivery**: transports are tried in order (R2, webhook). If all of them fail the
16
- batch is spooled to disk as NDJSON and retried on the next flush.
21
+ - **Delivery**: transports are a FALLBACK chain (the first success wins, the rest are
22
+ skipped - never a broadcast). If all of them fail the batch is spooled to disk as
23
+ NDJSON and retried on the next flush.
24
+ - **Durability**: the server only answers `202` after the batch is written to its
25
+ durable outbox. A background worker uploads it to R2 with a bounded backoff.
17
26
 
18
27
  ## Usage
19
28
 
@@ -21,17 +30,43 @@ producer -> redact -> sample -> buffer -> R2 -> webhook -> local spool
21
30
  import { centralInfo, centralWarn, initCentralLogging } from "./packages/logging/dist/index.js";
22
31
 
23
32
  initCentralLogging(); // reads the environment and the key files
24
- centralInfo("harness", "startup", "ready", { pid: process.pid });
33
+ centralInfo("harness.service-diagnostics", "service.check", "service is up", { durationMs: 3 });
25
34
  ```
26
35
 
36
+ The event name decides whether the record may be shipped: use an allowlisted shape
37
+ (`service.*`, `session.*`, `validation.*`, `harness.service-diagnostics.*`,
38
+ `harness.planner.decision`, `harness.glm-quota.quota`) or a `warn`/`error` level.
39
+
27
40
  ## Transports
28
41
 
29
42
  | Transport | Purpose |
30
43
  |-----------|---------|
31
- | `createR2Transport` | Cloudflare R2 (S3 API), gzipped NDJSON under a date prefix |
32
- | `createWebhookTransport` | HTTP POST to the unified webhook server (`/api/logs`) |
44
+ | `createWebhookTransport` | HTTP POST to the unified webhook server (`/api/logs`) - the client ingress point |
45
+ | `createR2Transport` | Cloudflare R2 (S3 API), gzipped NDJSON under a date prefix - normally used by the server, not by clients |
33
46
  | `LogSpool` | Local NDJSON fallback, rotated by size, with retention |
34
47
 
48
+ ## Server side
49
+
50
+ ```ts
51
+ import {
52
+ LogCredentialStore,
53
+ LogIndexStore,
54
+ LogIngestService,
55
+ LogOutbox,
56
+ LogOutboxWorker,
57
+ createLogHttpHandler,
58
+ } from "./packages/logging/dist/index.js";
59
+
60
+ const credentials = LogCredentialStore.load();
61
+ const outbox = new LogOutbox({ dir: `${home}/.pi-harness-runtime/logs/outbox` });
62
+ const index = new LogIndexStore({ dir: `${home}/.pi-harness-runtime/logs/index` });
63
+ const service = new LogIngestService({ credentials, outbox, index });
64
+ const handler = createLogHttpHandler({ service, outbox, index });
65
+ ```
66
+
67
+ The credential store decides whether the endpoint exists: without a credential every
68
+ write is refused (`503`). The tenant comes from the credential, never from the body.
69
+
35
70
  ## Configuration
36
71
 
37
72
  See the "Centralized Application Logging" section in the repository `AGENTS.md`.
@@ -0,0 +1,65 @@
1
+ /**
2
+ * What may leave the machine.
3
+ *
4
+ * The local log file keeps everything. The centralized archive keeps what an
5
+ * operator actually needs: service state, event codes, sanitized errors,
6
+ * durations and opaque identifiers.
7
+ *
8
+ * Two rules decide:
9
+ *
10
+ * 1. The event decides. A catch-all mirror of a local log line
11
+ * (`harness.log`) or anything that smells like a prompt, a response or
12
+ * command output never leaves the machine.
13
+ * 2. The payload decides. A message only travels when it looks like a
14
+ * sanitized summary: short, one line, no path and no URL with a query
15
+ * string. Fields with a private key name are dropped.
16
+ *
17
+ * The diagnostic mode (`PI_LOG_DIAGNOSTIC=1`) relaxes rule 2 for a user who
18
+ * explicitly asked for more, and nothing else.
19
+ */
20
+ import type { LogRecord } from "./types.js";
21
+ export interface ClassificationPolicy {
22
+ /** Events that may go remote. */
23
+ remoteEvents: RegExp[];
24
+ /** Events that never go remote, whatever the level is. */
25
+ localEvents: RegExp[];
26
+ /** Keep a message even when it does not look sanitized. */
27
+ allowRawMessages: boolean;
28
+ /** Maximum length of a message that is kept. */
29
+ maxMessageLength: number;
30
+ }
31
+ /**
32
+ * Events that stay local.
33
+ *
34
+ * `harness.log` is the mirror of the catch-all local log line - it carries
35
+ * whatever the harness printed, so it is never remote.
36
+ */
37
+ export declare const DEFAULT_LOCAL_EVENTS: RegExp[];
38
+ /**
39
+ * Events that may go remote.
40
+ *
41
+ * They are structured: a service state change, a session lifecycle event, a
42
+ * validation tier, a provider or quota event.
43
+ */
44
+ export declare const DEFAULT_REMOTE_EVENTS: RegExp[];
45
+ export declare const DEFAULT_CLASSIFICATION_POLICY: ClassificationPolicy;
46
+ /**
47
+ * True when a message looks like a sanitized summary and may travel.
48
+ */
49
+ export declare function isSanitizedMessage(message: string, policy: ClassificationPolicy): boolean;
50
+ /**
51
+ * Classify one record.
52
+ *
53
+ * "remote" means the record may be shipped; "local" means it must stay on
54
+ * the machine.
55
+ */
56
+ export declare function classifyRecord(record: LogRecord, policy?: ClassificationPolicy): "remote" | "local";
57
+ /**
58
+ * Build the version of a record that may leave the machine.
59
+ *
60
+ * Returns null when the record must stay local.
61
+ */
62
+ export declare function prepareRemoteRecord(record: LogRecord, policy?: ClassificationPolicy): LogRecord | null;
63
+ /** Keep only the records that may leave the machine. */
64
+ export declare function filterRemoteRecords(records: LogRecord[], policy?: ClassificationPolicy): LogRecord[];
65
+ //# sourceMappingURL=classification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classification.d.ts","sourceRoot":"","sources":["../src/classification.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,WAAW,oBAAoB;IACpC,iCAAiC;IACjC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,0DAA0D;IAC1D,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,2DAA2D;IAC3D,gBAAgB,EAAE,OAAO,CAAC;IAC1B,gDAAgD;IAChD,gBAAgB,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,EAAE,MAAM,EAUxC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,EAAE,MAAM,EAiBzC,CAAC;AAEF,eAAO,MAAM,6BAA6B,EAAE,oBAK3C,CAAC;AAKF;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAOzF;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC7B,MAAM,EAAE,SAAS,EACjB,MAAM,GAAE,oBAAoD,GAC1D,QAAQ,GAAG,OAAO,CAapB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAClC,MAAM,EAAE,SAAS,EACjB,MAAM,GAAE,oBAAoD,GAC1D,SAAS,GAAG,IAAI,CA8BlB;AAED,wDAAwD;AACxD,wBAAgB,mBAAmB,CAClC,OAAO,EAAE,SAAS,EAAE,EACpB,MAAM,GAAE,oBAAoD,GAC1D,SAAS,EAAE,CAOb"}
@@ -0,0 +1,155 @@
1
+ /**
2
+ * What may leave the machine.
3
+ *
4
+ * The local log file keeps everything. The centralized archive keeps what an
5
+ * operator actually needs: service state, event codes, sanitized errors,
6
+ * durations and opaque identifiers.
7
+ *
8
+ * Two rules decide:
9
+ *
10
+ * 1. The event decides. A catch-all mirror of a local log line
11
+ * (`harness.log`) or anything that smells like a prompt, a response or
12
+ * command output never leaves the machine.
13
+ * 2. The payload decides. A message only travels when it looks like a
14
+ * sanitized summary: short, one line, no path and no URL with a query
15
+ * string. Fields with a private key name are dropped.
16
+ *
17
+ * The diagnostic mode (`PI_LOG_DIAGNOSTIC=1`) relaxes rule 2 for a user who
18
+ * explicitly asked for more, and nothing else.
19
+ */
20
+ import { isLocalOnlyFieldKey } from "./sensitive-keys.js";
21
+ /**
22
+ * Events that stay local.
23
+ *
24
+ * `harness.log` is the mirror of the catch-all local log line - it carries
25
+ * whatever the harness printed, so it is never remote.
26
+ */
27
+ export const DEFAULT_LOCAL_EVENTS = [
28
+ /^harness\.log$/,
29
+ /prompt/i,
30
+ /response/i,
31
+ /transcript/i,
32
+ /output/i,
33
+ /command/i,
34
+ /content/i,
35
+ /message\.text/i,
36
+ /notification\.text/i,
37
+ ];
38
+ /**
39
+ * Events that may go remote.
40
+ *
41
+ * They are structured: a service state change, a session lifecycle event, a
42
+ * validation tier, a provider or quota event.
43
+ */
44
+ export const DEFAULT_REMOTE_EVENTS = [
45
+ /^harness\.service-diagnostics\./,
46
+ /^harness\.session\./,
47
+ /^harness\.startup\./,
48
+ /^harness\.shutdown\./,
49
+ /^harness\.planner\.decision$/,
50
+ /^harness\.glm-quota\.quota$/,
51
+ /^validation\./,
52
+ /^tier\./,
53
+ /^service\./,
54
+ /^session\./,
55
+ /^startup\./,
56
+ /^config\./,
57
+ /^provider\./,
58
+ /^quota\./,
59
+ /^logging\./,
60
+ /^jest\./,
61
+ ];
62
+ export const DEFAULT_CLASSIFICATION_POLICY = {
63
+ remoteEvents: DEFAULT_REMOTE_EVENTS,
64
+ localEvents: DEFAULT_LOCAL_EVENTS,
65
+ allowRawMessages: false,
66
+ maxMessageLength: 200,
67
+ };
68
+ const ABSOLUTE_PATH = /(?:^|\s)\/(?:[\w.-]+\/)+[\w.-]+/;
69
+ const URL_WITH_QUERY = /https?:\/\/\S+\?\S+/;
70
+ /**
71
+ * True when a message looks like a sanitized summary and may travel.
72
+ */
73
+ export function isSanitizedMessage(message, policy) {
74
+ if (policy.allowRawMessages)
75
+ return true;
76
+ if (message.length > policy.maxMessageLength)
77
+ return false;
78
+ if (message.includes("\n"))
79
+ return false;
80
+ if (ABSOLUTE_PATH.test(message))
81
+ return false;
82
+ if (URL_WITH_QUERY.test(message))
83
+ return false;
84
+ return true;
85
+ }
86
+ /**
87
+ * Classify one record.
88
+ *
89
+ * "remote" means the record may be shipped; "local" means it must stay on
90
+ * the machine.
91
+ */
92
+ export function classifyRecord(record, policy = DEFAULT_CLASSIFICATION_POLICY) {
93
+ for (const pattern of policy.localEvents) {
94
+ if (pattern.test(record.event))
95
+ return "local";
96
+ }
97
+ for (const pattern of policy.remoteEvents) {
98
+ if (pattern.test(record.event))
99
+ return "remote";
100
+ }
101
+ // Errors stay valuable even when the event is unknown: the message and
102
+ // the fields are sanitized anyway.
103
+ if (record.level === "warn" || record.level === "error")
104
+ return "remote";
105
+ // Unknown events are local by default: an allowlist is safer than a
106
+ // denylist.
107
+ return "local";
108
+ }
109
+ /**
110
+ * Build the version of a record that may leave the machine.
111
+ *
112
+ * Returns null when the record must stay local.
113
+ */
114
+ export function prepareRemoteRecord(record, policy = DEFAULT_CLASSIFICATION_POLICY) {
115
+ if (classifyRecord(record, policy) === "local")
116
+ return null;
117
+ const remote = {
118
+ ts: record.ts,
119
+ level: record.level,
120
+ source: record.source,
121
+ event: record.event,
122
+ };
123
+ if (record.message !== undefined && isSanitizedMessage(record.message, policy)) {
124
+ remote.message = record.message;
125
+ }
126
+ if (record.sessionId)
127
+ remote.sessionId = record.sessionId;
128
+ if (typeof record.durationMs === "number")
129
+ remote.durationMs = record.durationMs;
130
+ if (record.fields) {
131
+ const fields = {};
132
+ for (const [key, value] of Object.entries(record.fields)) {
133
+ if (isLocalOnlyFieldKey(key))
134
+ continue;
135
+ fields[key] = value;
136
+ }
137
+ if (Object.keys(fields).length > 0)
138
+ remote.fields = fields;
139
+ }
140
+ if (record.error) {
141
+ remote.error = { ...record.error };
142
+ }
143
+ return remote;
144
+ }
145
+ /** Keep only the records that may leave the machine. */
146
+ export function filterRemoteRecords(records, policy = DEFAULT_CLASSIFICATION_POLICY) {
147
+ const remote = [];
148
+ for (const record of records) {
149
+ const prepared = prepareRemoteRecord(record, policy);
150
+ if (prepared)
151
+ remote.push(prepared);
152
+ }
153
+ return remote;
154
+ }
155
+ //# sourceMappingURL=classification.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classification.js","sourceRoot":"","sources":["../src/classification.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,7 @@
7
7
  * Secrets are never hardcoded here. A key file that is missing simply means
8
8
  * the corresponding transport is not configured.
9
9
  */
10
+ import { type ClassificationPolicy } from "./classification.js";
10
11
  import type { LogBufferOptions } from "./buffer.js";
11
12
  import type { SamplingPolicy } from "./sampler.js";
12
13
  import type { LogTransport } from "./types.js";
@@ -16,6 +17,10 @@ export interface LogSinkConfig {
16
17
  enabled: boolean;
17
18
  /** Application name reported with every batch. */
18
19
  app: string;
20
+ /** Version of the emitting application. */
21
+ appVersion?: string;
22
+ /** Stable id of this installation. */
23
+ installationId: string;
19
24
  /** Transports in delivery priority order. */
20
25
  transports: LogTransport[];
21
26
  /** Directory of the local spool (undefined when logging is off). */
@@ -23,6 +28,8 @@ export interface LogSinkConfig {
23
28
  sampling: Partial<SamplingPolicy>;
24
29
  buffer: LogBufferOptions;
25
30
  flushIntervalMs: number;
31
+ /** What may leave the machine. */
32
+ classification: ClassificationPolicy;
26
33
  /** Human readable notes about what was enabled and why. */
27
34
  notes: string[];
28
35
  }
@@ -30,6 +37,8 @@ export interface ResolveConfigOptions {
30
37
  env?: Record<string, string | undefined>;
31
38
  /** Directory holding the credential key files. */
32
39
  keysDir?: string;
40
+ /** Overrides the installation id (tests, containers). */
41
+ installationId?: string;
33
42
  }
34
43
  export declare function defaultKeysDir(): string;
35
44
  export declare function defaultSpoolDir(): string;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,YAAY,CAAC;AAE3E,MAAM,WAAW,aAAa;IAC7B,sEAAsE;IACtE,OAAO,EAAE,OAAO,CAAC;IACjB,kDAAkD;IAClD,GAAG,EAAE,MAAM,CAAC;IACZ,6CAA6C;IAC7C,UAAU,EAAE,YAAY,EAAE,CAAC;IAC3B,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAClC,MAAM,EAAE,gBAAgB,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,2DAA2D;IAC3D,KAAK,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAoBD,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,oBAAyB,GAAG,aAAa,CA0FtF"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH,OAAO,EAEN,KAAK,oBAAoB,EACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,YAAY,CAAC;AAE3E,MAAM,WAAW,aAAa;IAC7B,sEAAsE;IACtE,OAAO,EAAE,OAAO,CAAC;IACjB,kDAAkD;IAClD,GAAG,EAAE,MAAM,CAAC;IACZ,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,cAAc,EAAE,MAAM,CAAC;IACvB,6CAA6C;IAC7C,UAAU,EAAE,YAAY,EAAE,CAAC;IAC3B,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAClC,MAAM,EAAE,gBAAgB,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,kCAAkC;IAClC,cAAc,EAAE,oBAAoB,CAAC;IACrC,2DAA2D;IAC3D,KAAK,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAoBD,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAiBD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,oBAAyB,GAAG,aAAa,CAuHtF"}