mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-07-01 20:41:26 +08:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a0b7b1e788 | |||
| 752ee82de1 | |||
| 9a70d61a0e |
Generated
+92
-334
@@ -24,7 +24,7 @@
|
|||||||
"@opencode-ai/plugin": "^1.16.2",
|
"@opencode-ai/plugin": "^1.16.2",
|
||||||
"@types/node": "25.9.2",
|
"@types/node": "25.9.2",
|
||||||
"c8": "^11.0.0",
|
"c8": "^11.0.0",
|
||||||
"eslint": "^9.39.2",
|
"eslint": "^10.6.0",
|
||||||
"globals": "^17.4.0",
|
"globals": "^17.4.0",
|
||||||
"markdownlint-cli": "^0.48.0",
|
"markdownlint-cli": "^0.48.0",
|
||||||
"typescript": "^6.0.3"
|
"typescript": "^6.0.3"
|
||||||
@@ -86,107 +86,46 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/config-array": {
|
"node_modules/@eslint/config-array": {
|
||||||
"version": "0.21.1",
|
"version": "0.23.5",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz",
|
||||||
"integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
|
"integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint/object-schema": "^2.1.7",
|
"@eslint/object-schema": "^3.0.5",
|
||||||
"debug": "^4.3.1",
|
"debug": "^4.3.1",
|
||||||
"minimatch": "^3.1.2"
|
"minimatch": "^10.2.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^20.19.0 || ^22.13.0 || >=24"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/config-helpers": {
|
"node_modules/@eslint/config-helpers": {
|
||||||
"version": "0.4.2",
|
"version": "0.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.6.0.tgz",
|
||||||
"integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
|
"integrity": "sha512-ii6Bw9jJ2zi2cWA2Z+9/QZ/+3DX6kwaV5Q986D/CdP3Lap3w/pgQZ373FV7byY/i7L4IRH/G43I5dz1ClsCbpA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint/core": "^0.17.0"
|
"@eslint/core": "^1.2.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^20.19.0 || ^22.13.0 || >=24"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/core": {
|
"node_modules/@eslint/core": {
|
||||||
"version": "0.17.0",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz",
|
||||||
"integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
|
"integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/json-schema": "^7.0.15"
|
"@types/json-schema": "^7.0.15"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^20.19.0 || ^22.13.0 || >=24"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/eslintrc": {
|
|
||||||
"version": "3.3.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz",
|
|
||||||
"integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"ajv": "^6.12.4",
|
|
||||||
"debug": "^4.3.2",
|
|
||||||
"espree": "^10.0.1",
|
|
||||||
"globals": "^14.0.0",
|
|
||||||
"ignore": "^5.2.0",
|
|
||||||
"import-fresh": "^3.2.1",
|
|
||||||
"js-yaml": "^4.1.1",
|
|
||||||
"minimatch": "^3.1.2",
|
|
||||||
"strip-json-comments": "^3.1.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://opencollective.com/eslint"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@eslint/eslintrc/node_modules/ajv": {
|
|
||||||
"version": "6.14.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz",
|
|
||||||
"integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"fast-deep-equal": "^3.1.1",
|
|
||||||
"fast-json-stable-stringify": "^2.0.0",
|
|
||||||
"json-schema-traverse": "^0.4.1",
|
|
||||||
"uri-js": "^4.2.2"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/epoberezkin"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@eslint/eslintrc/node_modules/globals": {
|
|
||||||
"version": "14.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
|
|
||||||
"integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": {
|
|
||||||
"version": "0.4.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
|
||||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/@eslint/js": {
|
"node_modules/@eslint/js": {
|
||||||
"version": "9.39.2",
|
"version": "9.39.2",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz",
|
||||||
@@ -201,27 +140,27 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/object-schema": {
|
"node_modules/@eslint/object-schema": {
|
||||||
"version": "2.1.7",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz",
|
||||||
"integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
|
"integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^20.19.0 || ^22.13.0 || >=24"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/plugin-kit": {
|
"node_modules/@eslint/plugin-kit": {
|
||||||
"version": "0.4.1",
|
"version": "0.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.2.tgz",
|
||||||
"integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
|
"integrity": "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint/core": "^0.17.0",
|
"@eslint/core": "^1.2.1",
|
||||||
"levn": "^0.4.1"
|
"levn": "^0.4.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^20.19.0 || ^22.13.0 || >=24"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@humanfs/core": {
|
"node_modules/@humanfs/core": {
|
||||||
@@ -459,6 +398,13 @@
|
|||||||
"@types/ms": "*"
|
"@types/ms": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/esrecurse": {
|
||||||
|
"version": "4.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz",
|
||||||
|
"integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/estree": {
|
"node_modules/@types/estree": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
||||||
@@ -512,9 +458,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/acorn": {
|
"node_modules/acorn": {
|
||||||
"version": "8.15.0",
|
"version": "8.17.0",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz",
|
||||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
"integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -587,21 +533,26 @@
|
|||||||
"license": "Python-2.0"
|
"license": "Python-2.0"
|
||||||
},
|
},
|
||||||
"node_modules/balanced-match": {
|
"node_modules/balanced-match": {
|
||||||
"version": "1.0.2",
|
"version": "4.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
|
||||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
"integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": "18 || 20 || >=22"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
"version": "1.1.14",
|
"version": "5.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz",
|
||||||
"integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==",
|
"integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^4.0.2"
|
||||||
"concat-map": "0.0.1"
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "18 || 20 || >=22"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/c8": {
|
"node_modules/c8": {
|
||||||
@@ -638,33 +589,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/callsites": {
|
|
||||||
"version": "3.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
|
|
||||||
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/chalk": {
|
|
||||||
"version": "4.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
|
||||||
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"ansi-styles": "^4.1.0",
|
|
||||||
"supports-color": "^7.1.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/character-entities": {
|
"node_modules/character-entities": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz",
|
||||||
@@ -798,13 +722,6 @@
|
|||||||
"node": ">=20"
|
"node": ">=20"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/concat-map": {
|
|
||||||
"version": "0.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
|
||||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/convert-source-map": {
|
"node_modules/convert-source-map": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
|
||||||
@@ -983,33 +900,33 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint": {
|
"node_modules/eslint": {
|
||||||
"version": "9.39.2",
|
"version": "10.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-10.6.0.tgz",
|
||||||
"integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
|
"integrity": "sha512-6lVbcqSodALYo+4ELD0heG6lFiFxnLMuLkiMi2qV8LMp54N8tE8FT1GMH+ev4Ti00nFjNze2+Su6DsV5OQW3Dg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"workspaces": [
|
||||||
|
"packages/*"
|
||||||
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.8.0",
|
"@eslint-community/eslint-utils": "^4.8.0",
|
||||||
"@eslint-community/regexpp": "^4.12.1",
|
"@eslint-community/regexpp": "^4.12.2",
|
||||||
"@eslint/config-array": "^0.21.1",
|
"@eslint/config-array": "^0.23.5",
|
||||||
"@eslint/config-helpers": "^0.4.2",
|
"@eslint/config-helpers": "^0.6.0",
|
||||||
"@eslint/core": "^0.17.0",
|
"@eslint/core": "^1.2.1",
|
||||||
"@eslint/eslintrc": "^3.3.1",
|
"@eslint/plugin-kit": "^0.7.2",
|
||||||
"@eslint/js": "9.39.2",
|
|
||||||
"@eslint/plugin-kit": "^0.4.1",
|
|
||||||
"@humanfs/node": "^0.16.6",
|
"@humanfs/node": "^0.16.6",
|
||||||
"@humanwhocodes/module-importer": "^1.0.1",
|
"@humanwhocodes/module-importer": "^1.0.1",
|
||||||
"@humanwhocodes/retry": "^0.4.2",
|
"@humanwhocodes/retry": "^0.4.2",
|
||||||
"@types/estree": "^1.0.6",
|
"@types/estree": "^1.0.6",
|
||||||
"ajv": "^6.12.4",
|
"ajv": "^6.14.0",
|
||||||
"chalk": "^4.0.0",
|
|
||||||
"cross-spawn": "^7.0.6",
|
"cross-spawn": "^7.0.6",
|
||||||
"debug": "^4.3.2",
|
"debug": "^4.3.2",
|
||||||
"escape-string-regexp": "^4.0.0",
|
"escape-string-regexp": "^4.0.0",
|
||||||
"eslint-scope": "^8.4.0",
|
"eslint-scope": "^9.1.2",
|
||||||
"eslint-visitor-keys": "^4.2.1",
|
"eslint-visitor-keys": "^5.0.1",
|
||||||
"espree": "^10.4.0",
|
"espree": "^11.2.0",
|
||||||
"esquery": "^1.5.0",
|
"esquery": "^1.7.0",
|
||||||
"esutils": "^2.0.2",
|
"esutils": "^2.0.2",
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
"file-entry-cache": "^8.0.0",
|
"file-entry-cache": "^8.0.0",
|
||||||
@@ -1019,8 +936,7 @@
|
|||||||
"imurmurhash": "^0.1.4",
|
"imurmurhash": "^0.1.4",
|
||||||
"is-glob": "^4.0.0",
|
"is-glob": "^4.0.0",
|
||||||
"json-stable-stringify-without-jsonify": "^1.0.1",
|
"json-stable-stringify-without-jsonify": "^1.0.1",
|
||||||
"lodash.merge": "^4.6.2",
|
"minimatch": "^10.2.4",
|
||||||
"minimatch": "^3.1.2",
|
|
||||||
"natural-compare": "^1.4.0",
|
"natural-compare": "^1.4.0",
|
||||||
"optionator": "^0.9.3"
|
"optionator": "^0.9.3"
|
||||||
},
|
},
|
||||||
@@ -1028,7 +944,7 @@
|
|||||||
"eslint": "bin/eslint.js"
|
"eslint": "bin/eslint.js"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^20.19.0 || ^22.13.0 || >=24"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://eslint.org/donate"
|
"url": "https://eslint.org/donate"
|
||||||
@@ -1043,30 +959,32 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-scope": {
|
"node_modules/eslint-scope": {
|
||||||
"version": "8.4.0",
|
"version": "9.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz",
|
||||||
"integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
|
"integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/esrecurse": "^4.3.1",
|
||||||
|
"@types/estree": "^1.0.8",
|
||||||
"esrecurse": "^4.3.0",
|
"esrecurse": "^4.3.0",
|
||||||
"estraverse": "^5.2.0"
|
"estraverse": "^5.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^20.19.0 || ^22.13.0 || >=24"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://opencollective.com/eslint"
|
"url": "https://opencollective.com/eslint"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint-visitor-keys": {
|
"node_modules/eslint-visitor-keys": {
|
||||||
"version": "4.2.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
|
||||||
"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
|
"integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^20.19.0 || ^22.13.0 || >=24"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://opencollective.com/eslint"
|
"url": "https://opencollective.com/eslint"
|
||||||
@@ -1097,18 +1015,18 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/espree": {
|
"node_modules/espree": {
|
||||||
"version": "10.4.0",
|
"version": "11.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz",
|
||||||
"integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
|
"integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"acorn": "^8.15.0",
|
"acorn": "^8.16.0",
|
||||||
"acorn-jsx": "^5.3.2",
|
"acorn-jsx": "^5.3.2",
|
||||||
"eslint-visitor-keys": "^4.2.1"
|
"eslint-visitor-keys": "^5.0.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"node": "^20.19.0 || ^22.13.0 || >=24"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://opencollective.com/eslint"
|
"url": "https://opencollective.com/eslint"
|
||||||
@@ -1366,45 +1284,6 @@
|
|||||||
"node": ">=10.13.0"
|
"node": ">=10.13.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/glob/node_modules/balanced-match": {
|
|
||||||
"version": "4.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
|
|
||||||
"integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": "18 || 20 || >=22"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/glob/node_modules/brace-expansion": {
|
|
||||||
"version": "5.0.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
|
|
||||||
"integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"balanced-match": "^4.0.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "18 || 20 || >=22"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/glob/node_modules/minimatch": {
|
|
||||||
"version": "10.2.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
|
|
||||||
"integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "BlueOak-1.0.0",
|
|
||||||
"dependencies": {
|
|
||||||
"brace-expansion": "^5.0.5"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "18 || 20 || >=22"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/isaacs"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/globals": {
|
"node_modules/globals": {
|
||||||
"version": "17.4.0",
|
"version": "17.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/globals/-/globals-17.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/globals/-/globals-17.4.0.tgz",
|
||||||
@@ -1445,23 +1324,6 @@
|
|||||||
"node": ">= 4"
|
"node": ">= 4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/import-fresh": {
|
|
||||||
"version": "3.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
|
|
||||||
"integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"parent-module": "^1.0.0",
|
|
||||||
"resolve-from": "^4.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/imurmurhash": {
|
"node_modules/imurmurhash": {
|
||||||
"version": "0.1.4",
|
"version": "0.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
|
||||||
@@ -1763,13 +1625,6 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/lodash.merge": {
|
|
||||||
"version": "4.6.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
|
||||||
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/lru-cache": {
|
"node_modules/lru-cache": {
|
||||||
"version": "11.2.7",
|
"version": "11.2.7",
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz",
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz",
|
||||||
@@ -1875,29 +1730,6 @@
|
|||||||
"node": ">=20"
|
"node": ">=20"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/markdownlint-cli/node_modules/balanced-match": {
|
|
||||||
"version": "4.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
|
|
||||||
"integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": "18 || 20 || >=22"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/markdownlint-cli/node_modules/brace-expansion": {
|
|
||||||
"version": "5.0.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
|
|
||||||
"integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"balanced-match": "^4.0.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "18 || 20 || >=22"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/markdownlint-cli/node_modules/ignore": {
|
"node_modules/markdownlint-cli/node_modules/ignore": {
|
||||||
"version": "7.0.5",
|
"version": "7.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
|
||||||
@@ -1908,22 +1740,6 @@
|
|||||||
"node": ">= 4"
|
"node": ">= 4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/markdownlint-cli/node_modules/minimatch": {
|
|
||||||
"version": "10.2.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
|
|
||||||
"integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "BlueOak-1.0.0",
|
|
||||||
"dependencies": {
|
|
||||||
"brace-expansion": "^5.0.5"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "18 || 20 || >=22"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/isaacs"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/mdurl": {
|
"node_modules/mdurl": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
|
||||||
@@ -2467,15 +2283,19 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/minimatch": {
|
"node_modules/minimatch": {
|
||||||
"version": "3.1.5",
|
"version": "10.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
|
||||||
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
"integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "BlueOak-1.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^5.0.5"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "*"
|
"node": "18 || 20 || >=22"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/minimist": {
|
"node_modules/minimist": {
|
||||||
@@ -2618,19 +2438,6 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/parent-module": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
|
||||||
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"callsites": "^3.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/parse-entities": {
|
"node_modules/parse-entities": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz",
|
||||||
@@ -2766,16 +2573,6 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/resolve-from": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
|
|
||||||
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/run-con": {
|
"node_modules/run-con": {
|
||||||
"version": "1.3.2",
|
"version": "1.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/run-con/-/run-con-1.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/run-con/-/run-con-1.3.2.tgz",
|
||||||
@@ -2934,45 +2731,6 @@
|
|||||||
"node": "20 || >=22"
|
"node": "20 || >=22"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/test-exclude/node_modules/balanced-match": {
|
|
||||||
"version": "4.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
|
|
||||||
"integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": "18 || 20 || >=22"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/test-exclude/node_modules/brace-expansion": {
|
|
||||||
"version": "5.0.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
|
|
||||||
"integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"balanced-match": "^4.0.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "18 || 20 || >=22"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/test-exclude/node_modules/minimatch": {
|
|
||||||
"version": "10.2.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
|
|
||||||
"integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "BlueOak-1.0.0",
|
|
||||||
"dependencies": {
|
|
||||||
"brace-expansion": "^5.0.5"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "18 || 20 || >=22"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/isaacs"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/tinyglobby": {
|
"node_modules/tinyglobby": {
|
||||||
"version": "0.2.15",
|
"version": "0.2.15",
|
||||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ dev = [
|
|||||||
"pytest-mock>=3.12",
|
"pytest-mock>=3.12",
|
||||||
"ruff>=0.4",
|
"ruff>=0.4",
|
||||||
"mypy>=2.1.0",
|
"mypy>=2.1.0",
|
||||||
|
"pyyaml>=6.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
|
|||||||
@@ -97,7 +97,10 @@ function findShellBinary() {
|
|||||||
windowsHide: true,
|
windowsHide: true,
|
||||||
timeout: 30000,
|
timeout: 30000,
|
||||||
});
|
});
|
||||||
if (!probe.error) {
|
// A candidate is only usable if it both spawns AND exits cleanly. The
|
||||||
|
// Windows System32 bash.exe WSL launcher spawns without error but exits
|
||||||
|
// non-zero when no distro is installed, so !probe.error alone is not enough.
|
||||||
|
if (!probe.error && probe.status === 0) {
|
||||||
_cachedShell = candidate;
|
_cachedShell = candidate;
|
||||||
return _cachedShell;
|
return _cachedShell;
|
||||||
}
|
}
|
||||||
@@ -118,7 +121,9 @@ function findBashBinary() {
|
|||||||
|
|
||||||
for (const candidate of candidates) {
|
for (const candidate of candidates) {
|
||||||
const probe = spawnSync(candidate, ['-c', ':'], { stdio: 'ignore', windowsHide: true, timeout: 30000 });
|
const probe = spawnSync(candidate, ['-c', ':'], { stdio: 'ignore', windowsHide: true, timeout: 30000 });
|
||||||
if (!probe.error) {
|
// Require a clean exit, not just a successful spawn: the Windows System32
|
||||||
|
// bash.exe WSL stub spawns fine but exits non-zero with no distro installed.
|
||||||
|
if (!probe.error && probe.status === 0) {
|
||||||
_cachedBash = candidate;
|
_cachedBash = candidate;
|
||||||
return _cachedBash;
|
return _cachedBash;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,29 @@ const path = require('path');
|
|||||||
|
|
||||||
const { writeInstallState } = require('../install-state');
|
const { writeInstallState } = require('../install-state');
|
||||||
const { filterMcpConfig, parseDisabledMcpServers } = require('../mcp-config');
|
const { filterMcpConfig, parseDisabledMcpServers } = require('../mcp-config');
|
||||||
|
const { rewriteNamespaceLinks } = require('./rewrite-namespace-links');
|
||||||
|
|
||||||
|
const CLAUDE_ECC_NAMESPACE = 'ecc';
|
||||||
|
|
||||||
|
// Claude home/project installs inject `skills/ecc/` and `rules/ecc/`. Markdown
|
||||||
|
// copied under those namespaced roots may carry source-relative links to a
|
||||||
|
// sibling top-level dir that break post-install; rewrite them on copy.
|
||||||
|
function getNamespaceLinkRewrite(plan, destinationPath) {
|
||||||
|
if (!plan.adapter || (plan.adapter.target !== 'claude' && plan.adapter.target !== 'claude-project')) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (!plan.targetRoot || !destinationPath.toLowerCase().endsWith('.md')) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const namespacedRoots = [
|
||||||
|
path.join(plan.targetRoot, 'skills', CLAUDE_ECC_NAMESPACE) + path.sep,
|
||||||
|
path.join(plan.targetRoot, 'rules', CLAUDE_ECC_NAMESPACE) + path.sep,
|
||||||
|
];
|
||||||
|
if (!namespacedRoots.some(root => destinationPath.startsWith(root))) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return CLAUDE_ECC_NAMESPACE;
|
||||||
|
}
|
||||||
|
|
||||||
function readJsonObject(filePath, label) {
|
function readJsonObject(filePath, label) {
|
||||||
let parsed;
|
let parsed;
|
||||||
@@ -149,6 +172,16 @@ function applyInstallPlan(plan) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const namespace = operation.kind === 'copy-file'
|
||||||
|
? getNamespaceLinkRewrite(plan, operation.destinationPath)
|
||||||
|
: null;
|
||||||
|
if (namespace) {
|
||||||
|
const original = fs.readFileSync(operation.sourcePath, 'utf8');
|
||||||
|
const rewritten = rewriteNamespaceLinks(original, namespace);
|
||||||
|
fs.writeFileSync(operation.destinationPath, rewritten, 'utf8');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
fs.copyFileSync(operation.sourcePath, operation.destinationPath);
|
fs.copyFileSync(operation.sourcePath, operation.destinationPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
// The Claude home/project installers inject a namespace segment into the
|
||||||
|
// destination layout: `skills/` -> `skills/<ns>/` and `rules/` -> `rules/<ns>/`.
|
||||||
|
// Skills that link to a sibling top-level dir using a source-relative path
|
||||||
|
// (e.g. `../../rules/react/hooks.md`) break after install, because the extra
|
||||||
|
// `<ns>/` level changes what `../../` resolves to and the target dir is itself
|
||||||
|
// namespaced.
|
||||||
|
//
|
||||||
|
// This rewrites such links so they remain valid post-install: prepend one `../`
|
||||||
|
// (to climb out of the injected namespace level) and insert the namespace
|
||||||
|
// segment after the managed top-level dir name. Only links that climb with at
|
||||||
|
// least two `../` and reference a namespaced managed dir (`rules`/`skills`) are
|
||||||
|
// touched; intra-skill links (a single `../`) and absolute/bare paths are left
|
||||||
|
// alone.
|
||||||
|
|
||||||
|
const NAMESPACED_DIRS = ['rules', 'skills'];
|
||||||
|
|
||||||
|
function buildLinkPattern() {
|
||||||
|
const dirs = NAMESPACED_DIRS.join('|');
|
||||||
|
// group 1: the `../` climb (>= 2), group 2: managed dir, group 3: trailing `/`
|
||||||
|
return new RegExp(`((?:\\.\\./){2,})(${dirs})(/)`, 'g');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rewrite source-relative links in a namespaced skill/rule markdown file so they
|
||||||
|
* resolve correctly after the installer injects `<namespace>/`.
|
||||||
|
* @param {string} content - file contents
|
||||||
|
* @param {string} namespace - injected namespace segment (e.g. "ecc")
|
||||||
|
* @returns {string} rewritten contents (unchanged if no matching links)
|
||||||
|
*/
|
||||||
|
function rewriteNamespaceLinks(content, namespace) {
|
||||||
|
if (typeof content !== 'string' || !namespace) {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pattern = buildLinkPattern();
|
||||||
|
return content.replace(pattern, (match, climb, dir, slash, offset, fullText) => {
|
||||||
|
// Already namespaced (`../../rules/ecc/...`) — leave untouched (idempotent).
|
||||||
|
const rest = fullText.slice(offset + match.length);
|
||||||
|
if (rest.startsWith(`${namespace}/`)) {
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
return `../${climb}${dir}${slash}${namespace}/`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { rewriteNamespaceLinks, NAMESPACED_DIRS };
|
||||||
@@ -26,6 +26,18 @@ const {
|
|||||||
// "2026-02-01-ChezMoi_2-session.tmp"
|
// "2026-02-01-ChezMoi_2-session.tmp"
|
||||||
const SESSION_FILENAME_REGEX = /^(\d{4}-\d{2}-\d{2})(?:-([a-zA-Z0-9_][a-zA-Z0-9_-]*))?-session\.tmp$/;
|
const SESSION_FILENAME_REGEX = /^(\d{4}-\d{2}-\d{2})(?:-([a-zA-Z0-9_][a-zA-Z0-9_-]*))?-session\.tmp$/;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve a file's creation time, preferring birthtime but falling back to
|
||||||
|
* ctime when birthtime is unavailable. Some filesystems (e.g. overlayfs in
|
||||||
|
* containers) report birthtime as epoch 0; a Date object is always truthy, so
|
||||||
|
* `birthtime || ctime` would never fall back. Compare on milliseconds instead.
|
||||||
|
* @param {import('fs').Stats} stats
|
||||||
|
* @returns {Date}
|
||||||
|
*/
|
||||||
|
function resolveCreatedTime(stats) {
|
||||||
|
return stats.birthtimeMs > 0 ? stats.birthtime : stats.ctime;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse session filename to extract metadata
|
* Parse session filename to extract metadata
|
||||||
* @param {string} filename - Session filename (e.g., "2026-01-17-abc123-session.tmp" or "2026-01-17-session.tmp")
|
* @param {string} filename - Session filename (e.g., "2026-01-17-abc123-session.tmp" or "2026-01-17-session.tmp")
|
||||||
@@ -116,7 +128,7 @@ function getSessionCandidates(options = {}) {
|
|||||||
hasContent: stats.size > 0,
|
hasContent: stats.size > 0,
|
||||||
size: stats.size,
|
size: stats.size,
|
||||||
modifiedTime: stats.mtime,
|
modifiedTime: stats.mtime,
|
||||||
createdTime: stats.birthtime || stats.ctime
|
createdTime: resolveCreatedTime(stats)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,7 +163,7 @@ function buildSessionRecord(sessionPath, metadata) {
|
|||||||
hasContent: stats.size > 0,
|
hasContent: stats.size > 0,
|
||||||
size: stats.size,
|
size: stats.size,
|
||||||
modifiedTime: stats.mtime,
|
modifiedTime: stats.mtime,
|
||||||
createdTime: stats.birthtime || stats.ctime
|
createdTime: resolveCreatedTime(stats)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ Validate and sanitize all user input before processing.
|
|||||||
|
|
||||||
When creating instincts, determine scope based on these heuristics:
|
When creating instincts, determine scope based on these heuristics:
|
||||||
|
|
||||||
> **Scope Decision Guide** – See the canonical table in `skills/continuous-learning-v2/SKILL.md` (lines 271‑282).
|
> **Scope Decision Guide** – See the canonical table under the "Scope Decision Guide" heading in `skills/continuous-learning-v2/SKILL.md`.
|
||||||
|
|
||||||
**When in doubt, default to `scope: project`** — it's safer to be project-specific and promote later than to contaminate the global space.
|
**When in doubt, default to `scope: project`** — it's safer to be project-specific and promote later than to contaminate the global space.
|
||||||
|
|
||||||
@@ -142,7 +142,7 @@ Confidence adjusts over time:
|
|||||||
|
|
||||||
An instinct should be promoted from project-scoped to global when:
|
An instinct should be promoted from project-scoped to global when:
|
||||||
1. The **same pattern** (by id or similar trigger) exists in **2+ different projects**
|
1. The **same pattern** (by id or similar trigger) exists in **2+ different projects**
|
||||||
2. Each instance has confidence **>= 0.8**
|
2. The **average** confidence across those instances is **>= 0.8** (matching `PROMOTE_CONFIDENCE_THRESHOLD` in `instinct-cli.py`)
|
||||||
3. The domain is in the global-friendly list (security, general-best-practices, workflow)
|
3. The domain is in the global-friendly list (security, general-best-practices, workflow)
|
||||||
|
|
||||||
Promotion is handled by the `instinct-cli.py promote` command or the `/evolve` analysis.
|
Promotion is handled by the `instinct-cli.py promote` command or the `/evolve` analysis.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
# Continuous Learning v2 - Observer Agent Launcher
|
# Continuous Learning v2 - Observer Agent Launcher
|
||||||
#
|
#
|
||||||
# Starts the background observer agent that analyzes observations
|
# Starts the background observer agent that analyzes observations
|
||||||
@@ -37,7 +37,7 @@ PYTHON_CMD="${CLV2_PYTHON_CMD:-}"
|
|||||||
|
|
||||||
# shellcheck disable=SC1091
|
# shellcheck disable=SC1091
|
||||||
. "${SKILL_ROOT}/scripts/lib/homunculus-dir.sh"
|
. "${SKILL_ROOT}/scripts/lib/homunculus-dir.sh"
|
||||||
CONFIG_DIR="$(_ecc_resolve_homunculus_dir)"
|
CONFIG_DIR="$(_clv2_resolve_homunculus_dir)"
|
||||||
if [ -n "${CLV2_CONFIG:-}" ]; then
|
if [ -n "${CLV2_CONFIG:-}" ]; then
|
||||||
CONFIG_FILE="$CLV2_CONFIG"
|
CONFIG_FILE="$CLV2_CONFIG"
|
||||||
elif [ -f "${CONFIG_DIR}/config.json" ]; then
|
elif [ -f "${CONFIG_DIR}/config.json" ]; then
|
||||||
@@ -215,8 +215,13 @@ case "$ACTION" in
|
|||||||
CLV2_OBSERVER_PROMPT_PATTERN="$CLV2_OBSERVER_PROMPT_PATTERN" \
|
CLV2_OBSERVER_PROMPT_PATTERN="$CLV2_OBSERVER_PROMPT_PATTERN" \
|
||||||
"$OBSERVER_LOOP_SCRIPT" >> "$LOG_FILE" 2>&1 &
|
"$OBSERVER_LOOP_SCRIPT" >> "$LOG_FILE" 2>&1 &
|
||||||
|
|
||||||
# Wait for PID file
|
# Wait for the PID file to appear (poll up to ~10s; exits early once ready).
|
||||||
sleep 2
|
# A fixed sleep is either too short on loaded/slow filesystems or wastes
|
||||||
|
# time on healthy ones.
|
||||||
|
for _i in $(seq 1 50); do
|
||||||
|
[ -f "$PID_FILE" ] && break
|
||||||
|
sleep 0.2
|
||||||
|
done
|
||||||
|
|
||||||
# Check for confirmation-seeking output in the observer log
|
# Check for confirmation-seeking output in the observer log
|
||||||
if tail -n +"$((start_line + 1))" "$LOG_FILE" 2>/dev/null | grep -E -i -q "$CLV2_OBSERVER_PROMPT_PATTERN"; then
|
if tail -n +"$((start_line + 1))" "$LOG_FILE" 2>/dev/null | grep -E -i -q "$CLV2_OBSERVER_PROMPT_PATTERN"; then
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
# Continuous Learning v2 - Observation Hook
|
# Continuous Learning v2 - Observation Hook
|
||||||
#
|
#
|
||||||
# Captures tool use events for pattern analysis.
|
# Captures tool use events for pattern analysis.
|
||||||
@@ -135,7 +135,7 @@ fi
|
|||||||
|
|
||||||
# shellcheck disable=SC1091
|
# shellcheck disable=SC1091
|
||||||
. "$(dirname "$0")/../scripts/lib/homunculus-dir.sh"
|
. "$(dirname "$0")/../scripts/lib/homunculus-dir.sh"
|
||||||
CONFIG_DIR="$(_ecc_resolve_homunculus_dir)"
|
CONFIG_DIR="$(_clv2_resolve_homunculus_dir)"
|
||||||
|
|
||||||
# Skip if disabled (check both default and CLV2_CONFIG-derived locations)
|
# Skip if disabled (check both default and CLV2_CONFIG-derived locations)
|
||||||
if [ -f "$CONFIG_DIR/disabled" ]; then
|
if [ -f "$CONFIG_DIR/disabled" ]; then
|
||||||
@@ -279,11 +279,11 @@ _SECRET_RE = re.compile(
|
|||||||
)
|
)
|
||||||
|
|
||||||
import signal
|
import signal
|
||||||
def _ecc_bail(*_):
|
def _clv2_bail(*_):
|
||||||
print("[observe] SIGALRM timeout: parse-error fallback observation dropped before write (#2300)", file=sys.stderr)
|
print("[observe] SIGALRM timeout: parse-error fallback observation dropped before write (#2300)", file=sys.stderr)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
try:
|
try:
|
||||||
signal.signal(signal.SIGALRM, _ecc_bail)
|
signal.signal(signal.SIGALRM, _clv2_bail)
|
||||||
signal.alarm(8) # self-terminate before the async hook 10s timeout can orphan us (#2278)
|
signal.alarm(8) # self-terminate before the async hook 10s timeout can orphan us (#2278)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
@@ -317,11 +317,11 @@ echo "$PARSED" | "$PYTHON_CMD" -c '
|
|||||||
import json, sys, os, re
|
import json, sys, os, re
|
||||||
import signal
|
import signal
|
||||||
|
|
||||||
def _ecc_bail(*_):
|
def _clv2_bail(*_):
|
||||||
print("[observe] SIGALRM timeout: in-flight observation dropped before write (#2300)", file=sys.stderr)
|
print("[observe] SIGALRM timeout: in-flight observation dropped before write (#2300)", file=sys.stderr)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
try:
|
try:
|
||||||
signal.signal(signal.SIGALRM, _ecc_bail)
|
signal.signal(signal.SIGALRM, _clv2_bail)
|
||||||
signal.alarm(8) # self-terminate before the async hook 10s timeout can orphan us (#2278)
|
signal.alarm(8) # self-terminate before the async hook 10s timeout can orphan us (#2278)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
@@ -493,7 +493,7 @@ touch "$ACTIVITY_FILE" 2>/dev/null || true
|
|||||||
# the lazy-start path above. Both wrap the same read-modify-write below.
|
# the lazy-start path above. Both wrap the same read-modify-write below.
|
||||||
should_signal=0
|
should_signal=0
|
||||||
|
|
||||||
_ecc_bump_signal_counter() {
|
_clv2_bump_signal_counter() {
|
||||||
if [ -f "$SIGNAL_COUNTER_FILE" ]; then
|
if [ -f "$SIGNAL_COUNTER_FILE" ]; then
|
||||||
counter=$(cat "$SIGNAL_COUNTER_FILE" 2>/dev/null || echo 0)
|
counter=$(cat "$SIGNAL_COUNTER_FILE" 2>/dev/null || echo 0)
|
||||||
# Guard against a corrupt counter file: a non-integer value would abort the
|
# Guard against a corrupt counter file: a non-integer value would abort the
|
||||||
@@ -518,7 +518,7 @@ if command -v flock >/dev/null 2>&1 && exec 8>"$SIGNAL_COUNTER_LOCK" 2>/dev/null
|
|||||||
# blocks indefinitely, and only bump the counter while the lock is held -- on
|
# blocks indefinitely, and only bump the counter while the lock is held -- on
|
||||||
# a timeout we skip the tick rather than doing an unlocked read-modify-write.
|
# a timeout we skip the tick rather than doing an unlocked read-modify-write.
|
||||||
if flock -w 2 8 2>/dev/null; then
|
if flock -w 2 8 2>/dev/null; then
|
||||||
_ecc_bump_signal_counter
|
_clv2_bump_signal_counter
|
||||||
flock -u 8 2>/dev/null || true
|
flock -u 8 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
exec 8>&- 2>/dev/null || true
|
exec 8>&- 2>/dev/null || true
|
||||||
@@ -547,7 +547,7 @@ else
|
|||||||
done
|
done
|
||||||
if [ "$_signal_lock_held" -eq 1 ]; then
|
if [ "$_signal_lock_held" -eq 1 ]; then
|
||||||
# Bump only under the held lock -- never an unlocked read-modify-write.
|
# Bump only under the held lock -- never an unlocked read-modify-write.
|
||||||
_ecc_bump_signal_counter
|
_clv2_bump_signal_counter
|
||||||
rmdir "$SIGNAL_COUNTER_LOCK" 2>/dev/null || true
|
rmdir "$SIGNAL_COUNTER_LOCK" 2>/dev/null || true
|
||||||
trap - EXIT INT TERM
|
trap - EXIT INT TERM
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
# Continuous Learning v2 - Project Detection Helper
|
# Continuous Learning v2 - Project Detection Helper
|
||||||
#
|
#
|
||||||
# Shared logic for detecting current project context.
|
# Shared logic for detecting current project context.
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
# shellcheck disable=SC1091
|
# shellcheck disable=SC1091
|
||||||
. "$(dirname "${BASH_SOURCE[0]}")/lib/homunculus-dir.sh"
|
. "$(dirname "${BASH_SOURCE[0]}")/lib/homunculus-dir.sh"
|
||||||
_CLV2_HOMUNCULUS_DIR="$(_ecc_resolve_homunculus_dir)"
|
_CLV2_HOMUNCULUS_DIR="$(_clv2_resolve_homunculus_dir)"
|
||||||
_CLV2_PROJECTS_DIR="${_CLV2_HOMUNCULUS_DIR}/projects"
|
_CLV2_PROJECTS_DIR="${_CLV2_HOMUNCULUS_DIR}/projects"
|
||||||
_CLV2_REGISTRY_FILE="${_CLV2_HOMUNCULUS_DIR}/projects.json"
|
_CLV2_REGISTRY_FILE="${_CLV2_HOMUNCULUS_DIR}/projects.json"
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
# 2. XDG_DATA_HOME/ecc-homunculus, when XDG_DATA_HOME is absolute
|
# 2. XDG_DATA_HOME/ecc-homunculus, when XDG_DATA_HOME is absolute
|
||||||
# 3. HOME/.local/share/ecc-homunculus
|
# 3. HOME/.local/share/ecc-homunculus
|
||||||
|
|
||||||
_ecc_resolve_homunculus_dir() {
|
_clv2_resolve_homunculus_dir() {
|
||||||
if [ -n "${CLV2_HOMUNCULUS_DIR:-}" ]; then
|
if [ -n "${CLV2_HOMUNCULUS_DIR:-}" ]; then
|
||||||
case "$CLV2_HOMUNCULUS_DIR" in
|
case "$CLV2_HOMUNCULUS_DIR" in
|
||||||
/*) printf '%s\n' "$CLV2_HOMUNCULUS_DIR"; return 0 ;;
|
/*) printf '%s\n' "$CLV2_HOMUNCULUS_DIR"; return 0 ;;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ OLD="${HOME}/.claude/homunculus"
|
|||||||
|
|
||||||
# shellcheck disable=SC1091
|
# shellcheck disable=SC1091
|
||||||
. "$(dirname "$0")/lib/homunculus-dir.sh"
|
. "$(dirname "$0")/lib/homunculus-dir.sh"
|
||||||
NEW="$(_ecc_resolve_homunculus_dir)"
|
NEW="$(_clv2_resolve_homunculus_dir)"
|
||||||
|
|
||||||
if [ "$NEW" = "$OLD" ]; then
|
if [ "$NEW" = "$OLD" ]; then
|
||||||
echo "Resolved destination equals source ($OLD); nothing to migrate."
|
echo "Resolved destination equals source ($OLD); nothing to migrate."
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
from unittest import mock
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ function buildSandbox() {
|
|||||||
path.join(scriptsLibDir, 'homunculus-dir.sh'),
|
path.join(scriptsLibDir, 'homunculus-dir.sh'),
|
||||||
[
|
[
|
||||||
'#!/bin/bash',
|
'#!/bin/bash',
|
||||||
'_ecc_resolve_homunculus_dir() { printf "%s\\n" "$HOME/.local/share/ecc-homunculus"; }',
|
'_clv2_resolve_homunculus_dir() { printf "%s\\n" "$HOME/.local/share/ecc-homunculus"; }',
|
||||||
''
|
''
|
||||||
].join('\n')
|
].join('\n')
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
*
|
*
|
||||||
* observe.sh arms a signal.SIGALRM alarm (8s) inside its inline-Python blocks so
|
* observe.sh arms a signal.SIGALRM alarm (8s) inside its inline-Python blocks so
|
||||||
* the observation writer self-terminates before the async hook's 10s timeout can
|
* the observation writer self-terminates before the async hook's 10s timeout can
|
||||||
* orphan it (#2278). Before #2300 the handler `_ecc_bail` called sys.exit(0) with
|
* orphan it (#2278). Before #2300 the handler `_clv2_bail` called sys.exit(0) with
|
||||||
* no logging, so a timeout silently dropped the in-flight observation: nothing was
|
* no logging, so a timeout silently dropped the in-flight observation: nothing was
|
||||||
* logged and the shell saw a clean exit. The fix adds a stderr visibility line to
|
* logged and the shell saw a clean exit. The fix adds a stderr visibility line to
|
||||||
* each handler while keeping exit 0 (changing to a non-zero exit would make the
|
* each handler while keeping exit 0 (changing to a non-zero exit would make the
|
||||||
* Claude hook report a block, per the repo's "always exit 0; log to stderr" rule).
|
* Claude hook report a block, per the repo's "always exit 0; log to stderr" rule).
|
||||||
*
|
*
|
||||||
* Two checks:
|
* Two checks:
|
||||||
* 1. Static regression guard — every `_ecc_bail` handler in observe.sh writes to
|
* 1. Static regression guard — every `_clv2_bail` handler in observe.sh writes to
|
||||||
* sys.stderr before sys.exit(0).
|
* sys.stderr before sys.exit(0).
|
||||||
* 2. Behavioral check — the REAL handler text extracted from observe.sh, when its
|
* 2. Behavioral check — the REAL handler text extracted from observe.sh, when its
|
||||||
* alarm fires, exits 0 and emits the `[observe]` visibility token on stderr
|
* alarm fires, exits 0 and emits the `[observe]` visibility token on stderr
|
||||||
@@ -73,14 +73,14 @@ const observeShPath = path.join(
|
|||||||
|
|
||||||
const observeSrc = fs.readFileSync(observeShPath, 'utf8');
|
const observeSrc = fs.readFileSync(observeShPath, 'utf8');
|
||||||
|
|
||||||
// Extract each `_ecc_bail` handler body: the `def` line plus the indented lines
|
// Extract each `_clv2_bail` handler body: the `def` line plus the indented lines
|
||||||
// that follow it, up to (and including) the first dedented `sys.exit(0)` line at
|
// that follow it, up to (and including) the first dedented `sys.exit(0)` line at
|
||||||
// the same indentation as the def's body.
|
// the same indentation as the def's body.
|
||||||
function extractHandlers(src) {
|
function extractHandlers(src) {
|
||||||
const lines = src.split('\n');
|
const lines = src.split('\n');
|
||||||
const handlers = [];
|
const handlers = [];
|
||||||
for (let i = 0; i < lines.length; i += 1) {
|
for (let i = 0; i < lines.length; i += 1) {
|
||||||
if (/^def _ecc_bail\(\*_\):\s*$/.test(lines[i])) {
|
if (/^def _clv2_bail\(\*_\):\s*$/.test(lines[i])) {
|
||||||
const body = [lines[i]];
|
const body = [lines[i]];
|
||||||
for (let j = i + 1; j < lines.length; j += 1) {
|
for (let j = i + 1; j < lines.length; j += 1) {
|
||||||
// Stop when we hit a line that is not indented (next top-level stmt).
|
// Stop when we hit a line that is not indented (next top-level stmt).
|
||||||
@@ -103,15 +103,15 @@ const handlers = extractHandlers(observeSrc);
|
|||||||
// The #2300 timeout handlers are the ones that log the `[observe] SIGALRM
|
// The #2300 timeout handlers are the ones that log the `[observe] SIGALRM
|
||||||
// timeout` marker. Selecting by marker (rather than by array index) keeps the
|
// timeout` marker. Selecting by marker (rather than by array index) keeps the
|
||||||
// behavioral check pinned to the timeout handlers even if an unrelated
|
// behavioral check pinned to the timeout handlers even if an unrelated
|
||||||
// `_ecc_bail` is ever added elsewhere in observe.sh.
|
// `_clv2_bail` is ever added elsewhere in observe.sh.
|
||||||
const timeoutHandlers = handlers.filter(body =>
|
const timeoutHandlers = handlers.filter(body =>
|
||||||
body.includes('[observe] SIGALRM timeout')
|
body.includes('[observe] SIGALRM timeout')
|
||||||
);
|
);
|
||||||
|
|
||||||
test('observe.sh defines at least two _ecc_bail timeout handlers', () => {
|
test('observe.sh defines at least two _clv2_bail timeout handlers', () => {
|
||||||
assert.ok(
|
assert.ok(
|
||||||
handlers.length >= 2,
|
handlers.length >= 2,
|
||||||
`expected >= 2 _ecc_bail handlers, found ${handlers.length}`
|
`expected >= 2 _clv2_bail handlers, found ${handlers.length}`
|
||||||
);
|
);
|
||||||
assert.ok(
|
assert.ok(
|
||||||
timeoutHandlers.length >= 2,
|
timeoutHandlers.length >= 2,
|
||||||
@@ -119,7 +119,7 @@ test('observe.sh defines at least two _ecc_bail timeout handlers', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('every _ecc_bail handler logs to stderr before exiting (regression guard)', () => {
|
test('every _clv2_bail handler logs to stderr before exiting (regression guard)', () => {
|
||||||
handlers.forEach((body, idx) => {
|
handlers.forEach((body, idx) => {
|
||||||
const stderrIdx = body.indexOf('file=sys.stderr');
|
const stderrIdx = body.indexOf('file=sys.stderr');
|
||||||
const exitIdx = body.indexOf('sys.exit(0)');
|
const exitIdx = body.indexOf('sys.exit(0)');
|
||||||
@@ -142,7 +142,7 @@ test('every _ecc_bail handler logs to stderr before exiting (regression guard)',
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('_ecc_bail handlers keep exit code 0 (no exit 2 / block regression)', () => {
|
test('_clv2_bail handlers keep exit code 0 (no exit 2 / block regression)', () => {
|
||||||
handlers.forEach((body, idx) => {
|
handlers.forEach((body, idx) => {
|
||||||
assert.ok(
|
assert.ok(
|
||||||
/sys\.exit\(0\)/.test(body),
|
/sys\.exit\(0\)/.test(body),
|
||||||
@@ -160,7 +160,7 @@ function runHandlerTimeout(python, handler) {
|
|||||||
const program = [
|
const program = [
|
||||||
'import sys, signal, time',
|
'import sys, signal, time',
|
||||||
handler,
|
handler,
|
||||||
'signal.signal(signal.SIGALRM, _ecc_bail)',
|
'signal.signal(signal.SIGALRM, _clv2_bail)',
|
||||||
'signal.alarm(1)',
|
'signal.alarm(1)',
|
||||||
'time.sleep(3)',
|
'time.sleep(3)',
|
||||||
'print("REACHED_END_SHOULD_NOT_HAPPEN")',
|
'print("REACHED_END_SHOULD_NOT_HAPPEN")',
|
||||||
@@ -178,7 +178,7 @@ function runHandlerTimeout(python, handler) {
|
|||||||
// the worst case. A behavioral check on only one handler would not catch a
|
// the worst case. A behavioral check on only one handler would not catch a
|
||||||
// regression that silenced another.
|
// regression that silenced another.
|
||||||
timeoutHandlers.forEach((handler, idx) => {
|
timeoutHandlers.forEach((handler, idx) => {
|
||||||
test(`real _ecc_bail timeout handler #${idx + 1}: SIGALRM fire emits stderr token and exits 0`, () => {
|
test(`real _clv2_bail timeout handler #${idx + 1}: SIGALRM fire emits stderr token and exits 0`, () => {
|
||||||
const python = findPython();
|
const python = findPython();
|
||||||
if (!python) {
|
if (!python) {
|
||||||
// Fail fast rather than returning (which the harness would record as a
|
// Fail fast rather than returning (which the harness would record as a
|
||||||
|
|||||||
@@ -375,7 +375,7 @@ test('observe.sh creates counter file and increments on each call', () => {
|
|||||||
path.join(scriptsLibDir, 'homunculus-dir.sh'),
|
path.join(scriptsLibDir, 'homunculus-dir.sh'),
|
||||||
[
|
[
|
||||||
'#!/bin/bash',
|
'#!/bin/bash',
|
||||||
'_ecc_resolve_homunculus_dir() { printf "%s\\n" "$HOME/.local/share/ecc-homunculus"; }',
|
'_clv2_resolve_homunculus_dir() { printf "%s\\n" "$HOME/.local/share/ecc-homunculus"; }',
|
||||||
''
|
''
|
||||||
].join('\n')
|
].join('\n')
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/**
|
||||||
|
* Tests for scripts/lib/install/rewrite-namespace-links.js (#2340)
|
||||||
|
*/
|
||||||
|
|
||||||
|
const assert = require('assert');
|
||||||
|
|
||||||
|
const { rewriteNamespaceLinks } = require('../../scripts/lib/install/rewrite-namespace-links');
|
||||||
|
|
||||||
|
function test(name, fn) {
|
||||||
|
try {
|
||||||
|
fn();
|
||||||
|
console.log(` \u2713 ${name}`);
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.log(` \u2717 ${name}`);
|
||||||
|
console.log(` Error: ${error.message}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function runTests() {
|
||||||
|
console.log('\n=== Testing rewrite-namespace-links.js ===\n');
|
||||||
|
|
||||||
|
let passed = 0;
|
||||||
|
let failed = 0;
|
||||||
|
|
||||||
|
if (test('rewrites a markdown link to a sibling rules dir', () => {
|
||||||
|
assert.strictEqual(
|
||||||
|
rewriteNamespaceLinks('See [hooks](../../rules/react/hooks.md) here', 'ecc'),
|
||||||
|
'See [hooks](../../../rules/ecc/react/hooks.md) here'
|
||||||
|
);
|
||||||
|
})) passed++; else failed++;
|
||||||
|
|
||||||
|
if (test('rewrites a bare rules dir link', () => {
|
||||||
|
assert.strictEqual(
|
||||||
|
rewriteNamespaceLinks('Rules: [r](../../rules/react/)', 'ecc'),
|
||||||
|
'Rules: [r](../../../rules/ecc/react/)'
|
||||||
|
);
|
||||||
|
})) passed++; else failed++;
|
||||||
|
|
||||||
|
if (test('handles deeper skill nesting (3+ climbs)', () => {
|
||||||
|
assert.strictEqual(
|
||||||
|
rewriteNamespaceLinks('link ../../../rules/x/y.md', 'ecc'),
|
||||||
|
'link ../../../../rules/ecc/x/y.md'
|
||||||
|
);
|
||||||
|
})) passed++; else failed++;
|
||||||
|
|
||||||
|
if (test('leaves intra-skill single-climb links untouched', () => {
|
||||||
|
const input = 'See ../sibling/file.md and ./local.md';
|
||||||
|
assert.strictEqual(rewriteNamespaceLinks(input, 'ecc'), input);
|
||||||
|
})) passed++; else failed++;
|
||||||
|
|
||||||
|
if (test('is idempotent on already-namespaced links', () => {
|
||||||
|
const input = 'See [x](../../../rules/ecc/react/hooks.md)';
|
||||||
|
assert.strictEqual(rewriteNamespaceLinks(input, 'ecc'), input);
|
||||||
|
})) passed++; else failed++;
|
||||||
|
|
||||||
|
if (test('rewrites multiple links in one document', () => {
|
||||||
|
assert.strictEqual(
|
||||||
|
rewriteNamespaceLinks('(../../rules/a) and (../../rules/b)', 'ecc'),
|
||||||
|
'(../../../rules/ecc/a) and (../../../rules/ecc/b)'
|
||||||
|
);
|
||||||
|
})) passed++; else failed++;
|
||||||
|
|
||||||
|
if (test('rewrites sibling skills-dir links symmetrically', () => {
|
||||||
|
assert.strictEqual(
|
||||||
|
rewriteNamespaceLinks('[s](../../skills/other/SKILL.md)', 'ecc'),
|
||||||
|
'[s](../../../skills/ecc/other/SKILL.md)'
|
||||||
|
);
|
||||||
|
})) passed++; else failed++;
|
||||||
|
|
||||||
|
if (test('returns input unchanged when namespace is missing', () => {
|
||||||
|
const input = 'See [x](../../rules/react/)';
|
||||||
|
assert.strictEqual(rewriteNamespaceLinks(input, ''), input);
|
||||||
|
})) passed++; else failed++;
|
||||||
|
|
||||||
|
console.log(`\nResults: Passed: ${passed}, Failed: ${failed}`);
|
||||||
|
process.exit(failed > 0 ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
runTests();
|
||||||
@@ -1165,16 +1165,21 @@ src/main.ts
|
|||||||
})) passed++; else failed++;
|
})) passed++; else failed++;
|
||||||
|
|
||||||
if (test('createdTime falls back to ctime when birthtime is epoch-zero', () => {
|
if (test('createdTime falls back to ctime when birthtime is epoch-zero', () => {
|
||||||
// This tests the || fallback logic: stats.birthtime || stats.ctime
|
// Some filesystems (e.g. overlayfs in containers) report birthtime as
|
||||||
// On some FS, birthtime may be epoch 0 (falsy as a Date number comparison
|
// epoch 0. A Date object is always truthy, so `birthtime || ctime` would
|
||||||
// but truthy as a Date object). The fallback is defensive.
|
// never fall back; the source compares birthtimeMs > 0 instead. Verify the
|
||||||
|
// resolved createdTime is always a non-zero Date regardless of birthtime.
|
||||||
const stats = fs.statSync(r33FilePath);
|
const stats = fs.statSync(r33FilePath);
|
||||||
// Both birthtime and ctime should be valid Dates on any modern OS
|
|
||||||
assert.ok(stats.ctime instanceof Date, 'ctime should exist');
|
assert.ok(stats.ctime instanceof Date, 'ctime should exist');
|
||||||
// The fallback expression `birthtime || ctime` should always produce a valid Date
|
const expected = stats.birthtimeMs > 0 ? stats.birthtime : stats.ctime;
|
||||||
const fallbackResult = stats.birthtime || stats.ctime;
|
assert.ok(expected.getTime() > 0, 'Resolved created time should be non-zero');
|
||||||
assert.ok(fallbackResult instanceof Date, 'Fallback should produce a Date');
|
const session = sessionManager.getSessionById('r33birth');
|
||||||
assert.ok(fallbackResult.getTime() > 0, 'Fallback date should be non-zero');
|
assert.ok(session, 'Should find the session');
|
||||||
|
assert.strictEqual(
|
||||||
|
session.createdTime.getTime(),
|
||||||
|
expected.getTime(),
|
||||||
|
'createdTime should fall back to ctime when birthtime is epoch-zero'
|
||||||
|
);
|
||||||
})) passed++; else failed++;
|
})) passed++; else failed++;
|
||||||
|
|
||||||
// Cleanup Round 33 HOME override
|
// Cleanup Round 33 HOME override
|
||||||
|
|||||||
@@ -123,6 +123,40 @@ function runTests() {
|
|||||||
}
|
}
|
||||||
})) passed++; else failed++;
|
})) passed++; else failed++;
|
||||||
|
|
||||||
|
if (test('rewrites namespaced skill links to the ecc/ rules path (#2340)', () => {
|
||||||
|
const homeDir = createTempDir('install-apply-home-');
|
||||||
|
const projectDir = createTempDir('install-apply-project-');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = run(['typescript'], { cwd: projectDir, homeDir });
|
||||||
|
assert.strictEqual(result.code, 0, result.stderr);
|
||||||
|
|
||||||
|
const claudeRoot = path.join(homeDir, '.claude');
|
||||||
|
const skillPath = path.join(claudeRoot, 'skills', 'ecc', 'react-patterns', 'SKILL.md');
|
||||||
|
assert.ok(fs.existsSync(skillPath), 'react-patterns SKILL.md should be installed');
|
||||||
|
|
||||||
|
const content = fs.readFileSync(skillPath, 'utf8');
|
||||||
|
assert.ok(
|
||||||
|
content.includes('../../../rules/ecc/react/'),
|
||||||
|
'source-relative rules link should be rewritten for the ecc/ namespace'
|
||||||
|
);
|
||||||
|
assert.ok(
|
||||||
|
!content.includes('](../../rules/'),
|
||||||
|
'no un-namespaced ](../../rules/ links should remain'
|
||||||
|
);
|
||||||
|
|
||||||
|
// The rewritten link must resolve to a file that actually exists on disk.
|
||||||
|
const linkTarget = path.join(
|
||||||
|
path.dirname(skillPath),
|
||||||
|
'../../../rules/ecc/react/hooks.md'
|
||||||
|
);
|
||||||
|
assert.ok(fs.existsSync(linkTarget), 'rewritten link target should exist');
|
||||||
|
} finally {
|
||||||
|
cleanup(homeDir);
|
||||||
|
cleanup(projectDir);
|
||||||
|
}
|
||||||
|
})) passed++; else failed++;
|
||||||
|
|
||||||
if (test('installs Cursor configs and writes install-state', () => {
|
if (test('installs Cursor configs and writes install-state', () => {
|
||||||
const homeDir = createTempDir('install-apply-home-');
|
const homeDir = createTempDir('install-apply-home-');
|
||||||
const projectDir = createTempDir('install-apply-project-');
|
const projectDir = createTempDir('install-apply-project-');
|
||||||
|
|||||||
Reference in New Issue
Block a user