@amsterdamdatalabs/enact-extensions 0.1.42 → 0.1.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -108
- package/bundled-extensions.json +6 -0
- package/dist/create/enact.d.ts.map +1 -1
- package/dist/create/enact.js +2 -0
- package/dist/create/enact.js.map +1 -1
- package/dist/create/index.d.ts +3 -0
- package/dist/create/index.d.ts.map +1 -1
- package/dist/create/index.js +6 -0
- package/dist/create/index.js.map +1 -1
- package/dist/create/kimi.d.ts +16 -0
- package/dist/create/kimi.d.ts.map +1 -0
- package/dist/create/kimi.js +87 -0
- package/dist/create/kimi.js.map +1 -0
- package/dist/create/opencode.d.ts +129 -0
- package/dist/create/opencode.d.ts.map +1 -0
- package/dist/create/opencode.js +696 -0
- package/dist/create/opencode.js.map +1 -0
- package/dist/index.d.ts +12 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -10
- package/dist/index.js.map +1 -1
- package/dist/internal/agents.d.ts +11 -1
- package/dist/internal/agents.d.ts.map +1 -1
- package/dist/internal/agents.js +119 -3
- package/dist/internal/agents.js.map +1 -1
- package/dist/internal/extensions-table.d.ts +58 -0
- package/dist/internal/extensions-table.d.ts.map +1 -0
- package/dist/internal/extensions-table.js +134 -0
- package/dist/internal/extensions-table.js.map +1 -0
- package/dist/internal/file-ops.d.ts +36 -0
- package/dist/internal/file-ops.d.ts.map +1 -0
- package/dist/internal/file-ops.js +89 -0
- package/dist/internal/file-ops.js.map +1 -0
- package/dist/internal/hooks.d.ts +56 -0
- package/dist/internal/hooks.d.ts.map +1 -0
- package/dist/internal/hooks.js +128 -0
- package/dist/internal/hooks.js.map +1 -0
- package/dist/internal/json-merge.d.ts +63 -0
- package/dist/internal/json-merge.d.ts.map +1 -0
- package/dist/internal/json-merge.js +122 -0
- package/dist/internal/json-merge.js.map +1 -0
- package/dist/internal/lock-ownership.d.ts +41 -0
- package/dist/internal/lock-ownership.d.ts.map +1 -0
- package/dist/internal/lock-ownership.js +24 -0
- package/dist/internal/lock-ownership.js.map +1 -0
- package/dist/internal/platform.d.ts.map +1 -1
- package/dist/internal/platform.js +90 -4
- package/dist/internal/platform.js.map +1 -1
- package/dist/internal/schema.js.map +1 -1
- package/dist/internal/toml-block.d.ts +59 -0
- package/dist/internal/toml-block.d.ts.map +1 -0
- package/dist/internal/toml-block.js +113 -0
- package/dist/internal/toml-block.js.map +1 -0
- package/dist/internal/types.d.ts +2 -1
- package/dist/internal/types.d.ts.map +1 -1
- package/dist/projection.d.ts +47 -0
- package/dist/projection.d.ts.map +1 -0
- package/dist/projection.js +180 -0
- package/dist/projection.js.map +1 -0
- package/dist/validate/index.d.ts +9 -4
- package/dist/validate/index.d.ts.map +1 -1
- package/dist/validate/index.js +56 -7
- package/dist/validate/index.js.map +1 -1
- package/dist/validate/kimi.d.ts +3 -0
- package/dist/validate/kimi.d.ts.map +1 -0
- package/dist/validate/kimi.js +11 -0
- package/dist/validate/kimi.js.map +1 -0
- package/dist/validate/opencode.d.ts +3 -0
- package/dist/validate/opencode.d.ts.map +1 -0
- package/dist/validate/opencode.js +11 -0
- package/dist/validate/opencode.js.map +1 -0
- package/dist/validate/run.d.ts +39 -0
- package/dist/validate/run.d.ts.map +1 -0
- package/dist/validate/run.js +63 -0
- package/dist/validate/run.js.map +1 -0
- package/extensions/enact-loop/.agents/plugin.json +12 -8
- package/extensions/enact-loop/scripts/validate.mjs +84 -2
- package/extensions/enact-loop/skills/enact-loop/SKILL.md +36 -466
- package/extensions/enact-loop/skills/enact-loop/references/loop-contract.md +114 -0
- package/extensions/enact-loop/skills/loop-budget/SKILL.md +43 -26
- package/extensions/enact-loop/skills/loop-intake/SKILL.md +44 -32
- package/extensions/enact-repo/.agents/plugin.json +55 -0
- package/extensions/enact-repo/.mcp.json +20 -0
- package/extensions/enact-repo/README.md +90 -0
- package/extensions/enact-repo/hooks/hooks.json +98 -0
- package/extensions/enact-repo/lean-ctx/config.toml +35 -0
- package/extensions/enact-repo/lean-ctx/layout.toml +5 -0
- package/extensions/enact-repo/skills/aca-sandboxes/SKILL.md +53 -0
- package/extensions/enact-repo/skills/aca-sandboxes/references/capabilities.md +52 -0
- package/extensions/enact-repo/skills/aca-sandboxes/references/install.md +87 -0
- package/extensions/enact-repo/skills/aca-sandboxes/references/prerequisites.md +52 -0
- package/extensions/enact-repo/skills/aca-sandboxes/references/quickstart.md +164 -0
- package/extensions/enact-repo/skills/aca-sandboxes/references/reference-advanced.md +251 -0
- package/extensions/enact-repo/skills/aca-sandboxes/references/reference.md +287 -0
- package/extensions/enact-repo/skills/aca-sandboxes/references/response-cues.md +71 -0
- package/extensions/enact-repo/skills/aca-sandboxes/references/scenarios.md +219 -0
- package/extensions/enact-repo/skills/aca-sandboxes/version.json +4 -0
- package/extensions/enact-repo/skills/backend-remove-deadcode/SKILL.md +96 -0
- package/extensions/enact-repo/skills/cmux-leader/SKILL.md +61 -0
- package/extensions/enact-repo/skills/cmux-send/SKILL.md +61 -0
- package/extensions/enact-repo/skills/code-review/SKILL.md +100 -0
- package/extensions/enact-repo/skills/codebase-design/SKILL.md +98 -0
- package/extensions/enact-repo/skills/codebase-design/references/DEEPENING.md +37 -0
- package/extensions/enact-repo/skills/codebase-design/references/DESIGN-IT-TWICE.md +44 -0
- package/extensions/enact-repo/skills/codebase-design/references/TESTABILITY.md +29 -0
- package/extensions/enact-repo/skills/computer-use/SKILL.md +76 -0
- package/extensions/enact-repo/skills/debug-issue/SKILL.md +40 -0
- package/extensions/enact-repo/skills/diagnosing-bugs/SKILL.md +100 -0
- package/extensions/enact-repo/skills/diagnosing-bugs/references/FEEDBACK-LOOP-TACTICS.md +34 -0
- package/extensions/enact-repo/skills/diagnosing-bugs/scripts/hitl-loop.template.sh +41 -0
- package/extensions/enact-repo/skills/domain-modeling/SKILL.md +86 -0
- package/extensions/enact-repo/skills/domain-modeling/references/ADR-FORMAT.md +47 -0
- package/extensions/enact-repo/skills/domain-modeling/references/CONTEXT-FORMAT.md +60 -0
- package/extensions/enact-repo/skills/explore-codebase/SKILL.md +41 -0
- package/extensions/enact-repo/skills/frontend-design/LICENSE.txt +177 -0
- package/extensions/enact-repo/skills/frontend-design/SKILL.md +56 -0
- package/extensions/enact-repo/skills/grill-me/SKILL.md +20 -0
- package/extensions/enact-repo/skills/grill-with-docs/SKILL.md +20 -0
- package/extensions/enact-repo/skills/handoff/SKILL.md +28 -0
- package/extensions/enact-repo/skills/http-contract-migration/SKILL.md +74 -0
- package/extensions/enact-repo/skills/http-contract-migration/references/compatibility-and-gates.md +26 -0
- package/extensions/enact-repo/skills/http-contract-migration/references/hexagonal-boundary.md +16 -0
- package/extensions/enact-repo/skills/http-contract-migration/references/publication-and-adoption.md +31 -0
- package/extensions/enact-repo/skills/http-contract-migration/references/wire-fidelity-and-dto.md +31 -0
- package/extensions/enact-repo/skills/implement/SKILL.md +28 -0
- package/extensions/enact-repo/skills/improve-codebase-architecture/SKILL.md +80 -0
- package/extensions/enact-repo/skills/improve-codebase-architecture/references/HTML-REPORT.md +123 -0
- package/extensions/enact-repo/skills/interaction-design/SKILL.md +30 -0
- package/extensions/enact-repo/skills/interaction-design/references/Workflow.md +146 -0
- package/extensions/enact-repo/skills/interaction-design/references/animation-libraries-gsap.md +220 -0
- package/extensions/enact-repo/skills/interaction-design/references/animation-libraries-native.md +110 -0
- package/extensions/enact-repo/skills/interaction-design/references/animation-libraries.md +178 -0
- package/extensions/enact-repo/skills/interaction-design/references/interaction-patterns.md +166 -0
- package/extensions/enact-repo/skills/interaction-design/references/microinteraction-patterns-advanced.md +285 -0
- package/extensions/enact-repo/skills/interaction-design/references/microinteraction-patterns.md +254 -0
- package/extensions/enact-repo/skills/interaction-design/references/scroll-animations-reveals.md +213 -0
- package/extensions/enact-repo/skills/interaction-design/references/scroll-animations.md +209 -0
- package/extensions/enact-repo/skills/lean-ctx/SKILL.md +81 -0
- package/extensions/enact-repo/skills/orca-cli/SKILL.md +88 -0
- package/extensions/enact-repo/skills/orchestration/SKILL.md +80 -0
- package/extensions/enact-repo/skills/prototype/SKILL.md +37 -0
- package/extensions/enact-repo/skills/prototype/references/LOGIC.md +79 -0
- package/extensions/enact-repo/skills/prototype/references/UI.md +112 -0
- package/extensions/enact-repo/skills/refactor-safely/SKILL.md +44 -0
- package/extensions/enact-repo/skills/remove-deadcode/SKILL.md +54 -0
- package/extensions/enact-repo/skills/research/SKILL.md +27 -0
- package/extensions/enact-repo/skills/resolving-merge-conflicts/SKILL.md +28 -0
- package/extensions/enact-repo/skills/review-changes/SKILL.md +45 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/SKILL.md +88 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/accent-color.mdx +149 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/adding-custom-styles.mdx +635 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/align-content.mdx +300 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/align-items.mdx +241 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/align-self.mdx +294 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/animation.mdx +286 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/appearance.mdx +180 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/aspect-ratio.mdx +98 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/backdrop-filter-blur.mdx +109 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/backdrop-filter-brightness.mdx +82 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/backdrop-filter-contrast.mdx +82 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/backdrop-filter-grayscale.mdx +99 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/backdrop-filter-hue-rotate.mdx +173 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/backdrop-filter-invert.mdx +99 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/backdrop-filter-opacity.mdx +103 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/backdrop-filter-saturate.mdx +98 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/backdrop-filter-sepia.mdx +95 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/backdrop-filter.mdx +113 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/backface-visibility.mdx +110 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/background-attachment.mdx +126 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/background-blend-mode.mdx +79 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/background-clip.mdx +85 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/background-color.mdx +176 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/background-image.mdx +349 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/background-origin.mdx +64 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/background-position.mdx +171 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/background-repeat.mdx +127 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/background-size.mdx +100 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/block-size.mdx +190 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/border-collapse.mdx +181 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/border-color.mdx +316 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/border-radius.mdx +347 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/border-spacing.mdx +117 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/border-style.mdx +129 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/border-width.mdx +344 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/box-decoration-break.mdx +71 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/box-shadow.mdx +497 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/box-sizing.mdx +175 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/break-after.mdx +38 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/break-before.mdx +38 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/break-inside.mdx +34 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/caption-side.mdx +190 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/caret-color.mdx +66 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/clear.mdx +224 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/color-scheme.mdx +81 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/color.mdx +125 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/colors.mdx +927 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/columns.mdx +310 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/compatibility.mdx +193 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/content.mdx +129 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/cursor.mdx +104 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/dark-mode.mdx +191 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/detecting-classes-in-source-files.mdx +315 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/display.mdx +523 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/editor-setup.mdx +90 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/field-sizing.mdx +75 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/fill.mdx +100 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/filter-blur.mdx +114 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/filter-brightness.mdx +102 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/filter-contrast.mdx +102 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/filter-drop-shadow.mdx +230 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/filter-grayscale.mdx +101 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/filter-hue-rotate.mdx +171 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/filter-invert.mdx +93 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/filter-saturate.mdx +109 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/filter-sepia.mdx +92 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/filter.mdx +113 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/flex-basis.mdx +144 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/flex-direction.mdx +130 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/flex-grow.mdx +129 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/flex-shrink.mdx +95 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/flex-wrap.mdx +118 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/flex.mdx +164 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/float.mdx +197 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/font-family.mdx +119 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/font-feature-settings.mdx +52 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/font-size.mdx +184 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/font-smoothing.mdx +67 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/font-stretch.mdx +138 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/font-style.mdx +62 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/font-variant-numeric.mdx +228 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/font-weight.mdx +105 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/forced-color-adjust.mdx +152 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/functions-and-directives.mdx +322 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/gap.mdx +100 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/grid-auto-columns.mdx +43 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/grid-auto-flow.mdx +58 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/grid-auto-rows.mdx +43 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/grid-column.mdx +124 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/grid-row.mdx +115 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/grid-template-columns.mdx +101 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/grid-template-rows.mdx +108 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/height.mdx +260 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/hover-focus-and-other-states.mdx +4935 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/hyphens.mdx +112 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/inline-size.mdx +191 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/isolation.mdx +30 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/justify-content.mdx +348 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/justify-items.mdx +286 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/justify-self.mdx +282 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/letter-spacing.mdx +100 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/line-clamp.mdx +110 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/line-height.mdx +147 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/list-style-image.mdx +80 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/list-style-position.mdx +67 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/list-style-type.mdx +86 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/margin.mdx +397 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/mask-clip.mdx +66 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/mask-composite.mdx +70 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/mask-image.mdx +933 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/mask-mode.mdx +114 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/mask-origin.mdx +66 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/mask-position.mdx +117 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/mask-repeat.mdx +169 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/mask-size.mdx +104 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/mask-type.mdx +98 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/max-block-size.mdx +153 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/max-height.mdx +164 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/max-inline-size.mdx +185 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/max-width.mdx +214 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/min-block-size.mdx +146 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/min-height.mdx +150 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/min-inline-size.mdx +153 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/min-width.mdx +153 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/mix-blend-mode.mdx +103 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/object-fit.mdx +147 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/object-position.mdx +182 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/opacity.mdx +84 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/order.mdx +94 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/outline-color.mdx +130 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/outline-offset.mdx +72 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/outline-style.mdx +134 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/outline-width.mdx +91 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/overflow-wrap.mdx +130 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/overflow.mdx +665 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/overscroll-behavior.mdx +151 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/padding.mdx +232 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/perspective-origin.mdx +127 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/perspective.mdx +137 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/place-content.mdx +257 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/place-items.mdx +269 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/place-self.mdx +257 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/pointer-events.mdx +101 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/position.mdx +399 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/preflight.mdx +291 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/resize.mdx +110 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/responsive-design.mdx +666 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/rotate.mdx +291 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/scale.mdx +360 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/scroll-behavior.mdx +39 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/scroll-margin.mdx +268 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/scroll-padding.mdx +255 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/scroll-snap-align.mdx +281 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/scroll-snap-stop.mdx +198 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/scroll-snap-type.mdx +284 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/skew.mdx +352 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/stroke-width.mdx +74 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/stroke.mdx +103 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/styling-with-utility-classes.mdx +1020 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/table-layout.mdx +212 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/text-align.mdx +162 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/text-decoration-color.mdx +155 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/text-decoration-line.mdx +143 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/text-decoration-style.mdx +75 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/text-decoration-thickness.mdx +75 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/text-indent.mdx +74 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/text-overflow.mdx +103 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/text-shadow.mdx +177 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/text-transform.mdx +106 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/text-underline-offset.mdx +74 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/text-wrap.mdx +144 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/theme.mdx +1142 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/top-right-bottom-left.mdx +296 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/touch-action.mdx +95 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/transform-origin.mdx +130 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/transform-style.mdx +110 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/transform.mdx +51 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/transition-behavior.mdx +76 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/transition-delay.mdx +76 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/transition-duration.mdx +82 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/transition-property.mdx +137 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/transition-timing-function.mdx +89 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/translate.mdx +487 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/upgrade-guide.mdx +910 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/user-select.mdx +114 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/vertical-align.mdx +194 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/visibility.mdx +287 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/white-space.mdx +211 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/width.mdx +264 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/will-change.mdx +47 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/word-break.mdx +94 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs/z-index.mdx +104 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs-catalog.md +251 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs-index.tsx +237 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/docs-source.txt +6 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/references/gotchas.md +18 -0
- package/extensions/enact-repo/skills/tailwind-4-docs/scripts/sync_tailwind_docs.py +183 -0
- package/extensions/enact-repo/skills/tdd/SKILL.md +49 -0
- package/extensions/enact-repo/skills/tdd/references/mocking.md +59 -0
- package/extensions/enact-repo/skills/tdd/references/tests.md +77 -0
- package/extensions/enact-repo/skills/teach/SKILL.md +88 -0
- package/extensions/enact-repo/skills/teach/references/GLOSSARY-FORMAT.md +35 -0
- package/extensions/enact-repo/skills/teach/references/LEARNING-RECORD-FORMAT.md +46 -0
- package/extensions/enact-repo/skills/teach/references/MISSION-FORMAT.md +31 -0
- package/extensions/enact-repo/skills/teach/references/PHILOSOPHY.md +65 -0
- package/extensions/enact-repo/skills/teach/references/RESOURCES-FORMAT.md +32 -0
- package/extensions/enact-repo/skills/testing/SKILL.md +54 -0
- package/extensions/enact-repo/skills/to-spec/SKILL.md +85 -0
- package/extensions/enact-repo/skills/to-tickets/SKILL.md +75 -0
- package/extensions/enact-repo/skills/to-tickets/references/TICKET-TEMPLATES.md +39 -0
- package/extensions/enact-repo/skills/triage/SKILL.md +99 -0
- package/extensions/enact-repo/skills/triage/references/AGENT-BRIEF.md +207 -0
- package/extensions/enact-repo/skills/triage/references/NEEDS-INFO-TEMPLATE.md +17 -0
- package/extensions/enact-repo/skills/triage/references/OUT-OF-SCOPE.md +105 -0
- package/extensions/enact-repo/skills/ui-ux-pro-max/SKILL.md +32 -0
- package/extensions/enact-repo/skills/ui-ux-pro-max/references/Workflow.md +207 -0
- package/extensions/enact-repo/skills/ui-ux-pro-max/references/workflow-reference.md +175 -0
- package/extensions/enact-repo/skills/wayfinder/SKILL.md +100 -0
- package/extensions/enact-repo/skills/wayfinder/references/TEMPLATES.md +35 -0
- package/extensions/enact-repo/skills/wayfinder/references/TICKET-TYPES.md +8 -0
- package/extensions/enact-repo/skills/writing-great-skills/SKILL.md +93 -0
- package/extensions/enact-repo/skills/writing-great-skills/references/GLOSSARY.md +201 -0
- package/package.json +18 -14
- package/scripts/enact-extensions.mjs +255 -878
- package/scripts/lib/allowed-plugins.mjs +52 -0
- package/scripts/lib/run-repo-doctor.mjs +571 -0
- package/scripts/lib/run-repo-install.mjs +1579 -0
- package/scripts/lib/run-sync.mjs +1 -1
- package/scripts/lib/run-validate.mjs +23 -37
- package/scripts/lib/skill-validator.mjs +872 -0
- package/spec/enact.json +21 -3
- package/spec/enact.md +13 -12
- package/spec/kimi.json +100 -0
- package/spec/opencode.json +64 -0
- package/dist/install.d.ts +0 -235
- package/dist/install.d.ts.map +0 -1
- package/dist/install.js +0 -697
- package/dist/install.js.map +0 -1
- package/dist/internal/claude.d.ts +0 -65
- package/dist/internal/claude.d.ts.map +0 -1
- package/dist/internal/claude.js +0 -200
- package/dist/internal/claude.js.map +0 -1
- package/dist/internal/codex.d.ts +0 -43
- package/dist/internal/codex.d.ts.map +0 -1
- package/dist/internal/codex.js +0 -211
- package/dist/internal/codex.js.map +0 -1
- package/dist/internal/cursor.d.ts +0 -2
- package/dist/internal/cursor.d.ts.map +0 -1
- package/dist/internal/cursor.js +0 -6
- package/dist/internal/cursor.js.map +0 -1
- package/dist/principles.d.ts +0 -28
- package/dist/principles.d.ts.map +0 -1
- package/dist/principles.js +0 -159
- package/dist/principles.js.map +0 -1
- package/dist/provision.d.ts +0 -30
- package/dist/provision.d.ts.map +0 -1
- package/dist/provision.js +0 -202
- package/dist/provision.js.map +0 -1
- package/extensions/dev-state/.agents/plugin.json +0 -36
- package/extensions/dev-state/skills/dev-state-plan-graduation/SKILL.md +0 -194
- package/extensions/dev-state/skills/dev-state-plan-graduation/agents/openai.yaml +0 -4
- package/extensions/dev-state/skills/dev-state-plan-graduation/references/reference.md +0 -130
- package/extensions/enact-context/.agents/plugin.json +0 -41
- package/extensions/enact-context/.mcp.json +0 -8
- package/extensions/enact-context/README.md +0 -25
- package/extensions/enact-context/assets/icon.png +0 -0
- package/extensions/enact-context/assets/logo.png +0 -0
- package/extensions/enact-context/hooks/hooks.json +0 -115
- package/extensions/enact-context/skills/enact-context/SKILL.md +0 -151
- package/extensions/enact-context/skills/enact-context/scripts/install.sh +0 -69
- package/extensions/enact-core/.agents/plugin.json +0 -40
- package/extensions/enact-core/OPERATING-PRINCIPLES.md +0 -7
- package/extensions/enact-core/hooks/hooks.json +0 -26
- package/extensions/enact-evolve/.agents/plugin.json +0 -47
- package/extensions/enact-evolve/agents/evolve-session-analyst.toml +0 -37
- package/extensions/enact-evolve/assets/icon.png +0 -0
- package/extensions/enact-evolve/assets/logo.png +0 -0
- package/extensions/enact-evolve/skills/mined-investigate-loop/SKILL.md +0 -68
- package/extensions/enact-evolve/skills/session-analysis/SKILL.md +0 -98
- package/extensions/enact-evolve/skills/session-analysis/scripts/run-evolve-analysis.sh +0 -343
- package/extensions/enact-factory/.agents/plugin.json +0 -49
- package/extensions/enact-factory/.mcp.json +0 -8
- package/extensions/enact-factory/agents/architect.toml +0 -34
- package/extensions/enact-factory/agents/code-reviewer.toml +0 -33
- package/extensions/enact-factory/agents/critic.toml +0 -39
- package/extensions/enact-factory/agents/executor.toml +0 -26
- package/extensions/enact-factory/agents/explore.toml +0 -25
- package/extensions/enact-factory/agents/planner.toml +0 -26
- package/extensions/enact-factory/agents/verifier.toml +0 -33
- package/extensions/enact-factory/assets/icon.png +0 -0
- package/extensions/enact-factory/assets/logo.png +0 -0
- package/extensions/enact-factory/skills/advisor/SKILL.md +0 -82
- package/extensions/enact-factory/skills/ai-slop-cleaner/SKILL.md +0 -57
- package/extensions/enact-factory/skills/autonomous-runner/SKILL.md +0 -353
- package/extensions/enact-factory/skills/azdo-ci-strategy/SKILL.md +0 -309
- package/extensions/enact-factory/skills/azdo-ci-strategy/references/build-failures.md +0 -60
- package/extensions/enact-factory/skills/azdo-ci-strategy/references/cli-reference.md +0 -87
- package/extensions/enact-factory/skills/azdo-ci-strategy/references/policies-and-pipelines.md +0 -132
- package/extensions/enact-factory/skills/azdo-ci-strategy/references/troubleshooting.md +0 -53
- package/extensions/enact-factory/skills/cmux-leader/SKILL.md +0 -74
- package/extensions/enact-factory/skills/cmux-send/SKILL.md +0 -50
- package/extensions/enact-factory/skills/committee/SKILL.md +0 -80
- package/extensions/enact-factory/skills/deep-interview/SKILL.md +0 -68
- package/extensions/enact-factory/skills/deslop-handover/SKILL.md +0 -97
- package/extensions/enact-factory/skills/deslop-handover/deslop.py +0 -181
- package/extensions/enact-factory/skills/drive-loop/SKILL.md +0 -394
- package/extensions/enact-factory/skills/drive-loop/references/contract-schema.md +0 -127
- package/extensions/enact-factory/skills/handoff/SKILL.md +0 -75
- package/extensions/enact-factory/skills/hyperplan/SKILL.md +0 -59
- package/extensions/enact-factory/skills/looplan/SKILL.md +0 -120
- package/extensions/enact-factory/skills/paseo-dispatch/SKILL.md +0 -141
- package/extensions/enact-factory/skills/plan/SKILL.md +0 -103
- package/extensions/enact-factory/skills/remove-deadcode/SKILL.md +0 -46
- package/extensions/enact-factory/skills/research/SKILL.md +0 -83
- package/extensions/enact-factory/skills/review/SKILL.md +0 -67
- package/extensions/enact-factory/skills/security-research/SKILL.md +0 -57
- package/extensions/enact-factory/skills/tdd/SKILL.md +0 -62
- package/extensions/enact-factory/skills/testing-strategy/SKILL.md +0 -172
- package/extensions/enact-factory/skills/trace/SKILL.md +0 -42
- package/extensions/enact-factory/skills/ultraqa/SKILL.md +0 -85
- package/extensions/enact-factory/skills/work-with-workitem/SKILL.md +0 -56
- package/extensions/enact-factory/skills/workitem-triage/SKILL.md +0 -42
- package/extensions/enact-wiki/.agents/plugin.json +0 -43
- package/extensions/enact-wiki/.mcp.json +0 -15
- package/extensions/enact-wiki/README.md +0 -44
- package/extensions/enact-wiki/assets/icon.png +0 -0
- package/extensions/enact-wiki/assets/logo.png +0 -0
- package/extensions/enact-wiki/skills/document-parser/SKILL.md +0 -17
- package/extensions/enact-wiki/skills/document-parser/scripts/parse.sh +0 -60
- package/extensions/enact-wiki/skills/document-parser/skill.json +0 -9
- package/extensions/enact-wiki/skills/enact-wiki/SKILL.md +0 -30
- package/extensions/enact-wiki/skills/enact-wiki/references/ingest.md +0 -62
- package/extensions/enact-wiki/skills/enact-wiki/references/manage.md +0 -34
- package/extensions/enact-wiki/skills/enact-wiki/references/query.md +0 -59
- package/extensions/enact-wiki/skills/search-lab/SKILL.md +0 -57
- package/extensions/enact-wiki/skills/search-lab/scripts/analyze.ts +0 -23
- package/extensions/enact-wiki/skills/wiki/SKILL.md +0 -42
- package/extensions/net-revenue-management/.agents/plugin.json +0 -40
- package/extensions/net-revenue-management/.mcp.json +0 -9
- package/extensions/net-revenue-management/skills/net-revenue-risks/SKILL.md +0 -30
- package/extensions/net-revenue-management/skills/net-revenue-scenario/SKILL.md +0 -31
- package/extensions/plugin-dev/.agents/plugin.json +0 -41
- package/extensions/plugin-dev/agents/agent-creator.md +0 -199
- package/extensions/plugin-dev/agents/plugin-validator.md +0 -91
- package/extensions/plugin-dev/agents/skill-reviewer.md +0 -212
- package/extensions/plugin-dev/skills/agent-development/SKILL.md +0 -641
- package/extensions/plugin-dev/skills/agent-development/examples/agent-creation-prompt.md +0 -250
- package/extensions/plugin-dev/skills/agent-development/examples/complete-agent-examples.md +0 -461
- package/extensions/plugin-dev/skills/agent-development/references/advanced-agent-fields.md +0 -246
- package/extensions/plugin-dev/skills/agent-development/references/agent-creation-system-prompt.md +0 -216
- package/extensions/plugin-dev/skills/agent-development/references/permission-modes-rules.md +0 -226
- package/extensions/plugin-dev/skills/agent-development/references/system-prompt-design.md +0 -464
- package/extensions/plugin-dev/skills/agent-development/references/triggering-examples.md +0 -474
- package/extensions/plugin-dev/skills/agent-development/scripts/create-agent-skeleton.sh +0 -176
- package/extensions/plugin-dev/skills/agent-development/scripts/test-agent-trigger.sh +0 -227
- package/extensions/plugin-dev/skills/agent-development/scripts/validate-agent.sh +0 -227
- package/extensions/plugin-dev/skills/create-plugin/SKILL.md +0 -505
- package/extensions/plugin-dev/skills/hook-development/SKILL.md +0 -861
- package/extensions/plugin-dev/skills/hook-development/examples/load-context.sh +0 -55
- package/extensions/plugin-dev/skills/hook-development/examples/validate-bash.sh +0 -57
- package/extensions/plugin-dev/skills/hook-development/examples/validate-write.sh +0 -48
- package/extensions/plugin-dev/skills/hook-development/references/advanced.md +0 -871
- package/extensions/plugin-dev/skills/hook-development/references/hook-input-schemas.md +0 -145
- package/extensions/plugin-dev/skills/hook-development/references/migration.md +0 -392
- package/extensions/plugin-dev/skills/hook-development/references/patterns.md +0 -430
- package/extensions/plugin-dev/skills/hook-development/scripts/README.md +0 -181
- package/extensions/plugin-dev/skills/hook-development/scripts/hook-linter.sh +0 -153
- package/extensions/plugin-dev/skills/hook-development/scripts/test-hook.sh +0 -276
- package/extensions/plugin-dev/skills/hook-development/scripts/validate-hook-schema.sh +0 -159
- package/extensions/plugin-dev/skills/mcp-integration/SKILL.md +0 -775
- package/extensions/plugin-dev/skills/mcp-integration/examples/http-server.json +0 -20
- package/extensions/plugin-dev/skills/mcp-integration/examples/sse-server.json +0 -19
- package/extensions/plugin-dev/skills/mcp-integration/examples/stdio-server.json +0 -38
- package/extensions/plugin-dev/skills/mcp-integration/examples/ws-server.json +0 -26
- package/extensions/plugin-dev/skills/mcp-integration/references/authentication.md +0 -601
- package/extensions/plugin-dev/skills/mcp-integration/references/server-discovery.md +0 -190
- package/extensions/plugin-dev/skills/mcp-integration/references/server-types.md +0 -572
- package/extensions/plugin-dev/skills/mcp-integration/references/tool-usage.md +0 -623
- package/extensions/plugin-dev/skills/plugin-dev-guide/SKILL.md +0 -221
- package/extensions/plugin-dev/skills/plugin-structure/SKILL.md +0 -705
- package/extensions/plugin-dev/skills/plugin-structure/examples/advanced-plugin.md +0 -774
- package/extensions/plugin-dev/skills/plugin-structure/examples/minimal-plugin.md +0 -83
- package/extensions/plugin-dev/skills/plugin-structure/examples/standard-plugin.md +0 -611
- package/extensions/plugin-dev/skills/plugin-structure/references/advanced-topics.md +0 -289
- package/extensions/plugin-dev/skills/plugin-structure/references/component-patterns.md +0 -592
- package/extensions/plugin-dev/skills/plugin-structure/references/github-actions.md +0 -233
- package/extensions/plugin-dev/skills/plugin-structure/references/headless-ci-mode.md +0 -193
- package/extensions/plugin-dev/skills/plugin-structure/references/manifest-reference.md +0 -625
- package/extensions/plugin-dev/skills/plugin-structure/references/output-styles.md +0 -116
- package/extensions/plugin-dev/skills/skill-development/SKILL.md +0 -562
- package/extensions/plugin-dev/skills/skill-development/examples/complete-skill.md +0 -465
- package/extensions/plugin-dev/skills/skill-development/examples/frontmatter-templates.md +0 -167
- package/extensions/plugin-dev/skills/skill-development/examples/minimal-skill.md +0 -111
- package/extensions/plugin-dev/skills/skill-development/references/advanced-frontmatter.md +0 -225
- package/extensions/plugin-dev/skills/skill-development/references/commands-vs-skills.md +0 -39
- package/extensions/plugin-dev/skills/skill-development/references/skill-creation-workflow.md +0 -379
- package/extensions/plugin-dev/skills/skill-development/references/skill-creator-original.md +0 -210
- package/extensions/plugin-dev/skills/start/SKILL.md +0 -82
- package/scripts/check-hooks.mjs +0 -174
- package/scripts/check-principles.mjs +0 -116
- package/scripts/hooks/session-start-drift-check.mjs +0 -49
- package/scripts/install.sh +0 -70
- package/scripts/lib/auto-update.mjs +0 -88
- package/scripts/lib/bundle-hash.mjs +0 -137
- package/scripts/lib/hooks.mjs +0 -585
- package/scripts/lib/ledger.mjs +0 -163
- package/scripts/lib/migrate-artifacts.mjs +0 -144
- package/scripts/lib/outdated.mjs +0 -144
- package/scripts/lib/postinstall-offer.mjs +0 -83
- package/scripts/lib/principles.mjs +0 -109
- package/scripts/lib/provision-mcp.mjs +0 -16
- package/scripts/lib/resolve-plugin-root.mjs +0 -9
- package/scripts/lib/run-install.mjs +0 -507
- package/scripts/lib/run-prune.mjs +0 -94
- package/scripts/lib/run-uninstall.mjs +0 -244
- package/scripts/lib/run-update.mjs +0 -165
- package/scripts/lib/serve.mjs +0 -472
- package/scripts/lib/ups-router.mjs +0 -392
- package/scripts/postinstall.mjs +0 -101
- package/scripts/setup-enact-context.sh +0 -28
- package/scripts/version-bump.sh +0 -484
- package/web/assets/README.md +0 -111
- package/web/assets/logo-full.png +0 -0
- package/web/assets/logo-slim.png +0 -0
- package/web/assets/tokens/base.css +0 -45
- package/web/assets/tokens/colors.css +0 -248
- package/web/assets/tokens/effects.css +0 -24
- package/web/assets/tokens/fonts.css +0 -8
- package/web/assets/tokens/index.css +0 -18
- package/web/assets/tokens/spacing.css +0 -50
- package/web/index.html +0 -1188
|
@@ -0,0 +1,696 @@
|
|
|
1
|
+
import { MANIFEST_FIELDS } from "../internal/platform.js";
|
|
2
|
+
import { pickManifestFields, withPlatformKeyword } from "../internal/pick.js";
|
|
3
|
+
import { withHostFlag } from "../internal/hooks.js";
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// OpenCode manifest descriptor (DERIVERS entry)
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
/**
|
|
8
|
+
* Derive the OpenCode descriptor (`.opencode-plugin/plugin.json`) from the
|
|
9
|
+
* canonical Enact manifest. OpenCode has no documented plugin manifest file of
|
|
10
|
+
* its own — this descriptor is Enact-internal bookkeeping (validated by
|
|
11
|
+
* spec/opencode.json) that records project metadata plus the canonical
|
|
12
|
+
* `hooks`/`mcpServers` SOURCE PATHS (not their resolved content). A future
|
|
13
|
+
* installer reads those paths, loads the referenced JSON, and calls
|
|
14
|
+
* {@link deriveOpenCodeMcp} / {@link deriveOpenCodePlugin} to generate the
|
|
15
|
+
* real OpenCode artifacts: a root `opencode.json` MCP fragment and a
|
|
16
|
+
* `.opencode/plugins/<name>.ts` file.
|
|
17
|
+
*/
|
|
18
|
+
export function deriveOpenCodeManifest(enact) {
|
|
19
|
+
const picked = pickManifestFields(enact, MANIFEST_FIELDS.opencode);
|
|
20
|
+
return {
|
|
21
|
+
...picked,
|
|
22
|
+
description: (typeof picked.description === "string" ? picked.description : undefined) ??
|
|
23
|
+
`${enact.name} plugin for OpenCode.`,
|
|
24
|
+
keywords: withPlatformKeyword(Array.isArray(picked.keywords) ? picked.keywords : undefined, "opencode"),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Project a canonical `.mcp.json` document
|
|
29
|
+
* (`{mcpServers:{name:{command,args,env,cwd?}}}`) into OpenCode's root
|
|
30
|
+
* `opencode.json` MCP fragment.
|
|
31
|
+
*
|
|
32
|
+
* Source (verified 2026-09-14, this session): https://opencode.ai/docs —
|
|
33
|
+
* OpenCode MCP servers are declared directly under `"mcp"` in `opencode.json`
|
|
34
|
+
* as `{"<name>": {"type":"local", "command":["cmd", ...args],
|
|
35
|
+
* "environment": {...}, "cwd": "...", "enabled": true}}`. There is no
|
|
36
|
+
* `servers` wrapper (unlike the canonical `mcpServers` key) and no `disabled`
|
|
37
|
+
* key — OpenCode uses `enabled` and we always emit `enabled: true` for a
|
|
38
|
+
* server the canonical manifest declares (a disabled server simply would not
|
|
39
|
+
* be declared).
|
|
40
|
+
*
|
|
41
|
+
* Servers without a `command` (e.g. a remote/HTTP-only definition) have no
|
|
42
|
+
* documented OpenCode "local" equivalent here and are skipped rather than
|
|
43
|
+
* guessed at.
|
|
44
|
+
*/
|
|
45
|
+
export function deriveOpenCodeMcp(canonicalMcp) {
|
|
46
|
+
const doc = canonicalMcp && typeof canonicalMcp === "object" && !Array.isArray(canonicalMcp)
|
|
47
|
+
? canonicalMcp
|
|
48
|
+
: {};
|
|
49
|
+
const servers = doc.mcpServers && typeof doc.mcpServers === "object" && !Array.isArray(doc.mcpServers)
|
|
50
|
+
? doc.mcpServers
|
|
51
|
+
: {};
|
|
52
|
+
const mcp = {};
|
|
53
|
+
for (const [name, def] of Object.entries(servers)) {
|
|
54
|
+
if (!def || typeof def !== "object" || Array.isArray(def))
|
|
55
|
+
continue;
|
|
56
|
+
const command = typeof def.command === "string" ? def.command : undefined;
|
|
57
|
+
if (!command)
|
|
58
|
+
continue;
|
|
59
|
+
const args = Array.isArray(def.args) ? def.args.map((a) => String(a)) : [];
|
|
60
|
+
const entry = {
|
|
61
|
+
type: "local",
|
|
62
|
+
command: [command, ...args],
|
|
63
|
+
enabled: true,
|
|
64
|
+
};
|
|
65
|
+
if (def.env && typeof def.env === "object" && !Array.isArray(def.env)) {
|
|
66
|
+
const environment = {};
|
|
67
|
+
for (const [k, v] of Object.entries(def.env)) {
|
|
68
|
+
environment[k] = String(v);
|
|
69
|
+
}
|
|
70
|
+
entry.environment = environment;
|
|
71
|
+
}
|
|
72
|
+
if (typeof def.cwd === "string" && def.cwd.trim()) {
|
|
73
|
+
entry.cwd = def.cwd;
|
|
74
|
+
}
|
|
75
|
+
mcp[name] = entry;
|
|
76
|
+
}
|
|
77
|
+
return { mcp };
|
|
78
|
+
}
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
// OpenCode hooks + MCP + skills -> ONE project plugin
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
//
|
|
83
|
+
// Owner decision (Tarun, 2026-09-14): OpenCode output is a SINGLE real plugin
|
|
84
|
+
// (`.opencode/plugins/<name>.ts`) that carries hooks, MCP servers AND skills
|
|
85
|
+
// together — not three separate artifacts. This reflects live evidence
|
|
86
|
+
// gathered against a real OpenCode 1.18.29 install (see
|
|
87
|
+
// .scratch/opencode-plugin-example/ and .scratch/opencode-probe/ in this
|
|
88
|
+
// repo) plus the official @opencode-ai/plugin `Hooks` interface:
|
|
89
|
+
//
|
|
90
|
+
// - `config(input)` mutation adds `mcp` servers and `skills.paths` —
|
|
91
|
+
// confirmed via `opencode debug config` / `opencode mcp list` /
|
|
92
|
+
// `opencode debug skill` against a live install. A same-named MCP server
|
|
93
|
+
// already present in the user's config is left untouched (skip + log to
|
|
94
|
+
// stderr) — user config survives.
|
|
95
|
+
// - `session.created` / `session.idle` are NOT top-level Hooks keys (an
|
|
96
|
+
// earlier version of this generator emitted them as top-level object
|
|
97
|
+
// keys, which never fired — a real bug the current tests catch). They
|
|
98
|
+
// only arrive via the generic `event({event})` hook, dispatched on
|
|
99
|
+
// `event.type`.
|
|
100
|
+
// - Pushing a synthetic text part onto `chat.message`'s `output.parts` was
|
|
101
|
+
// tried and PASSED without throwing, but broke every subsequent real
|
|
102
|
+
// `opencode run` call with `UnknownError: Unexpected server error` (live
|
|
103
|
+
// A/B evidence, .scratch/opencode-probe/log.jsonl). Context injection
|
|
104
|
+
// instead: `chat.message` runs the UserPromptSubmit command and stores
|
|
105
|
+
// its context keyed by `input.sessionID`; `experimental.chat.system.transform`
|
|
106
|
+
// (confirmed firing on every request, carrying `sessionID`) appends that
|
|
107
|
+
// stored context to `output.system` for the MATCHING session only.
|
|
108
|
+
// - `tool.execute.before` (throw to block) / `tool.execute.after` are real
|
|
109
|
+
// top-level keys, live-confirmed to block a bash call.
|
|
110
|
+
// - Plugin root is resolved from the `directory` the OpenCode runtime
|
|
111
|
+
// passes into the plugin factory (the project root) — never from
|
|
112
|
+
// `${CLAUDE_PLUGIN_ROOT}`, which OpenCode does not set.
|
|
113
|
+
//
|
|
114
|
+
// Event mapping (table-driven, same pattern as CURSOR_HOOK_EVENT_MAP in
|
|
115
|
+
// src/internal/agents.ts). The map value is either a literal OpenCode Hooks
|
|
116
|
+
// key ("tool.execute.before", "chat.message", ...) or, for the two events
|
|
117
|
+
// that only exist as `event.type` values, a synthetic "event:<type>" key
|
|
118
|
+
// meaning "dispatched inside the shared `event` hook when event.type equals
|
|
119
|
+
// <type>":
|
|
120
|
+
//
|
|
121
|
+
// PreToolUse -> tool.execute.before (throw to block; deny contract below)
|
|
122
|
+
// PostToolUse -> tool.execute.after (cannot block: the call already ran)
|
|
123
|
+
// UserPromptSubmit -> chat.message (+ experimental.chat.system.transform
|
|
124
|
+
// pairing — see context-injection
|
|
125
|
+
// note above; this used to fall
|
|
126
|
+
// back onto SessionStart because no
|
|
127
|
+
// direct equivalent was known. It
|
|
128
|
+
// is now a NATIVE mapping.)
|
|
129
|
+
// SessionStart -> event:session.created
|
|
130
|
+
// SessionIdle -> event:session.idle
|
|
131
|
+
// PreCompact -> experimental.session.compacting
|
|
132
|
+
//
|
|
133
|
+
// Left UNMAPPED on purpose (never invented — surfaced as `warnings` instead):
|
|
134
|
+
// - Stop: no documented "main agent turn finished" event distinct from
|
|
135
|
+
// session.idle (which already covers SessionIdle).
|
|
136
|
+
// - SubagentStart / SubagentStop: no documented subagent lifecycle hook.
|
|
137
|
+
//
|
|
138
|
+
// Fallback (owner rule, Tarun): when a host has no equivalent of a canonical
|
|
139
|
+
// event, its hooks run on a documented substitute event instead:
|
|
140
|
+
// - SessionEnd -> SessionIdle: OpenCode has no session-end event, so
|
|
141
|
+
// canonical SessionEnd hooks run on `event:session.idle` (folded into the
|
|
142
|
+
// same bucket as native SessionIdle hooks, running after them, each
|
|
143
|
+
// command still carrying its own `fallback_for: "SessionEnd"` tag).
|
|
144
|
+
// Accepted consequence: they fire after every response, not only at true
|
|
145
|
+
// session end.
|
|
146
|
+
const OPENCODE_HOOK_EVENT_MAP = {
|
|
147
|
+
PreToolUse: "tool.execute.before",
|
|
148
|
+
PostToolUse: "tool.execute.after",
|
|
149
|
+
UserPromptSubmit: "chat.message",
|
|
150
|
+
SessionStart: "event:session.created",
|
|
151
|
+
SessionIdle: "event:session.idle",
|
|
152
|
+
PreCompact: "experimental.session.compacting",
|
|
153
|
+
};
|
|
154
|
+
/**
|
|
155
|
+
* Table-driven fallback for canonical events with no documented OpenCode
|
|
156
|
+
* equivalent of their own.
|
|
157
|
+
*
|
|
158
|
+
* - SessionEnd -> SessionIdle (owner rule, Tarun): OpenCode has no
|
|
159
|
+
* session-end event, so canonical SessionEnd hooks run on SessionIdle
|
|
160
|
+
* instead — attaching to the `event:session.idle` bucket. Accepted
|
|
161
|
+
* consequence: they fire after every response, not only at true session
|
|
162
|
+
* end.
|
|
163
|
+
*
|
|
164
|
+
* Fallback commands run AFTER any native commands already targeting that
|
|
165
|
+
* same bucket, each still honoring its own `timeout`. The stdin payload for a
|
|
166
|
+
* fallback command stays truthful about which event actually fired
|
|
167
|
+
* (`hook_event_name` is the FALLBACK TARGET's canonical name) plus
|
|
168
|
+
* `fallback_for` naming the originating canonical event — and never
|
|
169
|
+
* fabricates fields that don't exist for the target event.
|
|
170
|
+
*/
|
|
171
|
+
const OPENCODE_HOOK_EVENT_FALLBACK = {
|
|
172
|
+
SessionEnd: "SessionIdle",
|
|
173
|
+
};
|
|
174
|
+
/** OpenCode Hooks keys whose handler receives the tool call as `(input, output)`. */
|
|
175
|
+
const OPENCODE_TOOL_EVENTS = new Set(["tool.execute.before", "tool.execute.after"]);
|
|
176
|
+
/**
|
|
177
|
+
* Canonical (Claude-style, cross-host) tool-name token -> real OpenCode tool
|
|
178
|
+
* id. Canonical `hooks.json` matchers (see
|
|
179
|
+
* `extensions/enact-repo/hooks/hooks.json`) are written in Claude's
|
|
180
|
+
* PascalCase vocabulary plus a handful of other hosts' own names
|
|
181
|
+
* (`str_replace_editor` is Codex's editor tool, `edit_file` is Cursor's,
|
|
182
|
+
* `create_file`/`write_file` appear in some agent SDKs) -- none of which
|
|
183
|
+
* match OpenCode's OWN tool ids.
|
|
184
|
+
*
|
|
185
|
+
* Source of truth: live `GET /experimental/tool/ids` against a real
|
|
186
|
+
* `opencode serve` 1.18.18 instance (verified 2026-09-14, this session,
|
|
187
|
+
* `.scratch/toolid-probe/`), which returned exactly:
|
|
188
|
+
* ["invalid","question","bash","read","glob","grep","edit","write","task",
|
|
189
|
+
* "webfetch","todowrite","websearch","skill","apply_patch"]
|
|
190
|
+
* Notably: OpenCode tool ids are lowercase and single-word; there is no
|
|
191
|
+
* "list" tool, and the apply-a-raw-patch tool is "apply_patch", not "patch".
|
|
192
|
+
*/
|
|
193
|
+
const CANONICAL_TO_OPENCODE_TOOL = {
|
|
194
|
+
bash: "bash",
|
|
195
|
+
shell: "bash",
|
|
196
|
+
read: "read",
|
|
197
|
+
write: "write",
|
|
198
|
+
writefile: "write",
|
|
199
|
+
write_file: "write",
|
|
200
|
+
createfile: "write",
|
|
201
|
+
create_file: "write",
|
|
202
|
+
edit: "edit",
|
|
203
|
+
multiedit: "edit",
|
|
204
|
+
strreplace: "edit",
|
|
205
|
+
str_replace: "edit",
|
|
206
|
+
str_replace_editor: "edit",
|
|
207
|
+
edit_file: "edit",
|
|
208
|
+
replace_in_file: "edit",
|
|
209
|
+
grep: "grep",
|
|
210
|
+
glob: "glob",
|
|
211
|
+
webfetch: "webfetch",
|
|
212
|
+
websearch: "websearch",
|
|
213
|
+
todowrite: "todowrite",
|
|
214
|
+
task: "task",
|
|
215
|
+
skill: "skill",
|
|
216
|
+
apply_patch: "apply_patch",
|
|
217
|
+
patch: "apply_patch",
|
|
218
|
+
question: "question",
|
|
219
|
+
};
|
|
220
|
+
/**
|
|
221
|
+
* Project a canonical matcher (e.g. `"Bash"`, or
|
|
222
|
+
* `"Write|Edit|MultiEdit|StrReplace|str_replace_editor|..."`) into an
|
|
223
|
+
* OpenCode-tool-id alternation (e.g. `"bash"`, `"write|edit"`), deduping
|
|
224
|
+
* repeated targets. A token with no known canonical mapping is kept
|
|
225
|
+
* (lowercased) as a passthrough rather than dropped -- combined with the
|
|
226
|
+
* case-insensitive ANCHORED matching {@link emitToolMethod} generates, this
|
|
227
|
+
* is a safety net that still matches an already-OpenCode-shaped or unknown
|
|
228
|
+
* matcher instead of silently never firing.
|
|
229
|
+
*/
|
|
230
|
+
export function projectMatcherToOpenCode(matcher) {
|
|
231
|
+
const tokens = matcher
|
|
232
|
+
.split("|")
|
|
233
|
+
.map((t) => t.trim())
|
|
234
|
+
.filter(Boolean);
|
|
235
|
+
const projected = [];
|
|
236
|
+
for (const token of tokens) {
|
|
237
|
+
const key = token.toLowerCase().replace(/[^a-z0-9_]/g, "");
|
|
238
|
+
const mapped = CANONICAL_TO_OPENCODE_TOOL[key] ?? token.toLowerCase();
|
|
239
|
+
if (!projected.includes(mapped))
|
|
240
|
+
projected.push(mapped);
|
|
241
|
+
}
|
|
242
|
+
return projected.join("|");
|
|
243
|
+
}
|
|
244
|
+
function asCanonicalHooksDoc(canonicalHooks) {
|
|
245
|
+
if (!canonicalHooks || typeof canonicalHooks !== "object")
|
|
246
|
+
return {};
|
|
247
|
+
const doc = canonicalHooks;
|
|
248
|
+
return doc.hooks && typeof doc.hooks === "object" && !Array.isArray(doc.hooks) ? doc.hooks : {};
|
|
249
|
+
}
|
|
250
|
+
function flattenCanonicalEvent(entries, fallbackFor) {
|
|
251
|
+
if (!Array.isArray(entries))
|
|
252
|
+
return [];
|
|
253
|
+
const flat = [];
|
|
254
|
+
for (const entry of entries) {
|
|
255
|
+
const matcher = typeof entry.matcher === "string" && entry.matcher.trim() ? entry.matcher : undefined;
|
|
256
|
+
for (const inner of entry.hooks ?? []) {
|
|
257
|
+
const command = typeof inner.command === "string" ? inner.command : undefined;
|
|
258
|
+
if (!command)
|
|
259
|
+
continue;
|
|
260
|
+
const flatCommand = { command: withHostFlag(command, "opencode") };
|
|
261
|
+
if (matcher)
|
|
262
|
+
flatCommand.matcher = projectMatcherToOpenCode(matcher);
|
|
263
|
+
if (typeof inner.timeout === "number" && Number.isFinite(inner.timeout)) {
|
|
264
|
+
flatCommand.timeoutMs = Math.round(inner.timeout * 1000);
|
|
265
|
+
}
|
|
266
|
+
if (fallbackFor)
|
|
267
|
+
flatCommand.fallbackFor = fallbackFor;
|
|
268
|
+
flat.push(flatCommand);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return flat;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Return canonical hook events that declare active commands but have no
|
|
275
|
+
* documented OpenCode equivalent in {@link OPENCODE_HOOK_EVENT_MAP} AND no
|
|
276
|
+
* entry in {@link OPENCODE_HOOK_EVENT_FALLBACK} (a fallback-projected event
|
|
277
|
+
* is not "unmapped" — see {@link fallbackOpenCodeHookEvents}).
|
|
278
|
+
*/
|
|
279
|
+
export function unmappedOpenCodeHookEvents(canonicalHooks) {
|
|
280
|
+
const sourceHooks = asCanonicalHooksDoc(canonicalHooks);
|
|
281
|
+
const unmapped = [];
|
|
282
|
+
for (const [event, entries] of Object.entries(sourceHooks)) {
|
|
283
|
+
if (OPENCODE_HOOK_EVENT_MAP[event])
|
|
284
|
+
continue;
|
|
285
|
+
if (OPENCODE_HOOK_EVENT_FALLBACK[event])
|
|
286
|
+
continue;
|
|
287
|
+
if (flattenCanonicalEvent(entries).length > 0)
|
|
288
|
+
unmapped.push(event);
|
|
289
|
+
}
|
|
290
|
+
return unmapped;
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Return the canonical hook events projected via
|
|
294
|
+
* {@link OPENCODE_HOOK_EVENT_FALLBACK} that declare active commands — e.g.
|
|
295
|
+
* `[{from:"SessionEnd", to:"SessionIdle"}]`. These are NOT reported by
|
|
296
|
+
* {@link unmappedOpenCodeHookEvents}: they run, just on a substitute event.
|
|
297
|
+
*/
|
|
298
|
+
export function fallbackOpenCodeHookEvents(canonicalHooks) {
|
|
299
|
+
const sourceHooks = asCanonicalHooksDoc(canonicalHooks);
|
|
300
|
+
const fallbacks = [];
|
|
301
|
+
for (const [from, to] of Object.entries(OPENCODE_HOOK_EVENT_FALLBACK)) {
|
|
302
|
+
if (flattenCanonicalEvent(sourceHooks[from]).length > 0)
|
|
303
|
+
fallbacks.push({ from, to });
|
|
304
|
+
}
|
|
305
|
+
return fallbacks;
|
|
306
|
+
}
|
|
307
|
+
function toIdentifier(pluginName) {
|
|
308
|
+
const parts = pluginName.split(/[^a-zA-Z0-9]+/).filter(Boolean);
|
|
309
|
+
if (parts.length === 0)
|
|
310
|
+
return "plugin";
|
|
311
|
+
const [first, ...rest] = parts;
|
|
312
|
+
return (first.toLowerCase() +
|
|
313
|
+
rest.map((p) => p.charAt(0).toUpperCase() + p.slice(1).toLowerCase()).join(""));
|
|
314
|
+
}
|
|
315
|
+
function emitCommandArray(name, commands) {
|
|
316
|
+
const lines = commands.map((c) => {
|
|
317
|
+
const fields = [`command: ${JSON.stringify(c.command)}`];
|
|
318
|
+
if (c.matcher)
|
|
319
|
+
fields.push(`matcher: ${JSON.stringify(c.matcher)}`);
|
|
320
|
+
if (c.timeoutMs !== undefined)
|
|
321
|
+
fields.push(`timeoutMs: ${c.timeoutMs}`);
|
|
322
|
+
if (c.fallbackFor)
|
|
323
|
+
fields.push(`fallbackFor: ${JSON.stringify(c.fallbackFor)}`);
|
|
324
|
+
return ` { ${fields.join(", ")} },`;
|
|
325
|
+
});
|
|
326
|
+
return `const ${name}: HookCommandSpec[] = [\n${lines.join("\n")}\n];`;
|
|
327
|
+
}
|
|
328
|
+
function emitConfigMethod(hasMcp, hasSkills) {
|
|
329
|
+
const mcpBlock = hasMcp
|
|
330
|
+
? ` input.mcp = input.mcp || {};
|
|
331
|
+
for (const [name, def] of Object.entries(CONFIG_MCP_SERVERS)) {
|
|
332
|
+
if (Object.prototype.hasOwnProperty.call(input.mcp, name)) {
|
|
333
|
+
// OpenCode re-invokes config() on every config reload. If WE added
|
|
334
|
+
// this server on a previous call, seeing it again here is not a
|
|
335
|
+
// real conflict -- do not warn about our own injection. Only a
|
|
336
|
+
// same-named entry this plugin never added is a genuine
|
|
337
|
+
// user-defined conflict worth logging.
|
|
338
|
+
if (!enactInjectedMcpServers.has(name)) {
|
|
339
|
+
console.error("[" + PLUGIN_NAME + "] config: mcp server " + name + " already defined in user config -- skipping");
|
|
340
|
+
}
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
input.mcp[name] = def;
|
|
344
|
+
enactInjectedMcpServers.add(name);
|
|
345
|
+
}`
|
|
346
|
+
: "";
|
|
347
|
+
const skillsBlock = hasSkills
|
|
348
|
+
? ` input.skills = input.skills || {};
|
|
349
|
+
input.skills.paths = Array.isArray(input.skills.paths) ? input.skills.paths : [];
|
|
350
|
+
const skillsDirAbs = join(directory, CONFIG_SKILLS_DIR);
|
|
351
|
+
if (!input.skills.paths.includes(skillsDirAbs)) {
|
|
352
|
+
input.skills.paths.push(skillsDirAbs);
|
|
353
|
+
}`
|
|
354
|
+
: "";
|
|
355
|
+
const body = [mcpBlock, skillsBlock].filter(Boolean).join("\n");
|
|
356
|
+
return ` async config(input: any) {
|
|
357
|
+
${body}
|
|
358
|
+
},`;
|
|
359
|
+
}
|
|
360
|
+
function emitChatMessageMethod(constName) {
|
|
361
|
+
return ` "chat.message": async (input: any, output: any) => {
|
|
362
|
+
const parts = output && Array.isArray(output.parts) ? output.parts : [];
|
|
363
|
+
const promptText = parts.filter((p: any) => p && p.type === "text").map((p: any) => p.text).join(" ");
|
|
364
|
+
let context: string | undefined;
|
|
365
|
+
for (const spec of ${constName}) {
|
|
366
|
+
const payload = {
|
|
367
|
+
hook_event_name: "UserPromptSubmit",
|
|
368
|
+
prompt: promptText,
|
|
369
|
+
cwd: directory,
|
|
370
|
+
session_id: input && input.sessionID,
|
|
371
|
+
};
|
|
372
|
+
const result = await runHookCommand(spec, payload, directory);
|
|
373
|
+
const extracted = extractHookContext(result);
|
|
374
|
+
if (extracted) context = context ? context + " " + extracted : extracted;
|
|
375
|
+
}
|
|
376
|
+
const sessionID = input && input.sessionID;
|
|
377
|
+
if (sessionID) {
|
|
378
|
+
if (context) enactPromptContext.set(sessionID, context);
|
|
379
|
+
else enactPromptContext.delete(sessionID);
|
|
380
|
+
}
|
|
381
|
+
},`;
|
|
382
|
+
}
|
|
383
|
+
function emitChatSystemTransformMethod() {
|
|
384
|
+
return ` "experimental.chat.system.transform": async (input: any, output: any) => {
|
|
385
|
+
const sessionID = input && input.sessionID;
|
|
386
|
+
if (!sessionID) return;
|
|
387
|
+
const context = enactPromptContext.get(sessionID);
|
|
388
|
+
if (context && output && Array.isArray(output.system)) {
|
|
389
|
+
output.system.push(context);
|
|
390
|
+
}
|
|
391
|
+
},`;
|
|
392
|
+
}
|
|
393
|
+
function emitToolMethod(opencodeEvent, constName, canonicalEvent, canBlock) {
|
|
394
|
+
return ` ${JSON.stringify(opencodeEvent)}: async (input: ToolHookInput, output: ToolHookOutput) => {
|
|
395
|
+
for (const spec of ${constName}) {
|
|
396
|
+
if (spec.matcher && !new RegExp("^(?:" + spec.matcher + ")$", "i").test(input.tool)) continue;
|
|
397
|
+
const payload = {
|
|
398
|
+
hook_event_name: ${JSON.stringify(canonicalEvent)},
|
|
399
|
+
tool_name: input.tool,
|
|
400
|
+
tool_input: output.args,
|
|
401
|
+
cwd: directory,
|
|
402
|
+
session_id: input.sessionID,
|
|
403
|
+
};
|
|
404
|
+
const result = await runHookCommand(spec, payload, directory);
|
|
405
|
+
${canBlock ? "const reason = denyReason(result);\n if (reason) throw new Error(reason);" : "// PostToolUse cannot block: the tool call already completed."}
|
|
406
|
+
}
|
|
407
|
+
},`;
|
|
408
|
+
}
|
|
409
|
+
function emitEventMethod(hasCreated, hasIdle, createdConstName, idleConstName) {
|
|
410
|
+
const createdBlock = hasCreated
|
|
411
|
+
? ` if (event && event.type === "session.created") {
|
|
412
|
+
for (const spec of ${createdConstName}) {
|
|
413
|
+
const payload = {
|
|
414
|
+
hook_event_name: "SessionStart",
|
|
415
|
+
cwd: directory,
|
|
416
|
+
session_id: event.properties && (event.properties.sessionID || (event.properties.info && event.properties.info.id)),
|
|
417
|
+
};
|
|
418
|
+
await runHookCommand(spec, payload, directory);
|
|
419
|
+
}
|
|
420
|
+
}`
|
|
421
|
+
: "";
|
|
422
|
+
const idleBlock = hasIdle
|
|
423
|
+
? ` if (event && event.type === "session.idle") {
|
|
424
|
+
for (const spec of ${idleConstName}) {
|
|
425
|
+
const payload = {
|
|
426
|
+
hook_event_name: "SessionIdle",
|
|
427
|
+
cwd: directory,
|
|
428
|
+
session_id: event.properties && (event.properties.sessionID || (event.properties.info && event.properties.info.id)),
|
|
429
|
+
...(spec.fallbackFor ? { fallback_for: spec.fallbackFor } : {}),
|
|
430
|
+
};
|
|
431
|
+
await runHookCommand(spec, payload, directory);
|
|
432
|
+
}
|
|
433
|
+
}`
|
|
434
|
+
: "";
|
|
435
|
+
const body = [createdBlock, idleBlock].filter(Boolean).join("\n");
|
|
436
|
+
return ` event: async ({ event }: { event: any }) => {
|
|
437
|
+
${body}
|
|
438
|
+
},`;
|
|
439
|
+
}
|
|
440
|
+
function emitCompactingMethod(constName) {
|
|
441
|
+
return ` "experimental.session.compacting": async (input: any) => {
|
|
442
|
+
for (const spec of ${constName}) {
|
|
443
|
+
const payload = {
|
|
444
|
+
hook_event_name: "PreCompact",
|
|
445
|
+
cwd: directory,
|
|
446
|
+
session_id: input && input.sessionID,
|
|
447
|
+
};
|
|
448
|
+
await runHookCommand(spec, payload, directory);
|
|
449
|
+
}
|
|
450
|
+
},`;
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Generate the TypeScript source for a SINGLE OpenCode project plugin
|
|
454
|
+
* (`.opencode/plugins/<pluginName>.ts`) that carries a bundle's hooks, MCP
|
|
455
|
+
* servers AND skills together — see the module-level owner-decision comment
|
|
456
|
+
* above for the live-evidence basis of every mapping choice below.
|
|
457
|
+
*
|
|
458
|
+
* Runtime choice: OpenCode plugins run on Bun. This generated file uses
|
|
459
|
+
* `Bun.spawn` rather than the Bun Shell `$` helper because `Bun.spawn` has a
|
|
460
|
+
* documented `timeout` + `killSignal` option
|
|
461
|
+
* (https://bun.com/docs/api/spawn, verified 2026-09-14) needed to honor each
|
|
462
|
+
* canonical hook command's `timeout` (seconds), and gives direct access to
|
|
463
|
+
* `stdin`, `exitCode`, `stdout`/`stderr` text.
|
|
464
|
+
*
|
|
465
|
+
* Truthful failures: a hook command that crashes (e.g. `Bun.spawn` itself
|
|
466
|
+
* throws) or exits non-zero for a reason other than a PreToolUse deny is
|
|
467
|
+
* logged to stderr with the plugin's name — never silently swallowed, and
|
|
468
|
+
* never treated as a block (fail open). The PreToolUse deny throw itself
|
|
469
|
+
* happens OUTSIDE any try/catch in the generated code, so it can never be
|
|
470
|
+
* caught and swallowed by error handling elsewhere in the same method.
|
|
471
|
+
*
|
|
472
|
+
* PreToolUse (`tool.execute.before`) deny contract: the configured command
|
|
473
|
+
* receives `{hook_event_name, tool_name, tool_input, cwd, session_id}` as
|
|
474
|
+
* JSON on stdin. The call is blocked (the generated hook throws) when the
|
|
475
|
+
* command exits with code 2, or its stdout parses as JSON with
|
|
476
|
+
* `hookSpecificOutput.permissionDecision === "deny"`.
|
|
477
|
+
*
|
|
478
|
+
* UserPromptSubmit (`chat.message` + `experimental.chat.system.transform`):
|
|
479
|
+
* the configured command receives `{hook_event_name:"UserPromptSubmit",
|
|
480
|
+
* prompt, cwd, session_id}` as JSON on stdin. Its `hookSpecificOutput.additionalContext`
|
|
481
|
+
* (or, failing that, its raw stdout) is stored keyed by session id and
|
|
482
|
+
* injected into `output.system` the next time `experimental.chat.system.transform`
|
|
483
|
+
* fires for that same session — see the module comment for why this replaced
|
|
484
|
+
* a direct `output.parts` push.
|
|
485
|
+
*
|
|
486
|
+
* Canonical events with no documented OpenCode equivalent and no fallback are
|
|
487
|
+
* NOT wired into any hook; call {@link unmappedOpenCodeHookEvents} to get
|
|
488
|
+
* that list. Events projected via {@link OPENCODE_HOOK_EVENT_FALLBACK} (e.g.
|
|
489
|
+
* SessionEnd -> SessionIdle) ARE wired in, under their fallback target's
|
|
490
|
+
* bucket; call {@link fallbackOpenCodeHookEvents} to get that list.
|
|
491
|
+
*/
|
|
492
|
+
export function deriveOpenCodePlugin(source, pluginName) {
|
|
493
|
+
const sourceHooks = asCanonicalHooksDoc(source?.hooks);
|
|
494
|
+
// Keyed by the OpenCode Hooks method this bucket attaches to (or, for
|
|
495
|
+
// SessionStart/SessionIdle, the synthetic "event:<event.type>" dispatch
|
|
496
|
+
// key), but each entry keeps the ORIGINATING canonical event name too: the
|
|
497
|
+
// JSON payload's `hook_event_name` must stay the canonical PascalCase name
|
|
498
|
+
// (PreToolUse, SessionStart, ...) so a command written against the
|
|
499
|
+
// canonical hook contract (Claude/Codex/Cursor-style) sees the name it
|
|
500
|
+
// expects, not OpenCode's own event naming.
|
|
501
|
+
const byOpenCodeEvent = new Map();
|
|
502
|
+
for (const [canonicalEvent, opencodeEvent] of Object.entries(OPENCODE_HOOK_EVENT_MAP)) {
|
|
503
|
+
const flat = flattenCanonicalEvent(sourceHooks[canonicalEvent]);
|
|
504
|
+
if (flat.length > 0)
|
|
505
|
+
byOpenCodeEvent.set(opencodeEvent, { canonicalEvent, commands: flat });
|
|
506
|
+
}
|
|
507
|
+
// Fold fallback-projected events (OPENCODE_HOOK_EVENT_FALLBACK) into their
|
|
508
|
+
// target's bucket, AFTER any native commands already collected above, so
|
|
509
|
+
// e.g. SessionEnd commands run after native SessionIdle commands under the
|
|
510
|
+
// same "event:session.idle" bucket.
|
|
511
|
+
for (const [fallbackEvent, targetCanonicalEvent] of Object.entries(OPENCODE_HOOK_EVENT_FALLBACK)) {
|
|
512
|
+
const opencodeEvent = OPENCODE_HOOK_EVENT_MAP[targetCanonicalEvent];
|
|
513
|
+
if (!opencodeEvent)
|
|
514
|
+
continue; // defensive: fallback target must itself be a mapped event
|
|
515
|
+
const flat = flattenCanonicalEvent(sourceHooks[fallbackEvent], fallbackEvent);
|
|
516
|
+
if (flat.length === 0)
|
|
517
|
+
continue;
|
|
518
|
+
const existing = byOpenCodeEvent.get(opencodeEvent);
|
|
519
|
+
if (existing) {
|
|
520
|
+
existing.commands = [...existing.commands, ...flat];
|
|
521
|
+
}
|
|
522
|
+
else {
|
|
523
|
+
byOpenCodeEvent.set(opencodeEvent, { canonicalEvent: targetCanonicalEvent, commands: flat });
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
const warnings = unmappedOpenCodeHookEvents(source?.hooks);
|
|
527
|
+
const fallbacks = fallbackOpenCodeHookEvents(source?.hooks);
|
|
528
|
+
const identifier = toIdentifier(pluginName);
|
|
529
|
+
const mcpAdditions = deriveOpenCodeMcp(source?.mcpServers).mcp;
|
|
530
|
+
const hasMcp = Object.keys(mcpAdditions).length > 0;
|
|
531
|
+
const skillsDir = typeof source?.skillsDir === "string" && source.skillsDir.trim() ? source.skillsDir : undefined;
|
|
532
|
+
const hasConfig = hasMcp || Boolean(skillsDir);
|
|
533
|
+
const hasChatMessage = byOpenCodeEvent.has("chat.message");
|
|
534
|
+
const hasToolBefore = byOpenCodeEvent.has("tool.execute.before");
|
|
535
|
+
const hasToolAfter = byOpenCodeEvent.has("tool.execute.after");
|
|
536
|
+
const hasSessionCreated = byOpenCodeEvent.has("event:session.created");
|
|
537
|
+
const hasSessionIdle = byOpenCodeEvent.has("event:session.idle");
|
|
538
|
+
const hasEvent = hasSessionCreated || hasSessionIdle;
|
|
539
|
+
const hasCompacting = byOpenCodeEvent.has("experimental.session.compacting");
|
|
540
|
+
const hasAnyHookExec = hasChatMessage || hasToolBefore || hasToolAfter || hasEvent || hasCompacting;
|
|
541
|
+
const isEmpty = !hasConfig && !hasAnyHookExec;
|
|
542
|
+
const constNameFor = (key) => `HOOKS_${key.toUpperCase().replace(/[^A-Z0-9]+/g, "_")}`;
|
|
543
|
+
const constDecls = [];
|
|
544
|
+
for (const [key, { commands }] of byOpenCodeEvent.entries()) {
|
|
545
|
+
constDecls.push(emitCommandArray(constNameFor(key), commands));
|
|
546
|
+
}
|
|
547
|
+
if (hasMcp) {
|
|
548
|
+
constDecls.push(`const CONFIG_MCP_SERVERS: Record<string, any> = ${JSON.stringify(mcpAdditions, null, 2)};`);
|
|
549
|
+
// Tracks MCP server names THIS plugin instance has injected into
|
|
550
|
+
// input.mcp, across repeated config() calls (OpenCode re-invokes
|
|
551
|
+
// config() on every config reload) -- see emitConfigMethod.
|
|
552
|
+
constDecls.push(`const enactInjectedMcpServers = new Set<string>();`);
|
|
553
|
+
}
|
|
554
|
+
if (skillsDir) {
|
|
555
|
+
constDecls.push(`const CONFIG_SKILLS_DIR = ${JSON.stringify(skillsDir)};`);
|
|
556
|
+
}
|
|
557
|
+
const methods = [];
|
|
558
|
+
if (hasConfig)
|
|
559
|
+
methods.push(emitConfigMethod(hasMcp, Boolean(skillsDir)));
|
|
560
|
+
if (hasChatMessage) {
|
|
561
|
+
methods.push(emitChatMessageMethod(constNameFor("chat.message")));
|
|
562
|
+
methods.push(emitChatSystemTransformMethod());
|
|
563
|
+
}
|
|
564
|
+
if (hasToolBefore) {
|
|
565
|
+
methods.push(emitToolMethod("tool.execute.before", constNameFor("tool.execute.before"), byOpenCodeEvent.get("tool.execute.before").canonicalEvent, true));
|
|
566
|
+
}
|
|
567
|
+
if (hasToolAfter) {
|
|
568
|
+
methods.push(emitToolMethod("tool.execute.after", constNameFor("tool.execute.after"), byOpenCodeEvent.get("tool.execute.after").canonicalEvent, false));
|
|
569
|
+
}
|
|
570
|
+
if (hasEvent) {
|
|
571
|
+
methods.push(emitEventMethod(hasSessionCreated, hasSessionIdle, constNameFor("event:session.created"), constNameFor("event:session.idle")));
|
|
572
|
+
}
|
|
573
|
+
if (hasCompacting)
|
|
574
|
+
methods.push(emitCompactingMethod(constNameFor("experimental.session.compacting")));
|
|
575
|
+
const warningsComment = warnings.length > 0
|
|
576
|
+
? `//\n// Unmapped canonical events with active commands (no documented OpenCode\n// equivalent — see OPENCODE_HOOK_EVENT_MAP in src/create/opencode.ts):\n${warnings.map((w) => `// - ${w}`).join("\n")}\n`
|
|
577
|
+
: "";
|
|
578
|
+
const fallbackComment = fallbacks.length > 0
|
|
579
|
+
? `//\n// Projected via fallback (owner rule: an event with no documented OpenCode\n// equivalent runs on a substitute event instead — see\n// OPENCODE_HOOK_EVENT_FALLBACK in src/create/opencode.ts):\n${fallbacks.map((f) => `// - ${f.from} -> ${f.to}`).join("\n")}\n`
|
|
580
|
+
: "";
|
|
581
|
+
// `join` is only actually referenced by the skills.paths block, not by the
|
|
582
|
+
// MCP block, so import it only when a skills dir was provided.
|
|
583
|
+
const importsBlock = skillsDir ? `import { join } from "node:path";\n\n` : "";
|
|
584
|
+
// PLUGIN_NAME is referenced both by config()'s same-named-server skip log
|
|
585
|
+
// and by runHookCommand's truthful-failure logging -- emit it whenever
|
|
586
|
+
// EITHER needs it, not only when hooks execute (a config-only plugin, with
|
|
587
|
+
// MCP servers but no hooks, still needs it for the skip log).
|
|
588
|
+
const needsPluginName = hasMcp || hasAnyHookExec;
|
|
589
|
+
const pluginNameConst = needsPluginName ? `const PLUGIN_NAME = ${JSON.stringify(pluginName)};\n\n` : "";
|
|
590
|
+
const sharedHelpers = hasAnyHookExec
|
|
591
|
+
? `async function runHookCommand(
|
|
592
|
+
spec: HookCommandSpec,
|
|
593
|
+
payload: Record<string, unknown>,
|
|
594
|
+
cwd: string,
|
|
595
|
+
): Promise<{ exitCode: number | null; stdout: string; stderr: string }> {
|
|
596
|
+
try {
|
|
597
|
+
const proc = Bun.spawn(["/bin/sh", "-c", spec.command], {
|
|
598
|
+
cwd,
|
|
599
|
+
stdin: "pipe",
|
|
600
|
+
stdout: "pipe",
|
|
601
|
+
stderr: "pipe",
|
|
602
|
+
...(spec.timeoutMs ? { timeout: spec.timeoutMs, killSignal: "SIGTERM" } : {}),
|
|
603
|
+
});
|
|
604
|
+
proc.stdin.write(JSON.stringify(payload));
|
|
605
|
+
proc.stdin.end();
|
|
606
|
+
const [stdout, stderr] = await Promise.all([
|
|
607
|
+
new Response(proc.stdout).text(),
|
|
608
|
+
new Response(proc.stderr).text(),
|
|
609
|
+
]);
|
|
610
|
+
await proc.exited;
|
|
611
|
+
if (proc.exitCode !== 0 && proc.exitCode !== 2) {
|
|
612
|
+
console.error("[" + PLUGIN_NAME + "] hook command exited " + proc.exitCode + ": " + spec.command);
|
|
613
|
+
}
|
|
614
|
+
return { exitCode: proc.exitCode, stdout, stderr };
|
|
615
|
+
} catch (err) {
|
|
616
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
617
|
+
console.error("[" + PLUGIN_NAME + "] hook command crashed: " + spec.command + " -- " + message);
|
|
618
|
+
return { exitCode: null, stdout: "", stderr: message };
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
`
|
|
622
|
+
: "";
|
|
623
|
+
const denyHelper = hasToolBefore
|
|
624
|
+
? `
|
|
625
|
+
function denyReason(result: { exitCode: number | null; stdout: string; stderr: string }): string | undefined {
|
|
626
|
+
if (result.exitCode === 2) {
|
|
627
|
+
return result.stderr.trim() || "PreToolUse hook denied the call (exit code 2)";
|
|
628
|
+
}
|
|
629
|
+
try {
|
|
630
|
+
const parsed = JSON.parse(result.stdout) as {
|
|
631
|
+
hookSpecificOutput?: { permissionDecision?: string; permissionDecisionReason?: string };
|
|
632
|
+
};
|
|
633
|
+
if (parsed?.hookSpecificOutput?.permissionDecision === "deny") {
|
|
634
|
+
return parsed.hookSpecificOutput.permissionDecisionReason || "PreToolUse hook denied the call";
|
|
635
|
+
}
|
|
636
|
+
} catch {
|
|
637
|
+
// stdout was not JSON -- not a deny signal.
|
|
638
|
+
}
|
|
639
|
+
return undefined;
|
|
640
|
+
}
|
|
641
|
+
`
|
|
642
|
+
: "";
|
|
643
|
+
const chatContextHelper = hasChatMessage
|
|
644
|
+
? `
|
|
645
|
+
const enactPromptContext = new Map<string, string>();
|
|
646
|
+
|
|
647
|
+
function extractHookContext(result: { exitCode: number | null; stdout: string; stderr: string }): string | undefined {
|
|
648
|
+
const trimmed = result.stdout.trim();
|
|
649
|
+
if (!trimmed) return undefined;
|
|
650
|
+
try {
|
|
651
|
+
const parsed = JSON.parse(trimmed) as { hookSpecificOutput?: { additionalContext?: string } };
|
|
652
|
+
const additional = parsed?.hookSpecificOutput?.additionalContext;
|
|
653
|
+
if (typeof additional === "string" && additional.trim()) {
|
|
654
|
+
return additional.trim();
|
|
655
|
+
}
|
|
656
|
+
} catch {
|
|
657
|
+
// stdout was not JSON -- treat it as plain-text context.
|
|
658
|
+
}
|
|
659
|
+
return trimmed;
|
|
660
|
+
}
|
|
661
|
+
`
|
|
662
|
+
: "";
|
|
663
|
+
return `// AUTO-GENERATED by enact-extensions (deriveOpenCodePlugin). Do not edit by hand.
|
|
664
|
+
// Source: canonical hooks.json + .mcp.json + skills dir -> ONE OpenCode project plugin.
|
|
665
|
+
${warningsComment}${fallbackComment}
|
|
666
|
+
${importsBlock}interface HookCommandSpec {
|
|
667
|
+
command: string;
|
|
668
|
+
matcher?: string;
|
|
669
|
+
timeoutMs?: number;
|
|
670
|
+
fallbackFor?: string;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
interface ToolHookInput {
|
|
674
|
+
tool: string;
|
|
675
|
+
sessionID?: string;
|
|
676
|
+
callID?: string;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
interface ToolHookOutput {
|
|
680
|
+
args: Record<string, unknown>;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
${constDecls.join("\n\n") || "// No canonical hook event maps to a documented OpenCode hook for this plugin, and no MCP servers or skills dir were provided."}
|
|
684
|
+
|
|
685
|
+
${pluginNameConst}
|
|
686
|
+
${sharedHelpers}${denyHelper}${chatContextHelper}
|
|
687
|
+
export const ${identifier}Plugin = async ({ directory }: { directory: string }) => {
|
|
688
|
+
return {
|
|
689
|
+
${methods.join("\n") || " // No mapped hooks."}
|
|
690
|
+
};
|
|
691
|
+
};
|
|
692
|
+
|
|
693
|
+
export default ${identifier}Plugin;
|
|
694
|
+
`;
|
|
695
|
+
}
|
|
696
|
+
//# sourceMappingURL=opencode.js.map
|