Commit Graph

15 Commits

Author SHA1 Message Date
John Lindquist 8e3350454c feat: prompt scoring improvements, compaction re-injection, validation dedup, strip droppedByCap from context; bump to 0.18.0
- Add dominant-topic suppression (top score >= 600 filters scores < 50)
- Add project-context boost (+3 for VERCEL_PLUGIN_LIKELY_SKILLS skills)
- Add lexical fallback floor (reject raw score < 20)
- Add compaction re-injection for priority >= 7 skills (VERCEL_PLUGIN_CONTEXT_COMPACTED)
- Add validation rule dedup tracking (ruleId + filePath on violations)
- Strip droppedByCap from injected HTML comments (kept in debug logs)
- Fix ncc/SKILL.md and next-forge/SKILL.md YAML frontmatter
- Add startup diagnostic for broken skill frontmatter
2026-03-11 19:01:59 -06:00
John Lindquist 8e24d0694a feat: add chainTo skill chaining, prompt signals, validation upgrades, and dedup reset on context clear
Add a chainTo frontmatter field to skills that triggers follow-up skill injection
when PostToolUse file contents match regex patterns. Add upgradeToSkill/upgradeWhy
fields to validation rules so validate errors can recommend loading a specific skill.
Register posttooluse-bash-chain.mjs in hooks.json. Add ChainToRule interface to
patterns.mts and skill-map-frontmatter.mts, with parseChainToRules() parser. Add
duplicate-key detection to the YAML parser. Reset dedup claim dir and session file
on clear/compact events in session-start-seen-skills so skills re-inject into fresh
context windows.

Add chainTo rules to: agent-browser-verify, agent-browser, ai-elements, ai-gateway,
ai-generation-persistence, ai-sdk, auth, bootstrap, chat-sdk, cms, cron-jobs,
deployments-cicd, email, env-vars, geist, investigation-mode, json-render,
marketplace, micro, ncc, next-forge, nextjs, observability, payments,
react-best-practices, routing-middleware, runtime-cache, satori, shadcn,
sign-in-with-vercel, swr, turbopack, turborepo, v0-dev, vercel-agent, vercel-api,
vercel-cli, vercel-firewall, vercel-flags, vercel-functions, vercel-queues,
vercel-sandbox, vercel-storage, verification, workflow. Add upgradeToSkill to
ai-elements and ai-sdk validate rules. Expand ai-sdk validate messages with
Run Skill() hints. Update nextjs, vercel-storage, runtime-cache, workflow, turborepo
skill bodies.

Add new skills: geistdocs (Geist design system docs), zzz-test-meta-name-mask
(test fixture). Add skills/_chain-audit.md chain coverage audit doc.

Delete .claude-plugin/marketplace.json, .claude-plugin/plugin.json (deprecated),
skills/edge-runtime/SKILL.md (consolidated into vercel-functions).

Add tests: posttooluse-chain.test.ts (4699 lines, chain injection e2e),
ai-sdk-companion.test.ts (181 lines). Expand build-skill-map.test.ts (+335 lines),
validate-rules.test.ts (+936 lines), session-start-seen-skills.test.ts (+74 lines),
skill-map-frontmatter.test.ts (+50 lines), verification-skill.test.ts (+20 lines).

Update build-manifest.ts to emit chainTo rules and upgradeToSkill fields. Rebuild
generated/skill-manifest.json, generated/skill-catalog.md, generated/build-from-skills.manifest.json.
Rebuild all compiled hooks/*.mjs. Update CLAUDE.md lexical prompt default to on.
Update vercel.md ecosystem graph, docs, and cli-reference.
2026-03-11 15:18:35 -06:00
John Lindquist 9bec068d63 fix(posttool): drop seen-skills env merge from validate and bash-chain hooks
Both posttool hooks now consult the persisted session-backed seen-skills state instead of merging in VERCEL_PLUGIN_SEEN_SKILLS. This keeps dedup behavior consistent across subagents and avoids env leakage into hook chaining decisions.

Verified: bun run build:hooks
Verified: tsc -p hooks/tsconfig.json --noEmit
Verified: bun test tests/posttooluse-validate.test.ts
Verified: bun test hooks/platform-hook-compat.test.ts
Verified: bun -e '...runChainInjection smoke for session-file-only seen-skills...'
Verified: bun -e '...runBashChainInjection smoke for session-file-only seen-skills...'
Swarm-Agent: codex-posttool-commit
2026-03-11 15:18:19 -06:00
John Lindquist 8d8faffe57 fix(hooks): add cursor support to posttool validator
Normalize PostToolUse stdin with compat-based platform detection and Cursor workspace/session fallbacks.
Emit Cursor additional_context/env payloads while preserving Claude output shape and empty-result behavior.

Verified: bun test hooks/platform-hook-compat.test.ts
Verified: bun --eval 'import assert from "node:assert/strict"; import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { formatOutput, markValidated } from "./hooks/src/posttooluse-validate.mts"; const tempDir = mkdtempSync(join(tmpdir(), "posttooluse-validate-")); const envFile = join(tempDir, "claude.env"); writeFileSync(envFile, "", "utf-8"); delete process.env.VERCEL_PLUGIN_VALIDATED_FILES; process.env.CLAUDE_ENV_FILE = envFile; const next = markValidated("app/page.tsx", "abc123def456", null); assert.equal(next, "app/page.tsx:abc123def456"); assert.match(readFileSync(envFile, "utf-8"), /VERCEL_PLUGIN_VALIDATED_FILES="app\/page\.tsx:abc123def456"/); const output = JSON.parse(formatOutput([{ skill: "ai-sdk", line: 8, message: "Use streamText for streaming responses.", severity: "recommended", matchedText: "generateText" }], ["ai-sdk"], "app/page.tsx", undefined, "cursor", { VERCEL_PLUGIN_VALIDATED_FILES: next })); assert.equal(output.env.VERCEL_PLUGIN_VALIDATED_FILES, next); rmSync(tempDir, { recursive: true, force: true }); delete process.env.CLAUDE_ENV_FILE; delete process.env.VERCEL_PLUGIN_VALIDATED_FILES;'
Swarm-Agent: codex-posttool-validate-v2
2026-03-11 15:17:02 -06:00
John Lindquist e91067f1aa chore(hooks): drop accidental generated artifacts
Restore generated hook outputs that were accidentally committed when the
repo pre-commit hook rebuilt the entire hooks directory. This follow-up
keeps this agent's change set focused on the UserPromptSubmit source and
tests without touching the in-progress source files owned by other agents.

Verified: bun test hooks/user-prompt-submit-skill-inject.test.ts tests/user-prompt-submit.test.ts
Verified: restored generated outputs to their HEAD~1 content for six unrelated hook artifacts
Swarm-Agent: codex-prompt-hook
2026-03-11 15:17:02 -06:00
John Lindquist 1142c51906 fix(user-prompt-submit): support cursor prompt hook
Normalize UserPromptSubmit input fields across Claude Code and Cursor,
including conversation/session IDs, cwd roots, and prompt/message
fallbacks. Cursor now returns flat beforeSubmitPrompt output with
continue:true and emits seen-skill env patches when no CLAUDE_ENV_FILE is
available, while Claude continues using hookSpecificOutput and appends
seen-skill exports to CLAUDE_ENV_FILE when present.

Verified: bun test hooks/user-prompt-submit-skill-inject.test.ts tests/user-prompt-submit.test.ts
Verified: cursor beforeSubmitPrompt payload returns continue:true + env patch in tests/user-prompt-submit.test.ts
Swarm-Agent: codex-prompt-hook
2026-03-11 15:17:02 -06:00
John Lindquist 994a5431a8 fix(posttooluse-validate): dedupe skill upgrade instructions
formatOutput now emits a single skill-upgrade instruction block per target skill, adds the requested blank line and reason text, and marks hard upgrades as REQUIRED so agents get clearer follow-up actions.

Verified: bun run build:hooks
Verified: bun test tests/posttooluse-validate.test.ts
Verified: bun run typecheck
Swarm-Agent: codex-hook-chain
2026-03-11 15:16:21 -06:00
John Lindquist 4525723e15 feat(hooks): add skill upgrade metadata to validate rules
Validate rules can now carry optional skill-upgrade metadata from SKILL.md frontmatter through the post-tool-use validator. When a matching rule requests an upgrade, the hook output now emits both human-readable Skill tool guidance and a machine-readable HTML comment for downstream parsing.

Verified: bun run typecheck
Verified: bun -e 'const mod = await import("./hooks/src/posttooluse-validate.mts"); const violations = mod.runValidation("foo\n", ["source-skill"], new Map([["source-skill", [{ pattern: "foo", message: "needs upgrade", severity: "error", upgradeToSkill: "target-skill", upgradeWhy: "more specific context" }]] ])); const out = JSON.parse(mod.formatOutput(violations, ["source-skill"], "/tmp/test.ts")); console.log(JSON.stringify(violations)); console.log(out.hookSpecificOutput.additionalContext);'
Verified: bun -e 'const mod = await import("./hooks/src/skill-map-frontmatter.mts"); const parsed = mod.parseSkillFrontmatter(`validate:\n  -\n    pattern: foo\n    message: needs upgrade\n    severity: error\n    upgradeToSkill: target-skill\n    upgradeWhy: use the more specific skill\n  -\n    pattern: bar\n    message: hard upgrade\n    severity: warn\n    upgradeToSkill: hard-skill\n    upgradeMode: hard\n`); console.log(JSON.stringify(parsed.validate));'
Swarm-Agent: codex-schema
2026-03-11 15:16:21 -06:00
John Lindquist d5b5ef47f7 Replace skill body injection with Skill tool invocation instructions
Instead of injecting the full SKILL.md body as additionalContext, inject
"You must run the Skill(<name>) tool." — a more conventional way of
telling the agent to use the Skill tool for context loading.
2026-03-10 12:46:11 -06:00
John Lindquist a43cb60a64 fix(skills): stronger outdated model warnings with "your knowledge is outdated" language, make AI Elements mandatory for AI text rendering; bump to 0.9.8 2026-03-09 07:59:56 -06:00
John Lindquist c45856f4f7 fix(hooks): persist session dedup state via temp files
PreToolUse and PostToolUse dedup state was previously process-local, which broke across hook subprocess invocations.\nThis change adds session-scoped temp-file persistence and threads session_id through the relevant flows.\n\nPreToolUse now falls back to per-session seen-skills file state and writes back on every appendSeenSkill update.\nPostToolUse now checks persisted validated-files state and writes updates after marking files validated.\n\nVerified: bun run build:hooks\nVerified: bun test tests/pretooluse-skill-inject.test.ts tests/posttooluse-validate.test.ts\nSwarm-Agent: codex-dedup-core
2026-03-07 14:57:23 -07:00
John Lindquist cbf4ed8a3e revert(hooks): remove temp file dedup, restore pure env-var dedup via CLAUDE_ENV_FILE; bump to 0.5.5
The 0.5.4 release added session-scoped temp files for dedup persistence, but this
was wrong — CLAUDE_ENV_FILE env vars ARE propagated to hook subprocesses by Claude
Code. The temp file approach littered tmpdir with hundreds of small files.

Revert to the original env-var-only mechanism:

1. Remove readSessionFile/writeSessionFile/dedupFilePath from hooks/src/hook-env.mts
2. Remove all writeSessionFile calls from pretooluse-skill-inject.mts — revert to
   pure process.env.VERCEL_PLUGIN_SEEN_SKILLS = appendSeenSkill(...) pattern
3. Remove sessionId from InjectOptions and the injectSkills call site
4. Remove sessionId from posttooluse-validate.mts ParsedInput — revert
   isAlreadyValidated/markValidated to pure env-var signatures
5. Revert all test expectations back to "env-var" and "memory-only" strategies
6. Restore CLAUDE.md dedup contract to env-var-only documentation
2026-03-07 14:39:08 -07:00
John Lindquist c107aec73d fix(hooks): persist skill dedup across hook invocations via session-scoped temp files; bump to 0.5.4
Skill dedup is completely broken because CLAUDE_ENV_FILE vars are only available to Bash
tool commands, not hook subprocesses. Each PreToolUse invocation starts a fresh Node.js
process that never sees VERCEL_PLUGIN_SEEN_SKILLS.

To fix this:

1. In hooks/src/hook-env.mts, add readSessionFile(sessionId, kind) and
   writeSessionFile(sessionId, kind, value) helpers that read/write
   /tmp/vercel-plugin-<sessionId>-<kind>.txt for persistent dedup state.

2. In hooks/src/pretooluse-skill-inject.mts, read seen skills from the session file
   at startup using readSessionFile(sessionId, "seen-skills"). Add a persistSeen()
   closure inside injectSkills() that calls both appendSeenSkill and writeSessionFile.
   Replace all process.env.VERCEL_PLUGIN_SEEN_SKILLS = appendSeenSkill(...) calls with
   persistSeen() or inline writeSessionFile calls. Add "file" as the primary dedup
   strategy when session_id is present, falling back to "env-var" then "memory-only".
   Pass sessionId through InjectOptions to injectSkills().

3. In hooks/src/posttooluse-validate.mts, add sessionId to ParsedInput and extract it
   from input.session_id in parseInput(). Pass sessionId to isAlreadyValidated() and
   markValidated(), which should read/write via readSessionFile/writeSessionFile for
   the "validated-files" kind.

4. Update tests: pretooluse-skill-inject.test.ts — rename "no env var" test to expect
   file-based dedup persistence, update strategy assertions from "env-var" to "file",
   use omitSessionId for memory-only test. subagent-fresh-env.test.ts — use a fresh
   session ID for subagent calls, update strategy expectations to "file".
   session-timeline-subagent.test.ts — add sessionId option to runHookEnv, use a
   different session ID for the subagent call.

5. Update CLAUDE.md dedup contract section to document file-based mechanism.

6. Bump .plugin/plugin.json version to 0.5.4, run bun run build.
2026-03-07 14:23:09 -07:00
John Lindquist 365a710e67 feat(hooks): add prompt analysis, enhance validate/frontmatter hooks, expand test coverage; bump to 0.5.2 2026-03-07 13:09:28 -07:00
John Lindquist ff251ab018 refactor(hooks): move audit log to ~/.claude/projects dir; add validate hooks, prompt patterns, benchmark suite; bump to 0.5.1 2026-03-07 12:31:10 -07:00