sneakoscope 4.2.0 → 4.3.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/README.md +35 -8
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/crates/sks-core/src/main.rs +1 -1
- package/dist/bin/sks.js +1 -1
- package/dist/cli/command-registry.js +3 -1
- package/dist/cli/ultra-search-command.js +163 -0
- package/dist/cli/xai-command.js +28 -168
- package/dist/core/agents/agent-codex-cockpit.js +3 -3
- package/dist/core/agents/agent-runner-ollama.js +2 -0
- package/dist/core/agents/agent-wrongness.js +1 -1
- package/dist/core/agents/native-worker-backend-router.js +3 -0
- package/dist/core/bench.js +115 -0
- package/dist/core/code-structure.js +399 -11
- package/dist/core/codex-control/codex-app-server-v2-client.js +86 -2
- package/dist/core/codex-control/codex-fake-sdk-adapter.js +67 -9
- package/dist/core/codex-control/codex-reliability-shield.js +26 -5
- package/dist/core/codex-control/codex-task-runner.js +7 -1
- package/dist/core/codex-control/gpt-final-arbiter.js +4 -1
- package/dist/core/codex-control/gpt-final-review-schema.js +58 -0
- package/dist/core/codex-control/model-call-concurrency.js +1 -1
- package/dist/core/codex-native/core-skill-manifest.js +23 -0
- package/dist/core/commands/bench-command.js +11 -2
- package/dist/core/commands/code-structure-command.js +34 -2
- package/dist/core/commands/qa-loop-command.js +23 -7
- package/dist/core/commands/run-command.js +92 -2
- package/dist/core/commands/seo-command.js +130 -0
- package/dist/core/feature-fixtures.js +6 -0
- package/dist/core/feature-registry.js +3 -1
- package/dist/core/fsx.js +1 -1
- package/dist/core/hooks-runtime.js +9 -1
- package/dist/core/init.js +8 -6
- package/dist/core/lean-engineering-policy.js +159 -0
- package/dist/core/pipeline-internals/runtime-core.js +15 -5
- package/dist/core/proof/auto-finalize.js +3 -2
- package/dist/core/proof/proof-schema.js +2 -1
- package/dist/core/proof/proof-writer.js +1 -0
- package/dist/core/proof/route-adapter.js +4 -2
- package/dist/core/proof/route-finalizer.js +35 -3
- package/dist/core/qa-loop/qa-app-server-driver.js +134 -0
- package/dist/core/qa-loop/qa-contract-v2.js +231 -0
- package/dist/core/qa-loop/qa-gate-v2.js +132 -0
- package/dist/core/qa-loop/qa-runtime-artifacts.js +53 -0
- package/dist/core/qa-loop/qa-surface-router.js +114 -0
- package/dist/core/qa-loop/qa-types.js +18 -0
- package/dist/core/qa-loop.js +83 -26
- package/dist/core/release/gate-manifest.js +1 -0
- package/dist/core/release/sla-scheduler.js +1 -1
- package/dist/core/release-parallel-full-coverage.js +1 -1
- package/dist/core/routes.js +96 -14
- package/dist/core/search-visibility/adapter-registry.js +26 -0
- package/dist/core/search-visibility/adapters/next-app.js +6 -0
- package/dist/core/search-visibility/adapters/next-pages.js +6 -0
- package/dist/core/search-visibility/adapters/static-site.js +6 -0
- package/dist/core/search-visibility/analyzers.js +377 -0
- package/dist/core/search-visibility/artifacts.js +183 -0
- package/dist/core/search-visibility/discovery.js +347 -0
- package/dist/core/search-visibility/index.js +199 -0
- package/dist/core/search-visibility/mission.js +67 -0
- package/dist/core/search-visibility/mutation.js +314 -0
- package/dist/core/search-visibility/types.js +2 -0
- package/dist/core/search-visibility/verifier.js +60 -0
- package/dist/core/source-intelligence/source-intelligence-policy.js +45 -26
- package/dist/core/source-intelligence/source-intelligence-proof.js +10 -16
- package/dist/core/source-intelligence/source-intelligence-runner.js +56 -42
- package/dist/core/triwiki/triwiki-affected-graph.js +3 -2
- package/dist/core/trust-kernel/trust-report.js +3 -5
- package/dist/core/ultra-search/index.js +3 -0
- package/dist/core/ultra-search/runtime.js +502 -0
- package/dist/core/ultra-search/types.js +3 -0
- package/dist/core/version.js +1 -1
- package/dist/scripts/agent-visual-consistency-check.js +1 -1
- package/dist/scripts/check-architecture.js +40 -7
- package/dist/scripts/check-command-module-budget.js +43 -5
- package/dist/scripts/check-pipeline-budget.js +17 -30
- package/dist/scripts/check-publish-tag.js +33 -6
- package/dist/scripts/check-route-modularity.js +25 -33
- package/dist/scripts/check-runtime-schemas.js +22 -0
- package/dist/scripts/codex-control-all-pipelines-check.js +1 -0
- package/dist/scripts/codex-control-model-capacity-fallback-check.js +53 -0
- package/dist/scripts/config-managed-merge-callsite-coverage-check.js +7 -1
- package/dist/scripts/core-skill-immutable-sync-check.js +3 -2
- package/dist/scripts/core-skill-integrity-blackbox.js +3 -2
- package/dist/scripts/core-skill-manifest-check.js +7 -2
- package/dist/scripts/geo-claim-evidence-check.js +18 -0
- package/dist/scripts/geo-cli-blackbox-check.js +18 -0
- package/dist/scripts/geo-crawler-policy-check.js +16 -0
- package/dist/scripts/geo-llms-txt-optional-check.js +19 -0
- package/dist/scripts/gpt-final-arbiter-check.js +4 -1
- package/dist/scripts/loop-directive-check-lib.js +78 -1
- package/dist/scripts/qa-loop-app-server-driver-check.js +74 -0
- package/dist/scripts/qa-loop-surface-router-check.js +49 -0
- package/dist/scripts/release-check-dynamic-execute.js +1 -1
- package/dist/scripts/release-metadata-1-19-check.js +2 -2
- package/dist/scripts/release-parallel-check.js +17 -2
- package/dist/scripts/release-parallel-full-coverage-check.js +1 -1
- package/dist/scripts/release-readiness-report.js +6 -6
- package/dist/scripts/release-registry-check.js +33 -14
- package/dist/scripts/runtime-ts-rust-boundary-check.js +1 -1
- package/dist/scripts/search-visibility-gate-lib.js +124 -0
- package/dist/scripts/seo-audit-fixture-check.js +16 -0
- package/dist/scripts/seo-canonical-locale-check.js +19 -0
- package/dist/scripts/seo-cli-blackbox-check.js +18 -0
- package/dist/scripts/seo-geo-feature-fixture-quality-check.js +18 -0
- package/dist/scripts/seo-geo-geo-disambiguation-check.js +12 -0
- package/dist/scripts/seo-geo-no-unsupported-ranking-claims-check.js +18 -0
- package/dist/scripts/seo-geo-route-identity-check.js +12 -0
- package/dist/scripts/seo-geo-skill-rich-content-check.js +22 -0
- package/dist/scripts/seo-mutation-rollback-check.js +23 -0
- package/dist/scripts/seo-no-mutation-by-default-check.js +17 -0
- package/dist/scripts/seo-structured-data-visible-content-check.js +19 -0
- package/dist/scripts/sks-1-18-gate-lib.js +2 -2
- package/dist/scripts/sks-3-1-5-directive-check-lib.js +10 -1
- package/dist/scripts/source-intelligence-all-modes-check.js +9 -19
- package/dist/scripts/source-intelligence-policy-check.js +6 -6
- package/dist/scripts/triwiki-affected-graph-check.js +2 -2
- package/dist/scripts/ultra-search-provider-interface-check.js +27 -0
- package/package.json +26 -5
- package/schemas/search-visibility/finding-ledger.schema.json +36 -0
- package/schemas/search-visibility/gate.schema.json +22 -0
- package/schemas/search-visibility/mutation-plan.schema.json +27 -0
- package/schemas/search-visibility/site-inventory.schema.json +21 -0
- package/schemas/search-visibility/verification-report.schema.json +23 -0
- package/dist/core/mcp/xai-mcp-detector.js +0 -157
- package/dist/core/mcp/xai-search-adapter.js +0 -100
- package/dist/scripts/xai-mcp-capability-check.js +0 -14
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
7
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-seo-geo-skills-'));
|
|
8
|
+
const init = await importDist('core/init.js');
|
|
9
|
+
await init.installSkills(root);
|
|
10
|
+
for (const name of ['search-visibility-core', 'seo-geo-optimizer']) {
|
|
11
|
+
const file = path.join(root, '.agents', 'skills', name, 'SKILL.md');
|
|
12
|
+
assertGate(fs.existsSync(file), `generated skill missing: ${name}`);
|
|
13
|
+
const text = fs.readFileSync(file, 'utf8');
|
|
14
|
+
assertGate(/^---\nname:/m.test(text) && /description:/.test(text), `skill frontmatter missing: ${name}`, text);
|
|
15
|
+
for (const token of ['Purpose:', 'Use when', 'Workflow:', 'Safety:', 'Evidence/artifacts:', 'Failure/recovery:']) {
|
|
16
|
+
assertGate(text.includes(token), `skill missing rich token ${token}: ${name}`, text);
|
|
17
|
+
}
|
|
18
|
+
assertGate(/CLI entrypoint:/i.test(text), `skill missing CLI entrypoint: ${name}`, text);
|
|
19
|
+
assertGate(/ranking|citation|traffic|guarantee|보장/i.test(text), `skill must name forbidden guarantee boundary: ${name}`, text);
|
|
20
|
+
}
|
|
21
|
+
emitGate('seo-geo:skill-rich-content', { skills_checked: 2 });
|
|
22
|
+
//# sourceMappingURL=seo-geo-skill-rich-content-check.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { assertGate, assertMissionArtifact, emitGate, makeSearchVisibilityFixture, runSksJson } from './search-visibility-gate-lib.js';
|
|
6
|
+
const fixture = makeSearchVisibilityFixture('seo-rollback');
|
|
7
|
+
const audit = runSksJson(['seo-geo-optimizer', 'audit', '--mode', 'seo', '--root', fixture, '--target', 'website', '--framework', 'static', '--url', 'https://example.test', '--offline', '--json']).json;
|
|
8
|
+
const plan = runSksJson(['seo-geo-optimizer', 'plan', audit.mission_id, '--mode', 'seo', '--root', fixture, '--json']).json;
|
|
9
|
+
assertGate(plan.operations >= 2, 'SEO rollback fixture should plan robots and sitemap creation', plan);
|
|
10
|
+
const apply = runSksJson(['seo-geo-optimizer', 'apply', audit.mission_id, '--mode', 'seo', '--root', fixture, '--apply', '--json']).json;
|
|
11
|
+
assertGate(apply.ok === true && apply.applied >= 2, 'SEO apply must create planned managed files', apply);
|
|
12
|
+
assertGate(fs.existsSync(path.join(fixture, 'public', 'robots.txt')) && fs.existsSync(path.join(fixture, 'public', 'sitemap.xml')), 'managed robots and sitemap must exist after apply');
|
|
13
|
+
const second = runSksJson(['seo-geo-optimizer', 'apply', audit.mission_id, '--mode', 'seo', '--root', fixture, '--apply', '--json']).json;
|
|
14
|
+
assertGate(second.ok === true, 'second apply must be idempotent', second);
|
|
15
|
+
const journal = fs.readFileSync(path.join(fixture, '.sneakoscope', 'missions', audit.mission_id, 'search-visibility', 'mutation-journal.jsonl'), 'utf8');
|
|
16
|
+
assertGate(/applied/.test(journal), 'mutation journal must record applied/idempotent events', journal);
|
|
17
|
+
const rollbackManifest = assertMissionArtifact(audit.mission_id, 'rollback-manifest.json', fixture);
|
|
18
|
+
assertGate(rollbackManifest.operations.length >= 2, 'rollback manifest must preserve inverse operations after idempotent apply', rollbackManifest);
|
|
19
|
+
const rollback = runSksJson(['seo-geo-optimizer', 'rollback', audit.mission_id, '--mode', 'seo', '--root', fixture, '--apply', '--json']).json;
|
|
20
|
+
assertGate(rollback.ok === true && rollback.rolled_back >= 2, 'rollback must reverse mission-owned operations', rollback);
|
|
21
|
+
assertGate(!fs.existsSync(path.join(fixture, 'public', 'robots.txt')) && !fs.existsSync(path.join(fixture, 'public', 'sitemap.xml')), 'rollback must remove mission-created files');
|
|
22
|
+
emitGate('seo:mutation-rollback', { mission_id: audit.mission_id, applied: apply.applied, rolled_back: rollback.rolled_back });
|
|
23
|
+
//# sourceMappingURL=seo-mutation-rollback-check.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { assertGate, emitGate, listSourceFiles, makeSearchVisibilityFixture, runSksJson } from './search-visibility-gate-lib.js';
|
|
6
|
+
const fixture = makeSearchVisibilityFixture('seo-readonly');
|
|
7
|
+
const before = listSourceFiles(fixture);
|
|
8
|
+
const audit = runSksJson(['seo-geo-optimizer', 'audit', '--mode', 'seo', '--root', fixture, '--target', 'website', '--framework', 'static', '--url', 'https://example.test', '--offline', '--json']).json;
|
|
9
|
+
const plan = runSksJson(['seo-geo-optimizer', 'plan', audit.mission_id, '--mode', 'seo', '--root', fixture, '--json']).json;
|
|
10
|
+
const blockedApply = runSksJson(['seo-geo-optimizer', 'apply', audit.mission_id, '--mode', 'seo', '--root', fixture, '--json'], { allowFailure: true }).json;
|
|
11
|
+
const after = listSourceFiles(fixture);
|
|
12
|
+
assertGate(JSON.stringify(before) === JSON.stringify(after), 'audit/plan/apply-without-flag must not mutate project source files', { before, after });
|
|
13
|
+
assertGate(plan.operations > 0, 'readonly fixture should still compile a mutation plan', plan);
|
|
14
|
+
assertGate(blockedApply.ok === false && blockedApply.blockers.includes('apply_requires_explicit_--apply'), 'apply must require explicit --apply', blockedApply);
|
|
15
|
+
assertGate(!fs.existsSync(path.join(fixture, 'public', 'robots.txt')) && !fs.existsSync(path.join(fixture, 'public', 'sitemap.xml')), 'policy files must not be created without --apply');
|
|
16
|
+
emitGate('seo:no-mutation-by-default', { mission_id: audit.mission_id, planned_operations: plan.operations });
|
|
17
|
+
//# sourceMappingURL=seo-no-mutation-by-default-check.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import { assertGate, assertMissionArtifact, emitGate, makeSearchVisibilityFixture, runSksJson } from './search-visibility-gate-lib.js';
|
|
4
|
+
const html = [
|
|
5
|
+
'<!doctype html>',
|
|
6
|
+
'<html lang="en"><head><title>Structured Data Fixture</title>',
|
|
7
|
+
'<script type="application/ld+json">{"@context":"https://schema.org","@type":"Product","aggregateRating":{"ratingValue":5,}}</script>',
|
|
8
|
+
'</head><body><h1>Structured Data Fixture</h1><p>Visible source content only.</p></body></html>',
|
|
9
|
+
'',
|
|
10
|
+
].join('\n');
|
|
11
|
+
const fixture = makeSearchVisibilityFixture('seo-structured', { html });
|
|
12
|
+
const audit = runSksJson(['seo-geo-optimizer', 'audit', '--mode', 'seo', '--root', fixture, '--target', 'website', '--framework', 'static', '--url', 'https://example.test', '--offline', '--json']).json;
|
|
13
|
+
const ledger = assertMissionArtifact(audit.mission_id, 'structured-data-ledger.json', fixture);
|
|
14
|
+
const findings = assertMissionArtifact(audit.mission_id, 'seo-findings.json', fixture);
|
|
15
|
+
assertGate(ledger.policies.some((url) => /structured-data/.test(url)), 'structured data ledger must cite structured-data policy sources', ledger);
|
|
16
|
+
assertGate(ledger.pages.some((page) => page.parse_errors.length > 0), 'invalid JSON-LD must be recorded as parse error', ledger);
|
|
17
|
+
assertGate(findings.findings.some((finding) => finding.ruleId.includes('jsonld-parse') && finding.evidence.length > 0), 'invalid JSON-LD finding must carry evidence', findings);
|
|
18
|
+
emitGate('seo:structured-data-visible-content', { mission_id: audit.mission_id });
|
|
19
|
+
//# sourceMappingURL=seo-structured-data-visible-content-check.js.map
|
|
@@ -41,8 +41,8 @@ export const SOURCE_INTELLIGENCE_FILES = [
|
|
|
41
41
|
'src/core/source-intelligence/source-intelligence-policy.ts',
|
|
42
42
|
'src/core/source-intelligence/source-intelligence-runner.ts',
|
|
43
43
|
'src/core/source-intelligence/source-intelligence-proof.ts',
|
|
44
|
-
'src/core/
|
|
45
|
-
'src/core/
|
|
44
|
+
'src/core/ultra-search/types.ts',
|
|
45
|
+
'src/core/ultra-search/runtime.ts',
|
|
46
46
|
'src/core/codex/codex-web-search-adapter.ts'
|
|
47
47
|
];
|
|
48
48
|
export const AGENT_118_FILES = [
|
|
@@ -251,7 +251,16 @@ async function richContentGate(id) {
|
|
|
251
251
|
const report = await mod.syncCodexSksSkills({ root: rootDir, skillsRoot, apply: true });
|
|
252
252
|
const skill = fs.readFileSync(path.join(skillsRoot, 'loop', 'SKILL.md'), 'utf8');
|
|
253
253
|
assertGate(/Purpose:|Evidence:|Fallback:/.test(skill), 'managed skill must include rich route content', { skill, report });
|
|
254
|
-
|
|
254
|
+
for (const name of ['search-visibility-core', 'seo-geo-optimizer']) {
|
|
255
|
+
const file = path.join(skillsRoot, name, 'SKILL.md');
|
|
256
|
+
assertGate(fs.existsSync(file), `managed skill missing: ${name}`, { report });
|
|
257
|
+
const text = fs.readFileSync(file, 'utf8');
|
|
258
|
+
assertGate(/Purpose:|Use when:|Workflow:|Safety:|Evidence\/artifacts:|Failure\/recovery:|CLI entrypoint:/i.test(text), `managed skill lacks rich content: ${name}`, { text });
|
|
259
|
+
assertGate(/ranking|citation|traffic|guarantee|보장/i.test(text), `managed skill must name forbidden guarantee boundary: ${name}`, { text });
|
|
260
|
+
if (name === 'seo-geo-optimizer')
|
|
261
|
+
assertGate(text.includes('sks seo-geo-optimizer doctor|audit|plan|apply|verify|status|rollback|fixture') && /not geolocation|GeoIP/i.test(text), 'seo-geo-optimizer skill must expose CLI entrypoint and geolocation disambiguation', { text });
|
|
262
|
+
}
|
|
263
|
+
return emitGate(id, { skills: report.created.length, search_visibility_skills_checked: 2 });
|
|
255
264
|
}
|
|
256
265
|
const previous = swapEnv({ SKS_CODEX_AGENT_TYPE_FIXTURE: 'supported' });
|
|
257
266
|
try {
|
|
@@ -6,27 +6,17 @@ import path from 'node:path';
|
|
|
6
6
|
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
7
7
|
const mod = await importDist('core/source-intelligence/source-intelligence-runner.js');
|
|
8
8
|
const dir = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-source-intelligence-'));
|
|
9
|
-
const
|
|
10
|
-
missionDir: dir,
|
|
11
|
-
route: '$Team',
|
|
12
|
-
query: 'fixture',
|
|
13
|
-
context7: async () => [{ title: 'docs' }],
|
|
14
|
-
codexWebSearch: async () => [{ title: 'web', url: 'https://example.com' }],
|
|
15
|
-
xaiDetection: { configured: false, search_capable: false, configured_but_unverified: false, status: 'missing' },
|
|
16
|
-
env: { SKS_CODEX_WEB_SEARCH_AVAILABLE: '1' }
|
|
17
|
-
});
|
|
18
|
-
const withXai = await mod.runSourceIntelligence({
|
|
9
|
+
const common = {
|
|
19
10
|
missionDir: dir,
|
|
20
11
|
route: '$Research',
|
|
21
|
-
|
|
22
|
-
context7: async () => [{ title: 'docs' }],
|
|
12
|
+
context7: async () => [{ title: 'docs', url: 'https://docs.example.com' }],
|
|
23
13
|
codexWebSearch: async () => [{ title: 'web', url: 'https://example.com' }],
|
|
24
|
-
xaiSearch: async () => [{ title: 'x', url: 'https://x.ai' }],
|
|
25
|
-
xaiDetection: { configured: true, search_capable: true, configured_but_unverified: false, status: 'search_capable' },
|
|
26
14
|
env: { SKS_CODEX_WEB_SEARCH_AVAILABLE: '1' }
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
assertGate(
|
|
31
|
-
|
|
15
|
+
};
|
|
16
|
+
const balanced = await mod.runSourceIntelligence({ ...common, query: 'fixture' });
|
|
17
|
+
const xSearch = await mod.runSourceIntelligence({ ...common, query: 'site:x.com product launch', xaiDetection: { configured: true, search_capable: true } });
|
|
18
|
+
assertGate(balanced.ok === true && balanced.mode === 'ultra_balanced', 'balanced UltraSearch mode must pass with provider-independent proof', balanced);
|
|
19
|
+
assertGate(xSearch.ok === false && xSearch.mode === 'x_search' && xSearch.blockers.includes('x_search_parity_not_proven'), 'X mode must not treat discovery-only public X evidence as parity', xSearch);
|
|
20
|
+
assertGate(xSearch.parallel.providers_requested.includes('x_public'), 'X public provider must be capability-selected', xSearch.parallel);
|
|
21
|
+
emitGate('source-intelligence:all-modes', { modes: [balanced.mode, xSearch.mode], x_parity_claim: 'not_proven_without_real_corpus' });
|
|
32
22
|
//# sourceMappingURL=source-intelligence-all-modes-check.js.map
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
import { assertFiles, assertGate, emitGate, importDist, SOURCE_INTELLIGENCE_FILES } from './sks-1-18-gate-lib.js';
|
|
4
4
|
assertFiles(SOURCE_INTELLIGENCE_FILES);
|
|
5
5
|
const mod = await importDist('core/source-intelligence/source-intelligence-policy.js');
|
|
6
|
-
const base = mod.buildSourceIntelligencePolicy({ context7Available: true, codexWebCapability: { available: true, status: 'available', reason: 'fixture' }
|
|
7
|
-
const
|
|
8
|
-
const blocked = mod.buildSourceIntelligencePolicy({ context7Available: false });
|
|
9
|
-
assertGate(base.mode === '
|
|
10
|
-
assertGate(
|
|
6
|
+
const base = mod.buildSourceIntelligencePolicy({ query: 'current release notes', context7Available: true, codexWebCapability: { available: true, status: 'available', reason: 'fixture' } });
|
|
7
|
+
const xSearch = mod.buildSourceIntelligencePolicy({ query: 'site:x.com product launch', context7Available: true, codexWebCapability: { available: true, status: 'available', reason: 'fixture' }, xaiDetection: { configured: true, search_capable: true } });
|
|
8
|
+
const blocked = mod.buildSourceIntelligencePolicy({ query: 'npm package docs', context7Available: false });
|
|
9
|
+
assertGate(base.mode === 'ultra_balanced', 'default mode must be ultra_balanced', base);
|
|
10
|
+
assertGate(xSearch.mode === 'x_search' && xSearch.selected_providers.includes('x_public') && !Object.hasOwn(xSearch, ['xai', 'mcp'].join('_')), 'X-search mode must be provider-independent and ignore xAI detection', xSearch);
|
|
11
11
|
assertGate(blocked.mode === 'blocked' && blocked.blockers.includes('docs_context_missing'), 'Context7 missing must block docs context');
|
|
12
|
-
emitGate('source-intelligence:policy', { modes: [base.mode,
|
|
12
|
+
emitGate('source-intelligence:policy', { modes: [base.mode, xSearch.mode, blocked.mode] });
|
|
13
13
|
//# sourceMappingURL=source-intelligence-policy-check.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
2
|
import { assertGate, emitGate, importDist, root } from './sks-1-18-gate-lib.js';
|
|
3
3
|
const mod = await importDist('core/triwiki/triwiki-affected-graph.js');
|
|
4
|
-
const graph = mod.computeTriWikiAffectedGraph({ root, changedFiles: ['src/core/triwiki/triwiki-proof-bank.ts'], tier: 'affected' });
|
|
4
|
+
const graph = mod.computeTriWikiAffectedGraph({ root, changedFiles: ['src/core/triwiki/triwiki-proof-bank.ts'], tier: 'affected', includeProofLookup: false });
|
|
5
5
|
assertGate(graph.schema === 'sks.triwiki-affected-graph.v1', 'affected graph schema mismatch', graph);
|
|
6
6
|
assertGate(graph.affected_modules.includes('triwiki') && graph.gate_packs.includes('triwiki') && graph.release_equivalent_within_scope === true, 'triwiki file must select triwiki release-equivalent pack', graph);
|
|
7
|
-
const full = mod.computeTriWikiAffectedGraph({ root, full: true, tier: 'release' });
|
|
7
|
+
const full = mod.computeTriWikiAffectedGraph({ root, full: true, tier: 'release', includeProofLookup: false });
|
|
8
8
|
assertGate(full.gates.length > graph.gates.length && full.gate_packs.length >= graph.gate_packs.length && full.conservative_reason === 'full_release_requested', 'full release graph must select the full gate surface', full);
|
|
9
9
|
emitGate('triwiki:affected-graph', { gates: graph.gates.length, packs: graph.gate_packs, full_gates: full.gates.length });
|
|
10
10
|
//# sourceMappingURL=triwiki-affected-graph-check.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-nocheck
|
|
3
|
+
import fs from 'node:fs/promises';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { assertGate, emitGate, importDist } from './sks-1-18-gate-lib.js';
|
|
7
|
+
const mod = await importDist('core/ultra-search/index.js');
|
|
8
|
+
const missionDir = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-ultra-search-'));
|
|
9
|
+
const result = await mod.runUltraSearch({
|
|
10
|
+
missionDir,
|
|
11
|
+
query: 'npm package docs',
|
|
12
|
+
mode: 'balanced',
|
|
13
|
+
context7: async () => [{ title: 'npm docs', url: 'https://docs.npmjs.com', snippet: 'official docs' }],
|
|
14
|
+
codexWebSearch: async () => [{ title: 'npm registry', url: 'https://www.npmjs.com/package/npm', snippet: 'registry' }],
|
|
15
|
+
env: { SKS_CODEX_WEB_SEARCH_AVAILABLE: '1' }
|
|
16
|
+
});
|
|
17
|
+
assertGate(result.proof.provider_independent === true, 'UltraSearch proof must be provider-independent', result.proof);
|
|
18
|
+
assertGate(result.proof.xai_runtime_dependency === false, 'UltraSearch must not require xAI runtime', result.proof);
|
|
19
|
+
assertGate(result.sources.some((source) => source.acquisition_verdict === 'verified_content'), 'UltraSearch must normalize verified source evidence', result.sources);
|
|
20
|
+
assertGate(result.convergence.schema === 'sks.ultra-search-convergence.v1', 'UltraSearch convergence artifact must be typed', result.convergence);
|
|
21
|
+
emitGate('ultra-search:provider-interface', {
|
|
22
|
+
mode: result.mode,
|
|
23
|
+
sources: result.sources.length,
|
|
24
|
+
verified: result.proof.verified_source_count,
|
|
25
|
+
xai_runtime_dependency: result.proof.xai_runtime_dependency
|
|
26
|
+
});
|
|
27
|
+
//# sourceMappingURL=ultra-search-provider-interface-check.js.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sneakoscope",
|
|
3
3
|
"displayName": "ㅅㅋㅅ",
|
|
4
|
-
"version": "4.
|
|
4
|
+
"version": "4.3.0",
|
|
5
5
|
"description": "Sneakoscope Codex: fast proof-first Codex trust layer with image-based Voxel TriWiki.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"homepage": "https://github.com/mandarange/Sneakoscope-Codex#readme",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"publishConfig": {
|
|
20
20
|
"access": "public",
|
|
21
21
|
"registry": "https://registry.npmjs.org/",
|
|
22
|
-
"tag": "
|
|
22
|
+
"tag": "backfill-4-3"
|
|
23
23
|
},
|
|
24
24
|
"files": [
|
|
25
25
|
"dist",
|
|
@@ -68,6 +68,21 @@
|
|
|
68
68
|
"typescript:migration-report": "node ./dist/scripts/typescript-migration-report.js",
|
|
69
69
|
"typecheck:contracts": "node ./dist/scripts/check-ts-contracts.js",
|
|
70
70
|
"schema:check": "node ./dist/scripts/check-runtime-schemas.js",
|
|
71
|
+
"seo:cli-blackbox": "node ./dist/scripts/seo-cli-blackbox-check.js",
|
|
72
|
+
"seo:audit-fixture": "node ./dist/scripts/seo-audit-fixture-check.js",
|
|
73
|
+
"seo:no-mutation-by-default": "node ./dist/scripts/seo-no-mutation-by-default-check.js",
|
|
74
|
+
"seo:mutation-rollback": "node ./dist/scripts/seo-mutation-rollback-check.js",
|
|
75
|
+
"seo:canonical-sitemap-locale": "node ./dist/scripts/seo-canonical-locale-check.js",
|
|
76
|
+
"seo:structured-data-visible-content": "node ./dist/scripts/seo-structured-data-visible-content-check.js",
|
|
77
|
+
"geo:cli-blackbox": "node ./dist/scripts/geo-cli-blackbox-check.js",
|
|
78
|
+
"geo:claim-evidence": "node ./dist/scripts/geo-claim-evidence-check.js",
|
|
79
|
+
"geo:crawler-purpose-policy": "node ./dist/scripts/geo-crawler-policy-check.js",
|
|
80
|
+
"geo:llms-txt-optional": "node ./dist/scripts/geo-llms-txt-optional-check.js",
|
|
81
|
+
"seo-geo:route-identity": "node ./dist/scripts/seo-geo-route-identity-check.js",
|
|
82
|
+
"seo-geo:geo-disambiguation": "node ./dist/scripts/seo-geo-geo-disambiguation-check.js",
|
|
83
|
+
"seo-geo:skill-rich-content": "node ./dist/scripts/seo-geo-skill-rich-content-check.js",
|
|
84
|
+
"seo-geo:no-unsupported-ranking-claims": "node ./dist/scripts/seo-geo-no-unsupported-ranking-claims-check.js",
|
|
85
|
+
"seo-geo:feature-fixture-quality": "node ./dist/scripts/seo-geo-feature-fixture-quality-check.js",
|
|
71
86
|
"package-boundary:check": "node ./dist/scripts/check-package-boundary.js",
|
|
72
87
|
"blackbox:command-import-smoke": "node ./dist/scripts/blackbox-command-import-smoke.js",
|
|
73
88
|
"repo-audit": "node ./dist/scripts/repo-audit.js",
|
|
@@ -323,6 +338,7 @@
|
|
|
323
338
|
"codex-control:side-effect-scope": "node ./dist/scripts/codex-control-side-effect-scope-check.js",
|
|
324
339
|
"codex-control:all-pipelines": "node ./dist/scripts/codex-control-all-pipelines-check.js",
|
|
325
340
|
"codex-control:empty-result-retry": "node ./dist/scripts/codex-control-empty-result-retry-check.js",
|
|
341
|
+
"codex-control:model-capacity-fallback": "node ./dist/scripts/codex-control-model-capacity-fallback-check.js",
|
|
326
342
|
"codex-control:stream-idle-watchdog": "node ./dist/scripts/codex-control-stream-idle-watchdog-check.js",
|
|
327
343
|
"codex-control:tool-call-sequence-repair": "node ./dist/scripts/codex-control-tool-call-sequence-repair-check.js",
|
|
328
344
|
"codex-control:keepalive-no-cot-leak": "node ./dist/scripts/codex-control-keepalive-no-cot-leak-check.js",
|
|
@@ -359,9 +375,10 @@
|
|
|
359
375
|
"coverage": "node --experimental-test-coverage --test \"test/**/*.test.mjs\"",
|
|
360
376
|
"release:check": "npm run release:check:affected",
|
|
361
377
|
"release:real-check": "node ./dist/scripts/release-real-check.js",
|
|
362
|
-
"release:publish": "npm run publish:
|
|
378
|
+
"release:publish": "npm run publish:ignore-scripts",
|
|
363
379
|
"publish:dry": "npm run release:metadata && npm run release:version-truth && npm run publish:packlist-performance && npm run release:check:full && node ./dist/scripts/check-publish-tag.js && node ./dist/scripts/release-check-stamp.js verify && npm run release:provenance -- --publish && npm run release:dist-freshness && node ./dist/scripts/release-registry-check.js --require-unpublished && npm --cache /tmp/sks-npm-cache publish --dry-run --ignore-scripts --registry https://registry.npmjs.org/ --access public",
|
|
364
|
-
"publish:
|
|
380
|
+
"publish:ignore-scripts": "npm run prepublishOnly && npm --cache /tmp/sks-npm-cache publish --ignore-scripts --registry https://registry.npmjs.org/ --access public",
|
|
381
|
+
"publish:npm": "npm run publish:ignore-scripts",
|
|
365
382
|
"publish:fast": "node -e \"console.error('publish:fast is quarantined; use publish:dry and publish:npm with the release gates.'); process.exit(1)\"",
|
|
366
383
|
"prepack": "npm run build",
|
|
367
384
|
"prepublishOnly": "npm run release:metadata && npm run release:version-truth && npm run release:dist-freshness && npm run publish:packlist-performance && node ./dist/scripts/prepublish-release-check-or-fast.js && node ./dist/scripts/check-publish-tag.js && node ./dist/scripts/release-check-stamp.js verify && npm run release:provenance -- --publish && node ./dist/scripts/release-registry-check.js --require-unpublished --require-publish-auth",
|
|
@@ -474,12 +491,12 @@
|
|
|
474
491
|
"qa:native-agent-backend": "node ./dist/scripts/agent-native-release-gate.js qa-native-agent-backend",
|
|
475
492
|
"agent:non-recursive-pipeline-report": "node ./dist/scripts/non-recursive-pipeline-check.js --json",
|
|
476
493
|
"agent:legacy-multiagent-removed": "node ./dist/scripts/legacy-multiagent-removal-check.js",
|
|
477
|
-
"xai-mcp:capability": "node ./dist/scripts/xai-mcp-capability-check.js",
|
|
478
494
|
"mcp:0.134-modernization": "node ./dist/scripts/mcp-0-134-modernization-check.js",
|
|
479
495
|
"mcp:readonly-concurrency": "node ./dist/scripts/mcp-readonly-concurrency-check.js",
|
|
480
496
|
"mcp:readonly-runtime-scheduler": "node ./dist/scripts/mcp-readonly-runtime-scheduler-check.js",
|
|
481
497
|
"codex:0.134-runner-truth": "node ./dist/scripts/codex-0-134-runner-truth-check.js",
|
|
482
498
|
"source-intelligence:policy": "node ./dist/scripts/source-intelligence-policy-check.js",
|
|
499
|
+
"ultra-search:provider-interface": "node ./dist/scripts/ultra-search-provider-interface-check.js",
|
|
483
500
|
"context7:evidence-dedupe": "node ./dist/scripts/context7-evidence-dedupe-check.js",
|
|
484
501
|
"source-intelligence:codex-history-search": "node ./dist/scripts/codex-history-search-check.js",
|
|
485
502
|
"source-intelligence:all-modes": "node ./dist/scripts/source-intelligence-all-modes-check.js",
|
|
@@ -619,6 +636,7 @@
|
|
|
619
636
|
"qa-loop:effort-escalation": "node ./dist/scripts/qa-loop-effort-escalation-check.js",
|
|
620
637
|
"codex:account-usage": "node ./dist/scripts/codex-account-usage-check.js",
|
|
621
638
|
"qa-loop:budget-policy": "node ./dist/scripts/qa-loop-budget-policy-check.js",
|
|
639
|
+
"qa-loop:surface-router": "node ./dist/scripts/qa-loop-surface-router-check.js",
|
|
622
640
|
"naruto:parallel-gate-consistency": "node ./dist/scripts/naruto-parallel-gate-consistency-check.js",
|
|
623
641
|
"codex:0138-doctor": "node ./dist/scripts/codex-0138-doctor-check.js",
|
|
624
642
|
"doctor:codex-0138-fix": "node ./dist/scripts/doctor-codex-0138-fix-check.js",
|
|
@@ -1079,6 +1097,9 @@
|
|
|
1079
1097
|
"goal",
|
|
1080
1098
|
"research",
|
|
1081
1099
|
"autoresearch",
|
|
1100
|
+
"seo",
|
|
1101
|
+
"search-visibility",
|
|
1102
|
+
"generative-engine-optimization",
|
|
1082
1103
|
"honest-mode",
|
|
1083
1104
|
"update-check",
|
|
1084
1105
|
"llm-wiki",
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://sneakoscope.dev/schemas/search-visibility/finding-ledger.schema.json",
|
|
4
|
+
"title": "SKS Search Visibility Finding Ledger",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": ["schema", "mission_id", "route", "findings", "counts"],
|
|
7
|
+
"properties": {
|
|
8
|
+
"schema": { "enum": ["sks.search-visibility.seo-findings.v1", "sks.search-visibility.geo-findings.v1"] },
|
|
9
|
+
"mission_id": { "type": "string" },
|
|
10
|
+
"route": { "const": "$SEO-GEO-OPTIMIZER" },
|
|
11
|
+
"findings": {
|
|
12
|
+
"type": "array",
|
|
13
|
+
"items": {
|
|
14
|
+
"type": "object",
|
|
15
|
+
"required": ["id", "ruleId", "domain", "category", "severity", "confidence", "blocking", "summary", "evidence", "affected", "remediation", "autoFixable"],
|
|
16
|
+
"properties": {
|
|
17
|
+
"id": { "type": "string" },
|
|
18
|
+
"ruleId": { "type": "string" },
|
|
19
|
+
"domain": { "enum": ["seo", "geo", "shared"] },
|
|
20
|
+
"category": { "type": "string" },
|
|
21
|
+
"severity": { "enum": ["info", "low", "medium", "high", "critical"] },
|
|
22
|
+
"confidence": { "type": "number" },
|
|
23
|
+
"blocking": { "type": "boolean" },
|
|
24
|
+
"summary": { "type": "string" },
|
|
25
|
+
"evidence": { "type": "array", "minItems": 1 },
|
|
26
|
+
"affected": { "type": "array" },
|
|
27
|
+
"remediation": { "type": "string" },
|
|
28
|
+
"autoFixable": { "type": "boolean" }
|
|
29
|
+
},
|
|
30
|
+
"additionalProperties": true
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"counts": { "type": "object" }
|
|
34
|
+
},
|
|
35
|
+
"additionalProperties": true
|
|
36
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://sneakoscope.dev/schemas/search-visibility/gate.schema.json",
|
|
4
|
+
"title": "SKS Search Visibility Gate",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": ["schema", "mission_id", "route", "ok", "passed", "status", "command_identity", "required_artifacts", "unsupported_claims", "blockers", "unverified", "completion_proof"],
|
|
7
|
+
"properties": {
|
|
8
|
+
"schema": { "const": "sks.search-visibility.gate.v1" },
|
|
9
|
+
"mission_id": { "type": "string" },
|
|
10
|
+
"route": { "const": "$SEO-GEO-OPTIMIZER" },
|
|
11
|
+
"ok": { "type": "boolean" },
|
|
12
|
+
"passed": { "type": "boolean" },
|
|
13
|
+
"status": { "enum": ["verified_partial", "blocked", "locally_verified", "production_verified"] },
|
|
14
|
+
"command_identity": { "type": "boolean" },
|
|
15
|
+
"required_artifacts": { "type": "array" },
|
|
16
|
+
"unsupported_claims": { "type": "array" },
|
|
17
|
+
"blockers": { "type": "array" },
|
|
18
|
+
"unverified": { "type": "array" },
|
|
19
|
+
"completion_proof": { "type": "string" }
|
|
20
|
+
},
|
|
21
|
+
"additionalProperties": true
|
|
22
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://sneakoscope.dev/schemas/search-visibility/mutation-plan.schema.json",
|
|
4
|
+
"title": "SKS Search Visibility Mutation Plan",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": ["schema", "mission_id", "route", "mode", "adapter", "detection_confidence", "status", "operations", "blockers", "unverified"],
|
|
7
|
+
"properties": {
|
|
8
|
+
"schema": { "const": "sks.search-visibility.mutation-plan.v1" },
|
|
9
|
+
"mission_id": { "type": "string" },
|
|
10
|
+
"route": { "const": "$SEO-GEO-OPTIMIZER" },
|
|
11
|
+
"mode": { "enum": ["seo", "geo"] },
|
|
12
|
+
"adapter": { "type": "string" },
|
|
13
|
+
"detection_confidence": { "type": "number" },
|
|
14
|
+
"status": { "enum": ["planned", "blocked"] },
|
|
15
|
+
"operations": {
|
|
16
|
+
"type": "array",
|
|
17
|
+
"items": {
|
|
18
|
+
"type": "object",
|
|
19
|
+
"required": ["id", "path", "baseSha256", "proposedSha256", "kind", "owner", "findingIds", "reversible", "preview", "risk", "requiredVerification", "scopeAuthorization", "ownershipStrategy"],
|
|
20
|
+
"additionalProperties": true
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"blockers": { "type": "array" },
|
|
24
|
+
"unverified": { "type": "array" }
|
|
25
|
+
},
|
|
26
|
+
"additionalProperties": true
|
|
27
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://sneakoscope.dev/schemas/search-visibility/site-inventory.schema.json",
|
|
4
|
+
"title": "SKS Search Visibility Site Inventory",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": ["schema", "mission_id", "route", "root", "target", "detected_adapter", "package", "routes", "policy_files"],
|
|
7
|
+
"properties": {
|
|
8
|
+
"schema": { "const": "sks.search-visibility.site-inventory.v1" },
|
|
9
|
+
"mission_id": { "type": "string" },
|
|
10
|
+
"route": { "const": "$SEO-GEO-OPTIMIZER" },
|
|
11
|
+
"root": { "type": "string" },
|
|
12
|
+
"target": { "enum": ["website", "docs", "package"] },
|
|
13
|
+
"detected_adapter": { "type": "object" },
|
|
14
|
+
"package": { "type": "object" },
|
|
15
|
+
"routes": { "type": "array" },
|
|
16
|
+
"policy_files": { "type": "array" },
|
|
17
|
+
"blockers": { "type": "array" },
|
|
18
|
+
"unverified": { "type": "array" }
|
|
19
|
+
},
|
|
20
|
+
"additionalProperties": true
|
|
21
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://sneakoscope.dev/schemas/search-visibility/verification-report.schema.json",
|
|
4
|
+
"title": "SKS Search Visibility Verification Report",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": ["schema", "mission_id", "route", "status", "source_verified", "build_verified", "http_verified", "browser_verified", "production_verified", "measured_outcome", "checked_artifacts", "blockers", "unverified"],
|
|
7
|
+
"properties": {
|
|
8
|
+
"schema": { "const": "sks.search-visibility.verification-report.v1" },
|
|
9
|
+
"mission_id": { "type": "string" },
|
|
10
|
+
"route": { "const": "$SEO-GEO-OPTIMIZER" },
|
|
11
|
+
"status": { "enum": ["verified_partial", "blocked", "locally_verified", "production_verified", "measured_outcome_pending", "measured_outcome_recorded"] },
|
|
12
|
+
"source_verified": { "type": "boolean" },
|
|
13
|
+
"build_verified": { "type": "boolean" },
|
|
14
|
+
"http_verified": { "type": "boolean" },
|
|
15
|
+
"browser_verified": { "type": "boolean" },
|
|
16
|
+
"production_verified": { "type": "boolean" },
|
|
17
|
+
"measured_outcome": { "enum": ["pending", "recorded", "not_applicable"] },
|
|
18
|
+
"checked_artifacts": { "type": "array" },
|
|
19
|
+
"blockers": { "type": "array" },
|
|
20
|
+
"unverified": { "type": "array" }
|
|
21
|
+
},
|
|
22
|
+
"additionalProperties": true
|
|
23
|
+
}
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import os from 'node:os';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import { exists, nowIso, readText } from '../fsx.js';
|
|
4
|
-
export const XAI_MCP_DETECTION_SCHEMA = 'sks.xai-mcp-detection.v1';
|
|
5
|
-
const XAI_SERVER_RE = /(?:^|[-_\s.])(xai|x-ai|x_ai|grok|x\.ai)(?:$|[-_\s.])/i;
|
|
6
|
-
const SEARCH_TOOL_RE = /(?:search|query|web|retrieve|retrieval|news|grok)/i;
|
|
7
|
-
export function isXaiServerName(name) {
|
|
8
|
-
return XAI_SERVER_RE.test(normalizeName(name));
|
|
9
|
-
}
|
|
10
|
-
export function isSearchToolName(name) {
|
|
11
|
-
return SEARCH_TOOL_RE.test(normalizeName(name));
|
|
12
|
-
}
|
|
13
|
-
export async function detectXaiMcp(opts = {}) {
|
|
14
|
-
const root = path.resolve(opts.root || process.cwd());
|
|
15
|
-
const home = opts.home || os.homedir();
|
|
16
|
-
const configPaths = [
|
|
17
|
-
{ path: path.join(home, '.codex', 'config.toml'), source: 'user' },
|
|
18
|
-
{ path: path.join(root, '.codex', 'config.toml'), source: 'project' },
|
|
19
|
-
{ path: path.join(root, '.codex', 'config.json'), source: 'project' }
|
|
20
|
-
];
|
|
21
|
-
const provided = opts.configSources || [];
|
|
22
|
-
const discovered = [...provided];
|
|
23
|
-
for (const entry of configPaths) {
|
|
24
|
-
if (provided.some((source) => path.resolve(source.path) === path.resolve(entry.path)))
|
|
25
|
-
continue;
|
|
26
|
-
if (await exists(entry.path)) {
|
|
27
|
-
discovered.push({ path: entry.path, source: entry.source, text: String(await readText(entry.path, '')) });
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return detectXaiMcpFromConfig(discovered, {
|
|
31
|
-
checked: configPaths.map((entry) => entry.path),
|
|
32
|
-
toolLists: opts.toolLists || {}
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
export function detectXaiMcpFromConfig(sources = [], opts = {}) {
|
|
36
|
-
try {
|
|
37
|
-
const servers = sources.flatMap((source) => detectServersInSource(source, opts.toolLists || {}));
|
|
38
|
-
const configured = servers.length > 0;
|
|
39
|
-
const searchCapable = servers.some((server) => server.search_capable);
|
|
40
|
-
const configuredButUnverified = configured && !searchCapable && servers.some((server) => server.configured_but_unverified);
|
|
41
|
-
const status = !configured
|
|
42
|
-
? 'missing'
|
|
43
|
-
: searchCapable
|
|
44
|
-
? 'search_capable'
|
|
45
|
-
: configuredButUnverified
|
|
46
|
-
? 'configured_but_unverified'
|
|
47
|
-
: 'configured_no_search';
|
|
48
|
-
return {
|
|
49
|
-
schema: XAI_MCP_DETECTION_SCHEMA,
|
|
50
|
-
generated_at: nowIso(),
|
|
51
|
-
ok: true,
|
|
52
|
-
status,
|
|
53
|
-
configured,
|
|
54
|
-
search_capable: searchCapable,
|
|
55
|
-
configured_but_unverified: configuredButUnverified,
|
|
56
|
-
servers,
|
|
57
|
-
config_paths_checked: [...new Set([...(opts.checked || []), ...sources.map((source) => source.path)])],
|
|
58
|
-
config_paths_found: sources.map((source) => source.path),
|
|
59
|
-
blockers: [],
|
|
60
|
-
warnings: configuredButUnverified ? ['xai_mcp_configured_but_tool_list_unverified'] : []
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
catch (err) {
|
|
64
|
-
return {
|
|
65
|
-
schema: XAI_MCP_DETECTION_SCHEMA,
|
|
66
|
-
generated_at: nowIso(),
|
|
67
|
-
ok: false,
|
|
68
|
-
status: 'error',
|
|
69
|
-
configured: false,
|
|
70
|
-
search_capable: false,
|
|
71
|
-
configured_but_unverified: false,
|
|
72
|
-
servers: [],
|
|
73
|
-
config_paths_checked: opts.checked || [],
|
|
74
|
-
config_paths_found: sources.map((source) => source.path),
|
|
75
|
-
blockers: [`xai_mcp_detection_error:${err instanceof Error ? err.message : String(err)}`],
|
|
76
|
-
warnings: []
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
function detectServersInSource(source, toolLists) {
|
|
81
|
-
const jsonServers = parseJsonServers(source);
|
|
82
|
-
const tomlServers = jsonServers.length ? [] : parseTomlServerNames(source.text);
|
|
83
|
-
const names = [...jsonServers, ...tomlServers].filter((server) => isXaiServerName(server.name));
|
|
84
|
-
return names.map((server) => {
|
|
85
|
-
const configuredTools = [...server.tools, ...(toolLists[server.name] || []), ...(toolLists[normalizeName(server.name)] || [])];
|
|
86
|
-
const uniqueTools = [...new Set(configuredTools.map(String).filter(Boolean))];
|
|
87
|
-
const searchCapable = uniqueTools.some(isSearchToolName);
|
|
88
|
-
return {
|
|
89
|
-
name: normalizeName(server.name),
|
|
90
|
-
source: `${source.source}:${source.path}`,
|
|
91
|
-
configured: true,
|
|
92
|
-
search_capable: searchCapable,
|
|
93
|
-
configured_but_unverified: !searchCapable && uniqueTools.length === 0,
|
|
94
|
-
tools: uniqueTools,
|
|
95
|
-
raw_name: server.name
|
|
96
|
-
};
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
function parseJsonServers(source) {
|
|
100
|
-
const text = source.text.trim();
|
|
101
|
-
if (!text.startsWith('{'))
|
|
102
|
-
return [];
|
|
103
|
-
try {
|
|
104
|
-
const parsed = JSON.parse(text);
|
|
105
|
-
const servers = parsed?.mcp_servers || parsed?.mcpServers || {};
|
|
106
|
-
return Object.entries(servers).map(([name, value]) => ({
|
|
107
|
-
name,
|
|
108
|
-
tools: extractToolNames(value)
|
|
109
|
-
}));
|
|
110
|
-
}
|
|
111
|
-
catch {
|
|
112
|
-
return [];
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
function parseTomlServerNames(text) {
|
|
116
|
-
const rows = [];
|
|
117
|
-
const tableRe = /^\s*\[(?:mcp_servers|mcpServers)\.([^\]]+)\]\s*$/gm;
|
|
118
|
-
let match;
|
|
119
|
-
while ((match = tableRe.exec(text)) !== null) {
|
|
120
|
-
const name = unquote(match[1] || '');
|
|
121
|
-
const bodyStart = match.index + match[0].length;
|
|
122
|
-
const nextTable = text.slice(bodyStart).search(/^\s*\[/m);
|
|
123
|
-
const body = nextTable >= 0 ? text.slice(bodyStart, bodyStart + nextTable) : text.slice(bodyStart);
|
|
124
|
-
rows.push({ name, tools: extractToolNamesFromText(body) });
|
|
125
|
-
}
|
|
126
|
-
return rows;
|
|
127
|
-
}
|
|
128
|
-
function extractToolNames(value) {
|
|
129
|
-
if (!value || typeof value !== 'object')
|
|
130
|
-
return [];
|
|
131
|
-
const possible = [
|
|
132
|
-
value.tools,
|
|
133
|
-
value.tool_names,
|
|
134
|
-
value.capabilities,
|
|
135
|
-
value.search_tools
|
|
136
|
-
];
|
|
137
|
-
return possible.flatMap((entry) => Array.isArray(entry) ? entry.map(String) : []);
|
|
138
|
-
}
|
|
139
|
-
function extractToolNamesFromText(text) {
|
|
140
|
-
const tools = [];
|
|
141
|
-
const arrayRe = /(?:tools|tool_names|capabilities|search_tools)\s*=\s*\[([^\]]*)\]/g;
|
|
142
|
-
let match;
|
|
143
|
-
while ((match = arrayRe.exec(text)) !== null) {
|
|
144
|
-
tools.push(...String(match[1] || '').split(',').map((part) => unquote(part.trim())).filter(Boolean));
|
|
145
|
-
}
|
|
146
|
-
const keyRe = /^\s*(search|query|web|retrieve|news|grok)\s*=/gmi;
|
|
147
|
-
while ((match = keyRe.exec(text)) !== null)
|
|
148
|
-
tools.push(match[1] || '');
|
|
149
|
-
return tools;
|
|
150
|
-
}
|
|
151
|
-
function normalizeName(name) {
|
|
152
|
-
return String(name || '').trim().replace(/^["']|["']$/g, '').toLowerCase();
|
|
153
|
-
}
|
|
154
|
-
function unquote(value) {
|
|
155
|
-
return String(value || '').trim().replace(/^["']|["']$/g, '');
|
|
156
|
-
}
|
|
157
|
-
//# sourceMappingURL=xai-mcp-detector.js.map
|