fix: port safe ci cleanup from backlog

This commit is contained in:
Affaan Mustafa 2026-04-01 16:09:54 -07:00
parent 9a6080f2e1
commit 8f63697113
11 changed files with 28 additions and 16 deletions

View File

@ -62,6 +62,7 @@ Public ECC plugin repo for agents, skills, commands, hooks, rules, install surfa
- `#1110` install-time Claude hook root resolution - `#1110` install-time Claude hook root resolution
- `#1106` portable Codex Context7 key extraction - `#1106` portable Codex Context7 key extraction
- `#1107` Codex baseline merge and sample agent-role sync - `#1107` Codex baseline merge and sample agent-role sync
- `#1119` stale CI/lint cleanup that still contained safe low-risk fixes
- Port or rebuild inside ECC after full audit: - Port or rebuild inside ECC after full audit:
- `#894` Jira integration - `#894` Jira integration
- `#814` + `#808` rebuild as a single consolidated notifications lane for Opencode and cross-harness surfaces - `#814` + `#808` rebuild as a single consolidated notifications lane for Opencode and cross-harness surfaces
@ -104,3 +105,4 @@ Keep this file detailed for only the current sprint, blockers, and next actions.
- 2026-04-01: Replaced the GNU-only `grep -P` parser in `scripts/sync-ecc-to-codex.sh` with a portable Node parser for Context7 key extraction. Added source-level regression coverage so BSD/macOS syncs do not drift back to non-portable parsing. - 2026-04-01: Replaced the GNU-only `grep -P` parser in `scripts/sync-ecc-to-codex.sh` with a portable Node parser for Context7 key extraction. Added source-level regression coverage so BSD/macOS syncs do not drift back to non-portable parsing.
- 2026-04-01: Targeted regression suite after the direct ports is green: `tests/scripts/install-apply.test.js`, `tests/scripts/sync-ecc-to-codex.test.js`, and `tests/scripts/codex-hooks.test.js`. - 2026-04-01: Targeted regression suite after the direct ports is green: `tests/scripts/install-apply.test.js`, `tests/scripts/sync-ecc-to-codex.test.js`, and `tests/scripts/codex-hooks.test.js`.
- 2026-04-01: Ported the useful core of `#1107` directly into `main` as an add-only Codex baseline merge. `scripts/sync-ecc-to-codex.sh` now fills missing non-MCP defaults from `.codex/config.toml`, syncs sample agent role files into `~/.codex/agents`, and preserves user config instead of replacing it. Added regression coverage for sparse configs and implicit parent tables. - 2026-04-01: Ported the useful core of `#1107` directly into `main` as an add-only Codex baseline merge. `scripts/sync-ecc-to-codex.sh` now fills missing non-MCP defaults from `.codex/config.toml`, syncs sample agent role files into `~/.codex/agents`, and preserves user config instead of replacing it. Added regression coverage for sparse configs and implicit parent tables.
- 2026-04-01: Ported the safe low-risk cleanup from `#1119` directly into `main` instead of keeping an obsolete CI PR open. This included `.mjs` eslint handling, stricter null checks, Windows home-dir coverage in bash-log tests, and longer Trae shell-test timeouts.

View File

@ -24,5 +24,11 @@ module.exports = [
'no-undef': 'error', 'no-undef': 'error',
'eqeqeq': 'warn' 'eqeqeq': 'warn'
} }
},
{
files: ['**/*.mjs'],
languageOptions: {
sourceType: 'module'
}
} }
]; ];

View File

@ -67,7 +67,7 @@ function findFileIssues(filePath) {
try { try {
const content = getStagedFileContent(filePath); const content = getStagedFileContent(filePath);
if (content == null) { if (content === null || content === undefined) {
return issues; return issues;
} }
const lines = content.split('\n'); const lines = content.split('\n');

View File

@ -37,8 +37,8 @@ function createSkillObservation(input) {
? input.skill.path.trim() ? input.skill.path.trim()
: null; : null;
const success = Boolean(input.success); const success = Boolean(input.success);
const error = input.error == null ? null : String(input.error); const error = input.error === null || input.error === undefined ? null : String(input.error);
const feedback = input.feedback == null ? null : String(input.feedback); const feedback = input.feedback === null || input.feedback === undefined ? null : String(input.feedback);
const variant = typeof input.variant === 'string' && input.variant.trim().length > 0 const variant = typeof input.variant === 'string' && input.variant.trim().length > 0
? input.variant.trim() ? input.variant.trim()
: 'baseline'; : 'baseline';

View File

@ -8,8 +8,7 @@
* exit 0: success exit 1: no projects * exit 0: success exit 1: no projects
*/ */
import { readProjects, loadContext, today, CONTEXTS_DIR } from './shared.mjs'; import { readProjects, loadContext, today, renderListTable } from './shared.mjs';
import { renderListTable } from './shared.mjs';
const cwd = process.env.PWD || process.cwd(); const cwd = process.env.PWD || process.cwd();
const projects = readProjects(); const projects = readProjects();

View File

@ -11,7 +11,7 @@
* exit 0: success exit 1: error * exit 0: success exit 1: error
*/ */
import { readFileSync, writeFileSync, existsSync, renameSync } from 'fs'; import { readFileSync, existsSync, renameSync } from 'fs';
import { resolve } from 'path'; import { resolve } from 'path';
import { readProjects, writeProjects, saveContext, today, shortId, CONTEXTS_DIR } from './shared.mjs'; import { readProjects, writeProjects, saveContext, today, shortId, CONTEXTS_DIR } from './shared.mjs';
@ -112,7 +112,11 @@ for (const [projectPath, info] of Object.entries(projects)) {
const contextMd = existsSync(contextMdPath) ? readFileSync(contextMdPath, 'utf8') : ''; const contextMd = existsSync(contextMdPath) ? readFileSync(contextMdPath, 'utf8') : '';
let meta = {}; let meta = {};
if (existsSync(metaPath)) { if (existsSync(metaPath)) {
try { meta = JSON.parse(readFileSync(metaPath, 'utf8')); } catch {} try {
meta = JSON.parse(readFileSync(metaPath, 'utf8'));
} catch (e) {
console.warn(` ! ${contextDir}: invalid meta.json, continuing with defaults (${e.message})`);
}
} }
// Extract fields from CONTEXT.md // Extract fields from CONTEXT.md

View File

@ -20,8 +20,8 @@ import { readFileSync, mkdirSync, writeFileSync } from 'fs';
import { resolve } from 'path'; import { resolve } from 'path';
import { import {
readProjects, writeProjects, loadContext, saveContext, readProjects, writeProjects, loadContext, saveContext,
today, shortId, gitSummary, nativeMemoryDir, encodeProjectPath, today, shortId, gitSummary, nativeMemoryDir,
CONTEXTS_DIR, CURRENT_SESSION, CURRENT_SESSION,
} from './shared.mjs'; } from './shared.mjs';
const isInit = process.argv.includes('--init'); const isInit = process.argv.includes('--init');

View File

@ -5,8 +5,8 @@
* No external dependencies. Node.js stdlib only. * No external dependencies. Node.js stdlib only.
*/ */
import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync } from 'fs'; import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
import { resolve, basename } from 'path'; import { resolve } from 'path';
import { homedir } from 'os'; import { homedir } from 'os';
import { spawnSync } from 'child_process'; import { spawnSync } from 'child_process';
import { randomBytes } from 'crypto'; import { randomBytes } from 'crypto';
@ -270,7 +270,7 @@ export function renderContextMd(ctx) {
} }
/** Render the bordered briefing box used by /ck:resume */ /** Render the bordered briefing box used by /ck:resume */
export function renderBriefingBox(ctx, meta = {}) { export function renderBriefingBox(ctx, _meta = {}) {
const latest = ctx.sessions?.[ctx.sessions.length - 1] || {}; const latest = ctx.sessions?.[ctx.sessions.length - 1] || {};
const W = 57; const W = 57;
const pad = (str, w) => { const pad = (str, w) => {
@ -344,7 +344,7 @@ export function renderInfoBlock(ctx) {
} }
/** Render ASCII list table used by /ck:list */ /** Render ASCII list table used by /ck:list */
export function renderListTable(entries, cwd, todayStr) { export function renderListTable(entries, cwd, _todayStr) {
// entries: [{name, contextDir, path, context, lastUpdated}] // entries: [{name, contextDir, path, context, lastUpdated}]
// Sorted alphabetically by contextDir before calling // Sorted alphabetically by contextDir before calling
const rows = entries.map((e, i) => { const rows = entries.map((e, i) => {

View File

@ -24,7 +24,7 @@ async function runTests() {
let store let store
try { try {
store = await import(pathToFileURL(storePath).href) store = await import(pathToFileURL(storePath).href)
} catch (err) { } catch (_err) {
console.log('\n[warn] Skipping: build .opencode first (cd .opencode && npm run build)\n') console.log('\n[warn] Skipping: build .opencode first (cd .opencode && npm run build)\n')
process.exit(0) process.exit(0)
} }

View File

@ -26,6 +26,7 @@ function runHook(mode, payload, homeDir) {
env: { env: {
...process.env, ...process.env,
HOME: homeDir, HOME: homeDir,
USERPROFILE: homeDir,
}, },
}); });
} }

View File

@ -29,7 +29,7 @@ function runInstall(options = {}) {
}, },
encoding: 'utf8', encoding: 'utf8',
stdio: ['pipe', 'pipe', 'pipe'], stdio: ['pipe', 'pipe', 'pipe'],
timeout: 20000, timeout: 60000,
}); });
} }
@ -43,7 +43,7 @@ function runUninstall(options = {}) {
encoding: 'utf8', encoding: 'utf8',
input: options.input || 'y\n', input: options.input || 'y\n',
stdio: ['pipe', 'pipe', 'pipe'], stdio: ['pipe', 'pipe', 'pipe'],
timeout: 20000, timeout: 60000,
}); });
} }