can1357/oh-my-pi · error · Error

Rule file not found: ${resolved}

Error message

Rule file not found: ${resolved}

What it means

`omp ttsr test --rule <path>` (and scan --rule) loads a standalone rule markdown file. readIsolatedRule resolves the path and verifies existence before parsing; a missing file throws this error with the absolute path. The rule is intentionally bypassed from project discovery, so the CLI has no other way to find it.

Source

Thrown at packages/coding-agent/src/cli/ttsr-cli.ts:303

async function loadProjectScanRules(cwd: string): Promise<Rule[]> {
	const settingsInstance = await Settings.init({ cwd });
	initializeWithSettings(settingsInstance);
	const ttsrSettings = settingsInstance.getGroup("ttsr");
	if (!ttsrSettings.enabled) {
		return [];
	}
	const result = await loadCapability<Rule>(ruleCapability.id, { cwd });
	return filterTtsrRulesForScan(result.items, {
		builtinRules: ttsrSettings.builtinRules,
		disabledRules: ttsrSettings.disabledRules,
	});
}

async function readIsolatedRule(rulePath: string): Promise<Rule> {
	const resolved = path.resolve(rulePath);
	const file = Bun.file(resolved);
	if (!(await file.exists())) {
		throw new Error(`Rule file not found: ${resolved}`);
	}
	const content = await file.text();
	const name = path.basename(resolved).replace(/\.(md|mdc)$/, "");
	return buildRuleFromMarkdown(name, content, resolved, createSourceMeta("ttsr-cli", resolved, "project"), {
		ruleName: name,
	});
}

async function loadIsolatedRule(rulePath: string): Promise<{ rules: Rule[]; manager: TtsrManager }> {
	const rule = await readIsolatedRule(rulePath);
	const manager = await createTtsrManager({
		enabled: true,
		contextMode: "discard",
		interruptMode: "always",
		repeatMode: "once",
		repeatGap: 10,
		builtinRules: true,
		disabledRules: [],

View on GitHub (pinned to 9690622007)

Solutions

  1. Fix the path in --rule to point at the actual .md/.mdc file (the error prints the resolved absolute path to compare against).
  2. Run `ls` on the rules directory to confirm the filename and extension (.md or .mdc).
  3. Re-run from the project root if you used a relative path.
  4. If the rule was renamed, update the path or use `omp ttsr list` to find rules already registered in project/user config.

Example fix

// before
omp ttsr test --snippet "..." --rule rule/no-secrets.md
// after
omp ttsr test --snippet "..." --rule rules/no-secrets.md
Defensive patterns

Strategy: validation

Validate before calling

import * as fs from "node:fs";
const resolved = path.resolve(rulePath);
if (!fs.existsSync(resolved) || !fs.statSync(resolved).isFile()) {
  throw new Error(`Rule file missing: ${resolved}`);
}

Try / catch

try {
  await runTest(args, json, cwd);
} catch (err) {
  if (err instanceof Error && err.message.startsWith("Rule file not found:")) {
    console.error(`${err.message}\n(cwd=${process.cwd()})`);
  }
  throw err;
}

Prevention

When it happens

Trigger: Running `omp ttsr test --rule <path>` where the markdown file does not exist at the resolved path — typo, wrong cwd, file deleted/renamed, or passing a directory instead of the .md/.mdc file.

Common situations: Testing a rule from a different repo whose path was copied incorrectly; rule files moved during a reorganization; shell glob not matching so a literal `rules/*.md` string was passed; relative path resolved against an unexpected cwd in scripts.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/b97178392a80360a. Report an issue: GitHub.