Route prompts to matching skills + fix check-ignore git env leak in worktrees#156
Conversation
The gitignore-vendor-not-ignored rule shells out to git check-ignore with cwd set to the target app dir but inherited the process git environment. When webjs check (and thus npm test) runs inside a pre-commit hook from a linked worktree, git exports GIT_WORK_TREE / GIT_DIR / GIT_INDEX_FILE into the hook env, and those override cwd-based repo discovery, so the probe consulted the outer repo instead of the temp fixture. Net effect: the pre-commit test suite could not pass from any git worktree. Strip GIT_DIR / GIT_WORK_TREE / GIT_INDEX_FILE / GIT_PREFIX before spawning git check-ignore (and in the initGit test helper) so cwd is authoritative. Add a regression test that leaks GIT_WORK_TREE at the real repo and asserts the rule still reads the temp app gitignore. Closes #155
Skills are model-invoked, so a relevant one can be skipped when a prompt reads as research or a question but the work it leads to is governed by a skill. Skill descriptions and AGENTS.md prose are advisory; only a hook is deterministic, the same posture as block-prose-punctuation.sh for the em-dash rule. route-skills.sh runs on every prompt, keyword-matches against each skill's documented triggers, and injects a directive to invoke the matched skill before other work, plus a standing generic policy to check skills whenever a task matches one. A hook cannot force a Skill tool-call (Claude Code only lets UserPromptSubmit inject context), so keyword cases are deterministic and ambiguous prompts lean on the always-injected policy. Closes #154
The check.js env-strip fix shipped without its guard test (an Edit was lost). This adds the test: it leaks GIT_DIR/GIT_WORK_TREE at the real repo the way a worktree pre-commit hook does, then asserts the rule still reads the temp app's gitignore. Verified it fails when env: gitEnv is removed from check.js and passes with it. Refs #155
|
Self-review: missing regression test added The review caught a real blocker: I claimed a regression test for the GIT_* env-leak fix but it never landed (an Edit was dropped mid-session, so only the On the other points: the |
|
Review round 2: clean Re-reviewed after adding the regression test. Verified the counterfactual genuinely holds (test fails if |
* chore: release @webjsdev/core 0.7.3 and @webjsdev/server 0.8.3 Release debt accumulated since the 0.7.2 / 0.8.2 release (#149): core 0.7.3 (patch): the two client-router fixes from #151 and #157 (JS-handled forms and links were hijacked by the router despite e.preventDefault). server 0.8.3 (patch): #161 (modulepreload hints no longer point at server-only or template-embedded files the auth gate 404s) and #156 (webjs check no longer leaks a git env var across worktrees). Both stay in a single minor line; all in-repo dependents pin ^0.7.0 / ^0.8.0, so no dependent range edits are needed. Lockfile regenerated. * chore: release @webjsdev/cli 0.10.0 (webjs vendor surface) cli 0.9.1 shipped without the `webjs vendor` command surface that #105 and #89 added (pin / unpin / list / audit / outdated / update, the --from multi-CDN selector, and --download caching). That is feature-level work, so a minor bump. create-webjs and webjsdev are thin shims that delegate to cli; widen their `@webjsdev/cli` range from ^0.9.0 to ^0.10.0 so the workspace keeps linking the local cli (a minor bump falls outside the old caret). They are not in the changelog auto-publish system, so they carry no changelog entry of their own. Lockfile regenerated.
Summary
Closes #154
Closes #155
Two related fixes to agent tooling and test isolation, found while investigating why a skill (the issue-filing workflow) was silently skipped during a session.
1. Deterministic skill routing (#154)
Skills are model-invoked, so a relevant one can be skipped when a prompt reads as research or a question but the work it leads to is governed by a skill. (This happened: a "can we add prefetch, verify in remix, let me know" request was treated as pure research, so the issue-filing workflow never ran.) Skill descriptions and AGENTS.md prose are advisory; only a hook is deterministic, the same posture
block-prose-punctuation.shtakes for the em-dash rule..claude/hooks/route-skills.sh(new): aUserPromptSubmithook. On every prompt it keyword-matches the text against each skill's documented triggers (webjs-file-issue, webjs-start-work, webjs-list-todos, use-railway) and injects a directive to invoke the matched skill via the Skill tool before other work, plus a standing generic policy to check the available skills whenever a task matches one. The policy is generic across ALL skills, not a rule about filing GitHub issues specifically..claude/settings.json: registers the hook.AGENTS.md: documents it in the agent-config table and a new subsection.test/hooks/route-skills.test.mjs(new): covers each skill's triggers, the no-match standing-only case, single-route-per-skill.Honest limitation (documented in the hook + AGENTS.md): a hook CANNOT force a Skill tool-call.
UserPromptSubmitcan only injectadditionalContext. So keyword-matched prompts route deterministically, but genuinely-ambiguous prompts lean on the always-injected standing policy rather than a mechanical guarantee. The hook never blocks a prompt.2. check-ignore git env leak (#155)
The
gitignore-vendor-not-ignoredrule shells out togit check-ignorewithcwdset to the target app dir, but inherited the process git environment. Whenwebjs check(and thusnpm test) runs inside a pre-commit hook from a linked worktree, git exportsGIT_WORK_TREE/GIT_DIR/GIT_INDEX_FILEinto the hook env, and those override cwd-based repo discovery, so the probe consulted the outer repo instead of the temp fixture. Net effect: the pre-commit test suite could not pass from any git worktree (the workflow this session needed).Fix: strip
GIT_DIR/GIT_WORK_TREE/GIT_INDEX_FILE/GIT_PREFIXbefore spawninggit check-ignore(and in theinitGittest helper) socwdis authoritative. Added a regression test that leaksGIT_WORK_TREEat the real repo and asserts the rule still reads the temp app's gitignore. Verified: with the env-clear reverted, the regression test fails; with it, the full suite passes from a worktree.Test plan
node --test test/hooks/route-skills.test.mjs(7/7)gitignore-vendor-not-ignoredtests pass withGIT_WORK_TREEset in env (was failing)node scripts/run-node-tests.js1478/1478, from a linked worktreenpm testgate from the worktree (the thing check.js git check-ignore inherits GIT_* env, breaks in worktree pre-commit #155 unblocks).claude/; check.js git check-ignore inherits GIT_* env, breaks in worktree pre-commit #155 touches a convention-check rule and its test, no served wire or user-facing surface changed.