pi-harness-runtime 1.1.366 → 1.1.368

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 (113) hide show
  1. package/AGENTS.md +33 -0
  2. package/index.ts +12 -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/connection-runtime/package.json +1 -1
  22. package/packages/context-compiler/package.json +1 -1
  23. package/packages/context-discovery/package.json +1 -1
  24. package/packages/context-manager/package.json +1 -1
  25. package/packages/contracts/dist/workspace-env.d.ts +46 -0
  26. package/packages/contracts/dist/workspace-env.js +231 -0
  27. package/packages/contracts/package.json +1 -1
  28. package/packages/contracts/src/workspace-env.ts +278 -0
  29. package/packages/cookie-sanitizer/package.json +1 -1
  30. package/packages/cost-optimizer/package.json +1 -1
  31. package/packages/dependency-analyzer/package.json +1 -1
  32. package/packages/django-plugin/package.json +1 -1
  33. package/packages/doc-generator/package.json +1 -1
  34. package/packages/durable-review/package.json +1 -1
  35. package/packages/e2e-tester/package.json +1 -1
  36. package/packages/evaluation-engine/package.json +1 -1
  37. package/packages/evaluation-runner/package.json +1 -1
  38. package/packages/event-bus/package.json +1 -1
  39. package/packages/event-sink/package.json +1 -1
  40. package/packages/event-store/package.json +1 -1
  41. package/packages/experience-replay/package.json +1 -1
  42. package/packages/feedback-collector/package.json +1 -1
  43. package/packages/file-copy-helper/package.json +1 -1
  44. package/packages/framework-detector/package.json +1 -1
  45. package/packages/framework-plugin-sdk/package.json +1 -1
  46. package/packages/frappe-plugin/package.json +1 -1
  47. package/packages/generic-web-plugin/package.json +1 -1
  48. package/packages/health-monitor/package.json +1 -1
  49. package/packages/intent-analyzer/package.json +1 -1
  50. package/packages/jev-judge/package.json +1 -1
  51. package/packages/knowledge-graph/package.json +1 -1
  52. package/packages/knowledge-retrieval/package.json +1 -1
  53. package/packages/laravel-plugin/package.json +1 -1
  54. package/packages/learning-engine/package.json +1 -1
  55. package/packages/mcp-adapter/package.json +1 -1
  56. package/packages/memory-engine/package.json +1 -1
  57. package/packages/milestone-manager/package.json +1 -1
  58. package/packages/model-registry/package.json +1 -1
  59. package/packages/nextjs-plugin/package.json +1 -1
  60. package/packages/notification/package.json +1 -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/permission-mode/package.json +1 -1
  66. package/packages/privilege-broker/package.json +1 -1
  67. package/packages/project-analyzer/package.json +1 -1
  68. package/packages/project-bootstrap/package.json +1 -1
  69. package/packages/projection-engine/package.json +1 -1
  70. package/packages/prompt-compiler/package.json +1 -1
  71. package/packages/prompt-versioning/package.json +1 -1
  72. package/packages/provider-adapter-sdk/package.json +1 -1
  73. package/packages/provider-router/package.json +1 -1
  74. package/packages/provider-selector/package.json +1 -1
  75. package/packages/providers/package.json +1 -1
  76. package/packages/qdrant-skills/package.json +1 -1
  77. package/packages/quota-manager/package.json +1 -1
  78. package/packages/rate-limiter/package.json +1 -1
  79. package/packages/react-vite-plugin/package.json +1 -1
  80. package/packages/relay/package.json +1 -1
  81. package/packages/release-manager/package.json +1 -1
  82. package/packages/requirement-compiler/package.json +1 -1
  83. package/packages/runtime/package.json +1 -1
  84. package/packages/scheduler/package.json +1 -1
  85. package/packages/scheduler-adapter/package.json +1 -1
  86. package/packages/session/package.json +1 -1
  87. package/packages/session-api/package.json +1 -1
  88. package/packages/session-export/package.json +1 -1
  89. package/packages/shared-context/package.json +1 -1
  90. package/packages/skill-mcp-client/package.json +1 -1
  91. package/packages/skill-registry/package.json +1 -1
  92. package/packages/skills/package.json +1 -1
  93. package/packages/sprint-planner/package.json +1 -1
  94. package/packages/subscription-engine/package.json +1 -1
  95. package/packages/task-compiler/package.json +1 -1
  96. package/packages/telegram/package.json +1 -1
  97. package/packages/tencentdb-memory/package.json +1 -1
  98. package/packages/tencentdb-sync/package.json +1 -1
  99. package/packages/test-data-generator/package.json +1 -1
  100. package/packages/test-generator/package.json +1 -1
  101. package/packages/todo-bd-sync/package.json +1 -1
  102. package/packages/token-estimation/package.json +1 -1
  103. package/packages/token-optimizer/package.json +1 -1
  104. package/packages/trajectory/package.json +1 -1
  105. package/packages/tui/package.json +1 -1
  106. package/packages/types/package.json +1 -1
  107. package/packages/voice-api/package.json +1 -1
  108. package/packages/webmcp-tester/package.json +1 -1
  109. package/packages/wiki/package.json +1 -1
  110. package/packages/workflow-events/package.json +1 -1
  111. package/packages/workspace-scanner/package.json +1 -1
  112. package/packages/worktree/package.json +1 -1
  113. package/packages/write-review/package.json +1 -1
package/AGENTS.md CHANGED
@@ -490,3 +490,36 @@ bun run start # ✅ Correct - run compiled
490
490
  bun run build && bun run test # CI pipeline
491
491
  bun run build && bun run start # Server deployment
492
492
  ```
493
+
494
+ ### 14. Workspace Environment Auto-Detection
495
+
496
+ **At session start, the harness auto-detects:**
497
+ - `.env` file presence → Dev environment
498
+ - `package.json` `dev` script → Hot reload available
499
+ - `NODE_ENV` value → development/production
500
+ - System RAM → Low RAM warning (<16GB)
501
+
502
+ **This info is stored in:**
503
+ ```
504
+ ~/.pi-harness-runtime/workspace-env.sqlite
505
+ ```
506
+
507
+ **Agent should check workspace environment BEFORE running build commands:**
508
+
509
+ ```
510
+ On Dev PC with hot reload:
511
+ → DON'T: bun run build (unless explicitly asked)
512
+ → DO: bun run dev (compiles on-demand, saves RAM)
513
+
514
+ On CI/Production:
515
+ → DO: bun run build (always build first)
516
+ ```
517
+
518
+ **Decision flow:**
519
+ ```
520
+ Is this a dev workspace? (.env, dev script exists?)
521
+ └─ YES + Has dev script?
522
+ └─ YES → Use bun run dev (no build needed)
523
+ └─ NO → May need build
524
+ └─ NO → Build required (production/server)
525
+ ```
package/index.ts CHANGED
@@ -138,6 +138,8 @@ const sharedState = {
138
138
  pqController: null as any,
139
139
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
140
140
  delegationHarness: null as any,
141
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
142
+ workspaceEnvMessage: null as string | null,
141
143
  };
142
144
 
143
145
  async function initAutoContinue(pi: ExtensionAPI): Promise<void> {
@@ -386,6 +388,16 @@ async function initAutoContinue(pi: ExtensionAPI): Promise<void> {
386
388
  _piSessionCwd = realpathSync(process.cwd());
387
389
  logToFile("[codex-trigger]", "Pi session cwd captured:", _piSessionCwd);
388
390
 
391
+ // --- Detect workspace environment ---
392
+ try {
393
+ const { formatEnvForAgent } = await import("./packages/contracts/dist/workspace-env.js");
394
+ const envMessage = formatEnvForAgent(_piSessionCwd);
395
+ logToFile("[WorkspaceEnv]", envMessage);
396
+ sharedState.workspaceEnvMessage = envMessage;
397
+ } catch (e) {
398
+ logToFile("[WorkspaceEnv]", "Detection failed:", String(e));
399
+ }
400
+
389
401
  // --- Drain pending greeting when Pi becomes active ---
390
402
  if (codexSessionState.pendingGreeting) {
391
403
  const pg = codexSessionState.pendingGreeting;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-harness-runtime",
3
- "version": "1.1.366",
3
+ "version": "1.1.368",
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.366",
3
+ "version": "1.1.368",
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.366",
3
+ "version": "1.1.368",
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.366",
3
+ "version": "1.1.368",
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.366",
3
+ "version": "1.1.368",
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.366",
3
+ "version": "1.1.368",
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.366",
3
+ "version": "1.1.368",
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.366",
3
+ "version": "1.1.368",
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.366",
3
+ "version": "1.1.368",
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.366",
3
+ "version": "1.1.368",
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.366",
3
+ "version": "1.1.368",
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.366",
3
+ "version": "1.1.368",
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.366",
3
+ "version": "1.1.368",
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.366",
3
+ "version": "1.1.368",
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.366",
3
+ "version": "1.1.368",
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.366",
3
+ "version": "1.1.368",
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.366",
3
+ "version": "1.1.368",
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.366",
3
+ "version": "1.1.368",
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-harness/connection-runtime",
3
- "version": "1.1.366",
3
+ "version": "1.1.368",
4
4
  "type": "module",
5
5
  "description": "Connection management with jittered exponential backoff for pi-harness",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/context-compiler",
3
- "version": "1.1.366",
3
+ "version": "1.1.368",
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.366",
3
+ "version": "1.1.368",
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.366",
3
+ "version": "1.1.368",
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",
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Workspace Environment Detector
3
+ *
4
+ * Detects if the workspace is a development environment by checking:
5
+ * 1. .env file existence and NODE_ENV value
6
+ * 2. package.json "dev" script presence
7
+ * 3. .env.development or .env.local files
8
+ *
9
+ * Stores detected environment in SQLite for agent reference.
10
+ */
11
+ /**
12
+ * Detect if workspace is a dev environment
13
+ */
14
+ export interface WorkspaceEnvResult {
15
+ workspacePath: string;
16
+ isDevEnv: boolean;
17
+ hasDevScript: boolean;
18
+ nodeEnv: string | null;
19
+ hasEnvFile: boolean;
20
+ ramGb: number | null;
21
+ detectedAt: number;
22
+ }
23
+ /**
24
+ * Detect and store workspace environment
25
+ */
26
+ export declare function detectWorkspaceEnv(workspacePath: string): WorkspaceEnvResult;
27
+ /**
28
+ * Load cached workspace environment
29
+ */
30
+ export declare function loadWorkspaceEnv(workspacePath: string): WorkspaceEnvResult | null;
31
+ /**
32
+ * Get or detect workspace environment
33
+ */
34
+ export declare function getWorkspaceEnv(workspacePath: string): WorkspaceEnvResult;
35
+ /**
36
+ * Check if agent should prefer dev mode (no build)
37
+ */
38
+ export declare function shouldUseDevMode(workspacePath: string): {
39
+ preferDev: boolean;
40
+ reason: string;
41
+ ramGb: number | null;
42
+ };
43
+ /**
44
+ * Format workspace env as agent-readable message
45
+ */
46
+ export declare function formatEnvForAgent(workspacePath: string): string;
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Workspace Environment Detector
3
+ *
4
+ * Detects if the workspace is a development environment by checking:
5
+ * 1. .env file existence and NODE_ENV value
6
+ * 2. package.json "dev" script presence
7
+ * 3. .env.development or .env.local files
8
+ *
9
+ * Stores detected environment in SQLite for agent reference.
10
+ */
11
+ import { DatabaseSync } from "node:sqlite";
12
+ import { existsSync, readFileSync } from "fs";
13
+ import { join, dirname } from "path";
14
+ import { fileURLToPath } from "url";
15
+ const __dirname = dirname(fileURLToPath(import.meta.url));
16
+ const STORE_DIR = join(process.env.HOME || "/home/frappe", ".pi-harness-runtime");
17
+ /**
18
+ * Ensure store directory exists
19
+ */
20
+ function ensureStoreDir() {
21
+ if (!existsSync(STORE_DIR)) {
22
+ // mkdirSync is not available in all contexts, use fs promises or exec
23
+ import("fs").then((fs) => fs.mkdirSync(STORE_DIR, { recursive: true }));
24
+ }
25
+ }
26
+ /**
27
+ * Get workspace database path
28
+ */
29
+ function getDbPath() {
30
+ ensureStoreDir();
31
+ return join(STORE_DIR, "workspace-env.sqlite");
32
+ }
33
+ /**
34
+ * Initialize workspace environment database
35
+ */
36
+ function initDatabase() {
37
+ const db = new DatabaseSync(getDbPath());
38
+ db.exec(`
39
+ CREATE TABLE IF NOT EXISTS workspace_env (
40
+ workspace_path TEXT PRIMARY KEY,
41
+ is_dev_env INTEGER NOT NULL DEFAULT 0,
42
+ has_dev_script INTEGER NOT NULL DEFAULT 0,
43
+ node_env TEXT,
44
+ has_env_file INTEGER NOT NULL DEFAULT 0,
45
+ ram_gb REAL,
46
+ detected_at INTEGER NOT NULL,
47
+ updated_at INTEGER NOT NULL
48
+ )
49
+ `);
50
+ return db;
51
+ }
52
+ /**
53
+ * Detect RAM in GB
54
+ */
55
+ function detectRamGb() {
56
+ try {
57
+ if (process.platform === "linux") {
58
+ const meminfo = readFileSync("/proc/meminfo", "utf8");
59
+ const match = meminfo.match(/MemTotal:\\s+(\\d+)\\s+kB/);
60
+ if (match) {
61
+ return Math.round((parseInt(match[1], 10) / 1024 / 1024) * 10) / 10;
62
+ }
63
+ }
64
+ else if (process.platform === "darwin") {
65
+ const out = require("child_process").execSync("sysctl hw.memsize", { encoding: "utf8" });
66
+ const match = out.match(/hw\\.memsize:\\s+(\\d+)/);
67
+ if (match) {
68
+ return Math.round((parseInt(match[1], 10) / 1024 / 1024 / 1024) * 10) / 10;
69
+ }
70
+ }
71
+ }
72
+ catch {
73
+ // Fallback: return null
74
+ }
75
+ return null;
76
+ }
77
+ /**
78
+ * Detect and store workspace environment
79
+ */
80
+ export function detectWorkspaceEnv(workspacePath) {
81
+ const now = Date.now();
82
+ const ramGb = detectRamGb();
83
+ // Check for .env files
84
+ const hasEnvFile = existsSync(join(workspacePath, ".env")) ||
85
+ existsSync(join(workspacePath, ".env.development")) ||
86
+ existsSync(join(workspacePath, ".env.local")) ||
87
+ existsSync(join(workspacePath, ".env.dev"));
88
+ // Read NODE_ENV from .env file if present
89
+ let nodeEnv = null;
90
+ const envFile = join(workspacePath, ".env");
91
+ if (existsSync(envFile)) {
92
+ try {
93
+ const envContent = readFileSync(envFile, "utf8");
94
+ const match = envContent.match(/NODE_ENV=(.+)/);
95
+ if (match) {
96
+ nodeEnv = match[1].trim().replace(/['"]/g, "");
97
+ }
98
+ }
99
+ catch {
100
+ // Ignore read errors
101
+ }
102
+ }
103
+ // Check for dev script in package.json
104
+ let hasDevScript = false;
105
+ const pkgJsonPath = join(workspacePath, "package.json");
106
+ if (existsSync(pkgJsonPath)) {
107
+ try {
108
+ const pkg = JSON.parse(readFileSync(pkgJsonPath, "utf8"));
109
+ hasDevScript = !!(pkg.scripts && (pkg.scripts.dev || pkg.scripts.development));
110
+ }
111
+ catch {
112
+ // Ignore parse errors
113
+ }
114
+ }
115
+ // Determine if this is a dev environment
116
+ // Dev env if: has .env file OR has dev script OR NODE_ENV=development
117
+ const isDevEnv = hasEnvFile || hasDevScript || nodeEnv === "development" || nodeEnv === "dev";
118
+ // Store in SQLite
119
+ const db = initDatabase();
120
+ db.prepare(`
121
+ INSERT OR REPLACE INTO workspace_env
122
+ (workspace_path, is_dev_env, has_dev_script, node_env, has_env_file, ram_gb, detected_at, updated_at)
123
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
124
+ `).run(workspacePath, isDevEnv ? 1 : 0, hasDevScript ? 1 : 0, nodeEnv, hasEnvFile ? 1 : 0, ramGb, now, now);
125
+ db.close();
126
+ return {
127
+ workspacePath,
128
+ isDevEnv,
129
+ hasDevScript,
130
+ nodeEnv,
131
+ hasEnvFile,
132
+ ramGb,
133
+ detectedAt: now,
134
+ };
135
+ }
136
+ /**
137
+ * Load cached workspace environment
138
+ */
139
+ export function loadWorkspaceEnv(workspacePath) {
140
+ const db = initDatabase();
141
+ const row = db.prepare("SELECT * FROM workspace_env WHERE workspace_path = ?").get(workspacePath);
142
+ db.close();
143
+ if (!row)
144
+ return null;
145
+ return {
146
+ workspacePath: row.workspace_path,
147
+ isDevEnv: row.is_dev_env === 1,
148
+ hasDevScript: row.has_dev_script === 1,
149
+ nodeEnv: row.node_env,
150
+ hasEnvFile: row.has_env_file === 1,
151
+ ramGb: row.ram_gb,
152
+ detectedAt: row.detected_at,
153
+ };
154
+ }
155
+ /**
156
+ * Get or detect workspace environment
157
+ */
158
+ export function getWorkspaceEnv(workspacePath) {
159
+ // Try to load cached result first
160
+ const cached = loadWorkspaceEnv(workspacePath);
161
+ if (cached) {
162
+ // Check if cache is recent (within 1 hour)
163
+ const ageMs = Date.now() - cached.detectedAt;
164
+ if (ageMs < 60 * 60 * 1000) {
165
+ return cached;
166
+ }
167
+ }
168
+ // Detect fresh
169
+ return detectWorkspaceEnv(workspacePath);
170
+ }
171
+ /**
172
+ * Check if agent should prefer dev mode (no build)
173
+ */
174
+ export function shouldUseDevMode(workspacePath) {
175
+ const env = getWorkspaceEnv(workspacePath);
176
+ // Low RAM threshold
177
+ const LOW_RAM_GB = 16;
178
+ if (!env.isDevEnv) {
179
+ return {
180
+ preferDev: false,
181
+ reason: "Not detected as dev environment",
182
+ ramGb: env.ramGb,
183
+ };
184
+ }
185
+ if (env.ramGb !== null && env.ramGb < LOW_RAM_GB) {
186
+ return {
187
+ preferDev: true,
188
+ reason: `Low RAM (${env.ramGb}GB < ${LOW_RAM_GB}GB) - avoid parallel build + dev`,
189
+ ramGb: env.ramGb,
190
+ };
191
+ }
192
+ if (env.hasDevScript) {
193
+ return {
194
+ preferDev: true,
195
+ reason: `Dev script detected - hot reload available`,
196
+ ramGb: env.ramGb,
197
+ };
198
+ }
199
+ return {
200
+ preferDev: false,
201
+ reason: "Dev environment but no dev script found",
202
+ ramGb: env.ramGb,
203
+ };
204
+ }
205
+ /**
206
+ * Format workspace env as agent-readable message
207
+ */
208
+ export function formatEnvForAgent(workspacePath) {
209
+ const env = shouldUseDevMode(workspacePath);
210
+ const details = getWorkspaceEnv(workspacePath);
211
+ let message = `[Workspace Environment]\n`;
212
+ message += `- Path: ${workspacePath}\n`;
213
+ message += `- Detected: ${details.isDevEnv ? "Development" : "Production/Unknown"}\n`;
214
+ message += `- Has dev script: ${details.hasDevScript ? "Yes" : "No"}\n`;
215
+ message += `- NODE_ENV: ${details.nodeEnv || "not set"}\n`;
216
+ message += `- Has .env file: ${details.hasEnvFile ? "Yes" : "No"}\n`;
217
+ message += `- RAM: ${details.ramGb ? `${details.ramGb}GB` : "unknown"}\n`;
218
+ message += `\n`;
219
+ if (env.preferDev) {
220
+ message += `RECOMMENDATION: Use \`dev\` mode (no build needed)\n`;
221
+ message += `Reason: ${env.reason}\n`;
222
+ message += `→ Run: \`bun run dev\` (or \`npm run dev\`)\n`;
223
+ message += `→ DON'T: Run \`build\` unless explicitly requested\n`;
224
+ }
225
+ else {
226
+ message += `RECOMMENDATION: Build may be needed\n`;
227
+ message += `Reason: ${env.reason}\n`;
228
+ message += `→ Use: \`bun run build\` before running\n`;
229
+ }
230
+ return message;
231
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/contracts",
3
- "version": "1.1.366",
3
+ "version": "1.1.368",
4
4
  "type": "module",
5
5
  "description": "RPC schema definitions for pi-harness runtime",
6
6
  "main": "./dist/index.js",