erne-universal 0.10.2 → 0.10.3
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.
package/dashboard/server.js
CHANGED
|
@@ -431,8 +431,13 @@ function handleContextApi(req, res, urlPath, body) {
|
|
|
431
431
|
}
|
|
432
432
|
|
|
433
433
|
try {
|
|
434
|
-
// POST /api/context/execute — sandbox execution
|
|
434
|
+
// POST /api/context/execute — sandbox execution (env-gated)
|
|
435
435
|
if (urlPath === '/api/context/execute' && req.method === 'POST') {
|
|
436
|
+
if (process.env.ERNE_ALLOW_EXECUTE !== 'true') {
|
|
437
|
+
res.writeHead(403, { 'Content-Type': 'application/json' });
|
|
438
|
+
res.end(JSON.stringify({ error: 'Execute endpoint disabled. Set ERNE_ALLOW_EXECUTE=true to enable.' }));
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
436
441
|
const { command, original_tool, timeout = 30000 } = JSON.parse(body);
|
|
437
442
|
const cwd = process.env.ERNE_PROJECT_DIR || process.cwd();
|
|
438
443
|
execFile('sh', ['-c', command], { cwd, timeout, maxBuffer: 1024 * 1024 }, (err, stdout, stderr) => {
|
|
@@ -601,8 +606,23 @@ const server = http.createServer(async (req, res) => {
|
|
|
601
606
|
const urlPath = req.url.split('?')[0];
|
|
602
607
|
if (urlPath.startsWith('/api/context/')) {
|
|
603
608
|
let body = '';
|
|
604
|
-
|
|
605
|
-
req.on('
|
|
609
|
+
let bodyBytes = 0;
|
|
610
|
+
req.on('data', chunk => {
|
|
611
|
+
bodyBytes += chunk.length;
|
|
612
|
+
if (bodyBytes > MAX_PAYLOAD_BYTES) {
|
|
613
|
+
req.destroy();
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
body += chunk;
|
|
617
|
+
});
|
|
618
|
+
req.on('end', () => {
|
|
619
|
+
if (bodyBytes > MAX_PAYLOAD_BYTES) {
|
|
620
|
+
res.writeHead(413, { 'Content-Type': 'application/json' });
|
|
621
|
+
res.end(JSON.stringify({ error: 'Payload too large' }));
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
handleContextApi(req, res, urlPath, body);
|
|
625
|
+
});
|
|
606
626
|
return;
|
|
607
627
|
}
|
|
608
628
|
|
package/lib/dashboard.js
CHANGED
|
@@ -157,7 +157,7 @@ async function dashboard() {
|
|
|
157
157
|
|
|
158
158
|
// Ensure ws dependency is installed
|
|
159
159
|
const dashboardDir = path.resolve(__dirname, '..', 'dashboard');
|
|
160
|
-
if (!fs.existsSync(path.join(dashboardDir, 'node_modules', '
|
|
160
|
+
if (!fs.existsSync(path.join(dashboardDir, 'node_modules', 'better-sqlite3'))) {
|
|
161
161
|
console.log(' Installing dashboard dependencies...');
|
|
162
162
|
require('child_process').execSync('npm install --production', { cwd: dashboardDir, stdio: 'ignore' });
|
|
163
163
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "erne-universal",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.3",
|
|
4
4
|
"description": "Complete AI coding agent harness for React Native and Expo development",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react-native",
|
|
@@ -45,7 +45,6 @@
|
|
|
45
45
|
"docs/commands.md",
|
|
46
46
|
"docs/hooks-profiles.md",
|
|
47
47
|
"docs/creating-skills.md",
|
|
48
|
-
"docs/assets/",
|
|
49
48
|
"install.sh",
|
|
50
49
|
"CLAUDE.md",
|
|
51
50
|
"AGENTS.md",
|
|
@@ -60,7 +59,7 @@
|
|
|
60
59
|
"node": ">=18"
|
|
61
60
|
},
|
|
62
61
|
"scripts": {
|
|
63
|
-
"test": "node --test tests/*.test.js tests/hooks/*.test.js tests/
|
|
62
|
+
"test": "node --test tests/*.test.js tests/hooks/*.test.js tests/worker/*.test.js",
|
|
64
63
|
"lint": "eslint lib/ scripts/ bin/",
|
|
65
64
|
"lint:agents": "node scripts/lint-agents.js",
|
|
66
65
|
"lint:content": "node scripts/lint-content.js",
|
|
@@ -25,6 +25,7 @@ const AGENT_KEYWORDS = [
|
|
|
25
25
|
'architect', 'code-reviewer', 'tdd-guide', 'performance-profiler',
|
|
26
26
|
'native-bridge-builder', 'expo-config-resolver', 'ui-designer', 'upgrade-assistant',
|
|
27
27
|
'senior-developer', 'feature-builder', 'pipeline-orchestrator', 'visual-debugger',
|
|
28
|
+
'documentation-generator',
|
|
28
29
|
];
|
|
29
30
|
|
|
30
31
|
function detectAgent(text) {
|
package/worker/pipeline.js
CHANGED
|
@@ -11,6 +11,7 @@ const { selfReview } = require('./self-reviewer');
|
|
|
11
11
|
const { runTests } = require('./test-verifier');
|
|
12
12
|
const { calculateHealthDelta } = require('./health-delta');
|
|
13
13
|
const { publishDashboardEvent } = require('./dashboard-events');
|
|
14
|
+
const { calculateConfidence } = require('./confidence-scorer');
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* Execute the full per-ticket pipeline.
|
|
@@ -89,6 +90,7 @@ async function executePipeline({ ticket, config, provider, auditData, stackInfo,
|
|
|
89
90
|
passed: testResults.passed,
|
|
90
91
|
});
|
|
91
92
|
|
|
93
|
+
let testsFailing = false;
|
|
92
94
|
if (!testResults.passed) {
|
|
93
95
|
// Auto-fix attempt: feed test errors back to Claude and retry once
|
|
94
96
|
logger.info('Tests failed — attempting auto-fix');
|
|
@@ -108,10 +110,13 @@ async function executePipeline({ ticket, config, provider, auditData, stackInfo,
|
|
|
108
110
|
autoFixAttempt: true,
|
|
109
111
|
});
|
|
110
112
|
}
|
|
113
|
+
if (!testResults.passed) {
|
|
114
|
+
testsFailing = true;
|
|
115
|
+
logger.warn('Tests still failing after auto-fix attempt');
|
|
116
|
+
}
|
|
111
117
|
}
|
|
112
118
|
|
|
113
119
|
// 5g. Health delta
|
|
114
|
-
const { calculateConfidence } = require('./confidence-scorer');
|
|
115
120
|
const confidenceResult = calculateConfidence(ticket, auditData, context);
|
|
116
121
|
const healthDelta = calculateHealthDelta({
|
|
117
122
|
testResults,
|
|
@@ -137,13 +142,14 @@ async function executePipeline({ ticket, config, provider, auditData, stackInfo,
|
|
|
137
142
|
}
|
|
138
143
|
}
|
|
139
144
|
|
|
140
|
-
// 5i. Return success
|
|
145
|
+
// 5i. Return success (PR is still created even if tests fail per spec)
|
|
141
146
|
return {
|
|
142
147
|
success: true,
|
|
143
|
-
output: execResult.output,
|
|
148
|
+
output: testsFailing ? `[TESTS FAILING] ${execResult.output}` : execResult.output,
|
|
144
149
|
agent,
|
|
145
150
|
confidence: confidenceResult,
|
|
146
151
|
testResults,
|
|
152
|
+
testsFailing,
|
|
147
153
|
healthDelta,
|
|
148
154
|
selfReview: reviewResult,
|
|
149
155
|
};
|
package/worker/worktree.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const {
|
|
3
|
+
const { execFileSync } = require('child_process');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const os = require('os');
|
|
6
6
|
|
|
@@ -13,7 +13,7 @@ function createWorktree(repoPath, branch, logger) {
|
|
|
13
13
|
|
|
14
14
|
try {
|
|
15
15
|
// Try creating a new branch from main
|
|
16
|
-
|
|
16
|
+
execFileSync('git', ['worktree', 'add', '-b', branch, worktreePath, 'main'], {
|
|
17
17
|
cwd: repoPath,
|
|
18
18
|
stdio: 'pipe',
|
|
19
19
|
});
|
|
@@ -21,7 +21,7 @@ function createWorktree(repoPath, branch, logger) {
|
|
|
21
21
|
} catch {
|
|
22
22
|
// Branch may already exist — try attaching to existing branch
|
|
23
23
|
try {
|
|
24
|
-
|
|
24
|
+
execFileSync('git', ['worktree', 'add', worktreePath, branch], {
|
|
25
25
|
cwd: repoPath,
|
|
26
26
|
stdio: 'pipe',
|
|
27
27
|
});
|
|
@@ -40,7 +40,7 @@ function createWorktree(repoPath, branch, logger) {
|
|
|
40
40
|
*/
|
|
41
41
|
function removeWorktree(repoPath, worktreePath, logger) {
|
|
42
42
|
try {
|
|
43
|
-
|
|
43
|
+
execFileSync('git', ['worktree', 'remove', '--force', worktreePath], {
|
|
44
44
|
cwd: repoPath,
|
|
45
45
|
stdio: 'pipe',
|
|
46
46
|
});
|
|
Binary file
|