@willbooster/shared-lib 10.20.0 → 10.22.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.
@@ -1 +1 @@
1
- {"version":3,"file":"foreignCjk.cjs","names":["HANGUL_REGEX","HAN_REGEX","CHINESE_CHARACTERS_IN_JIS_X_0208","japaneseKanji","detectForeignCjkInJapanese","characters","findForeignCjkCharactersInJapanese","text","allowedText","languages","char","allowedCharacters","kanjiSet","buildJapaneseKanjiSet","decoder","lead","trail"],"sources":["../src/foreignCjk.ts"],"sourcesContent":["export type ForeignCjkLanguage = 'chinese' | 'korean';\n\nconst HANGUL_REGEX = /\\p{Script=Hangul}/u;\nconst HAN_REGEX = /\\p{Script=Han}/u;\n// JIS X 0208 cannot encode these Jōyō kanji, which were added in 2010.\nconst JOYO_KANJI_OUTSIDE_JIS_X_0208 = '𠮟塡剝頰';\n// Kanji for Japanese names (e.g., 髙, 﨑, 濵, 栁) that Chinese prose rarely contains: the NFKC forms of the\n// Windows-31J NEC-selected IBM and IBM extension kanji that neither JIS X 0208, Big5, nor GB2312 encodes, plus 𠮷 from\n// JIS X 0213. NFKC forms are listed because the lookup runs after NFKC normalization (e.g., U+FA20 becomes U+8612).\n// Some also appear in Chinese names (e.g., 喆), but prose that mixes Chinese into Japanese hardly contains them.\n// Extension kanji that Big5 or GB2312 encodes (e.g., 德, 瀨) stay Chinese because Chinese prose uses them.\nconst JAPANESE_NAME_KANJI_OUTSIDE_JIS_X_0208 =\n '仼伃伹侊俿偂僘僴兊兤冝凬刕劜劯匇匤厓叝咊咜喆坙坥垬埈墲夋奛奝奣尞岺峵嵓嵭嶹巐弡弴彅惞愑愰憘戓抦敎昞昻晳暿曺曻朎杦栁桒棏樰橳櫢櫤涖淸澵濵焏犱犾猤玽甁硺礰竧箞絈緖罇荢葈蓜蘒蠇裵褜訷贒郞鄕釞釥鈼鉙鉷鍈鏆隝隯霳霻靍靏靑靕髙魲鮏鮱鮻鰀﨎﨏﨑﨓﨔﨟﨡﨣﨤﨧﨨﨩𠮷';\n// Characters JIS X 0208 can encode but modern Japanese prose does not use:\n// - old forms (kyūjitai) of Jōyō kanji, from the `kyujitai` npm package and Unihan's kJapaneseOldVariant,\n// except those still common in Japanese words or names (e.g., 應 in 慶應, 澤, 邊, 龍, 藝 in 東京藝術大学, 糺す)\n// - Chinese function words that Japanese writes in kana (e.g., 們, 這, 麼, 很, 怎, 跟, 嘛) and stray simplified forms (e.g., 个)\n// - traditional Chinese characters that neither table covers but Japanese never uses: 碼, 舉, 鏈, 雖\n// Other Chinese-only content characters (e.g., 媽, 豬) are not listed because separating them from rare kanji\n// that Japanese prose does use (e.g., 乖離, 瑕疵, 齟齬, 俯瞰) needs Japanese usage frequencies.\nconst CHINESE_CHARACTERS_IN_JIS_X_0208 = new Set(\n '个乘亂亞从佛來們假傳僞價儉兒兩册刄剩劍劑勞勳勵勸區卷參听呀咯哇哦唔單嘛嚴囑囘圈國圍圓圖團墮壓壘壞壤壯壹壻壽奧奬姙孃學寢實寫寶將專對屆屬峽巖帶广廢廣廳彈很徑從怎恆惡惱愼慘懷戀戰戲拂拔拜挾插搖搜擇擔據擧擴攜攝收效敍敕數斷晝曉會條棧榮樂樓樞樣檢權歐歡歸殘殼毆氣沒淨淺滯滿潛澁濕濟灣燈燒營爐爭爲犧狹獨獵獸獻瓣畫當疊癡發盜盡碎碼祕禪禮稱稻穗穩竊竝粹絲經縣縱總繩繪繼續纖缺罐聲聽肅腦膽臟臺與舉舊舍舖艷莊莖萬藏藥處號螢蟲蠶蠻衞裝襃覺覽觀觸謠證譯譽讀變讓讚豐豫貳賣贊跟踐輕轉辨辭辯這遙遞遲鄰醉醫釀釋錢鎭鏈鐵鑄鑛關陷隨險隱隸雖雙雜霸靈靜顏顯飜飮餘餠騷驅驗驛髓體髮鬪鷄鹽麥麼黏默點黨齊齒齡龜'\n);\n\nlet japaneseKanji: Set<string> | undefined;\n\n/**\n * Detects Chinese or Korean characters mixed into Japanese text, such as LLM-generated Japanese prose.\n * See {@link findForeignCjkCharactersInJapanese} for which characters count and how `allowedText` works.\n * Returns the detected languages, or an empty array if none are found.\n */\nexport function detectForeignCjkInJapanese(text: string, allowedText?: string): ForeignCjkLanguage[] {\n const characters = findForeignCjkCharactersInJapanese(text, allowedText);\n const languages: ForeignCjkLanguage[] = [];\n if (characters.some((char) => !HANGUL_REGEX.test(char))) languages.push('chinese');\n if (characters.some((char) => HANGUL_REGEX.test(char))) languages.push('korean');\n return languages;\n}\n\n/**\n * Returns the distinct Chinese or Korean characters mixed into Japanese text, NFKC-normalized, in order of appearance.\n * A kanji is treated as Chinese when it is outside JIS X 0208 (except the four Jōyō kanji 𠮟塡剝頰 and Japanese name\n * kanji that neither Big5 nor GB2312 encodes, e.g., 髙, 﨑, 𠮷) or is one of the listed old forms, Chinese function\n * words, or other Chinese-only characters that modern Japanese prose does not use (e.g., 對, 國, 這, 們, 很, 碼).\n * Old forms in names that Chinese prose also uses (e.g., 國, 與, 德) are therefore also reported, while Chinese\n * containing none of these characters (e.g., 最后返回答案, 豬肉) is not.\n * Characters that also occur in `allowedText` are not reported, so passing the input that an LLM may quote\n * (e.g., the prompt, a question, or an error message) keeps quoted names and code from being reported.\n */\nexport function findForeignCjkCharactersInJapanese(text: string, allowedText = ''): string[] {\n const allowedCharacters = new Set(allowedText.normalize('NFKC'));\n const kanjiSet = (japaneseKanji ??= buildJapaneseKanjiSet());\n const characters = new Set<string>();\n for (const char of text.normalize('NFKC')) {\n if (allowedCharacters.has(char)) continue;\n if (\n HANGUL_REGEX.test(char) ||\n (HAN_REGEX.test(char) && (!kanjiSet.has(char) || CHINESE_CHARACTERS_IN_JIS_X_0208.has(char)))\n ) {\n characters.add(char);\n }\n }\n return [...characters];\n}\n\nfunction buildJapaneseKanjiSet(): Set<string> {\n // The WHATWG `shift_jis` decoder is Windows-31J, so skip its vendor-extension lead bytes (0xED-0xFC) to keep JIS X 0208 only.\n const decoder = new TextDecoder('shift_jis');\n const kanjiSet = new Set(JOYO_KANJI_OUTSIDE_JIS_X_0208 + JAPANESE_NAME_KANJI_OUTSIDE_JIS_X_0208);\n for (let lead = 0x81; lead <= 0xEA; lead++) {\n if (lead >= 0xA0 && lead <= 0xDF) continue;\n for (let trail = 0x40; trail <= 0xFC; trail++) {\n kanjiSet.add(decoder.decode(new Uint8Array([lead, trail])));\n }\n }\n return kanjiSet;\n}\n"],"mappings":"aAEA,MAAMA,EAAe,qBACfC,EAAY,kBAiBZC,kBAAmC,IAAI,IAC3C,+RACF,EAEA,IAAIC,EAOJ,SAAgBC,EAA2B,EAAc,EAA4C,CACnG,IAAMC,EAAaC,EAAmCC,EAAMC,CAAW,EACjEC,EAAkC,CAAC,EAGzC,OAFIJ,EAAW,KAAM,GAAS,CAACL,EAAa,KAAKU,CAAI,CAAC,GAAGD,EAAU,KAAK,SAAS,EAC7EJ,EAAW,KAAM,GAASL,EAAa,KAAKU,CAAI,CAAC,GAAGD,EAAU,KAAK,QAAQ,EACxEA,CACT,CAYA,SAAgBH,EAAmC,EAAc,EAAc,GAAc,CAC3F,IAAMK,EAAoB,IAAI,IAAIH,EAAY,UAAU,MAAM,CAAC,EACzDI,EAAY,IAAkBC,EAAsB,EACpDR,kBAAa,IAAI,IACvB,IAAK,IAAMK,KAAQH,EAAK,UAAU,MAAM,EAClCI,EAAkB,IAAID,CAAI,IAE5BV,EAAa,KAAKU,CAAI,GACrBT,EAAU,KAAKS,CAAI,IAAM,CAACE,EAAS,IAAIF,CAAI,GAAKR,EAAiC,IAAIQ,CAAI,KAE1FL,EAAW,IAAIK,CAAI,EAGvB,MAAO,CAAC,GAAGL,CAAU,CACvB,CAEA,SAASQ,GAAqC,CAE5C,IAAMC,EAAU,IAAI,YAAY,WAAW,EACrCF,kBAAW,IAAI,IAAI,qIAAsE,EAC/F,IAAK,IAAIG,EAAO,IAAMA,GAAQ,IAAM,IAClC,GAAI,KAAQ,KAAQA,GAAQ,KAC5B,IAAK,IAAIC,EAAQ,GAAMA,GAAS,IAAM,IACpCJ,EAAS,IAAIE,EAAQ,OAAO,IAAI,WAAW,CAACC,EAAMC,CAAK,CAAC,CAAC,CAAC,EAG9D,OAAOJ,CACT"}
1
+ {"version":3,"file":"foreignCjk.cjs","names":["HANGUL_REGEX","HAN_REGEX","CHINESE_CHARACTERS_IN_JIS_X_0208","japaneseKanji","detectForeignCjkInJapanese","characters","findForeignCjkCharactersInJapanese","text","allowedText","languages","char","allowedCharacters","kanjiSet","buildJapaneseKanjiSet","decoder","lead","trail"],"sources":["../src/foreignCjk.ts"],"sourcesContent":["export type ForeignCjkLanguage = 'chinese' | 'korean';\n\nconst HANGUL_REGEX = /\\p{Script=Hangul}/u;\nconst HAN_REGEX = /\\p{Script=Han}/u;\n// JIS X 0208 cannot encode these Jōyō kanji, which were added in 2010.\nconst JOYO_KANJI_OUTSIDE_JIS_X_0208 = '𠮟塡剝頰';\n// Kanji for Japanese names (e.g., 髙, 﨑, 濵, 栁) that Chinese prose rarely contains: the NFKC forms of the\n// Windows-31J NEC-selected IBM and IBM extension kanji that neither JIS X 0208, Big5, nor GB2312 encodes, plus 𠮷 from\n// JIS X 0213. NFKC forms are listed because the lookup runs after NFKC normalization (e.g., U+FA20 becomes U+8612).\n// Some also appear in Chinese names (e.g., 喆), but prose that mixes Chinese into Japanese hardly contains them.\n// Extension kanji that Big5 or GB2312 encodes (e.g., 德, 瀨) stay Chinese because Chinese prose uses them.\nconst JAPANESE_NAME_KANJI_OUTSIDE_JIS_X_0208 =\n '仼伃伹侊俿偂僘僴兊兤冝凬刕劜劯匇匤厓叝咊咜喆坙坥垬埈墲夋奛奝奣尞岺峵嵓嵭嶹巐弡弴彅惞愑愰憘戓抦敎昞昻晳暿曺曻朎杦栁桒棏樰橳櫢櫤涖淸澵濵焏犱犾猤玽甁硺礰竧箞絈緖罇荢葈蓜蘒蠇裵褜訷贒郞鄕釞釥鈼鉙鉷鍈鏆隝隯霳霻靍靏靑靕髙魲鮏鮱鮻鰀﨎﨏﨑﨓﨔﨟﨡﨣﨤﨧﨨﨩𠮷';\n// Characters JIS X 0208 can encode but modern Japanese prose does not use:\n// - old forms (kyūjitai) of Jōyō kanji, from the `kyujitai` npm package and Unihan's kJapaneseOldVariant,\n// except those still common in Japanese words or names (e.g., 應 in 慶應, 澤, 邊, 龍, 藝 in 東京藝術大学, 糺す)\n// - Chinese function words that Japanese writes in kana (e.g., 們, 這, 麼, 很, 怎, 跟, 嘛) and stray simplified forms (e.g., 个)\n// - traditional Chinese characters that neither table covers but Japanese never uses: 碼, 舉, 鏈, 雖\n// Other Chinese-only content characters (e.g., 媽, 豬) are not listed because separating them from rare kanji\n// that Japanese prose does use (e.g., 乖離, 瑕疵, 齟齬, 俯瞰) needs Japanese usage frequencies.\nconst CHINESE_CHARACTERS_IN_JIS_X_0208 = new Set(\n '个乘亂亞从佛來們假傳僞價儉兒兩册刄剩劍劑勞勳勵勸區卷參听呀咯哇哦唔單嘛嚴囑囘圈國圍圓圖團墮壓壘壞壤壯壹壻壽奧奬姙孃學寢實寫寶將專對屆屬峽巖帶广廢廣廳彈很徑從怎恆惡惱愼慘懷戀戰戲拂拔拜挾插搖搜擇擔據擧擴攜攝收效敍敕數斷晝曉會條棧榮樂樓樞樣檢權歐歡歸殘殼毆氣沒淨淺滯滿潛澁濕濟灣燈燒營爐爭爲犧狹獨獵獸獻瓣畫當疊癡發盜盡碎碼祕禪禮稱稻穗穩竊竝粹絲經縣縱總繩繪繼續纖缺罐聲聽肅腦膽臟臺與舉舊舍舖艷莊莖萬藏藥處號螢蟲蠶蠻衞裝襃覺覽觀觸謠證譯譽讀變讓讚豐豫貳賣贊跟踐輕轉辨辭辯這遙遞遲鄰醉醫釀釋錢鎭鏈鐵鑄鑛關陷隨險隱隸雖雙雜霸靈靜顏顯飜飮餘餠騷驅驗驛髓體髮鬪鷄鹽麥麼黏默點黨齊齒齡龜'\n);\n\nlet japaneseKanji: Set<string> | undefined;\n\n/**\n * Detects Chinese or Korean characters mixed into Japanese text, such as LLM-generated Japanese prose.\n * See {@link findForeignCjkCharactersInJapanese} for which characters count and how `allowedText` works.\n * Returns the detected languages, or an empty array if none are found.\n */\nexport function detectForeignCjkInJapanese(text: string, allowedText?: string): ForeignCjkLanguage[] {\n const characters = findForeignCjkCharactersInJapanese(text, allowedText);\n const languages: ForeignCjkLanguage[] = [];\n if (characters.some((char) => !HANGUL_REGEX.test(char))) languages.push('chinese');\n if (characters.some((char) => HANGUL_REGEX.test(char))) languages.push('korean');\n return languages;\n}\n\n/**\n * Returns the distinct Chinese or Korean characters mixed into Japanese text, NFKC-normalized, in order of appearance.\n * A kanji is treated as Chinese when it is outside JIS X 0208 (except the four Jōyō kanji 𠮟塡剝頰 and Japanese name\n * kanji that neither Big5 nor GB2312 encodes, e.g., 髙, 﨑, 𠮷) or is one of the listed old forms, Chinese function\n * words, or other Chinese-only characters that modern Japanese prose does not use (e.g., 對, 國, 這, 們, 很, 碼).\n * Old forms in names that Chinese prose also uses (e.g., 國, 與, 德) are therefore also reported, while Chinese\n * containing none of these characters (e.g., 最后返回答案, 豬肉) is not.\n * Characters that also occur in `allowedText` are not reported, so passing the input that an LLM may quote\n * (e.g., the prompt, a question, or an error message) keeps quoted names and code from being reported.\n */\nexport function findForeignCjkCharactersInJapanese(text: string, allowedText = ''): string[] {\n const allowedCharacters = new Set(allowedText.normalize('NFKC'));\n const kanjiSet = (japaneseKanji ??= buildJapaneseKanjiSet());\n const characters = new Set<string>();\n for (const char of text.normalize('NFKC')) {\n if (allowedCharacters.has(char)) continue;\n if (\n HANGUL_REGEX.test(char) ||\n (HAN_REGEX.test(char) && (!kanjiSet.has(char) || CHINESE_CHARACTERS_IN_JIS_X_0208.has(char)))\n ) {\n characters.add(char);\n }\n }\n return [...characters];\n}\n\nfunction buildJapaneseKanjiSet(): Set<string> {\n // The WHATWG `shift_jis` decoder is Windows-31J, so skip its vendor-extension lead bytes (0xED-0xFC) to keep JIS X 0208 only.\n const decoder = new TextDecoder('shift_jis');\n const kanjiSet = new Set(JOYO_KANJI_OUTSIDE_JIS_X_0208 + JAPANESE_NAME_KANJI_OUTSIDE_JIS_X_0208);\n for (let lead = 0x81; lead <= 0xea; lead++) {\n if (lead >= 0xa0 && lead <= 0xdf) continue;\n for (let trail = 0x40; trail <= 0xfc; trail++) {\n kanjiSet.add(decoder.decode(new Uint8Array([lead, trail])));\n }\n }\n return kanjiSet;\n}\n"],"mappings":"aAEA,MAAMA,EAAe,qBACfC,EAAY,kBAiBZC,kBAAmC,IAAI,IAC3C,+RACF,EAEA,IAAIC,EAOJ,SAAgBC,EAA2B,EAAc,EAA4C,CACnG,IAAMC,EAAaC,EAAmCC,EAAMC,CAAW,EACjEC,EAAkC,CAAC,EAGzC,OAFIJ,EAAW,KAAM,GAAS,CAACL,EAAa,KAAKU,CAAI,CAAC,GAAGD,EAAU,KAAK,SAAS,EAC7EJ,EAAW,KAAM,GAASL,EAAa,KAAKU,CAAI,CAAC,GAAGD,EAAU,KAAK,QAAQ,EACxEA,CACT,CAYA,SAAgBH,EAAmC,EAAc,EAAc,GAAc,CAC3F,IAAMK,EAAoB,IAAI,IAAIH,EAAY,UAAU,MAAM,CAAC,EACzDI,EAAY,IAAkBC,EAAsB,EACpDR,kBAAa,IAAI,IACvB,IAAK,IAAMK,KAAQH,EAAK,UAAU,MAAM,EAClCI,EAAkB,IAAID,CAAI,IAE5BV,EAAa,KAAKU,CAAI,GACrBT,EAAU,KAAKS,CAAI,IAAM,CAACE,EAAS,IAAIF,CAAI,GAAKR,EAAiC,IAAIQ,CAAI,KAE1FL,EAAW,IAAIK,CAAI,EAGvB,MAAO,CAAC,GAAGL,CAAU,CACvB,CAEA,SAASQ,GAAqC,CAE5C,IAAMC,EAAU,IAAI,YAAY,WAAW,EACrCF,kBAAW,IAAI,IAAI,qIAAsE,EAC/F,IAAK,IAAIG,EAAO,IAAMA,GAAQ,IAAM,IAClC,GAAI,KAAQ,KAAQA,GAAQ,KAC5B,IAAK,IAAIC,EAAQ,GAAMA,GAAS,IAAM,IACpCJ,EAAS,IAAIE,EAAQ,OAAO,IAAI,WAAW,CAACC,EAAMC,CAAK,CAAC,CAAC,CAAC,EAG9D,OAAOJ,CACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"foreignCjk.js","names":["HANGUL_REGEX","HAN_REGEX","CHINESE_CHARACTERS_IN_JIS_X_0208","japaneseKanji","detectForeignCjkInJapanese","characters","findForeignCjkCharactersInJapanese","text","allowedText","languages","char","allowedCharacters","kanjiSet","buildJapaneseKanjiSet","decoder","lead","trail"],"sources":["../src/foreignCjk.ts"],"sourcesContent":["export type ForeignCjkLanguage = 'chinese' | 'korean';\n\nconst HANGUL_REGEX = /\\p{Script=Hangul}/u;\nconst HAN_REGEX = /\\p{Script=Han}/u;\n// JIS X 0208 cannot encode these Jōyō kanji, which were added in 2010.\nconst JOYO_KANJI_OUTSIDE_JIS_X_0208 = '𠮟塡剝頰';\n// Kanji for Japanese names (e.g., 髙, 﨑, 濵, 栁) that Chinese prose rarely contains: the NFKC forms of the\n// Windows-31J NEC-selected IBM and IBM extension kanji that neither JIS X 0208, Big5, nor GB2312 encodes, plus 𠮷 from\n// JIS X 0213. NFKC forms are listed because the lookup runs after NFKC normalization (e.g., U+FA20 becomes U+8612).\n// Some also appear in Chinese names (e.g., 喆), but prose that mixes Chinese into Japanese hardly contains them.\n// Extension kanji that Big5 or GB2312 encodes (e.g., 德, 瀨) stay Chinese because Chinese prose uses them.\nconst JAPANESE_NAME_KANJI_OUTSIDE_JIS_X_0208 =\n '仼伃伹侊俿偂僘僴兊兤冝凬刕劜劯匇匤厓叝咊咜喆坙坥垬埈墲夋奛奝奣尞岺峵嵓嵭嶹巐弡弴彅惞愑愰憘戓抦敎昞昻晳暿曺曻朎杦栁桒棏樰橳櫢櫤涖淸澵濵焏犱犾猤玽甁硺礰竧箞絈緖罇荢葈蓜蘒蠇裵褜訷贒郞鄕釞釥鈼鉙鉷鍈鏆隝隯霳霻靍靏靑靕髙魲鮏鮱鮻鰀﨎﨏﨑﨓﨔﨟﨡﨣﨤﨧﨨﨩𠮷';\n// Characters JIS X 0208 can encode but modern Japanese prose does not use:\n// - old forms (kyūjitai) of Jōyō kanji, from the `kyujitai` npm package and Unihan's kJapaneseOldVariant,\n// except those still common in Japanese words or names (e.g., 應 in 慶應, 澤, 邊, 龍, 藝 in 東京藝術大学, 糺す)\n// - Chinese function words that Japanese writes in kana (e.g., 們, 這, 麼, 很, 怎, 跟, 嘛) and stray simplified forms (e.g., 个)\n// - traditional Chinese characters that neither table covers but Japanese never uses: 碼, 舉, 鏈, 雖\n// Other Chinese-only content characters (e.g., 媽, 豬) are not listed because separating them from rare kanji\n// that Japanese prose does use (e.g., 乖離, 瑕疵, 齟齬, 俯瞰) needs Japanese usage frequencies.\nconst CHINESE_CHARACTERS_IN_JIS_X_0208 = new Set(\n '个乘亂亞从佛來們假傳僞價儉兒兩册刄剩劍劑勞勳勵勸區卷參听呀咯哇哦唔單嘛嚴囑囘圈國圍圓圖團墮壓壘壞壤壯壹壻壽奧奬姙孃學寢實寫寶將專對屆屬峽巖帶广廢廣廳彈很徑從怎恆惡惱愼慘懷戀戰戲拂拔拜挾插搖搜擇擔據擧擴攜攝收效敍敕數斷晝曉會條棧榮樂樓樞樣檢權歐歡歸殘殼毆氣沒淨淺滯滿潛澁濕濟灣燈燒營爐爭爲犧狹獨獵獸獻瓣畫當疊癡發盜盡碎碼祕禪禮稱稻穗穩竊竝粹絲經縣縱總繩繪繼續纖缺罐聲聽肅腦膽臟臺與舉舊舍舖艷莊莖萬藏藥處號螢蟲蠶蠻衞裝襃覺覽觀觸謠證譯譽讀變讓讚豐豫貳賣贊跟踐輕轉辨辭辯這遙遞遲鄰醉醫釀釋錢鎭鏈鐵鑄鑛關陷隨險隱隸雖雙雜霸靈靜顏顯飜飮餘餠騷驅驗驛髓體髮鬪鷄鹽麥麼黏默點黨齊齒齡龜'\n);\n\nlet japaneseKanji: Set<string> | undefined;\n\n/**\n * Detects Chinese or Korean characters mixed into Japanese text, such as LLM-generated Japanese prose.\n * See {@link findForeignCjkCharactersInJapanese} for which characters count and how `allowedText` works.\n * Returns the detected languages, or an empty array if none are found.\n */\nexport function detectForeignCjkInJapanese(text: string, allowedText?: string): ForeignCjkLanguage[] {\n const characters = findForeignCjkCharactersInJapanese(text, allowedText);\n const languages: ForeignCjkLanguage[] = [];\n if (characters.some((char) => !HANGUL_REGEX.test(char))) languages.push('chinese');\n if (characters.some((char) => HANGUL_REGEX.test(char))) languages.push('korean');\n return languages;\n}\n\n/**\n * Returns the distinct Chinese or Korean characters mixed into Japanese text, NFKC-normalized, in order of appearance.\n * A kanji is treated as Chinese when it is outside JIS X 0208 (except the four Jōyō kanji 𠮟塡剝頰 and Japanese name\n * kanji that neither Big5 nor GB2312 encodes, e.g., 髙, 﨑, 𠮷) or is one of the listed old forms, Chinese function\n * words, or other Chinese-only characters that modern Japanese prose does not use (e.g., 對, 國, 這, 們, 很, 碼).\n * Old forms in names that Chinese prose also uses (e.g., 國, 與, 德) are therefore also reported, while Chinese\n * containing none of these characters (e.g., 最后返回答案, 豬肉) is not.\n * Characters that also occur in `allowedText` are not reported, so passing the input that an LLM may quote\n * (e.g., the prompt, a question, or an error message) keeps quoted names and code from being reported.\n */\nexport function findForeignCjkCharactersInJapanese(text: string, allowedText = ''): string[] {\n const allowedCharacters = new Set(allowedText.normalize('NFKC'));\n const kanjiSet = (japaneseKanji ??= buildJapaneseKanjiSet());\n const characters = new Set<string>();\n for (const char of text.normalize('NFKC')) {\n if (allowedCharacters.has(char)) continue;\n if (\n HANGUL_REGEX.test(char) ||\n (HAN_REGEX.test(char) && (!kanjiSet.has(char) || CHINESE_CHARACTERS_IN_JIS_X_0208.has(char)))\n ) {\n characters.add(char);\n }\n }\n return [...characters];\n}\n\nfunction buildJapaneseKanjiSet(): Set<string> {\n // The WHATWG `shift_jis` decoder is Windows-31J, so skip its vendor-extension lead bytes (0xED-0xFC) to keep JIS X 0208 only.\n const decoder = new TextDecoder('shift_jis');\n const kanjiSet = new Set(JOYO_KANJI_OUTSIDE_JIS_X_0208 + JAPANESE_NAME_KANJI_OUTSIDE_JIS_X_0208);\n for (let lead = 0x81; lead <= 0xEA; lead++) {\n if (lead >= 0xA0 && lead <= 0xDF) continue;\n for (let trail = 0x40; trail <= 0xFC; trail++) {\n kanjiSet.add(decoder.decode(new Uint8Array([lead, trail])));\n }\n }\n return kanjiSet;\n}\n"],"mappings":"AAEA,MAAMA,EAAe,qBACfC,EAAY,kBAiBZC,kBAAmC,IAAI,IAC3C,+RACF,EAEA,IAAIC,EAOJ,SAAgBC,EAA2B,EAAc,EAA4C,CACnG,IAAMC,EAAaC,EAAmCC,EAAMC,CAAW,EACjEC,EAAkC,CAAC,EAGzC,OAFIJ,EAAW,KAAM,GAAS,CAACL,EAAa,KAAKU,CAAI,CAAC,GAAGD,EAAU,KAAK,SAAS,EAC7EJ,EAAW,KAAM,GAASL,EAAa,KAAKU,CAAI,CAAC,GAAGD,EAAU,KAAK,QAAQ,EACxEA,CACT,CAYA,SAAgBH,EAAmC,EAAc,EAAc,GAAc,CAC3F,IAAMK,EAAoB,IAAI,IAAIH,EAAY,UAAU,MAAM,CAAC,EACzDI,EAAY,IAAkBC,EAAsB,EACpDR,kBAAa,IAAI,IACvB,IAAK,IAAMK,KAAQH,EAAK,UAAU,MAAM,EAClCI,EAAkB,IAAID,CAAI,IAE5BV,EAAa,KAAKU,CAAI,GACrBT,EAAU,KAAKS,CAAI,IAAM,CAACE,EAAS,IAAIF,CAAI,GAAKR,EAAiC,IAAIQ,CAAI,KAE1FL,EAAW,IAAIK,CAAI,EAGvB,MAAO,CAAC,GAAGL,CAAU,CACvB,CAEA,SAASQ,GAAqC,CAE5C,IAAMC,EAAU,IAAI,YAAY,WAAW,EACrCF,kBAAW,IAAI,IAAI,qIAAsE,EAC/F,IAAK,IAAIG,EAAO,IAAMA,GAAQ,IAAM,IAClC,GAAI,KAAQ,KAAQA,GAAQ,KAC5B,IAAK,IAAIC,EAAQ,GAAMA,GAAS,IAAM,IACpCJ,EAAS,IAAIE,EAAQ,OAAO,IAAI,WAAW,CAACC,EAAMC,CAAK,CAAC,CAAC,CAAC,EAG9D,OAAOJ,CACT"}
1
+ {"version":3,"file":"foreignCjk.js","names":["HANGUL_REGEX","HAN_REGEX","CHINESE_CHARACTERS_IN_JIS_X_0208","japaneseKanji","detectForeignCjkInJapanese","characters","findForeignCjkCharactersInJapanese","text","allowedText","languages","char","allowedCharacters","kanjiSet","buildJapaneseKanjiSet","decoder","lead","trail"],"sources":["../src/foreignCjk.ts"],"sourcesContent":["export type ForeignCjkLanguage = 'chinese' | 'korean';\n\nconst HANGUL_REGEX = /\\p{Script=Hangul}/u;\nconst HAN_REGEX = /\\p{Script=Han}/u;\n// JIS X 0208 cannot encode these Jōyō kanji, which were added in 2010.\nconst JOYO_KANJI_OUTSIDE_JIS_X_0208 = '𠮟塡剝頰';\n// Kanji for Japanese names (e.g., 髙, 﨑, 濵, 栁) that Chinese prose rarely contains: the NFKC forms of the\n// Windows-31J NEC-selected IBM and IBM extension kanji that neither JIS X 0208, Big5, nor GB2312 encodes, plus 𠮷 from\n// JIS X 0213. NFKC forms are listed because the lookup runs after NFKC normalization (e.g., U+FA20 becomes U+8612).\n// Some also appear in Chinese names (e.g., 喆), but prose that mixes Chinese into Japanese hardly contains them.\n// Extension kanji that Big5 or GB2312 encodes (e.g., 德, 瀨) stay Chinese because Chinese prose uses them.\nconst JAPANESE_NAME_KANJI_OUTSIDE_JIS_X_0208 =\n '仼伃伹侊俿偂僘僴兊兤冝凬刕劜劯匇匤厓叝咊咜喆坙坥垬埈墲夋奛奝奣尞岺峵嵓嵭嶹巐弡弴彅惞愑愰憘戓抦敎昞昻晳暿曺曻朎杦栁桒棏樰橳櫢櫤涖淸澵濵焏犱犾猤玽甁硺礰竧箞絈緖罇荢葈蓜蘒蠇裵褜訷贒郞鄕釞釥鈼鉙鉷鍈鏆隝隯霳霻靍靏靑靕髙魲鮏鮱鮻鰀﨎﨏﨑﨓﨔﨟﨡﨣﨤﨧﨨﨩𠮷';\n// Characters JIS X 0208 can encode but modern Japanese prose does not use:\n// - old forms (kyūjitai) of Jōyō kanji, from the `kyujitai` npm package and Unihan's kJapaneseOldVariant,\n// except those still common in Japanese words or names (e.g., 應 in 慶應, 澤, 邊, 龍, 藝 in 東京藝術大学, 糺す)\n// - Chinese function words that Japanese writes in kana (e.g., 們, 這, 麼, 很, 怎, 跟, 嘛) and stray simplified forms (e.g., 个)\n// - traditional Chinese characters that neither table covers but Japanese never uses: 碼, 舉, 鏈, 雖\n// Other Chinese-only content characters (e.g., 媽, 豬) are not listed because separating them from rare kanji\n// that Japanese prose does use (e.g., 乖離, 瑕疵, 齟齬, 俯瞰) needs Japanese usage frequencies.\nconst CHINESE_CHARACTERS_IN_JIS_X_0208 = new Set(\n '个乘亂亞从佛來們假傳僞價儉兒兩册刄剩劍劑勞勳勵勸區卷參听呀咯哇哦唔單嘛嚴囑囘圈國圍圓圖團墮壓壘壞壤壯壹壻壽奧奬姙孃學寢實寫寶將專對屆屬峽巖帶广廢廣廳彈很徑從怎恆惡惱愼慘懷戀戰戲拂拔拜挾插搖搜擇擔據擧擴攜攝收效敍敕數斷晝曉會條棧榮樂樓樞樣檢權歐歡歸殘殼毆氣沒淨淺滯滿潛澁濕濟灣燈燒營爐爭爲犧狹獨獵獸獻瓣畫當疊癡發盜盡碎碼祕禪禮稱稻穗穩竊竝粹絲經縣縱總繩繪繼續纖缺罐聲聽肅腦膽臟臺與舉舊舍舖艷莊莖萬藏藥處號螢蟲蠶蠻衞裝襃覺覽觀觸謠證譯譽讀變讓讚豐豫貳賣贊跟踐輕轉辨辭辯這遙遞遲鄰醉醫釀釋錢鎭鏈鐵鑄鑛關陷隨險隱隸雖雙雜霸靈靜顏顯飜飮餘餠騷驅驗驛髓體髮鬪鷄鹽麥麼黏默點黨齊齒齡龜'\n);\n\nlet japaneseKanji: Set<string> | undefined;\n\n/**\n * Detects Chinese or Korean characters mixed into Japanese text, such as LLM-generated Japanese prose.\n * See {@link findForeignCjkCharactersInJapanese} for which characters count and how `allowedText` works.\n * Returns the detected languages, or an empty array if none are found.\n */\nexport function detectForeignCjkInJapanese(text: string, allowedText?: string): ForeignCjkLanguage[] {\n const characters = findForeignCjkCharactersInJapanese(text, allowedText);\n const languages: ForeignCjkLanguage[] = [];\n if (characters.some((char) => !HANGUL_REGEX.test(char))) languages.push('chinese');\n if (characters.some((char) => HANGUL_REGEX.test(char))) languages.push('korean');\n return languages;\n}\n\n/**\n * Returns the distinct Chinese or Korean characters mixed into Japanese text, NFKC-normalized, in order of appearance.\n * A kanji is treated as Chinese when it is outside JIS X 0208 (except the four Jōyō kanji 𠮟塡剝頰 and Japanese name\n * kanji that neither Big5 nor GB2312 encodes, e.g., 髙, 﨑, 𠮷) or is one of the listed old forms, Chinese function\n * words, or other Chinese-only characters that modern Japanese prose does not use (e.g., 對, 國, 這, 們, 很, 碼).\n * Old forms in names that Chinese prose also uses (e.g., 國, 與, 德) are therefore also reported, while Chinese\n * containing none of these characters (e.g., 最后返回答案, 豬肉) is not.\n * Characters that also occur in `allowedText` are not reported, so passing the input that an LLM may quote\n * (e.g., the prompt, a question, or an error message) keeps quoted names and code from being reported.\n */\nexport function findForeignCjkCharactersInJapanese(text: string, allowedText = ''): string[] {\n const allowedCharacters = new Set(allowedText.normalize('NFKC'));\n const kanjiSet = (japaneseKanji ??= buildJapaneseKanjiSet());\n const characters = new Set<string>();\n for (const char of text.normalize('NFKC')) {\n if (allowedCharacters.has(char)) continue;\n if (\n HANGUL_REGEX.test(char) ||\n (HAN_REGEX.test(char) && (!kanjiSet.has(char) || CHINESE_CHARACTERS_IN_JIS_X_0208.has(char)))\n ) {\n characters.add(char);\n }\n }\n return [...characters];\n}\n\nfunction buildJapaneseKanjiSet(): Set<string> {\n // The WHATWG `shift_jis` decoder is Windows-31J, so skip its vendor-extension lead bytes (0xED-0xFC) to keep JIS X 0208 only.\n const decoder = new TextDecoder('shift_jis');\n const kanjiSet = new Set(JOYO_KANJI_OUTSIDE_JIS_X_0208 + JAPANESE_NAME_KANJI_OUTSIDE_JIS_X_0208);\n for (let lead = 0x81; lead <= 0xea; lead++) {\n if (lead >= 0xa0 && lead <= 0xdf) continue;\n for (let trail = 0x40; trail <= 0xfc; trail++) {\n kanjiSet.add(decoder.decode(new Uint8Array([lead, trail])));\n }\n }\n return kanjiSet;\n}\n"],"mappings":"AAEA,MAAMA,EAAe,qBACfC,EAAY,kBAiBZC,kBAAmC,IAAI,IAC3C,+RACF,EAEA,IAAIC,EAOJ,SAAgBC,EAA2B,EAAc,EAA4C,CACnG,IAAMC,EAAaC,EAAmCC,EAAMC,CAAW,EACjEC,EAAkC,CAAC,EAGzC,OAFIJ,EAAW,KAAM,GAAS,CAACL,EAAa,KAAKU,CAAI,CAAC,GAAGD,EAAU,KAAK,SAAS,EAC7EJ,EAAW,KAAM,GAASL,EAAa,KAAKU,CAAI,CAAC,GAAGD,EAAU,KAAK,QAAQ,EACxEA,CACT,CAYA,SAAgBH,EAAmC,EAAc,EAAc,GAAc,CAC3F,IAAMK,EAAoB,IAAI,IAAIH,EAAY,UAAU,MAAM,CAAC,EACzDI,EAAY,IAAkBC,EAAsB,EACpDR,kBAAa,IAAI,IACvB,IAAK,IAAMK,KAAQH,EAAK,UAAU,MAAM,EAClCI,EAAkB,IAAID,CAAI,IAE5BV,EAAa,KAAKU,CAAI,GACrBT,EAAU,KAAKS,CAAI,IAAM,CAACE,EAAS,IAAIF,CAAI,GAAKR,EAAiC,IAAIQ,CAAI,KAE1FL,EAAW,IAAIK,CAAI,EAGvB,MAAO,CAAC,GAAGL,CAAU,CACvB,CAEA,SAASQ,GAAqC,CAE5C,IAAMC,EAAU,IAAI,YAAY,WAAW,EACrCF,kBAAW,IAAI,IAAI,qIAAsE,EAC/F,IAAK,IAAIG,EAAO,IAAMA,GAAQ,IAAM,IAClC,GAAI,KAAQ,KAAQA,GAAQ,KAC5B,IAAK,IAAIC,EAAQ,GAAMA,GAAS,IAAM,IACpCJ,EAAS,IAAIE,EAAQ,OAAO,IAAI,WAAW,CAACC,EAAMC,CAAK,CAAC,CAAC,CAAC,EAG9D,OAAOJ,CACT"}
@@ -1,4 +1,4 @@
1
- "use strict";const e=[{heading:`Why`,requirement:`the problem, with the numbers or observations behind it, and why this approach over the alternatives`},{heading:`Requirements`,requirement:"the requirements the change must satisfy and the guarantees it must keep as they stand now, one per line, each marked `required` (asked for by the requester, or an existing contract callers depend on) or `chosen` (the implementer's own decision with the reason that decided it, which a simpler design may replace); state the requester's instructions in the requester's terms, whether they came from an issue or a conversation, and keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of adding one beside it"},{heading:`Customer Summary`,requirement:`behavior, workflow, or user-visible changes, written for readers who know nothing about the implementation`},{heading:`Technical Summary`,requirement:`decisions and their reasons, data flow, where to look (the files that matter most), and what to check hardest: the parts whose correctness is argued rather than proven`},{heading:`Testing`,requirement:`commands run, tests added, and what was NOT exercised and why`},{heading:`Notes`,requirement:`known limitations, compatibility and migration, follow-up work; delete this section if there is none`}],t="- Requirements section: the requirements in force now, one line per requirement, taken from the requester's instructions in the requester's terms (the issue, the conversation that asked for the change), each marked `required` (asked for, or an existing contract callers depend on) or `chosen` (your own decision with the reason that decided it, which a simpler design may replace). Never infer a requirement from the diff: when no issue, PR message, or conversation states the request, write `required: not recorded — ask the requester` as the only request-derived line (a `required` line for an existing contract callers depend on may still be listed) and say so in Notes.\n- Current-state rule: an existing Requirements section records what the requester asked for and what was decided as it stands now; it is neither a description of the diff nor a log of how the request evolved. Keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of appending a line beside it; with no instructions available, keep the requester-derived lines unchanged. Never mark when a line was added (e.g., \"(added)\"), and add a `chosen` line for each new decision. When the current design cannot be understood without the change of direction, state it in one sentence in Notes. A section that merely describes the implementation, or holds only the template's placeholder or a `required: not recorded` line, is not a record: write it afresh by the rule above.\n- Place the section where the template puts it; when the template has no such heading, right after the issue-closing line, or at the top of the body when there is none.\n- Never drop or weaken a `required` line to fit what was implemented: when one cannot hold in the diff, keep it and say so in Notes.",n=`- Base the PR body on \`.github/pull_request_template.md\` when creating or updating a PR, even when a skill or workflow supplies its own skeleton: keep the template's headings in order, fill each section with what its placeholder comment asks for at a length fitting the change (a sentence for a small change, numbered subsections for a large one), and delete the placeholder comments and an empty Notes section. Without a template, use no fixed headings: state the scope, the motivation, and the verification concisely.
1
+ "use strict";const e=[{heading:`Why`,requirement:`the problem, with the numbers or observations behind it, and why this approach over the alternatives`},{heading:`Requirements`,requirement:"the requirements the change must satisfy and the guarantees it must keep as they stand now, one per line, each marked `required` (asked for by the requester, or an existing contract callers depend on) or `chosen` (the implementer's own decision with the reason that decided it, which a simpler design may replace); state the requester's instructions in the requester's terms, whether they came from an issue or a conversation, and keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of adding one beside it"},{heading:`Customer Summary`,requirement:`behavior, workflow, or user-visible changes, written for readers who know nothing about the implementation`},{heading:`Technical Summary`,requirement:`decisions and their reasons, data flow, where to look (the files that matter most), and what to check hardest: the parts whose correctness is argued rather than proven`},{heading:`Testing`,requirement:`commands run, tests added, and what was NOT exercised and why`},{heading:`Notes`,requirement:`known limitations, compatibility and migration, follow-up work; delete this section if there is none`}],t="- Requirements section: the requirements in force now, one line per requirement, taken from the requester's instructions in the requester's terms (the issue, the conversation that asked for the change), each marked `required` (asked for, or an existing contract callers depend on) or `chosen` (your own decision with the reason that decided it, which a simpler design may replace). Never infer a requirement from the diff: when no issue, PR message, or conversation states the request, write `required: not recorded — ask the requester` as the only request-derived line (`required` lines for existing contracts may still be listed) and say so in Notes.\n- When updating an existing section, keep each line until the requester overrides or withdraws the instruction behind it or the decision behind it changes, then rewrite or remove that line in place, never appending one beside it or marking when a line was added (e.g., \"(added)\"); with no instructions available, keep the requester-derived lines unchanged. When the current design cannot be understood without the change of direction, state it in one sentence in Notes. Write afresh by the rule above a section that merely describes the implementation or holds only the template's placeholder or a `required: not recorded` line.\n- Place the section where the template puts it; when the template has no such heading, right after the issue-closing line, or at the top of the body when there is none.\n- Never drop or weaken a `required` line to fit what was implemented: when one cannot hold in the diff, keep it and say so in Notes.",n=`- Base the PR body on \`.github/pull_request_template.md\` when creating or updating a PR, even when a skill or workflow supplies its own skeleton: keep the template's headings in order, fill each section with what its placeholder comment asks for at a length fitting the change (a sentence for a small change, numbered subsections for a large one), and delete the placeholder comments and an empty Notes section. Without a template, use no fixed headings: state the scope, the motivation, and the verification concisely.
2
2
  - Start the body with \`Close #<n>\` only when the PR resolves an existing issue.\n${t}`,r=[{heading:`Problem`,requirement:`what happens, and what should happen instead`},{heading:`Evidence`,requirement:`reproduction steps, logs, run IDs, or links`},{heading:`Impact`,requirement:`who or what is affected, and how badly`},{heading:`Proposal`,requirement:`the fix you have in mind, and the root cause if known`}],i=[{heading:`Background and goal`,requirement:`the problem being solved, for whom, and what outcome counts as success`},{heading:`Behavior`,requirement:`every user- or caller-observable behavior, including inputs, outputs, error cases, edge cases, and interactions with existing behavior, stated precisely enough that two implementers would build the same thing`},{heading:`Acceptance criteria`,requirement:`checkable conditions (Given/When/Then or an equivalent) that decide whether the implementation is done`},{heading:`Scope and non-goals`,requirement:`what the change covers and what it deliberately leaves out, so an implementer knows where to stop`},{heading:`Design constraints`,requirement:`the data, API, schema, UI, and configuration changes, naming, and the existing code or conventions the implementation must fit — as far as the writer intends to constrain them, with everything else explicitly left to the implementer`},{heading:`Compatibility and migration`,requirement:`what existing data, users, callers, or configurations are affected and how the transition happens`},{heading:`Verification`,requirement:`how the change is tested or demonstrated, including what needs no test and why`},{heading:`Open questions`,requirement:`undecided points, each with its options; empty once the specification is implementable`}];function a(e){return e.map(e=>`- **${e.heading}**: ${e.requirement}`).join(`
3
3
  `)}function o(e){return e.map(e=>`## ${e.heading}\n\n<!-- ${e.requirement.charAt(0).toUpperCase()}${e.requirement.slice(1)}. -->`).join(`
4
4
 
@@ -1 +1 @@
1
- {"version":3,"file":"githubTemplates.cjs","names":["PULL_REQUEST_SECTIONS","PULL_REQUEST_REQUIREMENTS_RULES","PULL_REQUEST_BODY_RULES","BUG_ISSUE_SECTIONS","CHANGE_ISSUE_SECTIONS","renderSectionChecklist","sections","section","renderSectionTemplate"],"sources":["../src/githubTemplates.ts"],"sourcesContent":["/**\n * A section of a PR or issue body: its heading and what the section must state. `requirement`\n * starts lowercase and ends without punctuation, so that it reads both as a placeholder sentence\n * (capitalized, with a period appended) and as a checklist clause after the heading.\n */\nexport interface TemplateSection {\n readonly heading: string;\n readonly requirement: string;\n}\n\n/** Sections of a pull request body, in the order they appear in the PR template. */\nexport const PULL_REQUEST_SECTIONS: readonly TemplateSection[] = [\n {\n heading: 'Why',\n requirement: 'the problem, with the numbers or observations behind it, and why this approach over the alternatives',\n },\n {\n heading: 'Requirements',\n requirement:\n \"the requirements the change must satisfy and the guarantees it must keep as they stand now, one per line, each marked `required` (asked for by the requester, or an existing contract callers depend on) or `chosen` (the implementer's own decision with the reason that decided it, which a simpler design may replace); state the requester's instructions in the requester's terms, whether they came from an issue or a conversation, and keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of adding one beside it\",\n },\n {\n heading: 'Customer Summary',\n requirement:\n 'behavior, workflow, or user-visible changes, written for readers who know nothing about the implementation',\n },\n {\n heading: 'Technical Summary',\n requirement:\n 'decisions and their reasons, data flow, where to look (the files that matter most), and what to check hardest: the parts whose correctness is argued rather than proven',\n },\n {\n heading: 'Testing',\n requirement: 'commands run, tests added, and what was NOT exercised and why',\n },\n {\n heading: 'Notes',\n requirement: 'known limitations, compatibility and migration, follow-up work; delete this section if there is none',\n },\n];\n\n/**\n * How a tool that writes or rewrites a PR body derives it from the repository's PR template, as\n * markdown bullets for an agent's instructions. Stated once here and rendered by every writer (the\n * generated agent instructions, the PR-drafting skills) so the writers cannot drift apart; the\n * template-less branch lets the same text serve repositories outside the organization.\n */\nconst PULL_REQUEST_TEMPLATE_RULES = `- Base the PR body on \\`.github/pull_request_template.md\\` when creating or updating a PR, even when a skill or workflow supplies its own skeleton: keep the template's headings in order, fill each section with what its placeholder comment asks for at a length fitting the change (a sentence for a small change, numbered subsections for a large one), and delete the placeholder comments and an empty Notes section. Without a template, use no fixed headings: state the scope, the motivation, and the verification concisely.\n- Start the body with \\`Close #<n>\\` only when the PR resolves an existing issue.`;\n\n/**\n * How a tool that writes or rewrites a PR body fills the Requirements section of\n * `PULL_REQUEST_SECTIONS`, as markdown bullets for an agent's instructions. Skills that draft PR\n * bodies render this text instead of restating it, so the writers and the reviewers that read the\n * section as the boundary a fix must keep never disagree on what a line means.\n */\nexport const PULL_REQUEST_REQUIREMENTS_RULES = `- Requirements section: the requirements in force now, one line per requirement, taken from the requester's instructions in the requester's terms (the issue, the conversation that asked for the change), each marked \\`required\\` (asked for, or an existing contract callers depend on) or \\`chosen\\` (your own decision with the reason that decided it, which a simpler design may replace). Never infer a requirement from the diff: when no issue, PR message, or conversation states the request, write \\`required: not recorded — ask the requester\\` as the only request-derived line (a \\`required\\` line for an existing contract callers depend on may still be listed) and say so in Notes.\n- Current-state rule: an existing Requirements section records what the requester asked for and what was decided as it stands now; it is neither a description of the diff nor a log of how the request evolved. Keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of appending a line beside it; with no instructions available, keep the requester-derived lines unchanged. Never mark when a line was added (e.g., \"(added)\"), and add a \\`chosen\\` line for each new decision. When the current design cannot be understood without the change of direction, state it in one sentence in Notes. A section that merely describes the implementation, or holds only the template's placeholder or a \\`required: not recorded\\` line, is not a record: write it afresh by the rule above.\n- Place the section where the template puts it; when the template has no such heading, right after the issue-closing line, or at the top of the body when there is none.\n- Never drop or weaken a \\`required\\` line to fit what was implemented: when one cannot hold in the diff, keep it and say so in Notes.`;\n\n/** The complete rules for writing a PR body: the template rules followed by the Requirements rules. */\nexport const PULL_REQUEST_BODY_RULES = `${PULL_REQUEST_TEMPLATE_RULES}\\n${PULL_REQUEST_REQUIREMENTS_RULES}`;\n\n/**\n * How a tool that creates an issue derives it from the repository's issue templates, as markdown\n * bullets for an agent's instructions; shared by the same writers as `PULL_REQUEST_BODY_RULES`.\n * Guidance the templates state in their own placeholder comments (which sections to keep, deleting\n * the comments) is deliberately not repeated here, since the writer reads the template anyway.\n */\nexport const ISSUE_TEMPLATE_RULES = `- Follow the closest template under \\`.github/ISSUE_TEMPLATE/\\`: \\`bug.md\\` for wrong behavior, \\`change.md\\` for anything to build or alter; a question or note fitting neither, or a repository without templates, needs no template.\n- Title: a Conventional Commits prefix for the type that fits the change (\\`feat:\\`, \\`fix:\\`, \\`refactor:\\`, \\`docs:\\`, \\`chore:\\`, ...); when it differs from the template's \\`title\\` prefix, replace the template's type label (\\`t: ...\\`) with the one matching the type.\n- The YAML front matter between the \\`---\\` lines is metadata, not body text: pass its \\`labels\\` via \\`--label\\` and submit only the content below the closing \\`---\\` as the body.`;\n\n/** Sections of a bug report, in the order they appear in the issue template. */\nexport const BUG_ISSUE_SECTIONS: readonly TemplateSection[] = [\n { heading: 'Problem', requirement: 'what happens, and what should happen instead' },\n { heading: 'Evidence', requirement: 'reproduction steps, logs, run IDs, or links' },\n { heading: 'Impact', requirement: 'who or what is affected, and how badly' },\n { heading: 'Proposal', requirement: 'the fix you have in mind, and the root cause if known' },\n];\n\n/**\n * Sections a change specification must settle before a third party can implement it, defined\n * once so that the issue template and any tool that drafts or reviews specifications against\n * these sections cannot drift apart; checklist consumers render it with `renderSectionChecklist`.\n * The first three sections suffice for a small change, so they come first.\n */\nexport const CHANGE_ISSUE_SECTIONS: readonly TemplateSection[] = [\n {\n heading: 'Background and goal',\n requirement: 'the problem being solved, for whom, and what outcome counts as success',\n },\n {\n heading: 'Behavior',\n requirement:\n 'every user- or caller-observable behavior, including inputs, outputs, error cases, edge cases, and interactions with existing behavior, stated precisely enough that two implementers would build the same thing',\n },\n {\n heading: 'Acceptance criteria',\n requirement:\n 'checkable conditions (Given/When/Then or an equivalent) that decide whether the implementation is done',\n },\n {\n heading: 'Scope and non-goals',\n requirement: 'what the change covers and what it deliberately leaves out, so an implementer knows where to stop',\n },\n {\n heading: 'Design constraints',\n requirement:\n 'the data, API, schema, UI, and configuration changes, naming, and the existing code or conventions the implementation must fit — as far as the writer intends to constrain them, with everything else explicitly left to the implementer',\n },\n {\n heading: 'Compatibility and migration',\n requirement: 'what existing data, users, callers, or configurations are affected and how the transition happens',\n },\n {\n heading: 'Verification',\n requirement: 'how the change is tested or demonstrated, including what needs no test and why',\n },\n {\n heading: 'Open questions',\n requirement: 'undecided points, each with its options; empty once the specification is implementable',\n },\n];\n\n/** Renders sections as markdown bullets (`- **Heading**: requirement`). */\nexport function renderSectionChecklist(sections: readonly TemplateSection[]): string {\n return sections.map((section) => `- **${section.heading}**: ${section.requirement}`).join('\\n');\n}\n\n/** Renders sections as markdown headings, each followed by its requirement as a placeholder comment. */\nexport function renderSectionTemplate(sections: readonly TemplateSection[]): string {\n return sections\n .map(\n (section) =>\n `## ${section.heading}\\n\\n<!-- ${section.requirement.charAt(0).toUpperCase()}${section.requirement.slice(1)}. -->`\n )\n .join('\\n\\n');\n}\n"],"mappings":"aAWA,MAAaA,EAAoD,CAC/D,CACE,QAAS,MACT,YAAa,sGACf,EACA,CACE,QAAS,eACT,YACE,qnBACJ,EACA,CACE,QAAS,mBACT,YACE,4GACJ,EACA,CACE,QAAS,oBACT,YACE,yKACJ,EACA,CACE,QAAS,UACT,YAAa,+DACf,EACA,CACE,QAAS,QACT,YAAa,sGACf,CACF,EAiBaC,EAAkC,y0DAMlCC,EAA0B;qFAAmCD,IAa7DE,EAAiD,CAC5D,CAAE,QAAS,UAAW,YAAa,8CAA+C,EAClF,CAAE,QAAS,WAAY,YAAa,6CAA8C,EAClF,CAAE,QAAS,SAAU,YAAa,wCAAyC,EAC3E,CAAE,QAAS,WAAY,YAAa,uDAAwD,CAC9F,EAQaC,EAAoD,CAC/D,CACE,QAAS,sBACT,YAAa,wEACf,EACA,CACE,QAAS,WACT,YACE,kNACJ,EACA,CACE,QAAS,sBACT,YACE,wGACJ,EACA,CACE,QAAS,sBACT,YAAa,mGACf,EACA,CACE,QAAS,qBACT,YACE,0OACJ,EACA,CACE,QAAS,8BACT,YAAa,mGACf,EACA,CACE,QAAS,eACT,YAAa,gFACf,EACA,CACE,QAAS,iBACT,YAAa,wFACf,CACF,EAGA,SAAgBC,EAAuB,EAA8C,CACnF,OAAOC,EAAS,IAAK,GAAY,OAAOC,EAAQ,QAAQ,MAAMA,EAAQ,aAAa,CAAC,CAAC,KAAK;CAAI,CAChG,CAGA,SAAgBC,EAAsB,EAA8C,CAClF,OAAOF,EACJ,IACE,GACC,MAAMC,EAAQ,QAAQ,WAAWA,EAAQ,YAAY,OAAO,CAAC,CAAC,CAAC,YAAY,IAAIA,EAAQ,YAAY,MAAM,CAAC,EAAE,MAChH,CAAC,CACA,KAAK;;CAAM,CAChB"}
1
+ {"version":3,"file":"githubTemplates.cjs","names":["PULL_REQUEST_SECTIONS","PULL_REQUEST_REQUIREMENTS_RULES","PULL_REQUEST_BODY_RULES","BUG_ISSUE_SECTIONS","CHANGE_ISSUE_SECTIONS","renderSectionChecklist","sections","section","renderSectionTemplate"],"sources":["../src/githubTemplates.ts"],"sourcesContent":["/**\n * A section of a PR or issue body: its heading and what the section must state. `requirement`\n * starts lowercase and ends without punctuation, so that it reads both as a placeholder sentence\n * (capitalized, with a period appended) and as a checklist clause after the heading.\n */\nexport interface TemplateSection {\n readonly heading: string;\n readonly requirement: string;\n}\n\n/** Sections of a pull request body, in the order they appear in the PR template. */\nexport const PULL_REQUEST_SECTIONS: readonly TemplateSection[] = [\n {\n heading: 'Why',\n requirement: 'the problem, with the numbers or observations behind it, and why this approach over the alternatives',\n },\n {\n heading: 'Requirements',\n requirement:\n \"the requirements the change must satisfy and the guarantees it must keep as they stand now, one per line, each marked `required` (asked for by the requester, or an existing contract callers depend on) or `chosen` (the implementer's own decision with the reason that decided it, which a simpler design may replace); state the requester's instructions in the requester's terms, whether they came from an issue or a conversation, and keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of adding one beside it\",\n },\n {\n heading: 'Customer Summary',\n requirement:\n 'behavior, workflow, or user-visible changes, written for readers who know nothing about the implementation',\n },\n {\n heading: 'Technical Summary',\n requirement:\n 'decisions and their reasons, data flow, where to look (the files that matter most), and what to check hardest: the parts whose correctness is argued rather than proven',\n },\n {\n heading: 'Testing',\n requirement: 'commands run, tests added, and what was NOT exercised and why',\n },\n {\n heading: 'Notes',\n requirement: 'known limitations, compatibility and migration, follow-up work; delete this section if there is none',\n },\n];\n\n/**\n * How a tool that writes or rewrites a PR body derives it from the repository's PR template, as\n * markdown bullets for an agent's instructions. Stated once here and rendered by every writer (the\n * generated agent instructions, the PR-drafting skills) so the writers cannot drift apart; the\n * template-less branch lets the same text serve repositories outside the organization.\n */\nconst PULL_REQUEST_TEMPLATE_RULES = `- Base the PR body on \\`.github/pull_request_template.md\\` when creating or updating a PR, even when a skill or workflow supplies its own skeleton: keep the template's headings in order, fill each section with what its placeholder comment asks for at a length fitting the change (a sentence for a small change, numbered subsections for a large one), and delete the placeholder comments and an empty Notes section. Without a template, use no fixed headings: state the scope, the motivation, and the verification concisely.\n- Start the body with \\`Close #<n>\\` only when the PR resolves an existing issue.`;\n\n/**\n * How a tool that writes or rewrites a PR body fills the Requirements section of\n * `PULL_REQUEST_SECTIONS`, as markdown bullets for an agent's instructions. Skills that draft PR\n * bodies render this text instead of restating it, so the writers and the reviewers that read the\n * section as the boundary a fix must keep never disagree on what a line means.\n */\nexport const PULL_REQUEST_REQUIREMENTS_RULES = `- Requirements section: the requirements in force now, one line per requirement, taken from the requester's instructions in the requester's terms (the issue, the conversation that asked for the change), each marked \\`required\\` (asked for, or an existing contract callers depend on) or \\`chosen\\` (your own decision with the reason that decided it, which a simpler design may replace). Never infer a requirement from the diff: when no issue, PR message, or conversation states the request, write \\`required: not recorded — ask the requester\\` as the only request-derived line (\\`required\\` lines for existing contracts may still be listed) and say so in Notes.\n- When updating an existing section, keep each line until the requester overrides or withdraws the instruction behind it or the decision behind it changes, then rewrite or remove that line in place, never appending one beside it or marking when a line was added (e.g., \"(added)\"); with no instructions available, keep the requester-derived lines unchanged. When the current design cannot be understood without the change of direction, state it in one sentence in Notes. Write afresh by the rule above a section that merely describes the implementation or holds only the template's placeholder or a \\`required: not recorded\\` line.\n- Place the section where the template puts it; when the template has no such heading, right after the issue-closing line, or at the top of the body when there is none.\n- Never drop or weaken a \\`required\\` line to fit what was implemented: when one cannot hold in the diff, keep it and say so in Notes.`;\n\n/** The complete rules for writing a PR body: the template rules followed by the Requirements rules. */\nexport const PULL_REQUEST_BODY_RULES = `${PULL_REQUEST_TEMPLATE_RULES}\\n${PULL_REQUEST_REQUIREMENTS_RULES}`;\n\n/**\n * How a tool that creates an issue derives it from the repository's issue templates, as markdown\n * bullets for an agent's instructions; shared by the same writers as `PULL_REQUEST_BODY_RULES`.\n * Guidance the templates state in their own placeholder comments (which sections to keep, deleting\n * the comments) is deliberately not repeated here, since the writer reads the template anyway.\n */\nexport const ISSUE_TEMPLATE_RULES = `- Follow the closest template under \\`.github/ISSUE_TEMPLATE/\\`: \\`bug.md\\` for wrong behavior, \\`change.md\\` for anything to build or alter; a question or note fitting neither, or a repository without templates, needs no template.\n- Title: a Conventional Commits prefix for the type that fits the change (\\`feat:\\`, \\`fix:\\`, \\`refactor:\\`, \\`docs:\\`, \\`chore:\\`, ...); when it differs from the template's \\`title\\` prefix, replace the template's type label (\\`t: ...\\`) with the one matching the type.\n- The YAML front matter between the \\`---\\` lines is metadata, not body text: pass its \\`labels\\` via \\`--label\\` and submit only the content below the closing \\`---\\` as the body.`;\n\n/** Sections of a bug report, in the order they appear in the issue template. */\nexport const BUG_ISSUE_SECTIONS: readonly TemplateSection[] = [\n { heading: 'Problem', requirement: 'what happens, and what should happen instead' },\n { heading: 'Evidence', requirement: 'reproduction steps, logs, run IDs, or links' },\n { heading: 'Impact', requirement: 'who or what is affected, and how badly' },\n { heading: 'Proposal', requirement: 'the fix you have in mind, and the root cause if known' },\n];\n\n/**\n * Sections a change specification must settle before a third party can implement it, defined\n * once so that the issue template and any tool that drafts or reviews specifications against\n * these sections cannot drift apart; checklist consumers render it with `renderSectionChecklist`.\n * The first three sections suffice for a small change, so they come first.\n */\nexport const CHANGE_ISSUE_SECTIONS: readonly TemplateSection[] = [\n {\n heading: 'Background and goal',\n requirement: 'the problem being solved, for whom, and what outcome counts as success',\n },\n {\n heading: 'Behavior',\n requirement:\n 'every user- or caller-observable behavior, including inputs, outputs, error cases, edge cases, and interactions with existing behavior, stated precisely enough that two implementers would build the same thing',\n },\n {\n heading: 'Acceptance criteria',\n requirement:\n 'checkable conditions (Given/When/Then or an equivalent) that decide whether the implementation is done',\n },\n {\n heading: 'Scope and non-goals',\n requirement: 'what the change covers and what it deliberately leaves out, so an implementer knows where to stop',\n },\n {\n heading: 'Design constraints',\n requirement:\n 'the data, API, schema, UI, and configuration changes, naming, and the existing code or conventions the implementation must fit — as far as the writer intends to constrain them, with everything else explicitly left to the implementer',\n },\n {\n heading: 'Compatibility and migration',\n requirement: 'what existing data, users, callers, or configurations are affected and how the transition happens',\n },\n {\n heading: 'Verification',\n requirement: 'how the change is tested or demonstrated, including what needs no test and why',\n },\n {\n heading: 'Open questions',\n requirement: 'undecided points, each with its options; empty once the specification is implementable',\n },\n];\n\n/** Renders sections as markdown bullets (`- **Heading**: requirement`). */\nexport function renderSectionChecklist(sections: readonly TemplateSection[]): string {\n return sections.map((section) => `- **${section.heading}**: ${section.requirement}`).join('\\n');\n}\n\n/** Renders sections as markdown headings, each followed by its requirement as a placeholder comment. */\nexport function renderSectionTemplate(sections: readonly TemplateSection[]): string {\n return sections\n .map(\n (section) =>\n `## ${section.heading}\\n\\n<!-- ${section.requirement.charAt(0).toUpperCase()}${section.requirement.slice(1)}. -->`\n )\n .join('\\n\\n');\n}\n"],"mappings":"aAWA,MAAaA,EAAoD,CAC/D,CACE,QAAS,MACT,YAAa,sGACf,EACA,CACE,QAAS,eACT,YACE,qnBACJ,EACA,CACE,QAAS,mBACT,YACE,4GACJ,EACA,CACE,QAAS,oBACT,YACE,yKACJ,EACA,CACE,QAAS,UACT,YAAa,+DACf,EACA,CACE,QAAS,QACT,YAAa,sGACf,CACF,EAiBaC,EAAkC,ujDAMlCC,EAA0B;qFAAmCD,IAa7DE,EAAiD,CAC5D,CAAE,QAAS,UAAW,YAAa,8CAA+C,EAClF,CAAE,QAAS,WAAY,YAAa,6CAA8C,EAClF,CAAE,QAAS,SAAU,YAAa,wCAAyC,EAC3E,CAAE,QAAS,WAAY,YAAa,uDAAwD,CAC9F,EAQaC,EAAoD,CAC/D,CACE,QAAS,sBACT,YAAa,wEACf,EACA,CACE,QAAS,WACT,YACE,kNACJ,EACA,CACE,QAAS,sBACT,YACE,wGACJ,EACA,CACE,QAAS,sBACT,YAAa,mGACf,EACA,CACE,QAAS,qBACT,YACE,0OACJ,EACA,CACE,QAAS,8BACT,YAAa,mGACf,EACA,CACE,QAAS,eACT,YAAa,gFACf,EACA,CACE,QAAS,iBACT,YAAa,wFACf,CACF,EAGA,SAAgBC,EAAuB,EAA8C,CACnF,OAAOC,EAAS,IAAK,GAAY,OAAOC,EAAQ,QAAQ,MAAMA,EAAQ,aAAa,CAAC,CAAC,KAAK;CAAI,CAChG,CAGA,SAAgBC,EAAsB,EAA8C,CAClF,OAAOF,EACJ,IACE,GACC,MAAMC,EAAQ,QAAQ,WAAWA,EAAQ,YAAY,OAAO,CAAC,CAAC,CAAC,YAAY,IAAIA,EAAQ,YAAY,MAAM,CAAC,EAAE,MAChH,CAAC,CACA,KAAK;;CAAM,CAChB"}
@@ -15,9 +15,9 @@ export declare const PULL_REQUEST_SECTIONS: readonly TemplateSection[];
15
15
  * bodies render this text instead of restating it, so the writers and the reviewers that read the
16
16
  * section as the boundary a fix must keep never disagree on what a line means.
17
17
  */
18
- export declare const PULL_REQUEST_REQUIREMENTS_RULES = "- Requirements section: the requirements in force now, one line per requirement, taken from the requester's instructions in the requester's terms (the issue, the conversation that asked for the change), each marked `required` (asked for, or an existing contract callers depend on) or `chosen` (your own decision with the reason that decided it, which a simpler design may replace). Never infer a requirement from the diff: when no issue, PR message, or conversation states the request, write `required: not recorded \u2014 ask the requester` as the only request-derived line (a `required` line for an existing contract callers depend on may still be listed) and say so in Notes.\n- Current-state rule: an existing Requirements section records what the requester asked for and what was decided as it stands now; it is neither a description of the diff nor a log of how the request evolved. Keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of appending a line beside it; with no instructions available, keep the requester-derived lines unchanged. Never mark when a line was added (e.g., \"(added)\"), and add a `chosen` line for each new decision. When the current design cannot be understood without the change of direction, state it in one sentence in Notes. A section that merely describes the implementation, or holds only the template's placeholder or a `required: not recorded` line, is not a record: write it afresh by the rule above.\n- Place the section where the template puts it; when the template has no such heading, right after the issue-closing line, or at the top of the body when there is none.\n- Never drop or weaken a `required` line to fit what was implemented: when one cannot hold in the diff, keep it and say so in Notes.";
18
+ export declare const PULL_REQUEST_REQUIREMENTS_RULES = "- Requirements section: the requirements in force now, one line per requirement, taken from the requester's instructions in the requester's terms (the issue, the conversation that asked for the change), each marked `required` (asked for, or an existing contract callers depend on) or `chosen` (your own decision with the reason that decided it, which a simpler design may replace). Never infer a requirement from the diff: when no issue, PR message, or conversation states the request, write `required: not recorded \u2014 ask the requester` as the only request-derived line (`required` lines for existing contracts may still be listed) and say so in Notes.\n- When updating an existing section, keep each line until the requester overrides or withdraws the instruction behind it or the decision behind it changes, then rewrite or remove that line in place, never appending one beside it or marking when a line was added (e.g., \"(added)\"); with no instructions available, keep the requester-derived lines unchanged. When the current design cannot be understood without the change of direction, state it in one sentence in Notes. Write afresh by the rule above a section that merely describes the implementation or holds only the template's placeholder or a `required: not recorded` line.\n- Place the section where the template puts it; when the template has no such heading, right after the issue-closing line, or at the top of the body when there is none.\n- Never drop or weaken a `required` line to fit what was implemented: when one cannot hold in the diff, keep it and say so in Notes.";
19
19
  /** The complete rules for writing a PR body: the template rules followed by the Requirements rules. */
20
- export declare const PULL_REQUEST_BODY_RULES = "- Base the PR body on `.github/pull_request_template.md` when creating or updating a PR, even when a skill or workflow supplies its own skeleton: keep the template's headings in order, fill each section with what its placeholder comment asks for at a length fitting the change (a sentence for a small change, numbered subsections for a large one), and delete the placeholder comments and an empty Notes section. Without a template, use no fixed headings: state the scope, the motivation, and the verification concisely.\n- Start the body with `Close #<n>` only when the PR resolves an existing issue.\n- Requirements section: the requirements in force now, one line per requirement, taken from the requester's instructions in the requester's terms (the issue, the conversation that asked for the change), each marked `required` (asked for, or an existing contract callers depend on) or `chosen` (your own decision with the reason that decided it, which a simpler design may replace). Never infer a requirement from the diff: when no issue, PR message, or conversation states the request, write `required: not recorded \u2014 ask the requester` as the only request-derived line (a `required` line for an existing contract callers depend on may still be listed) and say so in Notes.\n- Current-state rule: an existing Requirements section records what the requester asked for and what was decided as it stands now; it is neither a description of the diff nor a log of how the request evolved. Keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of appending a line beside it; with no instructions available, keep the requester-derived lines unchanged. Never mark when a line was added (e.g., \"(added)\"), and add a `chosen` line for each new decision. When the current design cannot be understood without the change of direction, state it in one sentence in Notes. A section that merely describes the implementation, or holds only the template's placeholder or a `required: not recorded` line, is not a record: write it afresh by the rule above.\n- Place the section where the template puts it; when the template has no such heading, right after the issue-closing line, or at the top of the body when there is none.\n- Never drop or weaken a `required` line to fit what was implemented: when one cannot hold in the diff, keep it and say so in Notes.";
20
+ export declare const PULL_REQUEST_BODY_RULES = "- Base the PR body on `.github/pull_request_template.md` when creating or updating a PR, even when a skill or workflow supplies its own skeleton: keep the template's headings in order, fill each section with what its placeholder comment asks for at a length fitting the change (a sentence for a small change, numbered subsections for a large one), and delete the placeholder comments and an empty Notes section. Without a template, use no fixed headings: state the scope, the motivation, and the verification concisely.\n- Start the body with `Close #<n>` only when the PR resolves an existing issue.\n- Requirements section: the requirements in force now, one line per requirement, taken from the requester's instructions in the requester's terms (the issue, the conversation that asked for the change), each marked `required` (asked for, or an existing contract callers depend on) or `chosen` (your own decision with the reason that decided it, which a simpler design may replace). Never infer a requirement from the diff: when no issue, PR message, or conversation states the request, write `required: not recorded \u2014 ask the requester` as the only request-derived line (`required` lines for existing contracts may still be listed) and say so in Notes.\n- When updating an existing section, keep each line until the requester overrides or withdraws the instruction behind it or the decision behind it changes, then rewrite or remove that line in place, never appending one beside it or marking when a line was added (e.g., \"(added)\"); with no instructions available, keep the requester-derived lines unchanged. When the current design cannot be understood without the change of direction, state it in one sentence in Notes. Write afresh by the rule above a section that merely describes the implementation or holds only the template's placeholder or a `required: not recorded` line.\n- Place the section where the template puts it; when the template has no such heading, right after the issue-closing line, or at the top of the body when there is none.\n- Never drop or weaken a `required` line to fit what was implemented: when one cannot hold in the diff, keep it and say so in Notes.";
21
21
  /**
22
22
  * How a tool that creates an issue derives it from the repository's issue templates, as markdown
23
23
  * bullets for an agent's instructions; shared by the same writers as `PULL_REQUEST_BODY_RULES`.
@@ -1,4 +1,4 @@
1
- const e=[{heading:`Why`,requirement:`the problem, with the numbers or observations behind it, and why this approach over the alternatives`},{heading:`Requirements`,requirement:"the requirements the change must satisfy and the guarantees it must keep as they stand now, one per line, each marked `required` (asked for by the requester, or an existing contract callers depend on) or `chosen` (the implementer's own decision with the reason that decided it, which a simpler design may replace); state the requester's instructions in the requester's terms, whether they came from an issue or a conversation, and keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of adding one beside it"},{heading:`Customer Summary`,requirement:`behavior, workflow, or user-visible changes, written for readers who know nothing about the implementation`},{heading:`Technical Summary`,requirement:`decisions and their reasons, data flow, where to look (the files that matter most), and what to check hardest: the parts whose correctness is argued rather than proven`},{heading:`Testing`,requirement:`commands run, tests added, and what was NOT exercised and why`},{heading:`Notes`,requirement:`known limitations, compatibility and migration, follow-up work; delete this section if there is none`}],t="- Requirements section: the requirements in force now, one line per requirement, taken from the requester's instructions in the requester's terms (the issue, the conversation that asked for the change), each marked `required` (asked for, or an existing contract callers depend on) or `chosen` (your own decision with the reason that decided it, which a simpler design may replace). Never infer a requirement from the diff: when no issue, PR message, or conversation states the request, write `required: not recorded — ask the requester` as the only request-derived line (a `required` line for an existing contract callers depend on may still be listed) and say so in Notes.\n- Current-state rule: an existing Requirements section records what the requester asked for and what was decided as it stands now; it is neither a description of the diff nor a log of how the request evolved. Keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of appending a line beside it; with no instructions available, keep the requester-derived lines unchanged. Never mark when a line was added (e.g., \"(added)\"), and add a `chosen` line for each new decision. When the current design cannot be understood without the change of direction, state it in one sentence in Notes. A section that merely describes the implementation, or holds only the template's placeholder or a `required: not recorded` line, is not a record: write it afresh by the rule above.\n- Place the section where the template puts it; when the template has no such heading, right after the issue-closing line, or at the top of the body when there is none.\n- Never drop or weaken a `required` line to fit what was implemented: when one cannot hold in the diff, keep it and say so in Notes.",n=`- Base the PR body on \`.github/pull_request_template.md\` when creating or updating a PR, even when a skill or workflow supplies its own skeleton: keep the template's headings in order, fill each section with what its placeholder comment asks for at a length fitting the change (a sentence for a small change, numbered subsections for a large one), and delete the placeholder comments and an empty Notes section. Without a template, use no fixed headings: state the scope, the motivation, and the verification concisely.
1
+ const e=[{heading:`Why`,requirement:`the problem, with the numbers or observations behind it, and why this approach over the alternatives`},{heading:`Requirements`,requirement:"the requirements the change must satisfy and the guarantees it must keep as they stand now, one per line, each marked `required` (asked for by the requester, or an existing contract callers depend on) or `chosen` (the implementer's own decision with the reason that decided it, which a simpler design may replace); state the requester's instructions in the requester's terms, whether they came from an issue or a conversation, and keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of adding one beside it"},{heading:`Customer Summary`,requirement:`behavior, workflow, or user-visible changes, written for readers who know nothing about the implementation`},{heading:`Technical Summary`,requirement:`decisions and their reasons, data flow, where to look (the files that matter most), and what to check hardest: the parts whose correctness is argued rather than proven`},{heading:`Testing`,requirement:`commands run, tests added, and what was NOT exercised and why`},{heading:`Notes`,requirement:`known limitations, compatibility and migration, follow-up work; delete this section if there is none`}],t="- Requirements section: the requirements in force now, one line per requirement, taken from the requester's instructions in the requester's terms (the issue, the conversation that asked for the change), each marked `required` (asked for, or an existing contract callers depend on) or `chosen` (your own decision with the reason that decided it, which a simpler design may replace). Never infer a requirement from the diff: when no issue, PR message, or conversation states the request, write `required: not recorded — ask the requester` as the only request-derived line (`required` lines for existing contracts may still be listed) and say so in Notes.\n- When updating an existing section, keep each line until the requester overrides or withdraws the instruction behind it or the decision behind it changes, then rewrite or remove that line in place, never appending one beside it or marking when a line was added (e.g., \"(added)\"); with no instructions available, keep the requester-derived lines unchanged. When the current design cannot be understood without the change of direction, state it in one sentence in Notes. Write afresh by the rule above a section that merely describes the implementation or holds only the template's placeholder or a `required: not recorded` line.\n- Place the section where the template puts it; when the template has no such heading, right after the issue-closing line, or at the top of the body when there is none.\n- Never drop or weaken a `required` line to fit what was implemented: when one cannot hold in the diff, keep it and say so in Notes.",n=`- Base the PR body on \`.github/pull_request_template.md\` when creating or updating a PR, even when a skill or workflow supplies its own skeleton: keep the template's headings in order, fill each section with what its placeholder comment asks for at a length fitting the change (a sentence for a small change, numbered subsections for a large one), and delete the placeholder comments and an empty Notes section. Without a template, use no fixed headings: state the scope, the motivation, and the verification concisely.
2
2
  - Start the body with \`Close #<n>\` only when the PR resolves an existing issue.\n${t}`,r="- Follow the closest template under `.github/ISSUE_TEMPLATE/`: `bug.md` for wrong behavior, `change.md` for anything to build or alter; a question or note fitting neither, or a repository without templates, needs no template.\n- Title: a Conventional Commits prefix for the type that fits the change (`feat:`, `fix:`, `refactor:`, `docs:`, `chore:`, ...); when it differs from the template's `title` prefix, replace the template's type label (`t: ...`) with the one matching the type.\n- The YAML front matter between the `---` lines is metadata, not body text: pass its `labels` via `--label` and submit only the content below the closing `---` as the body.",i=[{heading:`Problem`,requirement:`what happens, and what should happen instead`},{heading:`Evidence`,requirement:`reproduction steps, logs, run IDs, or links`},{heading:`Impact`,requirement:`who or what is affected, and how badly`},{heading:`Proposal`,requirement:`the fix you have in mind, and the root cause if known`}],a=[{heading:`Background and goal`,requirement:`the problem being solved, for whom, and what outcome counts as success`},{heading:`Behavior`,requirement:`every user- or caller-observable behavior, including inputs, outputs, error cases, edge cases, and interactions with existing behavior, stated precisely enough that two implementers would build the same thing`},{heading:`Acceptance criteria`,requirement:`checkable conditions (Given/When/Then or an equivalent) that decide whether the implementation is done`},{heading:`Scope and non-goals`,requirement:`what the change covers and what it deliberately leaves out, so an implementer knows where to stop`},{heading:`Design constraints`,requirement:`the data, API, schema, UI, and configuration changes, naming, and the existing code or conventions the implementation must fit — as far as the writer intends to constrain them, with everything else explicitly left to the implementer`},{heading:`Compatibility and migration`,requirement:`what existing data, users, callers, or configurations are affected and how the transition happens`},{heading:`Verification`,requirement:`how the change is tested or demonstrated, including what needs no test and why`},{heading:`Open questions`,requirement:`undecided points, each with its options; empty once the specification is implementable`}];function o(e){return e.map(e=>`- **${e.heading}**: ${e.requirement}`).join(`
3
3
  `)}function s(e){return e.map(e=>`## ${e.heading}\n\n<!-- ${e.requirement.charAt(0).toUpperCase()}${e.requirement.slice(1)}. -->`).join(`
4
4
 
@@ -1 +1 @@
1
- {"version":3,"file":"githubTemplates.js","names":["PULL_REQUEST_SECTIONS","PULL_REQUEST_REQUIREMENTS_RULES","PULL_REQUEST_BODY_RULES","ISSUE_TEMPLATE_RULES","BUG_ISSUE_SECTIONS","CHANGE_ISSUE_SECTIONS","renderSectionChecklist","sections","section","renderSectionTemplate"],"sources":["../src/githubTemplates.ts"],"sourcesContent":["/**\n * A section of a PR or issue body: its heading and what the section must state. `requirement`\n * starts lowercase and ends without punctuation, so that it reads both as a placeholder sentence\n * (capitalized, with a period appended) and as a checklist clause after the heading.\n */\nexport interface TemplateSection {\n readonly heading: string;\n readonly requirement: string;\n}\n\n/** Sections of a pull request body, in the order they appear in the PR template. */\nexport const PULL_REQUEST_SECTIONS: readonly TemplateSection[] = [\n {\n heading: 'Why',\n requirement: 'the problem, with the numbers or observations behind it, and why this approach over the alternatives',\n },\n {\n heading: 'Requirements',\n requirement:\n \"the requirements the change must satisfy and the guarantees it must keep as they stand now, one per line, each marked `required` (asked for by the requester, or an existing contract callers depend on) or `chosen` (the implementer's own decision with the reason that decided it, which a simpler design may replace); state the requester's instructions in the requester's terms, whether they came from an issue or a conversation, and keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of adding one beside it\",\n },\n {\n heading: 'Customer Summary',\n requirement:\n 'behavior, workflow, or user-visible changes, written for readers who know nothing about the implementation',\n },\n {\n heading: 'Technical Summary',\n requirement:\n 'decisions and their reasons, data flow, where to look (the files that matter most), and what to check hardest: the parts whose correctness is argued rather than proven',\n },\n {\n heading: 'Testing',\n requirement: 'commands run, tests added, and what was NOT exercised and why',\n },\n {\n heading: 'Notes',\n requirement: 'known limitations, compatibility and migration, follow-up work; delete this section if there is none',\n },\n];\n\n/**\n * How a tool that writes or rewrites a PR body derives it from the repository's PR template, as\n * markdown bullets for an agent's instructions. Stated once here and rendered by every writer (the\n * generated agent instructions, the PR-drafting skills) so the writers cannot drift apart; the\n * template-less branch lets the same text serve repositories outside the organization.\n */\nconst PULL_REQUEST_TEMPLATE_RULES = `- Base the PR body on \\`.github/pull_request_template.md\\` when creating or updating a PR, even when a skill or workflow supplies its own skeleton: keep the template's headings in order, fill each section with what its placeholder comment asks for at a length fitting the change (a sentence for a small change, numbered subsections for a large one), and delete the placeholder comments and an empty Notes section. Without a template, use no fixed headings: state the scope, the motivation, and the verification concisely.\n- Start the body with \\`Close #<n>\\` only when the PR resolves an existing issue.`;\n\n/**\n * How a tool that writes or rewrites a PR body fills the Requirements section of\n * `PULL_REQUEST_SECTIONS`, as markdown bullets for an agent's instructions. Skills that draft PR\n * bodies render this text instead of restating it, so the writers and the reviewers that read the\n * section as the boundary a fix must keep never disagree on what a line means.\n */\nexport const PULL_REQUEST_REQUIREMENTS_RULES = `- Requirements section: the requirements in force now, one line per requirement, taken from the requester's instructions in the requester's terms (the issue, the conversation that asked for the change), each marked \\`required\\` (asked for, or an existing contract callers depend on) or \\`chosen\\` (your own decision with the reason that decided it, which a simpler design may replace). Never infer a requirement from the diff: when no issue, PR message, or conversation states the request, write \\`required: not recorded — ask the requester\\` as the only request-derived line (a \\`required\\` line for an existing contract callers depend on may still be listed) and say so in Notes.\n- Current-state rule: an existing Requirements section records what the requester asked for and what was decided as it stands now; it is neither a description of the diff nor a log of how the request evolved. Keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of appending a line beside it; with no instructions available, keep the requester-derived lines unchanged. Never mark when a line was added (e.g., \"(added)\"), and add a \\`chosen\\` line for each new decision. When the current design cannot be understood without the change of direction, state it in one sentence in Notes. A section that merely describes the implementation, or holds only the template's placeholder or a \\`required: not recorded\\` line, is not a record: write it afresh by the rule above.\n- Place the section where the template puts it; when the template has no such heading, right after the issue-closing line, or at the top of the body when there is none.\n- Never drop or weaken a \\`required\\` line to fit what was implemented: when one cannot hold in the diff, keep it and say so in Notes.`;\n\n/** The complete rules for writing a PR body: the template rules followed by the Requirements rules. */\nexport const PULL_REQUEST_BODY_RULES = `${PULL_REQUEST_TEMPLATE_RULES}\\n${PULL_REQUEST_REQUIREMENTS_RULES}`;\n\n/**\n * How a tool that creates an issue derives it from the repository's issue templates, as markdown\n * bullets for an agent's instructions; shared by the same writers as `PULL_REQUEST_BODY_RULES`.\n * Guidance the templates state in their own placeholder comments (which sections to keep, deleting\n * the comments) is deliberately not repeated here, since the writer reads the template anyway.\n */\nexport const ISSUE_TEMPLATE_RULES = `- Follow the closest template under \\`.github/ISSUE_TEMPLATE/\\`: \\`bug.md\\` for wrong behavior, \\`change.md\\` for anything to build or alter; a question or note fitting neither, or a repository without templates, needs no template.\n- Title: a Conventional Commits prefix for the type that fits the change (\\`feat:\\`, \\`fix:\\`, \\`refactor:\\`, \\`docs:\\`, \\`chore:\\`, ...); when it differs from the template's \\`title\\` prefix, replace the template's type label (\\`t: ...\\`) with the one matching the type.\n- The YAML front matter between the \\`---\\` lines is metadata, not body text: pass its \\`labels\\` via \\`--label\\` and submit only the content below the closing \\`---\\` as the body.`;\n\n/** Sections of a bug report, in the order they appear in the issue template. */\nexport const BUG_ISSUE_SECTIONS: readonly TemplateSection[] = [\n { heading: 'Problem', requirement: 'what happens, and what should happen instead' },\n { heading: 'Evidence', requirement: 'reproduction steps, logs, run IDs, or links' },\n { heading: 'Impact', requirement: 'who or what is affected, and how badly' },\n { heading: 'Proposal', requirement: 'the fix you have in mind, and the root cause if known' },\n];\n\n/**\n * Sections a change specification must settle before a third party can implement it, defined\n * once so that the issue template and any tool that drafts or reviews specifications against\n * these sections cannot drift apart; checklist consumers render it with `renderSectionChecklist`.\n * The first three sections suffice for a small change, so they come first.\n */\nexport const CHANGE_ISSUE_SECTIONS: readonly TemplateSection[] = [\n {\n heading: 'Background and goal',\n requirement: 'the problem being solved, for whom, and what outcome counts as success',\n },\n {\n heading: 'Behavior',\n requirement:\n 'every user- or caller-observable behavior, including inputs, outputs, error cases, edge cases, and interactions with existing behavior, stated precisely enough that two implementers would build the same thing',\n },\n {\n heading: 'Acceptance criteria',\n requirement:\n 'checkable conditions (Given/When/Then or an equivalent) that decide whether the implementation is done',\n },\n {\n heading: 'Scope and non-goals',\n requirement: 'what the change covers and what it deliberately leaves out, so an implementer knows where to stop',\n },\n {\n heading: 'Design constraints',\n requirement:\n 'the data, API, schema, UI, and configuration changes, naming, and the existing code or conventions the implementation must fit — as far as the writer intends to constrain them, with everything else explicitly left to the implementer',\n },\n {\n heading: 'Compatibility and migration',\n requirement: 'what existing data, users, callers, or configurations are affected and how the transition happens',\n },\n {\n heading: 'Verification',\n requirement: 'how the change is tested or demonstrated, including what needs no test and why',\n },\n {\n heading: 'Open questions',\n requirement: 'undecided points, each with its options; empty once the specification is implementable',\n },\n];\n\n/** Renders sections as markdown bullets (`- **Heading**: requirement`). */\nexport function renderSectionChecklist(sections: readonly TemplateSection[]): string {\n return sections.map((section) => `- **${section.heading}**: ${section.requirement}`).join('\\n');\n}\n\n/** Renders sections as markdown headings, each followed by its requirement as a placeholder comment. */\nexport function renderSectionTemplate(sections: readonly TemplateSection[]): string {\n return sections\n .map(\n (section) =>\n `## ${section.heading}\\n\\n<!-- ${section.requirement.charAt(0).toUpperCase()}${section.requirement.slice(1)}. -->`\n )\n .join('\\n\\n');\n}\n"],"mappings":"AAWA,MAAaA,EAAoD,CAC/D,CACE,QAAS,MACT,YAAa,sGACf,EACA,CACE,QAAS,eACT,YACE,qnBACJ,EACA,CACE,QAAS,mBACT,YACE,4GACJ,EACA,CACE,QAAS,oBACT,YACE,yKACJ,EACA,CACE,QAAS,UACT,YAAa,+DACf,EACA,CACE,QAAS,QACT,YAAa,sGACf,CACF,EAiBaC,EAAkC,y0DAMlCC,EAA0B;qFAAmCD,IAQ7DE,EAAuB,qpBAKvBC,EAAiD,CAC5D,CAAE,QAAS,UAAW,YAAa,8CAA+C,EAClF,CAAE,QAAS,WAAY,YAAa,6CAA8C,EAClF,CAAE,QAAS,SAAU,YAAa,wCAAyC,EAC3E,CAAE,QAAS,WAAY,YAAa,uDAAwD,CAC9F,EAQaC,EAAoD,CAC/D,CACE,QAAS,sBACT,YAAa,wEACf,EACA,CACE,QAAS,WACT,YACE,kNACJ,EACA,CACE,QAAS,sBACT,YACE,wGACJ,EACA,CACE,QAAS,sBACT,YAAa,mGACf,EACA,CACE,QAAS,qBACT,YACE,0OACJ,EACA,CACE,QAAS,8BACT,YAAa,mGACf,EACA,CACE,QAAS,eACT,YAAa,gFACf,EACA,CACE,QAAS,iBACT,YAAa,wFACf,CACF,EAGA,SAAgBC,EAAuB,EAA8C,CACnF,OAAOC,EAAS,IAAK,GAAY,OAAOC,EAAQ,QAAQ,MAAMA,EAAQ,aAAa,CAAC,CAAC,KAAK;CAAI,CAChG,CAGA,SAAgBC,EAAsB,EAA8C,CAClF,OAAOF,EACJ,IACE,GACC,MAAMC,EAAQ,QAAQ,WAAWA,EAAQ,YAAY,OAAO,CAAC,CAAC,CAAC,YAAY,IAAIA,EAAQ,YAAY,MAAM,CAAC,EAAE,MAChH,CAAC,CACA,KAAK;;CAAM,CAChB"}
1
+ {"version":3,"file":"githubTemplates.js","names":["PULL_REQUEST_SECTIONS","PULL_REQUEST_REQUIREMENTS_RULES","PULL_REQUEST_BODY_RULES","ISSUE_TEMPLATE_RULES","BUG_ISSUE_SECTIONS","CHANGE_ISSUE_SECTIONS","renderSectionChecklist","sections","section","renderSectionTemplate"],"sources":["../src/githubTemplates.ts"],"sourcesContent":["/**\n * A section of a PR or issue body: its heading and what the section must state. `requirement`\n * starts lowercase and ends without punctuation, so that it reads both as a placeholder sentence\n * (capitalized, with a period appended) and as a checklist clause after the heading.\n */\nexport interface TemplateSection {\n readonly heading: string;\n readonly requirement: string;\n}\n\n/** Sections of a pull request body, in the order they appear in the PR template. */\nexport const PULL_REQUEST_SECTIONS: readonly TemplateSection[] = [\n {\n heading: 'Why',\n requirement: 'the problem, with the numbers or observations behind it, and why this approach over the alternatives',\n },\n {\n heading: 'Requirements',\n requirement:\n \"the requirements the change must satisfy and the guarantees it must keep as they stand now, one per line, each marked `required` (asked for by the requester, or an existing contract callers depend on) or `chosen` (the implementer's own decision with the reason that decided it, which a simpler design may replace); state the requester's instructions in the requester's terms, whether they came from an issue or a conversation, and keep each line as it is until the requester overrides or withdraws the instruction behind it or the decision behind it changes, and then rewrite or remove that line instead of adding one beside it\",\n },\n {\n heading: 'Customer Summary',\n requirement:\n 'behavior, workflow, or user-visible changes, written for readers who know nothing about the implementation',\n },\n {\n heading: 'Technical Summary',\n requirement:\n 'decisions and their reasons, data flow, where to look (the files that matter most), and what to check hardest: the parts whose correctness is argued rather than proven',\n },\n {\n heading: 'Testing',\n requirement: 'commands run, tests added, and what was NOT exercised and why',\n },\n {\n heading: 'Notes',\n requirement: 'known limitations, compatibility and migration, follow-up work; delete this section if there is none',\n },\n];\n\n/**\n * How a tool that writes or rewrites a PR body derives it from the repository's PR template, as\n * markdown bullets for an agent's instructions. Stated once here and rendered by every writer (the\n * generated agent instructions, the PR-drafting skills) so the writers cannot drift apart; the\n * template-less branch lets the same text serve repositories outside the organization.\n */\nconst PULL_REQUEST_TEMPLATE_RULES = `- Base the PR body on \\`.github/pull_request_template.md\\` when creating or updating a PR, even when a skill or workflow supplies its own skeleton: keep the template's headings in order, fill each section with what its placeholder comment asks for at a length fitting the change (a sentence for a small change, numbered subsections for a large one), and delete the placeholder comments and an empty Notes section. Without a template, use no fixed headings: state the scope, the motivation, and the verification concisely.\n- Start the body with \\`Close #<n>\\` only when the PR resolves an existing issue.`;\n\n/**\n * How a tool that writes or rewrites a PR body fills the Requirements section of\n * `PULL_REQUEST_SECTIONS`, as markdown bullets for an agent's instructions. Skills that draft PR\n * bodies render this text instead of restating it, so the writers and the reviewers that read the\n * section as the boundary a fix must keep never disagree on what a line means.\n */\nexport const PULL_REQUEST_REQUIREMENTS_RULES = `- Requirements section: the requirements in force now, one line per requirement, taken from the requester's instructions in the requester's terms (the issue, the conversation that asked for the change), each marked \\`required\\` (asked for, or an existing contract callers depend on) or \\`chosen\\` (your own decision with the reason that decided it, which a simpler design may replace). Never infer a requirement from the diff: when no issue, PR message, or conversation states the request, write \\`required: not recorded — ask the requester\\` as the only request-derived line (\\`required\\` lines for existing contracts may still be listed) and say so in Notes.\n- When updating an existing section, keep each line until the requester overrides or withdraws the instruction behind it or the decision behind it changes, then rewrite or remove that line in place, never appending one beside it or marking when a line was added (e.g., \"(added)\"); with no instructions available, keep the requester-derived lines unchanged. When the current design cannot be understood without the change of direction, state it in one sentence in Notes. Write afresh by the rule above a section that merely describes the implementation or holds only the template's placeholder or a \\`required: not recorded\\` line.\n- Place the section where the template puts it; when the template has no such heading, right after the issue-closing line, or at the top of the body when there is none.\n- Never drop or weaken a \\`required\\` line to fit what was implemented: when one cannot hold in the diff, keep it and say so in Notes.`;\n\n/** The complete rules for writing a PR body: the template rules followed by the Requirements rules. */\nexport const PULL_REQUEST_BODY_RULES = `${PULL_REQUEST_TEMPLATE_RULES}\\n${PULL_REQUEST_REQUIREMENTS_RULES}`;\n\n/**\n * How a tool that creates an issue derives it from the repository's issue templates, as markdown\n * bullets for an agent's instructions; shared by the same writers as `PULL_REQUEST_BODY_RULES`.\n * Guidance the templates state in their own placeholder comments (which sections to keep, deleting\n * the comments) is deliberately not repeated here, since the writer reads the template anyway.\n */\nexport const ISSUE_TEMPLATE_RULES = `- Follow the closest template under \\`.github/ISSUE_TEMPLATE/\\`: \\`bug.md\\` for wrong behavior, \\`change.md\\` for anything to build or alter; a question or note fitting neither, or a repository without templates, needs no template.\n- Title: a Conventional Commits prefix for the type that fits the change (\\`feat:\\`, \\`fix:\\`, \\`refactor:\\`, \\`docs:\\`, \\`chore:\\`, ...); when it differs from the template's \\`title\\` prefix, replace the template's type label (\\`t: ...\\`) with the one matching the type.\n- The YAML front matter between the \\`---\\` lines is metadata, not body text: pass its \\`labels\\` via \\`--label\\` and submit only the content below the closing \\`---\\` as the body.`;\n\n/** Sections of a bug report, in the order they appear in the issue template. */\nexport const BUG_ISSUE_SECTIONS: readonly TemplateSection[] = [\n { heading: 'Problem', requirement: 'what happens, and what should happen instead' },\n { heading: 'Evidence', requirement: 'reproduction steps, logs, run IDs, or links' },\n { heading: 'Impact', requirement: 'who or what is affected, and how badly' },\n { heading: 'Proposal', requirement: 'the fix you have in mind, and the root cause if known' },\n];\n\n/**\n * Sections a change specification must settle before a third party can implement it, defined\n * once so that the issue template and any tool that drafts or reviews specifications against\n * these sections cannot drift apart; checklist consumers render it with `renderSectionChecklist`.\n * The first three sections suffice for a small change, so they come first.\n */\nexport const CHANGE_ISSUE_SECTIONS: readonly TemplateSection[] = [\n {\n heading: 'Background and goal',\n requirement: 'the problem being solved, for whom, and what outcome counts as success',\n },\n {\n heading: 'Behavior',\n requirement:\n 'every user- or caller-observable behavior, including inputs, outputs, error cases, edge cases, and interactions with existing behavior, stated precisely enough that two implementers would build the same thing',\n },\n {\n heading: 'Acceptance criteria',\n requirement:\n 'checkable conditions (Given/When/Then or an equivalent) that decide whether the implementation is done',\n },\n {\n heading: 'Scope and non-goals',\n requirement: 'what the change covers and what it deliberately leaves out, so an implementer knows where to stop',\n },\n {\n heading: 'Design constraints',\n requirement:\n 'the data, API, schema, UI, and configuration changes, naming, and the existing code or conventions the implementation must fit — as far as the writer intends to constrain them, with everything else explicitly left to the implementer',\n },\n {\n heading: 'Compatibility and migration',\n requirement: 'what existing data, users, callers, or configurations are affected and how the transition happens',\n },\n {\n heading: 'Verification',\n requirement: 'how the change is tested or demonstrated, including what needs no test and why',\n },\n {\n heading: 'Open questions',\n requirement: 'undecided points, each with its options; empty once the specification is implementable',\n },\n];\n\n/** Renders sections as markdown bullets (`- **Heading**: requirement`). */\nexport function renderSectionChecklist(sections: readonly TemplateSection[]): string {\n return sections.map((section) => `- **${section.heading}**: ${section.requirement}`).join('\\n');\n}\n\n/** Renders sections as markdown headings, each followed by its requirement as a placeholder comment. */\nexport function renderSectionTemplate(sections: readonly TemplateSection[]): string {\n return sections\n .map(\n (section) =>\n `## ${section.heading}\\n\\n<!-- ${section.requirement.charAt(0).toUpperCase()}${section.requirement.slice(1)}. -->`\n )\n .join('\\n\\n');\n}\n"],"mappings":"AAWA,MAAaA,EAAoD,CAC/D,CACE,QAAS,MACT,YAAa,sGACf,EACA,CACE,QAAS,eACT,YACE,qnBACJ,EACA,CACE,QAAS,mBACT,YACE,4GACJ,EACA,CACE,QAAS,oBACT,YACE,yKACJ,EACA,CACE,QAAS,UACT,YAAa,+DACf,EACA,CACE,QAAS,QACT,YAAa,sGACf,CACF,EAiBaC,EAAkC,ujDAMlCC,EAA0B;qFAAmCD,IAQ7DE,EAAuB,qpBAKvBC,EAAiD,CAC5D,CAAE,QAAS,UAAW,YAAa,8CAA+C,EAClF,CAAE,QAAS,WAAY,YAAa,6CAA8C,EAClF,CAAE,QAAS,SAAU,YAAa,wCAAyC,EAC3E,CAAE,QAAS,WAAY,YAAa,uDAAwD,CAC9F,EAQaC,EAAoD,CAC/D,CACE,QAAS,sBACT,YAAa,wEACf,EACA,CACE,QAAS,WACT,YACE,kNACJ,EACA,CACE,QAAS,sBACT,YACE,wGACJ,EACA,CACE,QAAS,sBACT,YAAa,mGACf,EACA,CACE,QAAS,qBACT,YACE,0OACJ,EACA,CACE,QAAS,8BACT,YAAa,mGACf,EACA,CACE,QAAS,eACT,YAAa,gFACf,EACA,CACE,QAAS,iBACT,YAAa,wFACf,CACF,EAGA,SAAgBC,EAAuB,EAA8C,CACnF,OAAOC,EAAS,IAAK,GAAY,OAAOC,EAAQ,QAAQ,MAAMA,EAAQ,aAAa,CAAC,CAAC,KAAK;CAAI,CAChG,CAGA,SAAgBC,EAAsB,EAA8C,CAClF,OAAOF,EACJ,IACE,GACC,MAAMC,EAAQ,QAAQ,WAAWA,EAAQ,YAAY,OAAO,CAAC,CAAC,CAAC,YAAY,IAAIA,EAAQ,YAAY,MAAM,CAAC,EAAE,MAChH,CAAC,CACA,KAAK;;CAAM,CAChB"}
@@ -1,2 +1,2 @@
1
- "use strict";function e(e){if(!e)return[];let t=[],n=``,r=!1,i=!1;for(let a of e){if(a===`"`&&!i){r=!r;continue}if(a===`'`&&!r){i=!i;continue}if(a===` `&&!r&&!i){n&&=(t.push(n),``);continue}n+=a}return n&&t.push(n),t}exports.parseCommandLineArgs=e;
1
+ "use strict";function e(e){if(!e)return[];let t=[],n=``,r=!1,i=!1;for(let a of e)a===`"`&&!i?r=!r:a===`'`&&!r?i=!i:a===` `&&!r&&!i?n&&=(t.push(n),``):n+=a;return n&&t.push(n),t}exports.parseCommandLineArgs=e;
2
2
  //# sourceMappingURL=parseCommandLineArgs.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"parseCommandLineArgs.cjs","names":["parseCommandLineArgs","argsString","result","current","inDoubleQuote","inSingleQuote","char"],"sources":["../src/parseCommandLineArgs.ts"],"sourcesContent":["/**\n * Parses a command line string into an array of arguments, preserving quoted strings.\n *\n * This function handles:\n * - Space-separated arguments\n * - Double-quoted strings (preserves spaces within)\n * - Single-quoted strings (preserves spaces within)\n *\n * @param argsString The command line string to parse\n * @returns An array of parsed arguments\n */\nexport function parseCommandLineArgs(argsString: string): string[] {\n if (!argsString) return [];\n\n const result: string[] = [];\n let current = '';\n let inDoubleQuote = false;\n let inSingleQuote = false;\n\n for (const char of argsString) {\n if (char === '\"' && !inSingleQuote) {\n inDoubleQuote = !inDoubleQuote;\n continue;\n }\n\n if (char === \"'\" && !inDoubleQuote) {\n inSingleQuote = !inSingleQuote;\n continue;\n }\n\n if (char === ' ' && !inDoubleQuote && !inSingleQuote) {\n if (current) {\n result.push(current);\n current = '';\n }\n continue;\n }\n\n current += char;\n }\n\n if (current) {\n result.push(current);\n }\n\n return result;\n}\n"],"mappings":"aAWA,SAAgBA,EAAqB,EAA8B,CACjE,GAAI,CAACC,EAAY,MAAO,CAAC,EAEzB,IAAMC,EAAmB,CAAC,EACtBC,EAAU,GACVC,EAAgB,GAChBC,EAAgB,GAEpB,IAAK,IAAMC,KAAQL,EAAY,CAC7B,GAAIK,IAAS,KAAO,CAACD,EAAe,CAClC,EAAgB,CAACD,EACjB,QACF,CAEA,GAAIE,IAAS,KAAO,CAACF,EAAe,CAClC,EAAgB,CAACC,EACjB,QACF,CAEA,GAAIC,IAAS,KAAO,CAACF,GAAiB,CAACC,EAAe,CACpD,AAEEF,KADAD,EAAO,KAAKC,CAAO,EACT,IAEZ,QACF,CAEA,GAAWG,CACb,CAMA,OAJIH,GACFD,EAAO,KAAKC,CAAO,EAGdD,CACT"}
1
+ {"version":3,"file":"parseCommandLineArgs.cjs","names":["parseCommandLineArgs","argsString","result","current","inDoubleQuote","inSingleQuote","char"],"sources":["../src/parseCommandLineArgs.ts"],"sourcesContent":["/**\n * Parses a command line string into an array of arguments, preserving quoted strings.\n *\n * This function handles:\n * - Space-separated arguments\n * - Double-quoted strings (preserves spaces within)\n * - Single-quoted strings (preserves spaces within)\n *\n * @param argsString The command line string to parse\n * @returns An array of parsed arguments\n */\nexport function parseCommandLineArgs(argsString: string): string[] {\n if (!argsString) return [];\n\n const result: string[] = [];\n let current = '';\n let inDoubleQuote = false;\n let inSingleQuote = false;\n\n for (const char of argsString) {\n if (char === '\"' && !inSingleQuote) {\n inDoubleQuote = !inDoubleQuote;\n continue;\n }\n\n if (char === \"'\" && !inDoubleQuote) {\n inSingleQuote = !inSingleQuote;\n continue;\n }\n\n if (char === ' ' && !inDoubleQuote && !inSingleQuote) {\n if (current) {\n result.push(current);\n current = '';\n }\n continue;\n }\n\n current += char;\n }\n\n if (current) {\n result.push(current);\n }\n\n return result;\n}\n"],"mappings":"aAWA,SAAgBA,EAAqB,EAA8B,CACjE,GAAI,CAACC,EAAY,MAAO,CAAC,EAEzB,IAAMC,EAAmB,CAAC,EACtBC,EAAU,GACVC,EAAgB,GAChBC,EAAgB,GAEpB,IAAK,IAAMC,KAAQL,EACbK,IAAS,KAAO,CAACD,EACnB,EAAgB,CAACD,EAIfE,IAAS,KAAO,CAACF,EACnB,EAAgB,CAACC,EAIfC,IAAS,KAAO,CAACF,GAAiB,CAACC,EACrC,AAEEF,KADAD,EAAO,KAAKC,CAAO,EACT,IAKd,GAAWG,EAOb,OAJIH,GACFD,EAAO,KAAKC,CAAO,EAGdD,CACT"}
@@ -1,2 +1,2 @@
1
- function e(e){if(!e)return[];let t=[],n=``,r=!1,i=!1;for(let a of e){if(a===`"`&&!i){r=!r;continue}if(a===`'`&&!r){i=!i;continue}if(a===` `&&!r&&!i){n&&=(t.push(n),``);continue}n+=a}return n&&t.push(n),t}export{e as parseCommandLineArgs};
1
+ function e(e){if(!e)return[];let t=[],n=``,r=!1,i=!1;for(let a of e)a===`"`&&!i?r=!r:a===`'`&&!r?i=!i:a===` `&&!r&&!i?n&&=(t.push(n),``):n+=a;return n&&t.push(n),t}export{e as parseCommandLineArgs};
2
2
  //# sourceMappingURL=parseCommandLineArgs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"parseCommandLineArgs.js","names":["parseCommandLineArgs","argsString","result","current","inDoubleQuote","inSingleQuote","char"],"sources":["../src/parseCommandLineArgs.ts"],"sourcesContent":["/**\n * Parses a command line string into an array of arguments, preserving quoted strings.\n *\n * This function handles:\n * - Space-separated arguments\n * - Double-quoted strings (preserves spaces within)\n * - Single-quoted strings (preserves spaces within)\n *\n * @param argsString The command line string to parse\n * @returns An array of parsed arguments\n */\nexport function parseCommandLineArgs(argsString: string): string[] {\n if (!argsString) return [];\n\n const result: string[] = [];\n let current = '';\n let inDoubleQuote = false;\n let inSingleQuote = false;\n\n for (const char of argsString) {\n if (char === '\"' && !inSingleQuote) {\n inDoubleQuote = !inDoubleQuote;\n continue;\n }\n\n if (char === \"'\" && !inDoubleQuote) {\n inSingleQuote = !inSingleQuote;\n continue;\n }\n\n if (char === ' ' && !inDoubleQuote && !inSingleQuote) {\n if (current) {\n result.push(current);\n current = '';\n }\n continue;\n }\n\n current += char;\n }\n\n if (current) {\n result.push(current);\n }\n\n return result;\n}\n"],"mappings":"AAWA,SAAgBA,EAAqB,EAA8B,CACjE,GAAI,CAACC,EAAY,MAAO,CAAC,EAEzB,IAAMC,EAAmB,CAAC,EACtBC,EAAU,GACVC,EAAgB,GAChBC,EAAgB,GAEpB,IAAK,IAAMC,KAAQL,EAAY,CAC7B,GAAIK,IAAS,KAAO,CAACD,EAAe,CAClC,EAAgB,CAACD,EACjB,QACF,CAEA,GAAIE,IAAS,KAAO,CAACF,EAAe,CAClC,EAAgB,CAACC,EACjB,QACF,CAEA,GAAIC,IAAS,KAAO,CAACF,GAAiB,CAACC,EAAe,CACpD,AAEEF,KADAD,EAAO,KAAKC,CAAO,EACT,IAEZ,QACF,CAEA,GAAWG,CACb,CAMA,OAJIH,GACFD,EAAO,KAAKC,CAAO,EAGdD,CACT"}
1
+ {"version":3,"file":"parseCommandLineArgs.js","names":["parseCommandLineArgs","argsString","result","current","inDoubleQuote","inSingleQuote","char"],"sources":["../src/parseCommandLineArgs.ts"],"sourcesContent":["/**\n * Parses a command line string into an array of arguments, preserving quoted strings.\n *\n * This function handles:\n * - Space-separated arguments\n * - Double-quoted strings (preserves spaces within)\n * - Single-quoted strings (preserves spaces within)\n *\n * @param argsString The command line string to parse\n * @returns An array of parsed arguments\n */\nexport function parseCommandLineArgs(argsString: string): string[] {\n if (!argsString) return [];\n\n const result: string[] = [];\n let current = '';\n let inDoubleQuote = false;\n let inSingleQuote = false;\n\n for (const char of argsString) {\n if (char === '\"' && !inSingleQuote) {\n inDoubleQuote = !inDoubleQuote;\n continue;\n }\n\n if (char === \"'\" && !inDoubleQuote) {\n inSingleQuote = !inSingleQuote;\n continue;\n }\n\n if (char === ' ' && !inDoubleQuote && !inSingleQuote) {\n if (current) {\n result.push(current);\n current = '';\n }\n continue;\n }\n\n current += char;\n }\n\n if (current) {\n result.push(current);\n }\n\n return result;\n}\n"],"mappings":"AAWA,SAAgBA,EAAqB,EAA8B,CACjE,GAAI,CAACC,EAAY,MAAO,CAAC,EAEzB,IAAMC,EAAmB,CAAC,EACtBC,EAAU,GACVC,EAAgB,GAChBC,EAAgB,GAEpB,IAAK,IAAMC,KAAQL,EACbK,IAAS,KAAO,CAACD,EACnB,EAAgB,CAACD,EAIfE,IAAS,KAAO,CAACF,EACnB,EAAgB,CAACC,EAIfC,IAAS,KAAO,CAACF,GAAiB,CAACC,EACrC,AAEEF,KADAD,EAAO,KAAKC,CAAO,EACT,IAKd,GAAWG,EAOb,OAJIH,GACFD,EAAO,KAAKC,CAAO,EAGdD,CACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"prompt.cjs","names":["toTildeCodeBlock","escapeRegExp","sliceWithoutSplittingSurrogates","require_text","NON_STRING_SCALAR","UNSAFE_PLAIN_START","UNSAFE_PLAIN_MIDDLE","UNSAFE_PLAIN_END","SHORT_UNICODE_ESCAPES","serializeForPrompt","stringifyValue","toSerializable","value","serializeForPromptInTag","tagPatterns","tagName","createTagPatterns","escapePromptTag","text","escapeTags","name","pattern","patterns","BLOCK_OPENER","MISPLACED_BLOCK_OPENER","formatPrompt","lines","prompt","blocks","findBlocks","formatted","prose","index","line","block","blockLines","dedentPromptMarkers","nestedFenceLengths","backtickClosers","tildeClosers","match","opener","fence","closers","low","high","middle","end","lengths","maximumFenceLengthAt","recordFenceLength","maximum","node","left","start","right","length","replaceIndentedMarker","marker","truncateForPrompt","maxLength","stringifyNumber","stringifyString","ctx","stringifyObject","stringifyArray","stringifyEntries","lazyEntries","separator","itemCtx","str","item","key","entries","stringifyPair","record","indent","rawKey","rawValue","keyStr","valueStr","isCollection","doubleQuotedString","plainString","implicitKey","quotedString","blockString","containsDocumentMarker","endStart","isBlockEndWhitespace","endNewlinePos","chomp","leadingWhitespace","startsWithSpace","indentLines","singleQuotedString","json","i","ch","code","foldMultiline","codePoint"],"sources":["../src/prompt.ts"],"sourcesContent":["import { escapeRegExp, sliceWithoutSplittingSurrogates, toTildeCodeBlock } from './text.js';\n\nconst INDENT_STEP = ' ';\nconst MAX_IMPLICIT_KEY_LENGTH = 1024;\nconst MIN_MULTI_LINE_DOUBLE_QUOTED_LENGTH = 40;\n\n/** Strings matching this would be read back as a non-string scalar (null, bool, int, or float), so they must be quoted. */\nconst NON_STRING_SCALAR =\n /^(?:~|[Nn]ull|NULL|[Tt]rue|TRUE|[Ff]alse|FALSE|0o[0-7]+|[-+]?[0-9]+|0x[0-9a-fA-F]+|[-+]?\\.(?:inf|Inf|INF)|\\.nan|\\.NaN|\\.NAN|[-+]?(?:\\.[0-9]+|[0-9]+(?:\\.[0-9]*)?)[eE][-+]?[0-9]+|[-+]?(?:\\.[0-9]+|[0-9]+\\.[0-9]*))?$/u;\n\n// A single-line string must be quoted if it matches any of these. Checking the start, the middle, and the end separately\n// is much faster on long strings than one regex whose anchored alternatives are retried at every position.\nconst UNSAFE_PLAIN_START = /^(?:[\\t ,[\\]{}#&*!|>'\"%@`]|[?-](?:[ \\t]|$))/u;\nconst UNSAFE_PLAIN_MIDDLE = /:[ \\t]|[ \\t]#/u;\nconst UNSAFE_PLAIN_END = /[\\t :]$/u;\n\nconst SHORT_UNICODE_ESCAPES: Record<string, string> = {\n '0000': String.raw`\\0`,\n '0007': String.raw`\\a`,\n '000b': String.raw`\\v`,\n '001b': String.raw`\\e`,\n};\n\ninterface Context {\n indent: string;\n implicitKey?: boolean;\n tagPatterns?: readonly RegExp[];\n}\n\n/**\n * Serializes data into a code block to embed in an LLM prompt, so that the LLM can read its contents.\n * Accepts JSON data (honoring `toJSON` such as that of `Date`) as well as `undefined`, `NaN`, `Infinity`, bigints,\n * `Map`s (including non-string keys), `Set`s and other iterables, `Error`s (with their name, message, cause, and own properties),\n * and `RegExp`s. Symbols and functions without `toJSON` throw. The output is not meant to be deserialized back into the original value.\n * The format inside the code block is an implementation detail and may change.\n */\nexport function serializeForPrompt(value: unknown): string {\n return toTildeCodeBlock(`${stringifyValue(toSerializable(value), { indent: '' })}\\n`, 'yaml');\n}\n\n/**\n * Serializes data with `serializeForPrompt` for embedding inside a `<tagName>` element of a prompt, escaping that tag\n * in every string so that untrusted data cannot close the element and have the rest read as instructions.\n * The caller must wrap the result in the same tag.\n *\n * Only the named elements are protected, so a block nested inside other tagged elements takes every enclosing name.\n * Escaping the finished block instead is not an option: it would turn a plain scalar holding the escaped notation\n * into a YAML flow sequence, since the quoting of each scalar is decided as it is written.\n *\n * The escaped notation is the one `escapePromptTag` writes, and text that already holds it is left as it is, so two\n * strings differing only in that notation are written alike. Keys taken from untrusted data can therefore collide\n * into one duplicate key of the emitted mapping.\n */\nexport function serializeForPromptInTag(value: unknown, tagName: string | readonly string[]): string {\n const escapedTags = typeof tagName === 'string' ? [tagName] : tagName;\n const tagPatterns = escapedTags.flatMap(createTagPatterns);\n return toTildeCodeBlock(`${stringifyValue(toSerializable(value), { indent: '', tagPatterns })}\\n`, 'yaml');\n}\n\n/**\n * Replaces `<tagName` and `</tagName` not followed by `[\\w-]` with a harmless notation such as `[/tagName]`, so that\n * data embedded in a `<tagName>` element of a prompt cannot close the element and have the rest read as instructions.\n * A closing `>` is not required, since an HTML reader also closes an element on a tag carrying attribute-like junk,\n * on a trailing solidus, or on the next `>` anywhere in the prompt; the whitespace between `<` and the name is\n * dropped along with the brackets. Case is ignored deliberately: `tagName` is expected to be a literal written by\n * the caller, while the data is not.\n */\nexport function escapePromptTag(text: string, tagName: string): string {\n return text.includes('<') ? escapeTags(text, createTagPatterns(tagName)) : text;\n}\n\nfunction createTagPatterns(tagName: string): RegExp[] {\n const name = escapeRegExp(tagName);\n // Keep well-formed tags readable while also catching incomplete and malformed tags.\n return [\n new RegExp(`<\\\\s*(?:(/)\\\\s*)?(${name})\\\\s*>`, 'giu'),\n new RegExp(`<\\\\s*(?:(/)\\\\s*)?(${name})(?![\\\\w-])`, 'giu'),\n ];\n}\n\nfunction escapeTags(text: string, patterns: readonly RegExp[]): string {\n if (!text.includes('<')) return text;\n for (const pattern of patterns) text = text.replaceAll(pattern, '[$1$2]');\n return text;\n}\n\n/** The line opening a fenced block, with the indentation an interpolation may put before it. */\nconst BLOCK_OPENER = /^[ \\t]*((`{3,}|~{3,})[^\\n]*)$/u;\n\n/** A block interpolated after other text on its line, which no rule can tell from prose that ends in `~~~yaml`. */\nconst MISPLACED_BLOCK_OPENER = /[^\\s~][ \\t]*~{3,}yaml[ \\t]*$/u;\n\ninterface PromptBlock {\n opener: string;\n end: number;\n}\n\n/**\n * Strips template-literal indentation from Markdown headings, code fences, and triple-quote delimiters (`\"\"\"` and\n * `'''`), and collapses blank lines.\n * The contents of a fenced block are left untouched, since reindenting them would rewrite the data they carry, such\n * as the YAML of `serializeForPrompt` or the source of `toCodeBlock`. Every fenced block must be interpolated at\n * the start of a line. Only recognizable mid-line `~~~yaml` markers throw, including prose mentions;\n * this is not a complete placement validator, since preceding tildes can merge into an indistinguishable fence.\n * Blocks end at the first compatible same-character fence, which may carry trailing prose, unless a longer fence\n * of the same character opens and contains that candidate closing line. Other fence characters have no nesting\n * significance. Balance authored fences before interpolating blocks: an unmatched sample can consume part of a\n * later block and leave its tail subject to prose formatting.\n */\nexport function formatPrompt(prompt: string): string {\n const lines = prompt.split('\\n');\n const blocks = findBlocks(lines);\n let formatted = '';\n let prose = '';\n for (let index = 0; index < lines.length; index++) {\n const line = lines[index] ?? '';\n const block = blocks[index];\n if (block === undefined) {\n // An opening fence the prompt itself writes and never closes is prose, and so is every line inside a block.\n if (MISPLACED_BLOCK_OPENER.test(line)) {\n throw new TypeError('Interpolate a serializeForPrompt block at the start of a line');\n }\n prose += `${line}\\n`;\n continue;\n }\n // Dropping the opener's indentation keeps four spaces of it from turning the fence into an indented code block.\n const blockLines = lines.slice(index + 1, block.end + 1);\n blockLines[blockLines.length - 1] = blockLines.at(-1)?.trimStart() ?? '';\n formatted += `${dedentPromptMarkers(prose)}${block.opener}\\n${blockLines.join('\\n')}`;\n prose = '\\n';\n index = block.end;\n }\n return (formatted + dedentPromptMarkers(prose)).trim();\n}\n\nfunction findBlocks(lines: string[]): (PromptBlock | undefined)[] {\n const blocks: (PromptBlock | undefined)[] = [];\n const nestedFenceLengths = new Map<string, Uint32Array>();\n const backtickClosers: { length: number; index: number }[] = [];\n const tildeClosers: { length: number; index: number }[] = [];\n for (let index = lines.length - 1; index >= 0; index--) {\n const match = BLOCK_OPENER.exec(lines[index] ?? '');\n const opener = match?.[1]?.trimEnd();\n const fence = match?.[2];\n if (opener === undefined || fence === undefined) continue;\n const closers = fence[0] === '`' ? backtickClosers : tildeClosers;\n let low = 0;\n let high = closers.length;\n while (low < high) {\n const middle = (low + high) >>> 1;\n if ((closers[middle]?.length ?? 0) >= fence.length) low = middle + 1;\n else high = middle;\n }\n let end = closers[low - 1]?.index ?? -1;\n if (/^(?:[ \\t].*)?$/u.test((match?.[1] ?? '').slice(fence.length))) {\n // A nearer, longer closer also closes every fence that a shorter one could close.\n while (closers.length > 0 && (closers.at(-1)?.length ?? 0) <= fence.length) closers.pop();\n closers.push({ length: fence.length, index });\n }\n let lengths = nestedFenceLengths.get(fence[0] ?? '');\n if (end !== -1 && lengths !== undefined && maximumFenceLengthAt(lengths, end) > fence.length) end = -1;\n if (end !== -1) {\n blocks[index] = { opener, end };\n if (lengths === undefined) {\n lengths = new Uint32Array(lines.length * 2);\n nestedFenceLengths.set(fence[0] ?? '', lengths);\n }\n recordFenceLength(lengths, index + 1, end, fence.length);\n }\n }\n return blocks;\n}\n\nfunction maximumFenceLengthAt(lengths: Uint32Array, index: number): number {\n let maximum = 0;\n for (let node = index + lengths.length / 2; node > 0; node >>>= 1) {\n maximum = Math.max(maximum, lengths[node] ?? 0);\n }\n return maximum;\n}\n\nfunction recordFenceLength(lengths: Uint32Array, start: number, end: number, length: number): void {\n let left = start + lengths.length / 2;\n let right = end + lengths.length / 2;\n while (left <= right) {\n if (left % 2 === 1) {\n lengths[left] = Math.max(lengths[left] ?? 0, length);\n left++;\n }\n if (right % 2 === 0) {\n lengths[right] = Math.max(lengths[right] ?? 0, length);\n right--;\n }\n left >>>= 1;\n right >>>= 1;\n }\n}\n\nfunction dedentPromptMarkers(text: string): string {\n // Consume failed marker searches, and start blank-line searches only at whitespace-run boundaries.\n return text\n .replaceAll(/\\n\\s+(\"\"\"|'''|```|~{3,})|\\n\\s*/gu, replaceIndentedMarker)\n .replaceAll(/\\n\\s+(#+\\s)|\\n\\s*/gu, replaceIndentedMarker)\n .replaceAll(/(?<!\\s)\\s*\\n\\s*\\n/gu, '\\n\\n');\n}\n\nfunction replaceIndentedMarker(match: string, marker: string | undefined): string {\n return marker === undefined ? match : `\\n${marker}`;\n}\n\n/** Cuts text down to `maxLength` characters, marking it so that an LLM reads the rest as missing rather than absent. */\nexport function truncateForPrompt(text: string, maxLength: number): string {\n if (text.length <= maxLength) return text;\n return `${sliceWithoutSplittingSurrogates(text, maxLength)}\\n...<truncated>`;\n}\n\n// The functions below reproduce `stringify(value, { lineWidth: 0, aliasDuplicateObjects: false, blockQuote: 'literal' })`\n// of the `yaml` package, except that `toSerializable` makes `Error`s and `RegExp`s readable instead of `{}`.\n\nfunction stringifyValue(value: unknown, ctx: Context): string {\n switch (typeof value) {\n case 'undefined': {\n return 'null';\n }\n case 'boolean': {\n return String(value);\n }\n case 'number': {\n return stringifyNumber(value);\n }\n case 'bigint': {\n return String(value);\n }\n case 'string': {\n return stringifyString(value, ctx);\n }\n case 'object': {\n return stringifyObject(value, ctx);\n }\n default: {\n throw new TypeError(`Cannot serialize a ${typeof value} value for a prompt`);\n }\n }\n}\n\nfunction stringifyObject(value: object | null, ctx: Context): string {\n if (value === null) return 'null';\n if (Array.isArray(value)) return stringifyArray(value, ctx);\n return stringifyEntries(value instanceof Map ? value : lazyEntries(value as Record<string, unknown>), ctx);\n}\n\nfunction stringifyArray(value: unknown[], ctx: Context): string {\n if (value.length === 0) return '[]';\n const separator = `\\n${ctx.indent}`;\n const itemCtx = { indent: ctx.indent + INDENT_STEP, tagPatterns: ctx.tagPatterns };\n let str = '';\n for (const item of value) {\n str += `${str ? separator : ''}- ${stringifyValue(toSerializable(item), itemCtx)}`;\n }\n return str;\n}\n\nfunction stringifyEntries(entries: Iterable<[unknown, unknown]>, ctx: Context): string {\n const separator = `\\n${ctx.indent}`;\n let str = '';\n for (const [key, item] of entries) {\n if (item !== undefined) str += `${str ? separator : ''}${stringifyPair(key, item, ctx)}`;\n }\n return str || '{}';\n}\n\n// Reads each property only when its turn comes, as serializing an earlier one may run a `toJSON` that mutates the record.\nfunction* lazyEntries(record: Record<string, unknown>): Generator<[unknown, unknown]> {\n for (const key of Object.keys(record)) yield [key, record[key]];\n}\n\nfunction stringifyPair(rawKey: unknown, rawValue: unknown, ctx: Context): string {\n const indent = ctx.indent + INDENT_STEP;\n const key = toSerializable(rawKey);\n const value = toSerializable(rawValue);\n const keyStr = stringifyValue(key, { indent, implicitKey: true, tagPatterns: ctx.tagPatterns });\n const valueStr = stringifyValue(value, { indent, tagPatterns: ctx.tagPatterns });\n if (isCollection(key) || keyStr.length > MAX_IMPLICIT_KEY_LENGTH) return `? ${keyStr}\\n${ctx.indent}: ${valueStr}`;\n const isBlockCollection = isCollection(value) && valueStr !== '[]' && valueStr !== '{}';\n return `${keyStr}:${isBlockCollection ? `\\n${indent}` : ' '}${valueStr}`;\n}\n\nfunction toSerializable(rawValue: unknown): unknown {\n // Like `yaml`, call `toJSON` only once, but classify its result.\n const value =\n typeof (rawValue as { toJSON?: unknown } | null | undefined)?.toJSON === 'function'\n ? (rawValue as { toJSON: () => unknown }).toJSON()\n : rawValue;\n if (typeof value !== 'object' || value === null || Array.isArray(value) || value instanceof Map) return value;\n // oxlint-disable-next-line unicorn/no-instanceof-builtins -- boxed primitives have no typeof check; `yaml` unwraps them the same way.\n if (value instanceof String || value instanceof Number || value instanceof Boolean || value instanceof BigInt) {\n return value.valueOf();\n }\n if (value instanceof Error) {\n // `name` and `message` usually live on the prototype, and `cause` and `errors` are not enumerable.\n return {\n name: value.name,\n message: value.message,\n ...Object.fromEntries(Object.entries(value)),\n ...('cause' in value && { cause: value.cause }),\n ...(value instanceof AggregateError && { errors: value.errors }),\n };\n }\n if (value instanceof RegExp) return String(value);\n return Symbol.iterator in value ? [...(value as Iterable<unknown>)] : value;\n}\n\nfunction isCollection(value: unknown): value is object {\n return typeof value === 'object' && value !== null;\n}\n\nfunction stringifyNumber(value: number): string {\n if (Number.isNaN(value)) return '.nan';\n if (!Number.isFinite(value)) return value < 0 ? '-.inf' : '.inf';\n return Object.is(value, -0) ? '-0' : JSON.stringify(value);\n}\n\nfunction stringifyString(rawValue: string, ctx: Context): string {\n const value = ctx.tagPatterns === undefined ? rawValue : escapeTags(rawValue, ctx.tagPatterns);\n // A closing quote separates an unfinished tag prefix from the next mapping key.\n if (ctx.tagPatterns?.length && /<\\s*(?:\\/\\s*)?$/u.test(value)) return doubleQuotedString(value, ctx, false);\n // oxlint-disable-next-line no-control-regex -- control characters and lone surrogates can only be written escaped.\n return /[\\u0000-\\u0008\\u000B-\\u001F\\u007F-\\u009F\\u{D800}-\\u{DFFF}]/u.test(value)\n ? doubleQuotedString(value, ctx)\n : plainString(value, ctx);\n}\n\nfunction plainString(value: string, ctx: Context): string {\n const { implicitKey, indent } = ctx;\n if (value.includes('\\n')) return implicitKey ? quotedString(value, ctx) : blockString(value, ctx);\n if (UNSAFE_PLAIN_START.test(value) || UNSAFE_PLAIN_END.test(value.slice(-1)) || UNSAFE_PLAIN_MIDDLE.test(value)) {\n return quotedString(value, ctx);\n }\n if (containsDocumentMarker(value)) {\n if (indent === '') return blockString(value, ctx);\n if (implicitKey && indent === INDENT_STEP) return quotedString(value, ctx);\n }\n return NON_STRING_SCALAR.test(value) ? quotedString(value, ctx) : value;\n}\n\nfunction blockString(value: string, ctx: Context): string {\n let endStart = value.length;\n while (endStart > 0 && isBlockEndWhitespace(value.codePointAt(endStart - 1))) endStart--;\n let end = value.slice(endStart);\n // A block scalar cannot end with a whitespace-only line.\n if (end.includes('\\n') && !end.endsWith('\\n')) return quotedString(value, ctx);\n const indent = ctx.indent || (containsDocumentMarker(value) ? INDENT_STEP : '');\n\n const endNewlinePos = end.indexOf('\\n');\n const chomp = endNewlinePos === -1 ? '-' : value === end || endNewlinePos !== end.length - 1 ? '+' : '';\n if (end) {\n value = value.slice(0, -end.length);\n if (end.endsWith('\\n')) end = end.slice(0, -1);\n end = end.replaceAll(/(?:^|(?<!\\n))\\n+(?!\\n|$)/gu, `$&${indent}`);\n }\n\n const leadingWhitespace = /^[\\n ]*/u.exec(value)?.[0] ?? '';\n const startsWithSpace = leadingWhitespace.includes(' ');\n let start = value.slice(0, leadingWhitespace.lastIndexOf('\\n') + 1);\n if (start) {\n value = value.slice(start.length);\n start = start.replaceAll(/\\n+/gu, `$&${indent}`);\n }\n\n const header = (startsWithSpace ? (indent ? '2' : '1') : '') + chomp;\n return `|${header}\\n${indent}${start}${indentLines(value, indent)}${end}`;\n}\n\nfunction quotedString(value: string, ctx: Context): string {\n return value.includes('\"') && !value.includes(\"'\") ? singleQuotedString(value, ctx) : doubleQuotedString(value, ctx);\n}\n\nfunction singleQuotedString(value: string, ctx: Context): string {\n // Every multi-line value reaching here would contain a space or tab next to a newline or be an implicit key,\n // both of which need double quotes.\n if (value.includes('\\n')) return doubleQuotedString(value, ctx);\n return `'${value.replaceAll(\"'\", \"''\")}'`;\n}\n\nfunction doubleQuotedString(value: string, ctx: Context, foldMultiline = !ctx.implicitKey): string {\n const json = JSON.stringify(value);\n const indent = ctx.indent || (containsDocumentMarker(value) ? INDENT_STEP : '');\n let str = '';\n let start = 0;\n for (let i = 0; i < json.length; i++) {\n let ch = json[i];\n if (ch === ' ' && json[i + 1] === '\\\\' && json[i + 2] === 'n') {\n // A space before a line break would be folded away unless escaped.\n str += `${json.slice(start, i)}\\\\ `;\n i++;\n start = i;\n ch = '\\\\';\n }\n if (ch !== '\\\\') continue;\n if (json[i + 1] === 'u') {\n const code = json.slice(i + 2, i + 6);\n str +=\n json.slice(start, i) +\n (SHORT_UNICODE_ESCAPES[code] ?? (code.startsWith('00') ? `\\\\x${code.slice(2)}` : json.slice(i, i + 6)));\n i += 5;\n start = i + 1;\n } else if (\n json[i + 1] === 'n' &&\n foldMultiline &&\n json[i + 2] !== '\"' &&\n json.length >= MIN_MULTI_LINE_DOUBLE_QUOTED_LENGTH\n ) {\n // Folding turns the first of the written line breaks back into a space, hence the extra one.\n str += `${json.slice(start, i)}\\n\\n`;\n while (json[i + 2] === '\\\\' && json[i + 3] === 'n' && json[i + 4] !== '\"') {\n str += '\\n';\n i += 2;\n }\n str += indent;\n // A space after a line break would be folded away unless escaped.\n if (json[i + 2] === ' ') str += '\\\\';\n i++;\n start = i + 1;\n } else {\n i++;\n }\n }\n return start ? str + json.slice(start) : json;\n}\n\nfunction containsDocumentMarker(value: string): boolean {\n return /^(?:%|---|\\.\\.\\.)/mu.test(value);\n}\n\n/** Equivalent to `text.replaceAll(/\\n+/g, `$&${indent}`)` for text without leading or trailing newlines, but faster. */\nfunction indentLines(text: string, indent: string): string {\n const lines = text.split('\\n');\n let str = lines[0] ?? '';\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i];\n str += line ? `\\n${indent}${line}` : '\\n';\n }\n return str;\n}\n\nfunction isBlockEndWhitespace(codePoint: number | undefined): boolean {\n return codePoint === 0x0A || codePoint === 0x09 || codePoint === 0x20;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"prompt.cjs","names":["toTildeCodeBlock","escapeRegExp","sliceWithoutSplittingSurrogates","require_text","NON_STRING_SCALAR","UNSAFE_PLAIN_START","UNSAFE_PLAIN_MIDDLE","UNSAFE_PLAIN_END","SHORT_UNICODE_ESCAPES","serializeForPrompt","stringifyValue","toSerializable","value","serializeForPromptInTag","tagPatterns","tagName","createTagPatterns","escapePromptTag","text","escapeTags","name","pattern","patterns","BLOCK_OPENER","MISPLACED_BLOCK_OPENER","formatPrompt","lines","prompt","blocks","findBlocks","formatted","prose","index","line","block","blockLines","dedentPromptMarkers","nestedFenceLengths","backtickClosers","tildeClosers","match","opener","fence","closers","low","high","middle","end","lengths","maximumFenceLengthAt","recordFenceLength","maximum","node","left","start","right","length","replaceIndentedMarker","marker","truncateForPrompt","maxLength","stringifyNumber","stringifyString","ctx","stringifyObject","stringifyArray","stringifyEntries","lazyEntries","separator","itemCtx","str","item","key","entries","stringifyPair","record","indent","rawKey","rawValue","keyStr","valueStr","isCollection","doubleQuotedString","plainString","implicitKey","quotedString","blockString","containsDocumentMarker","endStart","isBlockEndWhitespace","endNewlinePos","chomp","leadingWhitespace","startsWithSpace","indentLines","singleQuotedString","json","i","ch","code","foldMultiline","codePoint"],"sources":["../src/prompt.ts"],"sourcesContent":["import { escapeRegExp, sliceWithoutSplittingSurrogates, toTildeCodeBlock } from './text.js';\n\nconst INDENT_STEP = ' ';\nconst MAX_IMPLICIT_KEY_LENGTH = 1024;\nconst MIN_MULTI_LINE_DOUBLE_QUOTED_LENGTH = 40;\n\n/** Strings matching this would be read back as a non-string scalar (null, bool, int, or float), so they must be quoted. */\nconst NON_STRING_SCALAR =\n /^(?:~|[Nn]ull|NULL|[Tt]rue|TRUE|[Ff]alse|FALSE|0o[0-7]+|[-+]?[0-9]+|0x[0-9a-fA-F]+|[-+]?\\.(?:inf|Inf|INF)|\\.nan|\\.NaN|\\.NAN|[-+]?(?:\\.[0-9]+|[0-9]+(?:\\.[0-9]*)?)[eE][-+]?[0-9]+|[-+]?(?:\\.[0-9]+|[0-9]+\\.[0-9]*))?$/u;\n\n// A single-line string must be quoted if it matches any of these. Checking the start, the middle, and the end separately\n// is much faster on long strings than one regex whose anchored alternatives are retried at every position.\nconst UNSAFE_PLAIN_START = /^(?:[\\t ,[\\]{}#&*!|>'\"%@`]|[?-](?:[ \\t]|$))/u;\nconst UNSAFE_PLAIN_MIDDLE = /:[ \\t]|[ \\t]#/u;\nconst UNSAFE_PLAIN_END = /[\\t :]$/u;\n\nconst SHORT_UNICODE_ESCAPES: Record<string, string> = {\n '0000': String.raw`\\0`,\n '0007': String.raw`\\a`,\n '000b': String.raw`\\v`,\n '001b': String.raw`\\e`,\n};\n\ninterface Context {\n indent: string;\n implicitKey?: boolean;\n tagPatterns?: readonly RegExp[];\n}\n\n/**\n * Serializes data into a code block to embed in an LLM prompt, so that the LLM can read its contents.\n * Accepts JSON data (honoring `toJSON` such as that of `Date`) as well as `undefined`, `NaN`, `Infinity`, bigints,\n * `Map`s (including non-string keys), `Set`s and other iterables, `Error`s (with their name, message, cause, and own properties),\n * and `RegExp`s. Symbols and functions without `toJSON` throw. The output is not meant to be deserialized back into the original value.\n * The format inside the code block is an implementation detail and may change.\n */\nexport function serializeForPrompt(value: unknown): string {\n return toTildeCodeBlock(`${stringifyValue(toSerializable(value), { indent: '' })}\\n`, 'yaml');\n}\n\n/**\n * Serializes data with `serializeForPrompt` for embedding inside a `<tagName>` element of a prompt, escaping that tag\n * in every string so that untrusted data cannot close the element and have the rest read as instructions.\n * The caller must wrap the result in the same tag.\n *\n * Only the named elements are protected, so a block nested inside other tagged elements takes every enclosing name.\n * Escaping the finished block instead is not an option: it would turn a plain scalar holding the escaped notation\n * into a YAML flow sequence, since the quoting of each scalar is decided as it is written.\n *\n * The escaped notation is the one `escapePromptTag` writes, and text that already holds it is left as it is, so two\n * strings differing only in that notation are written alike. Keys taken from untrusted data can therefore collide\n * into one duplicate key of the emitted mapping.\n */\nexport function serializeForPromptInTag(value: unknown, tagName: string | readonly string[]): string {\n const escapedTags = typeof tagName === 'string' ? [tagName] : tagName;\n const tagPatterns = escapedTags.flatMap(createTagPatterns);\n return toTildeCodeBlock(`${stringifyValue(toSerializable(value), { indent: '', tagPatterns })}\\n`, 'yaml');\n}\n\n/**\n * Replaces `<tagName` and `</tagName` not followed by `[\\w-]` with a harmless notation such as `[/tagName]`, so that\n * data embedded in a `<tagName>` element of a prompt cannot close the element and have the rest read as instructions.\n * A closing `>` is not required, since an HTML reader also closes an element on a tag carrying attribute-like junk,\n * on a trailing solidus, or on the next `>` anywhere in the prompt; the whitespace between `<` and the name is\n * dropped along with the brackets. Case is ignored deliberately: `tagName` is expected to be a literal written by\n * the caller, while the data is not.\n */\nexport function escapePromptTag(text: string, tagName: string): string {\n return text.includes('<') ? escapeTags(text, createTagPatterns(tagName)) : text;\n}\n\nfunction createTagPatterns(tagName: string): RegExp[] {\n const name = escapeRegExp(tagName);\n // Keep well-formed tags readable while also catching incomplete and malformed tags.\n return [\n new RegExp(`<\\\\s*(?:(/)\\\\s*)?(${name})\\\\s*>`, 'giu'),\n new RegExp(`<\\\\s*(?:(/)\\\\s*)?(${name})(?![\\\\w-])`, 'giu'),\n ];\n}\n\nfunction escapeTags(text: string, patterns: readonly RegExp[]): string {\n if (!text.includes('<')) return text;\n for (const pattern of patterns) text = text.replaceAll(pattern, '[$1$2]');\n return text;\n}\n\n/** The line opening a fenced block, with the indentation an interpolation may put before it. */\nconst BLOCK_OPENER = /^[ \\t]*((`{3,}|~{3,})[^\\n]*)$/u;\n\n/** A block interpolated after other text on its line, which no rule can tell from prose that ends in `~~~yaml`. */\nconst MISPLACED_BLOCK_OPENER = /[^\\s~][ \\t]*~{3,}yaml[ \\t]*$/u;\n\ninterface PromptBlock {\n opener: string;\n end: number;\n}\n\n/**\n * Strips template-literal indentation from Markdown headings, code fences, and triple-quote delimiters (`\"\"\"` and\n * `'''`), and collapses blank lines.\n * The contents of a fenced block are left untouched, since reindenting them would rewrite the data they carry, such\n * as the YAML of `serializeForPrompt` or the source of `toCodeBlock`. Every fenced block must be interpolated at\n * the start of a line. Only recognizable mid-line `~~~yaml` markers throw, including prose mentions;\n * this is not a complete placement validator, since preceding tildes can merge into an indistinguishable fence.\n * Blocks end at the first compatible same-character fence, which may carry trailing prose, unless a longer fence\n * of the same character opens and contains that candidate closing line. Other fence characters have no nesting\n * significance. Balance authored fences before interpolating blocks: an unmatched sample can consume part of a\n * later block and leave its tail subject to prose formatting.\n */\nexport function formatPrompt(prompt: string): string {\n const lines = prompt.split('\\n');\n const blocks = findBlocks(lines);\n let formatted = '';\n let prose = '';\n for (let index = 0; index < lines.length; index++) {\n const line = lines[index] ?? '';\n const block = blocks[index];\n if (block === undefined) {\n // An opening fence the prompt itself writes and never closes is prose, and so is every line inside a block.\n if (MISPLACED_BLOCK_OPENER.test(line)) {\n throw new TypeError('Interpolate a serializeForPrompt block at the start of a line');\n }\n prose += `${line}\\n`;\n continue;\n }\n // Dropping the opener's indentation keeps four spaces of it from turning the fence into an indented code block.\n const blockLines = lines.slice(index + 1, block.end + 1);\n blockLines[blockLines.length - 1] = blockLines.at(-1)?.trimStart() ?? '';\n formatted += `${dedentPromptMarkers(prose)}${block.opener}\\n${blockLines.join('\\n')}`;\n prose = '\\n';\n index = block.end;\n }\n return (formatted + dedentPromptMarkers(prose)).trim();\n}\n\nfunction findBlocks(lines: string[]): (PromptBlock | undefined)[] {\n const blocks: (PromptBlock | undefined)[] = [];\n const nestedFenceLengths = new Map<string, Uint32Array>();\n const backtickClosers: { length: number; index: number }[] = [];\n const tildeClosers: { length: number; index: number }[] = [];\n for (let index = lines.length - 1; index >= 0; index--) {\n const match = BLOCK_OPENER.exec(lines[index] ?? '');\n const opener = match?.[1]?.trimEnd();\n const fence = match?.[2];\n if (opener === undefined || fence === undefined) continue;\n const closers = fence[0] === '`' ? backtickClosers : tildeClosers;\n let low = 0;\n let high = closers.length;\n while (low < high) {\n const middle = (low + high) >>> 1;\n if ((closers[middle]?.length ?? 0) >= fence.length) low = middle + 1;\n else high = middle;\n }\n let end = closers[low - 1]?.index ?? -1;\n if (/^(?:[ \\t].*)?$/u.test((match?.[1] ?? '').slice(fence.length))) {\n // A nearer, longer closer also closes every fence that a shorter one could close.\n while (closers.length > 0 && (closers.at(-1)?.length ?? 0) <= fence.length) closers.pop();\n closers.push({ length: fence.length, index });\n }\n let lengths = nestedFenceLengths.get(fence[0] ?? '');\n if (end !== -1 && lengths !== undefined && maximumFenceLengthAt(lengths, end) > fence.length) end = -1;\n if (end !== -1) {\n blocks[index] = { opener, end };\n if (lengths === undefined) {\n lengths = new Uint32Array(lines.length * 2);\n nestedFenceLengths.set(fence[0] ?? '', lengths);\n }\n recordFenceLength(lengths, index + 1, end, fence.length);\n }\n }\n return blocks;\n}\n\nfunction maximumFenceLengthAt(lengths: Uint32Array, index: number): number {\n let maximum = 0;\n for (let node = index + lengths.length / 2; node > 0; node >>>= 1) {\n maximum = Math.max(maximum, lengths[node] ?? 0);\n }\n return maximum;\n}\n\nfunction recordFenceLength(lengths: Uint32Array, start: number, end: number, length: number): void {\n let left = start + lengths.length / 2;\n let right = end + lengths.length / 2;\n while (left <= right) {\n if (left % 2 === 1) {\n lengths[left] = Math.max(lengths[left] ?? 0, length);\n left++;\n }\n if (right % 2 === 0) {\n lengths[right] = Math.max(lengths[right] ?? 0, length);\n right--;\n }\n left >>>= 1;\n right >>>= 1;\n }\n}\n\nfunction dedentPromptMarkers(text: string): string {\n // Consume failed marker searches, and start blank-line searches only at whitespace-run boundaries.\n return text\n .replaceAll(/\\n\\s+(\"\"\"|'''|```|~{3,})|\\n\\s*/gu, replaceIndentedMarker)\n .replaceAll(/\\n\\s+(#+\\s)|\\n\\s*/gu, replaceIndentedMarker)\n .replaceAll(/(?<!\\s)\\s*\\n\\s*\\n/gu, '\\n\\n');\n}\n\nfunction replaceIndentedMarker(match: string, marker: string | undefined): string {\n return marker === undefined ? match : `\\n${marker}`;\n}\n\n/** Cuts text down to `maxLength` characters, marking it so that an LLM reads the rest as missing rather than absent. */\nexport function truncateForPrompt(text: string, maxLength: number): string {\n if (text.length <= maxLength) return text;\n return `${sliceWithoutSplittingSurrogates(text, maxLength)}\\n...<truncated>`;\n}\n\n// The functions below reproduce `stringify(value, { lineWidth: 0, aliasDuplicateObjects: false, blockQuote: 'literal' })`\n// of the `yaml` package, except that `toSerializable` makes `Error`s and `RegExp`s readable instead of `{}`.\n\nfunction stringifyValue(value: unknown, ctx: Context): string {\n switch (typeof value) {\n case 'undefined': {\n return 'null';\n }\n case 'boolean': {\n return String(value);\n }\n case 'number': {\n return stringifyNumber(value);\n }\n case 'bigint': {\n return String(value);\n }\n case 'string': {\n return stringifyString(value, ctx);\n }\n case 'object': {\n return stringifyObject(value, ctx);\n }\n default: {\n throw new TypeError(`Cannot serialize a ${typeof value} value for a prompt`);\n }\n }\n}\n\nfunction stringifyObject(value: object | null, ctx: Context): string {\n if (value === null) return 'null';\n if (Array.isArray(value)) return stringifyArray(value, ctx);\n return stringifyEntries(value instanceof Map ? value : lazyEntries(value as Record<string, unknown>), ctx);\n}\n\nfunction stringifyArray(value: unknown[], ctx: Context): string {\n if (value.length === 0) return '[]';\n const separator = `\\n${ctx.indent}`;\n const itemCtx = { indent: ctx.indent + INDENT_STEP, tagPatterns: ctx.tagPatterns };\n let str = '';\n for (const item of value) {\n str += `${str ? separator : ''}- ${stringifyValue(toSerializable(item), itemCtx)}`;\n }\n return str;\n}\n\nfunction stringifyEntries(entries: Iterable<[unknown, unknown]>, ctx: Context): string {\n const separator = `\\n${ctx.indent}`;\n let str = '';\n for (const [key, item] of entries) {\n if (item !== undefined) str += `${str ? separator : ''}${stringifyPair(key, item, ctx)}`;\n }\n return str || '{}';\n}\n\n// Reads each property only when its turn comes, as serializing an earlier one may run a `toJSON` that mutates the record.\nfunction* lazyEntries(record: Record<string, unknown>): Generator<[unknown, unknown]> {\n for (const key of Object.keys(record)) yield [key, record[key]];\n}\n\nfunction stringifyPair(rawKey: unknown, rawValue: unknown, ctx: Context): string {\n const indent = ctx.indent + INDENT_STEP;\n const key = toSerializable(rawKey);\n const value = toSerializable(rawValue);\n const keyStr = stringifyValue(key, { indent, implicitKey: true, tagPatterns: ctx.tagPatterns });\n const valueStr = stringifyValue(value, { indent, tagPatterns: ctx.tagPatterns });\n if (isCollection(key) || keyStr.length > MAX_IMPLICIT_KEY_LENGTH) return `? ${keyStr}\\n${ctx.indent}: ${valueStr}`;\n const isBlockCollection = isCollection(value) && valueStr !== '[]' && valueStr !== '{}';\n return `${keyStr}:${isBlockCollection ? `\\n${indent}` : ' '}${valueStr}`;\n}\n\nfunction toSerializable(rawValue: unknown): unknown {\n // Like `yaml`, call `toJSON` only once, but classify its result.\n const value =\n typeof (rawValue as { toJSON?: unknown } | null | undefined)?.toJSON === 'function'\n ? (rawValue as { toJSON: () => unknown }).toJSON()\n : rawValue;\n if (typeof value !== 'object' || value === null || Array.isArray(value) || value instanceof Map) return value;\n // oxlint-disable-next-line unicorn/no-instanceof-builtins -- boxed primitives have no typeof check; `yaml` unwraps them the same way.\n if (value instanceof String || value instanceof Number || value instanceof Boolean || value instanceof BigInt) {\n return value.valueOf();\n }\n if (value instanceof Error) {\n // `name` and `message` usually live on the prototype, and `cause` and `errors` are not enumerable.\n return {\n name: value.name,\n message: value.message,\n ...Object.fromEntries(Object.entries(value)),\n ...('cause' in value && { cause: value.cause }),\n ...(value instanceof AggregateError && { errors: value.errors }),\n };\n }\n if (value instanceof RegExp) return String(value);\n return Symbol.iterator in value ? [...(value as Iterable<unknown>)] : value;\n}\n\nfunction isCollection(value: unknown): value is object {\n return typeof value === 'object' && value !== null;\n}\n\nfunction stringifyNumber(value: number): string {\n if (Number.isNaN(value)) return '.nan';\n if (!Number.isFinite(value)) return value < 0 ? '-.inf' : '.inf';\n return Object.is(value, -0) ? '-0' : JSON.stringify(value);\n}\n\nfunction stringifyString(rawValue: string, ctx: Context): string {\n const value = ctx.tagPatterns === undefined ? rawValue : escapeTags(rawValue, ctx.tagPatterns);\n // A closing quote separates an unfinished tag prefix from the next mapping key.\n if (ctx.tagPatterns?.length && /<\\s*(?:\\/\\s*)?$/u.test(value)) return doubleQuotedString(value, ctx, false);\n // oxlint-disable-next-line no-control-regex -- control characters and lone surrogates can only be written escaped.\n return /[\\u0000-\\u0008\\u000B-\\u001F\\u007F-\\u009F\\u{D800}-\\u{DFFF}]/u.test(value)\n ? doubleQuotedString(value, ctx)\n : plainString(value, ctx);\n}\n\nfunction plainString(value: string, ctx: Context): string {\n const { implicitKey, indent } = ctx;\n if (value.includes('\\n')) return implicitKey ? quotedString(value, ctx) : blockString(value, ctx);\n if (UNSAFE_PLAIN_START.test(value) || UNSAFE_PLAIN_END.test(value.slice(-1)) || UNSAFE_PLAIN_MIDDLE.test(value)) {\n return quotedString(value, ctx);\n }\n if (containsDocumentMarker(value)) {\n if (indent === '') return blockString(value, ctx);\n if (implicitKey && indent === INDENT_STEP) return quotedString(value, ctx);\n }\n return NON_STRING_SCALAR.test(value) ? quotedString(value, ctx) : value;\n}\n\nfunction blockString(value: string, ctx: Context): string {\n let endStart = value.length;\n while (endStart > 0 && isBlockEndWhitespace(value.codePointAt(endStart - 1))) endStart--;\n let end = value.slice(endStart);\n // A block scalar cannot end with a whitespace-only line.\n if (end.includes('\\n') && !end.endsWith('\\n')) return quotedString(value, ctx);\n const indent = ctx.indent || (containsDocumentMarker(value) ? INDENT_STEP : '');\n\n const endNewlinePos = end.indexOf('\\n');\n const chomp = endNewlinePos === -1 ? '-' : value === end || endNewlinePos !== end.length - 1 ? '+' : '';\n if (end) {\n value = value.slice(0, -end.length);\n if (end.endsWith('\\n')) end = end.slice(0, -1);\n end = end.replaceAll(/(?:^|(?<!\\n))\\n+(?!\\n|$)/gu, `$&${indent}`);\n }\n\n const leadingWhitespace = /^[\\n ]*/u.exec(value)?.[0] ?? '';\n const startsWithSpace = leadingWhitespace.includes(' ');\n let start = value.slice(0, leadingWhitespace.lastIndexOf('\\n') + 1);\n if (start) {\n value = value.slice(start.length);\n start = start.replaceAll(/\\n+/gu, `$&${indent}`);\n }\n\n const header = (startsWithSpace ? (indent ? '2' : '1') : '') + chomp;\n return `|${header}\\n${indent}${start}${indentLines(value, indent)}${end}`;\n}\n\nfunction quotedString(value: string, ctx: Context): string {\n return value.includes('\"') && !value.includes(\"'\") ? singleQuotedString(value, ctx) : doubleQuotedString(value, ctx);\n}\n\nfunction singleQuotedString(value: string, ctx: Context): string {\n // Every multi-line value reaching here would contain a space or tab next to a newline or be an implicit key,\n // both of which need double quotes.\n if (value.includes('\\n')) return doubleQuotedString(value, ctx);\n return `'${value.replaceAll(\"'\", \"''\")}'`;\n}\n\nfunction doubleQuotedString(value: string, ctx: Context, foldMultiline = !ctx.implicitKey): string {\n const json = JSON.stringify(value);\n const indent = ctx.indent || (containsDocumentMarker(value) ? INDENT_STEP : '');\n let str = '';\n let start = 0;\n for (let i = 0; i < json.length; i++) {\n let ch = json[i];\n if (ch === ' ' && json[i + 1] === '\\\\' && json[i + 2] === 'n') {\n // A space before a line break would be folded away unless escaped.\n str += `${json.slice(start, i)}\\\\ `;\n i++;\n start = i;\n ch = '\\\\';\n }\n if (ch !== '\\\\') continue;\n if (json[i + 1] === 'u') {\n const code = json.slice(i + 2, i + 6);\n str +=\n json.slice(start, i) +\n (SHORT_UNICODE_ESCAPES[code] ?? (code.startsWith('00') ? `\\\\x${code.slice(2)}` : json.slice(i, i + 6)));\n i += 5;\n start = i + 1;\n } else if (\n json[i + 1] === 'n' &&\n foldMultiline &&\n json[i + 2] !== '\"' &&\n json.length >= MIN_MULTI_LINE_DOUBLE_QUOTED_LENGTH\n ) {\n // Folding turns the first of the written line breaks back into a space, hence the extra one.\n str += `${json.slice(start, i)}\\n\\n`;\n while (json[i + 2] === '\\\\' && json[i + 3] === 'n' && json[i + 4] !== '\"') {\n str += '\\n';\n i += 2;\n }\n str += indent;\n // A space after a line break would be folded away unless escaped.\n if (json[i + 2] === ' ') str += '\\\\';\n i++;\n start = i + 1;\n } else {\n i++;\n }\n }\n return start ? str + json.slice(start) : json;\n}\n\nfunction containsDocumentMarker(value: string): boolean {\n return /^(?:%|---|\\.\\.\\.)/mu.test(value);\n}\n\n/** Equivalent to `text.replaceAll(/\\n+/g, `$&${indent}`)` for text without leading or trailing newlines, but faster. */\nfunction indentLines(text: string, indent: string): string {\n const lines = text.split('\\n');\n let str = lines[0] ?? '';\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i];\n str += line ? `\\n${indent}${line}` : '\\n';\n }\n return str;\n}\n\nfunction isBlockEndWhitespace(codePoint: number | undefined): boolean {\n return codePoint === 0x0a || codePoint === 0x09 || codePoint === 0x20;\n}\n"],"mappings":"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"}