Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
117592e
feat(ui): align workspace surfaces with Vim
flyingrobots Sep 1, 2026
d01cd4b
fix(ui): preserve title intro presentation
flyingrobots Sep 1, 2026
cf0cebf
fix(ui): make static title state truthful
flyingrobots Sep 1, 2026
90b18c1
fix(logo): restore the original Jim artwork and drop the tool-sniffin…
flyingrobots Sep 7, 2026
14d17b5
feat(startup): open on an empty viewer instead of the title screen
flyingrobots Sep 7, 2026
910373f
fix(startup): stop instrumenting and re-rendering an idle editor
flyingrobots Sep 7, 2026
f5cf630
Fix: let the focused drawer own its navigation keys
flyingrobots Sep 7, 2026
30835da
Fix: stop pointer movement from starting the ray tracer
flyingrobots Sep 7, 2026
74f5da7
Fix: return the terminal on quit by closing the native Echo host
flyingrobots Sep 7, 2026
fa116b6
Fix: select a file explorer entry by clicking it
flyingrobots Sep 7, 2026
6b8083e
Fix: window the file explorer list instead of truncating it
flyingrobots Sep 7, 2026
2e52547
Fix: stop the footer advertising a theme shortcut that does not exist
flyingrobots Sep 7, 2026
13c11b2
Refactor: give list index arithmetic one implementation
flyingrobots Sep 7, 2026
0933a1c
Fix: open a file explorer entry by clicking it
flyingrobots Sep 7, 2026
403fb23
Fix: bring Solarized Light body text up to WCAG AA
flyingrobots Sep 7, 2026
cce8b48
Fix: discover the test repo root instead of assuming the launch direc…
flyingrobots Sep 7, 2026
b8c83e2
Fix: extend the quality ratchet to spec files
flyingrobots Sep 7, 2026
976f444
Fix: keep the backdrop and the Echo host safe on failure paths
flyingrobots Sep 8, 2026
af8b78d
Fix: load meshes on demand, keep the frame clock honest, stop the mat…
flyingrobots Sep 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
489 changes: 465 additions & 24 deletions JimLogo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
82 changes: 41 additions & 41 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,19 @@
"check": "npm run test:all && npm run quality"
},
"dependencies": {
"@flyingrobots/bijou": "7.0.0",
"@flyingrobots/bijou-i18n": "^7.0.0",
"@flyingrobots/bijou-node": "7.0.0",
"@flyingrobots/bijou-tui": "7.0.0",
"@flyingrobots/bijou-tui-app": "7.0.0",
"@flyingrobots/bijou": "7.2.0",
"@flyingrobots/bijou-i18n": "7.2.0",
"@flyingrobots/bijou-node": "7.2.0",
"@flyingrobots/bijou-tui": "7.2.0",
"@flyingrobots/bijou-tui-app": "7.2.0",
"@flyingrobots/graft": "0.11.1",
"@modelcontextprotocol/sdk": "^1.29.0",
"diff": "9.0.0",
"zod": "4.3.6"
},
"devDependencies": {
"@flyingrobots/bijou-i18n-tools-node": "^7.0.0",
"@flyingrobots/bijou-i18n-tools-xlsx": "^7.0.0",
"@flyingrobots/bijou-i18n-tools-node": "7.2.0",
"@flyingrobots/bijou-i18n-tools-xlsx": "7.2.0",
"@types/node": "^22.0.0",
"semver": "^7.8.5",
"tsx": "^4.22.4",
Expand Down
15 changes: 14 additions & 1 deletion quality-baseline.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
{
"maxLines": {},
"maxLines": {
"spec/graft-source-highlighter.spec.mjs": 659,
"spec/graph-rope-contract.spec.mjs": 537,
"spec/title-scene.spec.mjs": 817,
"spec/title-screen.spec.mjs": 518,
"spec/workspace-command-completion.spec.mjs": 932,
"spec/workspace-command-line.spec.mjs": 1979,
"spec/workspace-helpers.mjs": 625,
"spec/workspace-runtime.spec.mjs": 619,
"spec/workspace-text-boundaries.spec.mjs": 559,
"spec/workspace-text-cutover.spec.mjs": 2047,
"spec/workspace-title-screen.spec.mjs": 1184,
"tests/replace-range-law-cycle.spec.mjs": 539
},
"forbiddenTypeKeywords": {},
"booleanParameters": {}
}
73 changes: 53 additions & 20 deletions scripts/quality-gate.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import { countForbiddenSyntax } from './quality-gate/syntax-counts.mjs';

const ROOT = process.cwd();
const SOURCE_ROOT = path.join(ROOT, 'src');
// Specs were invisible to the ratchet, so oversized ones grew unchecked -- the
// largest reached four times the doctrine limit without ever reporting. Only
// max-lines applies here; the other rules encode TypeScript-specific doctrine.
const SPEC_ROOTS = [path.join(ROOT, 'spec'), path.join(ROOT, 'tests')];
const BASELINE_PATH = path.join(ROOT, 'quality-baseline.json');
const PACKAGE_PATH = path.join(ROOT, 'package.json');
const MAX_LINES_PER_FILE = 500;
Expand Down Expand Up @@ -39,25 +43,7 @@ function main() {
const lineCount = sourceText.split('\n').length;
const counts = countForbiddenSyntax(relativePath, sourceText);

const allowedLineCount = baseline.maxLines[relativePath] ?? MAX_LINES_PER_FILE;
if (lineCount > allowedLineCount) {
regressions.push({
file: relativePath,
rule: 'max-lines',
actual: lineCount,
allowed: allowedLineCount,
});
} else if (lineCount > MAX_LINES_PER_FILE) {
debt.push({
file: relativePath,
rule: 'max-lines',
actual: lineCount,
allowed: allowedLineCount,
});
if (lineCount < allowedLineCount) {
improvements.push(`${relativePath}: max-lines improved ${allowedLineCount} -> ${lineCount}`);
}
}
checkMaxLines(relativePath, lineCount, baseline, regressions, debt, improvements);

for (const key of ['any', 'unknown']) {
recordCountRule({
Expand Down Expand Up @@ -204,6 +190,12 @@ function main() {
});
}

for (const specPath of collectSpecFiles()) {
const relativeSpecPath = toRepoPath(specPath);
const specLineCount = fs.readFileSync(specPath, 'utf8').split('\n').length;
checkMaxLines(relativeSpecPath, specLineCount, baseline, regressions, debt, improvements);
}

const result = {
ok: regressions.length === 0,
enforcedRules: [
Expand All @@ -225,7 +217,7 @@ function main() {
'max-lines-500',
'identity-doctrine-links',
],
fileCount: files.length,
fileCount: files.length + collectSpecFiles().length,
regressions,
debt,
improvements,
Expand Down Expand Up @@ -348,6 +340,47 @@ function loadBaseline() {
return JSON.parse(fs.readFileSync(BASELINE_PATH, 'utf8'));
}

function checkMaxLines(relativePath, lineCount, baseline, regressions, debt, improvements) {
const allowedLineCount = baseline.maxLines[relativePath] ?? MAX_LINES_PER_FILE;
if (lineCount > allowedLineCount) {
regressions.push({ file: relativePath, rule: 'max-lines', actual: lineCount, allowed: allowedLineCount });
return;
}
if (lineCount <= MAX_LINES_PER_FILE) {
return;
}
debt.push({ file: relativePath, rule: 'max-lines', actual: lineCount, allowed: allowedLineCount });
if (lineCount < allowedLineCount) {
improvements.push(`${relativePath}: max-lines improved ${allowedLineCount} -> ${lineCount}`);
}
}

function collectSpecFiles() {
const files = [];
for (const root of SPEC_ROOTS) {
files.push(...collectFilesWithExtension(root, '.mjs'));
}
return files.sort();
}

function collectFilesWithExtension(directory, extension) {
if (!fs.existsSync(directory)) {
return [];
}
const files = [];
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
const fullPath = path.join(directory, entry.name);
if (entry.isDirectory()) {
files.push(...collectFilesWithExtension(fullPath, extension));
continue;
}
if (entry.isFile() && fullPath.endsWith(extension)) {
files.push(fullPath);
}
}
return files;
}

function collectTypeScriptFiles(directory) {
if (!fs.existsSync(directory)) {
return [];
Expand Down
9 changes: 0 additions & 9 deletions spec/audit-docs.spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import test from 'node:test';
const READY_AUDIT = 'docs/audits/ready-to-ship-assessment-2026-06-28.md';
const TWO_PHASE_AUDIT = 'docs/audits/two-phase-assessment-2026-06-28.md';
const DOC_AUDIT = 'docs/audits/documentation-readme-audit-2026-06-28.md';
const JIM_LOGO = 'JimLogo.svg';

function readRepoText(path) {
return readFileSync(path, 'utf8');
Expand Down Expand Up @@ -63,11 +62,3 @@ test('documentation audit prompt covers all stale Advanced Guide runtime referen
assert.match(audit, /`src\/main-workspace\.ts`/);
assert.match(audit, /`src\/main\.ts` only remains the process entrypoint/);
});

test('Jim logo is original project artwork with explicit metadata', () => {
const logo = readRepoText(JIM_LOGO);

assert.doesNotMatch(logo, /Vimlogo|VimLogo|Vim logo|sodipodi|inkscape/i);
assert.match(logo, /Original Jim project logo/);
assert.match(logo, /Apache-2\.0/);
});
5 changes: 4 additions & 1 deletion spec/ci-shards.spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,10 @@ test('local full test scripts use one prebuilt dist pass', () => {

assert.equal(packageJson.scripts['test:all'], FULL_PREBUILT_TEST_SCRIPT);
assert.equal(packageJson.scripts.test, 'npm run test:all');
assert.equal(packageJson.scripts.check, 'npm run test:all && npm run quality');
assert.equal(
packageJson.scripts.check,
'npm run test:all && npm run quality',
);
});

test('CI build artifact restores compiled output required by test shards', () => {
Expand Down
16 changes: 15 additions & 1 deletion spec/dist-helpers.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,21 @@ import { existsSync } from 'node:fs';
import path from 'node:path';
import { pathToFileURL } from 'node:url';

export const REPO_ROOT = process.cwd();
// Discovered, not assumed. Treating `process.cwd()` as the repository root
// only holds when tests are launched from the root; run from anywhere else the
// specs silently resolve paths against the wrong tree. Asking git removes the
// hidden harness assumption.
export function discoverRepoRoot(fromDirectory = process.cwd()) {
const result = spawnSync('git', ['rev-parse', '--show-toplevel'], {
cwd: fromDirectory,
encoding: 'utf8',
});
return result.status === 0 && typeof result.stdout === 'string'
? result.stdout.trim()
: fromDirectory;
}

export const REPO_ROOT = discoverRepoRoot();

const PREBUILT_DIST_ENV = 'JEDIT_DIST_PREBUILT';
const PREBUILT_DIST_ENABLED = '1';
Expand Down
Loading
Loading