@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
|
Binary file
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GET /api/events — cross-project alert stream (REQ-PWA-002).
|
|
3
|
+
*
|
|
4
|
+
* A single SSE stream that watches EVERY initialized project (not just the
|
|
5
|
+
* selected one) and emits an event when an alert-worthy transition happens:
|
|
6
|
+
* - `approval` — a workflow run entered `paused` (an approval gate)
|
|
7
|
+
* - `runDone` — a run entered `completed` or `failed`
|
|
8
|
+
* - `drift` — a spec→code link newly entered drifted/broken/orphaned
|
|
9
|
+
*
|
|
10
|
+
* Polls the same SQLite the executor/resolver write to (mirrors the workflow
|
|
11
|
+
* SSE's 500ms-poll approach), diffing against per-connection seen-state so only
|
|
12
|
+
* NEW transitions are emitted — never a backlog burst on connect, never a repeat
|
|
13
|
+
* for the same transition. The client (NotificationsService) turns these into
|
|
14
|
+
* desktop notifications, gated on permission + per-type toggles.
|
|
15
|
+
*/
|
|
16
|
+
import os from 'node:os';
|
|
17
|
+
import path from 'node:path';
|
|
18
|
+
import { enumerate } from './projects.js';
|
|
19
|
+
const POLL_MS = 3000;
|
|
20
|
+
const KEEPALIVE_MS = 15000;
|
|
21
|
+
// Reflection sweep cadence — high-severity-only, roughly daily (REQ-REFLECT-006).
|
|
22
|
+
// The persisted reflect_proposals store dedupes across sweeps/connections, so a
|
|
23
|
+
// proposal is only ever notified once regardless of how often the sweep runs.
|
|
24
|
+
const SWEEP_MS = 24 * 60 * 60 * 1000;
|
|
25
|
+
export async function registerEventsRoutes(app) {
|
|
26
|
+
const claudeRoot = path.join(os.homedir(), '.claude', 'projects');
|
|
27
|
+
app.get('/api/events', async (req, reply) => {
|
|
28
|
+
reply.raw.setHeader('Content-Type', 'text/event-stream');
|
|
29
|
+
reply.raw.setHeader('Cache-Control', 'no-cache');
|
|
30
|
+
reply.raw.setHeader('Connection', 'keep-alive');
|
|
31
|
+
reply.raw.write(': connected\n\n');
|
|
32
|
+
// Per-connection seen-state — emit only NEW transitions.
|
|
33
|
+
const lastStatus = new Map(); // `${slug}:${runId}` -> status
|
|
34
|
+
const seenDrift = new Set(); // `${slug}:${linkId}`
|
|
35
|
+
const lastSweep = new Map(); // slug -> last reflection sweep ms
|
|
36
|
+
let primed = false; // first pass seeds state silently (no burst on connect)
|
|
37
|
+
let closed = false;
|
|
38
|
+
const send = (ev) => {
|
|
39
|
+
if (closed)
|
|
40
|
+
return;
|
|
41
|
+
try {
|
|
42
|
+
reply.raw.write(`data: ${JSON.stringify(ev)}\n\n`);
|
|
43
|
+
}
|
|
44
|
+
catch { /* peer gone */ }
|
|
45
|
+
};
|
|
46
|
+
const poll = async () => {
|
|
47
|
+
let projects;
|
|
48
|
+
try {
|
|
49
|
+
projects = await enumerate(claudeRoot);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
for (const p of projects) {
|
|
55
|
+
if (!p.initialized || closed)
|
|
56
|
+
continue;
|
|
57
|
+
let cg;
|
|
58
|
+
try {
|
|
59
|
+
cg = await app.projects.getBySlug(p.slug);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
cg = null;
|
|
63
|
+
}
|
|
64
|
+
if (!cg)
|
|
65
|
+
continue;
|
|
66
|
+
const sq = cg.getSpecQueries();
|
|
67
|
+
// Workflow run transitions.
|
|
68
|
+
let runs = [];
|
|
69
|
+
try {
|
|
70
|
+
runs = sq.getAllWorkflowRuns(50);
|
|
71
|
+
}
|
|
72
|
+
catch { /* ignore */ }
|
|
73
|
+
for (const r of runs) {
|
|
74
|
+
const key = `${p.slug}:${r.id}`;
|
|
75
|
+
if (lastStatus.get(key) === r.status)
|
|
76
|
+
continue;
|
|
77
|
+
lastStatus.set(key, r.status);
|
|
78
|
+
if (!primed)
|
|
79
|
+
continue;
|
|
80
|
+
if (r.status === 'paused') {
|
|
81
|
+
send({ kind: 'approval', project: p.slug, projectPath: p.path, id: r.id, title: 'Run needs approval', detail: r.workflowName });
|
|
82
|
+
}
|
|
83
|
+
else if (r.status === 'completed' || r.status === 'failed') {
|
|
84
|
+
send({ kind: 'runDone', project: p.slug, projectPath: p.path, id: r.id, title: `Run ${r.status}`, detail: r.workflowName, status: r.status });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Newly-drifted links.
|
|
88
|
+
let links = [];
|
|
89
|
+
try {
|
|
90
|
+
links = sq.getLinksByState(['drifted', 'broken', 'orphaned']);
|
|
91
|
+
}
|
|
92
|
+
catch { /* ignore */ }
|
|
93
|
+
for (const l of links) {
|
|
94
|
+
const key = `${p.slug}:${l.id}`;
|
|
95
|
+
if (seenDrift.has(key))
|
|
96
|
+
continue;
|
|
97
|
+
seenDrift.add(key);
|
|
98
|
+
if (!primed)
|
|
99
|
+
continue;
|
|
100
|
+
send({ kind: 'drift', project: p.slug, projectPath: p.path, id: String(l.id), title: 'Drift detected', detail: `${l.specId} → ${l.targetQualifiedName}` });
|
|
101
|
+
}
|
|
102
|
+
// Reflection sweep — throttled to ~daily. Notifies only on NEW
|
|
103
|
+
// high-severity proposals; the persisted store dedupes, so this is NOT
|
|
104
|
+
// gated on `primed` (a brand-new finding should alert even on connect,
|
|
105
|
+
// while an already-seen one never re-fires regardless of connection).
|
|
106
|
+
const now = Date.now();
|
|
107
|
+
if (now - (lastSweep.get(p.slug) ?? 0) >= SWEEP_MS) {
|
|
108
|
+
lastSweep.set(p.slug, now);
|
|
109
|
+
try {
|
|
110
|
+
const res = cg.reflectSweep();
|
|
111
|
+
for (const prop of res.notify) {
|
|
112
|
+
send({ kind: 'reflect', project: p.slug, projectPath: p.path, id: prop.contentHash, title: prop.title, detail: prop.evidence.detail });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch { /* ignore — a sweep failure must not break the stream */ }
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
primed = true;
|
|
119
|
+
};
|
|
120
|
+
await poll(); // prime: seed seen-state without emitting
|
|
121
|
+
const pollTimer = setInterval(() => { void poll(); }, POLL_MS);
|
|
122
|
+
const kaTimer = setInterval(() => { if (!closed) {
|
|
123
|
+
try {
|
|
124
|
+
reply.raw.write(': ka\n\n');
|
|
125
|
+
}
|
|
126
|
+
catch { /* noop */ }
|
|
127
|
+
} }, KEEPALIVE_MS);
|
|
128
|
+
req.raw.on('close', () => {
|
|
129
|
+
closed = true;
|
|
130
|
+
clearInterval(pollTimer);
|
|
131
|
+
clearInterval(kaTimer);
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graph routes — node detail + explore + search.
|
|
3
|
+
*
|
|
4
|
+
* These are thin wrappers around methods on a SpecShip instance. Every
|
|
5
|
+
* route resolves the active instance via `app.activeCg(req)`, which honors
|
|
6
|
+
* `?project=<slug>` and falls back to the boot-time primary. When neither
|
|
7
|
+
* is available, returns 409 / `no_project` so the desktop UI can show its
|
|
8
|
+
* project picker instead of an opaque 500.
|
|
9
|
+
*
|
|
10
|
+
* The MCP layer's `specship_*` tools are markdown-formatted for agents;
|
|
11
|
+
* here we return raw JSON so the UI can render visually.
|
|
12
|
+
*/
|
|
13
|
+
/** Returns the active SpecShip or sends a 409. */
|
|
14
|
+
async function resolveCg(app, req, reply) {
|
|
15
|
+
const cg = await app.activeCg(req);
|
|
16
|
+
if (!cg) {
|
|
17
|
+
reply.code(409).send({ error: 'no project selected', code: 'no_project' });
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
return cg;
|
|
21
|
+
}
|
|
22
|
+
/** Dig the raw SQLite handle off a SpecShip instance (same shape as routes/claude.ts). */
|
|
23
|
+
function getDb(cg) {
|
|
24
|
+
const anyCg = cg;
|
|
25
|
+
if (anyCg.db?.getDb)
|
|
26
|
+
return anyCg.db.getDb();
|
|
27
|
+
if (anyCg.queries?.db)
|
|
28
|
+
return anyCg.queries.db;
|
|
29
|
+
throw new Error('specship DB handle not accessible from server context');
|
|
30
|
+
}
|
|
31
|
+
export async function registerGraphRoutes(app) {
|
|
32
|
+
app.get('/api/graph/stats', async (req, reply) => {
|
|
33
|
+
const cg = await resolveCg(app, req, reply);
|
|
34
|
+
if (!cg)
|
|
35
|
+
return;
|
|
36
|
+
return cg.getStats();
|
|
37
|
+
});
|
|
38
|
+
/**
|
|
39
|
+
* List nodes with optional kind / file / limit filtering. For node-explorer
|
|
40
|
+
* UI surfaces that want a flat paginated list.
|
|
41
|
+
*/
|
|
42
|
+
app.get('/api/graph/nodes', async (req, reply) => {
|
|
43
|
+
const cg = await resolveCg(app, req, reply);
|
|
44
|
+
if (!cg)
|
|
45
|
+
return;
|
|
46
|
+
const limit = Math.min(Math.max(parseInt(req.query.limit ?? '100', 10) || 100, 1), 1000);
|
|
47
|
+
const offset = Math.max(parseInt(req.query.offset ?? '0', 10) || 0, 0);
|
|
48
|
+
const results = cg.searchNodes(req.query.kind ?? '', { limit: limit + offset });
|
|
49
|
+
return {
|
|
50
|
+
total: results.length,
|
|
51
|
+
offset,
|
|
52
|
+
limit,
|
|
53
|
+
nodes: results.slice(offset, offset + limit).map((r) => r.node),
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
/**
|
|
57
|
+
* GET /api/graph/node — by symbol name (with optional file/line disambiguation)
|
|
58
|
+
* or by exact id. Returns the node + callers + callees + linked specs.
|
|
59
|
+
*/
|
|
60
|
+
app.get('/api/graph/node', async (req, reply) => {
|
|
61
|
+
const cg = await resolveCg(app, req, reply);
|
|
62
|
+
if (!cg)
|
|
63
|
+
return;
|
|
64
|
+
const { symbol, id, file, line } = req.query;
|
|
65
|
+
if (!symbol && !id) {
|
|
66
|
+
return reply.code(400).send({ error: 'symbol or id is required' });
|
|
67
|
+
}
|
|
68
|
+
let matches = [];
|
|
69
|
+
if (id) {
|
|
70
|
+
const node = cg.getNode(id);
|
|
71
|
+
if (node)
|
|
72
|
+
matches = [node];
|
|
73
|
+
}
|
|
74
|
+
else if (symbol) {
|
|
75
|
+
matches = cg.searchNodes(symbol, { limit: 50 }).map((r) => r.node);
|
|
76
|
+
if (file) {
|
|
77
|
+
const f = file.toLowerCase();
|
|
78
|
+
const narrowed = matches.filter((n) => n.filePath.toLowerCase().includes(f));
|
|
79
|
+
if (narrowed.length > 0)
|
|
80
|
+
matches = narrowed;
|
|
81
|
+
}
|
|
82
|
+
if (line) {
|
|
83
|
+
const ln = parseInt(line, 10);
|
|
84
|
+
if (Number.isFinite(ln)) {
|
|
85
|
+
const containing = matches.filter((n) => n.startLine <= ln && (n.endLine ?? n.startLine) >= ln);
|
|
86
|
+
matches = containing.length > 0 ? containing : matches.slice(0, 1);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (matches.length === 0)
|
|
91
|
+
return reply.code(404).send({ error: 'not found' });
|
|
92
|
+
const enriched = matches.map((n) => {
|
|
93
|
+
const callers = cg.getCallers(n.id).map((e) => e.node);
|
|
94
|
+
const callees = cg.getCallees(n.id).map((e) => e.node);
|
|
95
|
+
const links = cg.getSpecQueries().getLinksByNode(n.id);
|
|
96
|
+
return { ...n, callers, callees, linkedSpecs: links };
|
|
97
|
+
});
|
|
98
|
+
return { matches: enriched };
|
|
99
|
+
});
|
|
100
|
+
app.post('/api/graph/explore', async (req, reply) => {
|
|
101
|
+
const cg = await resolveCg(app, req, reply);
|
|
102
|
+
if (!cg)
|
|
103
|
+
return;
|
|
104
|
+
const { query, maxFiles } = req.body ?? { query: '' };
|
|
105
|
+
if (!query)
|
|
106
|
+
return reply.code(400).send({ error: 'query is required' });
|
|
107
|
+
void maxFiles;
|
|
108
|
+
const ctx = await cg.buildContext(query, {
|
|
109
|
+
maxNodes: 80,
|
|
110
|
+
includeCode: true,
|
|
111
|
+
format: 'markdown',
|
|
112
|
+
});
|
|
113
|
+
return ctx;
|
|
114
|
+
});
|
|
115
|
+
app.get('/api/graph/search', async (req, reply) => {
|
|
116
|
+
const cg = await resolveCg(app, req, reply);
|
|
117
|
+
if (!cg)
|
|
118
|
+
return;
|
|
119
|
+
const q = req.query.q ?? '';
|
|
120
|
+
const limit = Math.min(parseInt(req.query.limit ?? '20', 10) || 20, 200);
|
|
121
|
+
if (!q)
|
|
122
|
+
return { results: [] };
|
|
123
|
+
const kinds = req.query.kind ? [req.query.kind] : undefined;
|
|
124
|
+
const results = cg.searchNodes(q, { kinds, limit });
|
|
125
|
+
return { results };
|
|
126
|
+
});
|
|
127
|
+
app.get('/api/graph/callers/:id', async (req, reply) => {
|
|
128
|
+
const cg = await resolveCg(app, req, reply);
|
|
129
|
+
if (!cg)
|
|
130
|
+
return;
|
|
131
|
+
const node = cg.getNode(req.params.id);
|
|
132
|
+
if (!node)
|
|
133
|
+
return reply.code(404).send({ error: 'node not found' });
|
|
134
|
+
return { callers: cg.getCallers(req.params.id).map((e) => e.node) };
|
|
135
|
+
});
|
|
136
|
+
app.get('/api/graph/callees/:id', async (req, reply) => {
|
|
137
|
+
const cg = await resolveCg(app, req, reply);
|
|
138
|
+
if (!cg)
|
|
139
|
+
return;
|
|
140
|
+
const node = cg.getNode(req.params.id);
|
|
141
|
+
if (!node)
|
|
142
|
+
return reply.code(404).send({ error: 'node not found' });
|
|
143
|
+
return { callees: cg.getCallees(req.params.id).map((e) => e.node) };
|
|
144
|
+
});
|
|
145
|
+
app.get('/api/graph/impact/:id', async (req, reply) => {
|
|
146
|
+
const cg = await resolveCg(app, req, reply);
|
|
147
|
+
if (!cg)
|
|
148
|
+
return;
|
|
149
|
+
const depth = Math.min(parseInt(req.query.depth ?? '2', 10) || 2, 5);
|
|
150
|
+
return { impact: cg.getImpactRadius(req.params.id, depth) };
|
|
151
|
+
});
|
|
152
|
+
app.get('/api/graph/files', async (req, reply) => {
|
|
153
|
+
const cg = await resolveCg(app, req, reply);
|
|
154
|
+
if (!cg)
|
|
155
|
+
return;
|
|
156
|
+
return { files: cg.getFiles() };
|
|
157
|
+
});
|
|
158
|
+
/**
|
|
159
|
+
* GET /api/graph/health — feeds the Graph overview panel:
|
|
160
|
+
* - linkHealth: spec-link counts per state (verified/drifted/broken/orphaned/…)
|
|
161
|
+
* - edgeKinds: edge counts grouped into calls / implements-documents / tests
|
|
162
|
+
* - hubs: the most-connected nodes (by total degree), for the "Most connected" list
|
|
163
|
+
*/
|
|
164
|
+
app.get('/api/graph/health', async (req, reply) => {
|
|
165
|
+
const cg = await resolveCg(app, req, reply);
|
|
166
|
+
if (!cg)
|
|
167
|
+
return;
|
|
168
|
+
// Spec-link health — count by state off the spec_links table.
|
|
169
|
+
const linkHealth = {};
|
|
170
|
+
for (const l of cg.getSpecQueries().getAllLinks()) {
|
|
171
|
+
linkHealth[l.state] = (linkHealth[l.state] ?? 0) + 1;
|
|
172
|
+
}
|
|
173
|
+
const db = getDb(cg);
|
|
174
|
+
// Edge kinds — bucket by the node kinds the edge connects, mirroring the
|
|
175
|
+
// design's "calls / implements / tests" legend. spec endpoints → implements,
|
|
176
|
+
// test endpoints → tests, everything else → calls.
|
|
177
|
+
const edgeKinds = db.prepare(`
|
|
178
|
+
SELECT
|
|
179
|
+
CASE
|
|
180
|
+
WHEN ns.kind = 'spec' OR nt.kind = 'spec' THEN 'implements'
|
|
181
|
+
WHEN ns.kind = 'test' OR nt.kind = 'test' THEN 'tests'
|
|
182
|
+
ELSE 'calls'
|
|
183
|
+
END as bucket,
|
|
184
|
+
COUNT(*) as count
|
|
185
|
+
FROM edges e
|
|
186
|
+
JOIN nodes ns ON ns.id = e.source
|
|
187
|
+
JOIN nodes nt ON nt.id = e.target
|
|
188
|
+
GROUP BY bucket
|
|
189
|
+
`).all();
|
|
190
|
+
const edgeKindMap = { calls: 0, implements: 0, tests: 0 };
|
|
191
|
+
for (const r of edgeKinds)
|
|
192
|
+
edgeKindMap[r.bucket] = r.count;
|
|
193
|
+
// Synthesized (heuristic) edge count — dashed in the legend.
|
|
194
|
+
const synth = db.prepare(`SELECT COUNT(*) as c FROM edges WHERE provenance = 'heuristic'`).get();
|
|
195
|
+
edgeKindMap['synth'] = synth.c ?? 0;
|
|
196
|
+
// Most-connected hubs — total degree (in + out) per node, top 8.
|
|
197
|
+
const hubs = db.prepare(`
|
|
198
|
+
SELECT n.id, n.name, n.kind, n.file_path as filePath, deg.degree
|
|
199
|
+
FROM (
|
|
200
|
+
SELECT node, COUNT(*) as degree FROM (
|
|
201
|
+
SELECT source as node FROM edges
|
|
202
|
+
UNION ALL
|
|
203
|
+
SELECT target as node FROM edges
|
|
204
|
+
) GROUP BY node ORDER BY degree DESC LIMIT 8
|
|
205
|
+
) deg
|
|
206
|
+
JOIN nodes n ON n.id = deg.node
|
|
207
|
+
ORDER BY deg.degree DESC
|
|
208
|
+
`).all();
|
|
209
|
+
return { linkHealth, edgeKinds: edgeKindMap, hubs };
|
|
210
|
+
});
|
|
211
|
+
/**
|
|
212
|
+
* Full-graph overview for the Graph page's whole-repo view. The graph can be
|
|
213
|
+
* huge (10k+ nodes) and the canvas + client-side force layout are O(n²), so
|
|
214
|
+
* we return the top-N most-connected nodes (by total degree) plus the edges
|
|
215
|
+
* among them. Isolated (degree-0) nodes are omitted — an overview shows the
|
|
216
|
+
* connected core. `total` reports the full node count so the UI can say
|
|
217
|
+
* "showing N of M".
|
|
218
|
+
*/
|
|
219
|
+
app.get('/api/graph/full', async (req, reply) => {
|
|
220
|
+
const cg = await resolveCg(app, req, reply);
|
|
221
|
+
if (!cg)
|
|
222
|
+
return;
|
|
223
|
+
const db = getDb(cg);
|
|
224
|
+
const limit = Math.min(Math.max(parseInt(req.query.limit ?? '250', 10) || 250, 1), 400);
|
|
225
|
+
const nodeRows = db.prepare(`
|
|
226
|
+
SELECT n.id, n.name, n.kind, n.file_path as filePath, deg.degree
|
|
227
|
+
FROM (
|
|
228
|
+
SELECT node, COUNT(*) as degree FROM (
|
|
229
|
+
SELECT source as node FROM edges
|
|
230
|
+
UNION ALL
|
|
231
|
+
SELECT target as node FROM edges
|
|
232
|
+
) GROUP BY node ORDER BY degree DESC LIMIT ?
|
|
233
|
+
) deg
|
|
234
|
+
JOIN nodes n ON n.id = deg.node
|
|
235
|
+
ORDER BY deg.degree DESC
|
|
236
|
+
`).all(limit);
|
|
237
|
+
const keep = new Set(nodeRows.map((n) => n.id));
|
|
238
|
+
const allEdges = db.prepare(`SELECT source as "from", target as "to", kind, provenance FROM edges`).all();
|
|
239
|
+
const edges = allEdges.filter((e) => keep.has(e.from) && keep.has(e.to));
|
|
240
|
+
const totalRow = db.prepare(`SELECT COUNT(*) as c FROM nodes`).get();
|
|
241
|
+
return {
|
|
242
|
+
nodes: nodeRows.map((n) => ({ id: n.id, name: n.name, kind: n.kind, filePath: n.filePath, degree: n.degree })),
|
|
243
|
+
edges,
|
|
244
|
+
total: totalRow.c ?? nodeRows.length,
|
|
245
|
+
shown: nodeRows.length,
|
|
246
|
+
};
|
|
247
|
+
});
|
|
248
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GET /api/maintainability (REQ-MAINT-003).
|
|
3
|
+
*
|
|
4
|
+
* Returns the active project's graph-derived maintainability report — coupling,
|
|
5
|
+
* size hotspots, dependency cycles, dead-code candidates. Project-scoped (uses
|
|
6
|
+
* the active instance, like the graph/spec routes), driven through the instance
|
|
7
|
+
* method `getMaintainability()` so the server never runtime-imports the package.
|
|
8
|
+
*/
|
|
9
|
+
export async function registerMaintainabilityRoutes(app) {
|
|
10
|
+
app.get('/api/maintainability', async (req, reply) => {
|
|
11
|
+
const cg = await app.activeCg(req);
|
|
12
|
+
if (!cg) {
|
|
13
|
+
reply.code(409).send({ error: 'no project selected', code: 'no_project' });
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
return cg.getMaintainability();
|
|
17
|
+
});
|
|
18
|
+
}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GET /api/memory — CLAUDE.md hierarchy + ~/.claude/memory notes.
|
|
3
|
+
*
|
|
4
|
+
* Walks the standard Claude Code memory locations and returns a flattened
|
|
5
|
+
* list of MemoryFile records the desktop UI can render directly. Resolves
|
|
6
|
+
* `@path` imports from each instruction file.
|
|
7
|
+
*
|
|
8
|
+
* Levels:
|
|
9
|
+
* - enterprise — `/Library/Application Support/ClaudeCode/CLAUDE.md` (read-only)
|
|
10
|
+
* - user — `~/.claude/CLAUDE.md`
|
|
11
|
+
* - project — `<projectRoot>/CLAUDE.md`
|
|
12
|
+
* - subdir — `<projectRoot>/<sub>/CLAUDE.md` (one level deep; common case)
|
|
13
|
+
* - import — files referenced as `@path` from a project/subdir CLAUDE.md
|
|
14
|
+
* - note — `~/.claude/memory/*.md` (agent-written via memory tool)
|
|
15
|
+
*/
|
|
16
|
+
import { promises as fs } from 'node:fs';
|
|
17
|
+
import path from 'node:path';
|
|
18
|
+
import os from 'node:os';
|
|
19
|
+
import { decodeProjectSlug } from '../ingest/ingestor.js';
|
|
20
|
+
const ENTERPRISE_PATHS = [
|
|
21
|
+
'/Library/Application Support/ClaudeCode/CLAUDE.md',
|
|
22
|
+
'/etc/ClaudeCode/CLAUDE.md',
|
|
23
|
+
process.env['ProgramData'] ? path.join(process.env['ProgramData'], 'ClaudeCode', 'CLAUDE.md') : '',
|
|
24
|
+
].filter(Boolean);
|
|
25
|
+
function estimateTokens(body) {
|
|
26
|
+
// Rough heuristic: ~4 chars per token. Cheap; the UI tolerates approximation.
|
|
27
|
+
return Math.max(1, Math.round(body.length / 4));
|
|
28
|
+
}
|
|
29
|
+
function relativeTime(ms) {
|
|
30
|
+
const diff = Date.now() - ms;
|
|
31
|
+
const sec = Math.round(diff / 1000);
|
|
32
|
+
if (sec < 60)
|
|
33
|
+
return `${sec}s ago`;
|
|
34
|
+
const min = Math.round(sec / 60);
|
|
35
|
+
if (min < 60)
|
|
36
|
+
return `${min}m ago`;
|
|
37
|
+
const hr = Math.round(min / 60);
|
|
38
|
+
if (hr < 24)
|
|
39
|
+
return `${hr}h ago`;
|
|
40
|
+
const day = Math.round(hr / 24);
|
|
41
|
+
if (day < 7)
|
|
42
|
+
return `${day}d ago`;
|
|
43
|
+
const d = new Date(ms);
|
|
44
|
+
return d.toLocaleDateString();
|
|
45
|
+
}
|
|
46
|
+
async function tryRead(filePath) {
|
|
47
|
+
try {
|
|
48
|
+
const [body, stat] = await Promise.all([fs.readFile(filePath, 'utf-8'), fs.stat(filePath)]);
|
|
49
|
+
return { body, modified: stat.mtimeMs };
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function extractImports(body) {
|
|
56
|
+
const out = [];
|
|
57
|
+
for (const line of body.split('\n')) {
|
|
58
|
+
const m = line.match(/^@(\S+)/);
|
|
59
|
+
if (m && m[1])
|
|
60
|
+
out.push(m[1]);
|
|
61
|
+
}
|
|
62
|
+
return out;
|
|
63
|
+
}
|
|
64
|
+
function expandHome(p) {
|
|
65
|
+
if (p.startsWith('~/'))
|
|
66
|
+
return path.join(os.homedir(), p.slice(2));
|
|
67
|
+
return p;
|
|
68
|
+
}
|
|
69
|
+
function pathForUi(absolute) {
|
|
70
|
+
const home = os.homedir();
|
|
71
|
+
if (absolute.startsWith(home + path.sep))
|
|
72
|
+
return '~/' + absolute.slice(home.length + 1);
|
|
73
|
+
return absolute;
|
|
74
|
+
}
|
|
75
|
+
function makeFile(opts) {
|
|
76
|
+
return {
|
|
77
|
+
id: opts.id,
|
|
78
|
+
level: opts.level,
|
|
79
|
+
type: opts.type,
|
|
80
|
+
name: opts.name,
|
|
81
|
+
scope: opts.scope,
|
|
82
|
+
path: pathForUi(opts.absolutePath),
|
|
83
|
+
tokens: estimateTokens(opts.body),
|
|
84
|
+
lines: opts.body.split('\n').length,
|
|
85
|
+
modified: relativeTime(opts.modifiedMs),
|
|
86
|
+
body: opts.body,
|
|
87
|
+
readOnly: opts.readOnly,
|
|
88
|
+
imports: opts.imports?.length ? opts.imports : undefined,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
async function collectEnterprise() {
|
|
92
|
+
const out = [];
|
|
93
|
+
for (const p of ENTERPRISE_PATHS) {
|
|
94
|
+
const file = await tryRead(p);
|
|
95
|
+
if (file) {
|
|
96
|
+
out.push(makeFile({
|
|
97
|
+
id: 'm-ent',
|
|
98
|
+
level: 'enterprise',
|
|
99
|
+
type: 'instruction',
|
|
100
|
+
name: 'CLAUDE.md',
|
|
101
|
+
scope: 'managed',
|
|
102
|
+
absolutePath: p,
|
|
103
|
+
body: file.body,
|
|
104
|
+
modifiedMs: file.modified,
|
|
105
|
+
readOnly: true,
|
|
106
|
+
}));
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return out;
|
|
111
|
+
}
|
|
112
|
+
async function collectUser() {
|
|
113
|
+
const p = path.join(os.homedir(), '.claude', 'CLAUDE.md');
|
|
114
|
+
const file = await tryRead(p);
|
|
115
|
+
if (!file)
|
|
116
|
+
return [];
|
|
117
|
+
return [makeFile({
|
|
118
|
+
id: 'm-user',
|
|
119
|
+
level: 'user',
|
|
120
|
+
type: 'instruction',
|
|
121
|
+
name: 'CLAUDE.md',
|
|
122
|
+
scope: '~/.claude',
|
|
123
|
+
absolutePath: p,
|
|
124
|
+
body: file.body,
|
|
125
|
+
modifiedMs: file.modified,
|
|
126
|
+
})];
|
|
127
|
+
}
|
|
128
|
+
async function collectProject(projectRoot) {
|
|
129
|
+
const out = [];
|
|
130
|
+
const proj = path.join(projectRoot, 'CLAUDE.md');
|
|
131
|
+
const projFile = await tryRead(proj);
|
|
132
|
+
const importMap = new Map();
|
|
133
|
+
if (projFile) {
|
|
134
|
+
const imports = extractImports(projFile.body);
|
|
135
|
+
const resolvedIds = [];
|
|
136
|
+
for (const imp of imports) {
|
|
137
|
+
const abs = path.isAbsolute(imp) ? imp : path.join(projectRoot, imp);
|
|
138
|
+
const sub = await tryRead(abs);
|
|
139
|
+
if (sub) {
|
|
140
|
+
const id = 'm-imp-' + Buffer.from(imp).toString('base64').replace(/=/g, '').slice(0, 10);
|
|
141
|
+
importMap.set(imp, makeFile({
|
|
142
|
+
id,
|
|
143
|
+
level: 'import',
|
|
144
|
+
type: 'import',
|
|
145
|
+
name: path.basename(abs),
|
|
146
|
+
scope: '@import',
|
|
147
|
+
absolutePath: abs,
|
|
148
|
+
body: sub.body,
|
|
149
|
+
modifiedMs: sub.modified,
|
|
150
|
+
}));
|
|
151
|
+
resolvedIds.push(id);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
out.push(makeFile({
|
|
155
|
+
id: 'm-proj',
|
|
156
|
+
level: 'project',
|
|
157
|
+
type: 'instruction',
|
|
158
|
+
name: 'CLAUDE.md',
|
|
159
|
+
scope: 'project root',
|
|
160
|
+
absolutePath: proj,
|
|
161
|
+
body: projFile.body,
|
|
162
|
+
modifiedMs: projFile.modified,
|
|
163
|
+
imports: resolvedIds,
|
|
164
|
+
}));
|
|
165
|
+
for (const im of importMap.values())
|
|
166
|
+
out.push(im);
|
|
167
|
+
}
|
|
168
|
+
// Scan one level of subdirectories for nested CLAUDE.md files. Keeps the
|
|
169
|
+
// walk cheap — going deeper would need ignoring node_modules etc.
|
|
170
|
+
try {
|
|
171
|
+
const entries = await fs.readdir(projectRoot, { withFileTypes: true });
|
|
172
|
+
for (const ent of entries) {
|
|
173
|
+
if (!ent.isDirectory())
|
|
174
|
+
continue;
|
|
175
|
+
if (ent.name.startsWith('.') || ent.name === 'node_modules' || ent.name === 'dist')
|
|
176
|
+
continue;
|
|
177
|
+
const subPath = path.join(projectRoot, ent.name, 'CLAUDE.md');
|
|
178
|
+
const sub = await tryRead(subPath);
|
|
179
|
+
if (sub) {
|
|
180
|
+
out.push(makeFile({
|
|
181
|
+
id: 'm-sub-' + ent.name,
|
|
182
|
+
level: 'subdir',
|
|
183
|
+
type: 'instruction',
|
|
184
|
+
name: 'CLAUDE.md',
|
|
185
|
+
scope: ent.name,
|
|
186
|
+
absolutePath: subPath,
|
|
187
|
+
body: sub.body,
|
|
188
|
+
modifiedMs: sub.modified,
|
|
189
|
+
}));
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
// Project root not readable — ignore, return what we already have.
|
|
195
|
+
}
|
|
196
|
+
return out;
|
|
197
|
+
}
|
|
198
|
+
async function collectNotes() {
|
|
199
|
+
const dir = path.join(os.homedir(), '.claude', 'memory');
|
|
200
|
+
const out = [];
|
|
201
|
+
let entries;
|
|
202
|
+
try {
|
|
203
|
+
entries = await fs.readdir(dir, { withFileTypes: true });
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
return out;
|
|
207
|
+
}
|
|
208
|
+
for (const ent of entries) {
|
|
209
|
+
if (!ent.isFile() || !ent.name.endsWith('.md'))
|
|
210
|
+
continue;
|
|
211
|
+
const abs = path.join(dir, ent.name);
|
|
212
|
+
const file = await tryRead(abs);
|
|
213
|
+
if (!file)
|
|
214
|
+
continue;
|
|
215
|
+
const tags = Array.from(file.body.matchAll(/#([A-Za-z][A-Za-z0-9_-]*)/g))
|
|
216
|
+
.map((m) => m[1])
|
|
217
|
+
.filter((t) => typeof t === 'string')
|
|
218
|
+
.slice(0, 6);
|
|
219
|
+
out.push(makeFile({
|
|
220
|
+
id: 'n-' + ent.name.replace(/\.md$/, ''),
|
|
221
|
+
level: 'note',
|
|
222
|
+
type: 'note',
|
|
223
|
+
name: ent.name,
|
|
224
|
+
scope: 'memory tool',
|
|
225
|
+
absolutePath: abs,
|
|
226
|
+
body: file.body,
|
|
227
|
+
modifiedMs: file.modified,
|
|
228
|
+
}));
|
|
229
|
+
if (tags.length) {
|
|
230
|
+
const last = out[out.length - 1];
|
|
231
|
+
if (last)
|
|
232
|
+
last.tags = tags;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return out;
|
|
236
|
+
}
|
|
237
|
+
export async function registerMemoryRoutes(app) {
|
|
238
|
+
app.get('/api/memory', async (req) => {
|
|
239
|
+
// Memory has three global tiers (enterprise / user / notes) and one
|
|
240
|
+
// project tier. The global tiers always render; the project tier
|
|
241
|
+
// requires a project path. We try, in order:
|
|
242
|
+
// 1. The `?project=<slug>` query arg (decoded from Claude's slug).
|
|
243
|
+
// 2. The `?projectPath=` arg if the caller has the absolute path handy.
|
|
244
|
+
// 3. The primary SpecShip's projectRoot, if configured at boot.
|
|
245
|
+
// When none is available, the response just omits the project tier
|
|
246
|
+
// (no 409 — the user can still see their global memory).
|
|
247
|
+
let projectRoot = null;
|
|
248
|
+
if (req.query.project)
|
|
249
|
+
projectRoot = decodeProjectSlug(req.query.project);
|
|
250
|
+
else if (req.query.projectPath)
|
|
251
|
+
projectRoot = req.query.projectPath;
|
|
252
|
+
else if (app.primaryCg?.getProjectRoot)
|
|
253
|
+
projectRoot = app.primaryCg.getProjectRoot();
|
|
254
|
+
const [enterprise, user, project, notes] = await Promise.all([
|
|
255
|
+
collectEnterprise(),
|
|
256
|
+
collectUser(),
|
|
257
|
+
projectRoot ? collectProject(projectRoot) : Promise.resolve([]),
|
|
258
|
+
collectNotes(),
|
|
259
|
+
]);
|
|
260
|
+
const files = [...enterprise, ...user, ...project, ...notes];
|
|
261
|
+
const resp = {
|
|
262
|
+
totalTokens: files.reduce((a, b) => a + b.tokens, 0),
|
|
263
|
+
instructionCount: files.filter((f) => f.type === 'instruction').length,
|
|
264
|
+
noteCount: files.filter((f) => f.type === 'note').length,
|
|
265
|
+
importCount: files.filter((f) => f.type === 'import').length,
|
|
266
|
+
files,
|
|
267
|
+
};
|
|
268
|
+
return resp;
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
// Re-export the helper for tests
|
|
272
|
+
export const _testing = { expandHome, pathForUi, estimateTokens, extractImports };
|