* fix(#1747): register four search-provider keys in the config schema buildNewProjectConfig emits seven search-provider availability flags and research-provider.cts providerAvailability() consumes all seven, but only three were registered in VALID_CONFIG_KEYS (config-schema.manifest.json). config-loader.cts then printed an 'unknown config key(s)' warning for the four unregistered keys (tavily_search, ref_search, perplexity, jina) on every freshly generated .planning/config.json. Register the four missing keys in the schema manifest and document them alongside brave/exa/firecrawl in CONFIGURATION.md. Add a regression test plus a structural drift guard that requires every config-driven research-provider flag to be in VALID_CONFIG_KEYS, so a future provider addition cannot silently reintroduce the drift. * fix(#1747): move regression into owning test file + add changeset lint-regression-test-names rejects new bug-NNNN-*.test.cjs files; move the #1747 regression (four provider keys in VALID_CONFIG_KEYS + provider-flag drift guard) into tests/bug-2530-valid-config-keys.test.cjs, the canonical home for VALID_CONFIG_KEYS regressions, and delete the standalone file. Add the missing .changeset fragment — config-schema.manifest.json lives under gsd-core/ (user-facing), so changeset-lint requires a fragment. * test(#1747): regenerate golden-install-parity fixtures for schema change Adding four provider keys to config-schema.manifest.json shifts its shipped content hash (65dea848 -> 7d398e94); recapture all 16 runtime fixtures via UPDATE_GOLDEN=1. Each fixture changes exactly one line — the manifest hash.
This commit is contained in:
5
.changeset/1747-new-project-search-provider-keys.md
Normal file
5
.changeset/1747-new-project-search-provider-keys.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
type: Fixed
|
||||
pr: 1814
|
||||
---
|
||||
**`/gsd-settings` no longer warns about four search-provider keys on fresh projects (#1747)** — `buildNewProjectConfig` emits seven search-provider availability flags and `research-provider.cts` `providerAvailability()` consumes all seven, but only three were registered in `VALID_CONFIG_KEYS` (`config-schema.manifest.json`). Running `/gsd-settings` on a freshly generated `.planning/config.json` printed `unknown config key(s) … tavily_search, ref_search, perplexity, jina — these will be ignored` even though the user never hand-edited the config. The four missing keys are now registered alongside `brave_search`/`firecrawl`/`exa_search` and documented in `docs/CONFIGURATION.md`; a drift guard in `tests/bug-2530-valid-config-keys.test.cjs` now requires every config-driven research-provider flag to be in the schema, so a future provider addition cannot reintroduce the drift.
|
||||
@@ -171,6 +171,10 @@ GSD stores project settings in `.planning/config.json`. Created during `/gsd-new
|
||||
| `brave_search` | boolean | `true`/`false` | auto-detected | Override auto-detection of Brave Search API availability. When unset, GSD checks for `BRAVE_API_KEY` env var or `~/.gsd/brave_api_key` file |
|
||||
| `firecrawl` | boolean | `true`/`false` | auto-detected | Override auto-detection of Firecrawl API availability. When unset, GSD checks for `FIRECRAWL_API_KEY` env var or `~/.gsd/firecrawl_api_key` file |
|
||||
| `exa_search` | boolean | `true`/`false` | auto-detected | Override auto-detection of Exa Search API availability. When unset, GSD checks for `EXA_API_KEY` env var or `~/.gsd/exa_api_key` file |
|
||||
| `tavily_search` | boolean | `true`/`false` | auto-detected | Override auto-detection of Tavily Search API availability. When unset, GSD checks for `TAVILY_API_KEY` env var or `~/.gsd/tavily_api_key` file |
|
||||
| `ref_search` | boolean | `true`/`false` | auto-detected | Override auto-detection of Ref search API availability. When unset, GSD checks for `REF_API_KEY` env var or `~/.gsd/ref_api_key` file |
|
||||
| `perplexity` | boolean | `true`/`false` | auto-detected | Override auto-detection of Perplexity API availability. When unset, GSD checks for `PERPLEXITY_API_KEY` env var or `~/.gsd/perplexity_api_key` file |
|
||||
| `jina` | boolean | `true`/`false` | `true` | Override auto-detection of Jina API availability. Jina is a terminal fallback in the docs waterfall and defaults to available (`true`); GSD checks for `JINA_API_KEY` env var or `~/.gsd/jina_api_key` file when an explicit override is needed |
|
||||
| `search_gitignored` | boolean | `true`/`false` | `false` | Legacy top-level alias for `planning.search_gitignored`. Prefer the namespaced form; this alias is accepted for backward compatibility |
|
||||
|
||||
> **Note:** `granularity` was renamed from `depth` in v1.22.3. Existing configs are auto-migrated.
|
||||
@@ -190,6 +194,10 @@ API key fields accept a string value (the key itself). They can also be set to t
|
||||
| `brave_search` | string \| boolean \| null | `null` | Brave Search API key used for web research. Displayed as `****<last-4>` in all UI / `config-set` output; never echoed plaintext |
|
||||
| `firecrawl` | string \| boolean \| null | `null` | Firecrawl API key for deep-crawl scraping. Masked in display |
|
||||
| `exa_search` | string \| boolean \| null | `null` | Exa Search API key for semantic search. Masked in display |
|
||||
| `tavily_search` | string \| boolean \| null | `null` | Tavily Search API key used in the web-discovery waterfall. Masked in display |
|
||||
| `ref_search` | string \| boolean \| null | `null` | Ref search API key used in the docs-discovery waterfall. Masked in display |
|
||||
| `perplexity` | string \| boolean \| null | `null` | Perplexity API key used in the web-discovery waterfall. Masked in display |
|
||||
| `jina` | string \| boolean \| null | `null` | Jina API key (docs / scrape fallback). Masked in display |
|
||||
|
||||
**Masking convention (`gsd-core/bin/lib/secrets.cjs`):** keys 8+ characters render as `****<last-4>`; shorter keys render as `****`; `null`/empty renders as `(unset)`. Plaintext is written as-is to `.planning/config.json` — that file is the security boundary — but the CLI, confirmation tables, logs, and `AskUserQuestion` descriptions never display the plaintext. This applies to the `config-set` command output itself: `config-set brave_search <key>` returns a JSON payload with the value masked.
|
||||
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
"brave_search",
|
||||
"firecrawl",
|
||||
"exa_search",
|
||||
"tavily_search",
|
||||
"ref_search",
|
||||
"perplexity",
|
||||
"jina",
|
||||
"workflow.plan_check",
|
||||
"workflow.verifier",
|
||||
"workflow.auto_advance",
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
* #2535 — sub_repos and plan_checker legacy keys need CONFIG_KEY_SUGGESTIONS migration hints
|
||||
* #3162 — resolve_model_ids missing from VALID_CONFIG_KEYS; workflow._auto_chain_active must be
|
||||
* accepted by isValidConfigKey (written by workflows) without being user-visible
|
||||
* #1747 — buildNewProjectConfig emits four search-provider keys (tavily_search, ref_search,
|
||||
* perplexity, jina) that research-provider.cts consumes but were missing from
|
||||
* VALID_CONFIG_KEYS, causing /gsd-settings unknown-key warnings on fresh projects
|
||||
*/
|
||||
|
||||
const { describe, test } = require('node:test');
|
||||
@@ -74,6 +77,48 @@ describe('VALID_CONFIG_KEYS correctness', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('#1747: new-project config emits only schema-recognized provider keys', () => {
|
||||
// buildNewProjectConfig emits seven search-provider availability flags and
|
||||
// research-provider.cts providerAvailability() consumes all seven, but only
|
||||
// three were in VALID_CONFIG_KEYS → /gsd-settings warned on the four
|
||||
// unregistered keys (tavily_search, ref_search, perplexity, jina) for every
|
||||
// freshly generated .planning/config.json.
|
||||
|
||||
// The four keys that were emitted + consumed but missing from the schema.
|
||||
const MISSING_KEYS = ['tavily_search', 'ref_search', 'perplexity', 'jina'];
|
||||
|
||||
// Every config-driven provider flag read by providerAvailability() in
|
||||
// src/research-provider.cts. context7/websearch are excluded: hardcoded
|
||||
// `true`, not config-gated, so no config key to register.
|
||||
const PROVIDER_CONFIG_KEYS = [
|
||||
'brave_search',
|
||||
'firecrawl',
|
||||
'exa_search',
|
||||
'tavily_search',
|
||||
'ref_search',
|
||||
'perplexity',
|
||||
'jina',
|
||||
];
|
||||
|
||||
test('the four previously-missing provider keys are in VALID_CONFIG_KEYS', () => {
|
||||
const absent = MISSING_KEYS.filter((k) => !VALID_CONFIG_KEYS.has(k));
|
||||
assert.deepStrictEqual(
|
||||
absent,
|
||||
[],
|
||||
`These provider keys are emitted by buildNewProjectConfig and consumed by research-provider.cts but missing from VALID_CONFIG_KEYS:\n ${absent.join('\n ')}\n\nAdd them to gsd-core/bin/shared/config-schema.manifest.json (validKeys).`
|
||||
);
|
||||
});
|
||||
|
||||
test('every config-driven research-provider flag is registered in the schema (drift guard)', () => {
|
||||
const drifted = PROVIDER_CONFIG_KEYS.filter((k) => !VALID_CONFIG_KEYS.has(k));
|
||||
assert.deepStrictEqual(
|
||||
drifted,
|
||||
[],
|
||||
`These research-provider config flags are not in VALID_CONFIG_KEYS — a fresh /gsd-new-project config would trigger an unknown-key warning under /gsd-settings:\n ${drifted.join('\n ')}\n\nWhen you add a provider to providerAvailability() in src/research-provider.cts, also register its config key in gsd-core/bin/shared/config-schema.manifest.json.`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ADR-857 Phase 6 capability config ownership', () => {
|
||||
test('migrated capability config keys are valid through the registry, not central schema residue', () => {
|
||||
const capabilityKeys = Object.keys(capabilityRegistry.configSchema || {}).sort();
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"gsd-core/bin/gsd-tools.cjs": "5cf26d5f9e588cf8",
|
||||
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
|
||||
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
|
||||
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs": "8bc541aabc2e143c",
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
"gsd-core/bin/gsd-tools.cjs": "74594e8bf36e5580",
|
||||
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
|
||||
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
|
||||
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
"gsd-core/bin/gsd-tools.cjs": "74594e8bf36e5580",
|
||||
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
|
||||
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
|
||||
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"gsd-core/bin/gsd-tools.cjs": "74594e8bf36e5580",
|
||||
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
|
||||
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
|
||||
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
"gsd-core/bin/gsd-tools.cjs": "74594e8bf36e5580",
|
||||
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
|
||||
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
|
||||
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
"gsd-core/bin/gsd-tools.cjs": "74594e8bf36e5580",
|
||||
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
|
||||
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
|
||||
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
"gsd-core/bin/gsd-tools.cjs": "5cf26d5f9e588cf8",
|
||||
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
|
||||
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
|
||||
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs": "10226e9512dd44bf",
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
"gsd-core/bin/gsd-tools.cjs": "5cf26d5f9e588cf8",
|
||||
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
|
||||
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
|
||||
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
"gsd-core/bin/gsd-tools.cjs": "74594e8bf36e5580",
|
||||
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
|
||||
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
|
||||
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"gsd-core/bin/gsd-tools.cjs": "74594e8bf36e5580",
|
||||
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
|
||||
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
|
||||
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
"gsd-core/bin/gsd-tools.cjs": "74594e8bf36e5580",
|
||||
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
|
||||
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
|
||||
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
"gsd-core/bin/gsd-tools.cjs": "74594e8bf36e5580",
|
||||
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
|
||||
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
|
||||
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
"gsd-core/bin/gsd-tools.cjs": "74594e8bf36e5580",
|
||||
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
|
||||
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
|
||||
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"gsd-core/bin/gsd-tools.cjs": "74594e8bf36e5580",
|
||||
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
|
||||
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
|
||||
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"gsd-core/bin/gsd-tools.cjs": "5cf26d5f9e588cf8",
|
||||
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
|
||||
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
|
||||
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"gsd-core/bin/gsd-tools.cjs": "5cf26d5f9e588cf8",
|
||||
"gsd-core/bin/gsd_run": "62d9b647ede212e6",
|
||||
"gsd-core/bin/shared/config-defaults.manifest.json": "517e6a7c1e9f4f16",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "65dea848d50969a2",
|
||||
"gsd-core/bin/shared/config-schema.manifest.json": "7d398e94c44e5268",
|
||||
"gsd-core/bin/shared/model-catalog.json": "dbe26e683236d8c6",
|
||||
"gsd-core/bin/shared/runtime-aliases.manifest.json": "f6c8b3af10dcfdc4",
|
||||
"gsd-core/bin/verify-reapply-patches.cjs": "caec5dbce11e3904",
|
||||
|
||||
Reference in New Issue
Block a user