@specship/specship-win32-arm64 0.24.0 → 0.28.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/bin/specship.cmd +31 -1
- package/lib/dist/activation/cheatsheet.d.ts +17 -1
- package/lib/dist/activation/cheatsheet.d.ts.map +1 -1
- package/lib/dist/activation/cheatsheet.js +47 -3
- package/lib/dist/activation/cheatsheet.js.map +1 -1
- package/lib/dist/activation/hook-output.d.ts +80 -0
- package/lib/dist/activation/hook-output.d.ts.map +1 -0
- package/lib/dist/activation/hook-output.js +103 -0
- package/lib/dist/activation/hook-output.js.map +1 -0
- package/lib/dist/activation/search-intercept.d.ts +60 -29
- package/lib/dist/activation/search-intercept.d.ts.map +1 -1
- package/lib/dist/activation/search-intercept.js +159 -55
- package/lib/dist/activation/search-intercept.js.map +1 -1
- package/lib/dist/activation/steering.d.ts +11 -13
- package/lib/dist/activation/steering.d.ts.map +1 -1
- package/lib/dist/activation/steering.js +25 -10
- package/lib/dist/activation/steering.js.map +1 -1
- package/lib/dist/behaviour/behaviour-surface.d.ts +47 -0
- package/lib/dist/behaviour/behaviour-surface.d.ts.map +1 -1
- package/lib/dist/behaviour/behaviour-surface.js +108 -2
- package/lib/dist/behaviour/behaviour-surface.js.map +1 -1
- package/lib/dist/bin/node-version-check.d.ts +22 -7
- package/lib/dist/bin/node-version-check.d.ts.map +1 -1
- package/lib/dist/bin/node-version-check.js +39 -9
- package/lib/dist/bin/node-version-check.js.map +1 -1
- package/lib/dist/bin/specship.js +989 -116
- package/lib/dist/bin/specship.js.map +1 -1
- package/lib/dist/commands/specship/learn.md +27 -3
- package/lib/dist/commands/specship/spec.md +85 -15
- package/lib/dist/db/spec-queries.d.ts +73 -3
- package/lib/dist/db/spec-queries.d.ts.map +1 -1
- package/lib/dist/db/spec-queries.js +139 -5
- package/lib/dist/db/spec-queries.js.map +1 -1
- package/lib/dist/db/sqlite-adapter.d.ts +7 -5
- package/lib/dist/db/sqlite-adapter.d.ts.map +1 -1
- package/lib/dist/db/sqlite-adapter.js +11 -9
- package/lib/dist/db/sqlite-adapter.js.map +1 -1
- package/lib/dist/enforce/changed-files.d.ts +39 -0
- package/lib/dist/enforce/changed-files.d.ts.map +1 -0
- package/lib/dist/enforce/changed-files.js +114 -0
- package/lib/dist/enforce/changed-files.js.map +1 -0
- package/lib/dist/enforce/enforce.d.ts +53 -2
- package/lib/dist/enforce/enforce.d.ts.map +1 -1
- package/lib/dist/enforce/enforce.js +95 -8
- package/lib/dist/enforce/enforce.js.map +1 -1
- package/lib/dist/enforce/mutation.d.ts +46 -0
- package/lib/dist/enforce/mutation.d.ts.map +1 -0
- package/lib/dist/enforce/mutation.js +104 -0
- package/lib/dist/enforce/mutation.js.map +1 -0
- package/lib/dist/enforce/suppressions.d.ts +33 -0
- package/lib/dist/enforce/suppressions.d.ts.map +1 -0
- package/lib/dist/enforce/suppressions.js +159 -0
- package/lib/dist/enforce/suppressions.js.map +1 -0
- package/lib/dist/extraction/grammars.d.ts +10 -0
- package/lib/dist/extraction/grammars.d.ts.map +1 -1
- package/lib/dist/extraction/grammars.js +32 -3
- package/lib/dist/extraction/grammars.js.map +1 -1
- package/lib/dist/extraction/index.d.ts +7 -0
- package/lib/dist/extraction/index.d.ts.map +1 -1
- package/lib/dist/extraction/index.js.map +1 -1
- package/lib/dist/extraction/specs/markdown-spec-extractor.d.ts +7 -0
- package/lib/dist/extraction/specs/markdown-spec-extractor.d.ts.map +1 -1
- package/lib/dist/extraction/specs/markdown-spec-extractor.js +97 -10
- package/lib/dist/extraction/specs/markdown-spec-extractor.js.map +1 -1
- package/lib/dist/extraction/wasm/tree-sitter-pascal.wasm.gz +0 -0
- package/lib/dist/extraction/wasm/tree-sitter-scala.wasm.gz +0 -0
- package/lib/dist/graph/spec-coverage.d.ts +142 -0
- package/lib/dist/graph/spec-coverage.d.ts.map +1 -0
- package/lib/dist/graph/spec-coverage.js +276 -0
- package/lib/dist/graph/spec-coverage.js.map +1 -0
- package/lib/dist/health/smoke-check.js +2 -2
- package/lib/dist/health/smoke-check.js.map +1 -1
- package/lib/dist/index.d.ts +75 -7
- package/lib/dist/index.d.ts.map +1 -1
- package/lib/dist/index.js +191 -23
- package/lib/dist/index.js.map +1 -1
- package/lib/dist/installer/gemini-commands.d.ts +107 -0
- package/lib/dist/installer/gemini-commands.d.ts.map +1 -0
- package/lib/dist/installer/gemini-commands.js +264 -0
- package/lib/dist/installer/gemini-commands.js.map +1 -0
- package/lib/dist/installer/index.d.ts +55 -8
- package/lib/dist/installer/index.d.ts.map +1 -1
- package/lib/dist/installer/index.js +72 -53
- package/lib/dist/installer/index.js.map +1 -1
- package/lib/dist/installer/init-offer.d.ts +14 -9
- package/lib/dist/installer/init-offer.d.ts.map +1 -1
- package/lib/dist/installer/init-offer.js +13 -9
- package/lib/dist/installer/init-offer.js.map +1 -1
- package/lib/dist/installer/install-defaults.d.ts +81 -0
- package/lib/dist/installer/install-defaults.d.ts.map +1 -0
- package/lib/dist/installer/install-defaults.js +95 -0
- package/lib/dist/installer/install-defaults.js.map +1 -0
- package/lib/dist/installer/instructions-template.d.ts +22 -0
- package/lib/dist/installer/instructions-template.d.ts.map +1 -1
- package/lib/dist/installer/instructions-template.js +37 -1
- package/lib/dist/installer/instructions-template.js.map +1 -1
- package/lib/dist/installer/targets/claude.d.ts +18 -0
- package/lib/dist/installer/targets/claude.d.ts.map +1 -1
- package/lib/dist/installer/targets/claude.js +70 -23
- package/lib/dist/installer/targets/claude.js.map +1 -1
- package/lib/dist/installer/targets/gemini.d.ts +85 -12
- package/lib/dist/installer/targets/gemini.d.ts.map +1 -1
- package/lib/dist/installer/targets/gemini.js +527 -30
- package/lib/dist/installer/targets/gemini.js.map +1 -1
- package/lib/dist/installer/targets/shared.d.ts +13 -0
- package/lib/dist/installer/targets/shared.d.ts.map +1 -1
- package/lib/dist/installer/targets/shared.js +22 -4
- package/lib/dist/installer/targets/shared.js.map +1 -1
- package/lib/dist/installer/targets/types.d.ts +12 -0
- package/lib/dist/installer/targets/types.d.ts.map +1 -1
- package/lib/dist/jira/auto-publish.d.ts +71 -4
- package/lib/dist/jira/auto-publish.d.ts.map +1 -1
- package/lib/dist/jira/auto-publish.js +186 -17
- package/lib/dist/jira/auto-publish.js.map +1 -1
- package/lib/dist/jira/reconcile.d.ts +24 -1
- package/lib/dist/jira/reconcile.d.ts.map +1 -1
- package/lib/dist/jira/reconcile.js +46 -2
- package/lib/dist/jira/reconcile.js.map +1 -1
- package/lib/dist/jira/repo-config.d.ts +9 -0
- package/lib/dist/jira/repo-config.d.ts.map +1 -1
- package/lib/dist/jira/repo-config.js +11 -0
- package/lib/dist/jira/repo-config.js.map +1 -1
- package/lib/dist/jira/types.d.ts +7 -0
- package/lib/dist/jira/types.d.ts.map +1 -1
- package/lib/dist/jira/types.js.map +1 -1
- package/lib/dist/knowledge/enforce.d.ts +75 -0
- package/lib/dist/knowledge/enforce.d.ts.map +1 -0
- package/lib/dist/knowledge/enforce.js +250 -0
- package/lib/dist/knowledge/enforce.js.map +1 -0
- package/lib/dist/knowledge/facts.d.ts +33 -0
- package/lib/dist/knowledge/facts.d.ts.map +1 -0
- package/lib/dist/knowledge/facts.js +117 -0
- package/lib/dist/knowledge/facts.js.map +1 -0
- package/lib/dist/knowledge/proposals.d.ts +88 -0
- package/lib/dist/knowledge/proposals.d.ts.map +1 -0
- package/lib/dist/knowledge/proposals.js +360 -0
- package/lib/dist/knowledge/proposals.js.map +1 -0
- package/lib/dist/knowledge/stale.d.ts +64 -0
- package/lib/dist/knowledge/stale.d.ts.map +1 -0
- package/lib/dist/knowledge/stale.js +174 -0
- package/lib/dist/knowledge/stale.js.map +1 -0
- package/lib/dist/mcp/fitness-tool.d.ts +5 -6
- package/lib/dist/mcp/fitness-tool.d.ts.map +1 -1
- package/lib/dist/mcp/fitness-tool.js +0 -16
- package/lib/dist/mcp/fitness-tool.js.map +1 -1
- package/lib/dist/mcp/gemini-session.d.ts +50 -0
- package/lib/dist/mcp/gemini-session.d.ts.map +1 -0
- package/lib/dist/mcp/gemini-session.js +159 -0
- package/lib/dist/mcp/gemini-session.js.map +1 -0
- package/lib/dist/mcp/health-tool.d.ts +26 -0
- package/lib/dist/mcp/health-tool.d.ts.map +1 -0
- package/lib/dist/mcp/health-tool.js +50 -0
- package/lib/dist/mcp/health-tool.js.map +1 -0
- package/lib/dist/mcp/jira-tools.d.ts.map +1 -1
- package/lib/dist/mcp/jira-tools.js +25 -0
- package/lib/dist/mcp/jira-tools.js.map +1 -1
- package/lib/dist/mcp/maintainability-tool.d.ts +5 -7
- package/lib/dist/mcp/maintainability-tool.d.ts.map +1 -1
- package/lib/dist/mcp/maintainability-tool.js +0 -16
- package/lib/dist/mcp/maintainability-tool.js.map +1 -1
- package/lib/dist/mcp/model-context.d.ts +31 -7
- package/lib/dist/mcp/model-context.d.ts.map +1 -1
- package/lib/dist/mcp/model-context.js +70 -21
- package/lib/dist/mcp/model-context.js.map +1 -1
- package/lib/dist/mcp/proxy.d.ts.map +1 -1
- package/lib/dist/mcp/proxy.js +5 -2
- package/lib/dist/mcp/proxy.js.map +1 -1
- package/lib/dist/mcp/server-instructions.d.ts +16 -15
- package/lib/dist/mcp/server-instructions.d.ts.map +1 -1
- package/lib/dist/mcp/server-instructions.js +72 -5
- package/lib/dist/mcp/server-instructions.js.map +1 -1
- package/lib/dist/mcp/session.js +1 -1
- package/lib/dist/mcp/session.js.map +1 -1
- package/lib/dist/mcp/spec-tools.d.ts +9 -1
- package/lib/dist/mcp/spec-tools.d.ts.map +1 -1
- package/lib/dist/mcp/spec-tools.js +282 -49
- package/lib/dist/mcp/spec-tools.js.map +1 -1
- package/lib/dist/mcp/tools.d.ts +49 -9
- package/lib/dist/mcp/tools.d.ts.map +1 -1
- package/lib/dist/mcp/tools.js +210 -58
- package/lib/dist/mcp/tools.js.map +1 -1
- package/lib/dist/pulse/pulse.d.ts +93 -0
- package/lib/dist/pulse/pulse.d.ts.map +1 -0
- package/lib/dist/pulse/pulse.js +401 -0
- package/lib/dist/pulse/pulse.js.map +1 -0
- package/lib/dist/reflect/apply.d.ts.map +1 -1
- package/lib/dist/reflect/apply.js +38 -3
- package/lib/dist/reflect/apply.js.map +1 -1
- package/lib/dist/reflect/auto-sweep.d.ts +26 -0
- package/lib/dist/reflect/auto-sweep.d.ts.map +1 -0
- package/lib/dist/reflect/auto-sweep.js +90 -0
- package/lib/dist/reflect/auto-sweep.js.map +1 -0
- package/lib/dist/reflect/cli.d.ts +62 -0
- package/lib/dist/reflect/cli.d.ts.map +1 -0
- package/lib/dist/reflect/cli.js +163 -0
- package/lib/dist/reflect/cli.js.map +1 -0
- package/lib/dist/reflect/miner.d.ts.map +1 -1
- package/lib/dist/reflect/miner.js +119 -0
- package/lib/dist/reflect/miner.js.map +1 -1
- package/lib/dist/reflect/sweep.d.ts +1 -0
- package/lib/dist/reflect/sweep.d.ts.map +1 -1
- package/lib/dist/reflect/sweep.js +62 -13
- package/lib/dist/reflect/sweep.js.map +1 -1
- package/lib/dist/reflect/targets.d.ts +2 -0
- package/lib/dist/reflect/targets.d.ts.map +1 -1
- package/lib/dist/reflect/targets.js +33 -0
- package/lib/dist/reflect/targets.js.map +1 -1
- package/lib/dist/reflect/types.d.ts +19 -2
- package/lib/dist/reflect/types.d.ts.map +1 -1
- package/lib/dist/resolution/spec-link-resolver.d.ts +44 -2
- package/lib/dist/resolution/spec-link-resolver.d.ts.map +1 -1
- package/lib/dist/resolution/spec-link-resolver.js +132 -0
- package/lib/dist/resolution/spec-link-resolver.js.map +1 -1
- package/lib/dist/resolution/test-title-links.d.ts +62 -0
- package/lib/dist/resolution/test-title-links.d.ts.map +1 -0
- package/lib/dist/resolution/test-title-links.js +97 -0
- package/lib/dist/resolution/test-title-links.js.map +1 -0
- package/lib/dist/search/query-parser.d.ts.map +1 -1
- package/lib/dist/search/query-parser.js +6 -1
- package/lib/dist/search/query-parser.js.map +1 -1
- package/lib/dist/server/project-registry.js +1 -1
- package/lib/dist/server/routes/claude.js +24 -43
- package/lib/dist/server/routes/graph.js +53 -7
- package/lib/dist/server/routes/knowledge.js +118 -0
- package/lib/dist/server/routes/mcp.js +4 -3
- package/lib/dist/server/routes/projects.js +4 -4
- package/lib/dist/server/routes/spec.js +49 -7
- package/lib/dist/server/server.js +31 -17
- package/lib/dist/skills/spec-author/SKILL.md +164 -0
- package/lib/dist/skills/spec-author/references/format.md +210 -0
- package/lib/dist/skills/spec-author/references/gap-questions.md +152 -0
- package/lib/dist/skills/spec-author/references/quality-rubric.md +125 -0
- package/lib/dist/skills/spec-author/references/review-checklist.md +175 -0
- package/lib/dist/spec-lint/lint.d.ts +82 -0
- package/lib/dist/spec-lint/lint.d.ts.map +1 -0
- package/lib/dist/spec-lint/lint.js +491 -0
- package/lib/dist/spec-lint/lint.js.map +1 -0
- package/lib/dist/spec-quality/criterion-ids.d.ts +13 -0
- package/lib/dist/spec-quality/criterion-ids.d.ts.map +1 -0
- package/lib/dist/spec-quality/criterion-ids.js +38 -0
- package/lib/dist/spec-quality/criterion-ids.js.map +1 -0
- package/lib/dist/spec-quality/evidence-kind.d.ts +54 -0
- package/lib/dist/spec-quality/evidence-kind.d.ts.map +1 -0
- package/lib/dist/spec-quality/evidence-kind.js +183 -0
- package/lib/dist/spec-quality/evidence-kind.js.map +1 -0
- package/lib/dist/spec-quality/link-persist.d.ts +65 -0
- package/lib/dist/spec-quality/link-persist.d.ts.map +1 -0
- package/lib/dist/spec-quality/link-persist.js +249 -0
- package/lib/dist/spec-quality/link-persist.js.map +1 -0
- package/lib/dist/spec-quality/plan-scope.d.ts +38 -0
- package/lib/dist/spec-quality/plan-scope.d.ts.map +1 -0
- package/lib/dist/spec-quality/plan-scope.js +129 -0
- package/lib/dist/spec-quality/plan-scope.js.map +1 -0
- package/lib/dist/spec-quality/postcheck.d.ts +85 -0
- package/lib/dist/spec-quality/postcheck.d.ts.map +1 -0
- package/lib/dist/spec-quality/postcheck.js +390 -0
- package/lib/dist/spec-quality/postcheck.js.map +1 -0
- package/lib/dist/spec-quality/readiness.d.ts +72 -0
- package/lib/dist/spec-quality/readiness.d.ts.map +1 -0
- package/lib/dist/spec-quality/readiness.js +226 -0
- package/lib/dist/spec-quality/readiness.js.map +1 -0
- package/lib/dist/statusline/index.js.map +1 -1
- package/lib/dist/statusline/render.d.ts +1 -1
- package/lib/dist/statusline/render.d.ts.map +1 -1
- package/lib/dist/statusline/render.js +3 -1
- package/lib/dist/statusline/render.js.map +1 -1
- package/lib/dist/ui/assets/index-BzuUWUAE.js +50 -0
- package/lib/dist/ui/index.html +1 -1
- package/lib/dist/verify/report-ingest.d.ts +88 -0
- package/lib/dist/verify/report-ingest.d.ts.map +1 -0
- package/lib/dist/verify/report-ingest.js +269 -0
- package/lib/dist/verify/report-ingest.js.map +1 -0
- package/lib/dist/workflows/agents/claude.d.ts +16 -0
- package/lib/dist/workflows/agents/claude.d.ts.map +1 -0
- package/lib/dist/workflows/agents/claude.js +82 -0
- package/lib/dist/workflows/agents/claude.js.map +1 -0
- package/lib/dist/workflows/agents/gemini.d.ts +21 -0
- package/lib/dist/workflows/agents/gemini.d.ts.map +1 -0
- package/lib/dist/workflows/agents/gemini.js +124 -0
- package/lib/dist/workflows/agents/gemini.js.map +1 -0
- package/lib/dist/workflows/agents/index.d.ts +28 -0
- package/lib/dist/workflows/agents/index.d.ts.map +1 -0
- package/lib/dist/workflows/agents/index.js +104 -0
- package/lib/dist/workflows/agents/index.js.map +1 -0
- package/lib/dist/workflows/agents/types.d.ts +55 -0
- package/lib/dist/workflows/agents/types.d.ts.map +1 -0
- package/lib/dist/workflows/agents/types.js +46 -0
- package/lib/dist/workflows/agents/types.js.map +1 -0
- package/lib/dist/workflows/batch.d.ts +63 -0
- package/lib/dist/workflows/batch.d.ts.map +1 -0
- package/lib/dist/workflows/batch.js +151 -0
- package/lib/dist/workflows/batch.js.map +1 -0
- package/lib/dist/workflows/defaults/claude-design-implement.yaml +3 -4
- package/lib/dist/workflows/defaults/spec-author.yaml +11 -9
- package/lib/dist/workflows/defaults/spec-fix.yaml +103 -12
- package/lib/dist/workflows/defaults/spec-implement-mixed.yaml +21 -193
- package/lib/dist/workflows/defaults/spec-implement.yaml +701 -41
- package/lib/dist/workflows/defaults/spec-verify.yaml +60 -9
- package/lib/dist/workflows/discovery.d.ts +13 -0
- package/lib/dist/workflows/discovery.d.ts.map +1 -1
- package/lib/dist/workflows/discovery.js +79 -17
- package/lib/dist/workflows/discovery.js.map +1 -1
- package/lib/dist/workflows/executor.d.ts +18 -0
- package/lib/dist/workflows/executor.d.ts.map +1 -1
- package/lib/dist/workflows/executor.js +130 -33
- package/lib/dist/workflows/executor.js.map +1 -1
- package/lib/dist/workflows/gc.d.ts +50 -0
- package/lib/dist/workflows/gc.d.ts.map +1 -0
- package/lib/dist/workflows/gc.js +120 -0
- package/lib/dist/workflows/gc.js.map +1 -0
- package/lib/dist/workflows/merge-queue.d.ts +64 -0
- package/lib/dist/workflows/merge-queue.d.ts.map +1 -0
- package/lib/dist/workflows/merge-queue.js +162 -0
- package/lib/dist/workflows/merge-queue.js.map +1 -0
- package/lib/dist/workflows/runners/approval.d.ts +1 -1
- package/lib/dist/workflows/runners/approval.d.ts.map +1 -1
- package/lib/dist/workflows/runners/approval.js +11 -2
- package/lib/dist/workflows/runners/approval.js.map +1 -1
- package/lib/dist/workflows/runners/bash.d.ts +15 -0
- package/lib/dist/workflows/runners/bash.d.ts.map +1 -1
- package/lib/dist/workflows/runners/bash.js +50 -1
- package/lib/dist/workflows/runners/bash.js.map +1 -1
- package/lib/dist/workflows/runners/prompt.d.ts +16 -41
- package/lib/dist/workflows/runners/prompt.d.ts.map +1 -1
- package/lib/dist/workflows/runners/prompt.js +55 -120
- package/lib/dist/workflows/runners/prompt.js.map +1 -1
- package/lib/dist/workflows/runners/types.d.ts +12 -0
- package/lib/dist/workflows/runners/types.d.ts.map +1 -1
- package/lib/dist/workflows/schemas/workflow.d.ts +17 -0
- package/lib/dist/workflows/schemas/workflow.d.ts.map +1 -1
- package/lib/dist/workflows/schemas/workflow.js +27 -0
- package/lib/dist/workflows/schemas/workflow.js.map +1 -1
- package/lib/node_modules/.package-lock.json +1 -1
- package/lib/package.json +8 -4
- package/package.json +5 -3
- package/lib/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
- package/lib/dist/extraction/wasm/tree-sitter-scala.wasm +0 -0
- package/lib/dist/server/ingest/impact-query.js +0 -343
- package/lib/dist/server/routes/events.js +0 -152
- package/lib/dist/ui/assets/index-CjjaftDw.js +0 -50
- package/node.exe +0 -4
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External-fact staleness (KNOWLEDGE-DOC, REQ-KNOW-002 / REQ-KNOW-006.A1).
|
|
3
|
+
*
|
|
4
|
+
* An external domain fact (`type: external`) records the `version` of its
|
|
5
|
+
* `dependency` it was verified against. When the installed version differs,
|
|
6
|
+
* the fact is stale: what it says may no longer be true. A dependency that
|
|
7
|
+
* cannot be found is unverifiable — reported, never counted as fresh, but not
|
|
8
|
+
* by itself a failure.
|
|
9
|
+
*
|
|
10
|
+
* Version comparison is deliberately exact-string: a fact verified against
|
|
11
|
+
* 0.28.0 is not known to hold for 0.28.1, and semver ranges would hide that.
|
|
12
|
+
*
|
|
13
|
+
* Read-only: reads `specs/domain/` and `package.json` files, writes nothing.
|
|
14
|
+
*/
|
|
15
|
+
export interface ResolveVersionOptions {
|
|
16
|
+
/**
|
|
17
|
+
* Returns the global npm root (what `npm root -g` prints), or null. Injected
|
|
18
|
+
* by tests; the default shells out to npm once per process and caches it.
|
|
19
|
+
*/
|
|
20
|
+
globalRoot?: () => string | null;
|
|
21
|
+
}
|
|
22
|
+
export type StaleCheckOptions = ResolveVersionOptions;
|
|
23
|
+
export interface FreshFact {
|
|
24
|
+
id: string;
|
|
25
|
+
dependency: string;
|
|
26
|
+
version: string;
|
|
27
|
+
}
|
|
28
|
+
export interface StaleFact {
|
|
29
|
+
id: string;
|
|
30
|
+
dependency: string;
|
|
31
|
+
/** The version the fact was verified against. */
|
|
32
|
+
verified: string;
|
|
33
|
+
/** The version installed now. */
|
|
34
|
+
installed: string;
|
|
35
|
+
/** `path:Symbol` fixture tests to re-check (REQ-KNOW-006.A1). */
|
|
36
|
+
fixtures: string[];
|
|
37
|
+
}
|
|
38
|
+
export interface UnverifiableFact {
|
|
39
|
+
id: string;
|
|
40
|
+
dependency: string;
|
|
41
|
+
}
|
|
42
|
+
export interface StaleCheckResult {
|
|
43
|
+
fresh: FreshFact[];
|
|
44
|
+
stale: StaleFact[];
|
|
45
|
+
unverifiable: UnverifiableFact[];
|
|
46
|
+
}
|
|
47
|
+
/** `npm root -g`, run at most once per process. Null when npm is unavailable. */
|
|
48
|
+
export declare function defaultGlobalNpmRoot(): string | null;
|
|
49
|
+
/**
|
|
50
|
+
* The installed version of `dependency`: the project's `node_modules` first,
|
|
51
|
+
* then the global npm root; null when neither has it.
|
|
52
|
+
*/
|
|
53
|
+
export declare function resolveInstalledVersion(dependency: string, projectRoot: string, opts?: ResolveVersionOptions): string | null;
|
|
54
|
+
/**
|
|
55
|
+
* Compare every external fact under `<projectRoot>/specs/domain/` with the
|
|
56
|
+
* installed version of its dependency. Facts missing `dependency` or `version`
|
|
57
|
+
* are skipped (the lint reports them as errors).
|
|
58
|
+
*/
|
|
59
|
+
export declare function findStaleExternalFacts(projectRoot: string, opts?: StaleCheckOptions): StaleCheckResult;
|
|
60
|
+
/** Exit code for `knowledge stale`: non-zero when any fact is stale. Unverifiable alone passes. */
|
|
61
|
+
export declare function exitCodeForStale(result: StaleCheckResult): number;
|
|
62
|
+
/** Human-readable report for `knowledge stale`. */
|
|
63
|
+
export declare function formatStaleReport(result: StaleCheckResult): string;
|
|
64
|
+
//# sourceMappingURL=stale.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stale.d.ts","sourceRoot":"","sources":["../../src/knowledge/stale.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAOH,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,MAAM,iBAAiB,GAAG,qBAAqB,CAAC;AAEtD,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,YAAY,EAAE,gBAAgB,EAAE,CAAC;CAClC;AAID,iFAAiF;AACjF,wBAAgB,oBAAoB,IAAI,MAAM,GAAG,IAAI,CAcpD;AAaD;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,IAAI,GAAE,qBAA0B,GAC/B,MAAM,GAAG,IAAI,CAQf;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,IAAI,GAAE,iBAAsB,GAC3B,gBAAgB,CA+BlB;AAED,mGAAmG;AACnG,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAEjE;AAED,mDAAmD;AACnD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAoBlE"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* External-fact staleness (KNOWLEDGE-DOC, REQ-KNOW-002 / REQ-KNOW-006.A1).
|
|
4
|
+
*
|
|
5
|
+
* An external domain fact (`type: external`) records the `version` of its
|
|
6
|
+
* `dependency` it was verified against. When the installed version differs,
|
|
7
|
+
* the fact is stale: what it says may no longer be true. A dependency that
|
|
8
|
+
* cannot be found is unverifiable — reported, never counted as fresh, but not
|
|
9
|
+
* by itself a failure.
|
|
10
|
+
*
|
|
11
|
+
* Version comparison is deliberately exact-string: a fact verified against
|
|
12
|
+
* 0.28.0 is not known to hold for 0.28.1, and semver ranges would hide that.
|
|
13
|
+
*
|
|
14
|
+
* Read-only: reads `specs/domain/` and `package.json` files, writes nothing.
|
|
15
|
+
*/
|
|
16
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
19
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
20
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
21
|
+
}
|
|
22
|
+
Object.defineProperty(o, k2, desc);
|
|
23
|
+
}) : (function(o, m, k, k2) {
|
|
24
|
+
if (k2 === undefined) k2 = k;
|
|
25
|
+
o[k2] = m[k];
|
|
26
|
+
}));
|
|
27
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
28
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
29
|
+
}) : function(o, v) {
|
|
30
|
+
o["default"] = v;
|
|
31
|
+
});
|
|
32
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
33
|
+
var ownKeys = function(o) {
|
|
34
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
35
|
+
var ar = [];
|
|
36
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
37
|
+
return ar;
|
|
38
|
+
};
|
|
39
|
+
return ownKeys(o);
|
|
40
|
+
};
|
|
41
|
+
return function (mod) {
|
|
42
|
+
if (mod && mod.__esModule) return mod;
|
|
43
|
+
var result = {};
|
|
44
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
45
|
+
__setModuleDefault(result, mod);
|
|
46
|
+
return result;
|
|
47
|
+
};
|
|
48
|
+
})();
|
|
49
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
+
exports.defaultGlobalNpmRoot = defaultGlobalNpmRoot;
|
|
51
|
+
exports.resolveInstalledVersion = resolveInstalledVersion;
|
|
52
|
+
exports.findStaleExternalFacts = findStaleExternalFacts;
|
|
53
|
+
exports.exitCodeForStale = exitCodeForStale;
|
|
54
|
+
exports.formatStaleReport = formatStaleReport;
|
|
55
|
+
const fs = __importStar(require("fs"));
|
|
56
|
+
const path = __importStar(require("path"));
|
|
57
|
+
const child_process_1 = require("child_process");
|
|
58
|
+
const facts_1 = require("./facts");
|
|
59
|
+
let cachedGlobalRoot;
|
|
60
|
+
/** `npm root -g`, run at most once per process. Null when npm is unavailable. */
|
|
61
|
+
function defaultGlobalNpmRoot() {
|
|
62
|
+
if (cachedGlobalRoot !== undefined)
|
|
63
|
+
return cachedGlobalRoot;
|
|
64
|
+
try {
|
|
65
|
+
const out = (0, child_process_1.execFileSync)(process.platform === 'win32' ? 'npm.cmd' : 'npm', ['root', '-g'], {
|
|
66
|
+
encoding: 'utf8',
|
|
67
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
68
|
+
timeout: 10_000,
|
|
69
|
+
shell: process.platform === 'win32',
|
|
70
|
+
}).trim();
|
|
71
|
+
cachedGlobalRoot = out.length > 0 ? out : null;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
cachedGlobalRoot = null;
|
|
75
|
+
}
|
|
76
|
+
return cachedGlobalRoot;
|
|
77
|
+
}
|
|
78
|
+
function readPackageVersion(modulesDir, dependency) {
|
|
79
|
+
// `@scope/name` maps onto nested directories; path.join handles the slash.
|
|
80
|
+
const pkgPath = path.join(modulesDir, ...dependency.split('/'), 'package.json');
|
|
81
|
+
try {
|
|
82
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
83
|
+
return typeof pkg.version === 'string' && pkg.version.length > 0 ? pkg.version : null;
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The installed version of `dependency`: the project's `node_modules` first,
|
|
91
|
+
* then the global npm root; null when neither has it.
|
|
92
|
+
*/
|
|
93
|
+
function resolveInstalledVersion(dependency, projectRoot, opts = {}) {
|
|
94
|
+
const dep = dependency.trim();
|
|
95
|
+
if (dep.length === 0 || dep.includes('..'))
|
|
96
|
+
return null;
|
|
97
|
+
const local = readPackageVersion(path.join(projectRoot, 'node_modules'), dep);
|
|
98
|
+
if (local)
|
|
99
|
+
return local;
|
|
100
|
+
const globalRoot = (opts.globalRoot ?? defaultGlobalNpmRoot)();
|
|
101
|
+
if (!globalRoot)
|
|
102
|
+
return null;
|
|
103
|
+
return readPackageVersion(globalRoot, dep);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Compare every external fact under `<projectRoot>/specs/domain/` with the
|
|
107
|
+
* installed version of its dependency. Facts missing `dependency` or `version`
|
|
108
|
+
* are skipped (the lint reports them as errors).
|
|
109
|
+
*/
|
|
110
|
+
function findStaleExternalFacts(projectRoot, opts = {}) {
|
|
111
|
+
const result = { fresh: [], stale: [], unverifiable: [] };
|
|
112
|
+
// Resolve the global root lazily and at most once for the whole run.
|
|
113
|
+
let globalRoot;
|
|
114
|
+
const memoGlobal = () => {
|
|
115
|
+
if (globalRoot === undefined)
|
|
116
|
+
globalRoot = (opts.globalRoot ?? defaultGlobalNpmRoot)();
|
|
117
|
+
return globalRoot;
|
|
118
|
+
};
|
|
119
|
+
for (const fact of (0, facts_1.loadDomainFacts)(projectRoot)) {
|
|
120
|
+
if (fact.type !== 'external')
|
|
121
|
+
continue;
|
|
122
|
+
const dependency = typeof fact.metadata.dependency === 'string' ? fact.metadata.dependency.trim() : '';
|
|
123
|
+
const rawVersion = fact.metadata.version;
|
|
124
|
+
const verified = typeof rawVersion === 'string' || typeof rawVersion === 'number' ? String(rawVersion).trim() : '';
|
|
125
|
+
if (!dependency || !verified)
|
|
126
|
+
continue;
|
|
127
|
+
const installed = resolveInstalledVersion(dependency, projectRoot, { globalRoot: memoGlobal });
|
|
128
|
+
if (installed === null) {
|
|
129
|
+
result.unverifiable.push({ id: fact.id, dependency });
|
|
130
|
+
}
|
|
131
|
+
else if (installed === verified) {
|
|
132
|
+
result.fresh.push({ id: fact.id, dependency, version: verified });
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
result.stale.push({
|
|
136
|
+
id: fact.id,
|
|
137
|
+
dependency,
|
|
138
|
+
verified,
|
|
139
|
+
installed,
|
|
140
|
+
fixtures: (0, facts_1.parseFixtureList)(fact.metadata.fixture),
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return result;
|
|
145
|
+
}
|
|
146
|
+
/** Exit code for `knowledge stale`: non-zero when any fact is stale. Unverifiable alone passes. */
|
|
147
|
+
function exitCodeForStale(result) {
|
|
148
|
+
return result.stale.length > 0 ? 1 : 0;
|
|
149
|
+
}
|
|
150
|
+
/** Human-readable report for `knowledge stale`. */
|
|
151
|
+
function formatStaleReport(result) {
|
|
152
|
+
const total = result.fresh.length + result.stale.length + result.unverifiable.length;
|
|
153
|
+
if (total === 0)
|
|
154
|
+
return 'Knowledge stale: no external facts in specs/domain/.';
|
|
155
|
+
const out = [
|
|
156
|
+
`Knowledge stale: ${result.stale.length} stale, ${result.unverifiable.length} unverifiable, ${result.fresh.length} fresh (of ${total} external fact${total === 1 ? '' : 's'}).`,
|
|
157
|
+
];
|
|
158
|
+
if (result.stale.length > 0) {
|
|
159
|
+
out.push('', 'Stale:');
|
|
160
|
+
for (const s of result.stale) {
|
|
161
|
+
out.push(` ${s.id} ${s.dependency}: verified ${s.verified}, installed ${s.installed}`);
|
|
162
|
+
if (s.fixtures.length > 0) {
|
|
163
|
+
out.push(` re-check fixtures: ${s.fixtures.join(', ')}`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (result.unverifiable.length > 0) {
|
|
168
|
+
out.push('', 'Unverifiable (dependency not installed locally or globally):');
|
|
169
|
+
for (const u of result.unverifiable)
|
|
170
|
+
out.push(` ${u.id} ${u.dependency}`);
|
|
171
|
+
}
|
|
172
|
+
return out.join('\n');
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=stale.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stale.js","sourceRoot":"","sources":["../../src/knowledge/stale.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDH,oDAcC;AAiBD,0DAYC;AAOD,wDAkCC;AAGD,4CAEC;AAGD,8CAoBC;AA9JD,uCAAyB;AACzB,2CAA6B;AAC7B,iDAA6C;AAC7C,mCAA4D;AAwC5D,IAAI,gBAA2C,CAAC;AAEhD,iFAAiF;AACjF,SAAgB,oBAAoB;IAClC,IAAI,gBAAgB,KAAK,SAAS;QAAE,OAAO,gBAAgB,CAAC;IAC5D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAA,4BAAY,EAAC,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE;YACzF,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;YACnC,OAAO,EAAE,MAAM;YACf,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO;SACpC,CAAC,CAAC,IAAI,EAAE,CAAC;QACV,gBAAgB,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,gBAAgB,GAAG,IAAI,CAAC;IAC1B,CAAC;IACD,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED,SAAS,kBAAkB,CAAC,UAAkB,EAAE,UAAkB;IAChE,2EAA2E;IAC3E,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,cAAc,CAAC,CAAC;IAChF,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAA0B,CAAC;QAClF,OAAO,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IACxF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAgB,uBAAuB,CACrC,UAAkB,EAClB,WAAmB,EACnB,OAA8B,EAAE;IAEhC,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACxD,MAAM,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE,GAAG,CAAC,CAAC;IAC9E,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC;IACxB,MAAM,UAAU,GAAG,CAAC,IAAI,CAAC,UAAU,IAAI,oBAAoB,CAAC,EAAE,CAAC;IAC/D,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IAC7B,OAAO,kBAAkB,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;AAC7C,CAAC;AAED;;;;GAIG;AACH,SAAgB,sBAAsB,CACpC,WAAmB,EACnB,OAA0B,EAAE;IAE5B,MAAM,MAAM,GAAqB,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;IAC5E,qEAAqE;IACrE,IAAI,UAAqC,CAAC;IAC1C,MAAM,UAAU,GAAG,GAAG,EAAE;QACtB,IAAI,UAAU,KAAK,SAAS;YAAE,UAAU,GAAG,CAAC,IAAI,CAAC,UAAU,IAAI,oBAAoB,CAAC,EAAE,CAAC;QACvF,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;IACF,KAAK,MAAM,IAAI,IAAI,IAAA,uBAAe,EAAC,WAAW,CAAC,EAAE,CAAC;QAChD,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU;YAAE,SAAS;QACvC,MAAM,UAAU,GAAG,OAAO,IAAI,CAAC,QAAQ,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvG,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;QACzC,MAAM,QAAQ,GACZ,OAAO,UAAU,KAAK,QAAQ,IAAI,OAAO,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpG,IAAI,CAAC,UAAU,IAAI,CAAC,QAAQ;YAAE,SAAS;QACvC,MAAM,SAAS,GAAG,uBAAuB,CAAC,UAAU,EAAE,WAAW,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAC;QAC/F,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;QACxD,CAAC;aAAM,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;YAClC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;QACpE,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;gBAChB,EAAE,EAAE,IAAI,CAAC,EAAE;gBACX,UAAU;gBACV,QAAQ;gBACR,SAAS;gBACT,QAAQ,EAAE,IAAA,wBAAgB,EAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;aAClD,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,mGAAmG;AACnG,SAAgB,gBAAgB,CAAC,MAAwB;IACvD,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,mDAAmD;AACnD,SAAgB,iBAAiB,CAAC,MAAwB;IACxD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC;IACrF,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,sDAAsD,CAAC;IAC/E,MAAM,GAAG,GAAa;QACpB,oBAAoB,MAAM,CAAC,KAAK,CAAC,MAAM,WAAW,MAAM,CAAC,YAAY,CAAC,MAAM,kBAAkB,MAAM,CAAC,KAAK,CAAC,MAAM,cAAc,KAAK,iBAAiB,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI;KAChL,CAAC;IACF,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QACvB,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YAC7B,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,UAAU,cAAc,CAAC,CAAC,QAAQ,eAAe,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC;YACzF,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,GAAG,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC9D,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,8DAA8D,CAAC,CAAC;QAC7E,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,YAAY;YAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC"}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Architecture-fitness report handler (REQ-FITNESS-003.A3).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* The menu slot moved to the merged `specship_health` (REQ-SURF-007); this
|
|
5
|
+
* handler stays so `execute()` keeps answering clients holding a cached
|
|
6
|
+
* `specship_fitness` tool list.
|
|
7
7
|
*/
|
|
8
8
|
import type { SpecShip } from '../index';
|
|
9
|
-
import type {
|
|
10
|
-
export declare const fitnessToolDefinitions: ToolDefinition[];
|
|
9
|
+
import type { ToolResult } from './tools';
|
|
11
10
|
export declare function handleSpecshipFitness(cg: SpecShip, _args: Record<string, unknown>): Promise<ToolResult>;
|
|
12
11
|
//# sourceMappingURL=fitness-tool.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fitness-tool.d.ts","sourceRoot":"","sources":["../../src/mcp/fitness-tool.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"fitness-tool.d.ts","sourceRoot":"","sources":["../../src/mcp/fitness-tool.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAM1C,wBAAsB,qBAAqB,CACzC,EAAE,EAAE,QAAQ,EACZ,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,OAAO,CAAC,UAAU,CAAC,CAqBrB"}
|
|
@@ -1,22 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.fitnessToolDefinitions = void 0;
|
|
4
3
|
exports.handleSpecshipFitness = handleSpecshipFitness;
|
|
5
|
-
exports.fitnessToolDefinitions = [
|
|
6
|
-
{
|
|
7
|
-
name: 'specship_fitness',
|
|
8
|
-
description: 'Evaluate the project\'s architecture-fitness rules (specship.config.json `fitness.rules`) against the code graph: forbidden dependencies, layering allow-lists, module isolation. Returns concrete violations (source → target, file:line) plus config errors (a rule whose selector matches nothing). Use to check architecture conformance before committing.',
|
|
9
|
-
inputSchema: {
|
|
10
|
-
type: 'object',
|
|
11
|
-
properties: {
|
|
12
|
-
projectPath: {
|
|
13
|
-
type: 'string',
|
|
14
|
-
description: 'Path to a different project with .specship/ initialized. Omit for the current project.',
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
];
|
|
20
4
|
const text = (body) => ({ content: [{ type: 'text', text: body }] });
|
|
21
5
|
const CAP = 30;
|
|
22
6
|
async function handleSpecshipFitness(cg, _args) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fitness-tool.js","sourceRoot":"","sources":["../../src/mcp/fitness-tool.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fitness-tool.js","sourceRoot":"","sources":["../../src/mcp/fitness-tool.ts"],"names":[],"mappings":";;AAcA,sDAwBC;AA5BD,MAAM,IAAI,GAAG,CAAC,IAAY,EAAc,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;AAEzF,MAAM,GAAG,GAAG,EAAE,CAAC;AAER,KAAK,UAAU,qBAAqB,CACzC,EAAY,EACZ,KAA8B;IAE9B,MAAM,CAAC,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC;IAC1B,IAAI,CAAC,CAAC,SAAS,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC,2IAA2I,CAAC,CAAC;IAC3J,CAAC;IACD,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC,mCAAmC,CAAC,CAAC,SAAS,gBAAgB,CAAC,CAAC;IAC9E,CAAC;IACD,MAAM,KAAK,GAAa,CAAC,wBAAwB,CAAC,CAAC;IACnD,IAAI,CAAC,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,qBAAqB,CAAC,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;QAC9D,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,YAAY;YAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,kBAAkB,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;QACzD,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;YAC3C,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,MAAM,UAAU,CAAC,CAAC,MAAM,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC;QAC9F,CAAC;QACD,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,GAAG;YAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC;IACxF,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAChC,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gemini CLI session model detection (LOWEND-DOC, REQ-LOWEND-001).
|
|
3
|
+
*
|
|
4
|
+
* All three existing tier-detection channels — the status-line marker, the
|
|
5
|
+
* SessionStart hook seed, and the transcript tail — are Claude Code plumbing.
|
|
6
|
+
* The Gemini target is MCP-entry-only (no hooks, no status line), so a Gemini
|
|
7
|
+
* CLI session has to be read **in-server** from Gemini CLI's own configuration
|
|
8
|
+
* surface:
|
|
9
|
+
*
|
|
10
|
+
* GEMINI_MODEL (Gemini CLI's own env knob)
|
|
11
|
+
* <cwd>/.gemini/settings.json — project, wins over global
|
|
12
|
+
* <homedir>/.gemini/settings.json — global
|
|
13
|
+
*
|
|
14
|
+
* Gemini CLI has shipped both `"model": "gemini-3.5-flash"` and
|
|
15
|
+
* `"model": { "name": "gemini-3.5-flash" }`, so both shapes are accepted.
|
|
16
|
+
* Every read is best-effort: a missing file, malformed JSON, or a non-string
|
|
17
|
+
* model yields `null` and the caller falls back to `full` — detection must
|
|
18
|
+
* never error a tool call (REQ-LOWEND-001.A4).
|
|
19
|
+
*
|
|
20
|
+
* This module deliberately does NOT import the Gemini installer target: the
|
|
21
|
+
* MCP read path must not depend on installer code. The paths mirror what that
|
|
22
|
+
* target documents (Storage.getWorkspaceSettingsPath / getGlobalSettingsPath).
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* Gemini CLI's settings files for a workspace, project first (project settings
|
|
26
|
+
* override global ones, same as Gemini CLI's own precedence).
|
|
27
|
+
*/
|
|
28
|
+
export declare function geminiSettingsPaths(cwd: string, homedir?: string): string[];
|
|
29
|
+
/** Test seam — drops the parse cache. */
|
|
30
|
+
export declare function __resetGeminiCache(): void;
|
|
31
|
+
/**
|
|
32
|
+
* Host gate: the Gemini leg may only run inside a server that Gemini CLI
|
|
33
|
+
* launched. The Gemini installer target stamps `SPECSHIP_HOST=gemini` into
|
|
34
|
+
* the `mcpServers.specship` entry (written AND printed snippet), so the env
|
|
35
|
+
* is present exactly in Gemini-launched server processes. Without this gate
|
|
36
|
+
* a **Claude Code** session in a repo that happens to contain
|
|
37
|
+
* `.gemini/settings.json` (or a shell exporting `GEMINI_MODEL`) would be
|
|
38
|
+
* silently compacted during the first-prompt window before the Claude marker
|
|
39
|
+
* exists — the exact crossover REQ-MODCTX-001.A6 closes on the Claude side.
|
|
40
|
+
*/
|
|
41
|
+
export declare function isGeminiHost(env?: NodeJS.ProcessEnv): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Resolve the Gemini CLI session's model id, or null when nothing names one
|
|
44
|
+
* (REQ-LOWEND-001). Host-gated: returns null outright unless
|
|
45
|
+
* `SPECSHIP_HOST=gemini` (see `isGeminiHost`). Then env first, then project
|
|
46
|
+
* settings, then global settings — first hit wins. The returned id is
|
|
47
|
+
* verbatim; mapping it to a tier is `modelTier`'s job.
|
|
48
|
+
*/
|
|
49
|
+
export declare function readGeminiSessionModel(cwd: string, env?: NodeJS.ProcessEnv, homedir?: string): string | null;
|
|
50
|
+
//# sourceMappingURL=gemini-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini-session.d.ts","sourceRoot":"","sources":["../../src/mcp/gemini-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAMH;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,MAAqB,GAAG,MAAM,EAAE,CAKzF;AAiBD,yCAAyC;AACzC,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAmCD;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAE1E;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,MAAM,EACX,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,OAAO,GAAE,MAAqB,GAC7B,MAAM,GAAG,IAAI,CASf"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Gemini CLI session model detection (LOWEND-DOC, REQ-LOWEND-001).
|
|
4
|
+
*
|
|
5
|
+
* All three existing tier-detection channels — the status-line marker, the
|
|
6
|
+
* SessionStart hook seed, and the transcript tail — are Claude Code plumbing.
|
|
7
|
+
* The Gemini target is MCP-entry-only (no hooks, no status line), so a Gemini
|
|
8
|
+
* CLI session has to be read **in-server** from Gemini CLI's own configuration
|
|
9
|
+
* surface:
|
|
10
|
+
*
|
|
11
|
+
* GEMINI_MODEL (Gemini CLI's own env knob)
|
|
12
|
+
* <cwd>/.gemini/settings.json — project, wins over global
|
|
13
|
+
* <homedir>/.gemini/settings.json — global
|
|
14
|
+
*
|
|
15
|
+
* Gemini CLI has shipped both `"model": "gemini-3.5-flash"` and
|
|
16
|
+
* `"model": { "name": "gemini-3.5-flash" }`, so both shapes are accepted.
|
|
17
|
+
* Every read is best-effort: a missing file, malformed JSON, or a non-string
|
|
18
|
+
* model yields `null` and the caller falls back to `full` — detection must
|
|
19
|
+
* never error a tool call (REQ-LOWEND-001.A4).
|
|
20
|
+
*
|
|
21
|
+
* This module deliberately does NOT import the Gemini installer target: the
|
|
22
|
+
* MCP read path must not depend on installer code. The paths mirror what that
|
|
23
|
+
* target documents (Storage.getWorkspaceSettingsPath / getGlobalSettingsPath).
|
|
24
|
+
*/
|
|
25
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
26
|
+
if (k2 === undefined) k2 = k;
|
|
27
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
28
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
29
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
30
|
+
}
|
|
31
|
+
Object.defineProperty(o, k2, desc);
|
|
32
|
+
}) : (function(o, m, k, k2) {
|
|
33
|
+
if (k2 === undefined) k2 = k;
|
|
34
|
+
o[k2] = m[k];
|
|
35
|
+
}));
|
|
36
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
37
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
38
|
+
}) : function(o, v) {
|
|
39
|
+
o["default"] = v;
|
|
40
|
+
});
|
|
41
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
42
|
+
var ownKeys = function(o) {
|
|
43
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
44
|
+
var ar = [];
|
|
45
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
46
|
+
return ar;
|
|
47
|
+
};
|
|
48
|
+
return ownKeys(o);
|
|
49
|
+
};
|
|
50
|
+
return function (mod) {
|
|
51
|
+
if (mod && mod.__esModule) return mod;
|
|
52
|
+
var result = {};
|
|
53
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
54
|
+
__setModuleDefault(result, mod);
|
|
55
|
+
return result;
|
|
56
|
+
};
|
|
57
|
+
})();
|
|
58
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
59
|
+
exports.geminiSettingsPaths = geminiSettingsPaths;
|
|
60
|
+
exports.__resetGeminiCache = __resetGeminiCache;
|
|
61
|
+
exports.isGeminiHost = isGeminiHost;
|
|
62
|
+
exports.readGeminiSessionModel = readGeminiSessionModel;
|
|
63
|
+
const fs = __importStar(require("fs"));
|
|
64
|
+
const os = __importStar(require("os"));
|
|
65
|
+
const path = __importStar(require("path"));
|
|
66
|
+
/**
|
|
67
|
+
* Gemini CLI's settings files for a workspace, project first (project settings
|
|
68
|
+
* override global ones, same as Gemini CLI's own precedence).
|
|
69
|
+
*/
|
|
70
|
+
function geminiSettingsPaths(cwd, homedir = os.homedir()) {
|
|
71
|
+
return [
|
|
72
|
+
path.join(cwd, '.gemini', 'settings.json'),
|
|
73
|
+
path.join(homedir, '.gemini', 'settings.json'),
|
|
74
|
+
];
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Per-file parse cache keyed on path, invalidated by (mtimeMs, size).
|
|
78
|
+
* Resolution runs per tool call; one `statSync` per settings file is the whole
|
|
79
|
+
* cost on the warm path — JSON is re-parsed only when the file actually
|
|
80
|
+
* changed (REQ-LOWEND-001: "cached with invalidation, never adding
|
|
81
|
+
* perceptible latency").
|
|
82
|
+
*/
|
|
83
|
+
const cache = new Map();
|
|
84
|
+
/** Test seam — drops the parse cache. */
|
|
85
|
+
function __resetGeminiCache() {
|
|
86
|
+
cache.clear();
|
|
87
|
+
}
|
|
88
|
+
/** Pull a model id out of a parsed settings object, accepting both shapes. */
|
|
89
|
+
function modelFromSettings(parsed) {
|
|
90
|
+
if (!parsed || typeof parsed !== 'object')
|
|
91
|
+
return null;
|
|
92
|
+
const model = parsed.model;
|
|
93
|
+
if (typeof model === 'string' && model)
|
|
94
|
+
return model;
|
|
95
|
+
if (model && typeof model === 'object') {
|
|
96
|
+
const name = model.name;
|
|
97
|
+
if (typeof name === 'string' && name)
|
|
98
|
+
return name;
|
|
99
|
+
}
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
/** Read one settings file through the cache. Never throws. */
|
|
103
|
+
function readSettingsModel(filePath) {
|
|
104
|
+
try {
|
|
105
|
+
const stat = fs.statSync(filePath);
|
|
106
|
+
if (!stat.isFile())
|
|
107
|
+
return null;
|
|
108
|
+
const hit = cache.get(filePath);
|
|
109
|
+
if (hit && hit.mtimeMs === stat.mtimeMs && hit.size === stat.size)
|
|
110
|
+
return hit.model;
|
|
111
|
+
let model = null;
|
|
112
|
+
try {
|
|
113
|
+
model = modelFromSettings(JSON.parse(fs.readFileSync(filePath, 'utf-8')));
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
model = null; // malformed JSON — degrade silently
|
|
117
|
+
}
|
|
118
|
+
cache.set(filePath, { mtimeMs: stat.mtimeMs, size: stat.size, model });
|
|
119
|
+
return model;
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
cache.delete(filePath);
|
|
123
|
+
return null; // ENOENT, EACCES, a directory in the way — all just "unknown"
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Host gate: the Gemini leg may only run inside a server that Gemini CLI
|
|
128
|
+
* launched. The Gemini installer target stamps `SPECSHIP_HOST=gemini` into
|
|
129
|
+
* the `mcpServers.specship` entry (written AND printed snippet), so the env
|
|
130
|
+
* is present exactly in Gemini-launched server processes. Without this gate
|
|
131
|
+
* a **Claude Code** session in a repo that happens to contain
|
|
132
|
+
* `.gemini/settings.json` (or a shell exporting `GEMINI_MODEL`) would be
|
|
133
|
+
* silently compacted during the first-prompt window before the Claude marker
|
|
134
|
+
* exists — the exact crossover REQ-MODCTX-001.A6 closes on the Claude side.
|
|
135
|
+
*/
|
|
136
|
+
function isGeminiHost(env = process.env) {
|
|
137
|
+
return env.SPECSHIP_HOST === 'gemini';
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Resolve the Gemini CLI session's model id, or null when nothing names one
|
|
141
|
+
* (REQ-LOWEND-001). Host-gated: returns null outright unless
|
|
142
|
+
* `SPECSHIP_HOST=gemini` (see `isGeminiHost`). Then env first, then project
|
|
143
|
+
* settings, then global settings — first hit wins. The returned id is
|
|
144
|
+
* verbatim; mapping it to a tier is `modelTier`'s job.
|
|
145
|
+
*/
|
|
146
|
+
function readGeminiSessionModel(cwd, env = process.env, homedir = os.homedir()) {
|
|
147
|
+
if (!isGeminiHost(env))
|
|
148
|
+
return null;
|
|
149
|
+
const fromEnv = env.GEMINI_MODEL;
|
|
150
|
+
if (typeof fromEnv === 'string' && fromEnv.trim())
|
|
151
|
+
return fromEnv;
|
|
152
|
+
for (const p of geminiSettingsPaths(cwd, homedir)) {
|
|
153
|
+
const model = readSettingsModel(p);
|
|
154
|
+
if (model)
|
|
155
|
+
return model;
|
|
156
|
+
}
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=gemini-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini-session.js","sourceRoot":"","sources":["../../src/mcp/gemini-session.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUH,kDAKC;AAkBD,gDAEC;AA6CD,oCAEC;AASD,wDAaC;AAtGD,uCAAyB;AACzB,uCAAyB;AACzB,2CAA6B;AAE7B;;;GAGG;AACH,SAAgB,mBAAmB,CAAC,GAAW,EAAE,UAAkB,EAAE,CAAC,OAAO,EAAE;IAC7E,OAAO;QACL,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,eAAe,CAAC;QAC1C,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,eAAe,CAAC;KAC/C,CAAC;AACJ,CAAC;AAQD;;;;;;GAMG;AACH,MAAM,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAC;AAE5C,yCAAyC;AACzC,SAAgB,kBAAkB;IAChC,KAAK,CAAC,KAAK,EAAE,CAAC;AAChB,CAAC;AAED,8EAA8E;AAC9E,SAAS,iBAAiB,CAAC,MAAe;IACxC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACvD,MAAM,KAAK,GAAI,MAA8B,CAAC,KAAK,CAAC;IACpD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC;IACrD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,IAAI,GAAI,KAA4B,CAAC,IAAI,CAAC;QAChD,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC;IACpD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,8DAA8D;AAC9D,SAAS,iBAAiB,CAAC,QAAgB;IACzC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;YAAE,OAAO,IAAI,CAAC;QAChC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAChC,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO,IAAI,GAAG,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI;YAAE,OAAO,GAAG,CAAC,KAAK,CAAC;QACpF,IAAI,KAAK,GAAkB,IAAI,CAAC;QAChC,IAAI,CAAC;YACH,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;QAC5E,CAAC;QAAC,MAAM,CAAC;YACP,KAAK,GAAG,IAAI,CAAC,CAAC,oCAAoC;QACpD,CAAC;QACD,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACvE,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACvB,OAAO,IAAI,CAAC,CAAC,8DAA8D;IAC7E,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,YAAY,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC/D,OAAO,GAAG,CAAC,aAAa,KAAK,QAAQ,CAAC;AACxC,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,sBAAsB,CACpC,GAAW,EACX,MAAyB,OAAO,CAAC,GAAG,EACpC,UAAkB,EAAE,CAAC,OAAO,EAAE;IAE9B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,MAAM,OAAO,GAAG,GAAG,CAAC,YAAY,CAAC;IACjC,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,EAAE;QAAE,OAAO,OAAO,CAAC;IAClE,KAAK,MAAM,CAAC,IAAI,mBAAmB,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,CAAC;QAClD,MAAM,KAAK,GAAG,iBAAiB,CAAC,CAAC,CAAC,CAAC;QACnC,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;IAC1B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool: specship_health (REQ-SURF-007).
|
|
3
|
+
*
|
|
4
|
+
* One code-health door. Folds the former `specship_maintainability`
|
|
5
|
+
* (MAINT-DOC) and `specship_fitness` (FITNESS-DOC) tools into a single surface
|
|
6
|
+
* with a `checks` filter — two tools answering "is this codebase healthy?" made
|
|
7
|
+
* the agent pick between them, and it under-picked both. The two renderers stay
|
|
8
|
+
* where they are; this composes them.
|
|
9
|
+
*
|
|
10
|
+
* Config is untouched: both reports still read `specship.config.json`
|
|
11
|
+
* (`maintainability.thresholds`, `fitness.rules`), and the CLI enforce/check
|
|
12
|
+
* paths call the library directly, not this tool.
|
|
13
|
+
*/
|
|
14
|
+
import type { SpecShip } from '../index';
|
|
15
|
+
import type { ToolDefinition, ToolResult } from './tools';
|
|
16
|
+
export declare const HEALTH_CHECKS: readonly ["maintainability", "fitness"];
|
|
17
|
+
export type HealthCheck = (typeof HEALTH_CHECKS)[number];
|
|
18
|
+
export declare const healthToolDefinitions: ToolDefinition[];
|
|
19
|
+
/**
|
|
20
|
+
* Normalize the `checks` filter. Anything unrecognized (or absent) falls back
|
|
21
|
+
* to both reports — a filter typo must not silently return an empty health
|
|
22
|
+
* report.
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveHealthChecks(raw: unknown): HealthCheck[];
|
|
25
|
+
export declare function handleSpecshipHealth(cg: SpecShip, args: Record<string, unknown>): Promise<ToolResult>;
|
|
26
|
+
//# sourceMappingURL=health-tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health-tool.d.ts","sourceRoot":"","sources":["../../src/mcp/health-tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAI1D,eAAO,MAAM,aAAa,yCAA0C,CAAC;AACrE,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,eAAO,MAAM,qBAAqB,EAAE,cAAc,EAoBjD,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,WAAW,EAAE,CAM/D;AAED,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,QAAQ,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,UAAU,CAAC,CAWrB"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.healthToolDefinitions = exports.HEALTH_CHECKS = void 0;
|
|
4
|
+
exports.resolveHealthChecks = resolveHealthChecks;
|
|
5
|
+
exports.handleSpecshipHealth = handleSpecshipHealth;
|
|
6
|
+
const maintainability_tool_1 = require("./maintainability-tool");
|
|
7
|
+
const fitness_tool_1 = require("./fitness-tool");
|
|
8
|
+
exports.HEALTH_CHECKS = ['maintainability', 'fitness'];
|
|
9
|
+
exports.healthToolDefinitions = [
|
|
10
|
+
{
|
|
11
|
+
name: 'specship_health',
|
|
12
|
+
description: 'Report code health from the graph: maintainability signals (coupling hotspots by fan-in/out, oversized symbols + god-files, dependency cycles, dead-code candidates) and architecture-fitness violations (forbidden dependencies, layering allow-lists, module isolation) with file:line. Deterministic, no new parse. Returns both by default; pass `checks` to narrow. Thresholds and rules come from specship.config.json (maintainability.thresholds, fitness.rules).',
|
|
13
|
+
inputSchema: {
|
|
14
|
+
type: 'object',
|
|
15
|
+
properties: {
|
|
16
|
+
checks: {
|
|
17
|
+
type: 'array',
|
|
18
|
+
description: 'Which reports to include: "maintainability", "fitness". Omit for both.',
|
|
19
|
+
items: { type: 'string' },
|
|
20
|
+
},
|
|
21
|
+
projectPath: {
|
|
22
|
+
type: 'string',
|
|
23
|
+
description: 'Path to a different project with .specship/ initialized. Omit for the current project.',
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
/**
|
|
30
|
+
* Normalize the `checks` filter. Anything unrecognized (or absent) falls back
|
|
31
|
+
* to both reports — a filter typo must not silently return an empty health
|
|
32
|
+
* report.
|
|
33
|
+
*/
|
|
34
|
+
function resolveHealthChecks(raw) {
|
|
35
|
+
const requested = Array.isArray(raw) ? raw : typeof raw === 'string' ? [raw] : [];
|
|
36
|
+
const picked = exports.HEALTH_CHECKS.filter((c) => requested.some((r) => typeof r === 'string' && r.trim().toLowerCase() === c));
|
|
37
|
+
return picked.length > 0 ? picked : [...exports.HEALTH_CHECKS];
|
|
38
|
+
}
|
|
39
|
+
async function handleSpecshipHealth(cg, args) {
|
|
40
|
+
const checks = resolveHealthChecks(args.checks);
|
|
41
|
+
const sections = [];
|
|
42
|
+
for (const check of checks) {
|
|
43
|
+
const r = check === 'maintainability'
|
|
44
|
+
? await (0, maintainability_tool_1.handleSpecshipMaintainability)(cg, args)
|
|
45
|
+
: await (0, fitness_tool_1.handleSpecshipFitness)(cg, args);
|
|
46
|
+
sections.push(r.content.map((c) => c.text).join('\n'));
|
|
47
|
+
}
|
|
48
|
+
return { content: [{ type: 'text', text: sections.join('\n\n') }] };
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=health-tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health-tool.js","sourceRoot":"","sources":["../../src/mcp/health-tool.ts"],"names":[],"mappings":";;;AAgDA,kDAMC;AAED,oDAcC;AAvDD,iEAAuE;AACvE,iDAAuD;AAE1C,QAAA,aAAa,GAAG,CAAC,iBAAiB,EAAE,SAAS,CAAU,CAAC;AAGxD,QAAA,qBAAqB,GAAqB;IACrD;QACE,IAAI,EAAE,iBAAiB;QACvB,WAAW,EACT,2cAA2c;QAC7c,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,MAAM,EAAE;oBACN,IAAI,EAAE,OAAO;oBACb,WAAW,EAAE,wEAAwE;oBACrF,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;iBAC1B;gBACD,WAAW,EAAE;oBACX,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,wFAAwF;iBACtG;aACF;SACF;KACF;CACF,CAAC;AAEF;;;;GAIG;AACH,SAAgB,mBAAmB,CAAC,GAAY;IAC9C,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAClF,MAAM,MAAM,GAAG,qBAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CACxC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAC7E,CAAC;IACF,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,qBAAa,CAAC,CAAC;AACzD,CAAC;AAEM,KAAK,UAAU,oBAAoB,CACxC,EAAY,EACZ,IAA6B;IAE7B,MAAM,MAAM,GAAG,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,CAAC,GACL,KAAK,KAAK,iBAAiB;YACzB,CAAC,CAAC,MAAM,IAAA,oDAA6B,EAAC,EAAE,EAAE,IAAI,CAAC;YAC/C,CAAC,CAAC,MAAM,IAAA,oCAAqB,EAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAC5C,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;AACtE,CAAC"}
|