fix: repair opencode config and project metadata

This commit is contained in:
Affaan Mustafa
2026-03-11 01:51:41 -07:00
committed by Affaan Mustafa
parent dba4c462c4
commit da4db99c94
7 changed files with 223 additions and 49 deletions

View File

@@ -8,7 +8,7 @@ const assert = require('assert');
const path = require('path');
const fs = require('fs');
const os = require('os');
const { spawn } = require('child_process');
const { spawn, spawnSync } = require('child_process');
// Test helper
function test(name, fn) {
@@ -2148,6 +2148,69 @@ async function runTests() {
passed++;
else failed++;
if (
await asyncTest('detect-project writes project metadata to the registry and project directory', async () => {
const testRoot = createTestDir();
const homeDir = path.join(testRoot, 'home');
const repoDir = path.join(testRoot, 'repo');
const detectProjectPath = path.join(__dirname, '..', '..', 'skills', 'continuous-learning-v2', 'scripts', 'detect-project.sh');
try {
fs.mkdirSync(homeDir, { recursive: true });
fs.mkdirSync(repoDir, { recursive: true });
spawnSync('git', ['init'], { cwd: repoDir, stdio: 'ignore' });
spawnSync('git', ['remote', 'add', 'origin', 'https://github.com/example/ecc-test.git'], { cwd: repoDir, stdio: 'ignore' });
const shellCommand = [
`cd "${repoDir}"`,
`source "${detectProjectPath}" >/dev/null 2>&1`,
'printf "%s\\n" "$PROJECT_ID"',
'printf "%s\\n" "$PROJECT_DIR"'
].join('; ');
const proc = spawn('bash', ['-lc', shellCommand], {
env: { ...process.env, HOME: homeDir },
stdio: ['ignore', 'pipe', 'pipe']
});
let stdout = '';
let stderr = '';
proc.stdout.on('data', data => (stdout += data));
proc.stderr.on('data', data => (stderr += data));
const code = await new Promise((resolve, reject) => {
proc.on('close', resolve);
proc.on('error', reject);
});
assert.strictEqual(code, 0, `detect-project should source cleanly, stderr: ${stderr}`);
const [projectId, projectDir] = stdout.trim().split(/\r?\n/);
const registryPath = path.join(homeDir, '.claude', 'homunculus', 'projects.json');
const projectMetadataPath = path.join(projectDir, 'project.json');
assert.ok(projectId, 'detect-project should emit a project id');
assert.ok(fs.existsSync(registryPath), 'projects.json should be created');
assert.ok(fs.existsSync(projectMetadataPath), 'project.json should be written in the project directory');
const registry = JSON.parse(fs.readFileSync(registryPath, 'utf8'));
const metadata = JSON.parse(fs.readFileSync(projectMetadataPath, 'utf8'));
assert.ok(registry[projectId], 'registry should contain the detected project');
assert.strictEqual(metadata.id, projectId, 'project.json should include the detected id');
assert.strictEqual(metadata.name, path.basename(repoDir), 'project.json should include the repo name');
assert.strictEqual(fs.realpathSync(metadata.root), fs.realpathSync(repoDir), 'project.json should include the repo root');
assert.strictEqual(metadata.remote, 'https://github.com/example/ecc-test.git', 'project.json should include the sanitized remote');
assert.ok(metadata.created_at, 'project.json should include created_at');
assert.ok(metadata.last_seen, 'project.json should include last_seen');
} finally {
cleanupTestDir(testRoot);
}
})
)
passed++;
else failed++;
if (await asyncTest('observe.sh falls back to legacy output fields when tool_response is null', async () => {
const homeDir = createTestDir();
const projectDir = createTestDir();

View File

@@ -0,0 +1,81 @@
/**
* Tests for .opencode/opencode.json local file references.
*
* Run with: node tests/opencode-config.test.js
*/
const assert = require('assert');
const fs = require('fs');
const path = require('path');
function test(name, fn) {
try {
fn();
console.log(`${name}`);
return true;
} catch (err) {
console.log(`${name}`);
console.log(` Error: ${err.message}`);
return false;
}
}
const repoRoot = path.join(__dirname, '..');
const opencodeDir = path.join(repoRoot, '.opencode');
const configPath = path.join(opencodeDir, 'opencode.json');
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
let passed = 0;
let failed = 0;
if (
test('plugin paths do not duplicate the .opencode directory', () => {
const plugins = config.plugin || [];
for (const pluginPath of plugins) {
assert.ok(!pluginPath.includes('.opencode/'), `Plugin path should be config-relative, got: ${pluginPath}`);
assert.ok(fs.existsSync(path.resolve(opencodeDir, pluginPath)), `Plugin path should resolve from .opencode/: ${pluginPath}`);
}
})
)
passed++;
else failed++;
if (
test('file references are config-relative and resolve to existing files', () => {
const refs = [];
function walk(value) {
if (typeof value === 'string') {
const matches = value.matchAll(/\{file:([^}]+)\}/g);
for (const match of matches) {
refs.push(match[1]);
}
return;
}
if (Array.isArray(value)) {
value.forEach(walk);
return;
}
if (value && typeof value === 'object') {
Object.values(value).forEach(walk);
}
}
walk(config);
assert.ok(refs.length > 0, 'Expected to find file references in opencode.json');
for (const ref of refs) {
assert.ok(!ref.startsWith('.opencode/'), `File ref should not duplicate .opencode/: ${ref}`);
assert.ok(fs.existsSync(path.resolve(opencodeDir, ref)), `File ref should resolve from .opencode/: ${ref}`);
}
})
)
passed++;
else failed++;
console.log(`\nPassed: ${passed}`);
console.log(`Failed: ${failed}`);
process.exit(failed > 0 ? 1 : 0);