@specship/specship 0.11.0
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/.claude-plugin/plugin.json +6 -0
- package/LICENSE +21 -0
- package/README.md +583 -0
- package/agents/specship-explorer.md +29 -0
- package/commands/ss-behaviour.md +116 -0
- package/commands/ss-check.md +43 -0
- package/commands/ss-design-implement.md +84 -0
- package/commands/ss-design-loop.md +125 -0
- package/commands/ss-explore.md +43 -0
- package/commands/ss-spec.md +118 -0
- package/dist/activation/starter-prompt.d.ts +57 -0
- package/dist/activation/starter-prompt.d.ts.map +1 -0
- package/dist/activation/starter-prompt.js +164 -0
- package/dist/activation/starter-prompt.js.map +1 -0
- package/dist/analytics/specship-impact.d.ts +72 -0
- package/dist/analytics/specship-impact.d.ts.map +1 -0
- package/dist/analytics/specship-impact.js +216 -0
- package/dist/analytics/specship-impact.js.map +1 -0
- package/dist/behaviour/behaviour-surface.d.ts +59 -0
- package/dist/behaviour/behaviour-surface.d.ts.map +1 -0
- package/dist/behaviour/behaviour-surface.js +112 -0
- package/dist/behaviour/behaviour-surface.js.map +1 -0
- package/dist/bin/node-version-check.d.ts +37 -0
- package/dist/bin/node-version-check.d.ts.map +1 -0
- package/dist/bin/node-version-check.js +79 -0
- package/dist/bin/node-version-check.js.map +1 -0
- package/dist/bin/specship.d.ts +25 -0
- package/dist/bin/specship.d.ts.map +1 -0
- package/dist/bin/specship.js +2823 -0
- package/dist/bin/specship.js.map +1 -0
- package/dist/bin/uninstall.d.ts +13 -0
- package/dist/bin/uninstall.d.ts.map +1 -0
- package/dist/bin/uninstall.js +35 -0
- package/dist/bin/uninstall.js.map +1 -0
- package/dist/context/formatter.d.ts +30 -0
- package/dist/context/formatter.d.ts.map +1 -0
- package/dist/context/formatter.js +263 -0
- package/dist/context/formatter.js.map +1 -0
- package/dist/context/index.d.ts +119 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +1289 -0
- package/dist/context/index.js.map +1 -0
- package/dist/context/markers.d.ts +19 -0
- package/dist/context/markers.d.ts.map +1 -0
- package/dist/context/markers.js +22 -0
- package/dist/context/markers.js.map +1 -0
- package/dist/db/index.d.ts +103 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +279 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/migrations.d.ts +44 -0
- package/dist/db/migrations.d.ts.map +1 -0
- package/dist/db/migrations.js +503 -0
- package/dist/db/migrations.js.map +1 -0
- package/dist/db/queries.d.ts +357 -0
- package/dist/db/queries.d.ts.map +1 -0
- package/dist/db/queries.js +1504 -0
- package/dist/db/queries.js.map +1 -0
- package/dist/db/schema.sql +451 -0
- package/dist/db/spec-queries.d.ts +130 -0
- package/dist/db/spec-queries.d.ts.map +1 -0
- package/dist/db/spec-queries.js +738 -0
- package/dist/db/spec-queries.js.map +1 -0
- package/dist/db/sqlite-adapter.d.ts +65 -0
- package/dist/db/sqlite-adapter.d.ts.map +1 -0
- package/dist/db/sqlite-adapter.js +214 -0
- package/dist/db/sqlite-adapter.js.map +1 -0
- package/dist/designer/artifact-store.js +54 -0
- package/dist/designer/browser.js +141 -0
- package/dist/designer/cdp-ensure.js +60 -0
- package/dist/designer/cdp-env.js +18 -0
- package/dist/designer/cdp-trace.js +599 -0
- package/dist/designer/cross-platform.js +74 -0
- package/dist/designer/designer-controller.js +1413 -0
- package/dist/designer/file-panel.js +39 -0
- package/dist/designer/interstitials.js +97 -0
- package/dist/designer/oopif-reader.js +176 -0
- package/dist/designer/package-meta.js +18 -0
- package/dist/designer/preview-host.js +50 -0
- package/dist/designer/repo-root.js +31 -0
- package/dist/designer/run-state.js +353 -0
- package/dist/designer/session-store.js +59 -0
- package/dist/designer/ui-anchors.js +651 -0
- package/dist/directory.d.ts +67 -0
- package/dist/directory.d.ts.map +1 -0
- package/dist/directory.js +267 -0
- package/dist/directory.js.map +1 -0
- package/dist/enforce/enforce.d.ts +70 -0
- package/dist/enforce/enforce.d.ts.map +1 -0
- package/dist/enforce/enforce.js +125 -0
- package/dist/enforce/enforce.js.map +1 -0
- package/dist/errors.d.ts +136 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +219 -0
- package/dist/errors.js.map +1 -0
- package/dist/extraction/dfm-extractor.d.ts +31 -0
- package/dist/extraction/dfm-extractor.d.ts.map +1 -0
- package/dist/extraction/dfm-extractor.js +151 -0
- package/dist/extraction/dfm-extractor.js.map +1 -0
- package/dist/extraction/generated-detection.d.ts +30 -0
- package/dist/extraction/generated-detection.d.ts.map +1 -0
- package/dist/extraction/generated-detection.js +80 -0
- package/dist/extraction/generated-detection.js.map +1 -0
- package/dist/extraction/grammars.d.ts +100 -0
- package/dist/extraction/grammars.d.ts.map +1 -0
- package/dist/extraction/grammars.js +426 -0
- package/dist/extraction/grammars.js.map +1 -0
- package/dist/extraction/index.d.ts +138 -0
- package/dist/extraction/index.d.ts.map +1 -0
- package/dist/extraction/index.js +1394 -0
- package/dist/extraction/index.js.map +1 -0
- package/dist/extraction/languages/c-cpp.d.ts +4 -0
- package/dist/extraction/languages/c-cpp.d.ts.map +1 -0
- package/dist/extraction/languages/c-cpp.js +171 -0
- package/dist/extraction/languages/c-cpp.js.map +1 -0
- package/dist/extraction/languages/csharp.d.ts +3 -0
- package/dist/extraction/languages/csharp.d.ts.map +1 -0
- package/dist/extraction/languages/csharp.js +73 -0
- package/dist/extraction/languages/csharp.js.map +1 -0
- package/dist/extraction/languages/dart.d.ts +3 -0
- package/dist/extraction/languages/dart.d.ts.map +1 -0
- package/dist/extraction/languages/dart.js +192 -0
- package/dist/extraction/languages/dart.js.map +1 -0
- package/dist/extraction/languages/go.d.ts +3 -0
- package/dist/extraction/languages/go.d.ts.map +1 -0
- package/dist/extraction/languages/go.js +74 -0
- package/dist/extraction/languages/go.js.map +1 -0
- package/dist/extraction/languages/index.d.ts +10 -0
- package/dist/extraction/languages/index.d.ts.map +1 -0
- package/dist/extraction/languages/index.js +51 -0
- package/dist/extraction/languages/index.js.map +1 -0
- package/dist/extraction/languages/java.d.ts +3 -0
- package/dist/extraction/languages/java.d.ts.map +1 -0
- package/dist/extraction/languages/java.js +70 -0
- package/dist/extraction/languages/java.js.map +1 -0
- package/dist/extraction/languages/javascript.d.ts +3 -0
- package/dist/extraction/languages/javascript.d.ts.map +1 -0
- package/dist/extraction/languages/javascript.js +90 -0
- package/dist/extraction/languages/javascript.js.map +1 -0
- package/dist/extraction/languages/kotlin.d.ts +3 -0
- package/dist/extraction/languages/kotlin.d.ts.map +1 -0
- package/dist/extraction/languages/kotlin.js +259 -0
- package/dist/extraction/languages/kotlin.js.map +1 -0
- package/dist/extraction/languages/lua.d.ts +3 -0
- package/dist/extraction/languages/lua.d.ts.map +1 -0
- package/dist/extraction/languages/lua.js +150 -0
- package/dist/extraction/languages/lua.js.map +1 -0
- package/dist/extraction/languages/luau.d.ts +3 -0
- package/dist/extraction/languages/luau.d.ts.map +1 -0
- package/dist/extraction/languages/luau.js +37 -0
- package/dist/extraction/languages/luau.js.map +1 -0
- package/dist/extraction/languages/objc.d.ts +3 -0
- package/dist/extraction/languages/objc.d.ts.map +1 -0
- package/dist/extraction/languages/objc.js +133 -0
- package/dist/extraction/languages/objc.js.map +1 -0
- package/dist/extraction/languages/pascal.d.ts +3 -0
- package/dist/extraction/languages/pascal.d.ts.map +1 -0
- package/dist/extraction/languages/pascal.js +66 -0
- package/dist/extraction/languages/pascal.js.map +1 -0
- package/dist/extraction/languages/php.d.ts +3 -0
- package/dist/extraction/languages/php.d.ts.map +1 -0
- package/dist/extraction/languages/php.js +107 -0
- package/dist/extraction/languages/php.js.map +1 -0
- package/dist/extraction/languages/python.d.ts +3 -0
- package/dist/extraction/languages/python.d.ts.map +1 -0
- package/dist/extraction/languages/python.js +56 -0
- package/dist/extraction/languages/python.js.map +1 -0
- package/dist/extraction/languages/ruby.d.ts +3 -0
- package/dist/extraction/languages/ruby.d.ts.map +1 -0
- package/dist/extraction/languages/ruby.js +114 -0
- package/dist/extraction/languages/ruby.js.map +1 -0
- package/dist/extraction/languages/rust.d.ts +3 -0
- package/dist/extraction/languages/rust.d.ts.map +1 -0
- package/dist/extraction/languages/rust.js +109 -0
- package/dist/extraction/languages/rust.js.map +1 -0
- package/dist/extraction/languages/scala.d.ts +3 -0
- package/dist/extraction/languages/scala.d.ts.map +1 -0
- package/dist/extraction/languages/scala.js +139 -0
- package/dist/extraction/languages/scala.js.map +1 -0
- package/dist/extraction/languages/swift.d.ts +3 -0
- package/dist/extraction/languages/swift.d.ts.map +1 -0
- package/dist/extraction/languages/swift.js +91 -0
- package/dist/extraction/languages/swift.js.map +1 -0
- package/dist/extraction/languages/typescript.d.ts +3 -0
- package/dist/extraction/languages/typescript.d.ts.map +1 -0
- package/dist/extraction/languages/typescript.js +129 -0
- package/dist/extraction/languages/typescript.js.map +1 -0
- package/dist/extraction/liquid-extractor.d.ts +52 -0
- package/dist/extraction/liquid-extractor.d.ts.map +1 -0
- package/dist/extraction/liquid-extractor.js +313 -0
- package/dist/extraction/liquid-extractor.js.map +1 -0
- package/dist/extraction/mybatis-extractor.d.ts +48 -0
- package/dist/extraction/mybatis-extractor.d.ts.map +1 -0
- package/dist/extraction/mybatis-extractor.js +198 -0
- package/dist/extraction/mybatis-extractor.js.map +1 -0
- package/dist/extraction/parse-worker.d.ts +8 -0
- package/dist/extraction/parse-worker.d.ts.map +1 -0
- package/dist/extraction/parse-worker.js +94 -0
- package/dist/extraction/parse-worker.js.map +1 -0
- package/dist/extraction/specs/markdown-spec-extractor.d.ts +114 -0
- package/dist/extraction/specs/markdown-spec-extractor.d.ts.map +1 -0
- package/dist/extraction/specs/markdown-spec-extractor.js +699 -0
- package/dist/extraction/specs/markdown-spec-extractor.js.map +1 -0
- package/dist/extraction/specs/types.d.ts +39 -0
- package/dist/extraction/specs/types.d.ts.map +1 -0
- package/dist/extraction/specs/types.js +8 -0
- package/dist/extraction/specs/types.js.map +1 -0
- package/dist/extraction/svelte-extractor.d.ts +56 -0
- package/dist/extraction/svelte-extractor.d.ts.map +1 -0
- package/dist/extraction/svelte-extractor.js +272 -0
- package/dist/extraction/svelte-extractor.js.map +1 -0
- package/dist/extraction/tree-sitter-helpers.d.ts +28 -0
- package/dist/extraction/tree-sitter-helpers.d.ts.map +1 -0
- package/dist/extraction/tree-sitter-helpers.js +103 -0
- package/dist/extraction/tree-sitter-helpers.js.map +1 -0
- package/dist/extraction/tree-sitter-types.d.ts +193 -0
- package/dist/extraction/tree-sitter-types.d.ts.map +1 -0
- package/dist/extraction/tree-sitter-types.js +10 -0
- package/dist/extraction/tree-sitter-types.js.map +1 -0
- package/dist/extraction/tree-sitter.d.ts +317 -0
- package/dist/extraction/tree-sitter.d.ts.map +1 -0
- package/dist/extraction/tree-sitter.js +3092 -0
- package/dist/extraction/tree-sitter.js.map +1 -0
- package/dist/extraction/vue-extractor.d.ts +51 -0
- package/dist/extraction/vue-extractor.d.ts.map +1 -0
- package/dist/extraction/vue-extractor.js +251 -0
- package/dist/extraction/vue-extractor.js.map +1 -0
- package/dist/extraction/wasm/tree-sitter-lua.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-luau.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-scala.wasm +0 -0
- package/dist/extraction/wasm-runtime-flags.d.ts +38 -0
- package/dist/extraction/wasm-runtime-flags.d.ts.map +1 -0
- package/dist/extraction/wasm-runtime-flags.js +106 -0
- package/dist/extraction/wasm-runtime-flags.js.map +1 -0
- package/dist/fitness/fitness.d.ts +75 -0
- package/dist/fitness/fitness.d.ts.map +1 -0
- package/dist/fitness/fitness.js +204 -0
- package/dist/fitness/fitness.js.map +1 -0
- package/dist/graph/index.d.ts +8 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +13 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph/maintainability.d.ts +115 -0
- package/dist/graph/maintainability.d.ts.map +1 -0
- package/dist/graph/maintainability.js +299 -0
- package/dist/graph/maintainability.js.map +1 -0
- package/dist/graph/queries.d.ts +106 -0
- package/dist/graph/queries.d.ts.map +1 -0
- package/dist/graph/queries.js +366 -0
- package/dist/graph/queries.js.map +1 -0
- package/dist/graph/traversal.d.ts +127 -0
- package/dist/graph/traversal.d.ts.map +1 -0
- package/dist/graph/traversal.js +531 -0
- package/dist/graph/traversal.js.map +1 -0
- package/dist/health/smoke-check.d.ts +85 -0
- package/dist/health/smoke-check.d.ts.map +1 -0
- package/dist/health/smoke-check.js +246 -0
- package/dist/health/smoke-check.js.map +1 -0
- package/dist/index.d.ts +674 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1473 -0
- package/dist/index.js.map +1 -0
- package/dist/installer/config-writer.d.ts +28 -0
- package/dist/installer/config-writer.d.ts.map +1 -0
- package/dist/installer/config-writer.js +91 -0
- package/dist/installer/config-writer.js.map +1 -0
- package/dist/installer/index.d.ts +100 -0
- package/dist/installer/index.d.ts.map +1 -0
- package/dist/installer/index.js +442 -0
- package/dist/installer/index.js.map +1 -0
- package/dist/installer/init-offer.d.ts +31 -0
- package/dist/installer/init-offer.d.ts.map +1 -0
- package/dist/installer/init-offer.js +30 -0
- package/dist/installer/init-offer.js.map +1 -0
- package/dist/installer/instructions-template.d.ts +36 -0
- package/dist/installer/instructions-template.d.ts.map +1 -0
- package/dist/installer/instructions-template.js +57 -0
- package/dist/installer/instructions-template.js.map +1 -0
- package/dist/installer/targets/claude.d.ts +146 -0
- package/dist/installer/targets/claude.d.ts.map +1 -0
- package/dist/installer/targets/claude.js +864 -0
- package/dist/installer/targets/claude.js.map +1 -0
- package/dist/installer/targets/registry.d.ts +19 -0
- package/dist/installer/targets/registry.d.ts.map +1 -0
- package/dist/installer/targets/registry.js +31 -0
- package/dist/installer/targets/registry.js.map +1 -0
- package/dist/installer/targets/shared.d.ts +76 -0
- package/dist/installer/targets/shared.d.ts.map +1 -0
- package/dist/installer/targets/shared.js +260 -0
- package/dist/installer/targets/shared.js.map +1 -0
- package/dist/installer/targets/types.d.ts +95 -0
- package/dist/installer/targets/types.d.ts.map +1 -0
- package/dist/installer/targets/types.js +12 -0
- package/dist/installer/targets/types.js.map +1 -0
- package/dist/isolation/worktree.d.ts +65 -0
- package/dist/isolation/worktree.d.ts.map +1 -0
- package/dist/isolation/worktree.js +231 -0
- package/dist/isolation/worktree.js.map +1 -0
- package/dist/mcp/daemon-paths.d.ts +46 -0
- package/dist/mcp/daemon-paths.d.ts.map +1 -0
- package/dist/mcp/daemon-paths.js +125 -0
- package/dist/mcp/daemon-paths.js.map +1 -0
- package/dist/mcp/daemon.d.ts +161 -0
- package/dist/mcp/daemon.d.ts.map +1 -0
- package/dist/mcp/daemon.js +403 -0
- package/dist/mcp/daemon.js.map +1 -0
- package/dist/mcp/designer-tools.d.ts +33 -0
- package/dist/mcp/designer-tools.d.ts.map +1 -0
- package/dist/mcp/designer-tools.js +313 -0
- package/dist/mcp/designer-tools.js.map +1 -0
- package/dist/mcp/engine.d.ts +105 -0
- package/dist/mcp/engine.d.ts.map +1 -0
- package/dist/mcp/engine.js +270 -0
- package/dist/mcp/engine.js.map +1 -0
- package/dist/mcp/fitness-tool.d.ts +12 -0
- package/dist/mcp/fitness-tool.d.ts.map +1 -0
- package/dist/mcp/fitness-tool.js +46 -0
- package/dist/mcp/fitness-tool.js.map +1 -0
- package/dist/mcp/index.d.ts +112 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +477 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/maintainability-tool.d.ts +13 -0
- package/dist/mcp/maintainability-tool.d.ts.map +1 -0
- package/dist/mcp/maintainability-tool.js +64 -0
- package/dist/mcp/maintainability-tool.js.map +1 -0
- package/dist/mcp/proxy.d.ts +81 -0
- package/dist/mcp/proxy.d.ts.map +1 -0
- package/dist/mcp/proxy.js +510 -0
- package/dist/mcp/proxy.js.map +1 -0
- package/dist/mcp/server-instructions.d.ts +18 -0
- package/dist/mcp/server-instructions.d.ts.map +1 -0
- package/dist/mcp/server-instructions.js +79 -0
- package/dist/mcp/server-instructions.js.map +1 -0
- package/dist/mcp/session.d.ts +77 -0
- package/dist/mcp/session.d.ts.map +1 -0
- package/dist/mcp/session.js +294 -0
- package/dist/mcp/session.js.map +1 -0
- package/dist/mcp/spec-tools.d.ts +39 -0
- package/dist/mcp/spec-tools.d.ts.map +1 -0
- package/dist/mcp/spec-tools.js +534 -0
- package/dist/mcp/spec-tools.js.map +1 -0
- package/dist/mcp/tools.d.ts +417 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +3179 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/mcp/transport.d.ts +188 -0
- package/dist/mcp/transport.d.ts.map +1 -0
- package/dist/mcp/transport.js +343 -0
- package/dist/mcp/transport.js.map +1 -0
- package/dist/mcp/version.d.ts +19 -0
- package/dist/mcp/version.d.ts.map +1 -0
- package/dist/mcp/version.js +71 -0
- package/dist/mcp/version.js.map +1 -0
- package/dist/reflect/apply.d.ts +31 -0
- package/dist/reflect/apply.d.ts.map +1 -0
- package/dist/reflect/apply.js +286 -0
- package/dist/reflect/apply.js.map +1 -0
- package/dist/reflect/hash.d.ts +20 -0
- package/dist/reflect/hash.d.ts.map +1 -0
- package/dist/reflect/hash.js +36 -0
- package/dist/reflect/hash.js.map +1 -0
- package/dist/reflect/index.d.ts +16 -0
- package/dist/reflect/index.d.ts.map +1 -0
- package/dist/reflect/index.js +43 -0
- package/dist/reflect/index.js.map +1 -0
- package/dist/reflect/miner.d.ts +21 -0
- package/dist/reflect/miner.d.ts.map +1 -0
- package/dist/reflect/miner.js +463 -0
- package/dist/reflect/miner.js.map +1 -0
- package/dist/reflect/store.d.ts +31 -0
- package/dist/reflect/store.d.ts.map +1 -0
- package/dist/reflect/store.js +101 -0
- package/dist/reflect/store.js.map +1 -0
- package/dist/reflect/sweep.d.ts +26 -0
- package/dist/reflect/sweep.d.ts.map +1 -0
- package/dist/reflect/sweep.js +42 -0
- package/dist/reflect/sweep.js.map +1 -0
- package/dist/reflect/targets.d.ts +52 -0
- package/dist/reflect/targets.d.ts.map +1 -0
- package/dist/reflect/targets.js +192 -0
- package/dist/reflect/targets.js.map +1 -0
- package/dist/reflect/types.d.ts +96 -0
- package/dist/reflect/types.d.ts.map +1 -0
- package/dist/reflect/types.js +13 -0
- package/dist/reflect/types.js.map +1 -0
- package/dist/resolution/brief-link-resolver.d.ts +114 -0
- package/dist/resolution/brief-link-resolver.d.ts.map +1 -0
- package/dist/resolution/brief-link-resolver.js +261 -0
- package/dist/resolution/brief-link-resolver.js.map +1 -0
- package/dist/resolution/callback-synthesizer.d.ts +10 -0
- package/dist/resolution/callback-synthesizer.d.ts.map +1 -0
- package/dist/resolution/callback-synthesizer.js +1300 -0
- package/dist/resolution/callback-synthesizer.js.map +1 -0
- package/dist/resolution/domain-gap-seed.d.ts +60 -0
- package/dist/resolution/domain-gap-seed.d.ts.map +1 -0
- package/dist/resolution/domain-gap-seed.js +87 -0
- package/dist/resolution/domain-gap-seed.js.map +1 -0
- package/dist/resolution/frameworks/cargo-workspace.d.ts +18 -0
- package/dist/resolution/frameworks/cargo-workspace.d.ts.map +1 -0
- package/dist/resolution/frameworks/cargo-workspace.js +225 -0
- package/dist/resolution/frameworks/cargo-workspace.js.map +1 -0
- package/dist/resolution/frameworks/csharp.d.ts +8 -0
- package/dist/resolution/frameworks/csharp.d.ts.map +1 -0
- package/dist/resolution/frameworks/csharp.js +241 -0
- package/dist/resolution/frameworks/csharp.js.map +1 -0
- package/dist/resolution/frameworks/drupal.d.ts +51 -0
- package/dist/resolution/frameworks/drupal.d.ts.map +1 -0
- package/dist/resolution/frameworks/drupal.js +367 -0
- package/dist/resolution/frameworks/drupal.js.map +1 -0
- package/dist/resolution/frameworks/expo-modules.d.ts +3 -0
- package/dist/resolution/frameworks/expo-modules.d.ts.map +1 -0
- package/dist/resolution/frameworks/expo-modules.js +143 -0
- package/dist/resolution/frameworks/expo-modules.js.map +1 -0
- package/dist/resolution/frameworks/express.d.ts +8 -0
- package/dist/resolution/frameworks/express.d.ts.map +1 -0
- package/dist/resolution/frameworks/express.js +308 -0
- package/dist/resolution/frameworks/express.js.map +1 -0
- package/dist/resolution/frameworks/fabric.d.ts +3 -0
- package/dist/resolution/frameworks/fabric.d.ts.map +1 -0
- package/dist/resolution/frameworks/fabric.js +354 -0
- package/dist/resolution/frameworks/fabric.js.map +1 -0
- package/dist/resolution/frameworks/go.d.ts +8 -0
- package/dist/resolution/frameworks/go.d.ts.map +1 -0
- package/dist/resolution/frameworks/go.js +161 -0
- package/dist/resolution/frameworks/go.js.map +1 -0
- package/dist/resolution/frameworks/index.d.ts +48 -0
- package/dist/resolution/frameworks/index.d.ts.map +1 -0
- package/dist/resolution/frameworks/index.js +161 -0
- package/dist/resolution/frameworks/index.js.map +1 -0
- package/dist/resolution/frameworks/java.d.ts +8 -0
- package/dist/resolution/frameworks/java.d.ts.map +1 -0
- package/dist/resolution/frameworks/java.js +504 -0
- package/dist/resolution/frameworks/java.js.map +1 -0
- package/dist/resolution/frameworks/laravel.d.ts +13 -0
- package/dist/resolution/frameworks/laravel.d.ts.map +1 -0
- package/dist/resolution/frameworks/laravel.js +257 -0
- package/dist/resolution/frameworks/laravel.js.map +1 -0
- package/dist/resolution/frameworks/nestjs.d.ts +26 -0
- package/dist/resolution/frameworks/nestjs.d.ts.map +1 -0
- package/dist/resolution/frameworks/nestjs.js +698 -0
- package/dist/resolution/frameworks/nestjs.js.map +1 -0
- package/dist/resolution/frameworks/play.d.ts +19 -0
- package/dist/resolution/frameworks/play.d.ts.map +1 -0
- package/dist/resolution/frameworks/play.js +111 -0
- package/dist/resolution/frameworks/play.js.map +1 -0
- package/dist/resolution/frameworks/python.d.ts +10 -0
- package/dist/resolution/frameworks/python.d.ts.map +1 -0
- package/dist/resolution/frameworks/python.js +396 -0
- package/dist/resolution/frameworks/python.js.map +1 -0
- package/dist/resolution/frameworks/react-native.d.ts +3 -0
- package/dist/resolution/frameworks/react-native.d.ts.map +1 -0
- package/dist/resolution/frameworks/react-native.js +360 -0
- package/dist/resolution/frameworks/react-native.js.map +1 -0
- package/dist/resolution/frameworks/react.d.ts +8 -0
- package/dist/resolution/frameworks/react.d.ts.map +1 -0
- package/dist/resolution/frameworks/react.js +365 -0
- package/dist/resolution/frameworks/react.js.map +1 -0
- package/dist/resolution/frameworks/ruby.d.ts +8 -0
- package/dist/resolution/frameworks/ruby.d.ts.map +1 -0
- package/dist/resolution/frameworks/ruby.js +302 -0
- package/dist/resolution/frameworks/ruby.js.map +1 -0
- package/dist/resolution/frameworks/rust.d.ts +8 -0
- package/dist/resolution/frameworks/rust.d.ts.map +1 -0
- package/dist/resolution/frameworks/rust.js +304 -0
- package/dist/resolution/frameworks/rust.js.map +1 -0
- package/dist/resolution/frameworks/svelte.d.ts +9 -0
- package/dist/resolution/frameworks/svelte.d.ts.map +1 -0
- package/dist/resolution/frameworks/svelte.js +249 -0
- package/dist/resolution/frameworks/svelte.js.map +1 -0
- package/dist/resolution/frameworks/swift-objc.d.ts +37 -0
- package/dist/resolution/frameworks/swift-objc.d.ts.map +1 -0
- package/dist/resolution/frameworks/swift-objc.js +252 -0
- package/dist/resolution/frameworks/swift-objc.js.map +1 -0
- package/dist/resolution/frameworks/swift.d.ts +10 -0
- package/dist/resolution/frameworks/swift.d.ts.map +1 -0
- package/dist/resolution/frameworks/swift.js +400 -0
- package/dist/resolution/frameworks/swift.js.map +1 -0
- package/dist/resolution/frameworks/vue.d.ts +9 -0
- package/dist/resolution/frameworks/vue.d.ts.map +1 -0
- package/dist/resolution/frameworks/vue.js +306 -0
- package/dist/resolution/frameworks/vue.js.map +1 -0
- package/dist/resolution/go-module.d.ts +26 -0
- package/dist/resolution/go-module.d.ts.map +1 -0
- package/dist/resolution/go-module.js +78 -0
- package/dist/resolution/go-module.js.map +1 -0
- package/dist/resolution/import-resolver.d.ts +68 -0
- package/dist/resolution/import-resolver.d.ts.map +1 -0
- package/dist/resolution/import-resolver.js +1275 -0
- package/dist/resolution/import-resolver.js.map +1 -0
- package/dist/resolution/index.d.ts +117 -0
- package/dist/resolution/index.d.ts.map +1 -0
- package/dist/resolution/index.js +895 -0
- package/dist/resolution/index.js.map +1 -0
- package/dist/resolution/lru-cache.d.ts +24 -0
- package/dist/resolution/lru-cache.d.ts.map +1 -0
- package/dist/resolution/lru-cache.js +62 -0
- package/dist/resolution/lru-cache.js.map +1 -0
- package/dist/resolution/name-matcher.d.ts +32 -0
- package/dist/resolution/name-matcher.d.ts.map +1 -0
- package/dist/resolution/name-matcher.js +596 -0
- package/dist/resolution/name-matcher.js.map +1 -0
- package/dist/resolution/path-aliases.d.ts +68 -0
- package/dist/resolution/path-aliases.d.ts.map +1 -0
- package/dist/resolution/path-aliases.js +238 -0
- package/dist/resolution/path-aliases.js.map +1 -0
- package/dist/resolution/spec-link-resolver.d.ts +148 -0
- package/dist/resolution/spec-link-resolver.d.ts.map +1 -0
- package/dist/resolution/spec-link-resolver.js +337 -0
- package/dist/resolution/spec-link-resolver.js.map +1 -0
- package/dist/resolution/strip-comments.d.ts +27 -0
- package/dist/resolution/strip-comments.d.ts.map +1 -0
- package/dist/resolution/strip-comments.js +441 -0
- package/dist/resolution/strip-comments.js.map +1 -0
- package/dist/resolution/swift-objc-bridge.d.ts +134 -0
- package/dist/resolution/swift-objc-bridge.d.ts.map +1 -0
- package/dist/resolution/swift-objc-bridge.js +256 -0
- package/dist/resolution/swift-objc-bridge.js.map +1 -0
- package/dist/resolution/types.d.ts +216 -0
- package/dist/resolution/types.d.ts.map +1 -0
- package/dist/resolution/types.js +8 -0
- package/dist/resolution/types.js.map +1 -0
- package/dist/resolution/workspace-packages.d.ts +48 -0
- package/dist/resolution/workspace-packages.d.ts.map +1 -0
- package/dist/resolution/workspace-packages.js +208 -0
- package/dist/resolution/workspace-packages.js.map +1 -0
- package/dist/search/query-parser.d.ts +57 -0
- package/dist/search/query-parser.d.ts.map +1 -0
- package/dist/search/query-parser.js +177 -0
- package/dist/search/query-parser.js.map +1 -0
- package/dist/search/query-utils.d.ts +71 -0
- package/dist/search/query-utils.d.ts.map +1 -0
- package/dist/search/query-utils.js +380 -0
- package/dist/search/query-utils.js.map +1 -0
- package/dist/server/cli.js +152 -0
- package/dist/server/index.js +12 -0
- package/dist/server/ingest/impact-backfill.js +69 -0
- package/dist/server/ingest/impact-query.js +343 -0
- package/dist/server/ingest/index.js +19 -0
- package/dist/server/ingest/ingestor.js +541 -0
- package/dist/server/ingest/parser.js +104 -0
- package/dist/server/ingest/pricing.js +78 -0
- package/dist/server/ingest/specship-classify.js +153 -0
- package/dist/server/ingest/types.js +9 -0
- package/dist/server/ingest/watcher.js +77 -0
- package/dist/server/package.json +3 -0
- package/dist/server/project-registry.js +101 -0
- package/dist/server/routes/claude.js +907 -0
- package/dist/server/routes/domain.js +0 -0
- package/dist/server/routes/events.js +134 -0
- package/dist/server/routes/graph.js +248 -0
- package/dist/server/routes/maintainability.js +18 -0
- package/dist/server/routes/memory.js +272 -0
- package/dist/server/routes/projects.js +197 -0
- package/dist/server/routes/reflect.js +93 -0
- package/dist/server/routes/spec.js +373 -0
- package/dist/server/routes/status.js +112 -0
- package/dist/server/routes/workflow.js +253 -0
- package/dist/server/server.js +238 -0
- package/dist/server/static-handler.js +87 -0
- package/dist/statusline/active-run.d.ts +16 -0
- package/dist/statusline/active-run.d.ts.map +1 -0
- package/dist/statusline/active-run.js +73 -0
- package/dist/statusline/active-run.js.map +1 -0
- package/dist/statusline/cache.d.ts +21 -0
- package/dist/statusline/cache.d.ts.map +1 -0
- package/dist/statusline/cache.js +34 -0
- package/dist/statusline/cache.js.map +1 -0
- package/dist/statusline/index.d.ts +24 -0
- package/dist/statusline/index.d.ts.map +1 -0
- package/dist/statusline/index.js +128 -0
- package/dist/statusline/index.js.map +1 -0
- package/dist/statusline/paths.d.ts +27 -0
- package/dist/statusline/paths.d.ts.map +1 -0
- package/dist/statusline/paths.js +101 -0
- package/dist/statusline/paths.js.map +1 -0
- package/dist/statusline/render.d.ts +25 -0
- package/dist/statusline/render.d.ts.map +1 -0
- package/dist/statusline/render.js +72 -0
- package/dist/statusline/render.js.map +1 -0
- package/dist/statusline/session-marker.d.ts +30 -0
- package/dist/statusline/session-marker.d.ts.map +1 -0
- package/dist/statusline/session-marker.js +71 -0
- package/dist/statusline/session-marker.js.map +1 -0
- package/dist/statusline/types.d.ts +67 -0
- package/dist/statusline/types.d.ts.map +1 -0
- package/dist/statusline/types.js +16 -0
- package/dist/statusline/types.js.map +1 -0
- package/dist/sync/git-hooks.d.ts +45 -0
- package/dist/sync/git-hooks.d.ts.map +1 -0
- package/dist/sync/git-hooks.js +225 -0
- package/dist/sync/git-hooks.js.map +1 -0
- package/dist/sync/index.d.ts +19 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +35 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/watch-policy.d.ts +48 -0
- package/dist/sync/watch-policy.d.ts.map +1 -0
- package/dist/sync/watch-policy.js +124 -0
- package/dist/sync/watch-policy.js.map +1 -0
- package/dist/sync/watcher.d.ts +283 -0
- package/dist/sync/watcher.d.ts.map +1 -0
- package/dist/sync/watcher.js +606 -0
- package/dist/sync/watcher.js.map +1 -0
- package/dist/sync/worktree.d.ts +54 -0
- package/dist/sync/worktree.d.ts.map +1 -0
- package/dist/sync/worktree.js +137 -0
- package/dist/sync/worktree.js.map +1 -0
- package/dist/types.d.ts +625 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +118 -0
- package/dist/types.js.map +1 -0
- package/dist/ui/glyphs.d.ts +42 -0
- package/dist/ui/glyphs.d.ts.map +1 -0
- package/dist/ui/glyphs.js +78 -0
- package/dist/ui/glyphs.js.map +1 -0
- package/dist/ui/shimmer-progress.d.ts +11 -0
- package/dist/ui/shimmer-progress.d.ts.map +1 -0
- package/dist/ui/shimmer-progress.js +90 -0
- package/dist/ui/shimmer-progress.js.map +1 -0
- package/dist/ui/shimmer-worker.d.ts +2 -0
- package/dist/ui/shimmer-worker.d.ts.map +1 -0
- package/dist/ui/shimmer-worker.js +118 -0
- package/dist/ui/shimmer-worker.js.map +1 -0
- package/dist/ui/types.d.ts +17 -0
- package/dist/ui/types.d.ts.map +1 -0
- package/dist/ui/types.js +3 -0
- package/dist/ui/types.js.map +1 -0
- package/dist/utils.d.ts +205 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +549 -0
- package/dist/utils.js.map +1 -0
- package/dist/web/chunk-2AJCHB7P.js +1 -0
- package/dist/web/chunk-2CPLUFCH.js +2 -0
- package/dist/web/chunk-2I7L37NS.js +1 -0
- package/dist/web/chunk-2NAWAJB5.js +1 -0
- package/dist/web/chunk-2OJBIPE4.js +1 -0
- package/dist/web/chunk-372AYXK6.js +17 -0
- package/dist/web/chunk-3E2WB6D5.js +1 -0
- package/dist/web/chunk-3EBFYSCH.js +2 -0
- package/dist/web/chunk-3QCQ4BXS.js +1 -0
- package/dist/web/chunk-42XVAQ6I.js +1 -0
- package/dist/web/chunk-4IMMPEYM.js +1 -0
- package/dist/web/chunk-4JYHAP7B.js +1 -0
- package/dist/web/chunk-4TJQJPCZ.js +1 -0
- package/dist/web/chunk-4WZIHTPC.js +1 -0
- package/dist/web/chunk-4YVSYOSD.js +1 -0
- package/dist/web/chunk-52PO6IMB.js +2 -0
- package/dist/web/chunk-54D6RFSW.js +1 -0
- package/dist/web/chunk-5BQIOYKW.js +1 -0
- package/dist/web/chunk-5HGWHUJA.js +1 -0
- package/dist/web/chunk-5XRUOPZE.js +1 -0
- package/dist/web/chunk-5Y244R4G.js +1 -0
- package/dist/web/chunk-6O7Z3P2M.js +1 -0
- package/dist/web/chunk-6QXULGLG.js +1 -0
- package/dist/web/chunk-6RRDPT5Z.js +1 -0
- package/dist/web/chunk-6VKB2ZWM.js +1 -0
- package/dist/web/chunk-7DMFVTU4.js +1 -0
- package/dist/web/chunk-7P5CVBJZ.js +1 -0
- package/dist/web/chunk-7SMPKVEP.js +1 -0
- package/dist/web/chunk-AHLX543M.js +1 -0
- package/dist/web/chunk-AMGJBO7D.js +3 -0
- package/dist/web/chunk-AZJVTPLU.js +1 -0
- package/dist/web/chunk-B3CWIVBW.js +1 -0
- package/dist/web/chunk-BLBRMCN2.js +1 -0
- package/dist/web/chunk-BMIAXD2V.js +2 -0
- package/dist/web/chunk-BPCJLNBS.js +47 -0
- package/dist/web/chunk-BRHEUDLY.js +6 -0
- package/dist/web/chunk-BUXWEHIY.js +1 -0
- package/dist/web/chunk-CD5IZM7Y.js +1 -0
- package/dist/web/chunk-DLQPZWSI.css +1 -0
- package/dist/web/chunk-DSGNOCKQ.js +1 -0
- package/dist/web/chunk-DT5LJYFX.js +1 -0
- package/dist/web/chunk-DYRFLPJA.js +1 -0
- package/dist/web/chunk-E3J3CXR5.js +1 -0
- package/dist/web/chunk-E73OX2P7.js +1 -0
- package/dist/web/chunk-EAXRKDLV.js +1 -0
- package/dist/web/chunk-EBKKDHYI.js +1 -0
- package/dist/web/chunk-EE7V7Q5P.js +1 -0
- package/dist/web/chunk-EKY2FUHU.js +1 -0
- package/dist/web/chunk-EP6XOPXH.js +1 -0
- package/dist/web/chunk-ESGDLJOJ.js +1 -0
- package/dist/web/chunk-ETJG7NCY.js +1 -0
- package/dist/web/chunk-EUUEFEDI.js +1 -0
- package/dist/web/chunk-EX4ZHR4F.js +1 -0
- package/dist/web/chunk-F5UNCSXP.js +1 -0
- package/dist/web/chunk-FFGJXUHI.js +1 -0
- package/dist/web/chunk-FGNZDHTL.js +11 -0
- package/dist/web/chunk-FIJW2UNJ.js +1 -0
- package/dist/web/chunk-FMV5PXRC.js +5 -0
- package/dist/web/chunk-G7VZT5KB.js +3 -0
- package/dist/web/chunk-GCOM4JPR.js +2 -0
- package/dist/web/chunk-GEIIDO6C.js +1 -0
- package/dist/web/chunk-GRZYXPSO.js +7 -0
- package/dist/web/chunk-GWBABPZ5.js +1 -0
- package/dist/web/chunk-GYGPS3AN.js +1 -0
- package/dist/web/chunk-H4GLRD3Q.js +1 -0
- package/dist/web/chunk-H5TWEFYX.js +1 -0
- package/dist/web/chunk-H7AF7YS4.js +1 -0
- package/dist/web/chunk-HCB2N2KH.js +1 -0
- package/dist/web/chunk-HDZDQILN.js +1 -0
- package/dist/web/chunk-HMK6UO6N.js +1 -0
- package/dist/web/chunk-HVVXPI4D.js +1 -0
- package/dist/web/chunk-IHEE5NYJ.js +1 -0
- package/dist/web/chunk-IPB746BT.js +1 -0
- package/dist/web/chunk-ISNEBICW.js +1 -0
- package/dist/web/chunk-J2GZVLHH.js +1 -0
- package/dist/web/chunk-JTFXTIPE.js +903 -0
- package/dist/web/chunk-KHU5M2AL.js +1 -0
- package/dist/web/chunk-KW3DHCFV.js +1 -0
- package/dist/web/chunk-LB6JPLX2.js +1 -0
- package/dist/web/chunk-LBXLFPVN.js +1 -0
- package/dist/web/chunk-LGNSHRCE.js +1 -0
- package/dist/web/chunk-LNSVDHCI.js +1 -0
- package/dist/web/chunk-LVGIY3SO.js +1 -0
- package/dist/web/chunk-LXLHIHEN.js +1 -0
- package/dist/web/chunk-MFHO2F2U.js +4 -0
- package/dist/web/chunk-N5OSSQFZ.js +1 -0
- package/dist/web/chunk-N6SS4G6S.js +1 -0
- package/dist/web/chunk-NAJYJNHS.js +1 -0
- package/dist/web/chunk-NHD66NOI.js +1 -0
- package/dist/web/chunk-NNLJ55MY.js +1 -0
- package/dist/web/chunk-NTBJG6SJ.js +1 -0
- package/dist/web/chunk-NUDB3Q2Y.js +3 -0
- package/dist/web/chunk-OM7JVWQQ.js +1 -0
- package/dist/web/chunk-OXEF5E3E.js +1 -0
- package/dist/web/chunk-PGGJPDJG.js +1 -0
- package/dist/web/chunk-PUYSJNJR.js +1 -0
- package/dist/web/chunk-Q2RVFS45.js +1 -0
- package/dist/web/chunk-Q7L6LLAK.js +1 -0
- package/dist/web/chunk-QCMKJIWY.js +1 -0
- package/dist/web/chunk-QEQRY4QQ.js +1 -0
- package/dist/web/chunk-QH6CF3M3.js +1 -0
- package/dist/web/chunk-QQ5LD7PI.js +1 -0
- package/dist/web/chunk-QR6L3KAC.js +1 -0
- package/dist/web/chunk-QXJS6F3U.js +1 -0
- package/dist/web/chunk-R2DLK4HO.js +1 -0
- package/dist/web/chunk-RD6TVPOT.js +1 -0
- package/dist/web/chunk-RKY4EJYJ.js +1 -0
- package/dist/web/chunk-RONYWVY7.js +1 -0
- package/dist/web/chunk-RSZZWGGC.js +1 -0
- package/dist/web/chunk-RXKXYF2C.js +1 -0
- package/dist/web/chunk-SCNDZRN2.js +1 -0
- package/dist/web/chunk-SH6UVHQC.js +1 -0
- package/dist/web/chunk-SWKJRNYY.js +1 -0
- package/dist/web/chunk-T7AZ65JP.js +1 -0
- package/dist/web/chunk-TCZDVOHD.js +1 -0
- package/dist/web/chunk-TF5TF6IP.js +1 -0
- package/dist/web/chunk-TPTITA3V.js +1 -0
- package/dist/web/chunk-TR335633.js +1 -0
- package/dist/web/chunk-UR5KDXPX.js +1 -0
- package/dist/web/chunk-UR6O2GEH.js +1 -0
- package/dist/web/chunk-UTNMGWTP.js +1 -0
- package/dist/web/chunk-VECWMHJP.js +1 -0
- package/dist/web/chunk-VUACT35R.js +3 -0
- package/dist/web/chunk-VZI7H4SZ.js +1 -0
- package/dist/web/chunk-W22AVG3N.js +1 -0
- package/dist/web/chunk-W6NGHRHX.js +1 -0
- package/dist/web/chunk-WB6YHOD4.js +1 -0
- package/dist/web/chunk-WBT64AWV.js +1 -0
- package/dist/web/chunk-WFXJIXZE.js +4 -0
- package/dist/web/chunk-WTGYRH3Z.js +298 -0
- package/dist/web/chunk-WXTCVDTP.js +1 -0
- package/dist/web/chunk-XCDHWLVH.js +1 -0
- package/dist/web/chunk-Y3H6FFUZ.js +1 -0
- package/dist/web/chunk-Y4F5ULGJ.js +1 -0
- package/dist/web/chunk-YEGKAAEE.js +1 -0
- package/dist/web/chunk-YM2KU57F.js +1 -0
- package/dist/web/chunk-YRERBP6T.js +1 -0
- package/dist/web/chunk-ZLV4VCDG.js +3 -0
- package/dist/web/chunk-ZQUJMA5K.js +4 -0
- package/dist/web/chunk-ZTVI5KFF.js +1 -0
- package/dist/web/favicon-16.png +0 -0
- package/dist/web/favicon-180.png +0 -0
- package/dist/web/favicon-32.png +0 -0
- package/dist/web/favicon-512.png +0 -0
- package/dist/web/favicon-small.svg +15 -0
- package/dist/web/favicon.ico +0 -0
- package/dist/web/favicon.svg +20 -0
- package/dist/web/icon-192.png +0 -0
- package/dist/web/icon-512.png +0 -0
- package/dist/web/index.html +146 -0
- package/dist/web/main-ESADRXN2.css +1 -0
- package/dist/web/main-SQFUMVQA.js +1 -0
- package/dist/web/manifest.webmanifest +15 -0
- package/dist/web/media/codicon-LN6W7LCM.ttf +0 -0
- package/dist/web/styles-KSOPUVDA.css +1 -0
- package/dist/web/sw.js +69 -0
- package/dist/workflows/condition-evaluator.d.ts +75 -0
- package/dist/workflows/condition-evaluator.d.ts.map +1 -0
- package/dist/workflows/condition-evaluator.js +282 -0
- package/dist/workflows/condition-evaluator.js.map +1 -0
- package/dist/workflows/defaults/claude-design-implement.yaml +336 -0
- package/dist/workflows/defaults/index.d.ts +26 -0
- package/dist/workflows/defaults/index.d.ts.map +1 -0
- package/dist/workflows/defaults/index.js +94 -0
- package/dist/workflows/defaults/index.js.map +1 -0
- package/dist/workflows/defaults/spec-author.yaml +214 -0
- package/dist/workflows/defaults/spec-fix.yaml +110 -0
- package/dist/workflows/defaults/spec-implement.yaml +150 -0
- package/dist/workflows/defaults/spec-relink.yaml +81 -0
- package/dist/workflows/defaults/spec-verify.yaml +51 -0
- package/dist/workflows/discovery.d.ts +46 -0
- package/dist/workflows/discovery.d.ts.map +1 -0
- package/dist/workflows/discovery.js +193 -0
- package/dist/workflows/discovery.js.map +1 -0
- package/dist/workflows/executor.d.ts +98 -0
- package/dist/workflows/executor.d.ts.map +1 -0
- package/dist/workflows/executor.js +664 -0
- package/dist/workflows/executor.js.map +1 -0
- package/dist/workflows/runners/approval.d.ts +18 -0
- package/dist/workflows/runners/approval.d.ts.map +1 -0
- package/dist/workflows/runners/approval.js +34 -0
- package/dist/workflows/runners/approval.js.map +1 -0
- package/dist/workflows/runners/bash.d.ts +13 -0
- package/dist/workflows/runners/bash.d.ts.map +1 -0
- package/dist/workflows/runners/bash.js +143 -0
- package/dist/workflows/runners/bash.js.map +1 -0
- package/dist/workflows/runners/cancel.d.ts +10 -0
- package/dist/workflows/runners/cancel.d.ts.map +1 -0
- package/dist/workflows/runners/cancel.js +19 -0
- package/dist/workflows/runners/cancel.js.map +1 -0
- package/dist/workflows/runners/prompt.d.ts +51 -0
- package/dist/workflows/runners/prompt.d.ts.map +1 -0
- package/dist/workflows/runners/prompt.js +306 -0
- package/dist/workflows/runners/prompt.js.map +1 -0
- package/dist/workflows/runners/script.d.ts +17 -0
- package/dist/workflows/runners/script.d.ts.map +1 -0
- package/dist/workflows/runners/script.js +155 -0
- package/dist/workflows/runners/script.js.map +1 -0
- package/dist/workflows/runners/types.d.ts +57 -0
- package/dist/workflows/runners/types.d.ts.map +1 -0
- package/dist/workflows/runners/types.js +13 -0
- package/dist/workflows/runners/types.js.map +1 -0
- package/dist/workflows/schemas/workflow.d.ts +166 -0
- package/dist/workflows/schemas/workflow.d.ts.map +1 -0
- package/dist/workflows/schemas/workflow.js +437 -0
- package/dist/workflows/schemas/workflow.js.map +1 -0
- package/hooks/hooks.json +38 -0
- package/package.json +78 -0
- package/scripts/add-lang/bench.sh +60 -0
- package/scripts/add-lang/check-grammar.mjs +75 -0
- package/scripts/add-lang/dump-ast.mjs +103 -0
- package/scripts/add-lang/verify-extraction.mjs +70 -0
- package/scripts/agent-eval/arms-F.sh +21 -0
- package/scripts/agent-eval/arms-matrix.sh +37 -0
- package/scripts/agent-eval/audit.sh +68 -0
- package/scripts/agent-eval/bench-readme.sh +28 -0
- package/scripts/agent-eval/bench-why-repo.sh +22 -0
- package/scripts/agent-eval/block-read-hook.sh +19 -0
- package/scripts/agent-eval/hook-settings.json +15 -0
- package/scripts/agent-eval/itrun.sh +120 -0
- package/scripts/agent-eval/parse-arms.mjs +116 -0
- package/scripts/agent-eval/parse-bench-readme.mjs +84 -0
- package/scripts/agent-eval/parse-run.mjs +45 -0
- package/scripts/agent-eval/parse-session.mjs +93 -0
- package/scripts/agent-eval/probe-context.mjs +21 -0
- package/scripts/agent-eval/probe-explore.mjs +40 -0
- package/scripts/agent-eval/probe-node.mjs +20 -0
- package/scripts/agent-eval/probe-sweep.mjs +119 -0
- package/scripts/agent-eval/probe-trace.mjs +20 -0
- package/scripts/agent-eval/run-agent.sh +34 -0
- package/scripts/agent-eval/run-all.sh +67 -0
- package/scripts/agent-eval/run-arms.sh +56 -0
- package/scripts/agent-eval/seq-matrix.mjs +137 -0
- package/scripts/build-bundle.sh +118 -0
- package/scripts/build-server-bundle.mjs +80 -0
- package/scripts/build-web-bundle.mjs +66 -0
- package/scripts/extract-release-notes.mjs +130 -0
- package/scripts/local-install.sh +41 -0
- package/scripts/npm-sdk.js +75 -0
- package/scripts/npm-shim.js +246 -0
- package/scripts/offline-install.ps1 +148 -0
- package/scripts/offline-install.sh +149 -0
- package/scripts/pack-npm.sh +119 -0
- package/scripts/prepare-release.mjs +270 -0
- package/scripts/sync-shim-version.mjs +64 -0
- package/selectors.json +41 -0
|
@@ -0,0 +1,864 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Claude Code target. Writes:
|
|
4
|
+
*
|
|
5
|
+
* - MCP server entry to `~/.claude.json` (global = user scope, loads
|
|
6
|
+
* in every project) or `./.mcp.json` (local = project scope, the
|
|
7
|
+
* file Claude Code actually reads for a single project). See the
|
|
8
|
+
* scope table at https://code.claude.com/docs/en/mcp.
|
|
9
|
+
* - Permissions to `~/.claude/settings.json` (global) or
|
|
10
|
+
* `./.claude/settings.json` (local), gated on `autoAllow`.
|
|
11
|
+
* - Instructions to `~/.claude/CLAUDE.md` (global) or
|
|
12
|
+
* `./.claude/CLAUDE.md` (local).
|
|
13
|
+
*
|
|
14
|
+
* Earlier versions wrote the local MCP entry to `./.claude.json` — a
|
|
15
|
+
* file Claude Code never reads — so the server silently never loaded
|
|
16
|
+
* until the user manually renamed it to `.mcp.json` (issue #207). We
|
|
17
|
+
* now write `./.mcp.json` and migrate any stale `./.claude.json` entry
|
|
18
|
+
* out of the way on install and uninstall.
|
|
19
|
+
*/
|
|
20
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
21
|
+
if (k2 === undefined) k2 = k;
|
|
22
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
23
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
24
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
25
|
+
}
|
|
26
|
+
Object.defineProperty(o, k2, desc);
|
|
27
|
+
}) : (function(o, m, k, k2) {
|
|
28
|
+
if (k2 === undefined) k2 = k;
|
|
29
|
+
o[k2] = m[k];
|
|
30
|
+
}));
|
|
31
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
32
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
33
|
+
}) : function(o, v) {
|
|
34
|
+
o["default"] = v;
|
|
35
|
+
});
|
|
36
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
37
|
+
var ownKeys = function(o) {
|
|
38
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
39
|
+
var ar = [];
|
|
40
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
41
|
+
return ar;
|
|
42
|
+
};
|
|
43
|
+
return ownKeys(o);
|
|
44
|
+
};
|
|
45
|
+
return function (mod) {
|
|
46
|
+
if (mod && mod.__esModule) return mod;
|
|
47
|
+
var result = {};
|
|
48
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
49
|
+
__setModuleDefault(result, mod);
|
|
50
|
+
return result;
|
|
51
|
+
};
|
|
52
|
+
})();
|
|
53
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
54
|
+
exports.claudeTarget = void 0;
|
|
55
|
+
exports.writeMcpEntry = writeMcpEntry;
|
|
56
|
+
exports.cleanupLegacyHooks = cleanupLegacyHooks;
|
|
57
|
+
exports.cleanupCurrentHooks = cleanupCurrentHooks;
|
|
58
|
+
exports.writePermissionsEntry = writePermissionsEntry;
|
|
59
|
+
exports.statusLineState = statusLineState;
|
|
60
|
+
exports.getStatusLineSnippet = getStatusLineSnippet;
|
|
61
|
+
exports.writeStatusLineEntry = writeStatusLineEntry;
|
|
62
|
+
exports.removeStatusLineEntry = removeStatusLineEntry;
|
|
63
|
+
exports.removeInstructionsEntry = removeInstructionsEntry;
|
|
64
|
+
exports.writeHooksEntry = writeHooksEntry;
|
|
65
|
+
exports.writeSddHookEntry = writeSddHookEntry;
|
|
66
|
+
exports.cleanupSddHooks = cleanupSddHooks;
|
|
67
|
+
exports.writeSddInstructionsEntry = writeSddInstructionsEntry;
|
|
68
|
+
exports.removeSddInstructionsEntry = removeSddInstructionsEntry;
|
|
69
|
+
exports.writeCommandsEntries = writeCommandsEntries;
|
|
70
|
+
exports.cleanupLegacyCommandsEntries = cleanupLegacyCommandsEntries;
|
|
71
|
+
exports.writeAgentsEntries = writeAgentsEntries;
|
|
72
|
+
exports.removeCommandsEntries = removeCommandsEntries;
|
|
73
|
+
exports.removeAgentsEntries = removeAgentsEntries;
|
|
74
|
+
const fs = __importStar(require("fs"));
|
|
75
|
+
const path = __importStar(require("path"));
|
|
76
|
+
const os = __importStar(require("os"));
|
|
77
|
+
const shared_1 = require("./shared");
|
|
78
|
+
const instructions_template_1 = require("../instructions-template");
|
|
79
|
+
function configDir(loc) {
|
|
80
|
+
return loc === 'global'
|
|
81
|
+
? path.join(os.homedir(), '.claude')
|
|
82
|
+
: path.join(process.cwd(), '.claude');
|
|
83
|
+
}
|
|
84
|
+
function mcpJsonPath(loc) {
|
|
85
|
+
// global → ~/.claude.json (user scope: visible in every project).
|
|
86
|
+
// local → ./.mcp.json (project scope: the ONLY project-level MCP
|
|
87
|
+
// file Claude Code reads — NOT ./.claude.json, which it ignores).
|
|
88
|
+
return loc === 'global'
|
|
89
|
+
? path.join(os.homedir(), '.claude.json')
|
|
90
|
+
: path.join(process.cwd(), '.mcp.json');
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Where pre-#207 installers wrote the local MCP entry. Claude Code
|
|
94
|
+
* never reads a project-level `./.claude.json`, so we migrate the
|
|
95
|
+
* specship entry out of it on install and strip it on uninstall.
|
|
96
|
+
* Only the project-local path is legacy — global `~/.claude.json` is
|
|
97
|
+
* the correct user-scope location and is left untouched.
|
|
98
|
+
*/
|
|
99
|
+
function legacyLocalMcpPath() {
|
|
100
|
+
return path.join(process.cwd(), '.claude.json');
|
|
101
|
+
}
|
|
102
|
+
function settingsJsonPath(loc) {
|
|
103
|
+
return path.join(configDir(loc), 'settings.json');
|
|
104
|
+
}
|
|
105
|
+
function instructionsPath(loc) {
|
|
106
|
+
return path.join(configDir(loc), 'CLAUDE.md');
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* The CLAUDE.md Claude Code actually LOADS as memory — distinct from
|
|
110
|
+
* `instructionsPath` (the legacy `.claude/CLAUDE.md`, which the #529 block
|
|
111
|
+
* used). Project memory is the repo-root `./CLAUDE.md`; user memory is
|
|
112
|
+
* `~/.claude/CLAUDE.md`. The spec-driven-development steering rule goes here so
|
|
113
|
+
* the agent actually reads it.
|
|
114
|
+
*/
|
|
115
|
+
function claudeMdPath(loc) {
|
|
116
|
+
return loc === 'global'
|
|
117
|
+
? path.join(os.homedir(), '.claude', 'CLAUDE.md')
|
|
118
|
+
: path.join(process.cwd(), 'CLAUDE.md');
|
|
119
|
+
}
|
|
120
|
+
function commandsDir(loc) {
|
|
121
|
+
return path.join(configDir(loc), 'commands');
|
|
122
|
+
}
|
|
123
|
+
function agentsDir(loc) {
|
|
124
|
+
return path.join(configDir(loc), 'agents');
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Plugin-asset source dir at the package root — same `commands/`,
|
|
128
|
+
* `agents/`, `hooks/` directories that ship the plugin manifest path.
|
|
129
|
+
* Resolves identically from `src/installer/targets/claude.ts` (dev /
|
|
130
|
+
* test) and `dist/installer/targets/claude.js` (installed npm package).
|
|
131
|
+
*/
|
|
132
|
+
function packageAssetPath(...segments) {
|
|
133
|
+
return path.join(__dirname, '..', '..', '..', ...segments);
|
|
134
|
+
}
|
|
135
|
+
// Slash commands are a small set of progressive DOORS (WORKFLOW-DOORS-DOC),
|
|
136
|
+
// split into two TIERS (INSTALL-WEDGE-DOC, REQ-WEDGE-001.A3). The retrieval door
|
|
137
|
+
// is the adoption wedge — it ships on a default install with zero workflow
|
|
138
|
+
// change. The governance doors (the spec lifecycle + the gate) are the deliberate
|
|
139
|
+
// deep end and ship ONLY on an explicit opt-in (`--sdd`). Each door dispatches its
|
|
140
|
+
// sub-actions internally, so a newcomer meets one obvious entry per phase instead
|
|
141
|
+
// of a long flat list.
|
|
142
|
+
/** Retrieval tier — the reads door. Shipped on every install. */
|
|
143
|
+
const RETRIEVAL_TIER_COMMANDS = [
|
|
144
|
+
'ss-explore.md', // reads: explore / trace / impact
|
|
145
|
+
];
|
|
146
|
+
/** Governance tier — the intent + gate doors, plus the design→code commands. Opt-in (`--sdd`). */
|
|
147
|
+
const GOVERNANCE_TIER_COMMANDS = [
|
|
148
|
+
'ss-spec.md', // intent loop: view / new / fast / implement / review / triage / behaviour / domain
|
|
149
|
+
'ss-check.md', // gate & health: check / drifted / fix / relink / health
|
|
150
|
+
// Design→code workflow (own surface; designer is slated for a separate cut, untouched here).
|
|
151
|
+
'ss-design-implement.md',
|
|
152
|
+
'ss-design-loop.md',
|
|
153
|
+
];
|
|
154
|
+
/**
|
|
155
|
+
* Every command SpecShip ships, both tiers. Used by uninstall (which removes
|
|
156
|
+
* the whole surface regardless of which tier was installed) and the dry-run
|
|
157
|
+
* file list.
|
|
158
|
+
*/
|
|
159
|
+
const SHIPPED_COMMANDS = [...RETRIEVAL_TIER_COMMANDS, ...GOVERNANCE_TIER_COMMANDS];
|
|
160
|
+
/**
|
|
161
|
+
* Slash commands the installer used to ship but no longer does, so install can
|
|
162
|
+
* self-heal on upgrade (it removes any an earlier installer wrote, so the user's
|
|
163
|
+
* autocomplete doesn't carry stale duplicates) and uninstall strips them too.
|
|
164
|
+
* Two generations:
|
|
165
|
+
* - the pre-v0.2 `cg-` prefix (from when SpecShip was "code graph");
|
|
166
|
+
* - the flat per-action `ss-*` commands collapsed into the explore/spec/check
|
|
167
|
+
* doors by WORKFLOW-DOORS-DOC (REQ-DOORS-003.A1). NOTE: the three surviving
|
|
168
|
+
* doors — ss-explore, ss-spec, ss-check — are deliberately NOT listed here.
|
|
169
|
+
*/
|
|
170
|
+
const LEGACY_SHIPPED_COMMANDS = [
|
|
171
|
+
// pre-v0.2 `cg-` prefix
|
|
172
|
+
'cg-sync.md',
|
|
173
|
+
'cg-trace.md',
|
|
174
|
+
'cg-explore.md',
|
|
175
|
+
'cg-impact.md',
|
|
176
|
+
'cg-spec.md',
|
|
177
|
+
'cg-implement.md',
|
|
178
|
+
'cg-drifted.md',
|
|
179
|
+
'cg-fix.md',
|
|
180
|
+
'cg-relink.md',
|
|
181
|
+
'cg-spec-author.md',
|
|
182
|
+
'cg-spec-review.md',
|
|
183
|
+
// per-action ss-* commands folded into the doors (WORKFLOW-DOORS-DOC)
|
|
184
|
+
'ss-sync.md',
|
|
185
|
+
'ss-trace.md',
|
|
186
|
+
'ss-impact.md',
|
|
187
|
+
'ss-implement.md',
|
|
188
|
+
'ss-spec-author.md',
|
|
189
|
+
'ss-spec-review.md',
|
|
190
|
+
'ss-brainstorm.md',
|
|
191
|
+
'ss-domain.md',
|
|
192
|
+
'ss-triage.md',
|
|
193
|
+
'ss-behaviour.md',
|
|
194
|
+
'ss-drifted.md',
|
|
195
|
+
'ss-fix.md',
|
|
196
|
+
'ss-relink.md',
|
|
197
|
+
];
|
|
198
|
+
/** Subagents the installer copies into Claude's agents dir. */
|
|
199
|
+
const SHIPPED_AGENTS = ['specship-explorer.md'];
|
|
200
|
+
/** The PostToolUse + SessionStart hooks the installer writes. */
|
|
201
|
+
const SPECSHIP_HOOKS = [
|
|
202
|
+
{
|
|
203
|
+
event: 'PostToolUse',
|
|
204
|
+
matcher: 'Edit|Write|MultiEdit',
|
|
205
|
+
hook: { type: 'command', command: 'specship sync --quiet', async: true },
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
event: 'SessionStart',
|
|
209
|
+
matcher: 'startup|resume',
|
|
210
|
+
hook: { type: 'command', command: 'specship sync --quiet' },
|
|
211
|
+
},
|
|
212
|
+
];
|
|
213
|
+
/**
|
|
214
|
+
* The spec-driven-development steering hook (SDD-INSTALL-DOC, REQ-SDD-002).
|
|
215
|
+
* A `UserPromptSubmit` hook executed by the harness; `specship spec-nudge`
|
|
216
|
+
* reads the prompt and, on feature/bug-shaped intent, injects a non-blocking
|
|
217
|
+
* reminder to author the spec via spec-author first. UserPromptSubmit has no
|
|
218
|
+
* tool matcher, so the matcher is empty (runs on every prompt; the nudge
|
|
219
|
+
* command does the conservative intent filtering itself).
|
|
220
|
+
*/
|
|
221
|
+
const SPECSHIP_SDD_HOOKS = [
|
|
222
|
+
{
|
|
223
|
+
event: 'UserPromptSubmit',
|
|
224
|
+
matcher: '',
|
|
225
|
+
hook: { type: 'command', command: 'specship spec-nudge' },
|
|
226
|
+
},
|
|
227
|
+
];
|
|
228
|
+
/**
|
|
229
|
+
* The status-line entry the installer writes into `settings.json`
|
|
230
|
+
* (SHIP-STATUSLINE-DOC). `command` mirrors the MCP launcher (`specship` on
|
|
231
|
+
* PATH); Claude Code pipes the status-line JSON to it on stdin and renders its
|
|
232
|
+
* stdout. The `_specship` marker is how uninstall knows we own this entry — a
|
|
233
|
+
* status line the user authored has no marker and is never touched.
|
|
234
|
+
*/
|
|
235
|
+
const SPECSHIP_STATUSLINE = {
|
|
236
|
+
type: 'command',
|
|
237
|
+
command: 'specship statusline',
|
|
238
|
+
_specship: true,
|
|
239
|
+
};
|
|
240
|
+
/** True when a `statusLine` object is one SpecShip wrote (carries our marker). */
|
|
241
|
+
function isOurStatusLine(sl) {
|
|
242
|
+
return !!sl && typeof sl === 'object' && sl._specship === true;
|
|
243
|
+
}
|
|
244
|
+
class ClaudeCodeTarget {
|
|
245
|
+
id = 'claude';
|
|
246
|
+
displayName = 'Claude Code';
|
|
247
|
+
docsUrl = 'https://docs.claude.com/en/docs/claude-code';
|
|
248
|
+
supportsLocation(_loc) {
|
|
249
|
+
return true;
|
|
250
|
+
}
|
|
251
|
+
detect(loc) {
|
|
252
|
+
const mcpPath = mcpJsonPath(loc);
|
|
253
|
+
const config = (0, shared_1.readJsonFile)(mcpPath);
|
|
254
|
+
const alreadyConfigured = !!config.mcpServers?.specship;
|
|
255
|
+
// For "installed" we infer from the existence of either the dir
|
|
256
|
+
// (global) or the project marker file (local). Cheap and avoids
|
|
257
|
+
// shelling out to `claude --version`.
|
|
258
|
+
const installed = loc === 'global'
|
|
259
|
+
? fs.existsSync(configDir(loc)) || fs.existsSync(mcpPath)
|
|
260
|
+
: fs.existsSync(mcpPath) || fs.existsSync(configDir(loc));
|
|
261
|
+
return { installed, alreadyConfigured, configPath: mcpPath };
|
|
262
|
+
}
|
|
263
|
+
install(loc, opts) {
|
|
264
|
+
const files = [];
|
|
265
|
+
// 1. MCP server entry
|
|
266
|
+
files.push(writeMcpEntry(loc));
|
|
267
|
+
// 1b. Migrate away any stale ./.claude.json left by a pre-#207
|
|
268
|
+
// local install, so the project isn't left with two competing
|
|
269
|
+
// (one dead) MCP configs.
|
|
270
|
+
if (loc === 'local') {
|
|
271
|
+
const migrated = cleanupLegacyLocalMcp();
|
|
272
|
+
if (migrated)
|
|
273
|
+
files.push(migrated);
|
|
274
|
+
}
|
|
275
|
+
// 2. Permissions (only when autoAllow)
|
|
276
|
+
if (opts.autoAllow) {
|
|
277
|
+
files.push(writePermissionsEntry(loc));
|
|
278
|
+
}
|
|
279
|
+
// 2b. Strip stale auto-sync hooks left by a pre-0.8 install. Those
|
|
280
|
+
// versions wrote `specship mark-dirty` / `sync-if-dirty` hooks to
|
|
281
|
+
// settings.json; both subcommands are gone from the CLI, so the
|
|
282
|
+
// Stop hook now fails every turn with "unknown command
|
|
283
|
+
// 'sync-if-dirty'". Cleaning up on install makes an upgrade
|
|
284
|
+
// self-healing. Only surfaced when something was actually removed.
|
|
285
|
+
const hookCleanup = cleanupLegacyHooks(loc);
|
|
286
|
+
if (hookCleanup.action === 'removed')
|
|
287
|
+
files.push(hookCleanup);
|
|
288
|
+
// 2c. Write the current auto-sync hooks (PostToolUse + SessionStart
|
|
289
|
+
// running `specship sync --quiet`). Gated on autoAllow — same
|
|
290
|
+
// posture as the permissions list since both auto-execute commands
|
|
291
|
+
// without prompting. Idempotent: re-running with identical hooks
|
|
292
|
+
// already in settings.json returns 'unchanged'.
|
|
293
|
+
if (opts.autoAllow) {
|
|
294
|
+
files.push(writeHooksEntry(loc));
|
|
295
|
+
}
|
|
296
|
+
// 3. CLAUDE.md instructions — no longer written. The specship
|
|
297
|
+
// usage guidance now ships solely in the MCP server's `initialize`
|
|
298
|
+
// response (see `mcp/server-instructions.ts`), which Claude Code
|
|
299
|
+
// surfaces in the system prompt automatically. Writing it into
|
|
300
|
+
// CLAUDE.md as well meant the agent read the same playbook twice
|
|
301
|
+
// every turn (issue #529). Strip any block a previous install left
|
|
302
|
+
// behind so an upgrade self-heals — same idiom as the hook cleanup.
|
|
303
|
+
const instrCleanup = removeInstructionsEntry(loc);
|
|
304
|
+
if (instrCleanup.action === 'removed')
|
|
305
|
+
files.push(instrCleanup);
|
|
306
|
+
// 4. Slash commands + the specship-explorer subagent. NOT gated on
|
|
307
|
+
// autoAllow — these only execute when the user / agent invokes them
|
|
308
|
+
// explicitly. Copies the same .md files that ship for the plugin
|
|
309
|
+
// install path, so the two flows can't drift apart.
|
|
310
|
+
//
|
|
311
|
+
// 4a. Strip any legacy `cg-*.md` slash commands the pre-v0.2
|
|
312
|
+
// installer wrote. Self-heals on upgrade so the user's autocomplete
|
|
313
|
+
// doesn't carry both prefixes side-by-side.
|
|
314
|
+
// Governance is opt-in (INSTALL-WEDGE-DOC, REQ-WEDGE-002): the spec /
|
|
315
|
+
// authoring / review / design commands AND the SDD steering ship together
|
|
316
|
+
// only when the user explicitly enables them with `--sdd`. A default install
|
|
317
|
+
// provisions the retrieval tier alone, protecting the wedge (REQ-WEDGE-001).
|
|
318
|
+
const includeGovernance = opts.sdd === true;
|
|
319
|
+
for (const f of cleanupLegacyCommandsEntries(loc))
|
|
320
|
+
files.push(f);
|
|
321
|
+
for (const f of writeCommandsEntries(loc, includeGovernance))
|
|
322
|
+
files.push(f);
|
|
323
|
+
for (const f of writeAgentsEntries(loc))
|
|
324
|
+
files.push(f);
|
|
325
|
+
// 5. Spec-driven-development steering (SDD-INSTALL-DOC, as superseded by
|
|
326
|
+
// INSTALL-WEDGE-DOC). Part of the governance tier — opt-in via `--sdd`.
|
|
327
|
+
// Writes a marker-delimited "invoke spec-author first" rule into the project
|
|
328
|
+
// CLAUDE.md and a UserPromptSubmit nudge hook. NOT gated on autoAllow — the
|
|
329
|
+
// CLAUDE.md rule executes nothing and the nudge hook only prints guidance.
|
|
330
|
+
if (includeGovernance) {
|
|
331
|
+
files.push(writeSddInstructionsEntry(loc));
|
|
332
|
+
files.push(writeSddHookEntry(loc));
|
|
333
|
+
}
|
|
334
|
+
// 6. Status-line segment (SHIP-STATUSLINE-DOC, REQ-STATUSLINE-006).
|
|
335
|
+
// Strictly opt-in — only when the caller set installStatusLine (the
|
|
336
|
+
// interactive prompt, or `--statusline`). Never clobbers a user's existing
|
|
337
|
+
// status line: writeStatusLineEntry returns 'kept' and we surface the
|
|
338
|
+
// composable snippet as a note so the user can wire it in themselves.
|
|
339
|
+
const notes = [];
|
|
340
|
+
if (opts.installStatusLine) {
|
|
341
|
+
const sl = writeStatusLineEntry(loc);
|
|
342
|
+
files.push(sl);
|
|
343
|
+
if (sl.action === 'kept') {
|
|
344
|
+
notes.push('A status line is already configured — left untouched. Add the SpecShip ' +
|
|
345
|
+
`segment to your own status-line script:\n ${getStatusLineSnippet()}`);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return notes.length ? { files, notes } : { files };
|
|
349
|
+
}
|
|
350
|
+
uninstall(loc) {
|
|
351
|
+
const files = [];
|
|
352
|
+
// 1. MCP server entry
|
|
353
|
+
const mcpPath = mcpJsonPath(loc);
|
|
354
|
+
const config = (0, shared_1.readJsonFile)(mcpPath);
|
|
355
|
+
if (config.mcpServers?.specship) {
|
|
356
|
+
delete config.mcpServers.specship;
|
|
357
|
+
if (Object.keys(config.mcpServers).length === 0) {
|
|
358
|
+
delete config.mcpServers;
|
|
359
|
+
}
|
|
360
|
+
(0, shared_1.writeJsonFile)(mcpPath, config);
|
|
361
|
+
files.push({ path: mcpPath, action: 'removed' });
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
files.push({ path: mcpPath, action: 'not-found' });
|
|
365
|
+
}
|
|
366
|
+
// 1b. Also strip the specship entry from a legacy ./.claude.json
|
|
367
|
+
// so uninstall fully reverses a pre-#207 local install.
|
|
368
|
+
if (loc === 'local') {
|
|
369
|
+
const migrated = cleanupLegacyLocalMcp();
|
|
370
|
+
if (migrated)
|
|
371
|
+
files.push(migrated);
|
|
372
|
+
}
|
|
373
|
+
// 2. Permissions
|
|
374
|
+
const settingsPath = settingsJsonPath(loc);
|
|
375
|
+
const settings = (0, shared_1.readJsonFile)(settingsPath);
|
|
376
|
+
if (Array.isArray(settings.permissions?.allow)) {
|
|
377
|
+
const before = settings.permissions.allow.length;
|
|
378
|
+
settings.permissions.allow = settings.permissions.allow.filter((p) => !p.startsWith('mcp__specship__'));
|
|
379
|
+
if (settings.permissions.allow.length !== before) {
|
|
380
|
+
if (settings.permissions.allow.length === 0) {
|
|
381
|
+
delete settings.permissions.allow;
|
|
382
|
+
}
|
|
383
|
+
if (Object.keys(settings.permissions).length === 0) {
|
|
384
|
+
delete settings.permissions;
|
|
385
|
+
}
|
|
386
|
+
(0, shared_1.writeJsonFile)(settingsPath, settings);
|
|
387
|
+
files.push({ path: settingsPath, action: 'removed' });
|
|
388
|
+
}
|
|
389
|
+
else {
|
|
390
|
+
files.push({ path: settingsPath, action: 'not-found' });
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
else {
|
|
394
|
+
files.push({ path: settingsPath, action: 'not-found' });
|
|
395
|
+
}
|
|
396
|
+
// 2b. Strip auto-sync hooks the installer wrote — both the
|
|
397
|
+
// current `specship sync --quiet` form (writeHooksEntry) and the
|
|
398
|
+
// legacy `mark-dirty`/`sync-if-dirty` forms (pre-0.8). Two passes
|
|
399
|
+
// so each predicate stays narrow and we never accidentally strip a
|
|
400
|
+
// user-written hook.
|
|
401
|
+
const currentCleanup = cleanupCurrentHooks(loc);
|
|
402
|
+
if (currentCleanup.action === 'removed')
|
|
403
|
+
files.push(currentCleanup);
|
|
404
|
+
const legacyCleanup = cleanupLegacyHooks(loc);
|
|
405
|
+
if (legacyCleanup.action === 'removed')
|
|
406
|
+
files.push(legacyCleanup);
|
|
407
|
+
// 3. Instructions — strip the legacy SpecShip block if present.
|
|
408
|
+
files.push(removeInstructionsEntry(loc));
|
|
409
|
+
// 4. Slash commands + subagent — remove our shipped files; sibling
|
|
410
|
+
// user-written .md files in the same dir are left untouched.
|
|
411
|
+
// Includes legacy `cg-*.md` from pre-v0.2 installers so uninstall
|
|
412
|
+
// leaves the commands dir clean regardless of which prefix was
|
|
413
|
+
// installed.
|
|
414
|
+
for (const f of cleanupLegacyCommandsEntries(loc))
|
|
415
|
+
files.push(f);
|
|
416
|
+
for (const f of removeCommandsEntries(loc))
|
|
417
|
+
files.push(f);
|
|
418
|
+
for (const f of removeAgentsEntries(loc))
|
|
419
|
+
files.push(f);
|
|
420
|
+
// 5. Spec-driven-development steering — strip the CLAUDE.md rule block
|
|
421
|
+
// and the nudge hook (no-op when absent). Always runs so uninstall fully
|
|
422
|
+
// reverses install regardless of whether --no-sdd was used.
|
|
423
|
+
files.push(removeSddInstructionsEntry(loc));
|
|
424
|
+
const sddHookCleanup = cleanupSddHooks(loc);
|
|
425
|
+
if (sddHookCleanup.action === 'removed')
|
|
426
|
+
files.push(sddHookCleanup);
|
|
427
|
+
// 6. Status-line segment — remove only the marked entry we wrote
|
|
428
|
+
// (REQ-STATUSLINE-007). A user-authored status line has no marker and is
|
|
429
|
+
// left untouched; absent entry is a no-op. Always runs so uninstall fully
|
|
430
|
+
// reverses an opt-in status-line install.
|
|
431
|
+
const slCleanup = removeStatusLineEntry(loc);
|
|
432
|
+
if (slCleanup.action === 'removed')
|
|
433
|
+
files.push(slCleanup);
|
|
434
|
+
return { files };
|
|
435
|
+
}
|
|
436
|
+
printConfig(loc) {
|
|
437
|
+
const target = mcpJsonPath(loc);
|
|
438
|
+
const snippet = JSON.stringify({ mcpServers: { specship: (0, shared_1.getMcpServerConfig)() } }, null, 2);
|
|
439
|
+
return `# Add to ${target}\n\n${snippet}\n`;
|
|
440
|
+
}
|
|
441
|
+
describePaths(loc) {
|
|
442
|
+
return [
|
|
443
|
+
mcpJsonPath(loc),
|
|
444
|
+
settingsJsonPath(loc),
|
|
445
|
+
instructionsPath(loc),
|
|
446
|
+
...SHIPPED_COMMANDS.map((f) => path.join(commandsDir(loc), f)),
|
|
447
|
+
...SHIPPED_AGENTS.map((f) => path.join(agentsDir(loc), f)),
|
|
448
|
+
];
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Per-file write helpers, exported so the legacy `config-writer.ts`
|
|
453
|
+
* shim can call only the named operation (writeMcpConfig writes ONLY
|
|
454
|
+
* the MCP entry, etc.) instead of `claudeTarget.install()` which
|
|
455
|
+
* writes all three files. Without this split the shims silently
|
|
456
|
+
* cause side effects callers don't expect.
|
|
457
|
+
*/
|
|
458
|
+
function writeMcpEntry(loc) {
|
|
459
|
+
const file = mcpJsonPath(loc);
|
|
460
|
+
const existing = (0, shared_1.readJsonFile)(file);
|
|
461
|
+
const before = existing.mcpServers?.specship;
|
|
462
|
+
const after = (0, shared_1.getMcpServerConfig)();
|
|
463
|
+
if ((0, shared_1.jsonDeepEqual)(before, after)) {
|
|
464
|
+
// Already exactly what we'd write — preserve byte-identical file.
|
|
465
|
+
return { path: file, action: 'unchanged' };
|
|
466
|
+
}
|
|
467
|
+
// 'created' here means: the file itself did not exist before this
|
|
468
|
+
// write. A pre-existing MCP JSON file (`~/.claude.json` globally,
|
|
469
|
+
// `./.mcp.json` locally) containing other MCP servers (no
|
|
470
|
+
// `specship` key) is 'updated', not 'created' — we're adding an
|
|
471
|
+
// entry to a file that was already there. Codex uses a different
|
|
472
|
+
// idiom (empty-content => 'created') because its config.toml is
|
|
473
|
+
// ours alone to manage.
|
|
474
|
+
const action = before ? 'updated' : (fs.existsSync(file) ? 'updated' : 'created');
|
|
475
|
+
if (!existing.mcpServers)
|
|
476
|
+
existing.mcpServers = {};
|
|
477
|
+
existing.mcpServers.specship = after;
|
|
478
|
+
(0, shared_1.writeJsonFile)(file, existing);
|
|
479
|
+
return { path: file, action };
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Strip the specship entry from a legacy project-local
|
|
483
|
+
* `./.claude.json` (written by pre-#207 installers, which Claude Code
|
|
484
|
+
* never read). Surgical: only our `specship` key is removed; sibling
|
|
485
|
+
* MCP servers and any unrelated keys are preserved, and the file is
|
|
486
|
+
* deleted only when removal leaves it completely empty. Returns the
|
|
487
|
+
* file action for reporting, or `null` when there's nothing to migrate.
|
|
488
|
+
*/
|
|
489
|
+
function cleanupLegacyLocalMcp() {
|
|
490
|
+
const file = legacyLocalMcpPath();
|
|
491
|
+
if (!fs.existsSync(file))
|
|
492
|
+
return null;
|
|
493
|
+
const config = (0, shared_1.readJsonFile)(file);
|
|
494
|
+
if (!config.mcpServers?.specship)
|
|
495
|
+
return null;
|
|
496
|
+
delete config.mcpServers.specship;
|
|
497
|
+
if (Object.keys(config.mcpServers).length === 0)
|
|
498
|
+
delete config.mcpServers;
|
|
499
|
+
if (Object.keys(config).length === 0) {
|
|
500
|
+
try {
|
|
501
|
+
fs.unlinkSync(file);
|
|
502
|
+
}
|
|
503
|
+
catch { /* ignore */ }
|
|
504
|
+
}
|
|
505
|
+
else {
|
|
506
|
+
(0, shared_1.writeJsonFile)(file, config);
|
|
507
|
+
}
|
|
508
|
+
return { path: file, action: 'removed' };
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* True when a Claude Code hook `command` is one of the **pre-0.8**
|
|
512
|
+
* specship auto-sync hooks: `specship mark-dirty` (PostToolUse) /
|
|
513
|
+
* `specship sync-if-dirty` (Stop). Both subcommands have since been
|
|
514
|
+
* removed from the CLI, so the Stop hook fails every turn with
|
|
515
|
+
* "unknown command 'sync-if-dirty'" — stripping them on install
|
|
516
|
+
* (self-heal on upgrade) is what keeps the upgrade quiet. Local builds
|
|
517
|
+
* also wrote the npx form, which still contains the `specship
|
|
518
|
+
* <subcommand>` substring; the substring match covers both. Sibling
|
|
519
|
+
* user hooks (e.g. GitKraken's `gk ai hook run`) match nothing here.
|
|
520
|
+
*
|
|
521
|
+
* The **current** auto-sync hook form (`specship sync --quiet`) is
|
|
522
|
+
* NOT matched here — install writes those and would re-strip its own
|
|
523
|
+
* work if this predicate covered them. The uninstall flow uses
|
|
524
|
+
* `isCurrentSpecshipHookCommand` for those, on top of this one.
|
|
525
|
+
*/
|
|
526
|
+
function isLegacySpecshipHookCommand(command) {
|
|
527
|
+
if (typeof command !== 'string')
|
|
528
|
+
return false;
|
|
529
|
+
return (command.includes('specship mark-dirty') ||
|
|
530
|
+
command.includes('specship sync-if-dirty'));
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* True when a hook `command` is one of the auto-sync hooks
|
|
534
|
+
* `writeHooksEntry` writes in this release (`specship sync --quiet`).
|
|
535
|
+
* Uninstall-only — install must NOT match these or it would destroy
|
|
536
|
+
* the entries it just wrote.
|
|
537
|
+
*/
|
|
538
|
+
function isCurrentSpecshipHookCommand(command) {
|
|
539
|
+
if (typeof command !== 'string')
|
|
540
|
+
return false;
|
|
541
|
+
return SPECSHIP_HOOKS.some(({ hook }) => command === hook.command);
|
|
542
|
+
}
|
|
543
|
+
/**
|
|
544
|
+
* Strip specship hook commands matched by `predicate` from Claude
|
|
545
|
+
* `settings.json`. Surgical at the individual-command level: only
|
|
546
|
+
* matched entries are dropped, so a sibling hook sharing a matcher
|
|
547
|
+
* group (or the Stop event) survives. Matcher groups are pruned only
|
|
548
|
+
* once their `hooks` array is empty, events only once they have no
|
|
549
|
+
* groups left, and `hooks` itself only once every event is gone — and
|
|
550
|
+
* none of that runs unless we actually removed a command, so a
|
|
551
|
+
* settings.json with no matching hooks is left byte-for-byte untouched
|
|
552
|
+
* and reported `unchanged`.
|
|
553
|
+
*/
|
|
554
|
+
function stripHooksMatching(loc, predicate) {
|
|
555
|
+
const file = settingsJsonPath(loc);
|
|
556
|
+
if (!fs.existsSync(file))
|
|
557
|
+
return { path: file, action: 'not-found' };
|
|
558
|
+
const settings = (0, shared_1.readJsonFile)(file);
|
|
559
|
+
const hooks = settings.hooks;
|
|
560
|
+
if (!hooks || typeof hooks !== 'object' || Array.isArray(hooks)) {
|
|
561
|
+
return { path: file, action: 'unchanged' };
|
|
562
|
+
}
|
|
563
|
+
let removedAny = false;
|
|
564
|
+
for (const event of Object.keys(hooks)) {
|
|
565
|
+
const groups = hooks[event];
|
|
566
|
+
if (!Array.isArray(groups))
|
|
567
|
+
continue;
|
|
568
|
+
for (const group of groups) {
|
|
569
|
+
if (!group || !Array.isArray(group.hooks))
|
|
570
|
+
continue;
|
|
571
|
+
const before = group.hooks.length;
|
|
572
|
+
group.hooks = group.hooks.filter((h) => !predicate(h?.command));
|
|
573
|
+
if (group.hooks.length !== before)
|
|
574
|
+
removedAny = true;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
if (!removedAny)
|
|
578
|
+
return { path: file, action: 'unchanged' };
|
|
579
|
+
for (const event of Object.keys(hooks)) {
|
|
580
|
+
const groups = hooks[event];
|
|
581
|
+
if (!Array.isArray(groups))
|
|
582
|
+
continue;
|
|
583
|
+
hooks[event] = groups.filter((g) => !(g && Array.isArray(g.hooks) && g.hooks.length === 0));
|
|
584
|
+
if (hooks[event].length === 0)
|
|
585
|
+
delete hooks[event];
|
|
586
|
+
}
|
|
587
|
+
if (Object.keys(hooks).length === 0)
|
|
588
|
+
delete settings.hooks;
|
|
589
|
+
(0, shared_1.writeJsonFile)(file, settings);
|
|
590
|
+
return { path: file, action: 'removed' };
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Remove stale **pre-0.8** specship auto-sync hooks
|
|
594
|
+
* (`specship mark-dirty` / `specship sync-if-dirty`) from Claude
|
|
595
|
+
* `settings.json`. Safe to call from both `install` (self-heal on
|
|
596
|
+
* upgrade) and `uninstall`. Exported so it can be unit-tested directly.
|
|
597
|
+
*/
|
|
598
|
+
function cleanupLegacyHooks(loc) {
|
|
599
|
+
return stripHooksMatching(loc, isLegacySpecshipHookCommand);
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* Remove the current-release auto-sync hooks (`specship sync --quiet`)
|
|
603
|
+
* written by `writeHooksEntry`. Uninstall-only — install would
|
|
604
|
+
* destroy its own write if this ran there.
|
|
605
|
+
*/
|
|
606
|
+
function cleanupCurrentHooks(loc) {
|
|
607
|
+
return stripHooksMatching(loc, isCurrentSpecshipHookCommand);
|
|
608
|
+
}
|
|
609
|
+
function writePermissionsEntry(loc) {
|
|
610
|
+
const file = settingsJsonPath(loc);
|
|
611
|
+
const settings = (0, shared_1.readJsonFile)(file);
|
|
612
|
+
const created = !fs.existsSync(file);
|
|
613
|
+
if (!settings.permissions)
|
|
614
|
+
settings.permissions = {};
|
|
615
|
+
if (!Array.isArray(settings.permissions.allow))
|
|
616
|
+
settings.permissions.allow = [];
|
|
617
|
+
const want = (0, shared_1.getSpecShipPermissions)();
|
|
618
|
+
const before = [...settings.permissions.allow];
|
|
619
|
+
for (const perm of want) {
|
|
620
|
+
if (!settings.permissions.allow.includes(perm)) {
|
|
621
|
+
settings.permissions.allow.push(perm);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
if ((0, shared_1.jsonDeepEqual)(before, settings.permissions.allow) && !created) {
|
|
625
|
+
return { path: file, action: 'unchanged' };
|
|
626
|
+
}
|
|
627
|
+
(0, shared_1.writeJsonFile)(file, settings);
|
|
628
|
+
return { path: file, action: created ? 'created' : 'updated' };
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* What status line is configured at this location, from SpecShip's point of
|
|
632
|
+
* view (REQ-STATUSLINE-006): `none` (free to write), `ours` (a marked entry we
|
|
633
|
+
* wrote — safe to re-assert), or `foreign` (a status line the user owns — must
|
|
634
|
+
* never be clobbered). Drives the installer's offer-vs-snippet decision.
|
|
635
|
+
*/
|
|
636
|
+
function statusLineState(loc) {
|
|
637
|
+
const settings = (0, shared_1.readJsonFile)(settingsJsonPath(loc));
|
|
638
|
+
if (!settings.statusLine)
|
|
639
|
+
return 'none';
|
|
640
|
+
return isOurStatusLine(settings.statusLine) ? 'ours' : 'foreign';
|
|
641
|
+
}
|
|
642
|
+
/** The one-line snippet a user composes into their own status-line script. */
|
|
643
|
+
function getStatusLineSnippet() {
|
|
644
|
+
return 'specship statusline # pipe Claude\'s status-line JSON in; append its output to your line';
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Write SpecShip's status-line entry into `settings.json`
|
|
648
|
+
* (REQ-STATUSLINE-006). Refuses to overwrite a status line the user already
|
|
649
|
+
* configured: returns `kept` when a foreign `statusLine` is present, so the
|
|
650
|
+
* caller can surface the composable snippet instead. Idempotent — re-asserting
|
|
651
|
+
* our own marked entry byte-for-byte returns `unchanged`.
|
|
652
|
+
*/
|
|
653
|
+
function writeStatusLineEntry(loc) {
|
|
654
|
+
const file = settingsJsonPath(loc);
|
|
655
|
+
const settings = (0, shared_1.readJsonFile)(file);
|
|
656
|
+
const existing = settings.statusLine;
|
|
657
|
+
// Never clobber a user-authored status line.
|
|
658
|
+
if (existing && !isOurStatusLine(existing)) {
|
|
659
|
+
return { path: file, action: 'kept' };
|
|
660
|
+
}
|
|
661
|
+
if (isOurStatusLine(existing) && (0, shared_1.jsonDeepEqual)(existing, SPECSHIP_STATUSLINE)) {
|
|
662
|
+
return { path: file, action: 'unchanged' };
|
|
663
|
+
}
|
|
664
|
+
const created = !fs.existsSync(file);
|
|
665
|
+
settings.statusLine = { ...SPECSHIP_STATUSLINE };
|
|
666
|
+
(0, shared_1.writeJsonFile)(file, settings);
|
|
667
|
+
return { path: file, action: created ? 'created' : 'updated' };
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* Inverse of `writeStatusLineEntry`: remove the `statusLine` entry ONLY when
|
|
671
|
+
* it is the marked one we wrote (REQ-STATUSLINE-007). A user-authored status
|
|
672
|
+
* line (no marker) is left exactly as-is; an absent entry is a no-op.
|
|
673
|
+
*/
|
|
674
|
+
function removeStatusLineEntry(loc) {
|
|
675
|
+
const file = settingsJsonPath(loc);
|
|
676
|
+
if (!fs.existsSync(file))
|
|
677
|
+
return { path: file, action: 'not-found' };
|
|
678
|
+
const settings = (0, shared_1.readJsonFile)(file);
|
|
679
|
+
if (!isOurStatusLine(settings.statusLine)) {
|
|
680
|
+
// Either nothing there, or a user-owned status line — never touch it.
|
|
681
|
+
return { path: file, action: settings.statusLine ? 'kept' : 'not-found' };
|
|
682
|
+
}
|
|
683
|
+
delete settings.statusLine;
|
|
684
|
+
(0, shared_1.writeJsonFile)(file, settings);
|
|
685
|
+
return { path: file, action: 'removed' };
|
|
686
|
+
}
|
|
687
|
+
/**
|
|
688
|
+
* Strip the marker-delimited SpecShip block from CLAUDE.md if a prior
|
|
689
|
+
* install wrote one. Specship no longer maintains an instructions file
|
|
690
|
+
* (issue #529) — the MCP server's `initialize` instructions are the
|
|
691
|
+
* single source of truth — so both install (self-heal on upgrade) and
|
|
692
|
+
* uninstall call this. `removeMarkedSection` returns `not-found`/`kept`
|
|
693
|
+
* when there's nothing to strip; the install caller drops those from
|
|
694
|
+
* the report so a fresh install stays quiet.
|
|
695
|
+
*/
|
|
696
|
+
function removeInstructionsEntry(loc) {
|
|
697
|
+
const file = instructionsPath(loc);
|
|
698
|
+
const action = (0, shared_1.removeMarkedSection)(file, instructions_template_1.SPECSHIP_SECTION_START, instructions_template_1.SPECSHIP_SECTION_END);
|
|
699
|
+
return { path: file, action };
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Write specship's auto-sync hooks into Claude `settings.json`. Merges
|
|
703
|
+
* idempotently into any user-defined hooks: a matcher group sharing our
|
|
704
|
+
* exact matcher string is reused; sibling matchers / events / events are
|
|
705
|
+
* untouched. Returns `unchanged` when our two hook commands are already
|
|
706
|
+
* present byte-for-byte in the right places.
|
|
707
|
+
*
|
|
708
|
+
* Gated by `install()` on `autoAllow` — same posture as the permissions
|
|
709
|
+
* list. The matching uninstall lives in `cleanupLegacyHooks` (whose
|
|
710
|
+
* matcher predicate covers BOTH the new `specship sync --quiet` form
|
|
711
|
+
* and the legacy `specship mark-dirty`/`sync-if-dirty` forms).
|
|
712
|
+
*/
|
|
713
|
+
function writeHooksEntry(loc) {
|
|
714
|
+
return writeHooksFor(loc, SPECSHIP_HOOKS);
|
|
715
|
+
}
|
|
716
|
+
/**
|
|
717
|
+
* Write the spec-driven-development UserPromptSubmit nudge hook into
|
|
718
|
+
* `settings.json` (SDD-INSTALL-DOC, REQ-SDD-002). Same idempotent merge as
|
|
719
|
+
* the auto-sync hooks; gated by `install()` on `opts.sdd` rather than
|
|
720
|
+
* `autoAllow`, since it's part of the SDD steering feature.
|
|
721
|
+
*/
|
|
722
|
+
function writeSddHookEntry(loc) {
|
|
723
|
+
return writeHooksFor(loc, SPECSHIP_SDD_HOOKS);
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
726
|
+
* Idempotently merge a set of hooks into Claude `settings.json`. A matcher
|
|
727
|
+
* group sharing our exact matcher string is reused; sibling matchers / events
|
|
728
|
+
* are untouched; a command already present byte-for-byte is skipped. Returns
|
|
729
|
+
* `unchanged` when nothing was added.
|
|
730
|
+
*/
|
|
731
|
+
function writeHooksFor(loc, hooks) {
|
|
732
|
+
const file = settingsJsonPath(loc);
|
|
733
|
+
const created = !fs.existsSync(file);
|
|
734
|
+
const settings = (0, shared_1.readJsonFile)(file);
|
|
735
|
+
const beforeJson = JSON.stringify(settings);
|
|
736
|
+
if (!settings.hooks || typeof settings.hooks !== 'object' || Array.isArray(settings.hooks)) {
|
|
737
|
+
settings.hooks = {};
|
|
738
|
+
}
|
|
739
|
+
for (const { event, matcher, hook } of hooks) {
|
|
740
|
+
if (!Array.isArray(settings.hooks[event]))
|
|
741
|
+
settings.hooks[event] = [];
|
|
742
|
+
let group = settings.hooks[event].find((g) => g && g.matcher === matcher);
|
|
743
|
+
if (!group) {
|
|
744
|
+
group = { matcher, hooks: [] };
|
|
745
|
+
settings.hooks[event].push(group);
|
|
746
|
+
}
|
|
747
|
+
if (!Array.isArray(group.hooks))
|
|
748
|
+
group.hooks = [];
|
|
749
|
+
// Idempotent: skip if a command-equal entry is already there.
|
|
750
|
+
if (!group.hooks.some((h) => h && h.command === hook.command)) {
|
|
751
|
+
group.hooks.push({ ...hook });
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
const afterJson = JSON.stringify(settings);
|
|
755
|
+
if (beforeJson === afterJson && !created) {
|
|
756
|
+
return { path: file, action: 'unchanged' };
|
|
757
|
+
}
|
|
758
|
+
(0, shared_1.writeJsonFile)(file, settings);
|
|
759
|
+
return { path: file, action: created ? 'created' : 'updated' };
|
|
760
|
+
}
|
|
761
|
+
/** True when a hook command is the SDD nudge (`specship spec-nudge`). Uninstall-only. */
|
|
762
|
+
function isSddHookCommand(command) {
|
|
763
|
+
if (typeof command !== 'string')
|
|
764
|
+
return false;
|
|
765
|
+
return SPECSHIP_SDD_HOOKS.some(({ hook }) => command === hook.command);
|
|
766
|
+
}
|
|
767
|
+
/** Remove the SDD nudge hook written by `writeSddHookEntry`. Uninstall-only. */
|
|
768
|
+
function cleanupSddHooks(loc) {
|
|
769
|
+
return stripHooksMatching(loc, isSddHookCommand);
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Write the spec-driven-development steering rule into the project CLAUDE.md
|
|
773
|
+
* (SDD-INSTALL-DOC, REQ-SDD-001). Idempotent + marker-delimited so the user's
|
|
774
|
+
* surrounding content is untouched and a re-run reports `unchanged`. Distinct
|
|
775
|
+
* markers from the legacy #529 block — this is the ordering rule, not the MCP
|
|
776
|
+
* playbook.
|
|
777
|
+
*/
|
|
778
|
+
function writeSddInstructionsEntry(loc) {
|
|
779
|
+
const file = claudeMdPath(loc);
|
|
780
|
+
const action = (0, shared_1.upsertMarkedSection)(file, instructions_template_1.SPECSHIP_SDD_SECTION_START, instructions_template_1.SPECSHIP_SDD_SECTION_END, (0, instructions_template_1.getSddRuleBlock)());
|
|
781
|
+
return { path: file, action };
|
|
782
|
+
}
|
|
783
|
+
/** Inverse of `writeSddInstructionsEntry`: strip the SDD rule block. */
|
|
784
|
+
function removeSddInstructionsEntry(loc) {
|
|
785
|
+
const file = claudeMdPath(loc);
|
|
786
|
+
const action = (0, shared_1.removeMarkedSection)(file, instructions_template_1.SPECSHIP_SDD_SECTION_START, instructions_template_1.SPECSHIP_SDD_SECTION_END);
|
|
787
|
+
return { path: file, action };
|
|
788
|
+
}
|
|
789
|
+
/**
|
|
790
|
+
* Copy our shipped slash commands (commands/ss-*.md) into the user's
|
|
791
|
+
* commands dir (~/.claude/commands/ globally, ./.claude/commands/
|
|
792
|
+
* locally). Per-file idempotent: a destination with identical bytes is
|
|
793
|
+
* reported `unchanged`. Sibling user-written .md files in the same dir
|
|
794
|
+
* are never touched.
|
|
795
|
+
*
|
|
796
|
+
* The retrieval tier is always written; the governance tier is written only
|
|
797
|
+
* when `includeGovernance` is set (INSTALL-WEDGE-DOC, REQ-WEDGE-001/002). A
|
|
798
|
+
* default install never touches the governance commands — neither writing them
|
|
799
|
+
* nor (since this only ever writes) removing any a prior opt-in left behind, so
|
|
800
|
+
* an existing governance install is preserved on upgrade (REQ-WEDGE-002.A4).
|
|
801
|
+
*/
|
|
802
|
+
function writeCommandsEntries(loc, includeGovernance = false) {
|
|
803
|
+
const cmds = includeGovernance ? SHIPPED_COMMANDS : RETRIEVAL_TIER_COMMANDS;
|
|
804
|
+
return cmds.map((name) => copyAsset(packageAssetPath('commands', name), path.join(commandsDir(loc), name)));
|
|
805
|
+
}
|
|
806
|
+
/**
|
|
807
|
+
* Remove legacy `cg-*.md` slash commands left behind by a pre-v0.2
|
|
808
|
+
* installer. Called from `install()` so an upgrade self-heals (the user
|
|
809
|
+
* doesn't end up with both prefixes side-by-side cluttering their
|
|
810
|
+
* autocomplete) and from `uninstall()` so the legacy files don't
|
|
811
|
+
* persist after specship is removed. Sibling user-written .md files
|
|
812
|
+
* in the same dir are never touched — only the exact filenames in
|
|
813
|
+
* LEGACY_SHIPPED_COMMANDS are candidates.
|
|
814
|
+
*/
|
|
815
|
+
function cleanupLegacyCommandsEntries(loc) {
|
|
816
|
+
return LEGACY_SHIPPED_COMMANDS
|
|
817
|
+
.map((name) => removeFile(path.join(commandsDir(loc), name)))
|
|
818
|
+
// Only surface files that actually existed and got removed — keeps
|
|
819
|
+
// the install/uninstall log quiet for users who never had the
|
|
820
|
+
// legacy `cg-*` prefix on disk.
|
|
821
|
+
.filter((entry) => entry.action === 'removed');
|
|
822
|
+
}
|
|
823
|
+
/**
|
|
824
|
+
* Copy our shipped subagent (agents/specship-explorer.md) into the
|
|
825
|
+
* user's agents dir. Same idempotency contract as writeCommandsEntries.
|
|
826
|
+
*/
|
|
827
|
+
function writeAgentsEntries(loc) {
|
|
828
|
+
return SHIPPED_AGENTS.map((name) => copyAsset(packageAssetPath('agents', name), path.join(agentsDir(loc), name)));
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* Inverse of writeCommandsEntries: delete each cg-*.md we shipped, if
|
|
832
|
+
* present. A file the user replaced with their own content is still
|
|
833
|
+
* removed — match the existing uninstall posture for files specship
|
|
834
|
+
* owns (the user can re-add their version after).
|
|
835
|
+
*/
|
|
836
|
+
function removeCommandsEntries(loc) {
|
|
837
|
+
return SHIPPED_COMMANDS.map((name) => removeFile(path.join(commandsDir(loc), name)));
|
|
838
|
+
}
|
|
839
|
+
/** Inverse of writeAgentsEntries. */
|
|
840
|
+
function removeAgentsEntries(loc) {
|
|
841
|
+
return SHIPPED_AGENTS.map((name) => removeFile(path.join(agentsDir(loc), name)));
|
|
842
|
+
}
|
|
843
|
+
function copyAsset(src, dest) {
|
|
844
|
+
const body = fs.readFileSync(src, 'utf-8');
|
|
845
|
+
if (fs.existsSync(dest)) {
|
|
846
|
+
const existing = fs.readFileSync(dest, 'utf-8');
|
|
847
|
+
if (existing === body)
|
|
848
|
+
return { path: dest, action: 'unchanged' };
|
|
849
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
850
|
+
fs.writeFileSync(dest, body);
|
|
851
|
+
return { path: dest, action: 'updated' };
|
|
852
|
+
}
|
|
853
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
854
|
+
fs.writeFileSync(dest, body);
|
|
855
|
+
return { path: dest, action: 'created' };
|
|
856
|
+
}
|
|
857
|
+
function removeFile(p) {
|
|
858
|
+
if (!fs.existsSync(p))
|
|
859
|
+
return { path: p, action: 'not-found' };
|
|
860
|
+
fs.unlinkSync(p);
|
|
861
|
+
return { path: p, action: 'removed' };
|
|
862
|
+
}
|
|
863
|
+
exports.claudeTarget = new ClaudeCodeTarget();
|
|
864
|
+
//# sourceMappingURL=claude.js.map
|