feat(claude): emit plugin workflows and output styles (#187) - #300
Conversation
Keep bin compatibility by mirroring its source hooks and normalized payload fields per surface while sharing file enumeration and realpath containment. Emit only Claude's canonical workflows/ and output-styles/ directories, leaving manifest path fields and the plugin schema pin unchanged; workflows remain opaque, while output styles tighten to the documented .md format and native proof records that strict validation does not inspect frontmatter.
🦋 Changeset detectedLatest commit: 20ecfe2 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 20ecfe25dc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const hostOutputStyleRoots = (registry.outputStyleSources?.(loaded.config, targetNames) ?? []) | ||
| .flatMap((source) => 'source' in source ? [resolve(dirname(loaded.configPath), source.source)] : []); | ||
| const hostWorkflowRoots = (registry.workflowSources?.(loaded.config, targetNames) ?? []) | ||
| .flatMap((source) => 'source' in source ? [resolve(dirname(loaded.configPath), source.source)] : []); |
There was a problem hiding this comment.
Skip escaped payload symlinks before source snapshotting
When claude.outputStyles or claude.workflows names an in-project symlink whose target is outside the project, these roots are passed to snapshotProjectSource before normalization. payloadSourcePaths follows the directory symlink, and sourceInput then resolves each file's realpath and throws because it lies outside the root, so ProjectService returns generic AB7003 instead of reaching normalizeHostPayloadDirectories and emitting the intended claude.*.directory.outside diagnostic. Filter these roots using the same realpath-containment check, or make snapshotting skip escaped roots, so CLI validation/build preserves the newly documented diagnostic behavior.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in a45992e: additional payload roots are realpathed and filtered to the project before snapshot traversal, so escaped outputStyles/workflows symlinks no longer become AB7003 and validation emits the intended claude.*.directory.outside diagnostic.
Summary
ClaudeHostConfiggainsworkflowsandoutputStylesproject-directory surfaces, copied byte-faithfully to plugin-rootworkflows/andoutput-styles/(the canonical default locations; no manifest path fields emitted, consistent with theplugin.pathsevidence pinned in feat(claude): emit manifest metadata fields and pin component path rules (#187) #293).normalizeHostPayloadDirectorieswith per-surface registry hooks (workflowsSource,outputStylesSource), keepingNormalizedHostBinas a compatible alias. Adds realpath containment so a symlinked payload directory cannot escape the project root — a recorded tightening that now also guardsbin..mdformat (frontmatter fieldsname,description,keep-coding-instructions, plugin-onlyforce-for-pluginpinned from https://code.claude.com/docs/en/output-styles, 2026-09-01); workflow files stay opaque payloads because the reference documents no deeper schema.claude.workflows.*/claude.outputStyles.*mirroring the bin family; newworkflowsandoutputStylescapability rows; unified plugin adapter follows the bin precedent. Claude adapter 1.11.0 → 1.12.0, plugin adapter 1.10.0 → 1.11.0.Test plan
pnpm typecheckpnpm lintPart of #187 (slice 2).