mirror of
https://github.com/garrytan/gbrain.git
synced 2026-07-31 04:07:52 +00:00
* fix(frontmatter): derive validate slug from brain root, not absolute path (#2340) Single-file `frontmatter validate` derived the expected slug from the absolute path: relative(resolve(target), file) is empty when target IS the file, so it fell back to `|| file` (the full path), yielding "root/<abs>" slugs and a false SLUG_MISMATCH. The pre-commit hook from install-hook validates staged files one-by-one, so this rejected every commit in a markdown brain (only bypassable with --no-verify). Walk up to the brain root (nearest .git) and use relative(brainRoot, file) || basename(file), matching runAudit/runGenerate and sync/extract. Files above the root fall back to basename instead of a ../-prefixed slug. Reopens #565. Present since v0.32.0; reproduced on v0.42.51. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(facts): pin embedding dims in facts-engine — kill the shard-order 1280/1536 flake facts-engine.test.ts hardcodes Float32Array(1536) vectors (vec()) but lets initSchema size its vector columns from process-global gateway state (getEmbeddingDimensions(), default 1280). Whether the file passes depends on which test files run before it in the shard; adding test/frontmatter-validate-slug-565.test.ts reshuffled the weight-packed shards and tripped it on this PR's CI (test (1): 'expected 1280 dimensions, not 1536' in findCandidateDuplicates cosine ordering). Same fix + rationale as doctor-hidden-by-search-policy.test.ts (#2801), engine-find-trajectory.test.ts and cosine-rescore-column.test.ts: configureGateway(1536) in beforeAll BEFORE initSchema, resetGateway in afterAll. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: alessioalionco <alessioalionco@gmail.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Garry Tan <garrytan@gmail.com>
66 lines
2.6 KiB
TypeScript
66 lines
2.6 KiB
TypeScript
import { describe, expect, test, beforeEach, afterEach } from 'bun:test';
|
|
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'fs';
|
|
import { join } from 'path';
|
|
import { tmpdir } from 'os';
|
|
import { spawnSync } from 'child_process';
|
|
|
|
const fence = '---';
|
|
|
|
function runValidate(path: string): { stdout: string; code: number } {
|
|
const r = spawnSync(process.execPath, ['run', 'src/cli.ts', 'frontmatter', 'validate', path], {
|
|
encoding: 'utf8',
|
|
cwd: process.cwd(),
|
|
env: process.env,
|
|
});
|
|
return { stdout: r.stdout ?? '', code: r.status ?? -1 };
|
|
}
|
|
|
|
// Regression for #565. Single-file `frontmatter validate` derived the expected
|
|
// slug from the ABSOLUTE path: `relative(resolve(target), file)` is empty when
|
|
// the target IS the file, so it fell back to `|| file` (the full path),
|
|
// yielding bogus "root/<abs-path>" slugs and a false SLUG_MISMATCH. The hook
|
|
// installed by `frontmatter install-hook` validates staged files one-by-one,
|
|
// so this rejected every commit in a markdown brain. The expected slug must be
|
|
// derived relative to the brain root (nearest `.git`).
|
|
describe('frontmatter validate single-file slug (#565)', () => {
|
|
let brain: string;
|
|
|
|
beforeEach(() => {
|
|
brain = mkdtempSync(join(tmpdir(), 'fm-565-'));
|
|
mkdirSync(join(brain, '.git'), { recursive: true }); // brain-root marker
|
|
});
|
|
|
|
afterEach(() => {
|
|
rmSync(brain, { recursive: true, force: true });
|
|
});
|
|
|
|
test('single file with a correct nested slug validates clean', () => {
|
|
mkdirSync(join(brain, 'companies'), { recursive: true });
|
|
const f = join(brain, 'companies', 'readme.md');
|
|
writeFileSync(f, `${fence}\ntype: company\ntitle: Readme\nslug: companies/readme\n${fence}\n\nbody`);
|
|
const { stdout, code } = runValidate(f);
|
|
expect(stdout).not.toContain('SLUG_MISMATCH');
|
|
expect(code).toBe(0);
|
|
});
|
|
|
|
test('directory validation still derives brain-root-relative slugs', () => {
|
|
mkdirSync(join(brain, 'people'), { recursive: true });
|
|
writeFileSync(
|
|
join(brain, 'people', 'alice.md'),
|
|
`${fence}\ntype: person\ntitle: Alice\nslug: people/alice\n${fence}\n\nbody`,
|
|
);
|
|
const { stdout, code } = runValidate(join(brain, 'people'));
|
|
expect(stdout).not.toContain('SLUG_MISMATCH');
|
|
expect(code).toBe(0);
|
|
});
|
|
|
|
test('file with no .git ancestor falls back to basename (no crash, no abs-path slug)', () => {
|
|
rmSync(join(brain, '.git'), { recursive: true, force: true });
|
|
const f = join(brain, 'note.md');
|
|
writeFileSync(f, `${fence}\ntype: note\ntitle: Note\nslug: note\n${fence}\n\nbody`);
|
|
const { stdout, code } = runValidate(f);
|
|
expect(stdout).not.toContain('SLUG_MISMATCH');
|
|
expect(code).toBe(0);
|
|
});
|
|
});
|