Skip to content

feat(intent): add reviewable skill provenance with lockfiles and frozen CI#199

Open
LadyBluenotes wants to merge 66 commits into
mainfrom
m2-lockfile
Open

feat(intent): add reviewable skill provenance with lockfiles and frozen CI#199
LadyBluenotes wants to merge 66 commits into
mainfrom
m2-lockfile

Conversation

@LadyBluenotes

@LadyBluenotes LadyBluenotes commented Jul 10, 2026

Copy link
Copy Markdown
Member

Summary

Add consumer-managed intent.lock files so projects can review and record the exact skill content they approve from explicitly trusted dependency sources.

The consumer workflow is:

intent skills scan
intent skills diff
intent skills approve --all
intent skills scan --frozen

Consumer workflow

  • Add intent skills scan, diff, approve, and update.
  • Write deterministic intent.lock files at the consumer project root.
  • Track sources by (kind, id), keeping workspace:foo and npm:foo as distinct trust identities and approvals.
  • Hash each SKILL.md plus supported references/, assets/, and scripts/ files with deterministic SHA-256 content hashes.
  • Display complete current canonical text before trust-bearing approval writes; summarize binary files by path, byte length, and hash.
  • Escape control, newline, and bidirectional characters in untrusted content, source names, paths, and provenance before terminal output.
  • Require --yes before skills update accepts trust-bearing content, manifest, capability, secret, MCP, or skill-path changes.
  • When intent.lock exists, reject drift during ordinary intent load and agent catalog generation so interactive agents cannot silently consume content that differs from the approved state.
  • Enforce approved state in CI with --frozen, INTENT_FROZEN, or non-interactive CI detection.
  • Fail frozen checks for missing or malformed lockfiles, source drift, unlisted skill-bearing sources, and attempted mutations.
  • Preserve bootstrap behavior outside frozen mode when a project has not created its first lockfile.

Optional package manifests

  • Consume and strictly validate an optional package-provided skills/intent.manifest.json against installed package identity, skill paths, and per-skill hashes.
  • Include validated manifest hashes and declared capability changes in consumer lockfile diffs.
  • Keep lockfile fields for future secret and MCP declarations reserved and nullable.
  • Defer manifest authoring and generation to the maintainer milestone.

Documentation, exports, and performance

  • Document lockfile lifecycle, content review, activation enforcement, frozen-mode CI usage, command behavior, and exit codes.
  • Export public lockfile metadata types from @tanstack/intent.
  • Add representative lockfile scan benchmarks; no persistent cache is added because measured scans remain within budget.

Summary by CodeRabbit

  • New Features

    • Added intent skills commands for scanning, reviewing, approving, and updating approved skill sources.
    • Added tamper-evident intent.lock tracking for approved skill content and metadata.
    • Added frozen mode for enforcing lockfile consistency in CI.
    • Distinguished workspace and npm sources with the same name and improved provenance reporting.
    • Added deterministic content hashing and manifest validation.
  • Documentation

    • Added comprehensive guidance for lockfiles, frozen mode, source identity, and the new CLI commands.
    • Documented Node.js 20+ compatibility.

LadyBluenotes and others added 30 commits July 5, 2026 14:19
- Introduced 'skills' field in IntentLockfileSource and related types.
- Updated lockfile diffing logic to compare skills.
- Refactored source content hashing to handle skills independently.
- Enhanced tests to cover new skills functionality and ensure backward compatibility.
- Adjusted error handling and exit codes for various commands in frozen mode.
…es outside the consumer repository; add tests for frozen mode and approved installed dependencies
- Updated `intent-skills.md` to include `manifestHash` and `capabilities` in the mechanical refresh description.
- Improved `lockfile.md` to clarify the conditions under which `manifestHash` and `capabilities` are populated.
- Refactored `intent-core.ts` to streamline imports and maintain consistency.
- Enhanced `hash.ts` to enforce limits on entry counts and added validation for hash entries.
- Updated `lockfile-state.ts` to assert manifest matches package details.
- Improved `lockfile.ts` to reject undeclared fields in lockfile parsing.
- Enhanced `manifest.ts` to validate capabilities and MCP tools against declared fields.
- Added tests to ensure proper handling of unknown capabilities and undeclared fields in manifests.
- Updated resolver logic to handle skill resolution more effectively, especially for same-name skills across different sources.
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds intent.lock management with deterministic hashing, strict manifests, source identity tracking, frozen-mode enforcement, and new intent skills scan/diff/approve/update commands. Discovery, loading, agent catalogs, documentation, tests, and benchmarks are updated accordingly.

Changes

Intent lockfile and skills workflow

Layer / File(s) Summary
Lockfile and content integrity
packages/intent/src/core/lockfile/*, packages/intent/src/core/manifest.ts, packages/intent/src/core/skill-path.ts
Adds strict canonical lockfile parsing, manifest validation, deterministic SHA-256 hashing, path and symlink checks, content reviews, and field-level diffs.
Source identity and policy
packages/intent/src/discovery/*, packages/intent/src/core/excludes.ts, packages/intent/src/core/source-policy.ts, packages/intent/src/skills/resolver.ts
Tracks npm and workspace sources by (kind, id), preserves bounded provenance, supports kind-qualified excludes, and rejects ambiguous skill matches.
Frozen enforcement and CLI wiring
packages/intent/src/core/intent-core.ts, packages/intent/src/shared/*, packages/intent/src/commands/support.ts, packages/intent/src/cli.ts
Adds frozen-mode precedence, disables network/subprocess lookups where required, validates lock state during loading and agent catalog generation, and dispatches the new skills commands.
Approval, diff, scan, and update commands
packages/intent/src/commands/skills/*
Implements read-only drift inspection, interactive or explicit approval, trust-bearing content review, targeted metadata updates, canonical writes, and frozen-mode mutation refusal.
Tests and benchmarks
packages/intent/tests/*, benchmarks/intent/*
Covers hashing, manifests, lockfile behavior, source identity, provenance, frozen mode, CLI commands, integrations, and scan performance scenarios.
Documentation and package metadata
docs/*, packages/intent/README.md, packages/intent/package.json, tsconfig.json, .changeset/*
Documents lockfile and frozen-mode behavior, adds CLI navigation and command references, requires Node.js 20+, updates compiler targets, and records the minor release changeset.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant Scanner
  participant Lockfile
  participant Approval
  participant Loader
  CLI->>Scanner: scan installed skill sources
  Scanner->>Lockfile: compute current identities and hashes
  Lockfile-->>CLI: report missing, clean, or changed state
  CLI->>Approval: approve or update selected sources
  Approval->>Lockfile: write canonical intent.lock
  Loader->>Lockfile: validate approved state before loading
Loading

Possibly related PRs

  • TanStack/intent#156: Shares the allowlist and exclusion policy paths used by lockfile enforcement.
  • TanStack/intent#171: Introduces related package-kind and source-identity handling.
  • TanStack/intent#187: Overlaps with frozen-mode changes preventing registry and global package-manager lookups.

Suggested reviewers: KevinVandy, schiller-manuel, tannerlinsley

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.73% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The description is detailed, but it does not follow the repository template and is missing the required checklist and release-impact sections. Rewrite the PR description using the template sections: 🎯 Changes, ✅ Checklist, and 🚀 Release Impact, and fill in the required checkboxes.
✅ Passed checks (3 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title is concise and accurately reflects the lockfile review and frozen-CI workflow changes.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch m2-lockfile

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.

@nx-cloud

nx-cloud Bot commented Jul 10, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit 7e7adb5

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

☁️ Nx Cloud last updated this comment at 2026-07-12 14:14:47 UTC

@pkg-pr-new

pkg-pr-new Bot commented Jul 10, 2026

Copy link
Copy Markdown

Open in StackBlitz

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

commit: 7e7adb5

@LadyBluenotes LadyBluenotes marked this pull request as ready for review July 10, 2026 02:41

@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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/intent/src/shared/utils.ts (1)

252-269: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Pass the resolved frozen state into scan options scanOptionsFromGlobalFlags() only sets scope, so scanForIntents() still reaches detectGlobalNodeModules(..., options.frozen) with undefined. That lets CI auto-detect win even when --no-frozen was passed.

🤖 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/shared/utils.ts` around lines 252 - 269, Update
scanOptionsFromGlobalFlags() to resolve and include the effective frozen state
in its returned options, preserving the explicit --no-frozen value instead of
leaving frozen undefined. Ensure scanForIntents() passes this resolved
options.frozen to detectGlobalNodeModules() so caller flags take precedence over
CI auto-detection.
🧹 Nitpick comments (1)
docs/security/lockfile.md (1)

62-65: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider varying the sentence structure in the frozen-mode failure list.

Four consecutive bullet points begin with "Fails." While the parallel structure is readable as a reference list, varying the phrasing would improve flow.

🤖 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 `@docs/security/lockfile.md` around lines 62 - 65, Vary the sentence openings
in the frozen-mode failure list while preserving the existing meanings, exit
codes, and commands; update the bullets describing drift, unapproved
skill-bearing sources, a missing intent.lock, and malformed or unsupported
intent.lock files.

Source: Linters/SAST tools

🤖 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 `@packages/intent/src/skills/resolver.ts`:
- Around line 166-169: Map.groupBy in the resolver is unsupported on the
declared Node 20 minimum runtime. Replace the grouping in the packagesByIdentity
initialization with a Node 20-compatible approach, or consistently raise the
package and README Node version requirements to a runtime that supports
Map.groupBy.

In `@packages/intent/src/staleness/check.ts`:
- Around line 97-99: Thread the resolved frozen-mode state through the staleness
fetch flow so --no-frozen overrides auto-detection. Update fetchCurrentVersion
and fetchNpmVersion to accept the resolved state, and have callers pass
isFrozenMode({ frozen, noFrozen }) rather than calling isFrozenMode() without
options; use that explicit value for the early return that skips registry
access.

In `@packages/intent/tests/integration/source-policy-surfaces.test.ts`:
- Around line 13-15: Remove the duplicated changed properties from the type
annotation in the affected test declarations, keeping a single changed field
with the intended type; update all occurrences in the relevant test sections and
verify no duplicate changed keys remain.

In `@packages/intent/tests/skills-update.test.ts`:
- Around line 155-156: Restore the global fetch mock after each test: update the
setup around fetchSpy to use vi.stubGlobal, and extend the existing afterEach
cleanup to call vi.unstubAllGlobals() alongside vi.unstubAllEnvs().

---

Outside diff comments:
In `@packages/intent/src/shared/utils.ts`:
- Around line 252-269: Update scanOptionsFromGlobalFlags() to resolve and
include the effective frozen state in its returned options, preserving the
explicit --no-frozen value instead of leaving frozen undefined. Ensure
scanForIntents() passes this resolved options.frozen to
detectGlobalNodeModules() so caller flags take precedence over CI
auto-detection.

---

Nitpick comments:
In `@docs/security/lockfile.md`:
- Around line 62-65: Vary the sentence openings in the frozen-mode failure list
while preserving the existing meanings, exit codes, and commands; update the
bullets describing drift, unapproved skill-bearing sources, a missing
intent.lock, and malformed or unsupported intent.lock files.
🪄 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: 905a73c0-a301-4fe7-becd-f0ef5c627125

📥 Commits

Reviewing files that changed from the base of the PR and between 6039a26 and 215e2db.

📒 Files selected for processing (78)
  • .changeset/many-forks-cough.md
  • benchmarks/intent/README.md
  • benchmarks/intent/helpers.ts
  • benchmarks/intent/lockfile-scan.bench.ts
  • docs/cli/intent-list.md
  • docs/cli/intent-skills.md
  • docs/concepts/configuration.md
  • docs/config.json
  • docs/security/lockfile.md
  • packages/intent/README.md
  • packages/intent/package.json
  • packages/intent/src/cli.ts
  • packages/intent/src/commands/install/guidance.ts
  • packages/intent/src/commands/list.ts
  • packages/intent/src/commands/skills/approve.ts
  • packages/intent/src/commands/skills/diff.ts
  • packages/intent/src/commands/skills/generate-manifest.ts
  • packages/intent/src/commands/skills/scan.ts
  • packages/intent/src/commands/skills/stale.ts
  • packages/intent/src/commands/skills/support.ts
  • packages/intent/src/commands/skills/update.ts
  • packages/intent/src/commands/support.ts
  • packages/intent/src/core/excludes.ts
  • packages/intent/src/core/git-adapter.ts
  • packages/intent/src/core/intent-core.ts
  • packages/intent/src/core/load-resolution.ts
  • packages/intent/src/core/lockfile/baseline-drift.ts
  • packages/intent/src/core/lockfile/hash.ts
  • packages/intent/src/core/lockfile/lockfile-diff.ts
  • packages/intent/src/core/lockfile/lockfile-state.ts
  • packages/intent/src/core/lockfile/lockfile.ts
  • packages/intent/src/core/manifest.ts
  • packages/intent/src/core/secrets.ts
  • packages/intent/src/core/skill-path.ts
  • packages/intent/src/core/source-policy.ts
  • packages/intent/src/core/types.ts
  • packages/intent/src/discovery/register.ts
  • packages/intent/src/discovery/scanner.ts
  • packages/intent/src/discovery/walk.ts
  • packages/intent/src/index.ts
  • packages/intent/src/shared/cli-output.ts
  • packages/intent/src/shared/env-flag.ts
  • packages/intent/src/shared/mode.ts
  • packages/intent/src/shared/types.ts
  • packages/intent/src/shared/utils.ts
  • packages/intent/src/skills/paths.ts
  • packages/intent/src/skills/resolver.ts
  • packages/intent/src/staleness/check.ts
  • packages/intent/tests/baseline-drift.test.ts
  • packages/intent/tests/cli.test.ts
  • packages/intent/tests/core.test.ts
  • packages/intent/tests/excludes.test.ts
  • packages/intent/tests/git-adapter-failure.test.ts
  • packages/intent/tests/git-adapter.test.ts
  • packages/intent/tests/global-node-modules.test.ts
  • packages/intent/tests/hash.test.ts
  • packages/intent/tests/integration/pnp-berry-corepack.test.ts
  • packages/intent/tests/integration/skills-frozen-cli.test.ts
  • packages/intent/tests/integration/source-policy-surfaces.test.ts
  • packages/intent/tests/lockfile-diff.test.ts
  • packages/intent/tests/lockfile-state.test.ts
  • packages/intent/tests/lockfile.test.ts
  • packages/intent/tests/manifest.test.ts
  • packages/intent/tests/mode.test.ts
  • packages/intent/tests/public-lockfile-types.test.ts
  • packages/intent/tests/resolver.test.ts
  • packages/intent/tests/scanner.test.ts
  • packages/intent/tests/secrets.test.ts
  • packages/intent/tests/skills-approve.test.ts
  • packages/intent/tests/skills-diff.test.ts
  • packages/intent/tests/skills-generate-manifest.test.ts
  • packages/intent/tests/skills-resolve-source-arg.test.ts
  • packages/intent/tests/skills-scan.test.ts
  • packages/intent/tests/skills-stale.test.ts
  • packages/intent/tests/skills-update.test.ts
  • packages/intent/tests/source-policy.test.ts
  • packages/intent/tests/staleness.test.ts
  • tsconfig.json

Comment thread packages/intent/src/skills/resolver.ts Outdated
Comment thread packages/intent/src/staleness/check.ts
Comment thread packages/intent/tests/integration/source-policy-surfaces.test.ts
Comment thread packages/intent/tests/skills-update.test.ts Outdated

@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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/intent/src/cli.ts (1)

214-300: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Restore the skills stale and skills generate-manifest actions.

The dispatcher now rejects both commands, making the package-maintainer workflows required by this PR inaccessible. Restore their handlers/options or revise the public contract before merge.

🤖 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/cli.ts` around lines 214 - 300, Extend the skills command
dispatcher to recognize and route the previously supported `stale` and
`generate-manifest` actions instead of falling through to the unknown-action
failure. Restore each action’s corresponding handler and option wiring,
including any command usage, examples, and imports needed to preserve the public
package-maintainer workflows.
packages/intent/src/core/intent-core.ts (1)

407-438: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Validate the lock before resolving from scanned metadata.

droppedNames and resolveSkillUse currently consume potentially drifted metadata before assertApprovedLockState. A renamed or malformed skill can therefore produce resolution errors or suggestions instead of the required stale-lock rejection. Move the assertion immediately after scanning.

Proposed fix
   } = scanForPolicedIntents({
     cwd,
     scanOptions: withFsCache(scanOptions, fsCache),
     coreOptions: options,
     context: projectContext,
   })
+
+  if (frozen || lockedResult.status === 'found') {
+    assertApprovedLockState(cwd, scanResult, hiddenSourceCount, lockedResult, {
+      rejectHiddenSources: frozen,
+      requireLockfile: frozen,
+    })
+  }
+
   if (droppedNames.includes(parsedUse.packageName)) {
     const lateRefusal = packageNotListedRefusal(use, parsedUse.packageName)
     throw new IntentCoreError(lateRefusal.code, lateRefusal.message)
   }
@@
-  if (frozen || lockedResult.status === 'found') {
-    assertApprovedLockState(cwd, scanResult, hiddenSourceCount, lockedResult, {
-      rejectHiddenSources: frozen,
-      requireLockfile: frozen,
-    })
-  }
🤖 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 407 - 438, Move the
assertApprovedLockState call immediately after scanForPolicedIntents returns,
before checking droppedNames or calling resolveSkillUse. Preserve its existing
frozen and lockedResult.status conditions and options, while ensuring stale-lock
validation occurs before any scanned metadata is consumed.
🧹 Nitpick comments (2)
packages/intent/src/core/lockfile/hash.ts (1)

432-465: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the shared validation/expansion preamble.

computeSourceContentHash (lines 437-453) and readSourceContentForReview (lines 472-487) share an identical 4-block preamble: assertCanonicalPackageRelativePathsrealpathSynccollectSkillContentEntriesassertNoDuplicateKeys. Extracting this into a helper keeps both paths in sync and reduces maintenance risk.

♻️ Proposed refactor
+function prepareContentEntries(
+  packageRoot: string,
+  entries: ReadonlyArray<SkillContentEntry>,
+  fs: ReadFs,
+): { realPackageRoot: string; contentEntries: SkillContentEntry[] } {
+  assertCanonicalPackageRelativePaths(
+    entries.map((entry) => entry.relativePath),
+    'skill path',
+  )
+  const realPackageRoot = fs.realpathSync(packageRoot)
+  const contentEntries = collectSkillContentEntries(
+    fs,
+    packageRoot,
+    entries,
+    realPackageRoot,
+  )
+  assertNoDuplicateKeys(
+    contentEntries.map((entry) => entry.relativePath),
+    'skill content path',
+  )
+  return { realPackageRoot, contentEntries }
+}
+
 export function computeSourceContentHash(
   packageRoot: string,
   entries: ReadonlyArray<SkillContentEntry>,
   fs: ReadFs = nodeReadFs,
 ): SourceContentHash {
-  assertCanonicalPackageRelativePaths(
-    entries.map((entry) => entry.relativePath),
-    'skill path',
-  )
-
-  const realPackageRoot = fs.realpathSync(packageRoot)
-  const contentEntries = collectSkillContentEntries(
-    fs,
-    packageRoot,
-    entries,
-    realPackageRoot,
-  )
-  assertNoDuplicateKeys(
-    contentEntries.map((entry) => entry.relativePath),
-    'skill content path',
-  )
+  const { realPackageRoot, contentEntries } = prepareContentEntries(packageRoot, entries, fs)

   const hashed = readHashEntries(contentEntries, fs, realPackageRoot)

   return {
     skills: entries.map((entry) => entry.relativePath).toSorted(compareStrings),
     contentHash: computeReviewedSourceContentHash(
       hashed.map((entry) => ({
         relativePath: entry.key,
         content: entry.value,
       })),
     ),
   }
 }

 export function readSourceContentForReview(
   packageRoot: string,
   entries: ReadonlyArray<SkillContentEntry>,
   fs: ReadFs = nodeReadFs,
 ): Array<SourceContentReviewEntry> {
-  assertCanonicalPackageRelativePaths(
-    entries.map((entry) => entry.relativePath),
-    'skill path',
-  )
-
-  const realPackageRoot = fs.realpathSync(packageRoot)
-  const contentEntries = collectSkillContentEntries(
-    fs,
-    packageRoot,
-    entries,
-    realPackageRoot,
-  )
-  assertNoDuplicateKeys(
-    contentEntries.map((entry) => entry.relativePath),
-    'skill content path',
-  )
+  const { realPackageRoot, contentEntries } = prepareContentEntries(packageRoot, entries, fs)

   return readHashEntries(contentEntries, fs, realPackageRoot)
     .map((entry) => ({
       relativePath: entry.key,
       content: entry.value,
       contentHash: `sha256-${createHash('sha256').update(entry.value).digest('hex')}`,
       isBinary: entry.isBinary,
       byteLength: entry.byteLength,
     }))
     .toSorted((a, b) => compareStrings(a.relativePath, b.relativePath))
 }

Also applies to: 467-498

🤖 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/lockfile/hash.ts` around lines 432 - 465, Extract
the shared validation and expansion sequence from computeSourceContentHash and
readSourceContentForReview into a helper that canonicalizes entry paths,
resolves the package root, collects skill content entries, and rejects duplicate
keys. Update both functions to call the helper and reuse its returned entries
while preserving their existing hashing and review behavior.
packages/intent/tests/content-review.test.ts (1)

29-47: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider adding a test for the missing-source case.

assertSourceContentReviewsMatch throws when !source (review identity not found in current sources), but this path is not tested. A simple test with a review whose identity doesn't match any current source would close the gap.

🧪 Suggested test addition
   it('rejects content changed between hashing and review', () => {
     expect(() =>
       assertSourceContentReviewsMatch(
         [review('sha256-review')],
         [source('sha256-current')],
       ),
     ).toThrow('changed while it was being reviewed')
   })
+
+  it('rejects a review with no matching current source', () => {
+    expect(() =>
+      assertSourceContentReviewsMatch(
+        [{ ...review('sha256-current'), id: 'bar' }],
+        [source('sha256-current')],
+      ),
+    ).toThrow('changed while it was being reviewed')
+  })
 })
🤖 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/tests/content-review.test.ts` around lines 29 - 47, Add a
test in the assertSourceContentReviewsMatch suite covering a review identity
that is absent from the current sources, using distinct review and source
hashes. Assert that the call throws the expected missing-source error for the
!source path, while preserving the existing matching and changed-content tests.
🤖 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 `@packages/intent/src/commands/skills/support.ts`:
- Around line 113-124: Update the details formatting in the hidden-source
mapping callback to sanitize or escape each untrusted source.name and provenance
path before including them in the output strings. Preserve the existing sorting,
provenance joining, and “provenance unknown” behavior while ensuring terminal
escapes, newlines, and bidi controls cannot appear raw.

---

Outside diff comments:
In `@packages/intent/src/cli.ts`:
- Around line 214-300: Extend the skills command dispatcher to recognize and
route the previously supported `stale` and `generate-manifest` actions instead
of falling through to the unknown-action failure. Restore each action’s
corresponding handler and option wiring, including any command usage, examples,
and imports needed to preserve the public package-maintainer workflows.

In `@packages/intent/src/core/intent-core.ts`:
- Around line 407-438: Move the assertApprovedLockState call immediately after
scanForPolicedIntents returns, before checking droppedNames or calling
resolveSkillUse. Preserve its existing frozen and lockedResult.status conditions
and options, while ensuring stale-lock validation occurs before any scanned
metadata is consumed.

---

Nitpick comments:
In `@packages/intent/src/core/lockfile/hash.ts`:
- Around line 432-465: Extract the shared validation and expansion sequence from
computeSourceContentHash and readSourceContentForReview into a helper that
canonicalizes entry paths, resolves the package root, collects skill content
entries, and rejects duplicate keys. Update both functions to call the helper
and reuse its returned entries while preserving their existing hashing and
review behavior.

In `@packages/intent/tests/content-review.test.ts`:
- Around line 29-47: Add a test in the assertSourceContentReviewsMatch suite
covering a review identity that is absent from the current sources, using
distinct review and source hashes. Assert that the call throws the expected
missing-source error for the !source path, while preserving the existing
matching and changed-content tests.
🪄 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: 61829d78-f7ab-4c79-9b0c-cb9208945e3c

📥 Commits

Reviewing files that changed from the base of the PR and between 7a88e87 and a3f752e.

📒 Files selected for processing (31)
  • .changeset/many-forks-cough.md
  • docs/cli/intent-skills.md
  • docs/concepts/trust-model.md
  • docs/security/lockfile.md
  • packages/intent/README.md
  • packages/intent/src/cli.ts
  • packages/intent/src/commands/list.ts
  • packages/intent/src/commands/skills/approve.ts
  • packages/intent/src/commands/skills/diff.ts
  • packages/intent/src/commands/skills/support.ts
  • packages/intent/src/commands/skills/update.ts
  • packages/intent/src/core/intent-core.ts
  • packages/intent/src/core/lockfile/content-review.ts
  • packages/intent/src/core/lockfile/hash.ts
  • packages/intent/src/core/manifest.ts
  • packages/intent/src/core/skill-path.ts
  • packages/intent/src/core/source-policy.ts
  • packages/intent/src/core/types.ts
  • packages/intent/src/index.ts
  • packages/intent/tests/cli.test.ts
  • packages/intent/tests/content-review.test.ts
  • packages/intent/tests/core.test.ts
  • packages/intent/tests/integration/skills-frozen-cli.test.ts
  • packages/intent/tests/lockfile-state.test.ts
  • packages/intent/tests/manifest.test.ts
  • packages/intent/tests/public-lockfile-types.test.ts
  • packages/intent/tests/skills-approve.test.ts
  • packages/intent/tests/skills-diff.test.ts
  • packages/intent/tests/skills-scan.test.ts
  • packages/intent/tests/skills-update.test.ts
  • packages/intent/tests/source-policy.test.ts
💤 Files with no reviewable changes (2)
  • packages/intent/tests/public-lockfile-types.test.ts
  • packages/intent/src/index.ts
✅ Files skipped from review due to trivial changes (6)
  • packages/intent/src/commands/list.ts
  • docs/concepts/trust-model.md
  • packages/intent/README.md
  • .changeset/many-forks-cough.md
  • docs/cli/intent-skills.md
  • docs/security/lockfile.md
🚧 Files skipped from review as they are similar to previous changes (9)
  • packages/intent/src/core/types.ts
  • packages/intent/tests/skills-diff.test.ts
  • packages/intent/src/commands/skills/diff.ts
  • packages/intent/tests/cli.test.ts
  • packages/intent/tests/source-policy.test.ts
  • packages/intent/tests/lockfile-state.test.ts
  • packages/intent/src/core/source-policy.ts
  • packages/intent/tests/skills-scan.test.ts
  • packages/intent/src/commands/skills/approve.ts

Comment thread packages/intent/src/commands/skills/support.ts
@LadyBluenotes LadyBluenotes requested a review from a team as a code owner July 12, 2026 13:21
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