Skip to content

fix: run from directories without a local .cupcake policies folder (#104)#107

Open
punk-dev-robot wants to merge 3 commits into
eqtylab:mainfrom
punk-dev-robot:fix/issue-104-missing-local-policies-dir
Open

fix: run from directories without a local .cupcake policies folder (#104)#107
punk-dev-robot wants to merge 3 commits into
eqtylab:mainfrom
punk-dev-robot:fix/issue-104-missing-local-policies-dir

Conversation

@punk-dev-robot

@punk-dev-robot punk-dev-robot commented May 29, 2026

Copy link
Copy Markdown

Summary

Running a harness from a directory without a local .cupcake/policies/<harness> folder exited eval with code 1, blocking every tool call (#104). Two related causes:

  • Engine: the project policy scan errored on a missing dir, while the global scan already guards with .exists(). Mirror that guard so a missing project dir yields no policies and eval proceeds on global policies. Scanner stays strict (validate/inspect).
  • CLI: init --global emitted --policy-dir <global config root>, but eval treats --policy-dir as the project root and mis-resolved it, so local policies were never read (and pre-fix the bogus path exited 1). The global config auto-discovers independently, so global hooks now use the same project-relative path as project hooks ($CLAUDE_PROJECT_DIR/.cupcake, etc.).

Regression test added; cli + opencode/scanner/global suites pass.

Existing global installs must re-run cupcake init --global.

PunkDevRobot added 2 commits May 29, 2026 10:18
A missing project .cupcake/policies/<harness> dir made eval exit 1,
blocking every tool call. The project scan errored on a missing dir while
the global scan guards with .exists(); mirror that guard so eval proceeds
with global policies. Scanner stays strict. Adds a regression test.
init --global emitted --policy-dir <global config root>, but eval treats
it as the project root and mis-resolved it, so local policies were never
read (and pre-fix the bogus path exited 1). The global config auto-discovers
independently, so global hooks now use the same project-relative path as
project hooks. Existing global installs must re-run init --global.
@punk-dev-robot punk-dev-robot force-pushed the fix/issue-104-missing-local-policies-dir branch from b487aa9 to 7d81ab9 Compare May 29, 2026 09:18
@punk-dev-robot punk-dev-robot marked this pull request as ready for review May 29, 2026 09:22
Engine::new tolerates a missing project .cupcake/policies dir as of the
eqtylab#104 fix, initializing with global policies only. The binding smoke test
asserted is_err() on a bogus path; that path now yields Ok. Flip the
assertion to is_ok() to match the intended post-eqtylab#104 behavior.
@chozandrias76

Copy link
Copy Markdown

Confirming this reproduces on Claude Code with a global setup, not just OpenCode (matching @ahokinson on #104).

Symptom: after cupcake init --global --harness claude, every tool call in any directory without a local .cupcake/policies/claude exits the hook with code 1 (Fatal: ... Policy directory does not exist: ".../.cupcake/policies/claude"), so the agent can't run anything outside a Cupcake project.

We independently root-caused and fixed this the same way you did here — mirroring the .exists() guard from initialize_global() onto the project scan in engine/mod.rs. Two things that corroborate the approach:

  • The downstream init already tolerates an empty policy set (policies.is_empty()Ok, and non_system_count == 0 → skip WASM), so the guard alone is sufficient; no further changes needed for global-only operation.
  • After the guard, we verified a global deny policy is still enforced from a non-project directory (global config auto-discovers independently), and a benign command returns {} / exit 0.

Also +1 on the CLI half — init --global emitting --policy-dir <global config root> is a second, separate bug: eval treats --policy-dir as the project root and resolves it to <parent>/.cupcake, so project policies in the actual cwd are never read. Switching global hooks to the project-relative path is the right call.

This PR supersedes a local fix we'd staged, so we've dropped ours in favor of it. Thanks for getting to it. 🎂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants