@@ -122,6 +122,9 @@ const mocks = vi.hoisted(() => ({
122122 } ) ,
123123 ) ,
124124 collectStalePluginRuntimeSymlinkHealthFindings : vi . fn ( async ( ) => [ ] as unknown [ ] ) ,
125+ collectChannelPreviewWarningHealthFindings : vi . fn (
126+ async ( ) : Promise < readonly HealthFinding [ ] > => [ ] ,
127+ ) ,
125128 applyWizardMetadata : vi . fn ( ( cfg : unknown ) => cfg ) ,
126129 logConfigUpdated : vi . fn ( ) ,
127130 isRecord : vi . fn (
@@ -368,6 +371,14 @@ vi.mock("../commands/doctor/shared/channel-plugin-blockers.js", () => ({
368371 channelPluginBlockerHitToHealthFinding : mocks . channelPluginBlockerHitToHealthFinding ,
369372} ) ) ;
370373
374+ vi . mock ( "./doctor-startup-channel-maintenance.js" , async ( importOriginal ) => {
375+ const actual = await importOriginal < typeof import ( "./doctor-startup-channel-maintenance.js" ) > ( ) ;
376+ return {
377+ ...actual ,
378+ collectChannelPreviewWarningHealthFindings : mocks . collectChannelPreviewWarningHealthFindings ,
379+ } ;
380+ } ) ;
381+
371382vi . mock ( "../commands/onboard-helpers.js" , ( ) => ( {
372383 applyWizardMetadata : mocks . applyWizardMetadata ,
373384 randomToken : vi . fn ( ( ) => "generated-gateway-token" ) ,
@@ -583,6 +594,8 @@ describe("doctor health contributions", () => {
583594 mocks . channelPluginBlockerHitToHealthFinding . mockClear ( ) ;
584595 mocks . collectStalePluginRuntimeSymlinkHealthFindings . mockReset ( ) ;
585596 mocks . collectStalePluginRuntimeSymlinkHealthFindings . mockResolvedValue ( [ ] ) ;
597+ mocks . collectChannelPreviewWarningHealthFindings . mockReset ( ) ;
598+ mocks . collectChannelPreviewWarningHealthFindings . mockResolvedValue ( [ ] ) ;
586599 } ) ;
587600
588601 afterEach ( ( ) => {
@@ -1399,6 +1412,7 @@ describe("doctor health contributions", () => {
13991412 expect ( contributionIds ) . toContain ( "core/doctor/whatsapp-responsiveness" ) ;
14001413 expect ( contributionIds ) . toContain ( "core/doctor/device-pairing" ) ;
14011414 expect ( contributionIds ) . toContain ( "core/doctor/channel-plugin-blockers" ) ;
1415+ expect ( contributionIds ) . toContain ( "core/doctor/channel-preview-warnings" ) ;
14021416 expect ( contributionIds ) . toContain ( "core/doctor/tool-result-cap" ) ;
14031417 expect ( contributionChecks . map ( ( check ) => check . id ) ) . toEqual ( contributionIds ) ;
14041418 } ) ;
@@ -1966,6 +1980,78 @@ describe("doctor health contributions", () => {
19661980 expect ( mocks . scanConfiguredChannelPluginBlockers ) . toHaveBeenCalledWith ( ctx . cfg , process . env ) ;
19671981 } ) ;
19681982
1983+ it ( "keeps channel preview warnings opt-in for default lint selection" , async ( ) => {
1984+ const contribution = requireDoctorContribution ( "doctor:startup-channel-maintenance" ) ;
1985+ expect ( contribution . healthCheckIds ) . toEqual ( [
1986+ "core/doctor/channel-plugin-blockers" ,
1987+ "core/doctor/channel-preview-warnings" ,
1988+ ] ) ;
1989+ const previewWarningsCheck = contribution . healthChecks . find (
1990+ ( check ) => check . id === "core/doctor/channel-preview-warnings" ,
1991+ ) as HealthCheck | undefined ;
1992+ expect ( previewWarningsCheck ) . toMatchObject ( { defaultEnabled : false } ) ;
1993+ expect ( previewWarningsCheck ) . toBeDefined ( ) ;
1994+ mocks . collectChannelPreviewWarningHealthFindings . mockResolvedValue ( [
1995+ {
1996+ checkId : "core/doctor/channel-preview-warnings" ,
1997+ severity : "warning" ,
1998+ message : "channels.matrix has a preview warning" ,
1999+ path : "channels.matrix" ,
2000+ } ,
2001+ ] ) ;
2002+
2003+ const ctx = {
2004+ cfg : { channels : { matrix : { enabled : true } } } ,
2005+ mode : "lint" ,
2006+ runtime : { log : vi . fn ( ) , error : vi . fn ( ) , exit : vi . fn ( ) } ,
2007+ } as const ;
2008+ const checks = [ previewWarningsCheck ! ] ;
2009+
2010+ await expect ( runDoctorLintChecks ( ctx , { checks } ) ) . resolves . toMatchObject ( {
2011+ checksRun : 0 ,
2012+ checksSkipped : 1 ,
2013+ } ) ;
2014+ expect ( mocks . collectChannelPreviewWarningHealthFindings ) . not . toHaveBeenCalled ( ) ;
2015+
2016+ await expect (
2017+ runDoctorLintChecks ( ctx , { checks, onlyIds : [ "core/doctor/channel-preview-warnings" ] } ) ,
2018+ ) . resolves . toMatchObject ( {
2019+ checksRun : 1 ,
2020+ checksSkipped : 0 ,
2021+ findings : [
2022+ expect . objectContaining ( {
2023+ checkId : "core/doctor/channel-preview-warnings" ,
2024+ path : "channels.matrix" ,
2025+ } ) ,
2026+ ] ,
2027+ } ) ;
2028+ expect ( mocks . collectChannelPreviewWarningHealthFindings ) . toHaveBeenCalledWith ( {
2029+ cfg : ctx . cfg ,
2030+ allowExec : false ,
2031+ } ) ;
2032+ } ) ;
2033+
2034+ it ( "forwards allow-exec secret refs into channel preview warnings" , async ( ) => {
2035+ const contribution = requireDoctorContribution ( "doctor:startup-channel-maintenance" ) ;
2036+ const previewWarningsCheck = contribution . healthChecks . find (
2037+ ( check ) => check . id === "core/doctor/channel-preview-warnings" ,
2038+ ) as HealthCheck | undefined ;
2039+ expect ( previewWarningsCheck ) . toBeDefined ( ) ;
2040+ const ctx = {
2041+ cfg : { channels : { matrix : { enabled : true } } } ,
2042+ mode : "lint" ,
2043+ runtime : { log : vi . fn ( ) , error : vi . fn ( ) , exit : vi . fn ( ) } ,
2044+ allowExecSecretRefs : true ,
2045+ } as const ;
2046+
2047+ await previewWarningsCheck ! . detect ( ctx ) ;
2048+
2049+ expect ( mocks . collectChannelPreviewWarningHealthFindings ) . toHaveBeenCalledWith ( {
2050+ cfg : ctx . cfg ,
2051+ allowExec : true ,
2052+ } ) ;
2053+ } ) ;
2054+
19692055 it ( "uses legacy run when a contribution also declares structured health" , async ( ) => {
19702056 const legacyRun = vi . fn ( ) ;
19712057 const healthChecks = {
0 commit comments