Skip to content

Add Intent hook enforcement for supported agents#174

Open
LadyBluenotes wants to merge 13 commits into
mainfrom
intent-agent-invocation-evals
Open

Add Intent hook enforcement for supported agents#174
LadyBluenotes wants to merge 13 commits into
mainfrom
intent-agent-invocation-evals

Conversation

@LadyBluenotes

@LadyBluenotes LadyBluenotes commented Jun 21, 2026

Copy link
Copy Markdown
Member

Summary

Adds intent hooks install support for lifecycle-hook enforcement across supported agents, with project/user scope handling, generated hook runner scripts, and agent-specific policy wiring.

Includes docs and eval coverage for hooked intent discovery, plus validation updates so the hook flow is covered by the existing PR and integration gates.

Summary by CodeRabbit

  • New Features

    • Added intent hooks install command for configuring AI coding agents (Claude, Codex, Copilot) with lifecycle-hook enforcement.
    • Updated intent guidance block format from skills to tanstackIntent schema with id, run, and for fields.
  • Documentation

    • Added CLI documentation for the new hooks install command with per-agent scope guidance.
    • Updated install command documentation to reflect the new guidance block format.
    • Updated Quick Start guide with hook installation instructions for supported agents.
    • Updated overview to document hook enforcement capabilities.

…very evals

- Introduce 'hooked-intent' condition in conditions.ts
- Implement live-router-hooked-intent task in live-tasks.ts
- Create gate.mjs and hook-core.mts for intent hooks management
- Add hook-io.mjs for event handling and observation logging
- Implement prepare-copilot-home.ts for managing copilot home directory
- Update run-copilot-task.ts to support gate state management
- Enhance setup-intent-condition.ts to handle hooked-intent
- Add tests for hooked-intent functionality in intent-hooks.eval.ts
- Update vitest configuration for live concurrency settings
…ocumentation

- Added `--hooks` option to `intent install` for lifecycle hook installation.
- Updated documentation to reflect new hook options and usage.
- Introduced hook adapters for Claude, Codex, and Copilot with project/user scope support.
- Implemented tests to verify supported scopes in the adapter registry.
…ated install command and enhance type definitions
@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds a new intent hooks install CLI command that installs lifecycle-hook enforcement scripts for supported AI coding agents (Claude, Codex, Copilot). It migrates the managed install mapping block schema from skills/when/use to tanstackIntent/id/run/for, reorganizes the package's source modules into core/, setup/, discovery/, shared/, skills/, and staleness/ subdirectories, and extends the eval harness with a new hooked-intent condition and Copilot gate infrastructure.

Changes

Intent CLI, hooks, schema, and eval updates

Layer / File(s) Summary
Module boundary reorganization and command wiring
packages/intent/src/core.ts, packages/intent/src/core/index.ts, packages/intent/src/core/intent-core.ts, packages/intent/src/setup.ts, packages/intent/src/setup/index.ts, packages/intent/src/setup/project-setup.ts, packages/intent/src/index.ts, packages/intent/src/cli.ts, packages/intent/src/commands/support.ts, packages/intent/src/commands/..., packages/intent/src/discovery/..., packages/intent/src/staleness/..., packages/intent/src/shared/..., packages/intent/src/skills/..., packages/intent/tests/...
core.ts and setup.ts become single-line re-exports; implementations move into core/intent-core.ts and setup/project-setup.ts under new barrel index files. CLI command handlers switch dynamic imports from legacy flat paths to commands/support.js, commands/setup/..., and core/index.js. Discovery, staleness, shared, and skills modules all update their cross-module imports to point at the new subdirectory layout; all tests follow suit.
Install mapping schema migration to tanstackIntent
packages/intent/src/commands/install/guidance.ts, packages/intent/src/commands/install/command.ts, packages/intent/src/skills/categories.ts, evals/intent-discovery/condition-setup.eval.ts, packages/intent/tests/install-writer.test.ts, packages/intent/tests/cli.test.ts, packages/intent/tests/integration/source-policy-surfaces.test.ts, packages/intent/tests/skill-categories.test.ts
Guidance generation replaces skills/when/use YAML entries with a tanstackIntent list of id/run/for mappings; verification now validates those three fields via parseSkillUse on id. A new skills/categories.ts module classifies skills and exposes isGeneratedMappingSkill to control which skills produce map entries. INSTALL_PROMPT rules and verification checklist are updated. All install-writer, CLI, and integration tests assert the new field names.
Hook types, policy, adapters, installer, and CLI command
packages/intent/src/hooks/types.ts, packages/intent/src/hooks/policy.ts, packages/intent/src/hooks/adapters.ts, packages/intent/src/hooks/agents/..., packages/intent/src/hooks/install.ts, packages/intent/src/commands/hooks/command.ts, packages/intent/tests/hooks.test.ts, packages/intent/tests/hooks-install.test.ts
New hooks/types.ts defines HookAgent, HookInstallScope, IntentInvocation, IntentObservation, HookDecision, and ToolEvent. hooks/policy.ts implements command parsing, Bash-only observation extraction, per-agent edit-tool gating, and load detection. hooks/adapters.ts maps each agent to its config/script paths by scope. Per-agent formatter modules (Claude, Codex, Copilot) produce typed deny payloads. hooks/install.ts orchestrates script generation, JSON config upserts, and idempotent file writes. The hooks install CLI command is wired through commands/hooks/command.ts. Unit tests cover policy parsing, gating behavior, and end-to-end install/reinstall scenarios including runtime script execution.
Hooked-intent eval harness and live task wiring
evals/intent-discovery/harness/intent-hooks/..., evals/intent-discovery/harness/prepare-copilot-home.ts, evals/intent-discovery/harness/run-copilot-task.ts, evals/intent-discovery/harness/setup-intent-condition.ts, evals/intent-discovery/corpus/conditions.ts, evals/intent-discovery/corpus/live-tasks.ts, evals/intent-discovery/intent-hooks.eval.ts, evals/intent-discovery/live-copilot-harness.eval.ts, evals/intent-discovery/vitest.evals.config.ts, knip.json
A standalone gate.mjs CLI plus hook-core.mjs/hook-io.mjs modules implement the eval-harness gate (stdin event parsing, observation persistence, allow/deny decisions). prepare-copilot-home.ts builds a per-process gate Copilot home with a hooks.json wired to gate.mjs. run-copilot-task.ts injects COPILOT_HOME and INTENT_DISCOVERY_GATE_STATE for hooked-intent tasks. New hooked-intent corpus condition and live-router-hooked-intent task are registered. live-copilot-harness.eval.ts switches to describe.concurrent. Vitest config adds maxConcurrency from INTENT_DISCOVERY_LIVE_CONCURRENCY.
Documentation, navigation, and changeset updates
docs/cli/intent-hooks.md, docs/cli/intent-install.md, docs/config.json, docs/getting-started/quick-start-consumers.md, docs/overview.md, packages/intent/README.md, .changeset/hot-bottles-float.md
New docs/cli/intent-hooks.md documents hooks install command syntax, scope/agent options, and per-agent behavior. intent-install.md updates the --map examples to the tanstackIntent schema and adds a link to hooks. Quick-start and overview pages gain managed intent-skills blocks, hooks install instructions, and a new "hook enforcement" bullet. CLI nav config and README command table include the new entry. Changeset marks @tanstack/intent as a minor release.

Sequence Diagram(s)

sequenceDiagram
  participant agent as AI Agent (e.g. Copilot)
  participant hook as gate.mjs / hook runner
  participant state as JSONL state file
  participant policy as gateDecision()
  participant agent2 as Agent continues

  agent->>hook: PreToolUse event (stdin JSON)
  hook->>state: readObservations()
  state-->>hook: prior observations[]
  hook->>policy: gateDecision({toolName, hasLoaded})
  alt hasLoaded is false AND toolName is edit tool
    policy-->>hook: deny + GATE_DENY_REASON
    hook->>agent: stdout JSON permissionDecision: deny
  else intent list or load command
    hook->>state: appendObservation({action, skillUse})
    hook->>agent: no output (allow)
  else other tool or already loaded
    policy-->>hook: allow
    hook->>agent2: no output (allow)
  end
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

  • TanStack/intent#85: Both PRs touch packages/intent/src/cli.ts and the command dispatch layer to rewire shared error/support helpers, indicating this PR builds on the same CLI refactor foundation.
  • TanStack/intent#115: Both PRs modify the intent install managed-block mapping generation and --map output semantics in the same install command codepaths and related docs/tests.
  • TanStack/intent#173: This PR directly extends the evals/intent-discovery harness introduced in that PR by adding the hooked-intent gating condition, new corpus entries, and run-copilot-task environment plumbing.

Suggested reviewers

  • KyleAMathews
  • KevinVandy

Poem

🐰 Hop hop, the hooks are here at last!
A gate now guards each edit tool so fast.
tanstackIntent replaces the old skills,
New subfolders tidy all the spills.
The rabbit cheers — no file touched unblessed,
Load your guidance first, then do the rest! 🎉

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description provides a clear summary of changes but lacks the structured sections required by the template (Checklist items are missing). Add the Checklist section with the two required items (Contributing guide and local testing) and mark Release Impact appropriately.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main addition: Intent hook enforcement for supported agents, which directly aligns with the primary changes in the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch intent-agent-invocation-evals

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud

nx-cloud Bot commented Jun 21, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit d5c9525

Command Status Duration Result
nx run-many --targets=build --exclude=examples/** ✅ Succeeded <1s View ↗

☁️ Nx Cloud last updated this comment at 2026-06-21 05:46:46 UTC

@pkg-pr-new

pkg-pr-new Bot commented Jun 21, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/TanStack/intent/@tanstack/intent@174

commit: a88f636

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@evals/intent-discovery/harness/intent-hooks/hook-core.mjs`:
- Around line 1-3: The INTENT_COMMAND_PATTERN regex has two issues: the leading
`\s` alternative allows false positives by matching plain text mentions like
"echo intent load" as valid commands, and the pattern is missing the `||`
operator from the command-chain alternatives, creating inconsistency with the
production parser. Remove or restrict the `\s` alternative to only match at
proper command boundaries (start of line or after actual command delimiters like
&&, ;, |) and add `||` to the list of command separators in the initial
alternation group to match the production parser in
packages/intent/src/hooks/policy.ts.

In `@packages/intent/src/commands/install/command.ts`:
- Around line 112-114: The verification checklist comment at lines 112-114 in
the install command file promises to validate conditions (checking
`id`/`run`/`for` presence, validating `id` format as `<package>#<skill>`, and
rejecting local file paths) that are not actually enforced by the
`verifyIntentSkillsBlockFile` function in guidance.ts. Update the checklist
comment to accurately reflect only what the verifier currently validates (field
presence/types and `id` parseability), or alternatively enhance the
`verifyIntentSkillsBlockFile` verification function to add the missing
validations for ensuring `run` references match the parsed `id` and rejecting
any path-like values in mapping fields.

In `@packages/intent/src/commands/install/guidance.ts`:
- Around line 4-7: The import statements at the top of the file are not in the
correct order according to the import/order lint rule. Move the value import
statement containing formatSkillUse and parseSkillUse from `../../skills/use.js`
to appear before the type-only import statement containing ScanResult and
SkillEntry from `../../shared/types.js`. Value imports should be ordered before
type-only imports to comply with the linting configuration.

In `@packages/intent/src/commands/load.ts`:
- Around line 1-9: The imports at the top of the load.ts file are not ordered
according to the configured import/order ESLint rule. Reorganize the imports by
grouping type imports separately from regular imports, placing all regular value
imports first (including the imports from '../shared/cli-error.js',
'./support.js', and '../core/index.js'), then group all type imports together at
the end (the type imports from './support.js' and '../core/index.js'). This
ensures compliance with the import ordering convention used in the project.

In `@packages/intent/src/commands/validate.ts`:
- Around line 8-11: The import statement for printWarnings from ./support.js is
positioned incorrectly according to the import/order lint rule. Move the import
statement for printWarnings from ./support.js to appear after the import
statement for findWorkspacePackages from ../setup/workspace-patterns.js, so that
relative imports to parent directories come before relative imports to the
current directory.

In `@packages/intent/src/core/intent-core.ts`:
- Around line 2-16: The import ordering at the top of intent-core.ts violates
the configured rule where parent directory imports (../...) should be placed
before current directory imports (./...). Currently, the imports from
../discovery/fs-cache.js, ../skills/resolver.js, and ../skills/use.js are
scattered throughout the block after ./excludes.js and other ./ imports.
Reorganize the import statements by moving all parent directory imports (those
starting with ../) to the top of the import block, followed by all current
directory imports (those starting with ./), while preserving the internal
ordering within each group.

In `@packages/intent/src/discovery/scanner.ts`:
- Around line 9-24: The imports in the scanner.ts file violate the import/order
linting rule. Reorganize the imports so that the type imports (import type
statements for IntentFsCache and ReadFs) are placed at the end of the import
block, after all regular imports. Additionally, ensure that the regular imports
are ordered correctly with relative imports from the current directory
(./index.js, ./fs-cache.js, ./package-manager.js) appearing before parent
directory imports (../setup/workspace-patterns.js and ../shared/utils.js). This
will comply with the configured linting rules for import ordering.

In `@packages/intent/src/hooks/install.ts`:
- Around line 380-384: The isIntentHook function uses overly broad substring
matching on the entire serialized object, which can incorrectly identify
non-Intent hooks if they happen to contain 'intent-' and '-gate.mjs' anywhere in
their fields. Narrow the detection logic to check only the specific hook
identifier field (such as the hook name property) rather than the entire
serialized object, ensuring that only actual Intent hooks matching the expected
naming pattern are identified and preventing false positives that could lead to
deletion of unrelated hook entries during reinstall.

In `@packages/intent/src/setup/project-setup.ts`:
- Line 14: The import statement for resolveProjectContext from
'../core/project-context.js' at line 14 violates the ESLint import/order rule,
which enforces a specific ordering for imports. Review all import statements in
the project-setup.ts file and reorder the resolveProjectContext import to comply
with the enforced import order rules, which typically require relative parent
directory imports (../) to be grouped together and ordered correctly relative to
other imports like external packages and internal modules.
- Around line 175-217: The code currently treats URL-valued intent.docs (like
https://...) as file paths and appends /** to create invalid glob patterns.
Before constructing the docsPath and WATCH_PATHS, add a check to detect if the
docs value is a URL by checking if it starts with http:// or https://. For URL
values, skip the glob path transformation (the .replace(/\/$/, '') + '/**'
pattern) and handle them appropriately, so that remote URLs are not converted
into invalid file-watch globs like https://.../**. This check should be applied
to both the docsPath assignment and the WATCH_PATHS string construction in the
single-package mode branch.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ebc56361-5c29-4645-9d59-69fd8c3af984

📥 Commits

Reviewing files that changed from the base of the PR and between 559dd06 and a88f636.

📒 Files selected for processing (96)
  • .changeset/hot-bottles-float.md
  • docs/cli/intent-hooks.md
  • docs/cli/intent-install.md
  • docs/config.json
  • docs/getting-started/quick-start-consumers.md
  • docs/overview.md
  • evals/intent-discovery/README.md
  • evals/intent-discovery/condition-setup.eval.ts
  • evals/intent-discovery/corpus/conditions.ts
  • evals/intent-discovery/corpus/live-tasks.ts
  • evals/intent-discovery/harness/intent-hooks/gate.mjs
  • evals/intent-discovery/harness/intent-hooks/hook-core.d.mts
  • evals/intent-discovery/harness/intent-hooks/hook-core.mjs
  • evals/intent-discovery/harness/intent-hooks/hook-io.mjs
  • evals/intent-discovery/harness/prepare-copilot-home.ts
  • evals/intent-discovery/harness/run-copilot-task.ts
  • evals/intent-discovery/harness/setup-intent-condition.ts
  • evals/intent-discovery/intent-hooks.eval.ts
  • evals/intent-discovery/live-copilot-harness.eval.ts
  • evals/intent-discovery/vitest.evals.config.ts
  • knip.json
  • packages/intent/README.md
  • packages/intent/src/cli.ts
  • packages/intent/src/commands/exclude.ts
  • packages/intent/src/commands/hooks/command.ts
  • packages/intent/src/commands/install/command.ts
  • packages/intent/src/commands/install/guidance.ts
  • packages/intent/src/commands/list.ts
  • packages/intent/src/commands/load.ts
  • packages/intent/src/commands/meta.ts
  • packages/intent/src/commands/setup/edit-package-json.ts
  • packages/intent/src/commands/setup/github-actions.ts
  • packages/intent/src/commands/stale.ts
  • packages/intent/src/commands/support.ts
  • packages/intent/src/commands/validate.ts
  • packages/intent/src/core.ts
  • packages/intent/src/core/index.ts
  • packages/intent/src/core/intent-core.ts
  • packages/intent/src/core/load-resolution.ts
  • packages/intent/src/core/markdown.ts
  • packages/intent/src/core/project-context.ts
  • packages/intent/src/core/source-policy.ts
  • packages/intent/src/core/types.ts
  • packages/intent/src/discovery/fs-cache.ts
  • packages/intent/src/discovery/package-manager.ts
  • packages/intent/src/discovery/register.ts
  • packages/intent/src/discovery/scanner.ts
  • packages/intent/src/discovery/walk.ts
  • packages/intent/src/hooks/adapters.ts
  • packages/intent/src/hooks/agents/claude.ts
  • packages/intent/src/hooks/agents/codex.ts
  • packages/intent/src/hooks/agents/copilot.ts
  • packages/intent/src/hooks/install.ts
  • packages/intent/src/hooks/policy.ts
  • packages/intent/src/hooks/types.ts
  • packages/intent/src/index.ts
  • packages/intent/src/setup.ts
  • packages/intent/src/setup/index.ts
  • packages/intent/src/setup/project-setup.ts
  • packages/intent/src/setup/workspace-patterns.ts
  • packages/intent/src/shared/cli-error.ts
  • packages/intent/src/shared/cli-output.ts
  • packages/intent/src/shared/command-runner.ts
  • packages/intent/src/shared/display.ts
  • packages/intent/src/shared/types.ts
  • packages/intent/src/shared/utils.ts
  • packages/intent/src/skills/categories.ts
  • packages/intent/src/skills/paths.ts
  • packages/intent/src/skills/resolver.ts
  • packages/intent/src/skills/use.ts
  • packages/intent/src/staleness/artifact-coverage.ts
  • packages/intent/src/staleness/check.ts
  • packages/intent/src/staleness/index.ts
  • packages/intent/src/staleness/workflow-review.ts
  • packages/intent/tests/artifact-coverage.test.ts
  • packages/intent/tests/cli.test.ts
  • packages/intent/tests/core.test.ts
  • packages/intent/tests/fs-cache.test.ts
  • packages/intent/tests/hooks-install.test.ts
  • packages/intent/tests/hooks.test.ts
  • packages/intent/tests/install-writer.test.ts
  • packages/intent/tests/integration/source-policy-surfaces.test.ts
  • packages/intent/tests/parse-frontmatter.test.ts
  • packages/intent/tests/read-scalar-field.test.ts
  • packages/intent/tests/resolver.test.ts
  • packages/intent/tests/scanner.test.ts
  • packages/intent/tests/setup.test.ts
  • packages/intent/tests/skill-categories.test.ts
  • packages/intent/tests/skill-paths.test.ts
  • packages/intent/tests/skill-use.test.ts
  • packages/intent/tests/skills.test.ts
  • packages/intent/tests/source-policy.test.ts
  • packages/intent/tests/stale-command.test.ts
  • packages/intent/tests/staleness.test.ts
  • packages/intent/tests/workflow-review.test.ts
  • packages/intent/tests/workspace-patterns.test.ts

Comment on lines +1 to +3
const INTENT_COMMAND_PATTERN =
/(?:^|\s|&&|;|\|)\s*((?:bunx\s+@tanstack\/intent(?:@latest)?)|(?:pnpm\s+exec\s+intent)|(?:pnpm\s+dlx\s+@tanstack\/intent(?:@latest)?)|(?:npx\s+@tanstack\/intent(?:@latest)?)|(?:yarn\s+dlx\s+@tanstack\/intent(?:@latest)?)|(?:intent))\s+(list|load)(?:\s+([^\s|;&]+))?/i

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Regex in Line 2 allows false positives and diverges from the production parser.

The \s alternative makes plain text mentions parse as commands (e.g. echo intent load ...), which can incorrectly flip hasLoaded to true. It also omits ||, so command-chain coverage is inconsistent with packages/intent/src/hooks/policy.ts Line 10.

Suggested fix
-const INTENT_COMMAND_PATTERN =
-  /(?:^|\s|&&|;|\|)\s*((?:bunx\s+@tanstack\/intent(?:`@latest`)?)|(?:pnpm\s+exec\s+intent)|(?:pnpm\s+dlx\s+@tanstack\/intent(?:`@latest`)?)|(?:npx\s+@tanstack\/intent(?:`@latest`)?)|(?:yarn\s+dlx\s+@tanstack\/intent(?:`@latest`)?)|(?:intent))\s+(list|load)(?:\s+([^\s|;&]+))?/i
+const INTENT_COMMAND_PATTERN =
+  /(?:^|&&|\|\||;|\|)\s*((?:bunx\s+@tanstack\/intent(?:`@latest`)?)|(?:pnpm\s+exec\s+intent)|(?:pnpm\s+dlx\s+@tanstack\/intent(?:`@latest`)?)|(?:npx\s+@tanstack\/intent(?:`@latest`)?)|(?:yarn\s+dlx\s+@tanstack\/intent(?:`@latest`)?)|(?:intent))\s+(list|load)(?:\s+([^\s|;&]+))?/i
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const INTENT_COMMAND_PATTERN =
/(?:^|\s|&&|;|\|)\s*((?:bunx\s+@tanstack\/intent(?:@latest)?)|(?:pnpm\s+exec\s+intent)|(?:pnpm\s+dlx\s+@tanstack\/intent(?:@latest)?)|(?:npx\s+@tanstack\/intent(?:@latest)?)|(?:yarn\s+dlx\s+@tanstack\/intent(?:@latest)?)|(?:intent))\s+(list|load)(?:\s+([^\s|;&]+))?/i
const INTENT_COMMAND_PATTERN =
/(?:^|&&|\|\||;|\|)\s*((?:bunx\s+@tanstack\/intent(?:`@latest`)?)|(?:pnpm\s+exec\s+intent)|(?:pnpm\s+dlx\s+@tanstack\/intent(?:`@latest`)?)|(?:npx\s+@tanstack\/intent(?:`@latest`)?)|(?:yarn\s+dlx\s+@tanstack\/intent(?:`@latest`)?)|(?:intent))\s+(list|load)(?:\s+([^\s|;&]+))?/i
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@evals/intent-discovery/harness/intent-hooks/hook-core.mjs` around lines 1 -
3, The INTENT_COMMAND_PATTERN regex has two issues: the leading `\s` alternative
allows false positives by matching plain text mentions like "echo intent load"
as valid commands, and the pattern is missing the `||` operator from the
command-chain alternatives, creating inconsistency with the production parser.
Remove or restrict the `\s` alternative to only match at proper command
boundaries (start of line or after actual command delimiters like &&, ;, |) and
add `||` to the list of command separators in the initial alternation group to
match the production parser in packages/intent/src/hooks/policy.ts.

Comment on lines +112 to +114
- Confirm every mapping has \`id\`, \`run\`, and \`for\`
- Confirm every \`id\` parses as \`<package>#<skill>\`
- Confirm no mapping includes local file paths

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Verification checklist over-promises checks that are not actually enforced.

Lines 112-114 now require validating id/run/for and no local paths, but the verifier path used by runInstallCommand (packages/intent/src/commands/install/guidance.ts, verifyIntentSkillsBlockFile) currently only checks field presence/types and id parseability. It does not enforce that run actually loads that same id, nor reject path-like values in mapping fields. This can report successful install verification for semantically broken mappings.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/intent/src/commands/install/command.ts` around lines 112 - 114, The
verification checklist comment at lines 112-114 in the install command file
promises to validate conditions (checking `id`/`run`/`for` presence, validating
`id` format as `<package>#<skill>`, and rejecting local file paths) that are not
actually enforced by the `verifyIntentSkillsBlockFile` function in guidance.ts.
Update the checklist comment to accurately reflect only what the verifier
currently validates (field presence/types and `id` parseability), or
alternatively enhance the `verifyIntentSkillsBlockFile` verification function to
add the missing validations for ensuring `run` references match the parsed `id`
and rejecting any path-like values in mapping fields.

Comment on lines +4 to +7
import { formatIntentCommand } from '../../shared/command-runner.js'
import { isGeneratedMappingSkill } from '../../skills/categories.js'
import type { ScanResult, SkillEntry } from '../../shared/types.js'
import { formatSkillUse, parseSkillUse } from '../../skills/use.js'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix import ordering to satisfy lint.

The value import from ../../skills/use.js should be placed before the type-only import from ../../shared/types.js to comply with the configured import/order rule.

Suggested diff
 import { formatIntentCommand } from '../../shared/command-runner.js'
 import { isGeneratedMappingSkill } from '../../skills/categories.js'
-import type { ScanResult, SkillEntry } from '../../shared/types.js'
 import { formatSkillUse, parseSkillUse } from '../../skills/use.js'
+import type { ScanResult, SkillEntry } from '../../shared/types.js'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { formatIntentCommand } from '../../shared/command-runner.js'
import { isGeneratedMappingSkill } from '../../skills/categories.js'
import type { ScanResult, SkillEntry } from '../../shared/types.js'
import { formatSkillUse, parseSkillUse } from '../../skills/use.js'
import { formatIntentCommand } from '../../shared/command-runner.js'
import { isGeneratedMappingSkill } from '../../skills/categories.js'
import { formatSkillUse, parseSkillUse } from '../../skills/use.js'
import type { ScanResult, SkillEntry } from '../../shared/types.js'
🧰 Tools
🪛 ESLint

[error] 7-7: ../../skills/use.js import should occur before type import of ../../shared/types.js

(import/order)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/intent/src/commands/install/guidance.ts` around lines 4 - 7, The
import statements at the top of the file are not in the correct order according
to the import/order lint rule. Move the value import statement containing
formatSkillUse and parseSkillUse from `../../skills/use.js` to appear before the
type-only import statement containing ScanResult and SkillEntry from
`../../shared/types.js`. Value imports should be ordered before type-only
imports to comply with the linting configuration.

Source: Linters/SAST tools

Comment on lines +1 to +9
import { fail } from '../shared/cli-error.js'
import { coreOptionsFromGlobalFlags, printDebugInfo } from './support.js'
import {
IntentCoreError,
loadIntentSkill,
resolveIntentSkill,
} from '../core.js'
import type { GlobalScanFlags } from '../cli-support.js'
import type { LoadedIntentSkill, ResolvedIntentSkill } from '../core.js'
} from '../core/index.js'
import type { GlobalScanFlags } from './support.js'
import type { LoadedIntentSkill, ResolvedIntentSkill } from '../core/index.js'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix import ordering to satisfy import/order.

This block violates the configured import-order rule and can fail CI.

Suggested reorder
 import { fail } from '../shared/cli-error.js'
-import { coreOptionsFromGlobalFlags, printDebugInfo } from './support.js'
 import {
   IntentCoreError,
   loadIntentSkill,
   resolveIntentSkill,
 } from '../core/index.js'
+import { coreOptionsFromGlobalFlags, printDebugInfo } from './support.js'
 import type { GlobalScanFlags } from './support.js'
 import type { LoadedIntentSkill, ResolvedIntentSkill } from '../core/index.js'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { fail } from '../shared/cli-error.js'
import { coreOptionsFromGlobalFlags, printDebugInfo } from './support.js'
import {
IntentCoreError,
loadIntentSkill,
resolveIntentSkill,
} from '../core.js'
import type { GlobalScanFlags } from '../cli-support.js'
import type { LoadedIntentSkill, ResolvedIntentSkill } from '../core.js'
} from '../core/index.js'
import type { GlobalScanFlags } from './support.js'
import type { LoadedIntentSkill, ResolvedIntentSkill } from '../core/index.js'
import { fail } from '../shared/cli-error.js'
import {
IntentCoreError,
loadIntentSkill,
resolveIntentSkill,
} from '../core/index.js'
import { coreOptionsFromGlobalFlags, printDebugInfo } from './support.js'
import type { GlobalScanFlags } from './support.js'
import type { LoadedIntentSkill, ResolvedIntentSkill } from '../core/index.js'
🧰 Tools
🪛 ESLint

[error] 3-7: ../core/index.js import should occur before import of ./support.js

(import/order)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/intent/src/commands/load.ts` around lines 1 - 9, The imports at the
top of the load.ts file are not ordered according to the configured import/order
ESLint rule. Reorganize the imports by grouping type imports separately from
regular imports, placing all regular value imports first (including the imports
from '../shared/cli-error.js', './support.js', and '../core/index.js'), then
group all type imports together at the end (the type imports from './support.js'
and '../core/index.js'). This ensures compliance with the import ordering
convention used in the project.

Source: Linters/SAST tools

Comment on lines +8 to +11
import { fail, isCliFailure } from '../shared/cli-error.js'
import { printWarnings } from './support.js'
import { resolveProjectContext } from '../core/project-context.js'
import { findWorkspacePackages } from '../workspace-patterns.js'
import { findWorkspacePackages } from '../setup/workspace-patterns.js'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Reorder imports to satisfy import/order.

./support.js should be placed after ../setup/workspace-patterns.js per the lint rule.

Suggested reorder
 import { fail, isCliFailure } from '../shared/cli-error.js'
-import { printWarnings } from './support.js'
 import { resolveProjectContext } from '../core/project-context.js'
 import { findWorkspacePackages } from '../setup/workspace-patterns.js'
+import { printWarnings } from './support.js'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { fail, isCliFailure } from '../shared/cli-error.js'
import { printWarnings } from './support.js'
import { resolveProjectContext } from '../core/project-context.js'
import { findWorkspacePackages } from '../workspace-patterns.js'
import { findWorkspacePackages } from '../setup/workspace-patterns.js'
import { fail, isCliFailure } from '../shared/cli-error.js'
import { resolveProjectContext } from '../core/project-context.js'
import { findWorkspacePackages } from '../setup/workspace-patterns.js'
import { printWarnings } from './support.js'
🧰 Tools
🪛 ESLint

[error] 9-9: ./support.js import should occur after import of ../setup/workspace-patterns.js

(import/order)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/intent/src/commands/validate.ts` around lines 8 - 11, The import
statement for printWarnings from ./support.js is positioned incorrectly
according to the import/order lint rule. Move the import statement for
printWarnings from ./support.js to appear after the import statement for
findWorkspacePackages from ../setup/workspace-patterns.js, so that relative
imports to parent directories come before relative imports to the current
directory.

Source: Linters/SAST tools

Comment on lines +2 to +16
import {
compileExcludePatterns,
getEffectiveExcludePatterns,
} from './excludes.js'
import { createIntentFsCache } from '../discovery/fs-cache.js'
import { rewriteLoadedSkillMarkdownDestinations } from './markdown.js'
import { resolveSkillUseFastPath } from './load-resolution.js'
import { resolveProjectContext } from './project-context.js'
import {
checkLoadAllowed,
readSkillSourcesConfig,
scanForPolicedIntents,
} from './source-policy.js'
import { ResolveSkillUseError, resolveSkillUse } from '../skills/resolver.js'
import { formatSkillUse, parseSkillUse } from '../skills/use.js'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Resolve import/order violations in the top import block.

Line 6, Line 15, and Line 16 currently violate the configured ordering rule (../... imports should come before ./... imports in this setup).

Suggested reorder
 import { isAbsolute, relative, resolve } from 'node:path'
+import { createIntentFsCache } from '../discovery/fs-cache.js'
+import { ResolveSkillUseError, resolveSkillUse } from '../skills/resolver.js'
+import { formatSkillUse, parseSkillUse } from '../skills/use.js'
 import {
   compileExcludePatterns,
   getEffectiveExcludePatterns,
 } from './excludes.js'
-import { createIntentFsCache } from '../discovery/fs-cache.js'
 import { rewriteLoadedSkillMarkdownDestinations } from './markdown.js'
 import { resolveSkillUseFastPath } from './load-resolution.js'
 import { resolveProjectContext } from './project-context.js'
@@
-import { ResolveSkillUseError, resolveSkillUse } from '../skills/resolver.js'
-import { formatSkillUse, parseSkillUse } from '../skills/use.js'
🧰 Tools
🪛 ESLint

[error] 6-6: ../discovery/fs-cache.js import should occur before import of ./excludes.js

(import/order)


[error] 15-15: ../skills/resolver.js import should occur before import of ./excludes.js

(import/order)


[error] 16-16: ../skills/use.js import should occur before import of ./excludes.js

(import/order)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/intent/src/core/intent-core.ts` around lines 2 - 16, The import
ordering at the top of intent-core.ts violates the configured rule where parent
directory imports (../...) should be placed before current directory imports
(./...). Currently, the imports from ../discovery/fs-cache.js,
../skills/resolver.js, and ../skills/use.js are scattered throughout the block
after ./excludes.js and other ./ imports. Reorganize the import statements by
moving all parent directory imports (those starting with ../) to the top of the
import block, followed by all current directory imports (those starting with
./), while preserving the internal ordering within each group.

Source: Linters/SAST tools

Comment on lines +9 to +24
import { createDependencyWalker, createPackageRegistrar } from './index.js'
import {
detectGlobalNodeModules,
nodeReadFs,
parseFrontmatter,
readScalarField,
toPosixPath,
} from './utils.js'
} from '../shared/utils.js'
import { createIntentFsCache } from './fs-cache.js'
import { detectPackageManager } from './package-manager.js'
import {
findWorkspacePackages,
findWorkspaceRoot,
} from './workspace-patterns.js'
} from '../setup/workspace-patterns.js'
import type { IntentFsCache } from './fs-cache.js'
import type { ReadFs } from './utils.js'
import type { ReadFs } from '../shared/utils.js'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix import/order violations in scanner import grouping.

Line 9, Line 17, and Line 18 should be ordered after the ../setup/workspace-patterns.js import per the configured lint rule.

Suggested reorder
-import { createDependencyWalker, createPackageRegistrar } from './index.js'
 import {
   detectGlobalNodeModules,
   nodeReadFs,
   parseFrontmatter,
   readScalarField,
   toPosixPath,
 } from '../shared/utils.js'
-import { createIntentFsCache } from './fs-cache.js'
-import { detectPackageManager } from './package-manager.js'
 import {
   findWorkspacePackages,
   findWorkspaceRoot,
 } from '../setup/workspace-patterns.js'
+import { createDependencyWalker, createPackageRegistrar } from './index.js'
+import { createIntentFsCache } from './fs-cache.js'
+import { detectPackageManager } from './package-manager.js'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { createDependencyWalker, createPackageRegistrar } from './index.js'
import {
detectGlobalNodeModules,
nodeReadFs,
parseFrontmatter,
readScalarField,
toPosixPath,
} from './utils.js'
} from '../shared/utils.js'
import { createIntentFsCache } from './fs-cache.js'
import { detectPackageManager } from './package-manager.js'
import {
findWorkspacePackages,
findWorkspaceRoot,
} from './workspace-patterns.js'
} from '../setup/workspace-patterns.js'
import type { IntentFsCache } from './fs-cache.js'
import type { ReadFs } from './utils.js'
import type { ReadFs } from '../shared/utils.js'
import {
detectGlobalNodeModules,
nodeReadFs,
parseFrontmatter,
readScalarField,
toPosixPath,
} from '../shared/utils.js'
import {
findWorkspacePackages,
findWorkspaceRoot,
} from '../setup/workspace-patterns.js'
import { createDependencyWalker, createPackageRegistrar } from './index.js'
import { createIntentFsCache } from './fs-cache.js'
import { detectPackageManager } from './package-manager.js'
import type { IntentFsCache } from './fs-cache.js'
import type { ReadFs } from '../shared/utils.js'
🧰 Tools
🪛 ESLint

[error] 9-9: ./index.js import should occur after import of ../setup/workspace-patterns.js

(import/order)


[error] 17-17: ./fs-cache.js import should occur after import of ../setup/workspace-patterns.js

(import/order)


[error] 18-18: ./package-manager.js import should occur after import of ../setup/workspace-patterns.js

(import/order)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/intent/src/discovery/scanner.ts` around lines 9 - 24, The imports in
the scanner.ts file violate the import/order linting rule. Reorganize the
imports so that the type imports (import type statements for IntentFsCache and
ReadFs) are placed at the end of the import block, after all regular imports.
Additionally, ensure that the regular imports are ordered correctly with
relative imports from the current directory (./index.js, ./fs-cache.js,
./package-manager.js) appearing before parent directory imports
(../setup/workspace-patterns.js and ../shared/utils.js). This will comply with
the configured linting rules for import ordering.

Source: Linters/SAST tools

Comment on lines +380 to +384
function isIntentHook(value: unknown): boolean {
if (!value || typeof value !== 'object') return false
const serialized = JSON.stringify(value)
return serialized.includes('intent-') && serialized.includes('-gate.mjs')
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Narrow Intent-hook detection to avoid deleting unrelated hook entries.

On Line 382, isIntentHook matches by serializing the whole object and checking broad substrings. During reinstall, this can remove non-Intent hooks if any field text happens to include intent-...-gate.mjs, which is a config-integrity regression.

Suggested fix
+const INTENT_GATE_SCRIPT_RE =
+  /(?:^|[\\/])(?:old-)?intent-(claude|codex|copilot)-gate\.mjs(?:$|[?#\s'"])/i
+
 function isIntentHook(value: unknown): boolean {
   if (!value || typeof value !== 'object') return false
-  const serialized = JSON.stringify(value)
-  return serialized.includes('intent-') && serialized.includes('-gate.mjs')
+  const entry = value as Record<string, unknown>
+  const command = typeof entry.command === 'string' ? entry.command : ''
+  const args = Array.isArray(entry.args)
+    ? entry.args.filter((arg): arg is string => typeof arg === 'string')
+    : []
+
+  if (INTENT_GATE_SCRIPT_RE.test(command)) return true
+  return args.some((arg) => INTENT_GATE_SCRIPT_RE.test(arg))
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function isIntentHook(value: unknown): boolean {
if (!value || typeof value !== 'object') return false
const serialized = JSON.stringify(value)
return serialized.includes('intent-') && serialized.includes('-gate.mjs')
}
const INTENT_GATE_SCRIPT_RE =
/(?:^|[\\/])(?:old-)?intent-(claude|codex|copilot)-gate\.mjs(?:$|[?#\s'"])/i
function isIntentHook(value: unknown): boolean {
if (!value || typeof value !== 'object') return false
const entry = value as Record<string, unknown>
const command = typeof entry.command === 'string' ? entry.command : ''
const args = Array.isArray(entry.args)
? entry.args.filter((arg): arg is string => typeof arg === 'string')
: []
if (INTENT_GATE_SCRIPT_RE.test(command)) return true
return args.some((arg) => INTENT_GATE_SCRIPT_RE.test(arg))
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/intent/src/hooks/install.ts` around lines 380 - 384, The
isIntentHook function uses overly broad substring matching on the entire
serialized object, which can incorrectly identify non-Intent hooks if they
happen to contain 'intent-' and '-gate.mjs' anywhere in their fields. Narrow the
detection logic to check only the specific hook identifier field (such as the
hook name property) rather than the entire serialized object, ensuring that only
actual Intent hooks matching the expected naming pattern are identified and
preventing false positives that could lead to deletion of unrelated hook entries
during reinstall.

findWorkspaceRoot,
readWorkspacePatterns,
} from './workspace-patterns.js'
import { resolveProjectContext } from '../core/project-context.js'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fix import order to satisfy ESLint.

Line 14 currently violates the enforced import/order rule and will fail lint gates.

Suggested diff
 import {
   findPackagesWithSkills,
   findWorkspaceRoot,
   readWorkspacePatterns,
 } from './workspace-patterns.js'
 import { resolveProjectContext } from '../core/project-context.js'
+import { resolveProjectContext } from '../core/project-context.js'
+import {
+  findPackagesWithSkills,
+  findWorkspaceRoot,
+  readWorkspacePatterns,
+} from './workspace-patterns.js'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { resolveProjectContext } from '../core/project-context.js'
import { resolveProjectContext } from '../core/project-context.js'
import {
findPackagesWithSkills,
findWorkspaceRoot,
readWorkspacePatterns,
} from './workspace-patterns.js'
🧰 Tools
🪛 ESLint

[error] 14-14: ../core/project-context.js import should occur before import of ./workspace-patterns.js

(import/order)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/intent/src/setup/project-setup.ts` at line 14, The import statement
for resolveProjectContext from '../core/project-context.js' at line 14 violates
the ESLint import/order rule, which enforces a specific ordering for imports.
Review all import statements in the project-setup.ts file and reorder the
resolveProjectContext import to comply with the enforced import order rules,
which typically require relative parent directory imports (../) to be grouped
together and ordered correctly relative to other imports like external packages
and internal modules.

Source: Linters/SAST tools

Comment on lines +175 to +217
const docs =
typeof (pkgJson.intent as Record<string, unknown> | undefined)?.docs ===
'string'
? ((pkgJson.intent as Record<string, unknown>).docs as string)
: 'docs/'
const isMonorepo = packageDirs !== undefined
const monorepoFallbackPkg = packageDirs?.[0]
? readPackageJson(packageDirs[0])
: null
const repo = detectRepo(
pkgJson,
detectRepo(monorepoFallbackPkg ?? {}, basename(root)),
)

let packageName = rawName
if (isMonorepo && isGenericWorkspaceName(rawName, root)) {
packageName = deriveWorkspacePackageName(root, repo, packageDirs)
}

// Derive srcPath: monorepos use a wildcard; single packages use the short name or fall back to root src/
const shortName = packageName.replace(/^@[^/]+\//, '')
let srcPath = isMonorepo
? 'packages/*/src/**'
: `packages/${shortName}/src/**`
if (!isMonorepo && existsSync(join(root, 'src'))) {
srcPath = 'src/**'
}

const docsPath = isMonorepo ? 'packages/*/docs/**' : docs

return {
PACKAGE_NAME: packageName,
PACKAGE_LABEL: packageName,
PAYLOAD_PACKAGE: packageName,
REPO: repo,
DOCS_PATH: docsPath.endsWith('**')
? docsPath
: docsPath.replace(/\/$/, '') + '/**',
SRC_PATH: srcPath,
WATCH_PATHS: isMonorepo
? buildWatchPaths(root, packageDirs)
: ` - '${docs.endsWith('**') ? docs : docs.replace(/\/$/, '') + '/**'}'\n - '${srcPath}'`,
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Handle remote intent.docs URLs before building path globs.

In single-package mode, a URL-valued intent.docs becomes https://.../** in DOCS_PATH/WATCH_PATHS, which is not a valid file-watch glob.

Suggested diff
-  const docs =
+  const docs =
     typeof (pkgJson.intent as Record<string, unknown> | undefined)?.docs ===
     'string'
       ? ((pkgJson.intent as Record<string, unknown>).docs as string)
       : 'docs/'
+  const docsIsRemote = /^https?:\/\//.test(docs)
@@
-  const docsPath = isMonorepo ? 'packages/*/docs/**' : docs
+  const docsPath = isMonorepo
+    ? 'packages/*/docs/**'
+    : docsIsRemote
+      ? 'docs/**'
+      : docs
@@
-    WATCH_PATHS: isMonorepo
-      ? buildWatchPaths(root, packageDirs)
-      : `      - '${docs.endsWith('**') ? docs : docs.replace(/\/$/, '') + '/**'}'\n      - '${srcPath}'`,
+    WATCH_PATHS: isMonorepo
+      ? buildWatchPaths(root, packageDirs)
+      : docsIsRemote
+        ? `      - '${srcPath}'`
+        : `      - '${docs.endsWith('**') ? docs : docs.replace(/\/$/, '') + '/**'}'\n      - '${srcPath}'`,
   }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const docs =
typeof (pkgJson.intent as Record<string, unknown> | undefined)?.docs ===
'string'
? ((pkgJson.intent as Record<string, unknown>).docs as string)
: 'docs/'
const isMonorepo = packageDirs !== undefined
const monorepoFallbackPkg = packageDirs?.[0]
? readPackageJson(packageDirs[0])
: null
const repo = detectRepo(
pkgJson,
detectRepo(monorepoFallbackPkg ?? {}, basename(root)),
)
let packageName = rawName
if (isMonorepo && isGenericWorkspaceName(rawName, root)) {
packageName = deriveWorkspacePackageName(root, repo, packageDirs)
}
// Derive srcPath: monorepos use a wildcard; single packages use the short name or fall back to root src/
const shortName = packageName.replace(/^@[^/]+\//, '')
let srcPath = isMonorepo
? 'packages/*/src/**'
: `packages/${shortName}/src/**`
if (!isMonorepo && existsSync(join(root, 'src'))) {
srcPath = 'src/**'
}
const docsPath = isMonorepo ? 'packages/*/docs/**' : docs
return {
PACKAGE_NAME: packageName,
PACKAGE_LABEL: packageName,
PAYLOAD_PACKAGE: packageName,
REPO: repo,
DOCS_PATH: docsPath.endsWith('**')
? docsPath
: docsPath.replace(/\/$/, '') + '/**',
SRC_PATH: srcPath,
WATCH_PATHS: isMonorepo
? buildWatchPaths(root, packageDirs)
: ` - '${docs.endsWith('**') ? docs : docs.replace(/\/$/, '') + '/**'}'\n - '${srcPath}'`,
}
const docs =
typeof (pkgJson.intent as Record<string, unknown> | undefined)?.docs ===
'string'
? ((pkgJson.intent as Record<string, unknown>).docs as string)
: 'docs/'
const docsIsRemote = /^https?:\/\//.test(docs)
const isMonorepo = packageDirs !== undefined
const monorepoFallbackPkg = packageDirs?.[0]
? readPackageJson(packageDirs[0])
: null
const repo = detectRepo(
pkgJson,
detectRepo(monorepoFallbackPkg ?? {}, basename(root)),
)
let packageName = rawName
if (isMonorepo && isGenericWorkspaceName(rawName, root)) {
packageName = deriveWorkspacePackageName(root, repo, packageDirs)
}
// Derive srcPath: monorepos use a wildcard; single packages use the short name or fall back to root src/
const shortName = packageName.replace(/^@[^/]+\//, '')
let srcPath = isMonorepo
? 'packages/*/src/**'
: `packages/${shortName}/src/**`
if (!isMonorepo && existsSync(join(root, 'src'))) {
srcPath = 'src/**'
}
const docsPath = isMonorepo
? 'packages/*/docs/**'
: docsIsRemote
? 'docs/**'
: docs
return {
PACKAGE_NAME: packageName,
PACKAGE_LABEL: packageName,
PAYLOAD_PACKAGE: packageName,
REPO: repo,
DOCS_PATH: docsPath.endsWith('**')
? docsPath
: docsPath.replace(/\/$/, '') + '/**',
SRC_PATH: srcPath,
WATCH_PATHS: isMonorepo
? buildWatchPaths(root, packageDirs)
: docsIsRemote
? ` - '${srcPath}'`
: ` - '${docs.endsWith('**') ? docs : docs.replace(/\/$/, '') + '/**'}'\n - '${srcPath}'`,
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/intent/src/setup/project-setup.ts` around lines 175 - 217, The code
currently treats URL-valued intent.docs (like https://...) as file paths and
appends /** to create invalid glob patterns. Before constructing the docsPath
and WATCH_PATHS, add a check to detect if the docs value is a URL by checking if
it starts with http:// or https://. For URL values, skip the glob path
transformation (the .replace(/\/$/, '') + '/**' pattern) and handle them
appropriately, so that remote URLs are not converted into invalid file-watch
globs like https://.../**. This check should be applied to both the docsPath
assignment and the WATCH_PATHS string construction in the single-package mode
branch.

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.

1 participant