@amsterdamdatalabs/enact-extensions 0.1.42 → 0.1.48
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 +3 -0
- package/dist/create/claude.d.ts.map +1 -1
- package/dist/create/claude.js +1 -1
- package/dist/create/claude.js.map +1 -1
- package/dist/create/codex.d.ts.map +1 -1
- package/dist/create/codex.js +2 -3
- package/dist/create/codex.js.map +1 -1
- package/dist/create/cursor.d.ts.map +1 -1
- package/dist/create/cursor.js +3 -7
- package/dist/create/cursor.js.map +1 -1
- 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 +4 -1
- package/dist/create/index.d.ts.map +1 -1
- package/dist/create/index.js +9 -3
- 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 +86 -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 +689 -0
- package/dist/create/opencode.js.map +1 -0
- package/dist/index.d.ts +14 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -11
- 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 +120 -4
- package/dist/internal/agents.js.map +1 -1
- package/dist/internal/extensions-table.d.ts +87 -0
- package/dist/internal/extensions-table.d.ts.map +1 -0
- package/dist/internal/extensions-table.js +195 -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/io.d.ts.map +1 -1
- package/dist/internal/io.js.map +1 -1
- 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 +124 -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/pick.d.ts.map +1 -1
- package/dist/internal/pick.js.map +1 -1
- package/dist/internal/platform.d.ts.map +1 -1
- package/dist/internal/platform.js +82 -42
- package/dist/internal/platform.js.map +1 -1
- package/dist/internal/schema.d.ts.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 +10 -5
- package/dist/validate/index.d.ts.map +1 -1
- package/dist/validate/index.js +59 -10
- 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 +60 -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 +219 -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 +177 -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 +208 -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 +22 -17
- package/scripts/enact-extensions.mjs +411 -1006
- package/scripts/lib/allowed-plugins.mjs +52 -0
- package/scripts/lib/build-index.mjs +1 -3
- package/scripts/lib/resolve-bundle.mjs +1 -3
- package/scripts/lib/run-repo-doctor.mjs +604 -0
- package/scripts/lib/run-repo-install.mjs +1651 -0
- package/scripts/lib/run-sync.mjs +4 -10
- package/scripts/lib/run-validate.mjs +23 -39
- package/scripts/lib/skill-validator.mjs +1096 -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
|
@@ -1,32 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { resolvePluginRoot } from "./lib/resolve-plugin-root.mjs";
|
|
3
|
-
import { resolveBundlePath } from "./lib/resolve-bundle.mjs";
|
|
4
|
-
import { listBundles } from "./lib/list-bundles.mjs";
|
|
5
|
-
import { buildIndex } from "./lib/build-index.mjs";
|
|
6
|
-
import { runValidate } from "./lib/run-validate.mjs";
|
|
7
|
-
import { runSync } from "./lib/run-sync.mjs";
|
|
8
|
-
import { INSTALL_DRY_RUN_UNSUPPORTED_MESSAGE, runInstall } from "./lib/run-install.mjs";
|
|
9
|
-
import { runUpdate } from "./lib/run-update.mjs";
|
|
10
|
-
import { runPrune } from "./lib/run-prune.mjs";
|
|
11
|
-
import { runUninstall } from "./lib/run-uninstall.mjs";
|
|
12
|
-
import { readLedger } from "./lib/ledger.mjs";
|
|
13
|
-
import { computeOutdated } from "./lib/outdated.mjs";
|
|
14
|
-
import { migrateGlobalArtifacts } from "./lib/migrate-artifacts.mjs";
|
|
15
|
-
import { startServer, resolveServePort } from "./lib/serve.mjs";
|
|
16
|
-
import {
|
|
17
|
-
setupPrinciples,
|
|
18
|
-
removePrinciples,
|
|
19
|
-
checkPrinciples,
|
|
20
|
-
runDoctor,
|
|
21
|
-
SUPPORTED_PRINCIPLES_SURFACES,
|
|
22
|
-
} from "./lib/principles.mjs";
|
|
23
|
-
import { dirname, join, resolve } from "node:path";
|
|
24
2
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
25
|
-
import {
|
|
3
|
+
import { dirname, join, resolve } from "node:path";
|
|
26
4
|
import { cwd as processCwd } from "node:process";
|
|
27
|
-
import {
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
28
6
|
import { Ajv } from "ajv";
|
|
29
7
|
import addFormatsModule from "ajv-formats";
|
|
8
|
+
import { buildIndex } from "./lib/build-index.mjs";
|
|
9
|
+
import { listBundles } from "./lib/list-bundles.mjs";
|
|
10
|
+
import { resolveBundlePath } from "./lib/resolve-bundle.mjs";
|
|
11
|
+
import { runRepoDoctor } from "./lib/run-repo-doctor.mjs";
|
|
12
|
+
import { runRepoInstall, runRepoUninstall } from "./lib/run-repo-install.mjs";
|
|
13
|
+
import { runSync } from "./lib/run-sync.mjs";
|
|
14
|
+
import { runValidate } from "./lib/run-validate.mjs";
|
|
30
15
|
|
|
31
16
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
32
17
|
const PACKAGE_ROOT = resolve(__dirname, "..");
|
|
@@ -36,57 +21,48 @@ const VERSION = PACKAGE_JSON.version ?? "unknown";
|
|
|
36
21
|
const HELP = `enact-extensions — Enact multi-platform plugin manifests
|
|
37
22
|
Version: ${VERSION}
|
|
38
23
|
|
|
24
|
+
enact-extensions manages REPO-LOCAL agent setup only. It never installs
|
|
25
|
+
anything into host global homes; global agent wiring belongs to enact-vps.
|
|
26
|
+
install/uninstall/doctor only accept plugin names listed in
|
|
27
|
+
bundled-extensions.json, which names the DEFAULT bundles. Any bundle resolvable
|
|
28
|
+
by name or path can be installed or uninstalled.
|
|
29
|
+
|
|
39
30
|
Usage:
|
|
40
31
|
enact-extensions list [dir] List available plugin bundles (default: bundled + cwd/extensions/)
|
|
41
32
|
enact-extensions list [dir] --json Emit machine-readable JSON array
|
|
42
|
-
enact-extensions log Print the install ledger (single global file), newest first
|
|
43
|
-
enact-extensions log --json Emit the raw ledger array as JSON
|
|
44
|
-
enact-extensions outdated Report freshness drift: installed vs canonical source (per plugin+surface)
|
|
45
|
-
enact-extensions outdated --json Emit JSON array [{name, platform, scope, home, status, installedHash, currentHash, version}]
|
|
46
|
-
enact-extensions migrate-artifacts [--dry-run] [--json]
|
|
47
|
-
Rename legacy factory/loop markdown artifacts to YYMMDDHH-<slug>.md
|
|
48
|
-
enact-extensions update <name> Refresh an outdated plugin on every surface it is installed on (ledger-driven)
|
|
49
|
-
enact-extensions update --all Refresh EVERY outdated plugin/surface
|
|
50
|
-
enact-extensions update <name> --dry-run Show what would be refreshed; change nothing
|
|
51
|
-
enact-extensions update --all --dry-run Show every outdated surface that would be refreshed
|
|
52
|
-
enact-extensions prune --platform all Remove ledger-installed plugin surfaces whose local source bundle is gone
|
|
53
|
-
enact-extensions prune --platform shared Remove orphaned shared skill drops (explicit only)
|
|
54
|
-
enact-extensions prune --dry-run Show orphaned surfaces that would be removed
|
|
55
33
|
enact-extensions index [--out <path>] Generate a discovery index of all bundles (generated artifact, never committed)
|
|
56
34
|
enact-extensions index --out - Print the discovery index JSON to stdout
|
|
57
35
|
enact-extensions index --stdout Alias for --out -
|
|
58
36
|
enact-extensions validate [path|name] Validate manifests (default: cwd)
|
|
59
37
|
enact-extensions sync [path|name] Sync host manifests from .agents/plugin.json (default: cwd)
|
|
60
38
|
enact-extensions sync [path|name] --name <id> Create .agents/plugin.json then sync (new plugin)
|
|
61
|
-
enact-extensions install
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
enact-extensions install
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
enact-extensions
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
enact-extensions
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
enact-extensions
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
enact-extensions
|
|
88
|
-
Check operating-principles block drift per surface; --fix applies blocks.
|
|
89
|
-
enact-extensions -v | --version Print version and exit
|
|
39
|
+
enact-extensions install <name> --repo <path> [--host claude,codex,cursor,kimi,opencode] [--force]
|
|
40
|
+
Install a bundle INTO a git repo as committed, relative files
|
|
41
|
+
(per-host project standard; state in .agents/<name>.lock.json)
|
|
42
|
+
enact-extensions install <name> --repo <path> --dry-run Print exactly what install would write/merge, per
|
|
43
|
+
file (action + reason), and exit with the same success/failure
|
|
44
|
+
the real run would have. Touches nothing.
|
|
45
|
+
enact-extensions uninstall <name> --repo <path> [--purge] [--force]
|
|
46
|
+
Remove exactly what the repo lock records (--purge also removes
|
|
47
|
+
the [extensions] block install wrote to enact-config.toml, and the
|
|
48
|
+
file itself if install created it and only version = 1 remains)
|
|
49
|
+
enact-extensions uninstall <name> --repo <path> --dry-run [--purge]
|
|
50
|
+
Print exactly what uninstall would remove/restore, per file
|
|
51
|
+
(action + reason), and exit with the same success/failure the
|
|
52
|
+
real run would have. Touches nothing.
|
|
53
|
+
enact-extensions doctor enact-repo --repo <path> [--json]
|
|
54
|
+
Read-only health check for a repo-local enact-repo install:
|
|
55
|
+
installed?, version vs bundle (outdated?), lock integrity
|
|
56
|
+
(missing/drifted managed files), per-host status (claude,
|
|
57
|
+
codex incl. trust_level, cursor, kimi incl. workspace-trust,
|
|
58
|
+
opencode), required global binaries on PATH, the
|
|
59
|
+
enact-config.toml marker ([extensions] present; a stale
|
|
60
|
+
.agents/enact-repo.toml is reported), an "enact-hook doctor
|
|
61
|
+
--repo" passthrough when available, and the enact-hook
|
|
62
|
+
deny/activity log paths, existence, row counts, and (deny
|
|
63
|
+
log) the last 5 rows. Never writes anything; exits non-zero
|
|
64
|
+
only when a hard requirement fails.
|
|
65
|
+
enact-extensions -v | --version Print version and exit
|
|
90
66
|
|
|
91
67
|
Options:
|
|
92
68
|
path|name Plugin root path, or a bare plugin name resolved from bundled extensions.
|
|
@@ -94,65 +70,77 @@ Options:
|
|
|
94
70
|
--out <path> (index only) Output file path. Use - or --stdout to print to stdout.
|
|
95
71
|
Default: generated/index.json under the package root.
|
|
96
72
|
--stdout (index only) Alias for --out -.
|
|
97
|
-
--json (list
|
|
98
|
-
--
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
--
|
|
102
|
-
|
|
103
|
-
--
|
|
104
|
-
|
|
105
|
-
--
|
|
106
|
-
|
|
107
|
-
--
|
|
108
|
-
--marketplace <name> Marketplace name (default: enact-os-plugins)
|
|
109
|
-
--no-enable Install files without enabling the Codex/Enact plugin
|
|
110
|
-
--skip-sync Install current manifests without regenerating them
|
|
111
|
-
--no-provision Skip auto-provisioning the bundle's MCP-server packages.
|
|
112
|
-
By default, install resolves each declared MCP server
|
|
113
|
-
(.mcp.json) and provisions its package: uvx → uv tool
|
|
114
|
-
install, npx → npm install -g, pipx → pipx install,
|
|
115
|
-
pip/pip3 → pip install. Best-effort; never fails install.
|
|
73
|
+
--json (list/doctor) Emit JSON to stdout instead of human output.
|
|
74
|
+
--name <id> (sync only) Plugin name for a new .agents/plugin.json.
|
|
75
|
+
--repo <path> (install/uninstall/doctor) Target the git repository root at <path>.
|
|
76
|
+
Never writes under $HOME; never writes absolute paths.
|
|
77
|
+
--host <list> (install --repo) Hosts to install for: claude,codex,cursor,kimi,opencode
|
|
78
|
+
(default: every repo host the bundle targets).
|
|
79
|
+
--dry-run (install/uninstall --repo) Print exactly what would change, per file, and
|
|
80
|
+
exit with the same success/failure the real run would have. Writes nothing.
|
|
81
|
+
--force (install/uninstall --repo) Overwrite user-edited managed content and take over
|
|
82
|
+
same-named entries not owned by the bundle. Never overwrites a user skill dir.
|
|
83
|
+
--purge (uninstall --repo) Also remove the [extensions] block install wrote to enact-config.toml.
|
|
116
84
|
|
|
117
85
|
Name resolution (bare plugin names):
|
|
118
86
|
When a bare name (no "/" in it) is given, it is resolved in this order:
|
|
119
|
-
1. <this-package-root>/extensions/<name> (bundled extensions in this
|
|
87
|
+
1. <this-package-root>/extensions/<name> (bundled extensions in this package)
|
|
120
88
|
2. <cwd>/extensions/<name> (extensions in a sibling product repo)
|
|
121
89
|
3. <npm-global-root>/@amsterdamdatalabs/enact-extensions/extensions/<name>
|
|
122
90
|
|
|
123
|
-
Multi-platform notes:
|
|
124
|
-
- Platforms are installed sequentially in deterministic order: codex, claude, cursor, enact.
|
|
125
|
-
- Per-platform --<platform>-home flags apply to their respective platform in a multi-target run.
|
|
126
|
-
- If any platform fails, the others still proceed; a non-zero exit is returned and the summary
|
|
127
|
-
of succeeded/failed platforms is printed to stderr.
|
|
128
|
-
|
|
129
91
|
Examples:
|
|
130
92
|
enact-extensions list
|
|
131
93
|
enact-extensions list --json
|
|
132
|
-
enact-extensions list /path/to/extensions
|
|
133
|
-
enact-extensions index Generate generated/index.json (gitignored, local discovery artifact)
|
|
134
94
|
enact-extensions index --out - Print discovery index JSON to stdout (pipe-friendly)
|
|
135
|
-
enact-
|
|
136
|
-
enact-extensions index --out /tmp/my-index.json
|
|
137
|
-
cd extensions/enact-factory && enact-extensions validate
|
|
138
|
-
enact-extensions sync . --name my-plugin
|
|
139
|
-
enact-extensions install net-revenue-management --platform enact --global
|
|
140
|
-
enact-extensions install net-revenue-management --platform enact --local
|
|
141
|
-
enact-extensions install extensions/net-revenue-management --platform enact --global
|
|
142
|
-
enact-extensions install enact-factory --platform claude
|
|
143
|
-
enact-extensions install enact-factory --platform cursor
|
|
144
|
-
enact-extensions install net-revenue-management --platform shared
|
|
145
|
-
enact-extensions install net-revenue-management --platform shared --local
|
|
146
|
-
enact-extensions install net-revenue-management --platform all
|
|
147
|
-
enact-extensions install net-revenue-management --platform claude,cursor
|
|
148
|
-
enact-extensions install net-revenue-management --platform all --enact-home /path/to/enact
|
|
95
|
+
cd extensions/enact-repo && enact-extensions validate
|
|
149
96
|
enact-extensions validate extensions/plugin-dev
|
|
150
|
-
enact-extensions
|
|
97
|
+
enact-extensions sync . --name my-plugin
|
|
98
|
+
enact-extensions install enact-repo --repo .
|
|
99
|
+
enact-extensions install enact-repo --repo ~/code/my-service --host claude,cursor
|
|
100
|
+
enact-extensions install enact-repo --repo . --dry-run Preview the plan; writes nothing
|
|
101
|
+
enact-extensions uninstall enact-repo --repo . --purge
|
|
102
|
+
enact-extensions uninstall enact-repo --repo . --dry-run Preview what would be removed/restored
|
|
103
|
+
enact-extensions doctor enact-repo --repo . Read-only health check
|
|
104
|
+
enact-extensions doctor enact-repo --repo . --json
|
|
151
105
|
`;
|
|
152
106
|
|
|
107
|
+
const COMMANDS = new Set(["list", "index", "validate", "sync", "install", "uninstall", "doctor"]);
|
|
108
|
+
const REPO_USAGE_HINT =
|
|
109
|
+
"enact-extensions only performs repo-local installs: install|uninstall <name> --repo <path> " +
|
|
110
|
+
"[--host claude,codex,cursor,kimi,opencode]; doctor enact-repo --repo <path>. " +
|
|
111
|
+
"Global host installs were removed (global agent wiring belongs to enact-vps).";
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Unwinds to the top of the module so node can exit on its own.
|
|
115
|
+
*
|
|
116
|
+
* `exit()` must not be used here: `process.stdout` is ASYNCHRONOUS
|
|
117
|
+
* when it is a pipe -- under a test harness, under CI, or whenever a user
|
|
118
|
+
* pipes output into a file or a pager -- and exiting discards whatever is
|
|
119
|
+
* still queued. `install --repo --dry-run` prints ~1500 lines, and calling
|
|
120
|
+
* exit on the next statement silently cut the tail off on Linux agents while
|
|
121
|
+
* appearing fine on a fast local flush.
|
|
122
|
+
*/
|
|
123
|
+
class ExitSignal extends Error {
|
|
124
|
+
constructor(code) {
|
|
125
|
+
super(`exit ${code}`);
|
|
126
|
+
this.name = "ExitSignal";
|
|
127
|
+
this.code = code;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function exit(code) {
|
|
132
|
+
throw new ExitSignal(code);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function fail(message) {
|
|
136
|
+
console.error(message);
|
|
137
|
+
exit(1);
|
|
138
|
+
}
|
|
139
|
+
|
|
153
140
|
function parseArgs(argv) {
|
|
154
141
|
const positional = [];
|
|
155
142
|
const options = {};
|
|
143
|
+
const unknown = [];
|
|
156
144
|
|
|
157
145
|
for (let i = 0; i < argv.length; i++) {
|
|
158
146
|
const arg = argv[i];
|
|
@@ -162,988 +150,405 @@ function parseArgs(argv) {
|
|
|
162
150
|
options.out = "-";
|
|
163
151
|
} else if (arg === "--name" && argv[i + 1]) {
|
|
164
152
|
options.name = argv[++i];
|
|
165
|
-
} else if (arg === "--
|
|
166
|
-
options.
|
|
167
|
-
} else if (arg === "--
|
|
168
|
-
options.
|
|
169
|
-
} else if (arg === "--
|
|
170
|
-
options.
|
|
171
|
-
} else if (arg === "--
|
|
172
|
-
options.
|
|
173
|
-
} else if (arg === "--no-provision") {
|
|
174
|
-
options.noProvision = true;
|
|
175
|
-
} else if (arg === "--platform" && argv[i + 1]) {
|
|
176
|
-
options.platform = argv[++i];
|
|
177
|
-
} else if (arg === "--claude-home" && argv[i + 1]) {
|
|
178
|
-
options.claudeHome = argv[++i];
|
|
179
|
-
} else if (arg === "--cursor-home" && argv[i + 1]) {
|
|
180
|
-
options.cursorHome = argv[++i];
|
|
181
|
-
} else if (arg === "--enact-home" && argv[i + 1]) {
|
|
182
|
-
options.enactHome = argv[++i];
|
|
183
|
-
} else if (arg === "--shared-home" && argv[i + 1]) {
|
|
184
|
-
options.sharedHome = argv[++i];
|
|
185
|
-
} else if (arg === "--local") {
|
|
186
|
-
options.scope = "local";
|
|
187
|
-
} else if (arg === "--global") {
|
|
188
|
-
options.scope = "global";
|
|
189
|
-
} else if (arg === "--all") {
|
|
190
|
-
options.all = true;
|
|
153
|
+
} else if (arg === "--repo" && argv[i + 1]) {
|
|
154
|
+
options.repo = argv[++i];
|
|
155
|
+
} else if (arg === "--host" && argv[i + 1]) {
|
|
156
|
+
options.host = argv[++i];
|
|
157
|
+
} else if (arg === "--force") {
|
|
158
|
+
options.force = true;
|
|
159
|
+
} else if (arg === "--purge") {
|
|
160
|
+
options.purge = true;
|
|
191
161
|
} else if (arg === "--dry-run") {
|
|
192
162
|
options.dryRun = true;
|
|
193
163
|
} else if (arg === "--json") {
|
|
194
164
|
options.json = true;
|
|
195
|
-
} else if (arg === "--port" && argv[i + 1]) {
|
|
196
|
-
options.port = parseInt(argv[++i], 10);
|
|
197
|
-
} else if (arg === "--host" && argv[i + 1]) {
|
|
198
|
-
options.host = argv[++i];
|
|
199
|
-
} else if (arg === "--open") {
|
|
200
|
-
options.open = true;
|
|
201
|
-
} else if (arg === "--prod") {
|
|
202
|
-
options.prod = true;
|
|
203
|
-
} else if (arg === "--surfaces" && argv[i + 1]) {
|
|
204
|
-
// Comma-separated list of surfaces: claude,codex,cursor,enact
|
|
205
|
-
options.surfaces = argv[++i].split(",").map((s) => s.trim()).filter(Boolean);
|
|
206
|
-
} else if (arg === "--remove") {
|
|
207
|
-
options.remove = true;
|
|
208
|
-
} else if (arg === "--fix") {
|
|
209
|
-
options.fix = true;
|
|
210
165
|
} else if (arg === "-h" || arg === "--help") {
|
|
211
166
|
positional.push("help");
|
|
212
|
-
} else if (
|
|
167
|
+
} else if (arg.startsWith("-")) {
|
|
168
|
+
unknown.push(arg);
|
|
169
|
+
} else {
|
|
213
170
|
positional.push(arg);
|
|
214
171
|
}
|
|
215
172
|
}
|
|
216
173
|
|
|
217
|
-
return { command: positional[0], path: positional[1], options };
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
const rawArgv = process.argv.slice(2);
|
|
221
|
-
if (rawArgv.length === 1 && (rawArgv[0] === "-v" || rawArgv[0] === "--version")) {
|
|
222
|
-
console.log(`enact-extensions ${VERSION}`);
|
|
223
|
-
process.exit(0);
|
|
174
|
+
return { command: positional[0], path: positional[1], options, unknown };
|
|
224
175
|
}
|
|
225
176
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
if (
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
}
|
|
177
|
+
try {
|
|
178
|
+
const rawArgv = process.argv.slice(2);
|
|
179
|
+
if (rawArgv.length === 1 && (rawArgv[0] === "-v" || rawArgv[0] === "--version")) {
|
|
180
|
+
console.log(`enact-extensions ${VERSION}`);
|
|
181
|
+
exit(0);
|
|
182
|
+
}
|
|
232
183
|
|
|
233
|
-
|
|
234
|
-
// `hooks` command — register or remove the session-start drift-check hook.
|
|
235
|
-
//
|
|
236
|
-
// Surfaces: claude, codex, cursor, enact
|
|
237
|
-
// Registration is idempotent and reversible.
|
|
238
|
-
// ---------------------------------------------------------------------------
|
|
239
|
-
// ---------------------------------------------------------------------------
|
|
240
|
-
// `principles` command — inject or check operating-principles blocks in host files.
|
|
241
|
-
//
|
|
242
|
-
// Surfaces: claude, codex, cursor, enact
|
|
243
|
-
// ---------------------------------------------------------------------------
|
|
244
|
-
if (command === "principles") {
|
|
245
|
-
const subCommand = path ?? "setup";
|
|
184
|
+
const { command, path, options, unknown } = parseArgs(rawArgv);
|
|
246
185
|
|
|
247
|
-
if (
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
);
|
|
251
|
-
process.exit(1);
|
|
186
|
+
if (!command || command === "help") {
|
|
187
|
+
console.log(HELP);
|
|
188
|
+
exit(command ? 0 : 1);
|
|
252
189
|
}
|
|
253
190
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
let surfaces = [];
|
|
260
|
-
if (options.all) {
|
|
261
|
-
surfaces = [...surfacesList];
|
|
262
|
-
} else if (options.surfaces && options.surfaces.length > 0) {
|
|
263
|
-
const invalid = options.surfaces.filter((s) => !surfacesList.includes(s));
|
|
264
|
-
if (invalid.length > 0) {
|
|
265
|
-
process.stderr.write(
|
|
266
|
-
`[enact-extensions principles] Unknown surface(s): ${invalid.join(", ")}. Valid: ${surfacesList.join(", ")}\n`,
|
|
267
|
-
);
|
|
268
|
-
process.exit(1);
|
|
269
|
-
}
|
|
270
|
-
surfaces = options.surfaces;
|
|
271
|
-
} else if (subCommand === "setup" && process.stdin.isTTY) {
|
|
272
|
-
const { createInterface } = await import("node:readline");
|
|
273
|
-
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
274
|
-
const question = (prompt) => new Promise((resolve) => rl.question(prompt, resolve));
|
|
191
|
+
if (!COMMANDS.has(command)) {
|
|
192
|
+
console.error(`Unknown command: ${command}\n\n${REPO_USAGE_HINT}\nRun enact-extensions --help for usage.`);
|
|
193
|
+
exit(1);
|
|
194
|
+
}
|
|
275
195
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
196
|
+
if (unknown.length > 0) {
|
|
197
|
+
fail(`Unknown option(s) for ${command}: ${unknown.join(", ")}\n${REPO_USAGE_HINT}`);
|
|
198
|
+
}
|
|
279
199
|
|
|
280
|
-
|
|
281
|
-
|
|
200
|
+
if ((command === "install" || command === "uninstall") && !options.repo) {
|
|
201
|
+
fail(`${command} requires --repo <path>.\n${REPO_USAGE_HINT}`);
|
|
202
|
+
}
|
|
282
203
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
.filter(Boolean)
|
|
290
|
-
.map((s) => {
|
|
291
|
-
const idx = parseInt(s, 10);
|
|
292
|
-
if (!isNaN(idx) && idx >= 1 && idx <= surfacesList.length) {
|
|
293
|
-
return surfacesList[idx - 1];
|
|
294
|
-
}
|
|
295
|
-
return s.toLowerCase();
|
|
296
|
-
})
|
|
297
|
-
.filter((s) => surfacesList.includes(s));
|
|
204
|
+
if (
|
|
205
|
+
!["install", "uninstall"].includes(command) &&
|
|
206
|
+
(options.force || options.purge || options.host || options.dryRun)
|
|
207
|
+
) {
|
|
208
|
+
fail("--host/--force/--purge/--dry-run only apply to install|uninstall <name> --repo <path>");
|
|
209
|
+
}
|
|
298
210
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
211
|
+
function printRepoDoctorReport(report) {
|
|
212
|
+
const ok = (b) => (b ? "OK" : "FAIL");
|
|
213
|
+
console.log(`[doctor enact-repo] repo: ${report.repo}`);
|
|
214
|
+
console.log(` installed: ${report.installed ? "yes" : "NO"}`);
|
|
215
|
+
if (!report.installed) {
|
|
216
|
+
for (const p of report.problems) console.error(` problem: ${p}`);
|
|
217
|
+
return;
|
|
303
218
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
`[enact-extensions principles] No surface specified. Run with --surfaces or --all:\n` +
|
|
307
|
-
` enact-extensions principles ${subCommand} --surfaces claude,codex\n` +
|
|
308
|
-
` enact-extensions principles ${subCommand} --all\n`,
|
|
219
|
+
console.log(
|
|
220
|
+
` version: installed=${report.version.installed} bundle=${report.version.bundle ?? "(unknown)"} outdated=${report.version.outdated ? "YES" : "no"}`,
|
|
309
221
|
);
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
claudeHome: options.claudeHome,
|
|
315
|
-
codexHome: options.codexHome,
|
|
316
|
-
cursorHome: options.cursorHome,
|
|
317
|
-
enactHome: options.enactHome,
|
|
318
|
-
local: isLocal,
|
|
319
|
-
cwd,
|
|
320
|
-
};
|
|
321
|
-
|
|
322
|
-
let exitCode = 0;
|
|
323
|
-
|
|
324
|
-
if (subCommand === "check") {
|
|
325
|
-
const rows = [];
|
|
326
|
-
for (const surface of surfaces) {
|
|
327
|
-
try {
|
|
328
|
-
const res = checkPrinciples(surface, principleOpts);
|
|
329
|
-
rows.push(res);
|
|
330
|
-
if (!options.json) {
|
|
331
|
-
process.stdout.write(
|
|
332
|
-
` [principles] ${surface}: ${res.status} → ${res.path}\n`,
|
|
333
|
-
);
|
|
334
|
-
}
|
|
335
|
-
} catch (err) {
|
|
336
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
337
|
-
rows.push({ surface, path: "", status: "error", error: message });
|
|
338
|
-
process.stderr.write(` [principles] ${surface}: error — ${message}\n`);
|
|
339
|
-
}
|
|
222
|
+
if (report.version.contentOutdated.length > 0) {
|
|
223
|
+
console.log(
|
|
224
|
+
` content drifted from current bundle (${report.version.contentOutdated.length}): ${report.version.contentOutdated.join(", ")}`,
|
|
225
|
+
);
|
|
340
226
|
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
227
|
+
if (report.version.note) console.log(` note: ${report.version.note}`);
|
|
228
|
+
|
|
229
|
+
console.log(` lock integrity: ${ok(report.lock.valid)}`);
|
|
230
|
+
if (!report.lock.valid) {
|
|
231
|
+
if (report.lock.missingFiles.length) console.log(` missing: ${report.lock.missingFiles.join(", ")}`);
|
|
232
|
+
if (report.lock.driftedFiles.length) console.log(` drifted: ${report.lock.driftedFiles.join(", ")}`);
|
|
233
|
+
if (report.lock.jsonIssues.length) console.log(` json: ${report.lock.jsonIssues.join(", ")}`);
|
|
234
|
+
if (report.lock.tomlIssues.length) console.log(` toml: ${report.lock.tomlIssues.join(", ")}`);
|
|
344
235
|
}
|
|
345
236
|
|
|
346
|
-
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
? removePrinciples(surface, principleOpts)
|
|
353
|
-
: setupPrinciples(surface, principleOpts);
|
|
354
|
-
|
|
355
|
-
if (res.result === "applied") {
|
|
356
|
-
process.stdout.write(
|
|
357
|
-
` [principles] ${surface}: applied (${res.action}) → ${res.path}\n`,
|
|
358
|
-
);
|
|
359
|
-
} else if (res.result === "already_present") {
|
|
360
|
-
process.stdout.write(
|
|
361
|
-
` [principles] ${surface}: already present (noop) → ${res.path}\n`,
|
|
362
|
-
);
|
|
363
|
-
} else if (res.result === "removed") {
|
|
364
|
-
process.stdout.write(` [principles] ${surface}: removed → ${res.path}\n`);
|
|
365
|
-
} else if (res.result === "not_found") {
|
|
366
|
-
process.stdout.write(
|
|
367
|
-
` [principles] ${surface}: not found (nothing to remove) → ${res.path}\n`,
|
|
237
|
+
for (const [host, info] of Object.entries(report.hosts)) {
|
|
238
|
+
console.log(` host ${host}: targeted=${info.targeted} present=${info.targeted ? ok(info.present) : "n/a"}`);
|
|
239
|
+
if (info.note) console.log(` ${info.note}`);
|
|
240
|
+
if (info.trust) {
|
|
241
|
+
console.log(
|
|
242
|
+
` codex trust_level: ${info.trust.trustLevel ?? "(none)"}${info.trust.note ? ` -- ${info.trust.note}` : ""}`,
|
|
368
243
|
);
|
|
369
244
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
process.exit(exitCode);
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
// ---------------------------------------------------------------------------
|
|
381
|
-
// `doctor` command — check (and optionally fix) operating-principles drift.
|
|
382
|
-
//
|
|
383
|
-
// Surfaces: claude, codex, cursor, enact (defaults to all when omitted)
|
|
384
|
-
// ---------------------------------------------------------------------------
|
|
385
|
-
if (command === "doctor") {
|
|
386
|
-
const isFix = options.fix ?? false;
|
|
387
|
-
const isLocal = options.scope === "local";
|
|
388
|
-
const cwd = processCwd();
|
|
389
|
-
const surfacesList = SUPPORTED_PRINCIPLES_SURFACES;
|
|
390
|
-
|
|
391
|
-
let surfaces = [];
|
|
392
|
-
if (options.all || !options.surfaces || options.surfaces.length === 0) {
|
|
393
|
-
surfaces = [...surfacesList];
|
|
394
|
-
} else {
|
|
395
|
-
const invalid = options.surfaces.filter((s) => !surfacesList.includes(s));
|
|
396
|
-
if (invalid.length > 0) {
|
|
397
|
-
process.stderr.write(
|
|
398
|
-
`[enact-extensions doctor] Unknown surface(s): ${invalid.join(", ")}. Valid: ${surfacesList.join(", ")}\n`,
|
|
399
|
-
);
|
|
400
|
-
process.exit(1);
|
|
401
|
-
}
|
|
402
|
-
surfaces = options.surfaces;
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
const principleOpts = {
|
|
406
|
-
claudeHome: options.claudeHome,
|
|
407
|
-
codexHome: options.codexHome,
|
|
408
|
-
cursorHome: options.cursorHome,
|
|
409
|
-
enactHome: options.enactHome,
|
|
410
|
-
local: isLocal,
|
|
411
|
-
cwd,
|
|
412
|
-
fix: isFix,
|
|
413
|
-
};
|
|
414
|
-
|
|
415
|
-
const { rows, exitCode } = runDoctor(surfaces, principleOpts);
|
|
416
|
-
|
|
417
|
-
if (!options.json) {
|
|
418
|
-
for (const row of rows) {
|
|
419
|
-
if (row.error) {
|
|
420
|
-
process.stderr.write(` [doctor] ${row.surface}: error — ${row.error}\n`);
|
|
421
|
-
continue;
|
|
245
|
+
if (info.globalHooksNote) console.log(` ${info.globalHooksNote}`);
|
|
246
|
+
if (info.workspaceTrust) {
|
|
247
|
+
console.log(
|
|
248
|
+
` kimi workspace trust: ${info.workspaceTrust.trusted ? "TRUSTED" : "NOT TRUSTED"}${info.workspaceTrust.note ? ` -- ${info.workspaceTrust.note}` : ""}`,
|
|
249
|
+
);
|
|
422
250
|
}
|
|
423
|
-
if (
|
|
424
|
-
|
|
425
|
-
? "
|
|
426
|
-
|
|
427
|
-
process.stdout.write(` [doctor] ${row.surface}: ${row.status} — ${note} → ${row.path}\n`);
|
|
428
|
-
} else {
|
|
429
|
-
process.stdout.write(` [doctor] ${row.surface}: ${row.status} → ${row.path}\n`);
|
|
251
|
+
if (host === "opencode" && info.targeted) {
|
|
252
|
+
console.log(
|
|
253
|
+
` generated from current bundle: ${info.generatedFromCurrentBundle === false ? "NO (stale)" : info.generatedFromCurrentBundle === true ? "yes" : "n/a"}`,
|
|
254
|
+
);
|
|
430
255
|
}
|
|
431
256
|
}
|
|
432
|
-
if (!isFix && exitCode !== 0) {
|
|
433
|
-
process.stderr.write(
|
|
434
|
-
`[enact-extensions doctor] Drift detected. Fix with: enact-extensions doctor --fix --all\n`,
|
|
435
|
-
);
|
|
436
|
-
}
|
|
437
|
-
} else {
|
|
438
|
-
console.log(JSON.stringify(rows, null, 2));
|
|
439
|
-
}
|
|
440
257
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
// ---------------------------------------------------------------------------
|
|
445
|
-
// `list` command — enumerate available plugin bundles.
|
|
446
|
-
// ---------------------------------------------------------------------------
|
|
447
|
-
if (command === "list") {
|
|
448
|
-
// The package's own extensions/ dir, resolved relative to this script.
|
|
449
|
-
const PACKAGE_ROOT = resolve(__dirname, "..");
|
|
450
|
-
const packageExtensions = join(PACKAGE_ROOT, "extensions");
|
|
451
|
-
|
|
452
|
-
let roots;
|
|
453
|
-
if (path) {
|
|
454
|
-
// Explicit dir argument → scan only that dir.
|
|
455
|
-
roots = [resolve(processCwd(), path)];
|
|
456
|
-
} else {
|
|
457
|
-
// Default: package-bundled extensions/ + cwd/extensions/ (if it differs).
|
|
458
|
-
roots = [packageExtensions];
|
|
459
|
-
const cwdExtensions = join(processCwd(), "extensions");
|
|
460
|
-
if (resolve(cwdExtensions) !== resolve(packageExtensions) && existsSync(cwdExtensions)) {
|
|
461
|
-
roots.push(cwdExtensions);
|
|
258
|
+
console.log(" binaries:");
|
|
259
|
+
for (const [bin, info] of Object.entries(report.binaries)) {
|
|
260
|
+
console.log(` ${bin}: ${info.found ? `${info.version ?? "(unknown version)"} @ ${info.path}` : "NOT FOUND"}`);
|
|
462
261
|
}
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
const entries = listBundles(roots);
|
|
466
|
-
|
|
467
|
-
if (options.json) {
|
|
468
|
-
console.log(JSON.stringify(entries, null, 2));
|
|
469
|
-
process.exit(0);
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
// Human-readable table.
|
|
473
|
-
const TRUNC = 60;
|
|
474
|
-
function trunc(str, len) {
|
|
475
|
-
if (!str) return "";
|
|
476
|
-
return str.length > len ? str.slice(0, len - 1) + "…" : str;
|
|
477
|
-
}
|
|
478
262
|
|
|
479
|
-
if (entries.length === 0) {
|
|
480
|
-
console.log("No plugin bundles found.");
|
|
481
|
-
process.exit(0);
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
// Header.
|
|
485
|
-
const COL_NAME = 28;
|
|
486
|
-
const COL_VER = 8;
|
|
487
|
-
const COL_CAT = 18;
|
|
488
|
-
const COL_SURF = 22;
|
|
489
|
-
|
|
490
|
-
function padR(str, n) { return String(str ?? "").padEnd(n).slice(0, n); }
|
|
491
|
-
|
|
492
|
-
const hr = "─".repeat(COL_NAME + COL_VER + COL_CAT + COL_SURF + 3 + TRUNC);
|
|
493
|
-
console.log(hr);
|
|
494
|
-
console.log(
|
|
495
|
-
padR("Name", COL_NAME) + " " +
|
|
496
|
-
padR("Ver", COL_VER) + " " +
|
|
497
|
-
padR("Category", COL_CAT) + " " +
|
|
498
|
-
padR("Surfaces", COL_SURF) + " " +
|
|
499
|
-
"Description"
|
|
500
|
-
);
|
|
501
|
-
console.log(hr);
|
|
502
|
-
|
|
503
|
-
for (const e of entries) {
|
|
504
|
-
const surfaces = e.targets.join(", ");
|
|
505
263
|
console.log(
|
|
506
|
-
|
|
507
|
-
padR(e.version, COL_VER) + " " +
|
|
508
|
-
padR(e.category, COL_CAT) + " " +
|
|
509
|
-
padR(surfaces, COL_SURF) + " " +
|
|
510
|
-
trunc(e.description, TRUNC)
|
|
264
|
+
` marker (${report.marker.path}): ${ok(report.marker.valid)}${report.marker.note ? ` -- ${report.marker.note}` : ""}`,
|
|
511
265
|
);
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
console.log(`${entries.length} bundle${entries.length === 1 ? "" : "s"} found.`);
|
|
515
|
-
process.exit(0);
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
// ---------------------------------------------------------------------------
|
|
519
|
-
// `index` command — generate a discovery index of all plugin bundles.
|
|
520
|
-
//
|
|
521
|
-
// The index is a LOCAL GENERATED ARTIFACT (never committed). The generated/
|
|
522
|
-
// directory is gitignored. The schema at spec/index.json is the committed
|
|
523
|
-
// contract. No network, no marketplace, no catalog/ — purely local.
|
|
524
|
-
// ---------------------------------------------------------------------------
|
|
525
|
-
if (command === "index") {
|
|
526
|
-
const PACKAGE_ROOT = resolve(__dirname, "..");
|
|
527
|
-
const packageExtensions = join(PACKAGE_ROOT, "extensions");
|
|
528
|
-
|
|
529
|
-
// Same default roots as `list`.
|
|
530
|
-
const roots = [packageExtensions];
|
|
531
|
-
const cwdExtensions = join(processCwd(), "extensions");
|
|
532
|
-
if (resolve(cwdExtensions) !== resolve(packageExtensions) && existsSync(cwdExtensions)) {
|
|
533
|
-
roots.push(cwdExtensions);
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
// Build the index. The wall-clock timestamp is computed here at the CLI
|
|
537
|
-
// boundary and passed in — buildIndex itself stays pure (never calls Date).
|
|
538
|
-
let index;
|
|
539
|
-
try {
|
|
540
|
-
index = buildIndex(roots, { now: new Date().toISOString(), packageRoot: PACKAGE_ROOT });
|
|
541
|
-
} catch (err) {
|
|
542
|
-
console.error(`[enact-extensions index] Failed to build index: ${err instanceof Error ? err.message : String(err)}`);
|
|
543
|
-
process.exit(1);
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
// Validate against spec/index.json before writing.
|
|
547
|
-
const schemaPath = join(PACKAGE_ROOT, "spec", "index.json");
|
|
548
|
-
let schema;
|
|
549
|
-
try {
|
|
550
|
-
schema = JSON.parse(readFileSync(schemaPath, "utf8"));
|
|
551
|
-
} catch (err) {
|
|
552
|
-
console.error(`[enact-extensions index] Cannot read schema ${schemaPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
553
|
-
process.exit(1);
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
const addFormats = addFormatsModule.default ?? addFormatsModule;
|
|
557
|
-
const ajv = new Ajv({ allErrors: true, strict: false });
|
|
558
|
-
addFormats(ajv);
|
|
559
|
-
const validate = ajv.compile(schema);
|
|
560
|
-
const valid = validate(index);
|
|
561
|
-
if (!valid) {
|
|
562
|
-
const errs = (validate.errors ?? []).map((e) => ` ${e.instancePath || "/"}: ${e.message}`).join("\n");
|
|
563
|
-
console.error(`[enact-extensions index] Generated index failed schema validation:\n${errs}`);
|
|
564
|
-
process.exit(1);
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
const json = JSON.stringify(index, null, 2);
|
|
568
|
-
// --stdout is normalized to "-" during arg parsing, so this single check covers both.
|
|
569
|
-
const toStdout = options.out === "-";
|
|
570
|
-
|
|
571
|
-
if (toStdout) {
|
|
572
|
-
// Write JSON to stdout; summary to stderr (keeps stdout pipe-clean).
|
|
573
|
-
process.stdout.write(json + "\n");
|
|
574
|
-
process.stderr.write(`[enact-extensions index] ${index.count} plugin${index.count === 1 ? "" : "s"} indexed.\n`);
|
|
575
|
-
} else {
|
|
576
|
-
const outPath = options.out
|
|
577
|
-
? resolve(processCwd(), options.out)
|
|
578
|
-
: join(PACKAGE_ROOT, "generated", "index.json");
|
|
579
|
-
|
|
580
|
-
// Ensure parent directory exists.
|
|
581
|
-
const outDir = resolve(outPath, "..");
|
|
582
|
-
mkdirSync(outDir, { recursive: true });
|
|
583
|
-
|
|
584
|
-
writeFileSync(outPath, json + "\n", "utf8");
|
|
585
|
-
process.stderr.write(`[enact-extensions index] Wrote ${index.count} plugin${index.count === 1 ? "" : "s"} to ${outPath}\n`);
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
process.exit(0);
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
// ---------------------------------------------------------------------------
|
|
592
|
-
// `log` command — print the install ledger (single global file), newest first.
|
|
593
|
-
//
|
|
594
|
-
// Human table to stdout (chrome to stderr) or `--json` (raw ledger array).
|
|
595
|
-
// Reading a missing ledger yields an empty list — never an error.
|
|
596
|
-
// ---------------------------------------------------------------------------
|
|
597
|
-
if (command === "log") {
|
|
598
|
-
const entries = readLedger();
|
|
599
|
-
// Most-recent-first.
|
|
600
|
-
const sorted = [...entries].sort((a, b) =>
|
|
601
|
-
String(b.ts ?? "").localeCompare(String(a.ts ?? "")),
|
|
602
|
-
);
|
|
603
|
-
|
|
604
|
-
if (options.json) {
|
|
605
|
-
process.stdout.write(JSON.stringify(sorted, null, 2) + "\n");
|
|
606
|
-
process.exit(0);
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
if (sorted.length === 0) {
|
|
610
|
-
process.stderr.write("No install ledger entries found.\n");
|
|
611
|
-
process.exit(0);
|
|
612
|
-
}
|
|
266
|
+
if (report.staleMarker.present)
|
|
267
|
+
console.log(` stale marker (${report.staleMarker.path}): ${report.staleMarker.note}`);
|
|
613
268
|
|
|
614
|
-
const COL_TS = 24;
|
|
615
|
-
const COL_ACT = 10;
|
|
616
|
-
const COL_NAME = 28;
|
|
617
|
-
const COL_PLAT = 8;
|
|
618
|
-
const COL_SCOPE = 7;
|
|
619
|
-
function padR(str, n) { return String(str ?? "").padEnd(n).slice(0, n); }
|
|
620
|
-
|
|
621
|
-
const hr = "─".repeat(COL_TS + COL_ACT + COL_NAME + COL_PLAT + COL_SCOPE + 4 + 40);
|
|
622
|
-
console.log(hr);
|
|
623
|
-
console.log(
|
|
624
|
-
padR("Timestamp", COL_TS) + " " +
|
|
625
|
-
padR("Action", COL_ACT) + " " +
|
|
626
|
-
padR("Name", COL_NAME) + " " +
|
|
627
|
-
padR("Platform", COL_PLAT) + " " +
|
|
628
|
-
padR("Scope", COL_SCOPE) + " " +
|
|
629
|
-
"Home",
|
|
630
|
-
);
|
|
631
|
-
console.log(hr);
|
|
632
|
-
for (const e of sorted) {
|
|
633
|
-
console.log(
|
|
634
|
-
padR(e.ts, COL_TS) + " " +
|
|
635
|
-
padR(e.action, COL_ACT) + " " +
|
|
636
|
-
padR(e.name, COL_NAME) + " " +
|
|
637
|
-
padR(e.platform, COL_PLAT) + " " +
|
|
638
|
-
padR(e.scope, COL_SCOPE) + " " +
|
|
639
|
-
String(e.home ?? ""),
|
|
640
|
-
);
|
|
641
|
-
}
|
|
642
|
-
console.log(hr);
|
|
643
|
-
process.stderr.write(`${sorted.length} ledger entr${sorted.length === 1 ? "y" : "ies"}.\n`);
|
|
644
|
-
process.exit(0);
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
// ---------------------------------------------------------------------------
|
|
648
|
-
// `outdated` command — report drift between installed plugins and canonical source.
|
|
649
|
-
//
|
|
650
|
-
// Classifies each installed (plugin, platform) surface as:
|
|
651
|
-
// fresh → installed hash matches canonical source hash
|
|
652
|
-
// outdated → hash mismatch (or recorded hash missing), needs re-install
|
|
653
|
-
// orphaned → canonical source does not exist (can't refresh)
|
|
654
|
-
//
|
|
655
|
-
// Exit code: always 0 (it's a report, not a failure gate).
|
|
656
|
-
// Human chrome → stderr; --json stdout is always pure JSON.
|
|
657
|
-
// ---------------------------------------------------------------------------
|
|
658
|
-
if (command === "outdated") {
|
|
659
|
-
let entries;
|
|
660
|
-
try {
|
|
661
|
-
entries = computeOutdated({ cwd: processCwd() });
|
|
662
|
-
} catch (err) {
|
|
663
|
-
process.stderr.write(
|
|
664
|
-
`[enact-extensions outdated] Error: ${err instanceof Error ? err.message : String(err)}\n`,
|
|
665
|
-
);
|
|
666
|
-
process.exit(1);
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
if (options.json) {
|
|
670
|
-
process.stdout.write(JSON.stringify(entries, null, 2) + "\n");
|
|
671
|
-
process.exit(0);
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
// Human-readable table.
|
|
675
|
-
if (entries.length === 0) {
|
|
676
|
-
process.stderr.write("No installed plugins found in the ledger.\n");
|
|
677
|
-
process.exit(0);
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
const COL_NAME = 30;
|
|
681
|
-
const COL_PLAT = 10;
|
|
682
|
-
const COL_SCOPE = 8;
|
|
683
|
-
const COL_VER = 10;
|
|
684
|
-
const COL_STAT = 10;
|
|
685
|
-
|
|
686
|
-
function padR(str, n) { return String(str ?? "").padEnd(n).slice(0, n); }
|
|
687
|
-
|
|
688
|
-
const hr = "─".repeat(COL_NAME + COL_PLAT + COL_SCOPE + COL_VER + COL_STAT + 4 + 8);
|
|
689
|
-
console.log(hr);
|
|
690
|
-
console.log(
|
|
691
|
-
padR("Plugin", COL_NAME) + " " +
|
|
692
|
-
padR("Platform", COL_PLAT) + " " +
|
|
693
|
-
padR("Scope", COL_SCOPE) + " " +
|
|
694
|
-
padR("Version", COL_VER) + " " +
|
|
695
|
-
padR("Status", COL_STAT),
|
|
696
|
-
);
|
|
697
|
-
console.log(hr);
|
|
698
|
-
|
|
699
|
-
for (const e of entries) {
|
|
700
269
|
console.log(
|
|
701
|
-
|
|
702
|
-
padR(e.platform, COL_PLAT) + " " +
|
|
703
|
-
padR(e.scope, COL_SCOPE) + " " +
|
|
704
|
-
padR(e.version, COL_VER) + " " +
|
|
705
|
-
padR(e.status, COL_STAT),
|
|
270
|
+
` enact-hook doctor --repo: ${report.hookDoctor.available ? `exit ${report.hookDoctor.exitCode}` : `not available -- ${report.hookDoctor.note}`}`,
|
|
706
271
|
);
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
process.exit(0);
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
// ---------------------------------------------------------------------------
|
|
714
|
-
// `migrate-artifacts` command — rename legacy global markdown artifacts.
|
|
715
|
-
if (command === "migrate-artifacts") {
|
|
716
|
-
try {
|
|
717
|
-
const report = migrateGlobalArtifacts({ dryRun: Boolean(options.dryRun) });
|
|
718
|
-
if (options.json) {
|
|
719
|
-
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
720
|
-
} else {
|
|
721
|
-
const factoryRenamed = report.factory.flatMap((entry) => entry.renamed);
|
|
722
|
-
const loopRenamed = report.loop.flatMap((entry) => entry.renamed);
|
|
723
|
-
if (factoryRenamed.length === 0 && loopRenamed.length === 0) {
|
|
724
|
-
process.stdout.write("✓ no legacy markdown artifacts to migrate\n");
|
|
272
|
+
if (report.hookDoctor.available && report.hookDoctor.stdout) {
|
|
273
|
+
for (const line of report.hookDoctor.stdout.trim().split("\n")) {
|
|
274
|
+
if (line) console.log(` ${line}`);
|
|
725
275
|
}
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
)
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (report.hookLogs) {
|
|
279
|
+
const { denyLog, activityLog } = report.hookLogs;
|
|
280
|
+
console.log(
|
|
281
|
+
` hook logs: ${denyLog.path} ${denyLog.exists ? `(${denyLog.rowCount} row(s))` : "(not present)"}; ${activityLog.path} ${activityLog.exists ? `(${activityLog.rowCount} row(s))` : "(not present)"}`,
|
|
282
|
+
);
|
|
283
|
+
if (denyLog.lastRows.length > 0) {
|
|
284
|
+
console.log(` last ${denyLog.lastRows.length} deny row(s):`);
|
|
285
|
+
for (const row of denyLog.lastRows) {
|
|
286
|
+
console.log(` ${row.timestamp} ${row.surface} ${row.reason_id} ${row.command} ${row.agent_message}`);
|
|
287
|
+
}
|
|
736
288
|
}
|
|
737
289
|
}
|
|
738
|
-
process.exit(0);
|
|
739
|
-
} catch (err) {
|
|
740
|
-
process.stderr.write(
|
|
741
|
-
`[enact-extensions migrate-artifacts] Error: ${err instanceof Error ? err.message : String(err)}\n`,
|
|
742
|
-
);
|
|
743
|
-
process.exit(1);
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
290
|
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
// update --all → refresh every outdated surface
|
|
754
|
-
// update --dry-run→ report what WOULD change; touch nothing
|
|
755
|
-
//
|
|
756
|
-
// Exit code: non-zero ONLY on a real install failure or a missing target (no
|
|
757
|
-
// name + no --all). Orphaned and fresh surfaces are never failures.
|
|
758
|
-
// Human chrome → stderr; the ledger self-updates via runInstall.
|
|
759
|
-
// ---------------------------------------------------------------------------
|
|
760
|
-
if (command === "update") {
|
|
761
|
-
let summary;
|
|
762
|
-
try {
|
|
763
|
-
summary = runUpdate({
|
|
764
|
-
name: path, // positional[1]: a bare plugin name (or undefined)
|
|
765
|
-
all: options.all,
|
|
766
|
-
dryRun: options.dryRun,
|
|
767
|
-
home: homedir(), // single global ledger home
|
|
768
|
-
cwd: processCwd(), // canonical bundle resolution
|
|
769
|
-
});
|
|
770
|
-
} catch (err) {
|
|
771
|
-
process.stderr.write(
|
|
772
|
-
`[enact-extensions update] ${err instanceof Error ? err.message : String(err)}\n`,
|
|
773
|
-
);
|
|
774
|
-
process.exit(1);
|
|
291
|
+
if (report.problems.length > 0) {
|
|
292
|
+
console.error(`[doctor enact-repo] ${report.problems.length} problem(s):`);
|
|
293
|
+
for (const p of report.problems) console.error(` - ${p}`);
|
|
294
|
+
} else {
|
|
295
|
+
console.log("[doctor enact-repo] all hard requirements OK");
|
|
296
|
+
}
|
|
775
297
|
}
|
|
776
298
|
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
299
|
+
// ---------------------------------------------------------------------------
|
|
300
|
+
// `doctor <plugin> --repo <path>` — read-only repo-local health check.
|
|
301
|
+
// Any plugin, bundled or not: bundled-extensions.json is the DEFAULT set, not
|
|
302
|
+
// an allow-list. `<plugin>` is a bundled name or an explicit path, resolved
|
|
303
|
+
// exactly like install/uninstall.
|
|
304
|
+
// ---------------------------------------------------------------------------
|
|
305
|
+
if (command === "doctor") {
|
|
306
|
+
if (!path || !options.repo) {
|
|
307
|
+
fail(`doctor requires: doctor <plugin> --repo <path> [--json]\n${REPO_USAGE_HINT}`);
|
|
782
308
|
}
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
309
|
+
let pluginRoot;
|
|
310
|
+
try {
|
|
311
|
+
pluginRoot = resolveBundlePath(path);
|
|
312
|
+
} catch (err) {
|
|
313
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
314
|
+
exit(1);
|
|
787
315
|
}
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
316
|
+
let report;
|
|
317
|
+
try {
|
|
318
|
+
report = runRepoDoctor(pluginRoot, { repo: options.repo });
|
|
319
|
+
} catch (err) {
|
|
320
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
321
|
+
exit(1);
|
|
791
322
|
}
|
|
323
|
+
if (options.json) {
|
|
324
|
+
console.log(JSON.stringify(report, null, 2));
|
|
325
|
+
} else {
|
|
326
|
+
printRepoDoctorReport(report);
|
|
327
|
+
}
|
|
328
|
+
exit(report.exitCode);
|
|
792
329
|
}
|
|
793
330
|
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
const
|
|
801
|
-
process.stderr.write(
|
|
802
|
-
`failed: ${e.name} [${e.platform}] @ ${e.home}: ${f.error.message}\n`,
|
|
803
|
-
);
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
const doneCount = summary.dryRun ? summary.planned.length : summary.updated.length;
|
|
807
|
-
process.stderr.write(
|
|
808
|
-
`${doneCount} ${summary.dryRun ? "would be updated" : "updated"}, ` +
|
|
809
|
-
`${summary.skipped.length} skipped (orphaned), ${summary.failed.length} failed.\n`,
|
|
810
|
-
);
|
|
811
|
-
|
|
812
|
-
// Non-zero exit ONLY on a real install failure.
|
|
813
|
-
process.exit(summary.failed.length > 0 ? 1 : 0);
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
// ---------------------------------------------------------------------------
|
|
817
|
-
// `prune` command — remove orphaned installed surfaces, driven by the ledger.
|
|
818
|
-
//
|
|
819
|
-
// A surface is pruned only when:
|
|
820
|
-
// - the ledger still says it is installed,
|
|
821
|
-
// - it belongs to the requested marketplace,
|
|
822
|
-
// - its platform is in scope, and
|
|
823
|
-
// - no local source bundle exists for that plugin name.
|
|
824
|
-
// ---------------------------------------------------------------------------
|
|
825
|
-
if (command === "prune") {
|
|
826
|
-
let summary;
|
|
827
|
-
try {
|
|
828
|
-
summary = runPrune({
|
|
829
|
-
platform: options.platform ?? "all",
|
|
830
|
-
dryRun: options.dryRun,
|
|
831
|
-
ledgerHome: homedir(),
|
|
832
|
-
cwd: processCwd(),
|
|
833
|
-
marketplaceName: options.marketplaceName,
|
|
834
|
-
});
|
|
835
|
-
} catch (err) {
|
|
836
|
-
process.stderr.write(
|
|
837
|
-
`[enact-extensions prune] ${err instanceof Error ? err.message : String(err)}\n`,
|
|
838
|
-
);
|
|
839
|
-
process.exit(1);
|
|
840
|
-
}
|
|
841
|
-
|
|
842
|
-
if (options.json) {
|
|
843
|
-
process.stdout.write(JSON.stringify(summary, null, 2) + "\n");
|
|
844
|
-
process.exit(summary.failed.length > 0 ? 1 : 0);
|
|
845
|
-
}
|
|
331
|
+
// ---------------------------------------------------------------------------
|
|
332
|
+
// `list` command — enumerate available plugin bundles.
|
|
333
|
+
// ---------------------------------------------------------------------------
|
|
334
|
+
if (command === "list") {
|
|
335
|
+
// The package's own extensions/ dir, resolved relative to this script.
|
|
336
|
+
const PACKAGE_ROOT = resolve(__dirname, "..");
|
|
337
|
+
const packageExtensions = join(PACKAGE_ROOT, "extensions");
|
|
846
338
|
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
}
|
|
860
|
-
process.stderr.write(
|
|
861
|
-
`${rows.length} ${summary.dryRun ? "would be pruned" : "pruned"}, ${summary.failed.length} failed.\n`,
|
|
862
|
-
);
|
|
863
|
-
process.exit(summary.failed.length > 0 ? 1 : 0);
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
// ---------------------------------------------------------------------------
|
|
867
|
-
// `serve` command — localhost API + static-file server (no pluginRoot needed).
|
|
868
|
-
// Handled here (before resolveRoot) because it is async + long-running.
|
|
869
|
-
// ---------------------------------------------------------------------------
|
|
870
|
-
if (command === "serve") {
|
|
871
|
-
const PACKAGE_ROOT = resolve(__dirname, "..");
|
|
872
|
-
const port = resolveServePort(options);
|
|
873
|
-
const host = options.host ?? "127.0.0.1";
|
|
339
|
+
let roots;
|
|
340
|
+
if (path) {
|
|
341
|
+
// Explicit dir argument → scan only that dir.
|
|
342
|
+
roots = [resolve(processCwd(), path)];
|
|
343
|
+
} else {
|
|
344
|
+
// Default: package-bundled extensions/ + cwd/extensions/ (if it differs).
|
|
345
|
+
roots = [packageExtensions];
|
|
346
|
+
const cwdExtensions = join(processCwd(), "extensions");
|
|
347
|
+
if (resolve(cwdExtensions) !== resolve(packageExtensions) && existsSync(cwdExtensions)) {
|
|
348
|
+
roots.push(cwdExtensions);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
874
351
|
|
|
875
|
-
|
|
876
|
-
process.stderr.write(
|
|
877
|
-
`[enact-extensions serve] WARNING: binding to ${host} exposes the API to other machines on the network.\n`,
|
|
878
|
-
);
|
|
879
|
-
}
|
|
352
|
+
const entries = listBundles(roots);
|
|
880
353
|
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
let url;
|
|
885
|
-
try {
|
|
886
|
-
const started = await startServer({
|
|
887
|
-
port,
|
|
888
|
-
host,
|
|
889
|
-
packageRoot: PACKAGE_ROOT,
|
|
890
|
-
installDefaults: { ledgerHome: homedir() },
|
|
891
|
-
});
|
|
892
|
-
serverInstance = started.server;
|
|
893
|
-
url = started.url;
|
|
894
|
-
} catch (err) {
|
|
895
|
-
process.stderr.write(`[enact-extensions serve] Failed to start server: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
896
|
-
process.exit(1);
|
|
354
|
+
if (options.json) {
|
|
355
|
+
console.log(JSON.stringify(entries, null, 2));
|
|
356
|
+
exit(0);
|
|
897
357
|
}
|
|
898
358
|
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
const opener =
|
|
905
|
-
process.platform === "darwin"
|
|
906
|
-
? "open"
|
|
907
|
-
: process.platform === "win32"
|
|
908
|
-
? "start"
|
|
909
|
-
: "xdg-open";
|
|
910
|
-
try {
|
|
911
|
-
spawn(opener, [url], { detached: true, stdio: "ignore" }).unref();
|
|
912
|
-
} catch {
|
|
913
|
-
// xdg-open / open not available in all environments — ignore
|
|
914
|
-
}
|
|
359
|
+
// Human-readable table.
|
|
360
|
+
const TRUNC = 60;
|
|
361
|
+
function trunc(str, len) {
|
|
362
|
+
if (!str) return "";
|
|
363
|
+
return str.length > len ? str.slice(0, len - 1) + "…" : str;
|
|
915
364
|
}
|
|
916
365
|
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
})();
|
|
366
|
+
if (entries.length === 0) {
|
|
367
|
+
console.log("No plugin bundles found.");
|
|
368
|
+
exit(0);
|
|
369
|
+
}
|
|
922
370
|
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
process.exitCode = 0; // signal intent; overridden to 1 on error inside IIFE
|
|
929
|
-
}
|
|
371
|
+
// Header.
|
|
372
|
+
const COL_NAME = 28;
|
|
373
|
+
const COL_VER = 8;
|
|
374
|
+
const COL_CAT = 18;
|
|
375
|
+
const COL_SURF = 22;
|
|
930
376
|
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
// Runs the advisory drift-check and prints valid hook JSON only when plugin
|
|
937
|
-
// surfaces are outdated or auto-updated.
|
|
938
|
-
// enact-extensions hook user-prompt-submit
|
|
939
|
-
// Reads a UserPromptSubmit hook payload from stdin, extracts the prompt,
|
|
940
|
-
// builds the skill catalog from the bundled extensions dir, routes the
|
|
941
|
-
// prompt, and writes the hook response to stdout.
|
|
942
|
-
// Set ENACT_EXTENSIONS_UPS_ROUTER=0 to disable this hook locally without
|
|
943
|
-
// removing the installed plugin.
|
|
944
|
-
//
|
|
945
|
-
// Output contract (Claude Code hooks):
|
|
946
|
-
// Match: { continue: true, hookSpecificOutput: { hookEventName: "UserPromptSubmit", additionalContext: <string> } }
|
|
947
|
-
// No match: { continue: true }
|
|
948
|
-
// Error: { continue: true } (never throws/crashes — degrade gracefully)
|
|
949
|
-
// ---------------------------------------------------------------------------
|
|
950
|
-
if (command === "hook") {
|
|
951
|
-
const subCommand = path; // positional[1]
|
|
377
|
+
function padR(str, n) {
|
|
378
|
+
return String(str ?? "")
|
|
379
|
+
.padEnd(n)
|
|
380
|
+
.slice(0, n);
|
|
381
|
+
}
|
|
952
382
|
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
383
|
+
const hr = "─".repeat(COL_NAME + COL_VER + COL_CAT + COL_SURF + 3 + TRUNC);
|
|
384
|
+
console.log(hr);
|
|
385
|
+
console.log(
|
|
386
|
+
padR("Name", COL_NAME) +
|
|
387
|
+
" " +
|
|
388
|
+
padR("Ver", COL_VER) +
|
|
389
|
+
" " +
|
|
390
|
+
padR("Category", COL_CAT) +
|
|
391
|
+
" " +
|
|
392
|
+
padR("Surfaces", COL_SURF) +
|
|
393
|
+
" " +
|
|
394
|
+
"Description",
|
|
957
395
|
);
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
} catch {
|
|
974
|
-
// Fail-silent for session-start hooks.
|
|
975
|
-
}
|
|
976
|
-
process.exit(0);
|
|
396
|
+
console.log(hr);
|
|
397
|
+
|
|
398
|
+
for (const e of entries) {
|
|
399
|
+
const surfaces = e.targets.join(", ");
|
|
400
|
+
console.log(
|
|
401
|
+
padR(e.name, COL_NAME) +
|
|
402
|
+
" " +
|
|
403
|
+
padR(e.version, COL_VER) +
|
|
404
|
+
" " +
|
|
405
|
+
padR(e.category, COL_CAT) +
|
|
406
|
+
" " +
|
|
407
|
+
padR(surfaces, COL_SURF) +
|
|
408
|
+
" " +
|
|
409
|
+
trunc(e.description, TRUNC),
|
|
410
|
+
);
|
|
977
411
|
}
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
412
|
+
console.log(hr);
|
|
413
|
+
console.log(`${entries.length} bundle${entries.length === 1 ? "" : "s"} found.`);
|
|
414
|
+
exit(0);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// ---------------------------------------------------------------------------
|
|
418
|
+
// `index` command — generate a discovery index of all plugin bundles.
|
|
419
|
+
//
|
|
420
|
+
// The index is a LOCAL GENERATED ARTIFACT (never committed). The generated/
|
|
421
|
+
// directory is gitignored. The schema at spec/index.json is the committed
|
|
422
|
+
// contract. No network, no marketplace, no catalog/ — purely local.
|
|
423
|
+
// ---------------------------------------------------------------------------
|
|
424
|
+
if (command === "index") {
|
|
425
|
+
const PACKAGE_ROOT = resolve(__dirname, "..");
|
|
426
|
+
const packageExtensions = join(PACKAGE_ROOT, "extensions");
|
|
427
|
+
|
|
428
|
+
// Same default roots as `list`.
|
|
429
|
+
const roots = [packageExtensions];
|
|
430
|
+
const cwdExtensions = join(processCwd(), "extensions");
|
|
431
|
+
if (resolve(cwdExtensions) !== resolve(packageExtensions) && existsSync(cwdExtensions)) {
|
|
432
|
+
roots.push(cwdExtensions);
|
|
982
433
|
}
|
|
983
434
|
|
|
984
|
-
//
|
|
985
|
-
|
|
435
|
+
// Build the index. The wall-clock timestamp is computed here at the CLI
|
|
436
|
+
// boundary and passed in — buildIndex itself stays pure (never calls Date).
|
|
437
|
+
let index;
|
|
986
438
|
try {
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
process.stdout.write(JSON.stringify({ continue: true }) + "\n");
|
|
994
|
-
process.exit(0);
|
|
439
|
+
index = buildIndex(roots, { now: new Date().toISOString(), packageRoot: PACKAGE_ROOT });
|
|
440
|
+
} catch (err) {
|
|
441
|
+
console.error(
|
|
442
|
+
`[enact-extensions index] Failed to build index: ${err instanceof Error ? err.message : String(err)}`,
|
|
443
|
+
);
|
|
444
|
+
exit(1);
|
|
995
445
|
}
|
|
996
446
|
|
|
447
|
+
// Validate against spec/index.json before writing.
|
|
448
|
+
const schemaPath = join(PACKAGE_ROOT, "spec", "index.json");
|
|
449
|
+
let schema;
|
|
997
450
|
try {
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
if (!prompt) {
|
|
1006
|
-
process.stdout.write(JSON.stringify({ continue: true }) + "\n");
|
|
1007
|
-
process.exit(0);
|
|
1008
|
-
}
|
|
1009
|
-
|
|
1010
|
-
// Resolve the extensions dir relative to the installed package root so
|
|
1011
|
-
// the hook works whether invoked from the repo or the globally installed package.
|
|
1012
|
-
const { buildSkillCatalog, routePrompt } = await import("./lib/ups-router.mjs");
|
|
1013
|
-
const extensionsDir = join(PACKAGE_ROOT, "extensions");
|
|
1014
|
-
const catalog = buildSkillCatalog(extensionsDir);
|
|
1015
|
-
|
|
1016
|
-
const { additionalContext } = routePrompt(prompt, catalog);
|
|
451
|
+
schema = JSON.parse(readFileSync(schemaPath, "utf8"));
|
|
452
|
+
} catch (err) {
|
|
453
|
+
console.error(
|
|
454
|
+
`[enact-extensions index] Cannot read schema ${schemaPath}: ${err instanceof Error ? err.message : String(err)}`,
|
|
455
|
+
);
|
|
456
|
+
exit(1);
|
|
457
|
+
}
|
|
1017
458
|
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
);
|
|
1028
|
-
} else {
|
|
1029
|
-
process.stdout.write(JSON.stringify({ continue: true }) + "\n");
|
|
1030
|
-
}
|
|
1031
|
-
} catch {
|
|
1032
|
-
// Any unexpected error — safe passthrough, never crash.
|
|
1033
|
-
process.stdout.write(JSON.stringify({ continue: true }) + "\n");
|
|
459
|
+
const addFormats = addFormatsModule.default ?? addFormatsModule;
|
|
460
|
+
const ajv = new Ajv({ allErrors: true, strict: false });
|
|
461
|
+
addFormats(ajv);
|
|
462
|
+
const validate = ajv.compile(schema);
|
|
463
|
+
const valid = validate(index);
|
|
464
|
+
if (!valid) {
|
|
465
|
+
const errs = (validate.errors ?? []).map((e) => ` ${e.instancePath || "/"}: ${e.message}`).join("\n");
|
|
466
|
+
console.error(`[enact-extensions index] Generated index failed schema validation:\n${errs}`);
|
|
467
|
+
exit(1);
|
|
1034
468
|
}
|
|
1035
469
|
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
470
|
+
const json = JSON.stringify(index, null, 2);
|
|
471
|
+
// --stdout is normalized to "-" during arg parsing, so this single check covers both.
|
|
472
|
+
const toStdout = options.out === "-";
|
|
1039
473
|
|
|
1040
|
-
|
|
1041
|
-
//
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
474
|
+
if (toStdout) {
|
|
475
|
+
// Write JSON to stdout; summary to stderr (keeps stdout pipe-clean).
|
|
476
|
+
process.stdout.write(json + "\n");
|
|
477
|
+
process.stderr.write(`[enact-extensions index] ${index.count} plugin${index.count === 1 ? "" : "s"} indexed.\n`);
|
|
478
|
+
} else {
|
|
479
|
+
const outPath = options.out ? resolve(processCwd(), options.out) : join(PACKAGE_ROOT, "generated", "index.json");
|
|
1045
480
|
|
|
1046
|
-
//
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
// bare plugin names, throwing meaningful errors when nothing resolves.
|
|
1050
|
-
const resolveRoot = (pathArg) => {
|
|
1051
|
-
if (!pathArg) return resolvePluginRoot(undefined);
|
|
1052
|
-
return resolveBundlePath(pathArg);
|
|
1053
|
-
};
|
|
481
|
+
// Ensure parent directory exists.
|
|
482
|
+
const outDir = resolve(outPath, "..");
|
|
483
|
+
mkdirSync(outDir, { recursive: true });
|
|
1054
484
|
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
485
|
+
writeFileSync(outPath, json + "\n", "utf8");
|
|
486
|
+
process.stderr.write(
|
|
487
|
+
`[enact-extensions index] Wrote ${index.count} plugin${index.count === 1 ? "" : "s"} to ${outPath}\n`,
|
|
488
|
+
);
|
|
489
|
+
}
|
|
1058
490
|
|
|
1059
|
-
|
|
1060
|
-
try {
|
|
1061
|
-
pluginRoot = resolveRoot(path);
|
|
1062
|
-
} catch (err) {
|
|
1063
|
-
// UNINSTALL-ONLY FALLBACK: uninstall must work even when the source bundle is
|
|
1064
|
-
// gone. If the arg is a BARE NAME (not an explicit path) that did not resolve
|
|
1065
|
-
// to a bundle, fall back to using the arg verbatim as the plugin name. The
|
|
1066
|
-
// uninstall handler reads the name from `path` when pluginRoot is null.
|
|
1067
|
-
// For an explicit path that does not exist, or for any other command, this is
|
|
1068
|
-
// still a hard error.
|
|
1069
|
-
if (command === "uninstall" && isBareName(path)) {
|
|
1070
|
-
pluginRoot = null; // signal: use the raw `path` as the plugin name
|
|
1071
|
-
} else {
|
|
1072
|
-
console.error(err instanceof Error ? err.message : String(err));
|
|
1073
|
-
process.exit(1);
|
|
491
|
+
exit(0);
|
|
1074
492
|
}
|
|
1075
|
-
}
|
|
1076
493
|
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
494
|
+
// ---------------------------------------------------------------------------
|
|
495
|
+
// Commands that resolve a plugin root path: validate, sync, install/uninstall --repo.
|
|
496
|
+
// ---------------------------------------------------------------------------
|
|
497
|
+
let pluginRoot = null;
|
|
498
|
+
try {
|
|
499
|
+
pluginRoot = path ? resolveBundlePath(path) : resolve(processCwd());
|
|
500
|
+
} catch (err) {
|
|
501
|
+
// uninstall --repo must work even when the source bundle is gone: a bare
|
|
502
|
+
// name that does not resolve is used verbatim as the plugin name.
|
|
503
|
+
const isBareName = typeof path === "string" && path.length > 0 && !path.includes("/") && !path.includes("\\");
|
|
504
|
+
if (!(command === "uninstall" && isBareName)) {
|
|
505
|
+
fail(err instanceof Error ? err.message : String(err));
|
|
506
|
+
}
|
|
1081
507
|
}
|
|
1082
508
|
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
509
|
+
function manifestName(root) {
|
|
510
|
+
const manifestPath = root ? join(root, ".agents", "plugin.json") : null;
|
|
511
|
+
return manifestPath && existsSync(manifestPath) ? JSON.parse(readFileSync(manifestPath, "utf8")).name : null;
|
|
1086
512
|
}
|
|
1087
513
|
|
|
1088
|
-
|
|
1089
|
-
if (
|
|
1090
|
-
|
|
1091
|
-
|
|
514
|
+
try {
|
|
515
|
+
if (command === "validate") {
|
|
516
|
+
const ok = runValidate(pluginRoot, undefined, { pluginValidate: true, skillValidate: true });
|
|
517
|
+
exit(ok ? 0 : 1);
|
|
1092
518
|
}
|
|
1093
|
-
// Single global ledger: every install (local or global scope) records to
|
|
1094
|
-
// <homedir>/.enact/extensions/ledger.jsonl so `log` always finds it,
|
|
1095
|
-
// regardless of which per-platform home the bundle was installed to. The
|
|
1096
|
-
// local/global distinction is carried in each entry's `scope` field.
|
|
1097
|
-
runInstall(pluginRoot, { ...options, ledgerHome: homedir() });
|
|
1098
|
-
process.exit(0);
|
|
1099
|
-
}
|
|
1100
519
|
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
// Otherwise (source bundle gone / bare-name fallback), treat the raw
|
|
1105
|
-
// positional arg as the plugin name. This lets uninstall remove already-
|
|
1106
|
-
// installed plugins even when their source bundle has been deleted.
|
|
1107
|
-
let pluginName = null;
|
|
1108
|
-
if (pluginRoot) {
|
|
1109
|
-
try {
|
|
1110
|
-
const enactManifestPath = join(pluginRoot, ".agents", "plugin.json");
|
|
1111
|
-
if (existsSync(enactManifestPath)) {
|
|
1112
|
-
const manifest = JSON.parse(readFileSync(enactManifestPath, "utf8"));
|
|
1113
|
-
pluginName = typeof manifest.name === "string" ? manifest.name : null;
|
|
1114
|
-
}
|
|
1115
|
-
// Fall back to .codex-plugin/plugin.json
|
|
1116
|
-
if (!pluginName) {
|
|
1117
|
-
const codexManifestPath = join(pluginRoot, ".codex-plugin", "plugin.json");
|
|
1118
|
-
if (existsSync(codexManifestPath)) {
|
|
1119
|
-
const manifest = JSON.parse(readFileSync(codexManifestPath, "utf8"));
|
|
1120
|
-
pluginName = typeof manifest.name === "string" ? manifest.name : null;
|
|
1121
|
-
}
|
|
1122
|
-
}
|
|
1123
|
-
} catch {
|
|
1124
|
-
// Source bundle unreadable — fall through to raw name.
|
|
1125
|
-
}
|
|
520
|
+
if (command === "sync") {
|
|
521
|
+
runSync(pluginRoot, { name: options.name });
|
|
522
|
+
exit(0);
|
|
1126
523
|
}
|
|
1127
|
-
|
|
1128
|
-
//
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
524
|
+
|
|
525
|
+
// install | uninstall --repo
|
|
526
|
+
const dryRun = options.dryRun === true;
|
|
527
|
+
const repoPluginName = manifestName(pluginRoot) ?? path;
|
|
528
|
+
if (!repoPluginName) {
|
|
529
|
+
fail(`${command} --repo requires a plugin name`);
|
|
1132
530
|
}
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
531
|
+
const result =
|
|
532
|
+
command === "install"
|
|
533
|
+
? runRepoInstall(pluginRoot, { repo: options.repo, host: options.host, force: options.force, dryRun })
|
|
534
|
+
: runRepoUninstall(repoPluginName, { repo: options.repo, purge: options.purge, force: options.force, dryRun });
|
|
535
|
+
if (dryRun) {
|
|
536
|
+
if (result.actions.length === 0) {
|
|
537
|
+
console.log("[dry-run] no filesystem changes — nothing touched");
|
|
538
|
+
} else {
|
|
539
|
+
for (const a of result.actions) {
|
|
540
|
+
console.log(`[dry-run] would ${a.action}: ${a.file} — ${a.reason}`);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
1136
543
|
}
|
|
1137
|
-
|
|
1138
|
-
|
|
544
|
+
exit(0);
|
|
545
|
+
} catch (err) {
|
|
546
|
+
if (err instanceof ExitSignal) throw err;
|
|
547
|
+
fail(err instanceof Error ? err.message : String(err));
|
|
1139
548
|
}
|
|
1140
|
-
|
|
1141
|
-
console.error(`Unknown command: ${command}\n`);
|
|
1142
|
-
console.log(HELP);
|
|
1143
|
-
process.exit(1);
|
|
1144
549
|
} catch (err) {
|
|
1145
|
-
|
|
1146
|
-
|
|
550
|
+
// The only expected escape: a command asked to finish with a status.
|
|
551
|
+
// Setting exitCode rather than exiting lets node drain stdout first.
|
|
552
|
+
if (!(err instanceof ExitSignal)) throw err;
|
|
553
|
+
process.exitCode = err.code;
|
|
1147
554
|
}
|
|
1148
|
-
|
|
1149
|
-
} // end if (command !== "serve")
|