@@ -11,21 +11,28 @@ const {
1111} = require ( "./pr-quality.cjs" ) ;
1212
1313describe ( "isWrongAncestry" , ( ) => {
14- it ( "flags #644-shaped compares (0 behind main, far behind base)" , ( ) => {
14+ it ( "flags #644-shaped compares (0 behind main, far behind base, few ahead of main )" , ( ) => {
1515 assert . equal (
16- isWrongAncestry ( { behindMain : 0 , behindBase : 44 } ) ,
16+ isWrongAncestry ( { behindMain : 0 , behindBase : 44 , aheadMain : 1 } ) ,
1717 true ,
1818 ) ;
1919 } ) ;
2020
2121 it ( "uses threshold 20 by default" , ( ) => {
2222 assert . equal ( ANCESTRY_BEHIND_THRESHOLD , 20 ) ;
23- assert . equal ( isWrongAncestry ( { behindMain : 0 , behindBase : 20 } ) , true ) ;
24- assert . equal ( isWrongAncestry ( { behindMain : 0 , behindBase : 19 } ) , false ) ;
23+ assert . equal ( isWrongAncestry ( { behindMain : 0 , behindBase : 20 , aheadMain : 1 } ) , true ) ;
24+ assert . equal ( isWrongAncestry ( { behindMain : 0 , behindBase : 19 , aheadMain : 1 } ) , false ) ;
2525 } ) ;
2626
2727 it ( "passes when head is behind main (not sitting on main tip)" , ( ) => {
28- assert . equal ( isWrongAncestry ( { behindMain : 1 , behindBase : 44 } ) , false ) ;
28+ assert . equal ( isWrongAncestry ( { behindMain : 1 , behindBase : 44 , aheadMain : 1 } ) , false ) ;
29+ } ) ;
30+
31+ it ( "passes stale dev-based branches that are many commits ahead of main" , ( ) => {
32+ assert . equal (
33+ isWrongAncestry ( { behindMain : 0 , behindBase : 44 , aheadMain : 50 } ) ,
34+ false ,
35+ ) ;
2936 } ) ;
3037} ) ;
3138
@@ -65,6 +72,27 @@ describe("assessPrDescription", () => {
6572 assert . equal ( assessPrDescription ( "fix stuff" ) . reason , "thin" ) ;
6673 } ) ;
6774
75+ it ( "rejects an untouched GitHub PR template as empty/thin" , ( ) => {
76+ const body = [
77+ "## Summary" ,
78+ "" ,
79+ "- Explain the user-visible or maintainer-facing change." ,
80+ "" ,
81+ "## Verification" ,
82+ "" ,
83+ "- List the commands or checks you ran." ,
84+ "" ,
85+ "## Checklist" ,
86+ "" ,
87+ "- [ ] Scope stays focused and avoids unrelated cleanup." ,
88+ "- [ ] Docs or release notes were updated when needed." ,
89+ "- [ ] Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults." ,
90+ ] . join ( "\n" ) ;
91+ const result = assessPrDescription ( body ) ;
92+ assert . equal ( result . ok , false ) ;
93+ assert . ok ( result . reason === "empty" || result . reason === "thin" ) ;
94+ } ) ;
95+
6896 it ( "accepts two rich markdown sections" , ( ) => {
6997 const body = [
7098 "## Summary" ,
@@ -130,6 +158,7 @@ describe("collectPrQualityFailures", () => {
130158 ] . join ( "\n" ) ,
131159 behindMain : 0 ,
132160 behindBase : 44 ,
161+ aheadMain : 1 ,
133162 authorPermission : "read" ,
134163 } ) ;
135164 assert . deepEqual (
@@ -145,6 +174,7 @@ describe("collectPrQualityFailures", () => {
145174 body : "" ,
146175 behindMain : 0 ,
147176 behindBase : 44 ,
177+ aheadMain : 1 ,
148178 authorPermission : "write" ,
149179 } ) ;
150180 assert . ok ( ! failures . some ( ( f ) => f . code === "wrong_ancestry" ) ) ;
@@ -165,12 +195,33 @@ describe("collectPrQualityFailures", () => {
165195 ] . join ( "\n" ) ,
166196 behindMain : 0 ,
167197 behindBase : 44 ,
198+ aheadMain : 1 ,
168199 authorPermission : null ,
169200 permissionLookupFailed : true ,
170201 } ) ;
171202 assert . ok ( failures . some ( ( f ) => f . code === "wrong_ancestry" ) ) ;
172203 } ) ;
173204
205+ it ( "does not flag stale dev-based branches that are far ahead of main" , ( ) => {
206+ const failures = collectPrQualityFailures ( {
207+ baseRef : "dev" ,
208+ allowedBases : allowed ,
209+ body : [
210+ "## Summary" ,
211+ "This change updates the Windows tray launcher so it resolves CODEX_HOME through the shared helper instead of a hardcoded path." ,
212+ "" ,
213+ "## Test plan" ,
214+ "- Launch the tray app after setting CODEX_HOME" ,
215+ "- Confirm the listener and launcher use the same workspace root" ,
216+ ] . join ( "\n" ) ,
217+ behindMain : 0 ,
218+ behindBase : 44 ,
219+ aheadMain : 50 ,
220+ authorPermission : "read" ,
221+ } ) ;
222+ assert . ok ( ! failures . some ( ( f ) => f . code === "wrong_ancestry" ) ) ;
223+ } ) ;
224+
174225 it ( "skips ancestry when compare lookup failed (cannot evaluate)" , ( ) => {
175226 const failures = collectPrQualityFailures ( {
176227 baseRef : "dev" ,
@@ -185,6 +236,7 @@ describe("collectPrQualityFailures", () => {
185236 ] . join ( "\n" ) ,
186237 behindMain : 0 ,
187238 behindBase : 0 ,
239+ aheadMain : 0 ,
188240 authorPermission : "read" ,
189241 ancestryLookupFailed : true ,
190242 } ) ;
0 commit comments