safeword 0.78.0 → 0.78.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/codex-plugin/.codex-plugin/plugin.json +1 -1
- package/codex-plugin/hooks.json +5 -5
- package/dist/{architecture-4EIJWLZ2.js → architecture-N5ZC4CDU.js} +2 -2
- package/dist/{architecture-document-Z3GLUOE3.js → architecture-document-UBA5UT4J.js} +2 -2
- package/dist/{architecture-monorepo-EIF3E3L3.js → architecture-monorepo-E4JUYJGV.js} +2 -2
- package/dist/{boundary-U5U2PSX2.js → boundary-HLJILY7R.js} +2 -2
- package/dist/{chunk-VUWQD4AG.js → chunk-3SOJBMM6.js} +2 -2
- package/dist/{chunk-JZFZWY3K.js → chunk-4CKCRZDO.js} +2 -2
- package/dist/{chunk-SLRSGK2C.js → chunk-AV5LTEME.js} +8 -10
- package/dist/{chunk-SLRSGK2C.js.map → chunk-AV5LTEME.js.map} +1 -1
- package/dist/{chunk-3ETWYWGQ.js → chunk-BAVDDAN3.js} +4 -4
- package/dist/{chunk-4AIRSIOH.js → chunk-BSOUMHMQ.js} +724 -3
- package/dist/chunk-BSOUMHMQ.js.map +1 -0
- package/dist/chunk-FV2S4LAR.js +122 -0
- package/dist/chunk-FV2S4LAR.js.map +1 -0
- package/dist/{chunk-C377VEWH.js → chunk-GZ36UZJG.js} +3 -3
- package/dist/{chunk-FASTWBPY.js → chunk-J7UDLLTK.js} +3 -3
- package/dist/{chunk-RXQJH4LM.js → chunk-KXHVFCDT.js} +4 -4
- package/dist/{chunk-AQU52TJM.js → chunk-NOTBZCKG.js} +3 -3
- package/dist/{chunk-AQU52TJM.js.map → chunk-NOTBZCKG.js.map} +1 -1
- package/dist/{chunk-E4UMSKEX.js → chunk-NSZGI7HK.js} +2 -2
- package/dist/{chunk-E4UMSKEX.js.map → chunk-NSZGI7HK.js.map} +1 -1
- package/dist/chunk-QTG2EXFT.js +7 -0
- package/dist/chunk-QTG2EXFT.js.map +1 -0
- package/dist/{chunk-7KMQ3QPX.js → chunk-SME5SU3O.js} +4 -4
- package/dist/{chunk-7KMQ3QPX.js.map → chunk-SME5SU3O.js.map} +1 -1
- package/dist/{cleanup-QV2EBF6M.js → cleanup-X556LNWM.js} +5 -5
- package/dist/{cleanup-command-DTE64KTN.js → cleanup-command-RV2Q7G72.js} +6 -6
- package/dist/cli.js +86 -139
- package/dist/cli.js.map +1 -1
- package/dist/{clients-N4UXDPCN.js → clients-HP23HRN2.js} +2 -2
- package/dist/codex-bootstrap-MGY2D6HU.js +178 -0
- package/dist/codex-bootstrap-MGY2D6HU.js.map +1 -0
- package/dist/{codex-hook-VHGSPJN3.js → codex-hook-IPX3PDXX.js} +5 -5
- package/dist/{codify-DJELEKJ6.js → codify-J5ZLJ3HK.js} +2 -2
- package/dist/{commands-4NIKNAST.js → commands-L4AINARC.js} +14 -14
- package/dist/{config-5A4LJ62T.js → config-LUSJAK6B.js} +2 -2
- package/dist/{configured-paths-ZY2GRPYU.js → configured-paths-SPQ5XWOM.js} +2 -2
- package/dist/{contract-ZRRRAQWZ.js → contract-KEZY6YC3.js} +2 -2
- package/dist/{coordinator-ZPEXUBXT.js → coordinator-SA75UB3C.js} +126 -44
- package/dist/coordinator-SA75UB3C.js.map +1 -0
- package/dist/{corpus-ZJQNIU4R.js → corpus-PPOBTF4J.js} +2 -2
- package/dist/{doctor-HUUE7QWE.js → doctor-DSC36R4U.js} +8 -8
- package/dist/{feature-directories-7ACGMPS4.js → feature-directories-VOHVV26X.js} +2 -2
- package/dist/{finalization-5D5N64R7.js → finalization-7SMLMVLV.js} +2 -2
- package/dist/{gh-cli-46VSKW2O.js → gh-cli-ZMO7D2KE.js} +2 -2
- package/dist/{github-rest-SXLBFCQP.js → github-rest-KGKS4V2H.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/{job-EW5LWBHH.js → job-CDADLJDF.js} +257 -87
- package/dist/job-CDADLJDF.js.map +1 -0
- package/dist/{learning-sync-DRQM2JF6.js → learning-sync-6BTHM6ZC.js} +2 -2
- package/dist/{legacy-global-guidance-DWGAGL44.js → legacy-global-guidance-2JL4Y5EB.js} +2 -2
- package/dist/{lint-gherkin-5LJX6BBU.js → lint-gherkin-COSHVS6Z.js} +2 -2
- package/dist/{operations-5CJI6U6T.js → operations-XVRQSLJG.js} +6 -6
- package/dist/{output-5TOP54O5.js → output-3LB2OEHN.js} +2 -2
- package/dist/{packet-IHZNYM3G.js → packet-5WT5M3OS.js} +2 -2
- package/dist/presets/typescript/index.js +1 -1
- package/dist/{profile-ZZGSSTSJ.js → profile-UMKQ5JVO.js} +2 -2
- package/dist/{prompt-C3MNQKAT.js → prompt-GWYDFMLO.js} +2 -2
- package/dist/{remove-PRBJCO6G.js → remove-E6HGNHOU.js} +6 -6
- package/dist/{retro-Z2DREW77.js → retro-IFSVU5KS.js} +429 -236
- package/dist/retro-IFSVU5KS.js.map +1 -0
- package/dist/{retro-draft-spool-YVNO4VSB.js → retro-draft-spool-4S3TCHWL.js} +2 -2
- package/dist/{retro-extract-NBSIY4ZY.js → retro-extract-OSBFAXLU.js} +2 -2
- package/dist/{review-pr-TTJKQC4H.js → review-pr-6S2352CK.js} +2 -2
- package/dist/{review-pr-publication-DR75RPF4.js → review-pr-publication-CGHCRRUI.js} +2 -2
- package/dist/{run-5JWZAFET.js → run-5JESKXUR.js} +2 -2
- package/dist/{self-report-3KBA5TG7.js → self-report-VPHBPPSJ.js} +2 -2
- package/dist/{status-OFXGT5ZO.js → status-7VIGNTUI.js} +5 -5
- package/dist/{status-K62NWMZ6.js → status-EX4L3ELO.js} +8 -8
- package/dist/{sync-config-B62CJ5OS.js → sync-config-O7J7IDGE.js} +2 -2
- package/dist/{sync-tracker-QMPXXLJ4.js → sync-tracker-U2GYOFUO.js} +2 -2
- package/dist/{test-execution-MCMXLV5O.js → test-execution-6LIPMBIH.js} +2 -2
- package/dist/{test-plan-RJTKHEYA.js → test-plan-VASHZXJ7.js} +2 -2
- package/dist/{ticket-new-RPLN56XK.js → ticket-new-3YXDIWPC.js} +2 -2
- package/dist/{ticket-sync-VHTAPISH.js → ticket-sync-LLUBXZ2R.js} +2 -2
- package/dist/{tracker-map-WFRDFSKN.js → tracker-map-HR4MBYG5.js} +2 -2
- package/dist/{tracker-sync-5D4XNQHS.js → tracker-sync-YDICZN66.js} +2 -2
- package/package.json +1 -1
- package/templates/hooks/codex/pre-tool-quality.ts +8 -1
- package/templates/hooks/cursor/before-shell-execution.ts +2 -1
- package/templates/hooks/lib/closeout-binding.ts +130 -31
- package/templates/hooks/pre-tool-quality.ts +1 -1
- package/templates/hooks/run-review.ts +94 -5
- package/templates/hooks/session-codex-start.ts +4 -1
- package/templates/scripts/closeout-cleanup.ts +46 -68
- package/dist/chunk-4AIRSIOH.js.map +0 -1
- package/dist/chunk-BAYWBZ32.js +0 -7
- package/dist/chunk-BAYWBZ32.js.map +0 -1
- package/dist/codex-bootstrap-7OUYHP4G.js +0 -127
- package/dist/codex-bootstrap-7OUYHP4G.js.map +0 -1
- package/dist/coordinator-ZPEXUBXT.js.map +0 -1
- package/dist/job-EW5LWBHH.js.map +0 -1
- package/dist/retro-Z2DREW77.js.map +0 -1
- /package/dist/{architecture-4EIJWLZ2.js.map → architecture-N5ZC4CDU.js.map} +0 -0
- /package/dist/{architecture-document-Z3GLUOE3.js.map → architecture-document-UBA5UT4J.js.map} +0 -0
- /package/dist/{architecture-monorepo-EIF3E3L3.js.map → architecture-monorepo-E4JUYJGV.js.map} +0 -0
- /package/dist/{boundary-U5U2PSX2.js.map → boundary-HLJILY7R.js.map} +0 -0
- /package/dist/{chunk-VUWQD4AG.js.map → chunk-3SOJBMM6.js.map} +0 -0
- /package/dist/{chunk-JZFZWY3K.js.map → chunk-4CKCRZDO.js.map} +0 -0
- /package/dist/{chunk-3ETWYWGQ.js.map → chunk-BAVDDAN3.js.map} +0 -0
- /package/dist/{chunk-C377VEWH.js.map → chunk-GZ36UZJG.js.map} +0 -0
- /package/dist/{chunk-FASTWBPY.js.map → chunk-J7UDLLTK.js.map} +0 -0
- /package/dist/{chunk-RXQJH4LM.js.map → chunk-KXHVFCDT.js.map} +0 -0
- /package/dist/{cleanup-QV2EBF6M.js.map → cleanup-X556LNWM.js.map} +0 -0
- /package/dist/{cleanup-command-DTE64KTN.js.map → cleanup-command-RV2Q7G72.js.map} +0 -0
- /package/dist/{clients-N4UXDPCN.js.map → clients-HP23HRN2.js.map} +0 -0
- /package/dist/{codex-hook-VHGSPJN3.js.map → codex-hook-IPX3PDXX.js.map} +0 -0
- /package/dist/{codify-DJELEKJ6.js.map → codify-J5ZLJ3HK.js.map} +0 -0
- /package/dist/{commands-4NIKNAST.js.map → commands-L4AINARC.js.map} +0 -0
- /package/dist/{config-5A4LJ62T.js.map → config-LUSJAK6B.js.map} +0 -0
- /package/dist/{configured-paths-ZY2GRPYU.js.map → configured-paths-SPQ5XWOM.js.map} +0 -0
- /package/dist/{contract-ZRRRAQWZ.js.map → contract-KEZY6YC3.js.map} +0 -0
- /package/dist/{corpus-ZJQNIU4R.js.map → corpus-PPOBTF4J.js.map} +0 -0
- /package/dist/{doctor-HUUE7QWE.js.map → doctor-DSC36R4U.js.map} +0 -0
- /package/dist/{feature-directories-7ACGMPS4.js.map → feature-directories-VOHVV26X.js.map} +0 -0
- /package/dist/{finalization-5D5N64R7.js.map → finalization-7SMLMVLV.js.map} +0 -0
- /package/dist/{gh-cli-46VSKW2O.js.map → gh-cli-ZMO7D2KE.js.map} +0 -0
- /package/dist/{github-rest-SXLBFCQP.js.map → github-rest-KGKS4V2H.js.map} +0 -0
- /package/dist/{learning-sync-DRQM2JF6.js.map → learning-sync-6BTHM6ZC.js.map} +0 -0
- /package/dist/{legacy-global-guidance-DWGAGL44.js.map → legacy-global-guidance-2JL4Y5EB.js.map} +0 -0
- /package/dist/{lint-gherkin-5LJX6BBU.js.map → lint-gherkin-COSHVS6Z.js.map} +0 -0
- /package/dist/{operations-5CJI6U6T.js.map → operations-XVRQSLJG.js.map} +0 -0
- /package/dist/{output-5TOP54O5.js.map → output-3LB2OEHN.js.map} +0 -0
- /package/dist/{packet-IHZNYM3G.js.map → packet-5WT5M3OS.js.map} +0 -0
- /package/dist/{profile-ZZGSSTSJ.js.map → profile-UMKQ5JVO.js.map} +0 -0
- /package/dist/{prompt-C3MNQKAT.js.map → prompt-GWYDFMLO.js.map} +0 -0
- /package/dist/{remove-PRBJCO6G.js.map → remove-E6HGNHOU.js.map} +0 -0
- /package/dist/{retro-draft-spool-YVNO4VSB.js.map → retro-draft-spool-4S3TCHWL.js.map} +0 -0
- /package/dist/{retro-extract-NBSIY4ZY.js.map → retro-extract-OSBFAXLU.js.map} +0 -0
- /package/dist/{review-pr-TTJKQC4H.js.map → review-pr-6S2352CK.js.map} +0 -0
- /package/dist/{review-pr-publication-DR75RPF4.js.map → review-pr-publication-CGHCRRUI.js.map} +0 -0
- /package/dist/{run-5JWZAFET.js.map → run-5JESKXUR.js.map} +0 -0
- /package/dist/{self-report-3KBA5TG7.js.map → self-report-VPHBPPSJ.js.map} +0 -0
- /package/dist/{status-K62NWMZ6.js.map → status-7VIGNTUI.js.map} +0 -0
- /package/dist/{status-OFXGT5ZO.js.map → status-EX4L3ELO.js.map} +0 -0
- /package/dist/{sync-config-B62CJ5OS.js.map → sync-config-O7J7IDGE.js.map} +0 -0
- /package/dist/{sync-tracker-QMPXXLJ4.js.map → sync-tracker-U2GYOFUO.js.map} +0 -0
- /package/dist/{test-execution-MCMXLV5O.js.map → test-execution-6LIPMBIH.js.map} +0 -0
- /package/dist/{test-plan-RJTKHEYA.js.map → test-plan-VASHZXJ7.js.map} +0 -0
- /package/dist/{ticket-new-RPLN56XK.js.map → ticket-new-3YXDIWPC.js.map} +0 -0
- /package/dist/{ticket-sync-VHTAPISH.js.map → ticket-sync-LLUBXZ2R.js.map} +0 -0
- /package/dist/{tracker-map-WFRDFSKN.js.map → tracker-map-HR4MBYG5.js.map} +0 -0
- /package/dist/{tracker-sync-5D4XNQHS.js.map → tracker-sync-YDICZN66.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../node_modules/.bun/smol-toml@1.7.1/node_modules/smol-toml/src/date.ts","../../../node_modules/.bun/smol-toml@1.7.1/node_modules/smol-toml/src/error.ts","../../../node_modules/.bun/smol-toml@1.7.1/node_modules/smol-toml/src/primitive.ts","../../../node_modules/.bun/smol-toml@1.7.1/node_modules/smol-toml/src/util.ts","../../../node_modules/.bun/smol-toml@1.7.1/node_modules/smol-toml/src/extract.ts","../../../node_modules/.bun/smol-toml@1.7.1/node_modules/smol-toml/src/struct.ts","../../../node_modules/.bun/smol-toml@1.7.1/node_modules/smol-toml/src/parse.ts","../src/owned-paths.ts","../src/schema.ts","../src/packs/golang/files.ts","../src/packs/python/files.ts","../src/packs/python/setup.ts","../src/packs/rust/files.ts","../src/packs/sql/dialect.ts","../src/packs/sql/files.ts","../src/utils/json-merge.ts","../src/packs/typescript/files.ts","../src/cursor-wrappers.ts","../src/templates/content.ts"],"sourcesContent":["/*!\n * Copyright (c) Squirrel Chat et al., All rights reserved.\n * SPDX-License-Identifier: BSD-3-Clause\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n * list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n * this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holder nor the names of its contributors\n * may be used to endorse or promote products derived from this software without\n * specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n// Hopefully this class will disappear once Temporal lands in JS\n// But for now we have to reinvent the wheel once more!\n\ntype Offset = string | null\n\nlet DATE_TIME_RE = /^(\\d{4}-\\d{2}-\\d{2})?[T ]?(?:(\\d{2}):\\d{2}(?::\\d{2}(?:\\.\\d+)?)?)?(Z|[-+]\\d{2}:\\d{2})?$/i\n\nexport class TomlDate extends Date {\n\t#hasDate = false\n\t#hasTime = false\n\t#offset: Offset = null\n\n\tconstructor(date: string | Date) {\n\t\tlet hasDate = true\n\t\tlet hasTime = true\n\t\tlet offset: Offset = 'Z'\n\n\t\tif (typeof date === 'string') {\n\t\t\tlet match = date.match(DATE_TIME_RE)\n\t\t\tif (match) {\n\t\t\t\tif (!match[1]) {\n\t\t\t\t\thasDate = false\n\t\t\t\t\tdate = `0000-01-01T${date}`\n\t\t\t\t}\n\n\t\t\t\thasTime = !!match[2]\n\t\t\t\t// Make sure to use T instead of a space. Breaks in case of extreme values otherwise.\n\t\t\t\thasTime && date[10] === ' ' && (date = date.replace(' ', 'T'))\n\t\t\t\t// Do not allow rollover hours.\n\t\t\t\tif (match[2] && +match[2] > 23) {\n\t\t\t\t\tdate = ''\n\t\t\t\t} else {\n\t\t\t\t\toffset = match[3] || null\n\t\t\t\t\tdate = date.toUpperCase()\n\t\t\t\t\tif (!offset && hasTime) date += 'Z'\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdate = ''\n\t\t\t}\n\t\t}\n\n\t\tsuper(date)\n\t\tif (!isNaN(this.getTime())) {\n\t\t\tthis.#hasDate = hasDate\n\t\t\tthis.#hasTime = hasTime\n\t\t\tthis.#offset = offset\n\t\t}\n\t}\n\n\tisDateTime() {\n\t\treturn this.#hasDate && this.#hasTime\n\t}\n\n\tisLocal() {\n\t\treturn !this.#hasDate || !this.#hasTime || !this.#offset\n\t}\n\n\tisDate() {\n\t\treturn this.#hasDate && !this.#hasTime\n\t}\n\n\tisTime() {\n\t\treturn this.#hasTime && !this.#hasDate\n\t}\n\n\tisValid() {\n\t\treturn this.#hasDate || this.#hasTime\n\t}\n\n\toverride toISOString() {\n\t\tlet iso = super.toISOString()\n\n\t\t// Local Date\n\t\tif (this.isDate())\n\t\t\treturn iso.slice(0, 10)\n\n\t\t// Local Time\n\t\tif (this.isTime())\n\t\t\treturn iso.slice(11, 23)\n\n\t\t// Local DateTime\n\t\tif (this.#offset === null)\n\t\t\treturn iso.slice(0, -1)\n\n\t\t// Offset DateTime\n\t\tif (this.#offset === 'Z')\n\t\t\treturn iso\n\n\t\t// This part is quite annoying: JS strips the original timezone from the ISO string representation\n\t\t// Instead of using a \"modified\" date and \"Z\", we restore the representation \"as authored\"\n\n\t\tlet offset = (+(this.#offset.slice(1, 3)) * 60) + +(this.#offset.slice(4, 6))\n\t\toffset = this.#offset[0] === '-' ? offset : -offset\n\n\t\tlet offsetDate = new Date(this.getTime() - (offset * 60e3))\n\t\treturn offsetDate.toISOString().slice(0, -1) + this.#offset\n\t}\n\n\tstatic wrapAsOffsetDateTime(jsDate: Date, offset = 'Z') {\n\t\tlet date = new TomlDate(jsDate)\n\t\tdate.#offset = offset\n\t\treturn date\n\t}\n\n\tstatic wrapAsLocalDateTime(jsDate: Date) {\n\t\tlet date = new TomlDate(jsDate)\n\t\tdate.#offset = null\n\t\treturn date\n\t}\n\n\tstatic wrapAsLocalDate(jsDate: Date) {\n\t\tlet date = new TomlDate(jsDate)\n\t\tdate.#hasTime = false\n\t\tdate.#offset = null\n\t\treturn date\n\t}\n\n\tstatic wrapAsLocalTime(jsDate: Date) {\n\t\tlet date = new TomlDate(jsDate)\n\t\tdate.#hasDate = false\n\t\tdate.#offset = null\n\t\treturn date\n\t}\n}\n","/*!\n * Copyright (c) Squirrel Chat et al., All rights reserved.\n * SPDX-License-Identifier: BSD-3-Clause\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n * list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n * this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holder nor the names of its contributors\n * may be used to endorse or promote products derived from this software without\n * specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\ntype TomlErrorOptions = ErrorOptions & {\n\ttoml: string\n\tptr: number\n}\n\nfunction getLineColFromPtr(string: string, ptr: number): [number, number] {\n\tlet lines = string.slice(0, ptr).split(/\\r\\n|\\n|\\r/g)\n\treturn [lines.length, lines.pop()!.length + 1]\n}\n\nfunction makeCodeBlock(string: string, line: number, column: number) {\n\tlet lines = string.split(/\\r\\n|\\n|\\r/g)\n\tlet codeblock = ''\n\n\tlet numberLen = (Math.log10(line + 1) | 0) + 1\n\n\tfor (let i = line - 1; i <= line + 1; i++) {\n\t\tlet l = lines[i - 1]\n\t\tif (!l) continue\n\n\t\tcodeblock += i.toString().padEnd(numberLen, ' ')\n\t\tcodeblock += ': '\n\t\tcodeblock += l\n\t\tcodeblock += '\\n'\n\n\t\tif (i === line) {\n\t\t\tcodeblock += ' '.repeat(numberLen + column + 2)\n\t\t\tcodeblock += '^\\n'\n\t\t}\n\t}\n\n\treturn codeblock\n}\n\nexport class TomlError extends Error {\n\tline: number\n\tcolumn: number\n\tcodeblock: string\n\n\tconstructor(message: string, options: TomlErrorOptions) {\n\t\tconst [line, column] = getLineColFromPtr(options.toml, options.ptr)\n\t\tconst codeblock = makeCodeBlock(options.toml, line, column)\n\n\t\tsuper(`Invalid TOML document: ${message}\\n\\n${codeblock}`, options)\n\t\tthis.line = line\n\t\tthis.column = column\n\t\tthis.codeblock = codeblock\n\t}\n}\n","/*!\n * Copyright (c) Squirrel Chat et al., All rights reserved.\n * SPDX-License-Identifier: BSD-3-Clause\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n * list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n * this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holder nor the names of its contributors\n * may be used to endorse or promote products derived from this software without\n * specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport { TomlDate } from './date.js'\nimport { TomlError } from './error.js'\n\n// let CTRL_REGEX = /[\\x00-\\x08\\x0f-\\x1f\\x7f]/\nlet INT_REGEX = /^((0x[0-9a-fA-F](_?[0-9a-fA-F])*)|(([+-]|0[ob])?\\d(_?\\d)*))$/\nlet FLOAT_REGEX = /^[+-]?\\d(_?\\d)*(\\.\\d(_?\\d)*)?([eE][+-]?\\d(_?\\d)*)?$/\nlet LEADING_ZERO = /^[+-]?0[0-9_]/\n\n/** @internal */\nexport function parseString(str: string, ptr: number): [string, number] {\n\tlet c = str[ptr++]!\n\tlet first = c\n\tlet isLiteral = c === \"'\"\n\tlet isMultiline = c === str[ptr] && c === str[ptr + 1]\n\tif (isMultiline) {\n\t\t// Trim initial newline\n\t\tif (str[ptr += 2] === '\\n') ptr++\n\t\telse if (str[ptr] === '\\r' && str[ptr + 1] === '\\n') ptr += 2\n\t}\n\n\t/*\n\tThe fast path does not seem to bring significant performance gains, so it's commented out.\n\tKept for reference and/or future fafoing.\n\n\tWithout: spec 5.08 µs/iter 3.88 ipc (99.44% cache) 23.90 branch misses 28.61k cycles 111.01k instructions\n\t 5MB 115.73 ms/iter 2.51 ipc (98.36% cache) 3.12M branch misses 619.30M cycles 1.56G instructions\n\n\tWith: spec 5.09 µs/iter 3.90 ipc (99.46% cache) 24.42 branch misses 28.57k cycles 111.49k instructions\n\t 5MB 113.89 ms/iter 2.47 ipc (98.38% cache) 3.12M branch misses 611.94M cycles 1.51G instructions\n\n\tif (c === \"'\") {\n\t\t// Literal strings fast path - no transform needs to occur; just grab the str and that's it\n\t\tlet endPtr = str.indexOf(isMultiline ? \"'''\" : \"'\", ptr)\n\t\tif (endPtr < 0) {\n\t\t\tthrow new TomlError(\"unfinished string literal\", { toml: str, ptr })\n\t\t}\n\n\t\tif (isMultiline) {\n\t\t\t// If the string ends with 4-5 quotes, then the first 1-2 are part of the string\n\t\t\tif (str[endPtr + 3] === \"'\") endPtr++\n\t\t\tif (str[endPtr + 3] === \"'\") endPtr++\n\t\t}\n\n\t\tlet string = str.slice(ptr, endPtr)\n\t\tif (CTRL_REGEX.test(string)) {\n\t\t\tlet match = string.match(CTRL_REGEX)!\n\t\t\tthrow new TomlError('control characters are not allowed in strings', { toml: str, ptr: ptr + (match.index ?? 0) })\n\t\t}\n\t\treturn [string, endPtr + (isMultiline ? 3 : 1)]\n\t}\n\t*/\n\n\tlet parsed = ''\n\tlet sliceStart = ptr\n\n\t// states:\n\t// 0 - decoding\n\t// 1 - decoding escape\n\t// 2 - whitespace escape (no newline encountered yet, must fail on non-whitespace)\n\t// 3 - whitespace escape (newline encountered, allowed to transition back to normal decode)\n\tlet state = 0\n\tfor (let i = ptr; i < str.length; i++) {\n\t\tc = str[i]!\n\n\t\t// Deal with newlines first, since that simplifies control character checking and handling across all states\n\t\tif (isMultiline && (c === '\\n' || (c === '\\r' && str[i + 1] === '\\n'))) {\n\t\t\tstate = state && 3\n\t\t}\n\n\t\t// Control characters are banned in TOML, so we throw an error if we encounter them\n\t\telse if ((c < '\\x20' && c !== '\\t') || c === '\\x7f') {\n\t\t\tthrow new TomlError('control characters are not allowed in strings', {\n\t\t\t\ttoml: str,\n\t\t\t\tptr: i,\n\t\t\t})\n\t\t}\n\n\t\t// The string might terminate while we're parsing through a newline escape.\n\t\t// It must have encountered a newline; otherwise, it'll simply fail in another branch.\n\t\telse if ((!state || state === 3) && c === first && (!isMultiline || (str[i + 1] === first && str[i + 2] === first))) {\n\t\t\tif (isMultiline) {\n\t\t\t\t// If the string ends with 4-5 quotes, then the first 1-2 are part of the string\n\t\t\t\tif (str[i + 3] === first) i++\n\t\t\t\tif (str[i + 3] === first) i++\n\t\t\t}\n\n\t\t\treturn [\n\t\t\t\t// If we're in a newline escape still, then there's nothing to add.\n\t\t\t\t// Also try to avoid concat if there's nothing to add to parsed, or nothing has been added to parsed.\n\t\t\t\tstate ? parsed : parsed + str.slice(sliceStart, i),\n\t\t\t\ti + (isMultiline ? 3 : 1),\n\t\t\t]\n\t\t}\n\n\t\telse if (!state) {\n\t\t\tif (!isLiteral && c === '\\\\') {\n\t\t\t\tparsed += str.slice(sliceStart, (sliceStart = i))\n\t\t\t\tstate = 1\n\t\t\t}\n\t\t}\n\n\t\telse if (state === 1) {\n\t\t\tif (c === 'x' || c === 'u' || c === 'U') { // Unicode escape\n\t\t\t\tlet value = 0\n\t\t\t\tlet len = c === 'x' ? 2 : c === 'u' ? 4 : 8\n\t\t\t\tfor (let j = 0; j < len; j++, i++) {\n\t\t\t\t\tlet hex = str.charCodeAt(i + 1)\n\t\t\t\t\tlet digit =\n\t\t\t\t\t\t/* 0-9 */ hex >= 0x30 && hex <= 0x39 ? hex - 0x30 :\n\t\t\t\t\t\t/* A-F */ hex >= 0x41 && hex <= 0x46 ? hex - 0x41 + 10 :\n\t\t\t\t\t\t/* a-f */ hex >= 0x61 && hex <= 0x66 ? hex - 0x61 + 10 : -1\n\n\t\t\t\t\tif (digit < 0) throw new TomlError('invalid non-hex character in unicode escape', { toml: str, ptr: i + 1 })\n\t\t\t\t\tvalue = (value << 4) | digit\n\t\t\t\t}\n\n\t\t\t\t// Because JS does bitwise on signed 32bit integers, all 0xfzzzzzzz values are actually seen as negative\n\t\t\t\tif (value < 0 || value > 0x10ffff || (value >= 0xd800 && value <= 0xdfff)) {\n\t\t\t\t\tthrow new TomlError('invalid unicode escape', { toml: str, ptr: i })\n\t\t\t\t}\n\n\t\t\t\tparsed += String.fromCodePoint(value)\n\t\t\t\tsliceStart = i + 1\n\t\t\t\tstate = 0\n\t\t\t}\n\n\t\t\telse if (c === ' ' || c === '\\t') { // If it was a newline, it'd have been handled earlier\n\t\t\t\tstate = 2\n\t\t\t}\n\n\t\t\telse {\n\t\t\t\tif (c === 'b') parsed += '\\b'\n\t\t\t\telse if (c === 't') parsed += '\\t'\n\t\t\t\telse if (c === 'n') parsed += '\\n'\n\t\t\t\telse if (c === 'f') parsed += '\\f'\n\t\t\t\telse if (c === 'r') parsed += '\\r'\n\t\t\t\telse if (c === 'e') parsed += '\\x1b'\n\t\t\t\telse if (c === '\"') parsed += '\"'\n\t\t\t\telse if (c === '\\\\') parsed += '\\\\'\n\t\t\t\telse throw new TomlError('unrecognized escape sequence', { toml: str, ptr: i })\n\t\t\t\tsliceStart = i + 1\n\t\t\t\tstate = 0\n\t\t\t}\n\t\t}\n\n\t\telse if (c !== ' ' && c !== '\\t') {\n\t\t\tif (state === 2) {\n\t\t\t\tthrow new TomlError('invalid escape: only line-ending whitespace may be escaped', {\n\t\t\t\t\ttoml: str,\n\t\t\t\t\tptr: sliceStart,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\t// State cannot be zero, or we'd have branched earlier already.\n\t\t\t// If it's a backslash, immediately transition to the escape state so it can be processed.\n\t\t\tstate = !isLiteral && c === '\\\\' ? 1 : 0\n\t\t\tsliceStart = i\n\t\t}\n\t}\n\n\tthrow new TomlError('unfinished string', { toml: str, ptr })\n}\n\nexport type IntegersAsBigInt = undefined | boolean | 'asNeeded'\n\n/** @internal */\nexport function parseValue(value: string, toml: string, ptr: number, integersAsBigInt: IntegersAsBigInt): boolean | number | bigint | TomlDate {\n\t// Constant values\n\tif (value === 'true') return true\n\tif (value === 'false') return false\n\tif (value === '-inf') return -Infinity\n\tif (value === 'inf' || value === '+inf') return Infinity\n\tif (value === 'nan' || value === '+nan' || value === '-nan') return NaN\n\n\t// Avoid FP representation of -0\n\tif (value === '-0') return integersAsBigInt ? 0n : 0\n\n\t// Numbers\n\tlet isInt = INT_REGEX.test(value)\n\tif (isInt || FLOAT_REGEX.test(value)) {\n\t\tif (LEADING_ZERO.test(value)) {\n\t\t\tthrow new TomlError('leading zeroes are not allowed', {\n\t\t\t\ttoml: toml,\n\t\t\t\tptr: ptr,\n\t\t\t})\n\t\t}\n\n\t\tvalue = value.replace(/_/g, '')\n\t\tlet numeric: number | bigint = +value\n\n\t\tif (isNaN(numeric)) {\n\t\t\tthrow new TomlError('invalid number', {\n\t\t\t\ttoml: toml,\n\t\t\t\tptr: ptr,\n\t\t\t})\n\t\t}\n\n\t\tif (isInt) {\n\t\t\tif ((isInt = !Number.isSafeInteger(numeric)) && !integersAsBigInt) {\n\t\t\t\tthrow new TomlError('integer value cannot be represented losslessly', {\n\t\t\t\t\ttoml: toml,\n\t\t\t\t\tptr: ptr,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tif (isInt || integersAsBigInt === true) numeric = BigInt(value)\n\t\t}\n\n\t\treturn numeric\n\t}\n\n\tconst date = new TomlDate(value)\n\tif (!date.isValid()) {\n\t\tthrow new TomlError('invalid value', {\n\t\t\ttoml: toml,\n\t\t\tptr: ptr,\n\t\t})\n\t}\n\n\treturn date\n}\n","/*!\n * Copyright (c) Squirrel Chat et al., All rights reserved.\n * SPDX-License-Identifier: BSD-3-Clause\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n * list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n * this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holder nor the names of its contributors\n * may be used to endorse or promote products derived from this software without\n * specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport type { TomlDate } from './date.js'\nimport { TomlError } from './error.js'\n\nexport type TomlPrimitive = string | number | bigint | boolean | TomlDate\nexport type TomlTable = { [key: string]: TomlValue }\nexport type TomlValue = TomlPrimitive | TomlValue[] | TomlTable\n\nexport type TomlTableWithoutBigInt = { [key: string]: TomlValueWithoutBigInt }\nexport type TomlValueWithoutBigInt = Exclude<TomlPrimitive, bigint> | TomlValueWithoutBigInt[] | TomlTableWithoutBigInt\n\n/** @internal */\nexport function indexOfNewline(str: string, start = 0, end = str.length) {\n\tlet idx = str.indexOf('\\n', start)\n\tif (str[idx - 1] === '\\r') idx--\n\treturn idx <= end ? idx : -1\n}\n\n/** @internal */\nexport function skipComment(str: string, ptr: number) {\n\tfor (let i = ptr; i < str.length; i++) {\n\t\tlet c = str[i]!\n\t\tif (c === '\\n')\n\t\t\treturn i\n\n\t\tif (c === '\\r' && str[i + 1] === '\\n')\n\t\t\treturn i + 1\n\n\t\tif ((c < '\\x20' && c !== '\\t') || c === '\\x7f') {\n\t\t\tthrow new TomlError('control characters are not allowed in comments', {\n\t\t\t\ttoml: str,\n\t\t\t\tptr: ptr,\n\t\t\t})\n\t\t}\n\t}\n\n\treturn str.length\n}\n\n/** @internal */\nexport function skipVoid(str: string, ptr: number, banNewLines?: boolean, banComments?: boolean): number {\n\tlet c\n\twhile (1) {\n\t\twhile ((c = str[ptr]) === ' ' || c === '\\t' || (!banNewLines && (c === '\\n' || (c === '\\r' && str[ptr + 1] === '\\n')))) ptr++\n\n\t\t// Tucking the return statement here would save 5 characters >:)\n\t\t// But TypeScript fails to detect there is no way to exit the loop so it complains about the lack of final return\n\t\tif (banComments || c !== '#') break\n\n\t\tptr = skipComment(str, ptr)\n\t}\n\n\treturn ptr\n}\n\n/** @internal */\nexport function skipUntil(str: string, ptr: number, sep: string, end?: string, banNewLines: boolean = false) {\n\tif (!end) {\n\t\tptr = indexOfNewline(str, ptr)\n\t\treturn ptr < 0 ? str.length : ptr\n\t}\n\n\tfor (let i = ptr; i < str.length; i++) {\n\t\tlet c = str[i]\n\t\tif (c === '#') {\n\t\t\ti = indexOfNewline(str, i)\n\t\t\tif (i < 0) break\n\t\t} else if (c === sep) {\n\t\t\treturn i + 1\n\t\t} else if (c === end || (banNewLines && (c === '\\n' || (c === '\\r' && str[i + 1] === '\\n')))) {\n\t\t\treturn i\n\t\t}\n\t}\n\n\tthrow new TomlError('cannot find end of structure', {\n\t\ttoml: str,\n\t\tptr: ptr,\n\t})\n}\n","/*!\n * Copyright (c) Squirrel Chat et al., All rights reserved.\n * SPDX-License-Identifier: BSD-3-Clause\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n * list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n * this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holder nor the names of its contributors\n * may be used to endorse or promote products derived from this software without\n * specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport { type IntegersAsBigInt, parseString, parseValue } from './primitive.js'\nimport { parseArray, parseInlineTable } from './struct.js'\nimport { skipVoid, skipUntil, skipComment, type TomlValue } from './util.js'\nimport { TomlError } from './error.js'\n\nfunction sliceAndTrimEndOf(str: string, startPtr: number, endPtr: number): [string, number] {\n\tlet value = str.slice(startPtr, endPtr)\n\n\tlet commentIdx = value.indexOf('#')\n\tif (commentIdx > -1) {\n\t\t// The call to skipComment allows to \"validate\" the comment\n\t\t// (absence of control characters)\n\t\tskipComment(str, commentIdx)\n\t\tvalue = value.slice(0, commentIdx)\n\t}\n\n\treturn [value.trimEnd(), commentIdx]\n}\n\n/** @internal */\nexport function extractValue(str: string, ptr: number, end: string | undefined, depth: number, integersAsBigInt: IntegersAsBigInt): [TomlValue, number] {\n\tif (depth === 0) {\n\t\tthrow new TomlError('document contains excessively nested structures. aborting.', {\n\t\t\ttoml: str,\n\t\t\tptr: ptr,\n\t\t})\n\t}\n\n\tlet c = str[ptr]\n\tif (c === '[' || c === '{') {\n\t\tlet [value, endPtr] = c === '['\n\t\t\t? parseArray(str, ptr, depth, integersAsBigInt)\n\t\t\t: parseInlineTable(str, ptr, depth, integersAsBigInt)\n\n\t\tif (end) {\n\t\t\tendPtr = skipVoid(str, endPtr)\n\t\t\tif (str[endPtr] === ',') endPtr++\n\t\t\telse if (str[endPtr] !== end) {\n\t\t\t\tthrow new TomlError('expected comma or end of structure', {\n\t\t\t\t\ttoml: str,\n\t\t\t\t\tptr: endPtr,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\treturn [value, endPtr]\n\t}\n\n\tif (c === '\"' || c === \"'\") {\n\t\tlet [parsed, endPtr] = parseString(str, ptr)\n\t\tif (end) {\n\t\t\tendPtr = skipVoid(str, endPtr)\n\n\t\t\tif (str[endPtr] && str[endPtr] !== ',' && str[endPtr] !== end && str[endPtr] !== '\\n' && str[endPtr] !== '\\r') {\n\t\t\t\tthrow new TomlError('unexpected character encountered', {\n\t\t\t\t\ttoml: str,\n\t\t\t\t\tptr: endPtr,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tif (str[endPtr] === ',') endPtr++\n\t\t}\n\n\t\treturn [parsed, endPtr]\n\t}\n\n\tlet endPtr = skipUntil(str, ptr, ',', end)\n\tlet slice = sliceAndTrimEndOf(str, ptr, endPtr - (str[endPtr - 1] === ',' ? 1 : 0))\n\tif (!slice[0]) {\n\t\tthrow new TomlError('incomplete key-value declaration: no value specified', {\n\t\t\ttoml: str,\n\t\t\tptr: ptr,\n\t\t})\n\t}\n\n\tif (end && slice[1] > -1) {\n\t\tendPtr = skipVoid(str, ptr + slice[1])\n\t\tif (str[endPtr] === ',') endPtr++\n\t}\n\n\treturn [\n\t\tparseValue(slice[0], str, ptr, integersAsBigInt),\n\t\tendPtr,\n\t]\n}\n","/*!\n * Copyright (c) Squirrel Chat et al., All rights reserved.\n * SPDX-License-Identifier: BSD-3-Clause\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n * list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n * this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holder nor the names of its contributors\n * may be used to endorse or promote products derived from this software without\n * specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport { type IntegersAsBigInt, parseString } from './primitive.js'\nimport { extractValue } from './extract.js'\nimport { indexOfNewline, skipComment, skipVoid, type TomlTable, type TomlValue } from './util.js'\nimport { TomlError } from './error.js'\n\nlet KEY_PART_RE = /^[a-zA-Z0-9-_]+[ \\t]*$/\n\n/** @internal */\nexport function parseKey(str: string, ptr: number, end = '='): [string[], number] {\n\tlet dot = ptr - 1\n\tlet parsed = []\n\n\tlet endPtr = str.indexOf(end, ptr)\n\tif (endPtr < 0) {\n\t\tthrow new TomlError('incomplete key-value: cannot find end of key', {\n\t\t\ttoml: str,\n\t\t\tptr: ptr,\n\t\t})\n\t}\n\n\tdo {\n\t\tlet c = str[(ptr = ++dot)]\n\n\t\t// If it's whitespace, ignore\n\t\tif (c !== ' ' && c !== '\\t') {\n\t\t\t// If it's a string\n\t\t\tif (c === '\"' || c === \"'\") {\n\t\t\t\tif (c === str[ptr + 1] && c === str[ptr + 2]) {\n\t\t\t\t\tthrow new TomlError('multiline strings are not allowed in keys', {\n\t\t\t\t\t\ttoml: str,\n\t\t\t\t\t\tptr: ptr,\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tlet [part, eos] = parseString(str, ptr)\n\t\t\t\tdot = str.indexOf('.', eos)\n\n\t\t\t\tlet strEnd = str.slice(eos, dot < 0 || dot > endPtr ? endPtr : dot)\n\t\t\t\tlet newLine = indexOfNewline(strEnd)\n\t\t\t\tif (newLine > -1) {\n\t\t\t\t\tthrow new TomlError('newlines are not allowed in keys', {\n\t\t\t\t\t\ttoml: str,\n\t\t\t\t\t\tptr: ptr + dot + newLine,\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tif (strEnd.trimStart()) {\n\t\t\t\t\tthrow new TomlError('found extra tokens after the string part', {\n\t\t\t\t\t\ttoml: str,\n\t\t\t\t\t\tptr: eos,\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tif (endPtr < eos) {\n\t\t\t\t\tendPtr = str.indexOf(end, eos)\n\t\t\t\t\tif (endPtr < 0) {\n\t\t\t\t\t\tthrow new TomlError('incomplete key-value: cannot find end of key', {\n\t\t\t\t\t\t\ttoml: str,\n\t\t\t\t\t\t\tptr: ptr,\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tparsed.push(part)\n\t\t\t} else {\n\t\t\t\t// Normal raw key part consumption and validation\n\t\t\t\tdot = str.indexOf('.', ptr)\n\t\t\t\tlet part = str.slice(ptr, dot < 0 || dot > endPtr ? endPtr : dot)\n\t\t\t\tif (!KEY_PART_RE.test(part)) {\n\t\t\t\t\tthrow new TomlError('only letter, numbers, dashes and underscores are allowed in keys', {\n\t\t\t\t\t\ttoml: str,\n\t\t\t\t\t\tptr: ptr,\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tparsed.push(part.trimEnd())\n\t\t\t}\n\t\t}\n\t\t// Until there's no more dot\n\t} while (dot + 1 && dot < endPtr)\n\n\treturn [parsed, skipVoid(str, endPtr + 1, true, true)]\n}\n\n/** @internal */\nexport function parseInlineTable(str: string, ptr: number, depth: number, integersAsBigInt: IntegersAsBigInt): [TomlTable, number] {\n\tlet res: TomlTable = {}\n\tlet seen = new Set()\n\tlet c: string\n\n\tptr++\n\twhile ((c = str[ptr++]!) !== '}' && c) {\n\t\tif (c === ',') {\n\t\t\tthrow new TomlError('expected value, found comma', {\n\t\t\t\ttoml: str,\n\t\t\t\tptr: ptr - 1,\n\t\t\t})\n\t\t} else if (c === '#') ptr = skipComment(str, ptr)\n\t\telse if (c !== ' ' && c !== '\\t' && c !== '\\n' && c !== '\\r') {\n\t\t\tlet k: string\n\t\t\tlet t: any = res\n\t\t\tlet hasOwn = false\n\n\t\t\tlet [key, keyEndPtr] = parseKey(str, ptr - 1)\n\t\t\tfor (let i = 0; i < key.length; i++) {\n\t\t\t\tif (i) t = hasOwn! ? t[k!] : (t[k!] = {})\n\n\t\t\t\tk = key[i]!\n\t\t\t\tif ((hasOwn = Object.hasOwn(t, k)) && (typeof t[k] !== 'object' || seen.has(t[k]))) {\n\t\t\t\t\tthrow new TomlError('trying to redefine an already defined value', {\n\t\t\t\t\t\ttoml: str,\n\t\t\t\t\t\tptr: ptr,\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tif (!hasOwn && k === '__proto__') {\n\t\t\t\t\tObject.defineProperty(t, k, { enumerable: true, configurable: true, writable: true })\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (hasOwn) {\n\t\t\t\tthrow new TomlError('trying to redefine an already defined value', {\n\t\t\t\t\ttoml: str,\n\t\t\t\t\tptr: ptr,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tlet [value, valueEndPtr] = extractValue(str, keyEndPtr, '}', depth - 1, integersAsBigInt)\n\t\t\tseen.add(value)\n\n\t\t\tt[k!] = value\n\t\t\tptr = valueEndPtr\n\t\t}\n\t}\n\n\tif (!c) {\n\t\tthrow new TomlError('unfinished table encountered', {\n\t\t\ttoml: str,\n\t\t\tptr: ptr,\n\t\t})\n\t}\n\n\treturn [res, ptr]\n}\n\n/** @internal */\nexport function parseArray(str: string, ptr: number, depth: number, integersAsBigInt: IntegersAsBigInt): [TomlValue[], number] {\n\tlet res: TomlValue[] = []\n\tlet c\n\n\tptr++\n\twhile ((c = str[ptr++]) !== ']' && c) {\n\t\tif (c === ',') {\n\t\t\tthrow new TomlError('expected value, found comma', {\n\t\t\t\ttoml: str,\n\t\t\t\tptr: ptr - 1,\n\t\t\t})\n\t\t} else if (c === '#') ptr = skipComment(str, ptr)\n\t\telse if (c !== ' ' && c !== '\\t' && c !== '\\n' && c !== '\\r') {\n\t\t\tlet e = extractValue(str, ptr - 1, ']', depth - 1, integersAsBigInt)\n\t\t\tres.push(e[0])\n\t\t\tptr = e[1]\n\t\t}\n\t}\n\n\tif (!c) {\n\t\tthrow new TomlError('unfinished array encountered', {\n\t\t\ttoml: str,\n\t\t\tptr: ptr,\n\t\t})\n\t}\n\n\treturn [res, ptr]\n}\n","/*!\n * Copyright (c) Squirrel Chat et al., All rights reserved.\n * SPDX-License-Identifier: BSD-3-Clause\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this\n * list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright notice,\n * this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holder nor the names of its contributors\n * may be used to endorse or promote products derived from this software without\n * specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport type { IntegersAsBigInt } from './primitive.js'\nimport { parseKey } from './struct.js'\nimport { extractValue } from './extract.js'\nimport { skipVoid, type TomlTable, type TomlTableWithoutBigInt } from './util.js'\nimport { TomlError } from './error.js'\n\nconst enum Type { DOTTED, EXPLICIT, ARRAY, ARRAY_DOTTED }\n\ntype MetaState = { t: Type; d: boolean; i: number; c: MetaRecord }\ntype MetaRecord = { [k: string]: MetaState }\ntype PeekResult = [string, TomlTable, MetaRecord] | null\n\nfunction peekTable(key: string[], table: TomlTable, meta: MetaRecord, type: Type): PeekResult {\n\tlet t: any = table\n\tlet m = meta\n\tlet k: string\n\tlet hasOwn = false\n\tlet state: MetaState\n\n\tfor (let i = 0; i < key.length; i++) {\n\t\tif (i) {\n\t\t\tt = hasOwn! ? t[k!] : (t[k!] = {})\n\t\t\tm = (state = m[k!]!).c\n\n\t\t\tif (type === Type.DOTTED && (state.t === Type.EXPLICIT || state.t === Type.ARRAY)) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tif (state.t === Type.ARRAY) {\n\t\t\t\tlet l = t.length - 1\n\t\t\t\tt = t[l]\n\t\t\t\tm = m[l]!.c\n\t\t\t}\n\t\t}\n\n\t\tk = key[i]!\n\t\tif ((hasOwn = Object.hasOwn(t, k)) && m[k]?.t === Type.DOTTED && m[k]?.d) {\n\t\t\treturn null\n\t\t}\n\n\t\tif (!hasOwn) {\n\t\t\tif (k === '__proto__') {\n\t\t\t\tObject.defineProperty(t, k, { enumerable: true, configurable: true, writable: true })\n\t\t\t\tObject.defineProperty(m, k, { enumerable: true, configurable: true, writable: true })\n\t\t\t}\n\n\t\t\tm[k] = {\n\t\t\t\tt: i < key.length - 1 && type === Type.ARRAY\n\t\t\t\t\t? Type.ARRAY_DOTTED\n\t\t\t\t\t: type,\n\t\t\t\td: false,\n\t\t\t\ti: 0,\n\t\t\t\tc: {},\n\t\t\t}\n\t\t}\n\t}\n\n\tstate = m[k!]!\n\tif (state.t !== type && !(type === Type.EXPLICIT && state.t === Type.ARRAY_DOTTED)) {\n\t\t// Bad key type!\n\t\treturn null\n\t}\n\n\tif (type === Type.ARRAY) {\n\t\tif (!state.d) {\n\t\t\tstate.d = true\n\t\t\tt[k!] = []\n\t\t}\n\n\t\tt[k!].push(t = {})\n\t\tstate.c[state.i++] = (state = { t: Type.EXPLICIT, d: false, i: 0, c: {} })\n\t}\n\n\tif (state.d) {\n\t\t// Redefining a table!\n\t\treturn null\n\t}\n\n\tstate.d = true\n\tif (type === Type.EXPLICIT) {\n\t\tt = hasOwn ? t[k!] : (t[k!] = {})\n\t} else if (type === Type.DOTTED && hasOwn) {\n\t\treturn null\n\t}\n\n\treturn [k!, t, state.c]\n}\n\nexport interface ParseOptions {\n\tmaxDepth?: number\n\tintegersAsBigInt?: IntegersAsBigInt\n}\n\nexport function parse(toml: string, options?: ParseOptions & { integersAsBigInt: Exclude<IntegersAsBigInt, undefined | false> }): TomlTable\nexport function parse(toml: string, options?: ParseOptions): TomlTableWithoutBigInt\nexport function parse(toml: string, { maxDepth = 1000, integersAsBigInt }: ParseOptions = {}): TomlTable {\n\tlet res = {}\n\tlet meta = {}\n\n\tlet tbl = res\n\tlet m = meta\n\n\tfor (let ptr = skipVoid(toml, 0); ptr < toml.length;) {\n\t\tif (toml[ptr] === '[') {\n\t\t\tlet isTableArray = toml[++ptr] === '['\n\t\t\tlet k = parseKey(toml, (ptr += +isTableArray), ']')\n\n\t\t\tif (isTableArray) {\n\t\t\t\tif (toml[k[1] - 1] !== ']') {\n\t\t\t\t\tthrow new TomlError('expected end of table declaration', {\n\t\t\t\t\t\ttoml: toml,\n\t\t\t\t\t\tptr: k[1] - 1,\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\tk[1]++\n\t\t\t}\n\n\t\t\tlet p = peekTable(k[0], res, meta, isTableArray ? Type.ARRAY : Type.EXPLICIT)\n\t\t\tif (!p) {\n\t\t\t\tthrow new TomlError('trying to redefine an already defined table or value', {\n\t\t\t\t\ttoml: toml,\n\t\t\t\t\tptr: ptr,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tm = p[2]\n\t\t\ttbl = p[1]\n\t\t\tptr = k[1]\n\t\t} else {\n\t\t\tlet k = parseKey(toml, ptr)\n\t\t\tlet p = peekTable(k[0], tbl, m, Type.DOTTED)\n\t\t\tif (!p) {\n\t\t\t\tthrow new TomlError('trying to redefine an already defined table or value', {\n\t\t\t\t\ttoml: toml,\n\t\t\t\t\tptr: ptr,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tlet v = extractValue(toml, k[1], void 0, maxDepth, integersAsBigInt)\n\t\t\tp[1][p[0]] = v[0]\n\t\t\tptr = v[1]\n\t\t}\n\n\t\tptr = skipVoid(toml, ptr, true)\n\t\tif (toml[ptr] && toml[ptr] !== '\\n' && toml[ptr] !== '\\r') {\n\t\t\tthrow new TomlError('each key-value declaration must be followed by an end-of-line', {\n\t\t\t\ttoml: toml,\n\t\t\t\tptr: ptr,\n\t\t\t})\n\t\t}\n\t\tptr = skipVoid(toml, ptr)\n\t}\n\n\treturn res\n}\n","/**\n * Derive the set of top-level path prefixes that safeword may write to,\n * sourced from SAFEWORD_SCHEMA at build time. Consumed by the auto-upgrade\n * hook to identify files to stage after `safeword install` runs.\n *\n * Why this exists: the hook previously hardcoded the prefix list, which\n * silently drifts when a pack introduces a new top-level directory.\n *\n * Matching semantics: dir prefixes (trailing `/`) match by `startsWith`;\n * bare file paths match by exact equality. The generated module exports\n * both the flat list and an `isSafewordPath(file)` helper that uses these\n * semantics.\n */\n\nimport nodePath from 'node:path';\n\nimport type { JsonMergeDefinition, ProjectContext } from './packs/types.js';\nimport type { SafewordSchema } from './schema.js';\nimport { resolveNamespaceRoot } from './utils/configured-paths.js';\n\n/**\n * Safeword-owned top-level directories a customer's OWN formatter must skip, so\n * safeword's files never churn in their diffs/CI (ticket EYRK34). Single source\n * for every formatter's ignore wiring — `.prettierignore`, Biome excludes, ruff\n * `extend-exclude`, etc. — so adding an owned dir updates all of them in one\n * place. Bare names (no trailing slash); each tool maps to its own syntax.\n *\n * Covers the two well-known namespace roots; a *custom* `paths.projectRoot` is\n * layered on at apply time via `safewordIgnoreDirectories(resolvedNamespaceDirectory(ctx))`\n * (issue #273), since this static list can't name an arbitrary root.\n *\n * `features/` and `steps/` are intentionally absent: the customer authors the\n * BDD feature files and step definitions there and wants them formatted. A drift\n * test asserts every entry here is a directory the schema actually manages.\n */\nexport const SAFEWORD_IGNORE_DIRS: readonly string[] = [\n '.safeword',\n '.claude',\n '.cursor',\n '.codex',\n '.agents',\n '.project',\n '.safeword-project',\n];\n\n/**\n * Safeword-owned dirs a formatter must skip, including a custom `paths.projectRoot`\n * (issue #273). `namespaceRootLabel` is the repo-relative resolved root from\n * `resolvedNamespaceDirectory`; undefined (default/legacy/repo-root) leaves the static\n * base list untouched.\n */\nexport function safewordIgnoreDirectories(namespaceRootLabel?: string): readonly string[] {\n return namespaceRootLabel !== undefined && !SAFEWORD_IGNORE_DIRS.includes(namespaceRootLabel)\n ? [...SAFEWORD_IGNORE_DIRS, namespaceRootLabel]\n : SAFEWORD_IGNORE_DIRS;\n}\n\n/**\n * The resolved namespace root as a repo-relative dir label, returned only when it\n * is a custom root the static lists don't already cover. Returns undefined for the\n * default `.project`/legacy `.safeword-project` roots, for `paths.projectRoot:'.'`\n * (the repo root — excluding or staging it would match the whole repo), and for any\n * root resolved OUTSIDE the repo ('../…' would leak nonsensical entries).\n */\nexport function resolvedNamespaceDirectory(ctx: ProjectContext): string | undefined {\n const label = resolvedNamespaceRootLabel(ctx);\n // Skip the repo root ('.'), the well-known roots (already in the static lists),\n // and any root resolved OUTSIDE the repo ('../…') — a traversal label would leak\n // nonsensical ignore/prefix entries that match nothing under the repo.\n if (label === '.' || label.startsWith('..') || SAFEWORD_IGNORE_DIRS.includes(label)) {\n return undefined;\n }\n return label;\n}\n\n/**\n * The repo-relative resolved namespace-root label — always concrete (`.project` by\n * default, the legacy or custom `paths.projectRoot` otherwise), unlike\n * {@link resolvedNamespaceDirectory} which suppresses the well-known roots. Used where a\n * managed file must name the actual root path (e.g. the `.gitattributes` ticket-index\n * entries, #566). Repo-root namespace (`.`) yields `.`, so callers prefix-join cleanly.\n */\nexport function resolvedNamespaceRootLabel(ctx: ProjectContext): string {\n const root = ctx.namespaceRoot ?? resolveNamespaceRoot(ctx.cwd);\n return nodePath.relative(ctx.cwd, root) || '.';\n}\n\n/**\n * The safeword-owned ignore directories for a context — the static base list plus\n * the resolved custom `paths.projectRoot` (issue #273). Composition used by the\n * formatter merges so the two-step resolution lives in one place.\n */\nexport function resolvedIgnoreDirectories(ctx: ProjectContext): readonly string[] {\n return safewordIgnoreDirectories(resolvedNamespaceDirectory(ctx));\n}\n\n/**\n * Build a JSON-merge that adds safeword-owned dirs to a customer formatter's\n * string-array exclude/ignore field so the tool skips them (ticket EYRK34).\n * Resolved at apply time from `ctx`, so a custom `paths.projectRoot` is excluded\n * too (issue #273); `skipIfMissing` → only ever touches a config the customer has.\n *\n * `globForDir` controls the per-dir glob and defaults to the bare trailing-globstar\n * form used by dprint (`excludes`) and oxfmt (`ignorePatterns`). markdownlint-cli2\n * (`ignores`) overrides it with a leading-globstar form so the glob also matches\n * the absolute paths lint-staged passes (ticket #262).\n */\nexport function dirGlobExcludeMerge(\n field: string,\n globForDirectory: (dir: string) => string = dir => `${dir}/**`,\n): JsonMergeDefinition {\n return {\n keys: [field],\n skipIfMissing: true,\n merge: (existing, ctx) => {\n const safewordGlobs = resolvedIgnoreDirectories(ctx).map(dir => globForDirectory(dir));\n const current = Array.isArray(existing[field]) ? (existing[field] as string[]) : [];\n const merged = [...current];\n for (const glob of safewordGlobs) {\n if (!merged.includes(glob)) merged.push(glob);\n }\n return { ...existing, [field]: merged };\n },\n unmerge: (existing, ctx) => {\n const safewordGlobs = new Set(\n resolvedIgnoreDirectories(ctx).map(dir => globForDirectory(dir)),\n );\n const current = Array.isArray(existing[field]) ? (existing[field] as string[]) : [];\n const cleaned = current.filter(entry => !safewordGlobs.has(entry));\n // Drop the field without a dynamic `delete` or unused binding, re-adding it\n // only when entries remain.\n const rest = Object.fromEntries(Object.entries(existing).filter(([key]) => key !== field));\n return cleaned.length > 0 ? { ...rest, [field]: cleaned } : rest;\n },\n };\n}\n\nexport function computeSafewordPathPrefixes(schema: SafewordSchema): readonly string[] {\n const allPaths = [\n ...Object.keys(schema.ownedFiles),\n ...Object.keys(schema.managedFiles),\n ...Object.keys(schema.jsonMerges),\n ...Object.keys(schema.textPatches),\n ];\n\n const prefixes = new Set<string>();\n for (const path of allPaths) {\n const slashIndex = path.indexOf('/');\n prefixes.add(slashIndex === -1 ? path : path.slice(0, slashIndex + 1));\n }\n\n return [...prefixes].toSorted((a, b) => a.localeCompare(b));\n}\n\n/**\n * Reference implementation of the matching predicate. The generated module's\n * `isSafewordPath` is a closure over SAFEWORD_PATHS that runs this same logic.\n * Extracted so tests can verify semantics without evaluating generated code.\n */\nexport function matchesSafewordPath(file: string, prefixes: readonly string[]): boolean {\n for (const prefix of prefixes) {\n if (prefix.endsWith('/')) {\n if (file.startsWith(prefix)) return true;\n } else if (file === prefix) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Reference implementation of the auto-upgrade staging filter. Mirrors the\n * `filterSafewordFiles` exported from the generated module so tests can\n * exercise the exact behavior the hook relies on.\n */\nexport function referenceFilterSafewordFiles(\n changedFiles: readonly string[],\n untrackedFiles: readonly string[],\n prefixes: readonly string[],\n): readonly string[] {\n return [...changedFiles, ...untrackedFiles].filter(f => matchesSafewordPath(f, prefixes));\n}\n\nexport function generateOwnedPathsModule(\n schema: SafewordSchema,\n namespaceRootLabel?: string,\n): string {\n // The schema manifest carries legacy-prefixed namespace entries; installed\n // projects may run either well-known root (AQJ95G), so emit both prefixes —\n // plus the resolved custom root (issue #273) so the auto-upgrade hook stages\n // files scaffolded under a custom `paths.projectRoot`.\n const customPrefix = namespaceRootLabel === undefined ? [] : [`${namespaceRootLabel}/`];\n const prefixes = [\n ...new Set([\n ...computeSafewordPathPrefixes(schema).flatMap(prefix =>\n prefix === '.safeword-project/' ? ['.safeword-project/', '.project/'] : [prefix],\n ),\n ...customPrefix,\n ]),\n ];\n const entries = prefixes.map(prefix => ` '${prefix}',`).join('\\n');\n\n return `// Auto-generated by safeword from SAFEWORD_SCHEMA. Do not edit by hand.\n// Source: ownedFiles ∪ managedFiles ∪ jsonMerges ∪ textPatches → top-level prefixes.\n// Regenerated on every \\`safeword install\\`.\n\nexport const SAFEWORD_PATHS: readonly string[] = [\n${entries}\n];\n\n/**\n * Match a file path against the safeword-managed set. Directory prefixes\n * (entries ending in \\`/\\`) match by \\`startsWith\\`; bare file paths must\n * match exactly so e.g. \\`package.json.bak\\` does not match \\`package.json\\`.\n */\nexport function isSafewordPath(file: string): boolean {\n for (const prefix of SAFEWORD_PATHS) {\n if (prefix.endsWith('/')) {\n if (file.startsWith(prefix)) return true;\n } else if (file === prefix) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Pick the safeword-managed subset of files reported by \\`git diff --name-only\\`\n * (changed) and \\`git ls-files --others --exclude-standard\\` (untracked).\n * Used by the auto-upgrade hook to decide what to stage after \\`safeword install\\`.\n */\nexport function filterSafewordFiles(\n changedFiles: readonly string[],\n untrackedFiles: readonly string[],\n): readonly string[] {\n return [...changedFiles, ...untrackedFiles].filter(f => isSafewordPath(f));\n}\n`;\n}\n","/**\n * SAFEWORD Schema - Single Source of Truth\n *\n * All files, directories, configurations, and packages managed by safeword\n * are defined here. Commands use this schema via the reconciliation engine.\n *\n * Adding a new file? Add it here and it will be handled by setup/upgrade/reset.\n */\n\nimport nodePath from 'node:path';\n\nimport { acceptedHistoricalHookEntries } from './claude-plugin/historical-ownership.js';\nimport { CODEX_MIGRATION_SCHEMA } from './codex-plugin/inventory.js';\nimport { golangManagedFiles, golangOwnedFiles } from './packs/golang/files.js';\nimport { pythonManagedFiles, pythonOwnedFiles } from './packs/python/files.js';\nimport { rustManagedFiles, rustOwnedFiles } from './packs/rust/files.js';\nimport { sqlManagedFiles, sqlOwnedFiles } from './packs/sql/files.js';\nimport {\n typescriptJsonMerges,\n typescriptManagedFiles,\n typescriptOwnedFiles,\n typescriptPackages,\n} from './packs/typescript/files.js';\n// Re-export shared types from packs/types.ts (breaks circular dependency)\nexport type {\n FileDefinition,\n JsonMergeDefinition,\n ManagedFileDefinition,\n ProjectContext,\n} from './packs/types.js';\nimport { CURSOR_COMMAND_WRAPPERS, CURSOR_RULE_WRAPPERS } from './cursor-wrappers.js';\nimport {\n dirGlobExcludeMerge,\n generateOwnedPathsModule,\n resolvedIgnoreDirectories,\n resolvedNamespaceDirectory,\n resolvedNamespaceRootLabel,\n} from './owned-paths.js';\nimport type {\n FileDefinition,\n JsonMergeDefinition,\n ManagedFileDefinition,\n ProjectContext,\n} from './packs/types.js';\nimport { CURSOR_HOOKS, SETTINGS_HOOKS } from './templates/config.js';\nimport { AGENTS_MD_LINK, CLAUDE_MD_IMPORT_BLOCK } from './templates/content.js';\nimport { getTemplatesDirectory, readFile, readFileSafe } from './utils/fs.js';\nimport { filterOutEquivalentSafewordHooks, filterOutSafewordHooks } from './utils/hooks.js';\nimport { MCP_SERVERS } from './utils/install.js';\nimport { assignOrPrune } from './utils/json-merge.js';\nimport { VERSION } from './version.js';\n\nexport interface TextPatchDefinition {\n operation: 'prepend' | 'append';\n // Static string, or a factory resolved with ctx at plan time so the block can\n // depend on the resolved namespace root (e.g. a custom paths.projectRoot, #293).\n content: string | ((ctx: ProjectContext) => string);\n marker: string; // Used to detect if already applied & for removal\n // On apply, first remove this exact legacy block if present, then add `content`\n // — a byte-exact, idempotent one-block swap for migrating a managed file (e.g.\n // replacing a superseded SessionStart hook with its replacement) without a\n // separate imperative path. A no-op when the block is absent; guarded by\n // applyWhenContentIncludes so it only touches safeword-scaffolded files.\n supersedes?: string;\n applyWhenContentIncludes?: string[]; // Optional guard for semi-owned config files\n // Context predicate gating APPLICATION only (install/upgrade/creation) —\n // e.g. hook shims apply only in husky hosts (ZJMZ50). Unpatch is deliberately\n // NOT gated: reset must strip a leftover block even when the host's world\n // changed after install (a husky -> lefthook migration).\n when?: (ctx: ProjectContext) => boolean;\n unpatchContent?: string[]; // Additional exact blocks to remove on uninstall/reset\n removeFileIfContentEquals?: string[]; // Delete file only when remaining content is known scaffold\n // When set (append patches only), re-render the managed block in place on\n // upgrade instead of skip-on-marker — so a ctx-dependent block (e.g. a custom\n // projectRoot added to .prettierignore) heals on existing installs. A no-op\n // when the block is already current, so unchanged installs never churn (#293).\n rerender?: boolean;\n}\n\nexport interface ContractDefinition {\n requires: string[]; // Strings that must appear verbatim in the file content\n}\n\ninterface CodexMigrationDefinition {\n legacyFiles: string[];\n cleanupFiles: string[];\n legacyDirs: string[];\n hookEvents: string[];\n hookEventNames: Record<string, string>;\n hookScripts: string[];\n sharedRuntimePaths: readonly string[];\n cleanupRuntimePaths: string[];\n hookScriptEvents: Record<string, string>;\n hookScriptPrefix: string;\n packageRunner: 'npx';\n projectMarker: string;\n}\n\nexport interface SafewordSchema {\n version: string;\n ownedDirs: string[]; // Fully owned - create on setup, delete on reset\n sharedDirs: string[]; // We add to but don't own\n preservedDirs: string[]; // Created on setup, NOT deleted on reset (user data)\n deprecatedFiles: string[]; // Files to delete on upgrade (renamed or removed)\n deprecatedPackages: string[]; // Packages to uninstall on upgrade (consolidated into safeword plugin)\n deprecatedDirs: string[]; // Directories to delete on upgrade (no longer managed)\n ownedFiles: Record<string, FileDefinition>; // Overwrite on upgrade (if changed)\n managedFiles: Record<string, ManagedFileDefinition>; // Create if missing, update if safeword content\n jsonMerges: Record<string, JsonMergeDefinition>;\n // A file may carry an ordered list of patches. Patches apply in list order and\n // unpatch in reverse, so the patch that owns file removal\n // (removeFileIfContentEquals) runs last on uninstall. See #269.\n textPatches: Record<string, TextPatchDefinition | TextPatchDefinition[]>;\n legacyTextPatches: Record<string, TextPatchDefinition>; // Remove old managed text patches without installing them\n contracts: Record<string, ContractDefinition>; // Files that must contain specific strings (predicate parity)\n codexMigration: CodexMigrationDefinition; // Historical Codex identities retained until explicit finalization\n packages: {\n base: string[];\n conditional: Record<string, string[]>;\n };\n}\n\n// ============================================================================\n// Shared JSON Merge Definitions\n// ============================================================================\n\n/**\n * MCP servers JSON merge - shared between .mcp.json and .cursor/mcp.json\n */\nconst MCP_JSON_MERGE: JsonMergeDefinition = {\n keys: ['mcpServers.context7', 'mcpServers.playwright'],\n removeFileIfEmpty: true,\n merge: existing => {\n const mcpServers = { ...(existing.mcpServers as Record<string, unknown>) };\n // Add-if-missing: preserve any user-authored entry — including its key\n // ordering — and inject safeword's default only when the server key is\n // absent. This keeps `upgrade` from clobbering a customized\n // context7/playwright definition (e.g. a hosted HTTP transport), and\n // spreading existing first means an already-correct file produces an\n // identical merge (no write churn). (#255)\n mcpServers.context7 ??= MCP_SERVERS.context7;\n mcpServers.playwright ??= MCP_SERVERS.playwright;\n return { ...existing, mcpServers };\n },\n unmerge: existing => {\n const result = { ...existing };\n const mcpServers = { ...(existing.mcpServers as Record<string, unknown>) };\n\n // Blind-delete on uninstall: removing the server names safeword introduced\n // is the predictable inverse of install and matches the package.json /\n // .cursor/hooks.json unmerges. A value-match \"delete-if-ours\" was\n // considered but rejected — it can't tell a user customization from a\n // server installed by an older safeword version (different default value),\n // so it would orphan stale entries. uninstall is an explicit destructive\n // action; #255 is about upgrade not clobbering, which the merge handles.\n delete mcpServers.context7;\n delete mcpServers.playwright;\n\n assignOrPrune(result, 'mcpServers', mcpServers);\n return result;\n },\n};\n\n/**\n * markdownlint-cli2 `ignores` merge — add safeword-owned dirs so a consuming\n * repo's markdownlint never flags safeword's generated agent docs (ticket #262,\n * extends the EYRK34 formatter-ignore family alongside prettier/biome/dprint/oxfmt).\n *\n * Why this and not `.markdownlintignore`: markdownlint-cli2 does NOT read\n * `.markdownlintignore` at all (it's a markdownlint-cli v1 file), and even when a\n * tool honors it, lint-staged passes explicit absolute file paths that bypass\n * ignore-file globbing entirely. The cli2 `ignores` array is the one mechanism\n * that filters files even when passed explicitly — verified against lint-staged's\n * default absolute-path invocation.\n *\n * Glob form (see the call below) prefixes each dir with a leading globstar,\n * unlike the bare trailing-globstar form used by dprint/oxfmt: lint-staged passes\n * absolute paths by default, and the leading globstar is required for the glob to\n * match `/abs/repo/.claude/...`. It also still matches the relative tree-glob and\n * relative-explicit invocations.\n *\n * `ignores` is a cli2-only option, so it lives solely in `.markdownlint-cli2.jsonc`\n * (the standard `.markdownlint.*` rule files have no `ignores` field). `skipIfMissing`\n * → only ever touches a config the customer already has, never imposes markdownlint.\n *\n * Limitation (shared by the sibling biome/dprint/oxfmt `.jsonc` merges): the merge\n * engine parses with `JSON.parse`, so a `.markdownlint-cli2.jsonc` that actually\n * uses comments parses as undefined and `skipIfMissing` makes this a safe no-op —\n * the ignores aren't added, but the customer's commented config is never clobbered.\n * Stripping comments to parse would round-trip the file through `JSON.stringify` and\n * destroy those comments, which is worse than the no-op; comment-preserving JSONC\n * editing is a future improvement for the whole merge engine, not this ticket.\n */\nconst MARKDOWNLINT_CLI2_IGNORES_MERGE = dirGlobExcludeMerge('ignores', dir => `**/${dir}/**`);\n\nconst CURSOR_RULE_WRAPPER_OWNED_FILES: Record<string, FileDefinition> = Object.fromEntries(\n CURSOR_RULE_WRAPPERS.map(wrapper => [\n `.cursor/rules/${wrapper.name}.mdc`,\n { template: `cursor/rules/${wrapper.name}.mdc` },\n ]),\n);\n\nconst CURSOR_COMMAND_WRAPPER_OWNED_FILES: Record<string, FileDefinition> = Object.fromEntries(\n CURSOR_COMMAND_WRAPPERS.map(wrapper => [\n `.cursor/commands/${wrapper.name}.md`,\n { template: `commands/${wrapper.name}.md` },\n ]),\n);\n\nconst CURSOR_SHARED_SKILL_FILES = [\n 'audit/SKILL.md',\n 'bdd/SKILL.md',\n 'bdd/DISCOVERY.md',\n 'bdd/PLAN_IMPLEMENTATION.md',\n 'bdd/SCENARIOS.md',\n 'bdd/TDD.md',\n 'bdd/DONE.md',\n 'bdd/SPLITTING.md',\n 'bdd/VERIFY.md',\n 'brainstorm/SKILL.md',\n 'cleanup-zombies/SKILL.md',\n 'closeout/SKILL.md',\n 'debug/SKILL.md',\n 'elicit/SKILL.md',\n 'explain/SKILL.md',\n 'figure-it-out/SKILL.md',\n 'finish-review/SKILL.md',\n 'finish-review/REVIEWER.md',\n 'lint/SKILL.md',\n 'quality-review/SKILL.md',\n 'refactor/SKILL.md',\n 'retro/SKILL.md',\n 'retro-filer/SKILL.md',\n 'review-spec/SKILL.md',\n 'self-review/SKILL.md',\n 'spike/SKILL.md',\n 'tdd-review/SKILL.md',\n 'testing/SKILL.md',\n 'ticket-system/SKILL.md',\n 'verify/SKILL.md',\n] as const;\n\nconst CURSOR_SHARED_SKILL_OWNED_FILES: Record<string, FileDefinition> = Object.fromEntries(\n CURSOR_SHARED_SKILL_FILES.map(path => [\n `.safeword/skills/${path}`,\n { template: `skills/${path}` },\n ]),\n);\n\nconst CURSOR_SHARED_SKILL_DIRS = [\n '.safeword/skills',\n ...new Set(CURSOR_SHARED_SKILL_FILES.map(path => `.safeword/skills/${path.split('/', 1)[0]}`)),\n];\n\nfunction skipCodexRuntimeAssetInstall(): undefined {\n return;\n}\n\nconst CODEX_RUNTIME_ASSET_FILENAMES = [\n 'pre-tool-quality.ts',\n 'pre-tool-quality-helpers.ts',\n 'post-tool-quality.ts',\n 'post-tool-skill-nudge.ts',\n 'stop.ts',\n] as const;\n\nconst CODEX_RUNTIME_ASSETS: Record<string, ManagedFileDefinition> = Object.fromEntries(\n CODEX_RUNTIME_ASSET_FILENAMES.map(file => [\n `.safeword/hooks/codex/${file}`,\n {\n dogfoodParity: true,\n template: `hooks/codex/${file}`,\n generator: skipCodexRuntimeAssetInstall,\n },\n ]),\n);\n\n// ============================================================================\n// SAFEWORD_SCHEMA - The Single Source of Truth\n// ============================================================================\n\n/**\n * Transient state files safeword's hooks write under the *resolved namespace\n * root* every turn, as root-relative names (quality-state, failure-counts,\n * skill-invocations, re-entry, dependency-readiness). Single source for both\n * the per-root `.gitignore` managed file (`NAMESPACE_GITIGNORE_CONTENT`) and the\n * repo-root `.gitignore` block (`SAFEWORD_TRANSIENT_PATHS`). Patterns are exact\n * filenames plus the one `quality-state*` glob — never a bare `*` — so durable\n * siblings (tickets/, learnings/, principles.md, personas.md, glossary.md,\n * surfaces.md) stay tracked.\n */\nconst NAMESPACE_TRANSIENT_BASENAMES: readonly string[] = [\n 'quality-state*.json',\n 'cursor-run-identity.json',\n 'codex-run-identity.json',\n 'failure-counts.json',\n 'skill-invocations.log',\n 're-entry.md',\n 'dependency-readiness.json',\n];\n\n/**\n * Runtime/transient state files safeword's hooks write to the working tree\n * every turn (update-cache plus the namespace-root state above). They must be\n * gitignored — and untracked on upgrade if a customer committed them before the\n * ignore rule existed — because the hooks read/write these paths directly, so\n * git tracking is never consulted. Single source for the repo-root managed\n * `.gitignore` block (below) and the upgrade-time untrack.\n *\n * Both well-known namespace roots are listed: hooks write transient state under\n * the resolved root (TAGWZ8), which is `.project/` on fresh installs and\n * `.safeword-project/` on legacy ones. A *custom* `paths.projectRoot` is covered\n * by the per-root `.gitignore` (`NAMESPACE_GITIGNORE_CONTENT`) instead, since a\n * static repo-root block cannot name an arbitrary root (issue #272).\n */\nexport const SAFEWORD_TRANSIENT_PATHS: readonly string[] = [\n '.safeword/.update-cache.json',\n '.safeword/retro-drafts/',\n '.safeword/self-reports/',\n '.safeword/boundary-audit.jsonl',\n // Native Claude plugin migration state. The plugin's UserPromptSubmit hook\n // writes these directly every session — plugin mode, the attention record it\n // dedupes advisories against, the per-session launch claims, and the durable\n // cleanup transaction. `attempts-v1/` in particular grows one file per Claude\n // session, so tracking it would commit churn to every customer repository.\n '.safeword/claude-plugin/',\n '.safeword/state/reviews/',\n ...['.project', '.safeword-project'].flatMap(root =>\n NAMESPACE_TRANSIENT_BASENAMES.map(name => `${root}/${name}`),\n ),\n];\n\n/**\n * Content of the `.gitignore` written *inside* the resolved namespace root\n * (issue #272). Because the ignore rules live with the files they describe, a\n * custom `paths.projectRoot` is handled for free — the file lands wherever the\n * root resolves, and git applies each pattern relative to that directory. The\n * legacy-prefixed managed-file key is remapped to the resolved root by\n * `withResolvedNamespaceRoot`.\n *\n * Patterns are leading-slash-anchored so they match only the transient files at\n * the namespace root — where the hooks write them — and never a same-named file\n * deeper in the tree (e.g. a `tickets/.../re-entry.md`). This mirrors the\n * repo-root block, whose `.project/re-entry.md` entries are likewise anchored.\n */\nconst NAMESPACE_GITIGNORE_PATTERNS = NAMESPACE_TRANSIENT_BASENAMES.map(name => `/${name}`).join(\n '\\n',\n);\nconst NAMESPACE_GITIGNORE_CONTENT = `# Safeword - transient session state (auto-managed)\\n${NAMESPACE_GITIGNORE_PATTERNS}\\n`;\n\n/**\n * Top-level dirs a customer's prettier must skip so safeword's files don't dirty\n * the tree on install. Derived from the single SAFEWORD_IGNORE_DIRS list (ticket\n * EYRK34) — wholesale dir excludes (not per-file INDEX lines), so all of\n * `.safeword/`, `.claude/`, `.cursor/`, `.codex/`, `.agents/` and both namespace\n * roots are covered — plus husky's generated `_` dir. Previously this listed only\n * the INDEX markdown under each root (TAGWZ8/1GGD28); the whole `.project/` is\n * safeword-generated, so excluding it wholesale also covers tickets and learnings.\n *\n * Resolved per-ctx (issue #293) so a custom `paths.projectRoot` is excluded too —\n * for the two well-known roots this is identical to the old static list, so a\n * default/legacy install's `.prettierignore` block is byte-identical (no churn).\n */\nfunction managedPrettierPaths(ctx: ProjectContext): string[] {\n return ['.husky/_', ...resolvedIgnoreDirectories(ctx).map(dir => `${dir}/`)];\n}\n\n// Header line of the managed .prettierignore block — also its marker (re-applied\n// and re-rendered against this exact string). The \"(owned dirs)\" suffix marks the\n// post-EYRK34 format; the stable prefix is what stale-config-scan detects.\nconst PRETTIER_EXCLUSIONS_HEADER = '# Safeword - managed prettier exclusions (owned dirs)';\n\n// Header line of the managed .gitattributes block — also its marker (re-applied and\n// re-rendered against this exact string). See GitHub #566 / ticket GA7T6M.\nconst GITATTRIBUTES_HEADER = '# Safeword - managed merge strategy for generated artifacts';\n\n/**\n * The managed `.gitattributes` block (issue #566): safeword's committed but\n * deterministically-regenerated artifacts — the architecture docs and the ticket index —\n * get `merge=union` so a local `git merge`/`rebase`/`pull` of the default branch\n * auto-resolves them instead of conflicting on the `fingerprint:` line + reconcile/stale\n * markers. `union` is a BUILT-IN driver (attribute-only, no `git config`), so it works on\n * any clone/CI from the committed file; the heal + `architecture --check` pipeline then\n * reconciles the union result to the correct content. `linguist-generated=true` collapses\n * their diffs and marks them generated on GitHub. Resolved per-ctx so a custom\n * `paths.projectRoot` ticket index is covered; the architecture-doc glob is root-agnostic.\n */\nfunction managedGitattributes(ctx: ProjectContext): string {\n const root = resolvedNamespaceRootLabel(ctx);\n return [\n GITATTRIBUTES_HEADER,\n '**/architecture.generated.md merge=union linguist-generated=true',\n `${root}/tickets/INDEX.md merge=union linguist-generated=true`,\n `${root}/tickets/INDEX-completed.md merge=union linguist-generated=true`,\n ].join('\\n');\n}\n\n/**\n * The starter BDD lane's full surface — files (the bddLaneFile entries\n * below), deps (typescriptPackages.conditional.scaffoldBddLane), and the\n * test:bdd script. The `safeword doctor` leftover-scaffold advisory\n * enumerates from these constants so its list can never drift from the\n * schema (ticket 56JCFZ, TB3.AC2).\n */\nexport const BDD_LANE_FILE_PATHS = [\n 'cucumber.mjs',\n 'features/safeword-lane.feature',\n 'steps/world.ts',\n 'steps/shared.steps.ts',\n] as const;\n\nexport const BDD_LANE_SCRIPT = 'test:bdd';\n\n/**\n * Starter-lane template entry, suppressed when the repo has its own cucumber\n * harness (ticket 56JCFZ, issue #645): the generator returns undefined so\n * reconcile skips the file entirely instead of scaffolding a competing lane.\n * Behaves exactly like `{ template }` when no harness is detected.\n */\nfunction bddLaneFile(templatePath: string): FileDefinition {\n return {\n // `template` declares provenance for the schema↔templates contract;\n // the generator (which takes precedence) gates on harness detection.\n template: templatePath,\n generator: (ctx: ProjectContext): string | undefined =>\n ctx.projectType.scaffoldBddLane\n ? readFile(nodePath.join(getTemplatesDirectory(), templatePath))\n : undefined,\n };\n}\n\nfunction prReviewEnabled(cwd: string): boolean {\n const content = readFileSafe(nodePath.join(cwd, '.safeword', 'config.json'));\n if (content === undefined) return false;\n\n try {\n const config = JSON.parse(content) as { prReview?: { enabled?: unknown } };\n return config.prReview?.enabled === true;\n } catch {\n return false;\n }\n}\n\nfunction normalizePrReviewWorkflowVersionPins(content: string): string {\n const commandPrefix = 'npx --yes safeword@';\n const segments = content.split(commandPrefix);\n return segments\n .map((segment, index) => {\n if (index === 0) return segment;\n const end = segment.indexOf(' ');\n if (end === -1) return segment;\n const version = segment.slice(0, end);\n const coreIdentifiers = version.split('-', 1)[0]?.split('.') ?? [];\n const isSemver =\n coreIdentifiers.length === 3 &&\n coreIdentifiers.every(identifier => {\n const numeric = Number(identifier);\n return Number.isSafeInteger(numeric) && numeric >= 0 && String(numeric) === identifier;\n });\n return isSemver ? `__SAFEWORD_VERSION__${segment.slice(end)}` : segment;\n })\n .join(commandPrefix);\n}\n\nfunction prReviewWorkflowFile(templatePath: string): ManagedFileDefinition {\n const workflowContent = (): string =>\n readFile(nodePath.join(getTemplatesDirectory(), templatePath))\n .split('__SAFEWORD_VERSION__')\n .join(VERSION);\n\n return {\n template: templatePath,\n generator: (ctx: ProjectContext): string | undefined =>\n prReviewEnabled(ctx.cwd) ? workflowContent() : undefined,\n normalizeForUnmodifiedComparison: normalizePrReviewWorkflowVersionPins,\n removeIfUnmodified: workflowContent,\n removeWhenGeneratorOmitted: true,\n };\n}\n\n// Filing invariants shared word-for-word by the retro and self-report-filing\n// guides (#801). Both carry guide-specific nuance around them, so the guides\n// can't be collapsed into one — instead the shared bullets are contract-pinned\n// in both files below. Single-line bullets on purpose: contracts match exact\n// substrings, so a rewrap would break the check.\nconst SHARED_FILING_INVARIANTS = [\n '- **Autonomous** — no human approval; sanitization + dedup + caps are the safeguards, not a human gate.',\n \"- **Upstream only** — `ArcadeAI/safeword`, never the host project's tracker.\",\n '- **Code owns egress** — nothing leaves beyond what the sanitized output contains.',\n];\n\n// One session-id → safe-token rule (FG6V57): triage (public ledger JSON), the\n// retro draft spool (filename), and self-report (local records) each reduce an\n// attacker-influenceable session id to a bare bounded token. The spool module is\n// deliberately self-contained (node:* only), so the rule is pinned byte-identical\n// across the three files instead of shared via import — edit them together.\n// (Keep this string minimal: an equivalent-but-reformatted regex fails the pin.)\nconst SESSION_TOKEN_RULE = [String.raw`.replaceAll(/[^\\w.-]/g, '_').slice(0, 80) || 'unknown'`];\n\n/** Marker substring identifying a boundary-gate shim line (ZJMZ50). */\nconst BOUNDARY_SHIM_MARKER = '# Safeword boundary gate';\n\n/**\n * The armored boundary-gate invocation, shared by every hook manager so the\n * safety semantics can never drift: the `[ -x … ]` guard keeps a fresh clone\n * (no node_modules) silent, and `|| true` keeps a crashing gate from blocking\n * (warn-only contract, TB1.R4). Husky appends it via the textPatch below;\n * the lefthook/pre-commit snippets interpolate it in hook-nudge.ts.\n */\nexport function boundaryShimCommand(at: 'commit' | 'push'): string {\n return `[ -x node_modules/.bin/safeword ] && node_modules/.bin/safeword boundary --at ${at} || true`;\n}\n\n/**\n * One-line boundary-gate shim for a husky hook file (see the textPatches\n * entry comment for the full design rationale). The marker is a trailing sh\n * comment on the command line itself, so the block IS the marker line.\n */\nfunction boundaryShimPatch(at: 'commit' | 'push'): TextPatchDefinition {\n return {\n operation: 'append',\n content: `${boundaryShimCommand(at)} ${BOUNDARY_SHIM_MARKER}: warn-only; removed by \\`safeword uninstall --agents=none\\`\\n`,\n marker: BOUNDARY_SHIM_MARKER,\n rerender: true,\n // A hook file that setup alone created holds nothing but the shim after\n // unpatch — delete it rather than leave an empty husk (TB1.R5).\n removeFileIfContentEquals: ['', '\\n'],\n when: ctx => ctx.hookManager === 'husky',\n };\n}\n\n/** The canonical schema is plugin-only for Codex. */\nexport const SAFEWORD_SCHEMA: SafewordSchema = {\n version: VERSION,\n codexMigration: CODEX_MIGRATION_SCHEMA,\n\n // Directories fully owned by safeword (created on setup, deleted on reset)\n ownedDirs: [\n '.safeword',\n '.safeword/hooks',\n '.safeword/hooks/cursor',\n '.safeword/hooks/lib',\n '.safeword/guides',\n '.safeword/templates',\n '.safeword/prompts',\n '.safeword/scripts',\n '.safeword/statusline',\n ...CURSOR_SHARED_SKILL_DIRS,\n '.cursor',\n '.cursor/rules',\n '.cursor/commands',\n '.cursor/agents',\n ],\n\n // Directories we add to but don't own (not deleted on reset)\n sharedDirs: [\n '.claude',\n '.claude/skills',\n '.claude/commands',\n // Custom-agent homes (GH628F): users keep their own agents in this dir —\n // add-to, never own. Codex is plugin-only and receives no project scaffold.\n '.claude/agents',\n ],\n\n // Created on setup but NOT deleted on reset (preserves user data)\n preservedDirs: [\n '.safeword-project/learnings',\n '.safeword/logs',\n // Runtime cloud-filing spool (BNGK9W) — per-session drafts + nudge markers the\n // retro writes at runtime; user/runtime data the schema does not own.\n '.safeword/retro-drafts',\n // Runtime self-report capture (already in SAFEWORD_TRANSIENT_PATHS /\n // gitignore) — per-session JSONL the hooks write; without this entry the\n // schema-drift test fails for any session that recorded a signal.\n '.safeword/self-reports',\n // Authored collisions retained during automatic .safeword-project → .project\n // migration. Recovery copies are user data, not deployed framework assets.\n '.safeword/namespace-migration-conflicts-v1',\n '.safeword-project/tickets',\n '.safeword-project/tickets/completed',\n '.safeword-project/tmp',\n ],\n\n // Files to delete on upgrade (renamed or removed in newer versions)\n deprecatedFiles: [\n '.safeword/templates/user-stories-template.md',\n // Consolidated into planning-guide.md and testing-guide.md (v0.8.0)\n '.safeword/guides/development-workflow.md',\n '.safeword/guides/tdd-best-practices.md',\n '.safeword/guides/user-story-guide.md',\n '.safeword/guides/test-definitions-guide.md',\n // Boundaries config now project-specific (v0.9.0)\n '.safeword/eslint-boundaries.config.mjs',\n // Shell hooks replaced with TypeScript/Bun (v0.13.0)\n '.safeword/hooks/session-verify-agents.sh',\n // Replaced by session-safeword-context.ts (P30CRP): safeword no longer edits AGENTS.md.\n '.safeword/hooks/session-verify-agents.ts',\n '.safeword/hooks/session-version.sh',\n '.safeword/hooks/session-lint-check.sh',\n '.safeword/hooks/prompt-timestamp.sh',\n '.safeword/hooks/prompt-questions.sh',\n '.safeword/hooks/post-tool-lint.sh',\n '.safeword/hooks/stop-quality.sh',\n '.safeword/hooks/cursor/after-file-edit.sh',\n '.safeword/hooks/cursor/stop.sh',\n // Shell libraries no longer needed with Bun\n '.safeword/lib/common.sh',\n '.safeword/lib/jq-fallback.sh',\n // Skill renamed from enforcing-tdd to tdd-enforcing (v0.16.0)\n '.claude/skills/safeword-enforcing-tdd/SKILL.md',\n '.cursor/rules/safeword-enforcing-tdd.mdc',\n // TDD skill and command removed - BDD skill includes full TDD in the implement phase (v0.16.0)\n '.claude/skills/safeword-tdd-enforcing/SKILL.md',\n '.cursor/rules/safeword-tdd-enforcing.mdc',\n '.claude/commands/tdd.md',\n '.cursor/commands/tdd.md',\n // BDD skill split into phase files (v0.16.0)\n '.cursor/rules/safeword-bdd-orchestrating.mdc',\n '.safeword/commands/tdd.md',\n // Brainstorming skill: old safeword-* skill removed (v0.16.0); cursor rule was\n // re-introduced under same name (PR #103) for the new short-name brainstorm skill,\n // so .cursor/rules/safeword-brainstorming.mdc is no longer deprecated.\n '.claude/skills/safeword-brainstorming/SKILL.md',\n // Writing-plans skill removed - redundant with BDD decomposition + Claude Code native plan mode (v0.16.0)\n '.claude/skills/safeword-writing-plans/SKILL.md',\n '.cursor/rules/safeword-writing-plans.mdc',\n // Skills renamed from safeword-* to short names, overlapping commands removed (v0.17.0)\n '.claude/skills/safeword-debugging/SKILL.md',\n '.claude/skills/safeword-quality-reviewing/SKILL.md',\n '.claude/skills/safeword-refactoring/SKILL.md',\n '.claude/skills/safeword-bdd-orchestrating/SKILL.md',\n '.claude/skills/safeword-bdd-orchestrating/DISCOVERY.md',\n '.claude/skills/safeword-bdd-orchestrating/SCENARIOS.md',\n '.claude/skills/safeword-bdd-orchestrating/DECOMPOSITION.md',\n '.claude/skills/safeword-bdd-orchestrating/TDD.md',\n '.claude/skills/safeword-bdd-orchestrating/DONE.md',\n '.claude/skills/safeword-bdd-orchestrating/SPLITTING.md',\n // Command for debug was never a standalone command before v0.17.0 (always a skill)\n // /done renamed to /verify (v0.20.0)\n '.claude/commands/done.md',\n '.cursor/commands/done.md',\n // Shim commands removed — skills auto-create /slash-commands (v0.22.0)\n '.claude/commands/bdd.md',\n '.claude/commands/debug.md',\n '.claude/commands/quality-review.md',\n '.claude/commands/refactor.md',\n '.claude/commands/testing.md',\n // CLI reference inlined into SAFEWORD.md (v0.28.0, #112h)\n '.safeword/guides/cli-reference.md',\n // Commands converted to skills (ticket 038)\n '.claude/commands/lint.md',\n '.claude/commands/verify.md',\n '.claude/commands/audit.md',\n '.claude/commands/cleanup-zombies.md',\n '.safeword/.gherkin-lintrc',\n // Merged into session-auto-upgrade.ts — check + apply now run in one pass (XQ9CXA)\n '.safeword/hooks/session-update-check.ts',\n // Legacy Codex assets are intentionally absent. Generic maintenance must\n // preserve them until explicit, proof-gated migration finalization.\n ],\n\n // Packages to uninstall on upgrade (now bundled in safeword/eslint or replaced)\n deprecatedPackages: [\n // Individual ESLint plugins now bundled in safeword/eslint\n '@eslint/js',\n 'eslint-plugin-import-x',\n 'eslint-import-resolver-typescript',\n 'eslint-plugin-sonarjs',\n 'eslint-plugin-unicorn',\n 'eslint-plugin-boundaries', // replaced by dependency-cruiser\n 'eslint-plugin-playwright',\n 'eslint-plugin-promise',\n 'eslint-plugin-regexp',\n 'eslint-plugin-jsdoc',\n 'eslint-plugin-simple-import-sort',\n 'eslint-plugin-security',\n // Conditional ESLint plugins now in safeword\n 'typescript-eslint',\n 'eslint-plugin-react',\n 'eslint-plugin-react-hooks',\n 'eslint-plugin-jsx-a11y',\n '@next/eslint-plugin-next',\n 'eslint-plugin-astro',\n 'gherkin-lint',\n ],\n\n // Directories to delete on upgrade (no longer managed by safeword)\n deprecatedDirs: [\n '.safeword/lib', // Shell libraries no longer needed with Bun (v0.13.0)\n '.safeword/planning', // Moved to .safeword-project/tickets/ (v0.16.0)\n '.safeword/tickets', // Moved to .safeword-project/tickets/ (v0.16.0)\n '.claude/skills/safeword-enforcing-tdd', // Renamed to safeword-tdd-enforcing (v0.16.0)\n '.claude/skills/safeword-tdd-enforcing', // Removed - BDD includes TDD (v0.16.0)\n '.claude/skills/safeword-brainstorming', // Removed - BDD discovery phase covers this (v0.16.0)\n '.claude/skills/safeword-writing-plans', // Removed - redundant with BDD + native plan mode (v0.16.0)\n // Skills renamed from safeword-* to short names (v0.17.0)\n '.claude/skills/safeword-debugging',\n '.claude/skills/safeword-quality-reviewing',\n '.claude/skills/safeword-refactoring',\n '.claude/skills/safeword-bdd-orchestrating',\n // Legacy Codex skill directories remain until explicit migration finalization.\n ],\n\n // Files owned by safeword (overwritten on upgrade if content changed)\n // (bddLaneFile entries: see the helper defined above the schema)\n ownedFiles: {\n // Project root config files (for audit/quality tools)\n '.jscpd.json': { template: '.jscpd.json' },\n // BDD acceptance lane config (ticket 102b) — safeword-owned; the lane's\n // working files (features/, steps/) are customer-owned in managedFiles.\n // Suppressed when the repo has its own cucumber harness (56JCFZ).\n 'cucumber.mjs': bddLaneFile('cucumber/cucumber.mjs'),\n // Note: knip.json is in typescriptManagedFiles (with context-aware ignoreDependencies)\n\n // Core files\n '.safeword/AGENTS.md': { template: 'AGENTS.md' },\n '.safeword/SAFEWORD.md': { template: 'SAFEWORD.md' },\n '.safeword/version': { content: () => VERSION },\n // config.json is created by packs system but needs to be registered for cleanup on uninstall\n // Generator returns undefined = never created/updated by schema, but still deleted on uninstall\n '.safeword/config.json': { generator: (): undefined => undefined },\n\n // Language-specific safeword configs for hooks (extend project configs if they exist)\n ...typescriptOwnedFiles,\n ...pythonOwnedFiles,\n ...golangOwnedFiles,\n ...rustOwnedFiles,\n ...sqlOwnedFiles,\n\n // Hooks - Bash (no Bun dependency, must run before Bun hooks)\n '.safeword/hooks/session-bun-check.sh': {\n template: 'hooks/session-bun-check.sh',\n },\n '.safeword/hooks/lib/audit-scope.sh': {\n template: 'hooks/lib/audit-scope.sh',\n },\n '.safeword/hooks/resolve-namespace-root.ts': {\n template: 'hooks/resolve-namespace-root.ts',\n },\n '.safeword/hooks/resolve-verify-ticket.ts': {\n template: 'hooks/resolve-verify-ticket.ts',\n },\n '.safeword/hooks/resolve-project-knowledge.ts': {\n template: 'hooks/resolve-project-knowledge.ts',\n },\n '.safeword/hooks/audit-principle-trace.ts': {\n template: 'hooks/audit-principle-trace.ts',\n },\n '.safeword/hooks/record-skill-invocation.ts': {\n template: 'hooks/record-skill-invocation.ts',\n },\n '.safeword/hooks/run-review.ts': {\n template: 'hooks/run-review.ts',\n },\n\n // Hooks shared library - TypeScript with Bun runtime\n '.safeword/hooks/lib/active-ticket.ts': { template: 'hooks/lib/active-ticket.ts' },\n '.safeword/hooks/lib/feature-provenance.ts': { template: 'hooks/lib/feature-provenance.ts' },\n '.safeword/hooks/lib/inspiration.ts': { template: 'hooks/lib/inspiration.ts' },\n '.safeword/hooks/lib/markdown-structure.ts': { template: 'hooks/lib/markdown-structure.ts' },\n '.safeword/hooks/lib/architecture-document-nudge.ts': {\n template: 'hooks/lib/architecture-document-nudge.ts',\n },\n '.safeword/hooks/lib/architecture-staged-scope.ts': {\n template: 'hooks/lib/architecture-staged-scope.ts',\n },\n '.safeword/hooks/lib/branch-staleness.ts': { template: 'hooks/lib/branch-staleness.ts' },\n '.safeword/hooks/lib/blocked-on-gate.ts': { template: 'hooks/lib/blocked-on-gate.ts' },\n '.safeword/hooks/lib/closeout-binding.ts': { template: 'hooks/lib/closeout-binding.ts' },\n '.safeword/hooks/lib/cursor-run-identity.ts': {\n template: 'hooks/lib/cursor-run-identity.ts',\n },\n '.safeword/hooks/lib/cursor-state.ts': {\n template: 'hooks/lib/cursor-state.ts',\n },\n '.safeword/hooks/lib/git-operation.ts': { template: 'hooks/lib/git-operation.ts' },\n '.safeword/hooks/lib/re-entry.ts': { template: 'hooks/lib/re-entry.ts' },\n '.safeword/hooks/lib/hierarchy.ts': { template: 'hooks/lib/hierarchy.ts' },\n '.safeword/hooks/lib/lint.ts': { template: 'hooks/lib/lint.ts' },\n '.safeword/hooks/lib/host-toolchain.ts': { template: 'hooks/lib/host-toolchain.ts' },\n '.safeword/hooks/lib/quality.ts': { template: 'hooks/lib/quality.ts' },\n '.safeword/hooks/lib/quality-state.ts': { template: 'hooks/lib/quality-state.ts' },\n '.safeword/hooks/lib/run-identity.ts': { template: 'hooks/lib/run-identity.ts' },\n '.safeword/hooks/lib/dependency-readiness.ts': {\n template: 'hooks/lib/dependency-readiness.ts',\n },\n '.safeword/hooks/lib/done-gate.ts': { template: 'hooks/lib/done-gate.ts' },\n '.safeword/hooks/lib/jsonl-spool.ts': { template: 'hooks/lib/jsonl-spool.ts' },\n '.safeword/hooks/lib/namespace-root.ts': { template: 'hooks/lib/namespace-root.ts' },\n '.safeword/hooks/lib/drain-retro-spool.ts': { template: 'hooks/lib/drain-retro-spool.ts' },\n '.safeword/hooks/lib/retro-draft-spool.ts': { template: 'hooks/lib/retro-draft-spool.ts' },\n '.safeword/hooks/lib/retro-debug.ts': { template: 'hooks/lib/retro-debug.ts' },\n '.safeword/hooks/lib/retro-extract.ts': { template: 'hooks/lib/retro-extract.ts' },\n '.safeword/hooks/lib/retro-filing-gate.ts': { template: 'hooks/lib/retro-filing-gate.ts' },\n '.safeword/hooks/lib/retro-nudge.ts': { template: 'hooks/lib/retro-nudge.ts' },\n '.safeword/hooks/lib/retro-trigger.ts': { template: 'hooks/lib/retro-trigger.ts' },\n '.safeword/hooks/lib/self-report.ts': { template: 'hooks/lib/self-report.ts' },\n '.safeword/hooks/lib/skill-invocation-log.ts': {\n template: 'hooks/lib/skill-invocation-log.ts',\n },\n '.safeword/hooks/lib/parse-annotation.ts': { template: 'hooks/lib/parse-annotation.ts' },\n '.safeword/hooks/lib/jtbd.ts': { template: 'hooks/lib/jtbd.ts' },\n '.safeword/hooks/lib/phase-provenance.ts': { template: 'hooks/lib/phase-provenance.ts' },\n '.safeword/hooks/lib/impl-plan.ts': { template: 'hooks/lib/impl-plan.ts' },\n '.safeword/hooks/lib/project-knowledge.ts': { template: 'hooks/lib/project-knowledge.ts' },\n '.safeword/hooks/lib/principle-trace.ts': { template: 'hooks/lib/principle-trace.ts' },\n '.safeword/hooks/lib/plan-gate.ts': { template: 'hooks/lib/plan-gate.ts' },\n '.safeword/hooks/lib/replan-relevance.ts': { template: 'hooks/lib/replan-relevance.ts' },\n '.safeword/hooks/lib/replan.ts': { template: 'hooks/lib/replan.ts' },\n '.safeword/hooks/lib/review-ledger.ts': { template: 'hooks/lib/review-ledger.ts' },\n '.safeword/hooks/lib/lint-config.ts': { template: 'hooks/lib/lint-config.ts' },\n '.safeword/hooks/lib/typecheck-gate.ts': { template: 'hooks/lib/typecheck-gate.ts' },\n '.safeword/hooks/lib/checkbox-transitions.ts': {\n template: 'hooks/lib/checkbox-transitions.ts',\n },\n '.safeword/hooks/lib/shell-segments.ts': { template: 'hooks/lib/shell-segments.ts' },\n '.safeword/hooks/lib/bash-ledger-writes.ts': {\n template: 'hooks/lib/bash-ledger-writes.ts',\n },\n '.safeword/hooks/lib/process-kill-guard.ts': {\n template: 'hooks/lib/process-kill-guard.ts',\n },\n '.safeword/hooks/lib/work-log-stamp.ts': {\n template: 'hooks/lib/work-log-stamp.ts',\n },\n '.safeword/hooks/lib/review-trigger.ts': { template: 'hooks/lib/review-trigger.ts' },\n '.safeword/hooks/lib/dogfood.ts': { template: 'hooks/lib/dogfood.ts' },\n '.safeword/hooks/lib/ledger-git.ts': { template: 'hooks/lib/ledger-git.ts' },\n '.safeword/hooks/lib/ledger-validation.ts': { template: 'hooks/lib/ledger-validation.ts' },\n '.safeword/hooks/lib/scenario-format.ts': { template: 'hooks/lib/scenario-format.ts' },\n '.safeword/hooks/lib/skill-nudge.ts': { template: 'hooks/lib/skill-nudge.ts' },\n '.safeword/hooks/lib/test-runner.ts': { template: 'hooks/lib/test-runner.ts' },\n '.safeword/hooks/lib/auto-upgrade.ts': { template: 'hooks/lib/auto-upgrade.ts' },\n '.safeword/hooks/lib/auto-upgrade-lock.ts': { template: 'hooks/lib/auto-upgrade-lock.ts' },\n '.safeword/hooks/lib/safeword-context.ts': { template: 'hooks/lib/safeword-context.ts' },\n '.safeword/hooks/lib/update-cache.ts': { template: 'hooks/lib/update-cache.ts' },\n '.safeword/hooks/lib/version.ts': { template: 'hooks/lib/version.ts' },\n '.safeword/hooks/lib/learning-verification-stamps.ts': {\n template: 'hooks/lib/learning-verification-stamps.ts',\n },\n '.safeword/hooks/lib/readiness-pointer.ts': { template: 'hooks/lib/readiness-pointer.ts' },\n\n // Generated at setup/upgrade from SAFEWORD_SCHEMA itself — the prefix list\n // the auto-upgrade hook uses to decide which files to stage. See owned-paths.ts.\n '.safeword/hooks/lib/owned-paths.ts': {\n generator: (ctx): string =>\n generateOwnedPathsModule(SAFEWORD_SCHEMA, resolvedNamespaceDirectory(ctx)),\n },\n\n // Hooks - TypeScript with Bun runtime\n '.safeword/hooks/session-safeword-context.ts': {\n template: 'hooks/session-safeword-context.ts',\n },\n '.safeword/hooks/session-reply-format.ts': {\n template: 'hooks/session-reply-format.ts',\n },\n '.safeword/hooks/session-codex-start.ts': {\n template: 'hooks/session-codex-start.ts',\n // Packaged by the CLI for native Codex dispatch, but no longer copied\n // into projects. Existing copies are legacy migration inputs.\n generator: (): undefined => undefined,\n },\n '.safeword/hooks/session-cursor-auto-upgrade.ts': {\n template: 'hooks/session-cursor-auto-upgrade.ts',\n },\n '.safeword/hooks/session-dependency-readiness.ts': {\n template: 'hooks/session-dependency-readiness.ts',\n },\n '.safeword/hooks/dependency-bootstrap.ts': {\n template: 'hooks/dependency-bootstrap.ts',\n },\n '.safeword/hooks/session-version.ts': {\n template: 'hooks/session-version.ts',\n },\n '.safeword/hooks/session-lint-check.ts': {\n template: 'hooks/session-lint-check.ts',\n },\n '.safeword/hooks/session-architecture-heal.ts': {\n template: 'hooks/session-architecture-heal.ts',\n },\n '.safeword/hooks/session-author-model.ts': {\n template: 'hooks/session-author-model.ts',\n },\n '.safeword/hooks/session-compact-context.ts': {\n template: 'hooks/session-compact-context.ts',\n },\n '.safeword/hooks/prompt-timestamp.ts': {\n template: 'hooks/prompt-timestamp.ts',\n },\n '.safeword/hooks/prompt-questions.ts': {\n template: 'hooks/prompt-questions.ts',\n },\n '.safeword/hooks/prompt-retro-nudge.ts': {\n template: 'hooks/prompt-retro-nudge.ts',\n },\n '.safeword/hooks/post-tool-lint.ts': {\n template: 'hooks/post-tool-lint.ts',\n },\n '.safeword/hooks/post-tool-quality.ts': {\n template: 'hooks/post-tool-quality.ts',\n },\n '.safeword/hooks/post-tool-skill-nudge.ts': {\n template: 'hooks/post-tool-skill-nudge.ts',\n },\n '.safeword/hooks/post-tool-bypass-warn.ts': {\n template: 'hooks/post-tool-bypass-warn.ts',\n },\n '.safeword/hooks/pre-tool-quality.ts': {\n template: 'hooks/pre-tool-quality.ts',\n },\n '.safeword/hooks/pre-tool-architecture-stage.ts': {\n template: 'hooks/pre-tool-architecture-stage.ts',\n },\n '.safeword/hooks/pre-tool-stale-main.ts': {\n template: 'hooks/pre-tool-stale-main.ts',\n },\n '.safeword/hooks/write-review-stamp.ts': {\n template: 'hooks/write-review-stamp.ts',\n },\n '.safeword/hooks/pre-tool-config-guard.ts': {\n template: 'hooks/pre-tool-config-guard.ts',\n },\n '.safeword/hooks/pre-tool-dependency-readiness.ts': {\n template: 'hooks/pre-tool-dependency-readiness.ts',\n },\n '.safeword/hooks/post-tool-dependency-readiness.ts': {\n template: 'hooks/post-tool-dependency-readiness.ts',\n },\n '.safeword/hooks/pre-tool-git-bare-fix.sh': {\n template: 'hooks/pre-tool-git-bare-fix.sh',\n },\n '.safeword/hooks/session-auto-upgrade.ts': {\n template: 'hooks/session-auto-upgrade.ts',\n },\n '.safeword/hooks/session-cleanup-quality.ts': {\n template: 'hooks/session-cleanup-quality.ts',\n },\n '.safeword/hooks/stop-quality.ts': { template: 'hooks/stop-quality.ts' },\n '.safeword/hooks/stop-reentry.ts': { template: 'hooks/stop-reentry.ts' },\n '.safeword/hooks/stop-retro-filing.ts': { template: 'hooks/stop-retro-filing.ts' },\n '.safeword/hooks/stop-retro.ts': { template: 'hooks/stop-retro.ts' },\n '.safeword/hooks/stop-self-report.ts': { template: 'hooks/stop-self-report.ts' },\n '.safeword/hooks/session-start-reentry.ts': {\n template: 'hooks/session-start-reentry.ts',\n },\n '.safeword/statusline/reentry.ts': {\n template: 'statusline/reentry.ts',\n },\n '.safeword/hooks/post-tool-sync-learnings.ts': {\n template: 'hooks/post-tool-sync-learnings.ts',\n },\n '.safeword/hooks/post-tool-work-log.ts': {\n template: 'hooks/post-tool-work-log.ts',\n },\n\n // Retro filer subagent (GH628F, issue #628): the filing procedure lives in\n // the agent definition, dispatched by the per-harness stop gates. One\n // markdown source serves Claude and Cursor; Codex takes TOML. OWNED (not\n // managed): overwritten on upgrade and removed on reset — a leftover copy\n // would keep `.cursor/` alive after reset.\n '.claude/agents/safeword-retro-filer.md': { template: 'agents/safeword-retro-filer.md' },\n '.cursor/agents/safeword-retro-filer.md': { template: 'agents/safeword-retro-filer.md' },\n '.claude/agents/safeword-reviewer.md': { template: 'agents/safeword-reviewer.md' },\n '.cursor/agents/safeword-reviewer.md': { template: 'agents/safeword-reviewer.md' },\n\n // Guides\n '.safeword/guides/architecture-guide.md': {\n template: 'guides/architecture-guide.md',\n },\n '.safeword/guides/self-report-filing.md': {\n template: 'guides/self-report-filing.md',\n },\n '.safeword/guides/retro.md': {\n template: 'guides/retro.md',\n },\n '.safeword/guides/cold-start-check.md': {\n template: 'guides/cold-start-check.md',\n },\n '.safeword/guides/context-files-guide.md': {\n template: 'guides/context-files-guide.md',\n },\n '.safeword/guides/data-architecture-guide.md': {\n template: 'guides/data-architecture-guide.md',\n },\n '.safeword/guides/design-doc-guide.md': {\n template: 'guides/design-doc-guide.md',\n },\n '.safeword/guides/learning-extraction.md': {\n template: 'guides/learning-extraction.md',\n },\n '.safeword/guides/llm-writing-guide.md': {\n template: 'guides/llm-writing-guide.md',\n },\n '.safeword/guides/llm-evals-guide.md': {\n template: 'guides/llm-evals-guide.md',\n },\n '.safeword/guides/planning-guide.md': {\n template: 'guides/planning-guide.md',\n },\n '.safeword/guides/skill-eval-optimization-guide.md': {\n template: 'guides/skill-eval-optimization-guide.md',\n },\n '.safeword/guides/testing-guide.md': {\n template: 'guides/testing-guide.md',\n },\n '.safeword/guides/verification-lanes-guide.md': {\n template: 'guides/verification-lanes-guide.md',\n },\n '.safeword/guides/zombie-process-cleanup.md': {\n template: 'guides/zombie-process-cleanup.md',\n },\n\n // Templates\n '.safeword/templates/architecture-template.md': {\n template: 'doc-templates/architecture-template.md',\n },\n '.safeword/templates/design-doc-template.md': {\n template: 'doc-templates/design-doc-template.md',\n },\n '.safeword/templates/task-spec-template.md': {\n template: 'doc-templates/task-spec-template.md',\n },\n '.safeword/templates/test-definitions-feature.md': {\n template: 'doc-templates/test-definitions-feature.md',\n },\n '.safeword/templates/ticket-template.md': {\n template: 'doc-templates/ticket-template.md',\n },\n '.safeword/templates/feature-spec-template.md': {\n template: 'doc-templates/feature-spec-template.md',\n },\n // Per-ticket impl-plan.md scaffold (ticket XDNSZA) — authored at\n // the plan-implementation phase, validated by the stop hook's impl-plan gate.\n '.safeword/templates/impl-plan-template.md': {\n template: 'doc-templates/impl-plan-template.md',\n },\n '.safeword/templates/adr-template.md': {\n template: 'doc-templates/adr-template.md',\n },\n '.safeword/templates/work-log-template.md': {\n template: 'doc-templates/work-log-template.md',\n },\n // Upstream-workaround tripwire scaffold (issue #1907) — header runbook +\n // pinned-version test, emitted when a workaround's removal depends on\n // someone else's release. See guides/testing-guide.md.\n '.safeword/templates/tripwire-template.md': {\n template: 'doc-templates/tripwire-template.md',\n },\n // Per-ticket spec.md scaffold (ticket Y2HCNJ). ticket-writer reads this\n // from the bundled templates dir when scaffolding a feature's spec.md;\n // deployed here so it joins the other artifact templates and stays in the\n // schema's ownedFiles manifest.\n '.safeword/templates/spec-template.md': {\n template: 'spec-template.md',\n },\n\n // Prompts\n '.safeword/prompts/architecture.md': {\n template: 'prompts/architecture.md',\n },\n\n // Scripts\n '.safeword/scripts/bisect-test-pollution.sh': {\n template: 'scripts/bisect-test-pollution.sh',\n },\n '.safeword/scripts/bisect-zombie-processes.sh': {\n template: 'scripts/bisect-zombie-processes.sh',\n },\n '.safeword/scripts/cleanup-zombies.sh': {\n template: 'scripts/cleanup-zombies.sh',\n },\n '.safeword/scripts/closeout-cleanup.ts': {\n template: 'scripts/closeout-cleanup.ts',\n },\n\n // Host-neutral skill materialization retained for Cursor's thin wrappers.\n // Claude loads the same canonical sources from its native plugin cache.\n ...CURSOR_SHARED_SKILL_OWNED_FILES,\n\n // Claude skills (short names, auto-trigger + explicit invocation)\n '.claude/skills/debug/SKILL.md': {\n template: 'skills/debug/SKILL.md',\n },\n '.claude/skills/quality-review/SKILL.md': {\n template: 'skills/quality-review/SKILL.md',\n },\n '.claude/skills/finish-review/SKILL.md': {\n template: 'skills/finish-review/SKILL.md',\n },\n '.claude/skills/finish-review/REVIEWER.md': {\n template: 'skills/finish-review/REVIEWER.md',\n },\n '.claude/skills/refactor/SKILL.md': {\n template: 'skills/refactor/SKILL.md',\n },\n '.claude/skills/testing/SKILL.md': {\n template: 'skills/testing/SKILL.md',\n },\n '.claude/skills/bdd/SKILL.md': {\n template: 'skills/bdd/SKILL.md',\n },\n '.claude/skills/bdd/DISCOVERY.md': {\n template: 'skills/bdd/DISCOVERY.md',\n },\n '.claude/skills/bdd/PLAN_IMPLEMENTATION.md': {\n template: 'skills/bdd/PLAN_IMPLEMENTATION.md',\n },\n '.claude/skills/bdd/SCENARIOS.md': {\n template: 'skills/bdd/SCENARIOS.md',\n },\n '.claude/skills/bdd/TDD.md': {\n template: 'skills/bdd/TDD.md',\n },\n '.claude/skills/bdd/DONE.md': {\n template: 'skills/bdd/DONE.md',\n },\n '.claude/skills/bdd/SPLITTING.md': {\n template: 'skills/bdd/SPLITTING.md',\n },\n '.claude/skills/bdd/VERIFY.md': {\n template: 'skills/bdd/VERIFY.md',\n },\n '.claude/skills/ticket-system/SKILL.md': {\n template: 'skills/ticket-system/SKILL.md',\n },\n // Claude skills — action commands with disable-model-invocation\n // Skills auto-create /slash-commands, so separate commands are unnecessary\n '.claude/skills/lint/SKILL.md': { template: 'skills/lint/SKILL.md' },\n '.claude/skills/verify/SKILL.md': { template: 'skills/verify/SKILL.md' },\n '.claude/skills/closeout/SKILL.md': { template: 'skills/closeout/SKILL.md' },\n '.claude/skills/audit/SKILL.md': { template: 'skills/audit/SKILL.md' },\n '.claude/skills/explain/SKILL.md': { template: 'skills/explain/SKILL.md' },\n '.claude/skills/self-review/SKILL.md': { template: 'skills/self-review/SKILL.md' },\n '.claude/skills/review-spec/SKILL.md': {\n template: 'skills/review-spec/SKILL.md',\n },\n '.claude/skills/cleanup-zombies/SKILL.md': {\n template: 'skills/cleanup-zombies/SKILL.md',\n },\n '.claude/skills/retro/SKILL.md': { template: 'skills/retro/SKILL.md' },\n '.claude/skills/spike/SKILL.md': { template: 'skills/spike/SKILL.md' },\n '.claude/skills/retro-filer/SKILL.md': {\n template: 'skills/retro-filer/SKILL.md',\n },\n // Claude skills — contextual (auto-triggered, no slash command)\n '.claude/skills/brainstorm/SKILL.md': {\n template: 'skills/brainstorm/SKILL.md',\n },\n '.claude/skills/elicit/SKILL.md': {\n template: 'skills/elicit/SKILL.md',\n },\n '.claude/skills/tdd-review/SKILL.md': {\n template: 'skills/tdd-review/SKILL.md',\n },\n '.claude/skills/figure-it-out/SKILL.md': {\n template: 'skills/figure-it-out/SKILL.md',\n },\n\n // Cursor rules — generated from wrapper metadata; physical files stay installed.\n ...CURSOR_RULE_WRAPPER_OWNED_FILES,\n\n // Cursor commands (Cursor needs explicit commands for all action capabilities)\n ...CURSOR_COMMAND_WRAPPER_OWNED_FILES,\n '.cursor/commands/explain.md': { template: 'commands/explain.md' },\n '.cursor/commands/verify.md': { template: 'commands/verify.md' },\n '.cursor/commands/self-review.md': { template: 'commands/self-review.md' },\n '.cursor/commands/review-spec.md': { template: 'commands/review-spec.md' },\n '.cursor/commands/cleanup-zombies.md': {\n template: 'commands/cleanup-zombies.md',\n },\n '.cursor/commands/lint.md': { template: 'commands/lint.md' },\n\n // Cursor hooks adapters - TypeScript with Bun runtime\n '.safeword/hooks/cursor/after-file-edit.ts': {\n template: 'hooks/cursor/after-file-edit.ts',\n },\n '.safeword/hooks/cursor/gate-adapter.ts': {\n template: 'hooks/cursor/gate-adapter.ts',\n },\n '.safeword/hooks/cursor/pre-tool-quality.ts': {\n template: 'hooks/cursor/pre-tool-quality.ts',\n },\n '.safeword/hooks/cursor/before-shell-execution.ts': {\n template: 'hooks/cursor/before-shell-execution.ts',\n },\n '.safeword/hooks/cursor/post-tool-quality.ts': {\n template: 'hooks/cursor/post-tool-quality.ts',\n },\n '.safeword/hooks/cursor/post-tool-skill-nudge.ts': {\n template: 'hooks/cursor/post-tool-skill-nudge.ts',\n },\n '.safeword/hooks/cursor/stop.ts': { template: 'hooks/cursor/stop.ts' },\n },\n\n // Files created if missing, updated only if content matches current template\n managedFiles: {\n // Package-owned Codex runtime adapters. Their generator intentionally\n // returns undefined: the plugin CLI executes them from the npm package,\n // never from a customer repository.\n ...CODEX_RUNTIME_ASSETS,\n\n // BDD acceptance lane working files (ticket 102b) — scaffolded once; the\n // customer owns them thereafter (created if missing, updated only while\n // still safeword's template content). The lane config (cucumber.mjs) is\n // safeword-owned in ownedFiles. All suppressed when the repo has its own\n // cucumber harness (56JCFZ).\n 'features/safeword-lane.feature': bddLaneFile('cucumber/safeword-lane.feature'),\n 'steps/world.ts': bddLaneFile('cucumber/world.ts'),\n 'steps/shared.steps.ts': bddLaneFile('cucumber/shared.steps.ts'),\n\n // Default-off advisory PR review. Customers may customize managed workflow\n // files after setup; reconciliation updates only unchanged template content.\n '.github/workflows/safeword-pr-review.yml': prReviewWorkflowFile('workflows/pr-review.yml'),\n '.github/workflows/safeword-pr-review-publisher.yml': prReviewWorkflowFile(\n 'workflows/pr-review-publisher.yml',\n ),\n '.github/workflows/safeword-pr-review-worker.yml': prReviewWorkflowFile(\n 'workflows/pr-review-worker.yml',\n ),\n\n // TypeScript/JavaScript managed files (ESLint, tsconfig, Knip, Prettier configs)\n ...typescriptManagedFiles,\n // Python managed files (ruff.toml, mypy.ini, .importlinter)\n ...pythonManagedFiles,\n // Go managed files (.golangci.yml)\n ...golangManagedFiles,\n // Rust managed files (clippy.toml, rustfmt.toml, deny.toml)\n ...rustManagedFiles,\n // SQL managed files (.sqlfluff)\n ...sqlManagedFiles,\n\n // Project principles — scaffolded once; users author the small, durable set\n // that guides product and technical decisions. Like personas, a configured\n // paths.principles override suppresses the default scaffold uniformly.\n '.safeword-project/principles.md': {\n template: 'principles-template.md',\n configKey: 'principles',\n },\n\n // Project personas — scaffolded once with format header + commented example;\n // user authors real persona blocks thereafter (safeword reads, never overwrites\n // user content). See ticket 7YN5QB. `configKey: 'personas'` lets the user\n // redirect via `paths.personas` in .safeword/config.json — when set, reconcile\n // skips this entry uniformly (see ticket K7N2QM).\n '.safeword-project/personas.md': {\n template: 'personas-template.md',\n configKey: 'personas',\n },\n\n // Project glossary — scaffolded once with format header + commented example;\n // user authors real term blocks thereafter (safeword reads/validates, never\n // overwrites user content). See ticket YR6C49. `configKey: 'glossary'` lets\n // the user redirect via `paths.glossary` in .safeword/config.json — when set,\n // reconcile skips this entry uniformly (see ticket K7N2QM).\n '.safeword-project/glossary.md': {\n template: 'glossary-template.md',\n configKey: 'glossary',\n },\n\n // Project feature surfaces — scaffolded once with format header + commented\n // example; user authors real surface blocks thereafter. `configKey:\n // 'surfaces'` lets the user redirect via `paths.surfaces` in\n // .safeword/config.json, matching the personas/glossary contract.\n '.safeword-project/surfaces.md': {\n template: 'surfaces-template.md',\n configKey: 'surfaces',\n },\n\n // Per-root `.gitignore` for hook-written transient state. The legacy-prefixed\n // key is remapped to the resolved namespace root by withResolvedNamespaceRoot,\n // so a custom `paths.projectRoot` ignores its own transient files even though\n // the static repo-root block can't name that root (issue #272). Created once;\n // the repo-root block stays the belt-and-suspenders for `.project/`/legacy.\n '.safeword-project/.gitignore': {\n content: NAMESPACE_GITIGNORE_CONTENT,\n },\n },\n\n // JSON files where we merge specific keys\n jsonMerges: {\n // TypeScript/JavaScript JSON merges (package.json, .prettierrc, biome.json)\n ...typescriptJsonMerges,\n\n // Language-agnostic JSON merges\n '.claude/settings.json': {\n keys: ['hooks'],\n merge: existing => {\n // Preserve non-safeword hooks while adding/updating safeword hooks\n const existingHooks = (existing.hooks as Record<string, unknown[]>) ?? {};\n const mergedHooks: Record<string, unknown[]> = { ...existingHooks };\n\n for (const [event, newHooks] of Object.entries(SETTINGS_HOOKS)) {\n const eventHooks = mergedHooks[event] ?? [];\n const withoutCurrentHooks = filterOutEquivalentSafewordHooks(eventHooks, newHooks);\n const nonSafewordHooks = filterOutSafewordHooks(\n withoutCurrentHooks,\n acceptedHistoricalHookEntries(event),\n );\n mergedHooks[event] = [...nonSafewordHooks, ...newHooks];\n }\n\n return { ...existing, hooks: mergedHooks };\n },\n unmerge: existing => {\n // Remove only safeword hooks, preserve custom hooks\n const existingHooks = (existing.hooks as Record<string, unknown[]>) ?? {};\n const cleanedHooks: Record<string, unknown[]> = {};\n\n for (const [event, eventHooks] of Object.entries(existingHooks)) {\n const withoutCurrentHooks = filterOutEquivalentSafewordHooks(\n eventHooks,\n SETTINGS_HOOKS[event as keyof typeof SETTINGS_HOOKS] ?? [],\n );\n const nonSafewordHooks = filterOutSafewordHooks(\n withoutCurrentHooks,\n acceptedHistoricalHookEntries(event),\n );\n if (nonSafewordHooks.length > 0) {\n cleanedHooks[event] = nonSafewordHooks;\n }\n }\n\n const result = { ...existing };\n assignOrPrune(result, 'hooks', cleanedHooks);\n return result;\n },\n },\n\n '.mcp.json': MCP_JSON_MERGE,\n '.cursor/mcp.json': MCP_JSON_MERGE,\n\n // markdownlint-cli2 ignores - hide safeword's generated agent docs from a\n // consuming repo's markdown lint hooks (ticket #262). cli2's only JSON config\n // form is `.jsonc`; yaml/cjs/mjs variants fall back to manual wiring.\n '.markdownlint-cli2.jsonc': MARKDOWNLINT_CLI2_IGNORES_MERGE,\n\n '.cursor/hooks.json': {\n keys: [\n 'version',\n 'hooks.sessionStart',\n 'hooks.preToolUse',\n 'hooks.beforeShellExecution',\n 'hooks.afterFileEdit',\n 'hooks.postToolUse',\n 'hooks.stop',\n ],\n removeFileIfEmpty: true,\n merge: existing => {\n const existingHooks = (existing.hooks as Record<string, unknown[]>) ?? {};\n const hooks: Record<string, unknown[]> = { ...existingHooks };\n for (const [event, newHooks] of Object.entries(CURSOR_HOOKS)) {\n const eventHooks = hooks[event] ?? [];\n const nonSafewordHooks = filterOutEquivalentSafewordHooks(eventHooks, newHooks);\n hooks[event] = [...nonSafewordHooks, ...newHooks];\n }\n return {\n ...existing,\n version: 1, // Required by Cursor\n hooks,\n };\n },\n unmerge: existing => {\n const result = { ...existing };\n const existingHooks = (existing.hooks as Record<string, unknown[]>) ?? {};\n\n // Keep only hooks safeword did NOT install. Filtering entries instead of\n // whole events preserves user-authored Cursor hooks that share an event\n // with safeword, such as `sessionStart`.\n const hooks = Object.fromEntries(\n Object.entries(existingHooks)\n .map(\n ([name, eventHooks]) =>\n [\n name,\n filterOutEquivalentSafewordHooks(\n eventHooks,\n CURSOR_HOOKS[name as keyof typeof CURSOR_HOOKS] ?? [],\n ),\n ] as const,\n )\n .filter(([, eventHooks]) => eventHooks.length > 0),\n );\n\n // `version` is only meaningful while safeword's hooks remain; drop it\n // alongside an emptied hooks container.\n if (!assignOrPrune(result, 'hooks', hooks)) {\n delete result.version;\n }\n\n return result;\n },\n },\n },\n\n // Text files where we patch specific content\n textPatches: {\n // Boundary-gate shims for husky hosts (ZJMZ50, #810 child 2). One line,\n // all logic in the versioned CLI: explicit .bin path (husky's PATH\n // prepend is relative — worktree-unsafe, 9P3VVH), existence-guarded\n // (fresh clones), whole-line `|| true` (husky runs hooks with sh -e, so\n // an unguarded failure would BLOCK the commit — TB1.R4). The marker rides\n // the line as a trailing comment, which makes the whole block the marker\n // line: rerender then heals ANY future line change in place\n // (rerenderBlockLines excludes marker lines). Gated to the husky world —\n // lefthook/pre-commit/bare hosts get a printed nudge instead, and\n // `when` never gates unpatch, so reset still strips after a migration.\n '.husky/pre-commit': boundaryShimPatch('commit'),\n '.husky/pre-push': boundaryShimPatch('push'),\n '.gitignore': {\n operation: 'append',\n content: `\\n# Safeword - Local cache and transient state\\n${SAFEWORD_TRANSIENT_PATHS.join('\\n')}\\n`,\n // Marker is the NEWEST line (.safeword/state/reviews/, durable review\n // job state) so customers with any\n // older block re-apply on upgrade and pick up the latest transient paths.\n // This patch has no `rerender`, so moving the marker is the ONLY way an\n // existing install ever sees a newly added path — bump it whenever\n // SAFEWORD_TRANSIENT_PATHS grows. Hooks write state under the resolved\n // root, so fresh installs generate these under .project/. Without them,\n // those generated files show as untracked in `git status --porcelain` —\n // churning the tree and blocking the auto-upgrade gate.\n marker: '.safeword/state/reviews/',\n },\n // Prettier ignores: safeword owns the dot-directories in SAFEWORD_IGNORE_DIRS\n // (.safeword/, .claude/, .cursor/, .codex/, .agents/, and both namespace\n // roots). Without this, `prettier --write .` reformats hooks, Cursor/Codex\n // rules, and the generated ticket/learning markdown — churning the tree on\n // install (ticket EYRK34). Biome/eslint exclude these via their own configs.\n //\n // The marker carries an \"(owned dirs)\" suffix the pre-EYRK34 block lacks, so an\n // existing install re-applies on upgrade and picks up the broadened excludes\n // (.codex/ + wholesale namespace roots). The stable\n // \"# Safeword - managed prettier exclusions\" header substring is preserved so\n // stale-config-scan still detects the block.\n '.prettierignore': {\n operation: 'append',\n // ctx factory + rerender (issue #293): a custom paths.projectRoot is excluded,\n // and the block re-renders in place on upgrade for an existing custom-root\n // install. Default/legacy output is byte-identical, so those installs no-op.\n content: ctx => `\\n${PRETTIER_EXCLUSIONS_HEADER}\\n${managedPrettierPaths(ctx).join('\\n')}\\n`,\n rerender: true,\n marker: PRETTIER_EXCLUSIONS_HEADER,\n },\n '.gitattributes': {\n // ctx factory + rerender (issue #566), same shape as .prettierignore: a custom\n // paths.projectRoot resolves into the ticket-index paths, and the block re-renders\n // in place on upgrade. Default/legacy output is byte-identical, so those installs\n // no-op. Appended (marker-delimited) so a consumer's own .gitattributes is preserved.\n // No leading newline (unlike .prettierignore): prettier-plugin-sh DOES format\n // .gitattributes and rejects a leading blank line on a fresh install; existing\n // content separates via its own trailing newline.\n operation: 'append',\n content: ctx => `${managedGitattributes(ctx)}\\n`,\n rerender: true,\n marker: GITATTRIBUTES_HEADER,\n },\n },\n\n // Cleanup-only text patches. Safeword used to prepend these blocks to\n // customer-owned context files; P30CRP moved SAFEWORD.md delivery to\n // safeword-owned hooks.\n legacyTextPatches: {\n 'AGENTS.md': {\n operation: 'prepend',\n content: AGENTS_MD_LINK,\n marker: '.safeword/SAFEWORD.md',\n },\n 'CLAUDE.md': {\n operation: 'prepend',\n content: CLAUDE_MD_IMPORT_BLOCK,\n marker: '@./.safeword/SAFEWORD.md',\n },\n },\n\n // Content predicate parity — files that must contain specific strings.\n // Different from ownedFiles (which requires byte equality between two files):\n // contracts assert one-way \"this file must include these tokens\" invariants.\n // Used by runParity() in src/parity.ts for both release tests and pre-commit\n // (see ticket 144). Path key = file relative to repo root.\n contracts: {\n 'packages/cli/src/retro/triage.ts': {\n // Shared session-token rule (FG6V57) — see SESSION_TOKEN_RULE above.\n requires: SESSION_TOKEN_RULE,\n },\n 'packages/cli/templates/hooks/lib/retro-draft-spool.ts': {\n // Shared session-token rule (FG6V57); the .safeword mirror follows via pairs.\n requires: SESSION_TOKEN_RULE,\n },\n 'packages/cli/templates/hooks/lib/self-report.ts': {\n // Shared session-token rule (FG6V57); sanitizeToken stays for non-session fields.\n requires: SESSION_TOKEN_RULE,\n },\n 'packages/cli/templates/guides/self-report-filing.md': {\n // Shared filing invariants with retro.md (#801): the two guides carried\n // independently hand-tuned Rules blocks that silently forked. The exact\n // bullet text below must appear in BOTH guides — edit them together.\n requires: SHARED_FILING_INVARIANTS,\n },\n 'packages/cli/templates/guides/retro.md': {\n // See self-report-filing.md contract above (#801).\n requires: SHARED_FILING_INVARIANTS,\n },\n 'packages/cli/templates/hooks/lib/quality.ts': {\n // Cursor's stop hook imports QUALITY_REVIEW_MESSAGE. The grammar, renderer,\n // and evaluator exports keep proactive wording and Stop validation coupled;\n // requiring individual labels here would create a second grammar source.\n requires: [\n 'QUALITY_REVIEW_MESSAGE',\n // prompt-questions.ts imports all three pre-response pointers; the Stop\n // header composes the bare rule inline. Removing any one forks the\n // reply-shape vocabulary back across two hooks.\n 'REPLY_FORMAT_LEAD_RULE',\n 'REPLY_FORMAT_LEAD',\n 'REPLY_FORMAT_REMINDER',\n 'DECISION_BRIEF_GRAMMAR',\n 'GENERIC_REVIEW_EVIDENCE',\n 'renderDecisionBriefContract',\n 'renderDecisionBriefCorrection',\n 'evaluateDecisionBriefCompliance',\n 'getQualityEvidence',\n ],\n },\n 'packages/cli/templates/doc-templates/test-definitions-feature.md': {\n // Canonical test-definitions.md format. Rule grouping (Gherkin 6+\n // Rule: keyword, Example Mapping alignment) + nested Scenario with\n // Given/When/Then + per-scenario RED/GREEN/REFACTOR sub-checkboxes.\n // The R/G/R checkboxes are load-bearing: parseTddStep in\n // hooks/lib/active-ticket.ts depends on them to inject TDD-step\n // guidance during the implement phase. Removing any marker silently\n // regresses the format the BDD skill teaches.\n requires: [\n '## Rule:',\n '### Scenario:',\n 'Given',\n 'When',\n 'Then',\n '- [ ] RED',\n '- [ ] GREEN',\n '- [ ] REFACTOR',\n ],\n },\n 'packages/cli/templates/hooks/lib/scenario-format.ts': {\n // Runtime gate that powers done-phase scenario-completeness checks\n // (stop-quality.ts) and progress reporting. analyzeScenarioFormat is\n // imported by the stop hook; isUnrecognized distinguishes \"no\n // scenarios yet\" from \"scenarios in legacy/malformed format\" so the\n // done gate can hard-block the latter. Removing either silently\n // regresses scenario-completeness enforcement.\n requires: ['analyzeScenarioFormat', 'isUnrecognized', 'export function'],\n },\n },\n\n // NPM packages to install (JS/TS specific packages from typescript pack)\n packages: typescriptPackages,\n};\n\nexport type ProjectSurface = 'core' | 'cursor';\n\nconst CURSOR_PROJECT_PATHS = new Set([\n '.safeword/hooks/lib/cursor-run-identity.ts',\n '.safeword/hooks/lib/cursor-state.ts',\n '.safeword/hooks/session-cursor-auto-upgrade.ts',\n]);\n\nexport function isCursorProjectPath(path: string): boolean {\n return (\n path === '.cursor' ||\n path.startsWith('.cursor/') ||\n path === '.safeword/hooks/cursor' ||\n path.startsWith('.safeword/hooks/cursor/') ||\n CURSOR_PROJECT_PATHS.has(path)\n );\n}\n\nfunction withoutCursorEntries<T>(values: Record<string, T>): Record<string, T> {\n return Object.fromEntries(Object.entries(values).filter(([path]) => !isCursorProjectPath(path)));\n}\n\n/** Select project-owned surfaces without scattering Cursor path filters through commands. */\nexport function schemaForProjectSurfaces(\n schema: SafewordSchema,\n surfaces: readonly ProjectSurface[],\n): SafewordSchema {\n if (surfaces.includes('cursor')) return schema;\n return {\n ...schema,\n ownedDirs: schema.ownedDirs.filter(path => !isCursorProjectPath(path)),\n sharedDirs: schema.sharedDirs.filter(path => !isCursorProjectPath(path)),\n preservedDirs: schema.preservedDirs.filter(path => !isCursorProjectPath(path)),\n deprecatedFiles: schema.deprecatedFiles.filter(path => !isCursorProjectPath(path)),\n deprecatedDirs: schema.deprecatedDirs.filter(path => !isCursorProjectPath(path)),\n ownedFiles: withoutCursorEntries(schema.ownedFiles),\n managedFiles: withoutCursorEntries(schema.managedFiles),\n jsonMerges: withoutCursorEntries(schema.jsonMerges),\n textPatches: withoutCursorEntries(schema.textPatches),\n legacyTextPatches: withoutCursorEntries(schema.legacyTextPatches),\n contracts: withoutCursorEntries(schema.contracts),\n };\n}\n","/**\n * Go Language Pack - Schema Definitions\n *\n * All Go-specific file definitions and config generators.\n * Imported by schema.ts and spread into SAFEWORD_SCHEMA.\n *\n * Mirrors the structure of typescript/files.ts and python/files.ts for consistency.\n */\n\nimport { readFileSync } from 'node:fs';\nimport nodePath from 'node:path';\n\nimport YAML from 'yaml';\n\nimport { exists } from '../../utils/fs.js';\nimport { warn } from '../../utils/output.js';\nimport type { FileDefinition, ManagedFileDefinition } from '../types.js';\n\n// ============================================================================\n// Shared Configuration Constants\n// ============================================================================\n\n/**\n * Curated linter set — covers bugs, security, complexity, and modern Go\n * without the upgrade-breakage of `default: all`.\n *\n * Convention: `default: standard` + explicit `enable` list.\n * Used by golangci-lint itself, Docker, Prometheus, and the maratori golden config.\n */\nconst SAFEWORD_ENABLE = [\n // Bug detection\n 'bodyclose', // unclosed HTTP response bodies\n 'nilerr', // returning nil after checking err != nil\n 'sqlclosecheck', // unclosed sql.Rows/Stmt\n 'rowserrcheck', // unchecked sql.Rows.Err()\n 'noctx', // HTTP requests without context\n 'reassign', // reassigning top-level variables\n\n // Code quality\n 'cyclop', // cyclomatic complexity (max 10 default)\n 'nestif', // nested if depth\n 'gocognit', // cognitive complexity\n 'unconvert', // unnecessary type conversions\n 'unparam', // unused function parameters\n 'usestdlibvars', // use stdlib constants (http.StatusOK, etc.)\n 'wastedassign', // wasted variable assignments\n 'prealloc', // preallocate slice capacity\n\n // Security\n 'gosec', // security issues\n\n // Style (low noise)\n 'goconst', // repeated strings -> constants\n 'misspell', // spelling in comments/strings\n 'errorlint', // error wrapping conventions\n 'gocritic', // opinionated but high-signal\n 'revive', // flexible metalinter\n 'perfsprint', // faster string formatting\n 'copyloopvar', // loop variable capture\n 'intrange', // integer range loops\n];\n\n/**\n * Linters to disable (too strict for LLM enforcement).\n *\n * We intentionally do NOT list any `wsl`/`wsl_v5` whitespace linter here: it is\n * not part of `default: standard`, so disabling it is a no-op in the standalone\n * config, and naming the deprecated `wsl` would draw a `golangci-lint config\n * verify` deprecation notice. A customer who explicitly enables `wsl_v5` keeps\n * their choice in merge scenarios.\n */\nconst SAFEWORD_DISABLE = [\n 'forbidigo', // blocks all print statements\n];\n\n/** Exclusion presets for common false positives */\nconst SAFEWORD_EXCLUSION_PRESETS = ['std-error-handling', 'common-false-positives'];\n\n/** Safeword linter settings (only fills gaps — customer settings win) */\nconst SAFEWORD_SETTINGS: Record<string, Record<string, unknown>> = {\n nestif: { 'min-complexity': 4 },\n};\n\n// ============================================================================\n// Config Generators\n// ============================================================================\n\n/**\n * Build standalone golangci-lint v2 config object.\n *\n * We deliberately pin NO Go language version (no `run.go`): golangci-lint\n * derives the analysis target from the project's `go.mod` `go` directive, so a\n * pin here could only diverge from — and suppress analysis relative to — the\n * user's real Go version. Deriving from `go.mod` is correct and zero-maintenance.\n */\nfunction buildStandaloneConfig(): Record<string, unknown> {\n return {\n version: '2',\n linters: {\n default: 'standard',\n enable: [...SAFEWORD_ENABLE],\n disable: [...SAFEWORD_DISABLE],\n exclusions: { presets: [...SAFEWORD_EXCLUSION_PRESETS] },\n settings: structuredClone(SAFEWORD_SETTINGS),\n },\n formatters: { enable: ['gofumpt'] },\n };\n}\n\n/**\n * Generate golangci-lint v2 configuration for project root.\n * Created only when no existing config exists.\n */\nfunction generateGolangciConfig(): string {\n const header = `# Generated by safeword - DO NOT EDIT\n# To customize, add overrides below the formatters section\n\n`;\n return header + YAML.stringify(buildStandaloneConfig());\n}\n\n/**\n * Generate safeword golangci-lint configuration for .safeword/.golangci.yml.\n *\n * If project has existing config, merges additively (preserves customer choices).\n * Handles both v1 and v2 config formats.\n */\nfunction generateSafewordGolangciConfig(existingConfig: string | undefined, cwd: string): string {\n if (!existingConfig) {\n return getSafewordGolangciStandalone();\n }\n\n const configPath = nodePath.join(cwd, existingConfig);\n if (!exists(configPath)) {\n return getSafewordGolangciStandalone();\n }\n\n try {\n const projectContent = readFileSync(configPath, 'utf8');\n const projectConfig = YAML.parse(projectContent) as Record<string, unknown> | undefined;\n\n if (!projectConfig) {\n return getSafewordGolangciStandalone();\n }\n\n const merge =\n projectConfig.version === '2' ? getSafewordGolangciMergedV2 : getSafewordGolangciMergedV1;\n return merge(projectConfig);\n } catch {\n warn(`Safeword: Could not parse ${existingConfig}, using standalone config`);\n return getSafewordGolangciStandalone();\n }\n}\n\n/** Standalone safeword golangci-lint config (v2 format) */\nfunction getSafewordGolangciStandalone(): string {\n const header = `# Safeword golangci-lint config - standalone (no project config to merge)\n# Used by hooks for LLM enforcement.\n\n`;\n return header + YAML.stringify(buildStandaloneConfig());\n}\n\n// ============================================================================\n// Additive Merge Helpers\n// ============================================================================\n\n/** Additively merge the v2 linters section — preserves customer choices. */\nfunction mergeLinters(projectLinters: Record<string, unknown>): Record<string, unknown> {\n const customerExclusions = (projectLinters.exclusions as Record<string, unknown>) || {};\n const customerPresets = (customerExclusions.presets as string[]) || [];\n const customerSettings = (projectLinters.settings as Record<string, unknown>) || {};\n\n return {\n ...projectLinters,\n default: projectLinters.default || 'standard',\n enable: unionArrays((projectLinters.enable as string[]) || [], SAFEWORD_ENABLE),\n disable: unionArrays((projectLinters.disable as string[]) || [], SAFEWORD_DISABLE),\n exclusions: {\n ...customerExclusions,\n presets: unionArrays(customerPresets, SAFEWORD_EXCLUSION_PRESETS),\n },\n settings: fillGapMerge(customerSettings, SAFEWORD_SETTINGS),\n };\n}\n\n/** Additively merge formatters — append gofumpt if missing. */\nfunction mergeFormatters(projectFormatters: Record<string, unknown>): Record<string, unknown> {\n const enable = (projectFormatters.enable as string[]) || [];\n return {\n ...projectFormatters,\n enable: enable.includes('gofumpt') ? enable : [...enable, 'gofumpt'],\n };\n}\n\n// ============================================================================\n// Additive Merge (v2)\n// ============================================================================\n\n/** Merge project v2 config with safeword rules — additive, customer preserved. */\nfunction getSafewordGolangciMergedV2(projectConfig: Record<string, unknown>): string {\n const merged: Record<string, unknown> = {\n ...projectConfig,\n version: '2',\n linters: mergeLinters((projectConfig.linters as Record<string, unknown>) || {}),\n formatters: mergeFormatters((projectConfig.formatters as Record<string, unknown>) || {}),\n };\n\n const header = `# Safeword golangci-lint config - merged with project config\n# Used by hooks for LLM enforcement. Human pre-commits use project config.\n# Re-run \\`safeword install\\` to regenerate after project config changes.\n#\n# NOTE: Safeword adds linters via 'enable' without changing your 'default'.\n# Your disable list and exclusion presets are preserved (union, not replaced).\n\n`;\n\n return header + YAML.stringify(merged);\n}\n\n// ============================================================================\n// Additive Merge (v1 — legacy)\n// ============================================================================\n\n/** Merge project v1 config — additive, customer preserved. Outputs v1 format. */\nfunction getSafewordGolangciMergedV1(projectConfig: Record<string, unknown>): string {\n const merged: Record<string, unknown> = { ...projectConfig };\n const projectLinters = (projectConfig.linters as Record<string, unknown>) || {};\n\n merged.linters = {\n ...projectLinters,\n enable: unionArrays((projectLinters.enable as string[]) || [], SAFEWORD_ENABLE),\n disable: unionArrays((projectLinters.disable as string[]) || [], SAFEWORD_DISABLE),\n };\n\n const projectSettings = (projectConfig['linters-settings'] as Record<string, unknown>) || {};\n merged['linters-settings'] = fillGapMerge(projectSettings, {\n nestif: { 'min-complexity': 4 },\n gofumpt: { 'extra-rules': true },\n });\n\n const header = `# Safeword golangci-lint config - merged with project config (v1 format)\n# Used by hooks for LLM enforcement. Human pre-commits use project config.\n# NOTE: Consider migrating to golangci-lint v2 format.\n# Re-run \\`safeword install\\` to regenerate after project config changes.\n\n`;\n\n return header + YAML.stringify(merged);\n}\n\n// ============================================================================\n// Merge Utilities\n// ============================================================================\n\n/** Union two string arrays, preserving order (base first), deduplicated. */\nfunction unionArrays(base: string[], additions: string[]): string[] {\n const set = new Set(base);\n for (const item of additions) {\n set.add(item);\n }\n return [...set];\n}\n\n/**\n * Fill-gap merge: base (customer) wins on conflict, override fills missing keys.\n * For nested objects, recurses. Arrays are NOT replaced — customer's win.\n */\nfunction fillGapMerge(\n base: Record<string, unknown>,\n defaults: Record<string, unknown>,\n): Record<string, unknown> {\n const result: Record<string, unknown> = { ...base };\n\n for (const [key, defaultValue] of Object.entries(defaults)) {\n if (Object.hasOwn(result, key)) {\n const existingValue = result[key];\n if (\n defaultValue &&\n typeof defaultValue === 'object' &&\n !Array.isArray(defaultValue) &&\n existingValue &&\n typeof existingValue === 'object' &&\n !Array.isArray(existingValue)\n ) {\n result[key] = fillGapMerge(\n existingValue as Record<string, unknown>,\n defaultValue as Record<string, unknown>,\n );\n }\n } else {\n result[key] = defaultValue;\n }\n }\n\n return result;\n}\n\n// ============================================================================\n// Owned Files (overwritten on upgrade)\n// ============================================================================\n\nexport const golangOwnedFiles: Record<string, FileDefinition> = {\n '.safeword/.golangci.yml': {\n generator: ctx =>\n ctx.languages?.golang\n ? generateSafewordGolangciConfig(ctx.projectType.existingGolangciConfig, ctx.cwd)\n : undefined,\n },\n};\n\n// ============================================================================\n// Managed Files (create if missing, update if matches template)\n// ============================================================================\n\nexport const golangManagedFiles: Record<string, ManagedFileDefinition> = {\n '.golangci.yml': {\n generator: ctx =>\n !ctx.projectType.existingGolangciConfig && ctx.languages?.golang\n ? generateGolangciConfig()\n : undefined,\n },\n};\n","/**\n * Python Language Pack - Schema Definitions\n *\n * All Python-specific file definitions and config generators.\n * Imported by schema.ts and spread into SAFEWORD_SCHEMA.\n *\n * Mirrors the structure of typescript/files.ts and golang/files.ts for consistency.\n *\n * Note: Generator functions return `string | undefined` by design (undefined = skip file).\n * This conflicts with sonarjs/no-inconsistent-returns vs unicorn/no-useless-undefined (#1199).\n * Inline disables target only generator arrow functions, not regular functions in this file.\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport nodePath from 'node:path';\n\nimport type { FileDefinition, ManagedFileDefinition } from '../types.js';\nimport { detectPythonLayers, detectRootPackage, detectSolePackage } from './setup.js';\n\n/**\n * Detect a pre-138 legacy ruff.toml layout where the customer's project-level\n * ruff.toml extends `.safeword/ruff.toml`. In that case, making `.safeword/ruff.toml`\n * also extend `../ruff.toml` would create a circular configuration (ruff errors).\n *\n * We keep those projects on the old standalone shape until the customer migrates\n * by removing the `extend = \".safeword/ruff.toml\"` line from their ruff.toml.\n */\nfunction hasLegacyCustomerRuffExtend(cwd: string): boolean {\n const ruffPath = nodePath.join(cwd, 'ruff.toml');\n if (!existsSync(ruffPath)) return false;\n try {\n const content = readFileSync(ruffPath, 'utf8');\n return content.includes('extend = \".safeword/ruff.toml\"');\n } catch {\n return false;\n }\n}\n\n// ============================================================================\n// Shared Ruff Configuration\n// ============================================================================\n\n/**\n * Curated rule set — covers correctness, security, and modern Python\n * without the upgrade-breakage and noise of select = [\"ALL\"].\n *\n * See: https://docs.astral.sh/ruff/linter/ (ruff maintainers discourage ALL)\n */\nconst SAFEWORD_RULES = [\n '\"E\"', // pycodestyle errors\n '\"F\"', // Pyflakes\n '\"W\"', // pycodestyle warnings\n '\"I\"', // isort\n '\"UP\"', // pyupgrade\n '\"B\"', // flake8-bugbear\n '\"SIM\"', // flake8-simplify\n '\"C4\"', // flake8-comprehensions\n '\"RUF\"', // ruff-specific rules\n '\"PTH\"', // pathlib enforcement\n '\"RET\"', // return statement checks\n '\"S\"', // bandit security\n '\"T20\"', // print statement detection\n '\"TC\"', // type-checking imports\n '\"ERA\"', // commented-out code (LLMs leave dead comments)\n '\"PERF\"', // performance anti-patterns\n '\"PLE\"', // pylint errors\n '\"PLW\"', // pylint warnings\n].join(', ');\n\nconst RUFF_SHARED_SETTINGS = `ignore = [\n \"COM812\", # missing trailing comma - conflicts with formatter\n \"ISC001\", # single-line-implicit-string-concatenation - conflicts with formatter\n \"E501\", # line too long - formatter handles this\n]\n\n[lint.per-file-ignores]\n\"tests/**\" = [\"S101\"] # allow assert in tests\n\n[lint.mccabe]\nmax-complexity = 10`;\n\n/**\n * Standalone lint rules — used in legacy mode (pre-138 customers whose\n * ruff.toml contains `extend = \".safeword/ruff.toml\"`). Defines the full\n * baseline via `select`. Kept to avoid circular extends until the customer\n * migrates by removing that line.\n */\nconst RUFF_LINT_STANDALONE = `[lint]\nselect = [${SAFEWORD_RULES}]\n${RUFF_SHARED_SETTINGS}`;\n\n/**\n * Additive lint rules — used in `.safeword/ruff.toml` in unified mode (ticket 138),\n * which extends the project-level `ruff.toml`. Uses `extend-select` so customer's\n * `select` is preserved.\n */\nconst RUFF_LINT_ADDITIVE = `[lint]\nextend-select = [${SAFEWORD_RULES}]\n${RUFF_SHARED_SETTINGS}`;\n\n// ============================================================================\n// Config Generators for .safeword/ (ownedFiles)\n// ============================================================================\n\n/**\n * Generate Ruff configuration for .safeword/ruff.toml.\n *\n * If project has existing ruff config, extends it with stricter rules.\n * Otherwise generates standalone config.\n *\n * Used by hooks via --config .safeword/ruff.toml flag.\n *\n * @param existingRuffConfig - Path to existing config ('ruff.toml' or 'pyproject.toml'), or undefined\n */\nfunction generateRuffBaseConfig(\n cwd: string,\n existingRuffConfig: 'ruff.toml' | 'pyproject.toml' | undefined = 'ruff.toml',\n): string {\n // Ticket 138 migration: if customer's ruff.toml still contains the pre-138\n // line `extend = \".safeword/ruff.toml\"`, extending customer back would create\n // a circular configuration (ruff errors). Fall back to legacy standalone mode\n // for those projects until the customer removes that line.\n if (hasLegacyCustomerRuffExtend(cwd)) {\n return `# Safeword Ruff config — LEGACY standalone mode\n# Your project's ruff.toml still extends this file (pre-138 layout). To enable\n# the unified override contract (your rules win in the LLM hook too), remove\n# the line \\`extend = \".safeword/ruff.toml\"\\` from your ruff.toml and re-run\n# \\`safeword install\\`.\n\nline-length = 100\n\n${RUFF_LINT_STANDALONE}\n`;\n }\n\n // Unified (ticket 138): always extend from a project-level ruff config.\n // - If customer had pre-existing config (ruff.toml or [tool.ruff] in pyproject.toml), extend that file.\n // - If not, safeword generates a bare project-level ruff.toml (see generateProjectRuffConfig) — extend it.\n // This makes the LLM hook consistently honor customer overrides via ruff's native `extend`.\n return `# Safeword Ruff config - adds rules on top of project config\n# Used by hooks for LLM enforcement. Human pre-commits use project config.\n# Re-run \\`safeword install\\` to regenerate after project config changes.\n#\n# NOTE: Uses extend-select (additive) so your select/ignore are preserved.\n# Known edge case: ruff may drop parent ignore rules when child uses\n# extend-select (https://github.com/astral-sh/ruff/issues/10622).\n# If a project ignore stops working, duplicate it in this file.\n\n# Inherit from project's ${existingRuffConfig}\nextend = \"../${existingRuffConfig}\"\n\nline-length = 100\n\n${RUFF_LINT_ADDITIVE}\n`;\n}\n\n// ============================================================================\n// Owned Files (overwritten on upgrade)\n// ============================================================================\n\n/**\n * Python owned files for .safeword/ directory.\n * These are overwritten on upgrade if content changed.\n */\nexport const pythonOwnedFiles: Record<string, FileDefinition> = {\n // Ruff config for hooks (extends project config if exists)\n '.safeword/ruff.toml': {\n generator: ctx =>\n ctx.languages?.python\n ? generateRuffBaseConfig(ctx.cwd, ctx.projectType.existingRuffConfig)\n : undefined,\n },\n};\n\n// ============================================================================\n// Config Generators for project root (managedFiles)\n// ============================================================================\n\n/**\n * Generate a bare project-level ruff.toml (ticket 138).\n *\n * Customer-owned from the moment it's created: safeword never overwrites it.\n * The LLM hook's `.safeword/ruff.toml` extends this file via ruff's native\n * `extend` directive, so anything the customer adds here wins in both human\n * and LLM lint runs.\n */\nfunction generateProjectRuffConfig(): string {\n return `# Your project's Ruff config — customer-owned, safe to edit.\n# Your rules take precedence in the LLM hook (via .safeword/ruff.toml's extend).\n#\n# Add your rules below, e.g.:\n# [lint]\n# select = [\"E\", \"F\"]\n# ignore = [\"E501\"]\n`;\n}\n\n/**\n * Generate standalone mypy.ini for project root.\n * Strict config for LLM agents - enforces type annotations.\n */\nfunction generateProjectMypyConfig(): string {\n return `# Generated by safeword\n# Strict config for LLM agents - type annotations enforced.\n\n[mypy]\nstrict = True\nwarn_unreachable = True\nignore_missing_imports = True\nshow_error_codes = True\npretty = True\n`;\n}\n\n/**\n * Generate standalone .importlinter for project root.\n *\n * @param layers - Detected layers (e.g., ['domain', 'services', 'api'])\n * @param rootPackage - Root package name for the project\n */\nfunction generateProjectImportLinterConfig(layers: string[], rootPackage: string): string {\n if (layers.length < 2) return '';\n\n const layerList = layers.map(l => ` ${rootPackage}.${l}`).join('\\n');\n\n return `# Generated by safeword\n# Layer architecture contracts - enforces clean dependencies\n\n[importlinter]\nroot_packages = ${rootPackage}\n\n[importlinter:contract:layers]\nname = Layer architecture\ntype = layers\nlayers =\n${layerList}\n`;\n}\n\n/**\n * Generic circular-import guard for a single-package project (ticket V4MATC,\n * upstream #847) — the Python analog of depcruise's no-circular rule, emitted\n * when no layer structure is detected but the top-level package is unambiguous.\n * Exact syntax per import-linter 2.x docs: `type = acyclic_siblings`\n * (underscore), `ancestors` is required, `root_package` singular is the\n * documented single-package form.\n */\nfunction generateAcyclicImportLinterConfig(packageName: string): string {\n return `# Generated by safeword\n# Circular-import guard - forbids dependency cycles between sibling modules\n\n[importlinter]\nroot_package = ${packageName}\n\n[importlinter:contract:safeword-acyclic]\nname = No circular imports between sibling modules (safeword)\ntype = acyclic_siblings\nancestors = ${packageName}\n`;\n}\n\n// ============================================================================\n// Managed Files (create if missing, reconciled on reset/upgrade)\n// ============================================================================\n\nexport const pythonManagedFiles: Record<string, ManagedFileDefinition> = {\n // Project-level ruff config (created only if no existing ruff config)\n 'ruff.toml': {\n generator: ctx =>\n ctx.languages?.python && !ctx.projectType.existingRuffConfig\n ? generateProjectRuffConfig()\n : undefined,\n },\n\n // Project-level mypy config (created only if no existing mypy config)\n 'mypy.ini': {\n generator: ctx =>\n ctx.languages?.python && !ctx.projectType.existingMypyConfig\n ? generateProjectMypyConfig()\n : undefined,\n },\n\n // Project-level import-linter config (created when no existing config and either\n // layers are detected or the top-level package is unambiguous — ticket V4MATC)\n '.importlinter': {\n // eslint-disable-next-line sonarjs/no-inconsistent-returns -- generator returns undefined to skip file\n generator: ctx => {\n if (!ctx.languages?.python) return;\n if (ctx.projectType.existingImportLinterConfig) return;\n return importLinterScaffoldContent(ctx.cwd);\n },\n // Default reset removes the file only when it byte-equals the scaffold we\n // would generate — gate-free content source, since at reset time the\n // scaffold's own existence trips the existing-config gate above (V4MATC R4).\n // If the project layout changed since scaffolding (package renamed, layers\n // appeared) or line endings were converted (e.g. autocrlf), the regenerated\n // content won't byte-match and the file survives reset — intentional:\n // never delete what we can't prove we wrote.\n removeIfUnmodified: ctx =>\n ctx.languages?.python ? importLinterScaffoldContent(ctx.cwd) : undefined,\n },\n};\n\n/**\n * True when this project is one safeword would scaffold an .importlinter for —\n * the single source of the \"should import-linter be part of this project\"\n * decision, shared by the scaffold generator and the install condition in\n * lifecycle/project-install.ts (so the two can never drift).\n */\nexport function hasImportLinterScaffoldTarget(cwd: string): boolean {\n return importLinterScaffoldContent(cwd) !== undefined;\n}\n\n/**\n * Expected .importlinter scaffold for this project, WITHOUT the existing-config\n * gate: layers contract when a layer structure is detected, otherwise the\n * generic acyclic guard when the top-level package is unambiguous, else\n * undefined. Shared by the create-time generator (which adds the gate) and the\n * reset-time removeIfUnmodified comparison (which must not have it).\n */\nfunction importLinterScaffoldContent(cwd: string): string | undefined {\n const layers = detectPythonLayers(cwd);\n if (layers.length >= 2) {\n return generateProjectImportLinterConfig(layers, detectRootPackage(cwd));\n }\n const solePackage = detectSolePackage(cwd);\n if (!solePackage) return undefined;\n return generateAcyclicImportLinterConfig(solePackage);\n}\n","/**\n * Python-specific Setup Utilities\n *\n * Setup logic for Python projects.\n * Config generators are in files.ts (same pattern as TypeScript and Go).\n *\n * This file contains:\n * - Layer detection for architecture boundaries\n * - Package manager detection for install guidance\n */\n\nimport { execFileSync } from 'node:child_process';\nimport { readdirSync, realpathSync } from 'node:fs';\nimport nodePath from 'node:path';\n\nimport { parse } from 'smol-toml';\n\nimport { exists, readFileSafe } from '../../utils/fs.js';\nimport type { SetupResult } from '../types.js';\n\n/**\n * Python layer patterns for architecture detection.\n * Mirrors boundaries.ts ARCHITECTURE_LAYERS pattern.\n *\n * @see .safeword/planning/design/phase2-python-tooling.md → Layer detection heuristic\n */\nconst PYTHON_LAYERS: Record<string, string[]> = {\n domain: ['domain', 'models', 'entities', 'core'],\n services: ['services', 'usecases', 'application'],\n infra: ['infra', 'infrastructure', 'adapters', 'repositories'],\n api: ['api', 'routes', 'handlers', 'views', 'controllers'],\n};\n\n/**\n * Detect Python layers in a project directory.\n * Looks for common Python layer directory patterns.\n *\n * @param cwd - Project root directory\n * @returns Array of detected layer names in dependency order (domain first)\n */\n/**\n * Whether any of the given layer patterns exists under `cwd` (either at\n * `src/{pattern}` or `{pattern}`).\n */\nfunction hasAnyLayerPattern(cwd: string, patterns: readonly string[]): boolean {\n for (const pattern of patterns) {\n // Check common locations: src/{pattern}, {pattern}\n const srcPath = nodePath.join(cwd, 'src', pattern);\n const rootPath = nodePath.join(cwd, pattern);\n if (exists(srcPath) || exists(rootPath)) {\n return true;\n }\n }\n return false;\n}\n\nexport function detectPythonLayers(cwd: string): string[] {\n const detected: string[] = [];\n\n for (const [layer, patterns] of Object.entries(PYTHON_LAYERS)) {\n if (hasAnyLayerPattern(cwd, patterns)) {\n detected.push(layer);\n }\n }\n\n // Return in correct dependency order (domain → services → infra → api)\n const layerOrder = ['domain', 'services', 'infra', 'api'];\n return layerOrder.filter(layer => detected.includes(layer));\n}\n\n/**\n * Detect the root package name from pyproject.toml or directory structure.\n *\n * @param cwd - Project root directory\n * @returns Package name or 'src' as fallback\n */\nexport function detectRootPackage(cwd: string): string {\n const pyprojectPath = nodePath.join(cwd, 'pyproject.toml');\n const content = readFileSafe(pyprojectPath);\n\n if (content) {\n // Try to extract name from [project] section\n // Using simple pattern to avoid regex backtracking\n const nameMatch = /^name\\s*=\\s*\"([^\"]+)\"/m.exec(content);\n if (nameMatch?.[1]) {\n // Convert kebab-case to snake_case for Python imports\n return nameMatch[1].replaceAll('-', '_');\n }\n }\n\n // Fallback: check for src/ directory\n if (exists(nodePath.join(cwd, 'src'))) {\n return 'src';\n }\n\n // Last resort: use directory name\n return nodePath.basename(cwd).replaceAll('-', '_');\n}\n\n/**\n * Directory names that hold Python files but are not the distribution package —\n * excluded from sole-package detection so `tests/__init__.py` etc. never make a\n * real single-package project read as ambiguous.\n */\nconst NON_PACKAGE_DIRS = new Set([\n 'tests',\n 'test',\n 'docs',\n 'examples',\n 'scripts',\n 'node_modules',\n 'venv',\n]);\n\n/**\n * Importable packages (dirs with `__init__.py`) directly under `dir`, excluding\n * non-package dirs. Symlinked directories are not counted (`isDirectory()` is\n * false for symlinks) — deliberate narrow detection: a layout that only looks\n * ambiguous through symlinks still scaffolds, and the unchecked package is at\n * worst uncovered, never wrongly deleted.\n */\nfunction importablePackagesIn(dir: string): string[] {\n if (!exists(dir)) return [];\n try {\n return readdirSync(dir, { withFileTypes: true })\n .filter(\n entry =>\n entry.isDirectory() &&\n !entry.name.startsWith('.') &&\n !NON_PACKAGE_DIRS.has(entry.name) &&\n exists(nodePath.join(dir, entry.name, '__init__.py')),\n )\n .map(entry => entry.name);\n } catch {\n return [];\n }\n}\n\n/**\n * The project's single unambiguous top-level package, from filesystem truth:\n * exactly one importable package (a directory with `__init__.py`) at the repo\n * root or under `src/`. Anything else — zero packages (scripts-only), two or\n * more, or a root+src mix — returns undefined, and callers scaffold nothing\n * (ticket V4MATC R3: a wrong guess errors every audit; the honest skip wins).\n */\nexport function detectSolePackage(cwd: string): string | undefined {\n const candidates = [\n ...importablePackagesIn(cwd),\n ...importablePackagesIn(nodePath.join(cwd, 'src')),\n ];\n return candidates.length === 1 ? candidates[0] : undefined;\n}\n\ntype PythonPackageManager = 'uv' | 'poetry' | 'pipenv' | 'pip';\nexport type PythonTool = 'ruff' | 'mypy' | 'deadcode' | 'import-linter';\n\nconst PYTHON_DEPENDENCY_SEPARATORS = new Set(['[', '<', '>', '=', '!', '~', ';', '@']);\n\nfunction normalizePythonDistributionName(value: string): string {\n return value\n .trim()\n .toLowerCase()\n .replaceAll(/[-_.]+/g, '-');\n}\n\nfunction startsPythonDependency(value: string, dependency: PythonTool): boolean {\n const candidate = normalizePythonDistributionName(value);\n const normalizedDependency = normalizePythonDistributionName(dependency);\n if (!candidate.startsWith(normalizedDependency)) return false;\n\n const next = candidate.at(normalizedDependency.length);\n return next === undefined || PYTHON_DEPENDENCY_SEPARATORS.has(next) || next.trim() === '';\n}\n\ntype TomlTable = Record<string, unknown>;\n\nfunction asTomlTable(value: unknown): TomlTable | undefined {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as TomlTable)\n : undefined;\n}\n\nfunction parseTomlTable(content: string): TomlTable | undefined {\n try {\n return asTomlTable(parse(content));\n } catch {\n return undefined;\n }\n}\n\nfunction tomlTableAt(table: TomlTable, path: readonly string[]): TomlTable | undefined {\n let current: TomlTable | undefined = table;\n for (const key of path) {\n current = current === undefined ? undefined : asTomlTable(current[key]);\n }\n return current;\n}\n\nfunction tomlStringArray(value: unknown): string[] {\n return Array.isArray(value)\n ? value.filter((item): item is string => typeof item === 'string')\n : [];\n}\n\nfunction dependencyGroupSpecs(\n groups: TomlTable,\n groupName: string,\n visited: Set<string> = new Set<string>(),\n): string[] {\n if (visited.has(groupName)) return [];\n visited.add(groupName);\n\n return (Array.isArray(groups[groupName]) ? groups[groupName] : []).flatMap(item => {\n if (typeof item === 'string') return [item];\n const includeGroup = asTomlTable(item)?.['include-group'];\n return typeof includeGroup === 'string'\n ? dependencyGroupSpecs(groups, includeGroup, visited)\n : [];\n });\n}\n\nfunction pyprojectDependencySpecs(document: TomlTable): string[] {\n const project = asTomlTable(document.project);\n const optionalDependencies = asTomlTable(project?.['optional-dependencies']);\n const dependencyGroups = asTomlTable(document['dependency-groups']);\n const uv = tomlTableAt(document, ['tool', 'uv']);\n\n return [\n ...tomlStringArray(project?.dependencies),\n ...Object.values(optionalDependencies ?? {}).flatMap(value => tomlStringArray(value)),\n ...(dependencyGroups === undefined\n ? []\n : Object.keys(dependencyGroups).flatMap(groupName =>\n dependencyGroupSpecs(dependencyGroups, groupName),\n )),\n ...tomlStringArray(uv?.['dev-dependencies']),\n ];\n}\n\nfunction poetryDependencyNames(document: TomlTable): string[] {\n const poetry = tomlTableAt(document, ['tool', 'poetry']);\n const groups = asTomlTable(poetry?.group);\n const groupNames = Object.values(groups ?? {}).flatMap(group =>\n Object.keys(asTomlTable(asTomlTable(group)?.dependencies) ?? {}),\n );\n\n return [\n ...Object.keys(asTomlTable(poetry?.dependencies) ?? {}),\n ...Object.keys(asTomlTable(poetry?.['dev-dependencies']) ?? {}),\n ...groupNames,\n ];\n}\n\nfunction hasPythonDependencyName(names: readonly string[], dependency: PythonTool): boolean {\n const normalizedDependency = normalizePythonDistributionName(dependency);\n return names.some(name => normalizePythonDistributionName(name) === normalizedDependency);\n}\n\nfunction containsPyprojectPythonDependency(content: string, dependency: PythonTool): boolean {\n const document = parseTomlTable(content);\n if (document === undefined) return false;\n\n return (\n hasPythonDependencyName(poetryDependencyNames(document), dependency) ||\n pyprojectDependencySpecs(document).some(specification =>\n startsPythonDependency(specification, dependency),\n )\n );\n}\n\nfunction containsPipfilePythonDependency(content: string, dependency: PythonTool): boolean {\n const document = parseTomlTable(content);\n if (document === undefined) return false;\n\n return hasPythonDependencyName(\n [\n ...Object.keys(asTomlTable(document.packages) ?? {}),\n ...Object.keys(asTomlTable(document['dev-packages']) ?? {}),\n ],\n dependency,\n );\n}\n\nfunction shortRequirementsInclude(declaration: string): string | undefined {\n if (!declaration.startsWith('-r')) return undefined;\n return declaration.slice(2).trim() || undefined;\n}\n\nfunction longRequirementsInclude(declaration: string): string | undefined {\n const longOption = '--requirement';\n if (!declaration.startsWith(longOption)) return undefined;\n\n const suffix = declaration.slice(longOption.length);\n if (suffix.startsWith('=')) return suffix.slice(1).trim() || undefined;\n if (suffix.trimStart().length === suffix.length) return undefined;\n return suffix.trim() || undefined;\n}\n\nfunction unquoteRequirementsInclude(include: string): string {\n if (\n (include.startsWith('\"') && include.endsWith('\"')) ||\n (include.startsWith(\"'\") && include.endsWith(\"'\"))\n ) {\n return include.slice(1, -1);\n }\n return include;\n}\n\nfunction requirementsIncludePath(line: string): string | undefined {\n const declaration = (line.split('#', 1)[0] ?? '').trim();\n const include = shortRequirementsInclude(declaration) ?? longRequirementsInclude(declaration);\n return include === undefined ? undefined : unquoteRequirementsInclude(include);\n}\n\nfunction isPathWithinDirectory(candidate: string, directory: string): boolean {\n const relative = nodePath.relative(directory, candidate);\n return relative === '' || (relative !== '..' && !relative.startsWith(`..${nodePath.sep}`));\n}\n\nfunction isRealPathWithinDirectory(candidate: string, directory: string): boolean {\n try {\n return isPathWithinDirectory(realpathSync(candidate), realpathSync(directory));\n } catch {\n return false;\n }\n}\n\nfunction containsRequirementsPythonDependency(\n projectDirectory: string,\n requirementsPath: string,\n dependency: PythonTool,\n visited: Set<string> = new Set<string>(),\n): boolean {\n const resolvedRequirementsPath = nodePath.resolve(requirementsPath);\n if (\n !isRealPathWithinDirectory(resolvedRequirementsPath, projectDirectory) ||\n visited.has(resolvedRequirementsPath)\n ) {\n return false;\n }\n visited.add(resolvedRequirementsPath);\n\n const content = readFileSafe(resolvedRequirementsPath);\n if (content === undefined) return false;\n\n return content.split('\\n').some(line => {\n if (line.trimStart().startsWith('#')) return false;\n const declaration = line.split('#', 1)[0] ?? '';\n if (startsPythonDependency(declaration, dependency)) return true;\n\n const include = requirementsIncludePath(line);\n if (include === undefined || nodePath.isAbsolute(include)) return false;\n const includePath = nodePath.resolve(nodePath.dirname(resolvedRequirementsPath), include);\n return containsRequirementsPythonDependency(projectDirectory, includePath, dependency, visited);\n });\n}\n\nfunction hasPythonDependency(cwd: string, dependency: PythonTool): boolean {\n const pyprojectContent = readFileSafe(nodePath.join(cwd, 'pyproject.toml'));\n const pipfileContent = readFileSafe(nodePath.join(cwd, 'Pipfile'));\n\n return (\n (pyprojectContent !== undefined &&\n containsPyprojectPythonDependency(pyprojectContent, dependency)) ||\n (pipfileContent !== undefined && containsPipfilePythonDependency(pipfileContent, dependency)) ||\n containsRequirementsPythonDependency(cwd, nodePath.join(cwd, 'requirements.txt'), dependency)\n );\n}\n\n/**\n * Check whether ruff is declared in a project dependency manifest rather than\n * merely configured under [tool.ruff].\n */\nexport function hasRuffDependency(cwd: string): boolean {\n return hasPythonDependency(cwd, 'ruff');\n}\n\n/**\n * Detect the Python package manager used by the project.\n */\nexport function detectPythonPackageManager(cwd: string): PythonPackageManager {\n // Check for uv (uv.lock or .python-version with uv markers)\n if (exists(nodePath.join(cwd, 'uv.lock'))) {\n return 'uv';\n }\n\n // Check for Poetry\n if (exists(nodePath.join(cwd, 'poetry.lock'))) {\n return 'poetry';\n }\n\n // Check for poetry in pyproject.toml\n const pyprojectPath = nodePath.join(cwd, 'pyproject.toml');\n const pyprojectContent = readFileSafe(pyprojectPath);\n if (pyprojectContent?.includes('[tool.poetry]')) {\n return 'poetry';\n }\n\n // Check for Pipenv\n if (exists(nodePath.join(cwd, 'Pipfile'))) {\n return 'pipenv';\n }\n\n // Default to pip\n return 'pip';\n}\n\n/**\n * Get the install command for Python tools based on package manager.\n *\n * @param cwd - Project root directory\n * @param tools - Tools to install (defaults to ['ruff'])\n */\nexport function getPythonInstallCommand(cwd: string, tools: string[] = ['ruff']): string {\n const pm = detectPythonPackageManager(cwd);\n const toolList = tools.join(' ');\n\n switch (pm) {\n case 'uv': {\n return `uv add --dev ${toolList}`;\n }\n case 'poetry': {\n return `poetry add --group dev ${toolList}`;\n }\n case 'pipenv': {\n return `pipenv install --dev ${toolList}`;\n }\n case 'pip': {\n return `pip install ${toolList}`;\n }\n }\n}\n\nfunction pythonInstallInvocation(\n cwd: string,\n tools: readonly PythonTool[],\n): { command: string; arguments: string[] } {\n switch (detectPythonPackageManager(cwd)) {\n case 'uv': {\n return { command: 'uv', arguments: ['add', '--dev', ...tools] };\n }\n case 'poetry': {\n return { command: 'poetry', arguments: ['add', '--group', 'dev', ...tools] };\n }\n case 'pipenv': {\n return { command: 'pipenv', arguments: ['install', '--dev', ...tools] };\n }\n case 'pip': {\n return { command: 'pip', arguments: ['install', ...tools] };\n }\n }\n}\n\n/**\n * Install Python development dependencies using detected package manager.\n * Matches TypeScript parity where we auto-install ESLint/Prettier.\n *\n * @param cwd - Project root directory\n * @param tools - Tools to install (e.g., ['ruff', 'mypy', 'import-linter'])\n * @returns true if installation succeeded, false otherwise\n */\n/**\n * The Python tools safeword installs: ruff, mypy, deadcode, plus import-linter\n * when safeword would scaffold a config for it (layers OR an unambiguous single\n * package — the hasImportLinterScaffoldTarget predicate). Single source so\n * `setup` and `upgrade` install the same set; they had drifted (upgrade shipped\n * only ruff + mypy).\n */\nexport function getPythonTools(includeImportLinter: boolean): PythonTool[] {\n const tools: PythonTool[] = ['ruff', 'mypy', 'deadcode'];\n if (includeImportLinter) tools.push('import-linter');\n return tools;\n}\n\n/**\n * Safe Word's Python tooling is project configuration, not a global shell\n * prerequisite: uv and Poetry keep project tools in managed environments. Read\n * declarations only so health checks stay filesystem-only and never invoke a\n * package manager merely to inspect readiness.\n */\nexport function getMissingPythonToolDependencies(\n cwd: string,\n includeImportLinter: boolean,\n): PythonTool[] {\n return getPythonTools(includeImportLinter).filter(tool => !hasPythonDependency(cwd, tool));\n}\n\nexport function installPythonDependencies(cwd: string, tools: readonly PythonTool[]): boolean {\n if (tools.length === 0) return true;\n if (process.env.SAFEWORD_SKIP_INSTALL) return true;\n\n // pip projects need manual install due to PEP 668\n const pm = detectPythonPackageManager(cwd);\n if (pm === 'pip') return false;\n\n try {\n const invocation = pythonInstallInvocation(cwd, tools);\n execFileSync(invocation.command, invocation.arguments, {\n cwd,\n stdio: 'pipe',\n timeout: 60_000, // 60s timeout to prevent hanging on network/resolution issues\n });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Set up Python tooling configuration.\n *\n * Note: Config files (ruff.toml, mypy.ini, .importlinter) are now created\n * by the schema system (managedFiles) for full reconciliation support.\n * This function exists for future Python-specific setup logic.\n *\n * @returns Empty result (schema handles file creation)\n */\nexport function setupPythonTooling(): SetupResult {\n // Config files are created by schema.ts managedFiles\n // Future: Add any Python-specific setup logic here\n return { files: [] };\n}\n","/**\n * Rust language pack file definitions\n *\n * Defines config generators and file definitions for:\n * - clippy.toml (lint thresholds)\n * - rustfmt.toml (formatting options)\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport nodePath from 'node:path';\n\nimport type { FileDefinition, ManagedFileDefinition } from '../types.js';\n\n// ============================================================================\n// Shared Configuration Constants\n// ============================================================================\n\n/**\n * Safeword's clippy thresholds — fills gaps only, customer values win.\n *\n * Clippy defaults are lenient (cognitive-complexity = 25, args = 7).\n * Safeword tightens for LLM code but respects explicit customer choices.\n */\nconst SAFEWORD_CLIPPY_THRESHOLDS: Record<string, number> = {\n 'cognitive-complexity-threshold': 10,\n 'too-many-arguments-threshold': 5,\n 'too-many-lines-threshold': 100,\n 'type-complexity-threshold': 250,\n};\n\n// ============================================================================\n// Config Generators\n// ============================================================================\n\n/** Generate standalone clippy.toml with safeword thresholds. */\nfunction generateClippyConfig(): string {\n const thresholds = Object.entries(SAFEWORD_CLIPPY_THRESHOLDS)\n .map(([key, value]) => `${key} = ${String(value)}`)\n .join('\\n');\n\n return `# Generated by safeword - DO NOT EDIT\n# Configure lint levels in Cargo.toml [lints.clippy] section\n\n${thresholds}\n`;\n}\n\n/**\n * Generate .safeword/clippy.toml — fills gaps only.\n * Customer's thresholds are preserved; safeword only adds missing ones.\n */\nfunction generateSafewordClippyConfig(existingConfig: string | undefined, cwd: string): string {\n if (!existingConfig) {\n return `# Safeword clippy config - standalone (no project config to merge)\n# Used by hooks for LLM enforcement.\n\n${generateClippyThresholds()}\n`;\n }\n\n const configPath = nodePath.join(cwd, existingConfig);\n if (!existsSync(configPath)) {\n return `# Safeword clippy config - standalone (no project config to merge)\n# Used by hooks for LLM enforcement.\n\n${generateClippyThresholds()}\n`;\n }\n\n try {\n const content = readFileSync(configPath, 'utf8');\n const customerKeys = parseClippyKeys(content);\n\n // Fill gaps: only add thresholds customer didn't set\n const gapEntries = Object.entries(SAFEWORD_CLIPPY_THRESHOLDS)\n .filter(([key]) => !customerKeys.has(key))\n .map(([key, value]) => `${key} = ${String(value)}`);\n\n // Include all customer content, then append safeword's gap-fills\n const safewordSection =\n gapEntries.length > 0\n ? `\\n# Safeword defaults (not set in project config)\\n${gapEntries.join('\\n')}\\n`\n : '';\n\n return `# Safeword clippy config - merged with project config\n# Used by hooks for LLM enforcement. Human pre-commits use project config.\n# Re-run \\`safeword install\\` to regenerate after project config changes.\n#\n# NOTE: Your thresholds are preserved. Safeword only fills gaps.\n\n${content.trim()}\n${safewordSection}`;\n } catch {\n return `# Safeword clippy config - standalone (parse error on project config)\n# Used by hooks for LLM enforcement.\n\n${generateClippyThresholds()}\n`;\n }\n}\n\n/** Generate threshold lines from SAFEWORD_CLIPPY_THRESHOLDS. */\nfunction generateClippyThresholds(): string {\n return Object.entries(SAFEWORD_CLIPPY_THRESHOLDS)\n .map(([key, value]) => `${key} = ${String(value)}`)\n .join('\\n');\n}\n\n/** Parse a clippy.toml and return the set of keys that are defined. */\nfunction parseClippyKeys(content: string): Set<string> {\n const keys = new Set<string>();\n for (const line of content.split('\\n')) {\n const trimmed = line.trim();\n if (trimmed && !trimmed.startsWith('#')) {\n const match = /^([\\w-]+)\\s*=/.exec(trimmed);\n if (match?.[1]) keys.add(match[1]);\n }\n }\n return keys;\n}\n\n/**\n * Fallback Rust edition when the project's edition is truly unresolvable — an\n * unreadable/absent Cargo.toml, or a manifest with neither a `[package]` nor a\n * `[workspace.package]` edition to anchor to. Tracks the latest STABLE edition,\n * not the oldest: a fresh or unknowable project in 2026 is best served by the\n * current style edition (edition 2024, stable since Rust 1.85, 2025-02-20), not\n * a 2021 default that mis-sorts imports and can't parse 2024 syntax.\n */\nconst FALLBACK_RUST_EDITION = '2024';\n\n/**\n * The edition Cargo assigns a `[package]` that declares none. We mirror it so an\n * edition-less (legacy) crate is formatted as the 2015 it actually is, rather\n * than having 2024 parsing/style imposed on 2015 code (which uses `async`,\n * `await`, `dyn`, `try` as identifiers).\n */\nconst CARGO_DEFAULT_EDITION = '2015';\n\n/**\n * The `edition = \"…\"` value declared inside a named TOML section, or undefined.\n * Scoped to the section slice (header → next `[…]` header), comment-stripped,\n * and line-anchored so a `# edition = \"2018\"` comment or a `foo-edition` key\n * can't be mistaken for the real key. Accepts basic or literal TOML strings.\n */\nfunction editionInSection(content: string, header: string): string | undefined {\n const start = content.indexOf(header);\n if (start === -1) return undefined;\n\n const rest = content.slice(start + header.length);\n const nextHeader = rest.search(/\\n[ \\t]*\\[/);\n const section = nextHeader === -1 ? rest : rest.slice(0, nextHeader);\n\n for (const rawLine of section.split('\\n')) {\n const line = rawLine.replace(/#.*/, '').trim();\n const match = /^edition\\s*=\\s*[\"']([^\"']+)[\"']/.exec(line);\n if (match?.[1]) return match[1];\n }\n return undefined;\n}\n\n/**\n * Resolve the Rust edition to emit in rustfmt.toml by reading the project's\n * Cargo.toml. rustfmt's `edition` drives both parsing and (by default) the\n * style edition, and an explicit value in rustfmt.toml OVERRIDES what\n * `cargo fmt` would infer — so it must match the crate's real edition or it\n * mis-parses/mis-styles. Resolution order mirrors Cargo:\n * 1. `[package] edition`,\n * 2. workspace-inherited `[workspace.package] edition` (also the\n * virtual-manifest case, where there is no `[package]`),\n * 3. a `[package]` that declares no edition → Cargo's 2015 default,\n * 4. otherwise the modern fallback (unreadable/absent manifest, or no edition\n * anywhere to anchor to).\n * This never demands a newer toolchain than the crate already needs: a 2024\n * crate already requires Rust 1.85 to compile.\n */\nexport function resolveRustEdition(cwd: string): string {\n let content: string;\n try {\n content = readFileSync(nodePath.join(cwd, 'Cargo.toml'), 'utf8');\n } catch {\n return FALLBACK_RUST_EDITION;\n }\n\n const packageEdition = editionInSection(content, '[package]');\n if (packageEdition) return packageEdition;\n\n const workspaceEdition = editionInSection(content, '[workspace.package]');\n if (workspaceEdition) return workspaceEdition;\n\n // A present-but-edition-less `[package]` is edition 2015 by Cargo's default;\n // match it rather than imposing the modern fallback on legacy code. `.includes`\n // mirrors the pack's own `detectWorkspaceType` idiom.\n if (content.includes('[package]')) return CARGO_DEFAULT_EDITION;\n\n return FALLBACK_RUST_EDITION;\n}\n\n/**\n * Generate a lenient, forward-compatible `deny.toml` for the `cargo deny check`\n * supply-chain gate (`safeword project test-plan --kind deps`, run at the /verify gate).\n *\n * Design choices, driven by cargo-deny's schema churn and the cost of a false\n * red on a customer's done-gate:\n * - Only long-lived fields; NO `version`/severity keys (`vulnerability`,\n * `yanked`, …) — those were reshuffled across releases. cargo-deny denies\n * advisories by default, so an explicit-but-empty `[advisories]` is enough and\n * leaves an obvious place to add `ignore = [\"RUSTSEC-…\"]`.\n * - A BROAD permissive `allow` list (covers the overwhelming majority of\n * crates.io) so the licenses check doesn't fail on a routine transitive dep the\n * first time the gate runs. Users extend it when the gate flags a new license.\n * - `multiple-versions = \"warn\"` — duplicate versions are bloat, not a hard stop.\n */\nfunction generateDenyConfig(): string {\n return `# Generated by safeword — cargo-deny dependency config.\n# Safeword creates this file if missing and won't overwrite your edits.\n# Full schema: https://embarkstudios.github.io/cargo-deny/checks/cfg.html\n#\n# The /verify done-gate runs ONLY the advisories check (\\`cargo deny check\n# advisories\\`) — the universal security signal. The licenses/bans/sources\n# sections below are configured but NOT gated by default, because they false-red\n# on things unrelated to a change (missing license metadata, intentional git\n# deps). Enforce them in your own CI with a full \\`cargo deny check\\`.\n#\n# Note: the advisories check fetches the RustSec advisory-db over git on first\n# run, so an offline done-gate can fail here. Prime the cache once online, or run\n# \\`cargo deny check advisories\\` yourself, before relying on the gate offline.\n\n[advisories]\n# Security advisories from the RustSec DB (the cargo-audit source). cargo-deny\n# denies vulnerabilities by default; add \\`ignore = [\"RUSTSEC-YYYY-NNNN\"]\\` to\n# accept a specific one with a rationale.\n\n[licenses]\n# Permissive licenses covering the vast majority of crates.io. Extend this list\n# when the gate flags a dependency whose license you accept.\nallow = [\n \"MIT\",\n \"MIT-0\",\n \"Apache-2.0\",\n \"Apache-2.0 WITH LLVM-exception\",\n \"BSD-2-Clause\",\n \"BSD-3-Clause\",\n \"0BSD\",\n \"ISC\",\n \"Zlib\",\n \"MPL-2.0\",\n \"Unicode-3.0\",\n \"Unicode-DFS-2016\",\n \"CC0-1.0\",\n \"Unlicense\",\n \"BSL-1.0\",\n \"OpenSSL\",\n]\n\n[bans]\n# Duplicate versions bloat builds but rarely warrant a hard failure — warn only.\nmultiple-versions = \"warn\"\n\n[sources]\n# Trust only crates.io by default; flag crates pulled from unknown registries.\nunknown-registry = \"deny\"\nunknown-git = \"deny\"\n`;\n}\n\nfunction generateRustfmtConfig(cwd: string): string {\n const edition = resolveRustEdition(cwd);\n return `# Generated by safeword - DO NOT EDIT\n# edition is derived from your Cargo.toml (fallback: ${FALLBACK_RUST_EDITION}); it\n# must match the crate's edition because rustfmt.toml overrides what cargo fmt infers.\n# All other options are stable on any toolchain that supports this edition.\n\nedition = \"${edition}\"\nmax_width = 100\ntab_spaces = 4\nnewline_style = \"Unix\"\nreorder_imports = true\nuse_field_init_shorthand = true\n`;\n}\n\n// ============================================================================\n// Owned Files (.safeword/ - overwritten on upgrade)\n// ============================================================================\n\nexport const rustOwnedFiles: Record<string, FileDefinition> = {\n '.safeword/clippy.toml': {\n generator: ctx =>\n ctx.languages?.rust\n ? generateSafewordClippyConfig(ctx.projectType.existingClippyConfig, ctx.cwd)\n : undefined,\n },\n '.safeword/rustfmt.toml': {\n generator: ctx => (ctx.languages?.rust ? generateRustfmtConfig(ctx.cwd) : undefined),\n },\n};\n\n// ============================================================================\n// Managed Files (project root - create if missing)\n// ============================================================================\n\nexport const rustManagedFiles: Record<string, ManagedFileDefinition> = {\n 'clippy.toml': {\n generator: ctx =>\n ctx.languages?.rust && !ctx.projectType.existingClippyConfig\n ? generateClippyConfig()\n : undefined,\n },\n 'rustfmt.toml': {\n generator: ctx =>\n ctx.languages?.rust && !ctx.projectType.existingRustfmtConfig\n ? generateRustfmtConfig(ctx.cwd)\n : undefined,\n },\n // deny.toml is create-if-missing (managed): the `cargo deny check` supply-chain\n // gate reads it from the project root. Never overwrites a user's own config.\n 'deny.toml': {\n generator: ctx => (ctx.languages?.rust ? generateDenyConfig() : undefined),\n },\n};\n","/**\n * SQL dialect auto-detection\n *\n * Detects the correct SQLFluff dialect from project signals.\n * Returns undefined when no signal found (caller defaults to 'ansi').\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport nodePath from 'node:path';\nimport process from 'node:process';\n\nimport YAML from 'yaml';\n\nimport { findInTree } from '../../utils/fs.js';\n\n// dbt adapter name → SQLFluff dialect (most are 1:1)\nconst ADAPTER_TO_DIALECT: Record<string, string> = {\n postgres: 'postgres',\n postgresql: 'postgres',\n redshift: 'redshift',\n snowflake: 'snowflake',\n bigquery: 'bigquery',\n clickhouse: 'clickhouse',\n duckdb: 'duckdb',\n trino: 'trino',\n databricks: 'databricks',\n athena: 'athena',\n teradata: 'teradata',\n materialize: 'materialize',\n sqlite: 'sqlite',\n mysql: 'mysql',\n oracle: 'oracle',\n vertica: 'vertica',\n starrocks: 'starrocks',\n doris: 'doris',\n hive: 'hive',\n impala: 'impala',\n db2: 'db2',\n greenplum: 'greenplum',\n exasol: 'exasol',\n // Name mismatches\n spark: 'sparksql',\n fabric: 'tsql',\n synapse: 'tsql',\n // Compatibility aliases\n tidb: 'mysql',\n singlestore: 'mysql',\n cratedb: 'postgres',\n timescaledb: 'postgres',\n};\n\n// URL scheme → SQLFluff dialect\nconst SCHEME_TO_DIALECT: Record<string, string> = {\n postgresql: 'postgres',\n postgres: 'postgres',\n mysql: 'mysql',\n mariadb: 'mysql',\n sqlite: 'sqlite',\n sqlite3: 'sqlite',\n bigquery: 'bigquery',\n clickhouse: 'clickhouse',\n redshift: 'redshift',\n snowflake: 'snowflake',\n sqlserver: 'tsql',\n mssql: 'tsql',\n};\n\n// Drizzle dialect → SQLFluff dialect\nconst DRIZZLE_TO_DIALECT: Record<string, string> = {\n postgresql: 'postgres',\n mysql: 'mysql',\n sqlite: 'sqlite',\n turso: 'sqlite',\n singlestore: 'mysql',\n mssql: 'tsql',\n gel: 'postgres',\n cockroach: 'postgres',\n};\n\n// ORM provider → SQLFluff dialect\nconst PROVIDER_TO_DIALECT: Record<string, string> = {\n postgresql: 'postgres',\n mysql: 'mysql',\n sqlite: 'sqlite',\n sqlserver: 'tsql',\n cockroachdb: 'postgres',\n};\n\n/**\n * Detect SQL dialect from project signals.\n * Returns the SQLFluff dialect string or undefined (→ ansi default).\n *\n * Priority order: profiles.yml (canonical for dbt) → Python deps (always in repo)\n * → sqlc config → Prisma schema → Drizzle config → DATABASE_URL (lowest confidence).\n */\nexport function detectSqlDialect(cwd: string): string | undefined {\n return (\n detectFromProfiles(cwd) ??\n detectFromPythonDependencies(cwd) ??\n detectFromSqlcConfig(cwd) ??\n detectFromPrismaSchema(cwd) ??\n detectFromDrizzleConfig(cwd) ??\n detectFromDatabaseUrl(cwd)\n );\n}\n\n/** Read adapter type from a profiles.yml file for the given profile name. */\nfunction resolveProfileType(profilesPath: string, profileName: string): string | undefined {\n if (!existsSync(profilesPath)) return undefined;\n\n const content = readFileSync(profilesPath, 'utf8');\n const profiles = YAML.parse(content, { schema: 'failsafe' }) as Record<string, unknown>;\n const profile = profiles[profileName] as Record<string, unknown> | undefined;\n if (!profile?.outputs) return undefined;\n\n const outputs = profile.outputs as Record<string, Record<string, unknown>>;\n const targetName = typeof profile.target === 'string' ? profile.target : Object.keys(outputs)[0];\n if (!targetName) return undefined;\n\n const target = outputs[targetName];\n return typeof target?.type === 'string' ? target.type : undefined;\n}\n\n/** Signal 1: dbt profiles.yml → adapter type field. */\nfunction detectFromProfiles(cwd: string): string | undefined {\n const dbtProjectDirectory = findInTree(cwd, 'dbt_project.yml');\n if (!dbtProjectDirectory) return undefined;\n\n try {\n const projectContent = readFileSync(\n nodePath.join(dbtProjectDirectory, 'dbt_project.yml'),\n 'utf8',\n );\n const project = YAML.parse(projectContent, { schema: 'failsafe' }) as Record<string, unknown>;\n const profileName = project.profile;\n if (typeof profileName !== 'string') return undefined;\n\n // Search: project root → dbt/ subdir → ~/.dbt/ (dbt's standard fallback)\n const candidates = [\n nodePath.join(dbtProjectDirectory, 'profiles.yml'),\n nodePath.join(dbtProjectDirectory, 'dbt', 'profiles.yml'),\n nodePath.join(process.env.HOME ?? '', '.dbt', 'profiles.yml'),\n ];\n\n for (const profilesPath of candidates) {\n const adapterType = resolveProfileType(profilesPath, profileName);\n if (adapterType) return ADAPTER_TO_DIALECT[adapterType];\n }\n return undefined;\n } catch {\n return undefined;\n }\n}\n\n/** Signal 2: dbt-{adapter} packages in Python dependency files. */\nfunction detectFromPythonDependencies(cwd: string): string | undefined {\n const directory = findInTree(cwd, 'requirements.txt') ?? findInTree(cwd, 'pyproject.toml');\n if (!directory) return undefined;\n\n const requirementsPath = nodePath.join(directory, 'requirements.txt');\n const pyprojectPath = nodePath.join(directory, 'pyproject.toml');\n\n try {\n let content: string | undefined;\n if (existsSync(requirementsPath)) {\n content = readFileSync(requirementsPath, 'utf8');\n } else if (existsSync(pyprojectPath)) {\n content = readFileSync(pyprojectPath, 'utf8');\n }\n if (!content) return undefined;\n\n // Match dbt-{adapter} packages, skipping dbt-core (framework, not adapter)\n const adapters = content\n .matchAll(/dbt-(\\w+)/g)\n .map(m => m[1])\n .filter((a): a is string => a !== undefined && a !== 'core')\n .toArray();\n for (const adapter of adapters) {\n const dialect = ADAPTER_TO_DIALECT[adapter];\n if (dialect) return dialect;\n }\n return undefined;\n } catch {\n return undefined;\n }\n}\n\n/** Signal 3: sqlc config → engine field. */\nfunction detectFromSqlcConfig(cwd: string): string | undefined {\n for (const filename of ['sqlc.yaml', 'sqlc.yml', 'sqlc.json']) {\n const directory = findInTree(cwd, filename);\n if (!directory) continue;\n\n try {\n const content = readFileSync(nodePath.join(directory, filename), 'utf8');\n const match = /engine['\":\\s]+(\\w+)/.exec(content);\n if (match?.[1]) return ADAPTER_TO_DIALECT[match[1]] ?? match[1];\n } catch {\n continue;\n }\n }\n return undefined;\n}\n\n/** Signal 4: Prisma schema.prisma → provider field. */\nfunction detectFromPrismaSchema(cwd: string): string | undefined {\n const schemaPath = nodePath.join(cwd, 'prisma', 'schema.prisma');\n if (!existsSync(schemaPath)) return undefined;\n\n try {\n const content = readFileSync(schemaPath, 'utf8');\n const match = /provider\\s*=\\s*\"(\\w+)\"/.exec(content);\n if (!match?.[1]) return undefined;\n\n // Skip non-database providers (e.g., \"prisma-client-js\")\n return PROVIDER_TO_DIALECT[match[1]];\n } catch {\n return undefined;\n }\n}\n\n/** Signal 5: drizzle.config.ts → dialect field. */\nfunction detectFromDrizzleConfig(cwd: string): string | undefined {\n for (const filename of ['drizzle.config.ts', 'drizzle.config.js', 'drizzle.config.mjs']) {\n const filePath = nodePath.join(cwd, filename);\n if (!existsSync(filePath)) continue;\n\n try {\n const content = readFileSync(filePath, 'utf8');\n const match = /dialect\\s*:\\s*[\"'](\\w+)[\"']/.exec(content);\n if (match?.[1]) return DRIZZLE_TO_DIALECT[match[1]];\n } catch {\n continue;\n }\n }\n return undefined;\n}\n\n/** Signal 6: DATABASE_URL scheme in .env file. */\nfunction detectFromDatabaseUrl(cwd: string): string | undefined {\n const envPath = nodePath.join(cwd, '.env');\n if (!existsSync(envPath)) return undefined;\n\n try {\n const content = readFileSync(envPath, 'utf8');\n const match = /DATABASE_URL\\s*=\\s*[\"']?(\\w+):/.exec(content);\n if (!match?.[1]) return undefined;\n\n return SCHEME_TO_DIALECT[match[1]];\n } catch {\n return undefined;\n }\n}\n","/**\n * SQL Language Pack - Schema Definitions\n *\n * All SQL-specific file definitions and config generators.\n * Imported by schema.ts and spread into SAFEWORD_SCHEMA.\n */\n\nimport type { FileDefinition, ManagedFileDefinition, ProjectContext } from '../types.js';\nimport { detectSqlDialect } from './dialect.js';\n\n/**\n * Whether the host repo already owns SQL formatting via prettier-plugin-sql\n * declared in its root package.json (#636/#638). Setup then generates no\n * sqlfluff configs — safeword defers to the host's formatter, the same way it\n * defers to Biome/dprint for JS/TS. Declared deps only: a transitive copy in\n * node_modules is not ownership. Hook-side twin: hostFormatsSqlWithPrettier in\n * templates/hooks/lib/lint-config.ts (kept in sync by hand — src can't import\n * templates).\n */\nfunction hostOwnsSqlFormatting(ctx: ProjectContext): boolean {\n return (\n 'prettier-plugin-sql' in ctx.developmentDeps || 'prettier-plugin-sql' in ctx.productionDeps\n );\n}\n\n// ============================================================================\n// SQLFluff Configuration\n// ============================================================================\n\n/**\n * Shared SQLFluff rules for .safeword/sqlfluff.cfg.\n * Stricter rules for LLM enforcement — extends project config.\n */\nconst SQLFLUFF_STRICT_RULES = `[sqlfluff:rules:capitalisation.keywords]\ncapitalisation_policy = upper\n\n[sqlfluff:rules:capitalisation.identifiers]\ncapitalisation_policy = lower\n\n[sqlfluff:rules:capitalisation.functions]\ncapitalisation_policy = upper\n\n[sqlfluff:rules:capitalisation.literals]\ncapitalisation_policy = upper\n\n[sqlfluff:rules:capitalisation.types]\ncapitalisation_policy = upper\n\n[sqlfluff:rules:layout.long_lines]\nmax_line_length = 120`;\n\n// ============================================================================\n// Config Generators for .safeword/ (ownedFiles)\n// ============================================================================\n\n/**\n * Generate SQLFluff config for .safeword/sqlfluff.cfg.\n *\n * If project has existing config, extends it with stricter rules.\n * Otherwise generates standalone config.\n */\nfunction generateSqlfluffBaseConfig(\n existingSqlfluffConfig: string | undefined,\n dialect: string,\n): string {\n if (existingSqlfluffConfig) {\n // Don't emit dialect or templater — let customer's config provide them.\n // sqlfluff --config patches key-by-key, so omitting means customer's values survive.\n return `# Safeword SQLFluff config - adds stricter rules on top of project config\n# Used by hooks for LLM enforcement. Human pre-commits use project config.\n# Re-run \\`safeword install\\` to regenerate after project config changes.\n#\n# NOTE: Your dialect and templater are preserved. Safeword only adds style rules.\n\n[sqlfluff]\nwarnings =\n\n${SQLFLUFF_STRICT_RULES}\n`;\n }\n\n return `# Generated by safeword - DO NOT EDIT\n# Customize by creating .sqlfluff at project root\n\n[sqlfluff]\ndialect = ${dialect}\ntemplater = jinja\nmax_line_length = 120\nwarnings =\n\n[sqlfluff:templater:jinja]\napply_dbt_builtins = True\n\n${SQLFLUFF_STRICT_RULES}\n`;\n}\n\n// ============================================================================\n// Owned Files (overwritten on upgrade)\n// ============================================================================\n\nexport const sqlOwnedFiles: Record<string, FileDefinition> = {\n '.safeword/sqlfluff.cfg': {\n generator: ctx =>\n ctx.languages?.sql && !hostOwnsSqlFormatting(ctx)\n ? generateSqlfluffBaseConfig(\n ctx.projectType.existingSqlfluffConfig,\n detectSqlDialect(ctx.cwd) ?? 'ansi',\n )\n : undefined,\n },\n};\n\n// ============================================================================\n// Config Generators for project root (managedFiles)\n// ============================================================================\n\nfunction generateProjectSqlfluffConfig(dialect: string): string {\n return `# Generated by safeword\n# Add your project-specific overrides here.\n# Strict rules for LLM enforcement are in .safeword/sqlfluff.cfg\n\n[sqlfluff]\ndialect = ${dialect}\ntemplater = jinja\nmax_line_length = 120\n\n[sqlfluff:templater:jinja]\napply_dbt_builtins = True\n`;\n}\n\n// ============================================================================\n// Managed Files (create if missing, reconciled on reset/upgrade)\n// ============================================================================\n\nexport const sqlManagedFiles: Record<string, ManagedFileDefinition> = {\n '.sqlfluff': {\n generator: ctx =>\n ctx.languages?.sql && !ctx.projectType.existingSqlfluffConfig && !hostOwnsSqlFormatting(ctx)\n ? generateProjectSqlfluffConfig(detectSqlDialect(ctx.cwd) ?? 'ansi')\n : undefined,\n },\n};\n","/**\n * Helpers shared by `JsonMergeDefinition.unmerge` implementations.\n */\n\n/**\n * Assign `value` to `target[key]`, or delete the key when `value` has no\n * remaining entries. Unmerge functions strip safeword's managed keys out of a\n * nested object (scripts, hooks, mcpServers, …) and then must either write the\n * trimmed object back or drop the now-empty container entirely. Returns whether\n * the key was kept, so callers can prune sibling keys that only make sense when\n * the container survives (e.g. `.cursor/hooks.json`'s `version`).\n */\nexport function assignOrPrune(\n target: Record<string, unknown>,\n key: string,\n value: Record<string, unknown>,\n): boolean {\n if (Object.keys(value).length > 0) {\n target[key] = value;\n return true;\n }\n Reflect.deleteProperty(target, key);\n return false;\n}\n","/**\n * TypeScript/JavaScript Language Pack - Schema Definitions\n *\n * All JS/TS specific file definitions, JSON merges, and packages.\n * Imported by schema.ts and spread into SAFEWORD_SCHEMA.\n *\n * Note: Generator functions return `string | undefined` by design (undefined = skip file).\n * This conflicts with sonarjs/no-inconsistent-returns vs unicorn/no-useless-undefined (#1199).\n * Inline disables target only generator arrow functions, not regular functions in this file.\n */\n\nimport {\n dirGlobExcludeMerge,\n resolvedIgnoreDirectories,\n resolvedNamespaceDirectory,\n} from '../../owned-paths.js';\nimport { getEslintConfig, getSafewordEslintConfig } from '../../templates/config.js';\nimport { assignOrPrune } from '../../utils/json-merge.js';\nimport type {\n FileDefinition,\n JsonMergeDefinition,\n ManagedFileDefinition,\n ProjectContext,\n} from '../types.js';\n\n// Deliberately duplicated with presets/typescript/detect.ts: published presets must\n// remain self-contained, while language packs may not import preset implementation.\nconst SAFEWORD_PRIMARY_LINT_SCRIPT = 'eslint . && bun run lint:gherkin';\n\n// ============================================================================\n// Shared Definitions\n// ============================================================================\n\n/**\n * Add framework-specific ignores to Knip config.\n */\nfunction addKnipIgnores(config: { ignore: string[] }, ctx: ProjectContext): void {\n const allDependencies = ctx.developmentDeps;\n\n // Framework build/cache directories\n if (ctx.projectType.nextjs) config.ignore.push('.next/**');\n if (ctx.projectType.astro) config.ignore.push('.astro/**');\n if ('storybook' in allDependencies || '@storybook/react' in allDependencies) {\n config.ignore.push('.storybook/**', 'storybook-static/**');\n }\n if ('turbo' in allDependencies) config.ignore.push('.turbo/**');\n\n // Electron - Knip has no Electron plugin\n if ('electron' in allDependencies || 'electron' in ctx.productionDeps) {\n config.ignore.push('electron/**', 'dist-electron/**', 'out/**');\n }\n}\n\n/**\n * Add framework-specific ignoreDependencies to Knip config.\n */\nfunction addKnipIgnoreDependencies(\n config: { ignoreDependencies: string[] },\n ctx: ProjectContext,\n): void {\n const allDependencies = ctx.developmentDeps;\n\n // Dependencies used via config files, not imports\n if (ctx.projectType.tailwind) {\n config.ignoreDependencies.push('tailwindcss', '@tailwindcss/typography', '@tailwindcss/forms');\n }\n if (ctx.projectType.playwright) config.ignoreDependencies.push('@playwright/test');\n if ('husky' in allDependencies) config.ignoreDependencies.push('husky');\n if ('lint-staged' in allDependencies) config.ignoreDependencies.push('lint-staged');\n\n // Electron ecosystem packages\n if ('electron' in allDependencies || 'electron' in ctx.productionDeps) {\n config.ignoreDependencies.push(\n 'electron',\n 'electron-builder',\n 'electron-updater',\n 'electron-devtools-installer',\n 'electron-is-dev',\n 'electron-store',\n );\n }\n}\n\n/**\n * Generate Knip config based on project type.\n * Adds framework-specific ignores and ignoreDependencies.\n * Knip plugins auto-enable based on deps, so we just configure ignore patterns.\n */\nfunction getKnipConfig(ctx: ProjectContext): object {\n // A custom paths.projectRoot is added alongside the two well-known roots so\n // Knip doesn't scan (and false-positive on) the custom namespace dir (#273).\n // NB: Knip's ignore is intentionally just the namespace roots, not the full\n // safewordIgnoreDirectories/resolvedIgnoreDirectories list — so resolve the\n // custom root directly here rather than reusing that composer.\n const customRoot = resolvedNamespaceDirectory(ctx);\n const config = {\n ignore: [\n '.safeword/**',\n '.project/**',\n '.safeword-project/**',\n ...(customRoot === undefined ? [] : [`${customRoot}/**`]),\n ],\n ignoreDependencies: ['safeword', 'dependency-cruiser'],\n };\n\n addKnipIgnores(config, ctx);\n addKnipIgnoreDependencies(config, ctx);\n\n return config;\n}\n\n/**\n * Prettier styling defaults - shared between .safeword/.prettierrc and root .prettierrc\n */\nconst PRETTIER_DEFAULTS = {\n semi: true,\n singleQuote: true,\n tabWidth: 2,\n trailingComma: 'all',\n printWidth: 100,\n endOfLine: 'lf',\n useTabs: false,\n bracketSpacing: true,\n arrowParens: 'avoid',\n} as const;\n\n/**\n * Get Prettier plugins based on project type.\n * Tailwind plugin must be last for proper class sorting.\n */\nfunction getPrettierPlugins(projectType: {\n astro?: boolean;\n shell?: boolean;\n tailwind?: boolean;\n}): string[] {\n const plugins: string[] = [];\n if (projectType.astro) plugins.push('prettier-plugin-astro');\n if (projectType.shell) plugins.push('prettier-plugin-sh');\n if (projectType.tailwind) plugins.push('prettier-plugin-tailwindcss');\n return plugins;\n}\n\n/**\n * Biome config merge - adds safeword files to excludes list.\n * Biome v2 uses `includes` with `!` prefix for exclusions.\n */\nconst BIOME_JSON_MERGE: JsonMergeDefinition = {\n keys: ['files.includes'],\n skipIfMissing: true, // Only modify if project already uses Biome\n merge: (existing, ctx) => {\n const files = (existing.files as Record<string, unknown>) ?? {};\n const existingIncludes = Array.isArray(files.includes) ? files.includes : [];\n\n // Add safeword exclusions (! prefix) if not already present, sourced from\n // the single SAFEWORD_IGNORE_DIRS list (ticket EYRK34) so Biome skips every\n // safeword-owned dir, not just .safeword/ — including a custom paths.projectRoot\n // (issue #273). Biome v2.2.0+ doesn't need /**.\n const safewordExcludes = [\n '!eslint.config.mjs',\n ...resolvedIgnoreDirectories(ctx).map(dir => `!${dir}`),\n ];\n const newIncludes = [...existingIncludes];\n for (const exclude of safewordExcludes) {\n if (!newIncludes.includes(exclude)) {\n newIncludes.push(exclude);\n }\n }\n\n return {\n ...existing,\n files: {\n ...files,\n includes: newIncludes,\n },\n };\n },\n unmerge: (existing, ctx) => {\n const files = (existing.files as Record<string, unknown>) ?? {};\n const existingIncludes = Array.isArray(files.includes) ? files.includes : [];\n\n // Remove safeword exclusions from includes list (current set + the legacy\n // '!.safeword/**' folder form, cleaned up on unmerge). Mirrors merge, so a\n // custom paths.projectRoot exclusion is also removed (issue #273).\n const safewordExcludes = new Set([\n '!eslint.config.mjs',\n '!.safeword/**',\n ...resolvedIgnoreDirectories(ctx).map(dir => `!${dir}`),\n ]);\n const cleanedIncludes = existingIncludes.filter(\n (entry: string) => !safewordExcludes.has(entry),\n );\n\n // Build cleaned files object\n const cleanedFiles = { ...files };\n if (cleanedIncludes.length > 0) {\n cleanedFiles.includes = cleanedIncludes;\n } else {\n delete cleanedFiles.includes;\n }\n\n // Remove files key entirely if empty\n if (Object.keys(cleanedFiles).length === 0) {\n const result = { ...existing };\n delete result.files;\n return result;\n }\n\n return { ...existing, files: cleanedFiles };\n },\n};\n\n// dprint's `excludes` and oxfmt's `ignorePatterns` both take a glob list (EYRK34).\nconst DPRINT_JSON_MERGE = dirGlobExcludeMerge('excludes');\nconst OXFMT_JSON_MERGE = dirGlobExcludeMerge('ignorePatterns');\n\n// ============================================================================\n// Owned Files (overwritten on upgrade)\n// ============================================================================\n\nexport const typescriptOwnedFiles: Record<string, FileDefinition> = {\n // Language-specific safeword configs for hooks (extend project configs if they exist)\n // These configs are used by hooks for LLM enforcement with stricter rules\n '.safeword/eslint.config.mjs': {\n generator: ctx =>\n ctx.languages?.javascript\n ? getSafewordEslintConfig(\n ctx.projectType.existingEslintConfig,\n ctx.projectType.existingFormatter,\n )\n : undefined,\n },\n\n '.safeword/.prettierrc': {\n // eslint-disable-next-line sonarjs/no-inconsistent-returns -- generator returns undefined to skip file\n generator: ctx => {\n // Skip for non-JS projects, projects with an alternative formatter (Biome,\n // etc.), or projects that already have their own prettier config — writing\n // our own would shadow a config we can't merge into.\n if (\n !ctx.languages?.javascript ||\n ctx.projectType.existingFormatter ||\n ctx.projectType.existingPrettierConfig\n ) {\n return;\n }\n // Add plugins based on project type\n const plugins = getPrettierPlugins(ctx.projectType);\n const config = plugins.length > 0 ? { ...PRETTIER_DEFAULTS, plugins } : PRETTIER_DEFAULTS;\n return JSON.stringify(config, undefined, 2);\n },\n },\n};\n\n// ============================================================================\n// Managed Files (create if missing, update if matches template)\n// ============================================================================\n\nexport const typescriptManagedFiles: Record<string, ManagedFileDefinition> = {\n // Project-level ESLint config (created only if no existing ESLint config)\n 'eslint.config.mjs': {\n // eslint-disable-next-line sonarjs/no-inconsistent-returns -- generator returns undefined to skip file\n generator: ctx => {\n // Skip if project already has ESLint config (safeword will use .safeword/eslint.config.mjs)\n if (ctx.projectType.existingEslintConfig) return;\n if (!ctx.languages?.javascript) return;\n return getEslintConfig(ctx.projectType.existingFormatter);\n },\n },\n // Minimal tsconfig for ESLint type-checked linting (only if missing)\n 'tsconfig.json': {\n // eslint-disable-next-line sonarjs/no-inconsistent-returns -- generator returns undefined to skip file\n generator: ctx => {\n // Skip for non-JS projects (Python-only)\n if (!ctx.languages?.javascript) return;\n // Only create for TypeScript projects\n if (!ctx.developmentDeps.typescript && !ctx.developmentDeps['typescript-eslint']) {\n return;\n }\n return JSON.stringify(\n {\n compilerOptions: {\n target: 'ES2022',\n module: 'NodeNext',\n moduleResolution: 'NodeNext',\n strict: true,\n esModuleInterop: true,\n skipLibCheck: true,\n noEmit: true,\n },\n include: ['**/*.ts', '**/*.tsx'],\n exclude: ['node_modules', 'dist', 'build'],\n },\n undefined,\n 2,\n );\n },\n },\n // Knip config for dead code detection (used by /audit)\n // Plugins auto-enable based on deps, we just configure ignore patterns\n 'knip.json': {\n generator: ctx =>\n ctx.projectType?.hasJsSource ? JSON.stringify(getKnipConfig(ctx), undefined, 2) : undefined,\n },\n // Project-level Prettier config (created only if no existing formatter)\n '.prettierrc': {\n // eslint-disable-next-line sonarjs/no-inconsistent-returns -- generator returns undefined to skip file\n generator: ctx => {\n // Skip for non-JS projects, projects with an alternative formatter, or\n // projects that already have their own prettier config — a new .prettierrc\n // resolves ahead of prettier.config.* and would silently shadow it.\n if (!ctx.languages?.javascript) return;\n if (ctx.projectType.existingFormatter) return;\n if (ctx.projectType.existingPrettierConfig) return;\n // Create base config with styling defaults (no plugins - those are in .safeword/.prettierrc)\n return JSON.stringify(PRETTIER_DEFAULTS, undefined, 2);\n },\n },\n};\n\n// ============================================================================\n// JSON Merges\n// ============================================================================\n\n/**\n * Add a script if it doesn't exist.\n */\nfunction addScriptIfMissing(scripts: Record<string, string>, name: string, command: string): void {\n const existing = scripts[name];\n if (!existing) scripts[name] = command;\n}\n\nconst GHERKIN_LINT_SCRIPT = 'safeword project lint-gherkin';\n\n/**\n * Merge lint scripts based on project type.\n */\nfunction mergeLintScripts(\n scripts: Record<string, string>,\n projectType: { existingLinter: boolean },\n): void {\n addScriptIfMissing(scripts, 'lint:gherkin', GHERKIN_LINT_SCRIPT);\n if (projectType.existingLinter) {\n // Project with existing linter: add lint:eslint for safeword-specific rules\n addScriptIfMissing(scripts, 'lint:eslint', 'eslint .');\n } else {\n // No existing linter: ESLint is the primary linter\n addScriptIfMissing(scripts, 'lint', SAFEWORD_PRIMARY_LINT_SCRIPT);\n }\n}\n\n/**\n * Merge format scripts if no existing formatter.\n */\nfunction mergeFormatScripts(\n scripts: Record<string, string>,\n projectType: { existingFormatter: boolean },\n): void {\n if (projectType.existingFormatter) return;\n addScriptIfMissing(scripts, 'format', 'prettier --write .');\n addScriptIfMissing(scripts, 'format:check', 'prettier --check .');\n}\n\nexport const typescriptJsonMerges: Record<string, JsonMergeDefinition> = {\n 'package.json': {\n keys: [\n 'scripts.lint',\n 'scripts.lint:gherkin',\n 'scripts.format',\n 'scripts.format:check',\n 'scripts.test:bdd',\n ],\n skipIfMissing: true, // Setup creates package.json first (ensurePackageJson), so this only skips outside setup\n conditionalKeys: {\n existingLinter: ['scripts.lint:eslint'], // Projects with existing linter get separate ESLint script\n publishableLibrary: ['scripts.publint'],\n shell: ['scripts.lint:sh'],\n hasJsSource: ['scripts.knip'], // knip script only added for repos with real JS source (BE7C7B)\n },\n merge: (existing, ctx) => {\n const scripts = { ...(existing.scripts as Record<string, string>) };\n const result = { ...existing };\n\n mergeLintScripts(scripts, ctx.projectType);\n mergeFormatScripts(scripts, ctx.projectType);\n // knip is JS-app dead-code detection — only for repos with real JS source (BE7C7B).\n if (ctx.projectType.hasJsSource) addScriptIfMissing(scripts, 'knip', 'knip');\n // BDD acceptance lane (ticket 102b) — add-if-absent: an existing\n // customer test:bdd script always wins. Suppressed entirely when the\n // lane isn't safeword's to scaffold (56JCFZ).\n if (ctx.projectType.scaffoldBddLane) {\n addScriptIfMissing(scripts, 'test:bdd', 'cucumber-js');\n }\n\n // Conditional scripts based on project type\n if (ctx.projectType.publishableLibrary) {\n addScriptIfMissing(scripts, 'publint', 'publint');\n }\n if (ctx.projectType.shell) {\n addScriptIfMissing(\n scripts,\n 'lint:sh',\n \"if command -v shellcheck >/dev/null 2>&1; then shellcheck **/*.sh; else echo 'shellcheck not installed; skipping'; fi\",\n );\n }\n\n result.scripts = scripts;\n return result;\n },\n unmerge: (existing, _ctx) => {\n const result = { ...existing };\n const scripts = { ...(existing.scripts as Record<string, string>) };\n\n // Remove safeword-specific scripts but preserve lint/format (useful standalone)\n delete scripts['lint:eslint']; // Biome hybrid mode\n delete scripts['lint:sh'];\n delete scripts['format:check'];\n delete scripts.knip;\n delete scripts.publint;\n delete scripts['test:bdd'];\n\n assignOrPrune(result, 'scripts', scripts);\n return result;\n },\n },\n\n // Prettier config — adds safeword's plugins (and, greenfield only, its style\n // defaults) to safeword's OWN `.prettierrc`. A customer who already owns a\n // prettier config is left untouched — see the existingPrettierConfig gate below.\n '.prettierrc': {\n keys: ['plugins'],\n skipIfMissing: true,\n merge: (existing, ctx) => {\n // A customer who already owns a prettier config keeps it exactly as-is:\n // filling in safeword's style defaults or injecting plugins changes the\n // resolved style and churns their files on the next prettier run (ticket\n // 9C2CFX — revisits 8BNSTE's \"the additive merge is safe\" call). Only a\n // greenfield install, where safeword wrote this `.prettierrc` itself and\n // existingPrettierConfig is false, gets safeword's plugins.\n if (ctx.projectType.existingPrettierConfig) return existing;\n\n const result = { ...existing } as Record<string, unknown>;\n\n // Add defaults for missing styling options (preserves user customizations)\n for (const [key, value] of Object.entries(PRETTIER_DEFAULTS)) {\n if (result[key] === undefined) {\n result[key] = value;\n }\n }\n\n // Merge plugins: preserve user's plugins + add safeword's\n const safewordPlugins = getPrettierPlugins(ctx.projectType);\n const existingPlugins = Array.isArray(result.plugins) ? (result.plugins as string[]) : [];\n\n // Combine existing + safeword plugins (deduplicated)\n const allPlugins = [...existingPlugins];\n for (const plugin of safewordPlugins) {\n if (!allPlugins.includes(plugin)) {\n allPlugins.push(plugin);\n }\n }\n\n // Ensure tailwind plugin is always last (required for proper class sorting)\n const tailwindIndex = allPlugins.indexOf('prettier-plugin-tailwindcss');\n if (tailwindIndex !== -1 && tailwindIndex !== allPlugins.length - 1) {\n allPlugins.splice(tailwindIndex, 1);\n allPlugins.push('prettier-plugin-tailwindcss');\n }\n\n if (allPlugins.length > 0) {\n result.plugins = allPlugins;\n } else {\n delete result.plugins;\n }\n\n return result;\n },\n unmerge: (existing, ctx) => {\n const result = { ...existing } as Record<string, unknown>;\n // Only remove safeword's plugins, preserve user's custom plugins\n const safewordPlugins = new Set(getPrettierPlugins(ctx.projectType));\n if (Array.isArray(result.plugins)) {\n const remaining = (result.plugins as string[]).filter(p => !safewordPlugins.has(p));\n if (remaining.length > 0) {\n result.plugins = remaining;\n } else {\n delete result.plugins;\n }\n }\n return result;\n },\n },\n\n // Biome excludes - add safeword files so they don't get linted by Biome/Ultracite\n // Biome v2 uses `includes` with `!` prefix for exclusions (not a separate `ignore` key)\n // Support both biome.json and biome.jsonc\n 'biome.json': BIOME_JSON_MERGE,\n 'biome.jsonc': BIOME_JSON_MERGE,\n\n // dprint excludes - add safeword-owned dirs so a customer's dprint fmt skips them.\n 'dprint.json': DPRINT_JSON_MERGE,\n '.dprint.json': DPRINT_JSON_MERGE,\n 'dprint.jsonc': DPRINT_JSON_MERGE,\n '.dprint.jsonc': DPRINT_JSON_MERGE,\n\n // oxfmt ignorePatterns - JSON config forms only (oxfmt.config.* modules can't be\n // merged, like prettier.config.*); customers on those add the excludes themselves.\n '.oxfmtrc.json': OXFMT_JSON_MERGE,\n '.oxfmtrc.jsonc': OXFMT_JSON_MERGE,\n};\n\n// ============================================================================\n// Packages\n// ============================================================================\n\n// Default new installs to ESLint 10 — safeword's peer range is `^9.22.0 || ^10.0.0`\n// since v0.52.0, and the plugin-ecosystem blocker that pinned this to v9 is resolved.\n// Existing customers are NOT bumped: reconcile skips packages already installed, so\n// this only affects fresh setups. v10 keeps the `eslint/config` defineConfig helper\n// used in generated configs.\nexport const ESLINT_PACKAGE = 'eslint@^10.0.0';\nexport const JITI_PACKAGE = 'jiti@^2.2.0';\n\nexport const typescriptPackages = {\n base: [\n // Core tools (always needed for JS/TS — eslint/prettier also lint the BDD lane's .ts step files)\n ESLINT_PACKAGE,\n // Safeword (bundles eslint-config-prettier + all ESLint plugins)\n 'safeword',\n // Generated .safeword/eslint.config.mjs uses jiti to load eslint.config.ts.\n JITI_PACKAGE,\n ],\n conditional: {\n // BDD acceptance lane (ticket 102b) — cucumber-js runs the scaffolded\n // .feature files; tsx transpiles the TypeScript step definitions, and\n // @types/node lets the scaffolded steps (node: imports) pass typechecks.\n // Keyed on ProjectType.scaffoldBddLane: suppressed when the repo has its\n // own cucumber harness and safeword's lane is absent (56JCFZ).\n scaffoldBddLane: ['@cucumber/cucumber', 'tsx', '@types/node'],\n // Prettier (only for projects without existing formatter)\n standard: ['prettier'], // \"standard\" = !existingFormatter\n // Prettier plugins (only for projects without existing formatter that need them)\n astro: ['prettier-plugin-astro'],\n tailwind: ['prettier-plugin-tailwindcss'],\n shell: ['prettier-plugin-sh'],\n // Non-ESLint tools\n publishableLibrary: ['publint'],\n // Legacy ESLint config compat (needed when extending .eslintrc.* configs)\n legacyEslint: ['@eslint/eslintrc'],\n // Architecture + dead-code tools (used by /audit) — these scan JS APPLICATION\n // code/deps, so only for repos with real JS source, not a non-JS repo carrying\n // just the TS BDD lane (BE7C7B).\n hasJsSource: ['dependency-cruiser', 'knip'],\n },\n};\n","export interface CursorCommandWrapper {\n readonly name: string;\n readonly description: string;\n readonly skillPath: string;\n}\n\nexport interface CursorRuleWrapper {\n readonly name: string;\n readonly alwaysApply: boolean;\n readonly description?: string;\n readonly frontmatterOrder?: 'description-first';\n readonly globs?: readonly string[];\n readonly referencePath: string;\n readonly skill?: string;\n}\n\nexport interface SkillCursorPair {\n readonly skill: string;\n readonly cursorRules: readonly string[] | undefined;\n}\n\ninterface FrontmatterField {\n readonly key: string;\n readonly value: string | boolean | readonly string[];\n}\n\nconst CURSOR_ACTION_SKILLS = [\n 'lint',\n 'verify',\n 'closeout',\n 'audit',\n 'explain',\n 'cleanup-zombies',\n 'self-review',\n 'review-spec',\n 'retro',\n 'spike',\n] as const;\n\n// Shared verbatim by a skill's command wrapper and its rule wrapper.\nconst DEBUG_DESCRIPTION =\n \"Finds the real cause of a bug, in four steps, before you touch a fix. Use when encountering bugs, test failures, unexpected behavior, or when previous fix attempts failed. Enforces investigate-first discipline ('debug this', 'fix this error', 'test is failing', 'not working').\";\n\nconst REFACTOR_DESCRIPTION =\n \"Systematic refactoring with small-step discipline. Use when user says 'refactor', 'clean up', 'restructure', 'extract', 'rename', 'simplify', or mentions code smells. Enforces one change → test → commit when the commit can stay scoped. For structural improvements, NOT style/formatting (use /lint). NOT for adding features or fixing bugs.\";\n\nexport const CURSOR_COMMAND_WRAPPERS: readonly CursorCommandWrapper[] = [\n {\n name: 'bdd',\n description:\n \"BDD orchestrator for feature-level work. Use when user says 'add', 'implement', 'build', 'feature', 'iteration', 'story', 'phase', 'resume', 'continue', or references a ticket/iteration/story. Also use when work touches 3+ files with new state/flows, or when user runs /bdd. Do NOT use for bug fixes, typos, config changes, or 1-2 file tasks.\",\n skillPath: 'bdd/SKILL.md',\n },\n {\n name: 'debug',\n description: DEBUG_DESCRIPTION,\n skillPath: 'debug/SKILL.md',\n },\n {\n name: 'quality-review',\n description:\n \"Deep code review with web research. Use when the user says 'double check against latest', 'verify versions', or 'check security'. Adds live research on top of the automatic quality hook — confirms you're using current library versions and APIs, not stale ones.\",\n skillPath: 'quality-review/SKILL.md',\n },\n {\n name: 'finish-review',\n description:\n \"Internal fallback used only right after the shared review coordinator reports it's run out of reviewer routes. Not something a user invokes directly.\",\n skillPath: 'finish-review/SKILL.md',\n },\n {\n name: 'audit',\n description: 'Run comprehensive code audit for architecture, dead code, and test quality',\n skillPath: 'audit/SKILL.md',\n },\n {\n name: 'closeout',\n description:\n \"Close a completed local delivery safely after verification. Use when wrapping up a finished coding session: merging only when you've been explicitly told to merge, running the retro, and cleaning up the exact merged branch and worktree.\",\n skillPath: 'closeout/SKILL.md',\n },\n {\n name: 'refactor',\n description: REFACTOR_DESCRIPTION,\n skillPath: 'refactor/SKILL.md',\n },\n {\n name: 'retro',\n description:\n 'Run a safeword retrospective on the current session on demand — mine the transcript for friction (bugs / rough edges / gaps) and submit it through the outbound safety check before filing upstream. Use when the user says \"run a retro\", \"/retro\", or wants to capture friction before the session ends.',\n skillPath: 'retro/SKILL.md',\n },\n {\n name: 'spike',\n description:\n 'Run a quick, throwaway experiment to answer one open technical question before committing to the real build. Only runs when you ask for it directly.',\n skillPath: 'spike/SKILL.md',\n },\n {\n name: 'testing',\n description: 'How to write good tests — quality knowledge for any testing context',\n skillPath: 'testing/SKILL.md',\n },\n] as const;\n\nexport const CURSOR_RULE_WRAPPERS: readonly CursorRuleWrapper[] = [\n {\n name: 'safeword-core',\n alwaysApply: true,\n referencePath: '.safeword/SAFEWORD.md',\n },\n {\n name: 'safeword-brainstorming',\n alwaysApply: false,\n description:\n \"Collaborative brainstorming and rubber-ducking — divergence-first thinking partner. Use when the user wants to explore options, weigh approaches, or think through uncertainty before committing to a direction ('brainstorm', 'rubber duck', 'help me think', 'explore options', 'what are the tradeoffs').\",\n referencePath: '.safeword/skills/brainstorm/SKILL.md',\n skill: 'brainstorm',\n },\n {\n name: 'safeword-debugging',\n alwaysApply: false,\n description: DEBUG_DESCRIPTION,\n referencePath: '.safeword/skills/debug/SKILL.md',\n skill: 'debug',\n },\n {\n name: 'safeword-elicitation',\n alwaysApply: false,\n description:\n \"Extract tacit knowledge through non-obvious microquestions — things only the user knows that can't be found in code, docs, or research. Use when about to guess at intent, context, or constraints, or when user says 'ask me', 'what do you need to know', 'what's missing'. Skips questions answerable by reading the codebase or searching the web.\",\n referencePath: '.safeword/skills/elicit/SKILL.md',\n skill: 'elicit',\n },\n {\n name: 'safeword-figure-it-out',\n alwaysApply: false,\n description:\n 'Explore and debate options with fresh documentation and research before committing. Use when facing a real decision with multiple plausible approaches — library/framework choice, architecture call, API or schema design, algorithm selection. Looks up current docs and recent research, weighs options on correctness and elegance, and resists bloat.',\n referencePath: '.safeword/skills/figure-it-out/SKILL.md',\n skill: 'figure-it-out',\n },\n {\n name: 'safeword-finish-review',\n alwaysApply: false,\n description:\n \"Internal fallback used only right after the shared review coordinator reports it's run out of reviewer routes. Not something a user invokes directly.\",\n referencePath: '.safeword/skills/finish-review/SKILL.md',\n skill: 'finish-review',\n },\n {\n name: 'safeword-quality-reviewing',\n alwaysApply: false,\n description:\n \"Deep quality review of any work-product — code, docs, specs, plans, decisions — with web research. Use when explicitly verifying against latest docs ('double check against latest', 'verify versions', 'check security'), pressure-testing correctness and elegance, or needing deeper analysis beyond the automatic hook. Fetches current sources, checks versions and claims, and weighs alternatives.\",\n referencePath: '.safeword/skills/quality-review/SKILL.md',\n skill: 'quality-review',\n },\n {\n name: 'safeword-refactoring',\n alwaysApply: false,\n description: REFACTOR_DESCRIPTION,\n referencePath: '.safeword/skills/refactor/SKILL.md',\n skill: 'refactor',\n },\n {\n name: 'safeword-tdd-review',\n alwaysApply: false,\n description:\n \"Step-aware quality review at TDD phase boundaries — review test quality after RED, implementation correctness after GREEN, completed scenario after REFACTOR. Use when user says 'review my test', 'review my implementation', 'is this GREEN solid?', or just finished a TDD step. (Note: Claude Code triggers this automatically via the phase-tracking hook; Cursor users must invoke explicitly.)\",\n referencePath: '.safeword/skills/tdd-review/SKILL.md',\n skill: 'tdd-review',\n },\n {\n name: 'safeword-testing',\n alwaysApply: false,\n description:\n \"How to write good tests. Use when writing tests in any context — 'write tests', 'add tests', 'test this', 'need tests for', 'improve coverage'. Also consult when writing tests during BDD or debugging. Core knowledge for test quality across all workflows.\",\n referencePath: '.safeword/skills/testing/SKILL.md',\n skill: 'testing',\n },\n {\n name: 'safeword-ticket-system',\n alwaysApply: false,\n description:\n 'Ticket system and work logs for context anchoring during complex work. Use when creating tickets, managing work logs, referencing ticket IDs, or when work needs context anchoring (multi-step tasks, debugging, investigation).',\n globs: ['.project/tickets/**', '.safeword-project/tickets/**', '.safeword/logs/**'],\n referencePath: '.safeword/skills/ticket-system/SKILL.md',\n skill: 'ticket-system',\n },\n {\n name: 'safeword-retro-filer',\n alwaysApply: false,\n description:\n \"Files Safeword's sanitized spooled retrospective drafts to its upstream tracker. Use only when a trusted Safeword Stop continuation or authenticated closeout cleanup guard output names a spool path. Do not use for ordinary retros, project issues, or user-authored drafts.\",\n referencePath: '.safeword/skills/retro-filer/SKILL.md',\n skill: 'retro-filer',\n },\n {\n name: 'bdd-core',\n alwaysApply: false,\n frontmatterOrder: 'description-first',\n description:\n \"USE WHEN starting feature work, running /bdd, resuming a BDD ticket, or user says 'add', 'implement', 'build', 'feature', 'resume', 'continue'. Orchestrates BDD phases.\",\n referencePath: '.safeword/skills/bdd/SKILL.md',\n skill: 'bdd',\n },\n {\n name: 'bdd-discovery',\n alwaysApply: false,\n frontmatterOrder: 'description-first',\n description:\n 'USE WHEN in BDD intake phase OR ticket has phase:intake. Guides discovery and context gathering for features.',\n referencePath: '.safeword/skills/bdd/DISCOVERY.md',\n skill: 'bdd',\n },\n {\n name: 'bdd-scenarios',\n alwaysApply: false,\n frontmatterOrder: 'description-first',\n description:\n 'USE WHEN in BDD define-behavior or scenario-gate phase. Guides Given/When/Then scenario creation and validation.',\n referencePath: '.safeword/skills/bdd/SCENARIOS.md',\n skill: 'bdd',\n },\n {\n name: 'bdd-plan-implementation',\n alwaysApply: false,\n frontmatterOrder: 'description-first',\n description:\n 'USE WHEN in BDD plan-implementation phase. Author impl-plan.md, run figure-it-out on load-bearing choices, ADR lifecycle, review before implement.',\n referencePath: '.safeword/skills/bdd/PLAN_IMPLEMENTATION.md',\n skill: 'bdd',\n },\n {\n name: 'bdd-tdd',\n alwaysApply: false,\n frontmatterOrder: 'description-first',\n description: 'USE WHEN in BDD implement phase. RED/GREEN TDD cycle; run /refactor after GREEN.',\n referencePath: '.safeword/skills/bdd/TDD.md',\n skill: 'bdd',\n },\n {\n name: 'bdd-verify',\n alwaysApply: false,\n frontmatterOrder: 'description-first',\n description:\n 'USE WHEN in BDD verify phase OR all scenarios marked [x]. Evidence gate — cross-scenario refactor, then /verify and /audit.',\n referencePath: '.safeword/skills/bdd/VERIFY.md',\n skill: 'bdd',\n },\n {\n name: 'bdd-done',\n alwaysApply: false,\n frontmatterOrder: 'description-first',\n description:\n 'USE WHEN in BDD done phase (verify.md exists). Close the ticket — verification already happened in verify.',\n referencePath: '.safeword/skills/bdd/DONE.md',\n skill: 'bdd',\n },\n {\n name: 'bdd-splitting',\n alwaysApply: false,\n frontmatterOrder: 'description-first',\n description:\n 'USE WHEN BDD thresholds exceeded (2+ stories, >15 scenarios, >20 tasks). Split protocol and examples.',\n referencePath: '.safeword/skills/bdd/SPLITTING.md',\n skill: 'bdd',\n },\n] as const;\n\nfunction cursorRuleSkillPairs(): SkillCursorPair[] {\n const skillRules = new Map<string, string[]>();\n\n for (const wrapper of CURSOR_RULE_WRAPPERS) {\n if (wrapper.skill === undefined) continue;\n\n const rules = skillRules.get(wrapper.skill);\n if (rules === undefined) {\n skillRules.set(wrapper.skill, [wrapper.name]);\n continue;\n }\n\n rules.push(wrapper.name);\n }\n\n return [...skillRules].map(([skill, cursorRules]) => ({ skill, cursorRules }));\n}\n\nexport const SKILL_CURSOR_PAIRS: readonly SkillCursorPair[] = [\n ...cursorRuleSkillPairs(),\n ...CURSOR_ACTION_SKILLS.map(skill => ({ skill, cursorRules: undefined })),\n];\n\nfunction renderFrontmatter({ fields }: { readonly fields: readonly FrontmatterField[] }): string {\n const lines = fields.flatMap(field => {\n if (Array.isArray(field.value)) {\n return [`${field.key}:`, ...field.value.map(item => ` - ${item}`)];\n }\n\n return [`${field.key}: ${field.value}`];\n });\n\n return `---\\n${lines.join('\\n')}\\n---`;\n}\n\nexport function renderCursorCommandWrapper({\n wrapper,\n}: {\n readonly wrapper: CursorCommandWrapper;\n}): string {\n return `${renderFrontmatter({\n fields: [{ key: 'description', value: wrapper.description }],\n })}\n\nRead and follow the instructions in .safeword/skills/${wrapper.skillPath}\n`;\n}\n\nexport function renderCursorRuleWrapper({\n wrapper,\n}: {\n readonly wrapper: CursorRuleWrapper;\n}): string {\n const fields: FrontmatterField[] = [];\n if (wrapper.frontmatterOrder === 'description-first' && wrapper.description !== undefined) {\n fields.push({ key: 'description', value: wrapper.description });\n }\n\n fields.push({ key: 'alwaysApply', value: wrapper.alwaysApply });\n\n if (wrapper.frontmatterOrder !== 'description-first' && wrapper.description !== undefined) {\n fields.push({ key: 'description', value: wrapper.description });\n }\n\n if (wrapper.globs !== undefined) {\n fields.push({ key: 'globs', value: wrapper.globs });\n }\n\n return `${renderFrontmatter({ fields })}\n\n@${wrapper.referencePath}\n`;\n}\n","/**\n * Content templates - static string content\n *\n * Note: Most templates (SAFEWORD.md, hooks, skills, guides, etc.) are now\n * file-based in the templates/ directory. This file contains only small\n * string constants that are used inline.\n */\n\n/**\n * Legacy prose reference for AGENTS.md. Kept only so upgrade/reset can remove\n * old safeword-managed blocks from customer-owned context files.\n */\nexport const AGENTS_MD_LINK = `**⚠️ ALWAYS READ FIRST:** \\`.safeword/SAFEWORD.md\\`\n\nThe SAFEWORD.md file contains core development patterns, workflows, and conventions.\nRead it BEFORE working on any task in this project.\n\n---\n\n`;\n\n/**\n * Legacy import block for CLAUDE.md. Kept only so upgrade/reset can remove old\n * safeword-managed imports from customer-owned context files.\n */\nexport const CLAUDE_MD_IMPORT_BLOCK = `@./.safeword/SAFEWORD.md\n\n---\n\n`;\n"],"mappings":"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","names":["endPtr","nodePath","nodePath","nodePath","readFileSync","nodePath","nodePath","nodePath","nodePath","readFileSync","existsSync","readFileSync","nodePath","existsSync","readFileSync","nodePath","process","YAML","existsSync","readFileSync","YAML","nodePath","process","nodePath"]}
|