From fb891f8138a8a559f0df53fb7030a1c65fb790ef Mon Sep 17 00:00:00 2001 From: Mikhail Liubushkin Date: Thu, 8 Oct 2026 12:47:38 +0200 Subject: [PATCH 1/3] Deprecate AI Search prompts filters and document the new data source (DAT-917) - prompts-by-target / prompts-by-brand: mark filter[volume], filter[keyword_count] and filter[characters_count] as deprecated (removed on , 400 unsupported filter afterwards), document limit maximum 1000 and a 400 response. - Overview (aggregated, by-engine) and leaderboard: document the response changes since 2026-09-29 (average_position null, empty traffic/position time series, entity-based brand_presence, real previous/change values). - Prompts: volume null on ai-overview / 0 on LLM engines, date is the current month. - data-api.json regenerated from data-api.yaml. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01Wgf1DkCuX1WDHgjtcpzQ4y --- openapi/data-api.json | 58 +++++++++++++++--- openapi/data-api.yaml | 135 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 179 insertions(+), 14 deletions(-) diff --git a/openapi/data-api.json b/openapi/data-api.json index f30b23f..3ab8d7e 100644 --- a/openapi/data-api.json +++ b/openapi/data-api.json @@ -5094,7 +5094,7 @@ ], "responses": { "200": { - "description": "Successful response", + "description": "Successful response.\n\nChanges since 2026-09-29 (new AI Search data source):\n\n- `summary.average_position` is always `null`.\n- `time_series.organic_traffic`, `time_series.overall_traffic` and\n `time_series.average_position` are empty arrays.\n- `summary.brand_presence` counts the prompts whose answer mentions the\n brand as a recognized entity, instead of a text match on the brand\n name.\n- `summary.*.previous` is the value of the previous monthly snapshot\n (`null` when unknown), and `change_absolute` / `change_percent` are\n computed from it and signed. Before, `previous` was always `null`\n and the change was reported as the current value and 100%.", "content": { "application/json": {} } @@ -5168,7 +5168,7 @@ ], "responses": { "200": { - "description": "Successful response", + "description": "Successful response.\n\nChanges since 2026-09-29 (new AI Search data source):\n\n- `summary.average_position` is always `null`.\n- `time_series.organic_traffic`, `time_series.overall_traffic` and\n `time_series.average_position` are empty arrays.\n- `summary.brand_presence` counts the prompts whose answer mentions the\n brand as a recognized entity, instead of a text match on the brand\n name.\n- `summary.*.previous` is the value of the previous monthly snapshot\n (`null` when unknown), and `change_absolute` / `change_percent` are\n computed from it and signed. Before, `previous` was always `null`\n and the change was reported as the current value and 100%.", "content": { "application/json": {} } @@ -5244,7 +5244,7 @@ ], "responses": { "200": { - "description": "Successful response", + "description": "Successful response.\n\nSince 2026-09-29 (new AI Search data source) `brand_presence` counts\nthe prompts whose answer mentions the brand as a recognized entity,\ninstead of a text match on the brand name.", "content": { "application/json": {} } @@ -5318,7 +5318,7 @@ "AI search" ], "summary": "prompts by target", - "description": "Fetches a list of prompts where a specified domain, subdomain, or URL appears in the results of a chosen LLM.", + "description": "Fetches a list of prompts where a specified domain, subdomain, or URL appears in the results of a chosen LLM.\n\nThe `filter[volume]`, `filter[keyword_count]` and `filter[characters_count]` filters are deprecated and will be removed on . A page holds at most 1000 prompts (`limit`).", "parameters": [ { "name": "apikey", @@ -5400,8 +5400,10 @@ "name": "limit", "in": "query", "schema": { - "type": "integer" + "type": "integer", + "maximum": 1000 }, + "description": "Number of prompts per page, at most 1000. A larger value is rejected with 400.", "example": 100 }, { @@ -5423,6 +5425,8 @@ { "name": "filter[volume][from]", "in": "query", + "deprecated": true, + "description": "Removed on ; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5431,6 +5435,8 @@ { "name": "filter[volume][to]", "in": "query", + "deprecated": true, + "description": "Removed on ; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5439,6 +5445,8 @@ { "name": "filter[keyword_count][from]", "in": "query", + "deprecated": true, + "description": "Removed on ; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5447,6 +5455,8 @@ { "name": "filter[keyword_count][to]", "in": "query", + "deprecated": true, + "description": "Removed on ; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5455,6 +5465,8 @@ { "name": "filter[characters_count][from]", "in": "query", + "deprecated": true, + "description": "Removed on ; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5463,6 +5475,8 @@ { "name": "filter[characters_count][to]", "in": "query", + "deprecated": true, + "description": "Removed on ; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5471,7 +5485,13 @@ ], "responses": { "200": { - "description": "Successful response", + "description": "Successful response.\n\nChanges since 2026-09-29 (new AI Search data source):\n\n- `prompts[].volume` is `null` for `engine=ai-overview` and `0` for\n the LLM engines.\n- `date` is the current month.", + "content": { + "application/json": {} + } + }, + "400": { + "description": "Invalid request, e.g. `limit` above 1000 or a filter that is no longer supported (`unsupported filter`).", "content": { "application/json": {} } @@ -5486,7 +5506,7 @@ "AI search" ], "summary": "prompts by brand", - "description": "Retrieves a list of prompts where a specified brand name is mentioned in the results of a chosen LLM.", + "description": "Retrieves a list of prompts where a specified brand name is mentioned in the results of a chosen LLM.\n\nThe `filter[volume]`, `filter[keyword_count]` and `filter[characters_count]` filters are deprecated and will be removed on . A page holds at most 1000 prompts (`limit`).", "parameters": [ { "name": "apikey", @@ -5559,8 +5579,10 @@ "name": "limit", "in": "query", "schema": { - "type": "integer" + "type": "integer", + "maximum": 1000 }, + "description": "Number of prompts per page, at most 1000. A larger value is rejected with 400.", "example": 10 }, { @@ -5582,6 +5604,8 @@ { "name": "filter[volume][from]", "in": "query", + "deprecated": true, + "description": "Removed on ; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5590,6 +5614,8 @@ { "name": "filter[volume][to]", "in": "query", + "deprecated": true, + "description": "Removed on ; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5598,6 +5624,8 @@ { "name": "filter[keyword_count][from]", "in": "query", + "deprecated": true, + "description": "Removed on ; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5606,6 +5634,8 @@ { "name": "filter[keyword_count][to]", "in": "query", + "deprecated": true, + "description": "Removed on ; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5614,6 +5644,8 @@ { "name": "filter[characters_count][from]", "in": "query", + "deprecated": true, + "description": "Removed on ; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5622,6 +5654,8 @@ { "name": "filter[characters_count][to]", "in": "query", + "deprecated": true, + "description": "Removed on ; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5630,7 +5664,13 @@ ], "responses": { "200": { - "description": "Successful response", + "description": "Successful response.\n\nChanges since 2026-09-29 (new AI Search data source):\n\n- `prompts[].volume` is `null` for `engine=ai-overview` and `0` for\n the LLM engines.\n- `date` is the current month.", + "content": { + "application/json": {} + } + }, + "400": { + "description": "Invalid request, e.g. `limit` above 1000 or a filter that is no longer supported (`unsupported filter`).", "content": { "application/json": {} } diff --git a/openapi/data-api.yaml b/openapi/data-api.yaml index ee2e74d..d1c8f35 100644 --- a/openapi/data-api.yaml +++ b/openapi/data-api.yaml @@ -3809,7 +3809,21 @@ paths: example: base_domain responses: '200': - description: Successful response + description: |- + Successful response. + + Changes since 2026-09-29 (new AI Search data source): + + - `summary.average_position` is always `null`. + - `time_series.organic_traffic`, `time_series.overall_traffic` and + `time_series.average_position` are empty arrays. + - `summary.brand_presence` counts the prompts whose answer mentions the + brand as a recognized entity, instead of a text match on the brand + name. + - `summary.*.previous` is the value of the previous monthly snapshot + (`null` when unknown), and `change_absolute` / `change_percent` are + computed from it and signed. Before, `previous` was always `null` + and the change was reported as the current value and 100%. content: application/json: {} /v1/ai-search/overview/by-engine/time-series: @@ -3859,7 +3873,21 @@ paths: example: base_domain responses: '200': - description: Successful response + description: |- + Successful response. + + Changes since 2026-09-29 (new AI Search data source): + + - `summary.average_position` is always `null`. + - `time_series.organic_traffic`, `time_series.overall_traffic` and + `time_series.average_position` are empty arrays. + - `summary.brand_presence` counts the prompts whose answer mentions the + brand as a recognized entity, instead of a text match on the brand + name. + - `summary.*.previous` is the value of the previous monthly snapshot + (`null` when unknown), and `change_absolute` / `change_percent` are + computed from it and signed. Before, `previous` was always `null` + and the change was reported as the current value and 100%. content: application/json: {} /v1/ai-search/overview/leaderboard: @@ -3909,7 +3937,12 @@ paths: example: base_domain responses: '200': - description: Successful response + description: |- + Successful response. + + Since 2026-09-29 (new AI Search data source) `brand_presence` counts + the prompts whose answer mentions the brand as a recognized entity, + instead of a text match on the brand name. content: application/json: {} /v1/ai-search/discover-brand: @@ -3965,6 +3998,11 @@ paths: description: >- Fetches a list of prompts where a specified domain, subdomain, or URL appears in the results of a chosen LLM. + + + The `filter[volume]`, `filter[keyword_count]` and + `filter[characters_count]` filters are deprecated and will be removed + on . A page holds at most 1000 prompts (`limit`). parameters: - name: apikey in: query @@ -4023,6 +4061,10 @@ paths: in: query schema: type: integer + maximum: 1000 + description: >- + Number of prompts per page, at most 1000. A larger value is rejected + with 400. example: 100 - name: filter[multi_keyword_included] in: query @@ -4053,37 +4095,74 @@ paths: ] - name: filter[volume][from] in: query + deprecated: true + description: >- + Removed on ; requests that use it get 400 unsupported + filter. schema: type: integer example: 100 - name: filter[volume][to] in: query + deprecated: true + description: >- + Removed on ; requests that use it get 400 unsupported + filter. schema: type: integer example: 100000 - name: filter[keyword_count][from] in: query + deprecated: true + description: >- + Removed on ; requests that use it get 400 unsupported + filter. schema: type: integer example: 5 - name: filter[keyword_count][to] in: query + deprecated: true + description: >- + Removed on ; requests that use it get 400 unsupported + filter. schema: type: integer example: 8 - name: filter[characters_count][from] in: query + deprecated: true + description: >- + Removed on ; requests that use it get 400 unsupported + filter. schema: type: integer example: 15 - name: filter[characters_count][to] in: query + deprecated: true + description: >- + Removed on ; requests that use it get 400 unsupported + filter. schema: type: integer example: 50 responses: '200': - description: Successful response + description: |- + Successful response. + + Changes since 2026-09-29 (new AI Search data source): + + - `prompts[].volume` is `null` for `engine=ai-overview` and `0` for + the LLM engines. + - `date` is the current month. + content: + application/json: {} + '400': + description: >- + Invalid request, e.g. `limit` above 1000 or a filter that is no + longer supported (`unsupported filter`). content: application/json: {} /v1/ai-search/prompts-by-brand: @@ -4095,6 +4174,11 @@ paths: description: >- Retrieves a list of prompts where a specified brand name is mentioned in the results of a chosen LLM. + + + The `filter[volume]`, `filter[keyword_count]` and + `filter[characters_count]` filters are deprecated and will be removed + on . A page holds at most 1000 prompts (`limit`). parameters: - name: apikey in: query @@ -4144,6 +4228,10 @@ paths: in: query schema: type: integer + maximum: 1000 + description: >- + Number of prompts per page, at most 1000. A larger value is rejected + with 400. example: 10 - name: filter[multi_keyword_included] in: query @@ -4174,37 +4262,74 @@ paths: ] - name: filter[volume][from] in: query + deprecated: true + description: >- + Removed on ; requests that use it get 400 unsupported + filter. schema: type: integer example: 100 - name: filter[volume][to] in: query + deprecated: true + description: >- + Removed on ; requests that use it get 400 unsupported + filter. schema: type: integer example: 100000 - name: filter[keyword_count][from] in: query + deprecated: true + description: >- + Removed on ; requests that use it get 400 unsupported + filter. schema: type: integer example: 5 - name: filter[keyword_count][to] in: query + deprecated: true + description: >- + Removed on ; requests that use it get 400 unsupported + filter. schema: type: integer example: 8 - name: filter[characters_count][from] in: query + deprecated: true + description: >- + Removed on ; requests that use it get 400 unsupported + filter. schema: type: integer example: 15 - name: filter[characters_count][to] in: query + deprecated: true + description: >- + Removed on ; requests that use it get 400 unsupported + filter. schema: type: integer example: 50 responses: '200': - description: Successful response + description: |- + Successful response. + + Changes since 2026-09-29 (new AI Search data source): + + - `prompts[].volume` is `null` for `engine=ai-overview` and `0` for + the LLM engines. + - `date` is the current month. + content: + application/json: {} + '400': + description: >- + Invalid request, e.g. `limit` above 1000 or a filter that is no + longer supported (`unsupported filter`). content: application/json: {} /v1/serp/classic/tasks: From 5749ff1188471059d8ac9617b3304f70cdd3d396 Mon Sep 17 00:00:00 2001 From: Mikhail Liubushkin Date: Wed, 14 Oct 2026 08:28:19 +0200 Subject: [PATCH 2/3] Set the removal date of the three AI Search prompts filters (DAT-917) filter[volume], filter[keyword_count] and filter[characters_count] were removed on 2026-10-14; the placeholder date is replaced in the YAML and the JSON alike. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01Wgf1DkCuX1WDHgjtcpzQ4y --- openapi/data-api.json | 28 ++++++++++++++-------------- openapi/data-api.yaml | 32 ++++++++++++++++---------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/openapi/data-api.json b/openapi/data-api.json index 3ab8d7e..6cac094 100644 --- a/openapi/data-api.json +++ b/openapi/data-api.json @@ -5318,7 +5318,7 @@ "AI search" ], "summary": "prompts by target", - "description": "Fetches a list of prompts where a specified domain, subdomain, or URL appears in the results of a chosen LLM.\n\nThe `filter[volume]`, `filter[keyword_count]` and `filter[characters_count]` filters are deprecated and will be removed on . A page holds at most 1000 prompts (`limit`).", + "description": "Fetches a list of prompts where a specified domain, subdomain, or URL appears in the results of a chosen LLM.\n\nThe `filter[volume]`, `filter[keyword_count]` and `filter[characters_count]` filters were removed on 2026-10-14. A page holds at most 1000 prompts (`limit`).", "parameters": [ { "name": "apikey", @@ -5426,7 +5426,7 @@ "name": "filter[volume][from]", "in": "query", "deprecated": true, - "description": "Removed on ; requests that use it get 400 unsupported filter.", + "description": "Removed on 2026-10-14; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5436,7 +5436,7 @@ "name": "filter[volume][to]", "in": "query", "deprecated": true, - "description": "Removed on ; requests that use it get 400 unsupported filter.", + "description": "Removed on 2026-10-14; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5446,7 +5446,7 @@ "name": "filter[keyword_count][from]", "in": "query", "deprecated": true, - "description": "Removed on ; requests that use it get 400 unsupported filter.", + "description": "Removed on 2026-10-14; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5456,7 +5456,7 @@ "name": "filter[keyword_count][to]", "in": "query", "deprecated": true, - "description": "Removed on ; requests that use it get 400 unsupported filter.", + "description": "Removed on 2026-10-14; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5466,7 +5466,7 @@ "name": "filter[characters_count][from]", "in": "query", "deprecated": true, - "description": "Removed on ; requests that use it get 400 unsupported filter.", + "description": "Removed on 2026-10-14; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5476,7 +5476,7 @@ "name": "filter[characters_count][to]", "in": "query", "deprecated": true, - "description": "Removed on ; requests that use it get 400 unsupported filter.", + "description": "Removed on 2026-10-14; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5506,7 +5506,7 @@ "AI search" ], "summary": "prompts by brand", - "description": "Retrieves a list of prompts where a specified brand name is mentioned in the results of a chosen LLM.\n\nThe `filter[volume]`, `filter[keyword_count]` and `filter[characters_count]` filters are deprecated and will be removed on . A page holds at most 1000 prompts (`limit`).", + "description": "Retrieves a list of prompts where a specified brand name is mentioned in the results of a chosen LLM.\n\nThe `filter[volume]`, `filter[keyword_count]` and `filter[characters_count]` filters were removed on 2026-10-14. A page holds at most 1000 prompts (`limit`).", "parameters": [ { "name": "apikey", @@ -5605,7 +5605,7 @@ "name": "filter[volume][from]", "in": "query", "deprecated": true, - "description": "Removed on ; requests that use it get 400 unsupported filter.", + "description": "Removed on 2026-10-14; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5615,7 +5615,7 @@ "name": "filter[volume][to]", "in": "query", "deprecated": true, - "description": "Removed on ; requests that use it get 400 unsupported filter.", + "description": "Removed on 2026-10-14; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5625,7 +5625,7 @@ "name": "filter[keyword_count][from]", "in": "query", "deprecated": true, - "description": "Removed on ; requests that use it get 400 unsupported filter.", + "description": "Removed on 2026-10-14; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5635,7 +5635,7 @@ "name": "filter[keyword_count][to]", "in": "query", "deprecated": true, - "description": "Removed on ; requests that use it get 400 unsupported filter.", + "description": "Removed on 2026-10-14; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5645,7 +5645,7 @@ "name": "filter[characters_count][from]", "in": "query", "deprecated": true, - "description": "Removed on ; requests that use it get 400 unsupported filter.", + "description": "Removed on 2026-10-14; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, @@ -5655,7 +5655,7 @@ "name": "filter[characters_count][to]", "in": "query", "deprecated": true, - "description": "Removed on ; requests that use it get 400 unsupported filter.", + "description": "Removed on 2026-10-14; requests that use it get 400 unsupported filter.", "schema": { "type": "integer" }, diff --git a/openapi/data-api.yaml b/openapi/data-api.yaml index d1c8f35..858f039 100644 --- a/openapi/data-api.yaml +++ b/openapi/data-api.yaml @@ -4001,8 +4001,8 @@ paths: The `filter[volume]`, `filter[keyword_count]` and - `filter[characters_count]` filters are deprecated and will be removed - on . A page holds at most 1000 prompts (`limit`). + `filter[characters_count]` filters were removed + on 2026-10-14. A page holds at most 1000 prompts (`limit`). parameters: - name: apikey in: query @@ -4097,7 +4097,7 @@ paths: in: query deprecated: true description: >- - Removed on ; requests that use it get 400 unsupported + Removed on 2026-10-14; requests that use it get 400 unsupported filter. schema: type: integer @@ -4106,7 +4106,7 @@ paths: in: query deprecated: true description: >- - Removed on ; requests that use it get 400 unsupported + Removed on 2026-10-14; requests that use it get 400 unsupported filter. schema: type: integer @@ -4115,7 +4115,7 @@ paths: in: query deprecated: true description: >- - Removed on ; requests that use it get 400 unsupported + Removed on 2026-10-14; requests that use it get 400 unsupported filter. schema: type: integer @@ -4124,7 +4124,7 @@ paths: in: query deprecated: true description: >- - Removed on ; requests that use it get 400 unsupported + Removed on 2026-10-14; requests that use it get 400 unsupported filter. schema: type: integer @@ -4133,7 +4133,7 @@ paths: in: query deprecated: true description: >- - Removed on ; requests that use it get 400 unsupported + Removed on 2026-10-14; requests that use it get 400 unsupported filter. schema: type: integer @@ -4142,7 +4142,7 @@ paths: in: query deprecated: true description: >- - Removed on ; requests that use it get 400 unsupported + Removed on 2026-10-14; requests that use it get 400 unsupported filter. schema: type: integer @@ -4177,8 +4177,8 @@ paths: The `filter[volume]`, `filter[keyword_count]` and - `filter[characters_count]` filters are deprecated and will be removed - on . A page holds at most 1000 prompts (`limit`). + `filter[characters_count]` filters were removed + on 2026-10-14. A page holds at most 1000 prompts (`limit`). parameters: - name: apikey in: query @@ -4264,7 +4264,7 @@ paths: in: query deprecated: true description: >- - Removed on ; requests that use it get 400 unsupported + Removed on 2026-10-14; requests that use it get 400 unsupported filter. schema: type: integer @@ -4273,7 +4273,7 @@ paths: in: query deprecated: true description: >- - Removed on ; requests that use it get 400 unsupported + Removed on 2026-10-14; requests that use it get 400 unsupported filter. schema: type: integer @@ -4282,7 +4282,7 @@ paths: in: query deprecated: true description: >- - Removed on ; requests that use it get 400 unsupported + Removed on 2026-10-14; requests that use it get 400 unsupported filter. schema: type: integer @@ -4291,7 +4291,7 @@ paths: in: query deprecated: true description: >- - Removed on ; requests that use it get 400 unsupported + Removed on 2026-10-14; requests that use it get 400 unsupported filter. schema: type: integer @@ -4300,7 +4300,7 @@ paths: in: query deprecated: true description: >- - Removed on ; requests that use it get 400 unsupported + Removed on 2026-10-14; requests that use it get 400 unsupported filter. schema: type: integer @@ -4309,7 +4309,7 @@ paths: in: query deprecated: true description: >- - Removed on ; requests that use it get 400 unsupported + Removed on 2026-10-14; requests that use it get 400 unsupported filter. schema: type: integer From e5a965ab73c27e2e2942d4c2887d3b2c4e32f912 Mon Sep 17 00:00:00 2001 From: Mikhail Liubushkin Date: Wed, 14 Oct 2026 09:05:15 +0200 Subject: [PATCH 3/3] ci: install js-yaml where the JSON-vs-YAML check can require it `npm install -g` puts js-yaml in the global prefix, which `node -e "require('js-yaml')"` does not search, so the check failed with MODULE_NOT_FOUND on every run. A local, unsaved install lands in ./node_modules (already in .gitignore) and resolves. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01Wgf1DkCuX1WDHgjtcpzQ4y --- .github/workflows/validate.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 53ef42c..c9d69ee 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -30,7 +30,7 @@ jobs: - name: Validate JSON matches YAML run: | - npm install -g js-yaml + npm install --no-save js-yaml node -e " const fs = require('fs'); const yaml = require('js-yaml');