pipcode 0.0.0-stage → 2.1.1

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.
Files changed (401) hide show
  1. package/LICENSE +47 -0
  2. package/README.md +44 -2
  3. package/auto.js +40 -0
  4. package/bin/setup.js +31 -0
  5. package/bin/teardown.js +18 -0
  6. package/grammars/tree-sitter-javascript.wasm +0 -0
  7. package/grammars/tree-sitter-python.wasm +0 -0
  8. package/grammars/tree-sitter-tsx.wasm +0 -0
  9. package/grammars/tree-sitter-typescript.wasm +0 -0
  10. package/index.js +39 -0
  11. package/package.json +45 -4
  12. package/src/auth/auth-email.js +32 -0
  13. package/src/auth/trusted-key.js +13 -0
  14. package/src/auto/adjust.js +41 -0
  15. package/src/auto/amnesia.js +37 -0
  16. package/src/auto/anonymize-tasks.js +13 -0
  17. package/src/auto/apply-diff-backed.js +10 -0
  18. package/src/auto/apply-diff.js +60 -0
  19. package/src/auto/ask-guard.js +16 -0
  20. package/src/auto/ask-pause.js +36 -0
  21. package/src/auto/ask-protocol.js +6 -0
  22. package/src/auto/ask-user.js +29 -0
  23. package/src/auto/backup-touched.js +30 -0
  24. package/src/auto/budget.js +52 -0
  25. package/src/auto/cancel.js +20 -0
  26. package/src/auto/constants.js +30 -0
  27. package/src/auto/crypto-util.js +17 -0
  28. package/src/auto/decompose.js +47 -0
  29. package/src/auto/diff.js +19 -0
  30. package/src/auto/fs-list.js +34 -0
  31. package/src/auto/git-base.js +16 -0
  32. package/src/auto/git-init.js +39 -0
  33. package/src/auto/git-restore.js +34 -0
  34. package/src/auto/git-scope.js +10 -0
  35. package/src/auto/git.js +38 -0
  36. package/src/auto/mission-docs.js +29 -0
  37. package/src/auto/mission-line.js +22 -0
  38. package/src/auto/node-check.js +30 -0
  39. package/src/auto/observe.js +23 -0
  40. package/src/auto/orchestrator.js +30 -0
  41. package/src/auto/patch-ask.js +16 -0
  42. package/src/auto/paths.js +18 -0
  43. package/src/auto/plan.js +42 -0
  44. package/src/auto/pricing.js +49 -0
  45. package/src/auto/project-files.js +12 -0
  46. package/src/auto/prompts.js +24 -0
  47. package/src/auto/quote-format.js +33 -0
  48. package/src/auto/retry.js +40 -0
  49. package/src/auto/run-lock.js +40 -0
  50. package/src/auto/run-loop.js +38 -0
  51. package/src/auto/run.js +49 -0
  52. package/src/auto/snapshot-gate.js +51 -0
  53. package/src/auto/snapshot-paths.js +33 -0
  54. package/src/auto/snapshot-restore.js +59 -0
  55. package/src/auto/snapshot-take.js +30 -0
  56. package/src/auto/state.js +52 -0
  57. package/src/auto/step-commit.js +46 -0
  58. package/src/auto/step-green.js +38 -0
  59. package/src/auto/step-loop.js +56 -0
  60. package/src/auto/step-prep.js +60 -0
  61. package/src/auto/step-qa.js +53 -0
  62. package/src/auto/step.js +30 -0
  63. package/src/auto/stop-options.js +34 -0
  64. package/src/auto/stop-report.js +17 -0
  65. package/src/auto/tasks.js +44 -0
  66. package/src/cli/apply-loop.js +29 -0
  67. package/src/cli/apply-toml.js +26 -0
  68. package/src/cli/apply.js +45 -0
  69. package/src/cli/ask-prepare.js +37 -0
  70. package/src/cli/auth-branches.js +53 -0
  71. package/src/cli/auth-interactive.js +46 -0
  72. package/src/cli/auto-ask.js +33 -0
  73. package/src/cli/auto-audit.js +16 -0
  74. package/src/cli/auto-cli.js +46 -0
  75. package/src/cli/auto-consent.js +22 -0
  76. package/src/cli/auto-flags.js +39 -0
  77. package/src/cli/auto-gate-session.js +27 -0
  78. package/src/cli/auto-gate.js +34 -0
  79. package/src/cli/auto-loader.js +17 -0
  80. package/src/cli/auto-plan.js +36 -0
  81. package/src/cli/auto-preflight.js +35 -0
  82. package/src/cli/auto-quote.js +28 -0
  83. package/src/cli/auto-report.js +36 -0
  84. package/src/cli/auto-resume.js +28 -0
  85. package/src/cli/auto-rules.js +20 -0
  86. package/src/cli/auto-run.js +26 -0
  87. package/src/cli/auto-task.js +26 -0
  88. package/src/cli/banner.js +20 -0
  89. package/src/cli/centralize.js +23 -0
  90. package/src/cli/collect-step.js +25 -0
  91. package/src/cli/config-pairs.js +46 -0
  92. package/src/cli/config.js +51 -0
  93. package/src/cli/detect-os.js +11 -0
  94. package/src/cli/dispatch.js +36 -0
  95. package/src/cli/env-file.js +44 -0
  96. package/src/cli/env-load.js +28 -0
  97. package/src/cli/env-parse.js +39 -0
  98. package/src/cli/env-rebuild.js +33 -0
  99. package/src/cli/gitignore-env.js +46 -0
  100. package/src/cli/help.js +28 -0
  101. package/src/cli/ide-entries.js +42 -0
  102. package/src/cli/ide-paths.js +37 -0
  103. package/src/cli/ide-roots.js +25 -0
  104. package/src/cli/interactive.js +26 -0
  105. package/src/cli/jetbrains.js +40 -0
  106. package/src/cli/legacy-entry.js +17 -0
  107. package/src/cli/main.js +42 -0
  108. package/src/cli/memory-cli.js +15 -0
  109. package/src/cli/prompts.js +24 -0
  110. package/src/cli/server-entry.js +42 -0
  111. package/src/cli/setup-args.js +39 -0
  112. package/src/cli/target-manual.js +24 -0
  113. package/src/cli/target-select.js +51 -0
  114. package/src/cli/toml-merge.js +56 -0
  115. package/src/cli/trial-check.js +15 -0
  116. package/src/cli/welcome.js +7 -0
  117. package/src/core/abort-signal.js +38 -0
  118. package/src/core/auto-deps.js +29 -0
  119. package/src/core/cache-ttl.js +21 -0
  120. package/src/core/config-base.js +38 -0
  121. package/src/core/config-cache.js +50 -0
  122. package/src/core/config.js +58 -0
  123. package/src/core/constants.js +31 -0
  124. package/src/core/crypto.js +45 -0
  125. package/src/core/dlp.js +51 -0
  126. package/src/core/doctrine-all.js +31 -0
  127. package/src/core/doctrine-caches.js +10 -0
  128. package/src/core/doctrine-fetch.js +49 -0
  129. package/src/core/doctrine-one.js +18 -0
  130. package/src/core/doctrine.js +39 -0
  131. package/src/core/dual-stream-parser.js +55 -0
  132. package/src/core/exports.js +28 -0
  133. package/src/core/google-route.js +17 -0
  134. package/src/core/identity.js +23 -0
  135. package/src/core/lang.js +19 -0
  136. package/src/core/leak-guard.js +40 -0
  137. package/src/core/llm-builder-anthropic.js +26 -0
  138. package/src/core/llm-builder-gemini.js +22 -0
  139. package/src/core/llm-builder-openai.js +26 -0
  140. package/src/core/llm-call.js +53 -0
  141. package/src/core/llm-config-secondary.js +28 -0
  142. package/src/core/llm-config.js +32 -0
  143. package/src/core/llm-errors.js +25 -0
  144. package/src/core/llm-exchange.js +27 -0
  145. package/src/core/llm-extract.js +52 -0
  146. package/src/core/llm-label.js +33 -0
  147. package/src/core/llm-ollama-request.js +32 -0
  148. package/src/core/llm-ollama.js +42 -0
  149. package/src/core/llm-prompts.js +14 -0
  150. package/src/core/llm-providers.js +26 -0
  151. package/src/core/llm-request.js +17 -0
  152. package/src/core/llm-retry-429.js +23 -0
  153. package/src/core/llm-stream-events.js +29 -0
  154. package/src/core/llm-stream.js +42 -0
  155. package/src/core/llm-unbounded.js +15 -0
  156. package/src/core/llm-warmup.js +44 -0
  157. package/src/core/manifest.js +42 -0
  158. package/src/core/master-prompt.js +11 -0
  159. package/src/core/model-id.js +19 -0
  160. package/src/core/ollama-lines.js +48 -0
  161. package/src/core/ollama.js +43 -0
  162. package/src/core/pkg-manager.js +35 -0
  163. package/src/core/process-guards.js +47 -0
  164. package/src/core/progress-emit.js +25 -0
  165. package/src/core/purge-key.js +20 -0
  166. package/src/core/reasoning-cut.js +19 -0
  167. package/src/core/reasoning-models.js +8 -0
  168. package/src/core/session-net.js +60 -0
  169. package/src/core/session-resilient.js +44 -0
  170. package/src/core/session.js +49 -0
  171. package/src/core/sse-parser.js +25 -0
  172. package/src/core/stdout-guard.js +11 -0
  173. package/src/core/tier.js +48 -0
  174. package/src/core/trial-resolve.js +22 -0
  175. package/src/core/trial-session.js +60 -0
  176. package/src/core/trial-status.js +35 -0
  177. package/src/core/usage-cost.js +25 -0
  178. package/src/core/usage-extract.js +28 -0
  179. package/src/core/usage-meter.js +41 -0
  180. package/src/engine/analyze-need.js +24 -0
  181. package/src/engine/analyze-ux.js +42 -0
  182. package/src/engine/ask-history.js +43 -0
  183. package/src/engine/ask-llm.js +40 -0
  184. package/src/engine/ask-prompt.js +48 -0
  185. package/src/engine/ask-rules.js +13 -0
  186. package/src/engine/ast-call-rules-danger.js +24 -0
  187. package/src/engine/ast-call-rules-inject.js +29 -0
  188. package/src/engine/ast-context.js +28 -0
  189. package/src/engine/ast-import-helpers.js +46 -0
  190. package/src/engine/ast-lang.js +24 -0
  191. package/src/engine/ast-node-helpers.js +51 -0
  192. package/src/engine/ast-rules-calls.js +16 -0
  193. package/src/engine/ast-rules-graph.js +58 -0
  194. package/src/engine/ast-rules-js.js +30 -0
  195. package/src/engine/ast-rules-jsx-py.js +26 -0
  196. package/src/engine/ast-runtime.js +60 -0
  197. package/src/engine/ast-scan.js +48 -0
  198. package/src/engine/audit-citations.js +28 -0
  199. package/src/engine/audit-facts.js +47 -0
  200. package/src/engine/audit-report.js +40 -0
  201. package/src/engine/audit-task.js +37 -0
  202. package/src/engine/cap-cache.js +50 -0
  203. package/src/engine/cap-eval.js +49 -0
  204. package/src/engine/cap-http.js +32 -0
  205. package/src/engine/cap-meta-anthropic.js +15 -0
  206. package/src/engine/cap-meta-ollama.js +15 -0
  207. package/src/engine/cap-meta-openrouter.js +19 -0
  208. package/src/engine/cap-meta.js +19 -0
  209. package/src/engine/cap-probe.js +34 -0
  210. package/src/engine/cap-types.js +29 -0
  211. package/src/engine/chat-doctrine.js +31 -0
  212. package/src/engine/checkpoint-control.js +23 -0
  213. package/src/engine/checkpoint-detect.js +19 -0
  214. package/src/engine/checkpoint-rules.js +19 -0
  215. package/src/engine/code-decls.js +12 -0
  216. package/src/engine/code-graph.js +52 -0
  217. package/src/engine/coerce.js +8 -0
  218. package/src/engine/collect.js +21 -0
  219. package/src/engine/compute-impact.js +17 -0
  220. package/src/engine/context-files.js +42 -0
  221. package/src/engine/context-fit.js +28 -0
  222. package/src/engine/context-margin.js +37 -0
  223. package/src/engine/context-relay.js +60 -0
  224. package/src/engine/control-duo.js +38 -0
  225. package/src/engine/control-phase.js +32 -0
  226. package/src/engine/control-prompt.js +25 -0
  227. package/src/engine/control-verdict.js +36 -0
  228. package/src/engine/default-steps.js +7 -0
  229. package/src/engine/deps-parse-js.js +49 -0
  230. package/src/engine/deps-parse-more.js +30 -0
  231. package/src/engine/deps-parse-other.js +41 -0
  232. package/src/engine/deps-parse.js +31 -0
  233. package/src/engine/det-builders-1.js +38 -0
  234. package/src/engine/det-builders-2.js +50 -0
  235. package/src/engine/detect-domains.js +27 -0
  236. package/src/engine/diff-files.js +35 -0
  237. package/src/engine/doc-suite.js +39 -0
  238. package/src/engine/doctrine-prefix.js +13 -0
  239. package/src/engine/domain-regex.js +11 -0
  240. package/src/engine/exports.js +35 -0
  241. package/src/engine/extract-deterministic.js +33 -0
  242. package/src/engine/extract-llm.js +48 -0
  243. package/src/engine/facts-binary.js +12 -0
  244. package/src/engine/facts-embedded.js +18 -0
  245. package/src/engine/facts-functions.js +21 -0
  246. package/src/engine/facts-html.js +22 -0
  247. package/src/engine/facts-inventory.js +33 -0
  248. package/src/engine/facts-lang.js +34 -0
  249. package/src/engine/facts-measure.js +43 -0
  250. package/src/engine/facts-patterns.js +28 -0
  251. package/src/engine/facts-project.js +26 -0
  252. package/src/engine/facts-size.js +26 -0
  253. package/src/engine/facts-wordpress.js +36 -0
  254. package/src/engine/generate-architecture-guide.js +46 -0
  255. package/src/engine/generate-readme.js +38 -0
  256. package/src/engine/generate-runbook.js +47 -0
  257. package/src/engine/git-facts.js +16 -0
  258. package/src/engine/history-purge.js +16 -0
  259. package/src/engine/json-balance.js +37 -0
  260. package/src/engine/json-safe.js +13 -0
  261. package/src/engine/line-numbers.js +16 -0
  262. package/src/engine/md-build-mid.js +35 -0
  263. package/src/engine/md-build-top.js +58 -0
  264. package/src/engine/md-build.js +36 -0
  265. package/src/engine/md-parse-helpers.js +7 -0
  266. package/src/engine/md-parse-pillars.js +38 -0
  267. package/src/engine/md-parse-ux-design.js +31 -0
  268. package/src/engine/md-parse.js +33 -0
  269. package/src/engine/mission-context-prefix.js +30 -0
  270. package/src/engine/mission-guard.js +36 -0
  271. package/src/engine/mission-helpers.js +23 -0
  272. package/src/engine/mission-log.js +56 -0
  273. package/src/engine/mission-paths.js +7 -0
  274. package/src/engine/mission-store.js +51 -0
  275. package/src/engine/normalize-extraction.js +35 -0
  276. package/src/engine/normalize-impact-design.js +39 -0
  277. package/src/engine/normalize-pillars.js +36 -0
  278. package/src/engine/orchestrate-route.js +39 -0
  279. package/src/engine/orchestrator-build.js +37 -0
  280. package/src/engine/orchestrator-phases.js +55 -0
  281. package/src/engine/orchestrator.js +40 -0
  282. package/src/engine/osv.js +43 -0
  283. package/src/engine/parse-json-loose.js +36 -0
  284. package/src/engine/patch-file-sections.js +28 -0
  285. package/src/engine/patch-scan-cheat.js +52 -0
  286. package/src/engine/patch-scan-prep.js +37 -0
  287. package/src/engine/patch-scan-rules.js +51 -0
  288. package/src/engine/patch-scan.js +38 -0
  289. package/src/engine/patch-secret-guard.js +50 -0
  290. package/src/engine/patch-ui-guard.js +49 -0
  291. package/src/engine/pattern-sanitize.js +23 -0
  292. package/src/engine/plan-draft.js +37 -0
  293. package/src/engine/plan-mission.js +60 -0
  294. package/src/engine/plan-reply-legacy.js +34 -0
  295. package/src/engine/plan-reply-pillars.js +34 -0
  296. package/src/engine/plan-reply-ux.js +17 -0
  297. package/src/engine/plan-reply.js +28 -0
  298. package/src/engine/plan-summary.js +16 -0
  299. package/src/engine/preflight-text.js +27 -0
  300. package/src/engine/preflight.js +27 -0
  301. package/src/engine/project-brief.js +41 -0
  302. package/src/engine/project-context.js +49 -0
  303. package/src/engine/project-instructions.js +19 -0
  304. package/src/engine/py-imports.js +31 -0
  305. package/src/engine/relay-analysis.js +44 -0
  306. package/src/engine/relay-digest.js +42 -0
  307. package/src/engine/route-llm.js +25 -0
  308. package/src/engine/rule-text.js +12 -0
  309. package/src/engine/self-assessment.js +33 -0
  310. package/src/engine/steps-block.js +19 -0
  311. package/src/engine/ux-violations-leak.js +43 -0
  312. package/src/engine/vuln-facts.js +37 -0
  313. package/src/fs/atomic-text.js +45 -0
  314. package/src/fs/atomic-write.js +21 -0
  315. package/src/fs/backup-once.js +27 -0
  316. package/src/fs/config-path.js +39 -0
  317. package/src/fs/config-read.js +23 -0
  318. package/src/fs/config-write.js +60 -0
  319. package/src/fs/home-root.js +55 -0
  320. package/src/fs/load-config.js +36 -0
  321. package/src/fs/os-errors.js +26 -0
  322. package/src/fs/permissions.js +48 -0
  323. package/src/mcp/boot-warmup.js +9 -0
  324. package/src/mcp/call-tool.js +20 -0
  325. package/src/mcp/client-info.js +35 -0
  326. package/src/mcp/engine-rules.js +16 -0
  327. package/src/mcp/handle-dlp.js +37 -0
  328. package/src/mcp/handle-licence.js +46 -0
  329. package/src/mcp/handle-list.js +15 -0
  330. package/src/mcp/handle-memory.js +37 -0
  331. package/src/mcp/handle-skill-fetch.js +50 -0
  332. package/src/mcp/handle-skill.js +38 -0
  333. package/src/mcp/licence-text.js +29 -0
  334. package/src/mcp/prompt-licence.js +11 -0
  335. package/src/mcp/server-create.js +33 -0
  336. package/src/mcp/server-main.js +39 -0
  337. package/src/mcp/tool-dispatch.js +28 -0
  338. package/src/mcp/tool-dlp.js +20 -0
  339. package/src/mcp/tool-licence.js +17 -0
  340. package/src/mcp/tool-memory.js +32 -0
  341. package/src/mcp/tool-skill.js +24 -0
  342. package/src/mcp/tools-list.js +13 -0
  343. package/src/memory/exports.js +5 -0
  344. package/src/memory/memory-filter.js +32 -0
  345. package/src/memory/memory-gate.js +21 -0
  346. package/src/memory/memory-store.js +44 -0
  347. package/src/net/auth-browser.js +49 -0
  348. package/src/net/auth-endpoints.js +33 -0
  349. package/src/net/local-fetch.js +31 -0
  350. package/src/net/loopback.js +8 -0
  351. package/src/net/proxy-env.js +59 -0
  352. package/src/project-memory/batches.js +17 -0
  353. package/src/project-memory/cahiers.js +42 -0
  354. package/src/project-memory/decision-settle.js +15 -0
  355. package/src/project-memory/decisions.js +36 -0
  356. package/src/project-memory/index-build.js +35 -0
  357. package/src/project-memory/memory-build.js +16 -0
  358. package/src/project-memory/memory-tags.js +40 -0
  359. package/src/project-memory/pending.js +24 -0
  360. package/src/project-memory/qa-apply.js +39 -0
  361. package/src/project-memory/qa-tags.js +28 -0
  362. package/src/project-memory/recall.js +38 -0
  363. package/src/project-memory/store.js +37 -0
  364. package/src/project-memory/window.js +13 -0
  365. package/src/rules/rules-advisor.js +17 -0
  366. package/src/rules/rules-frugality.js +17 -0
  367. package/src/rules/rules-load.js +56 -0
  368. package/src/rules/rules-project.js +16 -0
  369. package/src/rules/rules-registry.js +32 -0
  370. package/src/rules/rules-validate-pricing.js +22 -0
  371. package/src/rules/rules-validate-scan.js +45 -0
  372. package/src/rules/rules-validate.js +53 -0
  373. package/src/teardown/consent.js +31 -0
  374. package/src/teardown/flags.js +39 -0
  375. package/src/teardown/main.js +41 -0
  376. package/src/teardown/plan.js +31 -0
  377. package/src/teardown/remove-entry.js +39 -0
  378. package/src/teardown/remove-file.js +37 -0
  379. package/src/teardown/remove-toml.js +33 -0
  380. package/src/teardown/report.js +34 -0
  381. package/src/types/ast.d.ts +40 -0
  382. package/src/types/auto-ask.d.ts +6 -0
  383. package/src/types/auto-orch.d.ts +59 -0
  384. package/src/types/auto.d.ts +45 -0
  385. package/src/types/capability.d.ts +12 -0
  386. package/src/types/cli-auto-gate.d.ts +45 -0
  387. package/src/types/cli-auto.d.ts +42 -0
  388. package/src/types/config.d.ts +53 -0
  389. package/src/types/control.d.ts +56 -0
  390. package/src/types/docs.d.ts +6 -0
  391. package/src/types/doctrine.d.ts +22 -0
  392. package/src/types/llm.d.ts +28 -0
  393. package/src/types/mcp.d.ts +32 -0
  394. package/src/types/memory.d.ts +17 -0
  395. package/src/types/mission.d.ts +46 -0
  396. package/src/types/orchestrator.d.ts +33 -0
  397. package/src/types/routing.d.ts +25 -0
  398. package/src/types/rules.d.ts +30 -0
  399. package/src/types/snapshots.d.ts +25 -0
  400. package/src/types/teardown.d.ts +13 -0
  401. package/src/types/usage.d.ts +30 -0
@@ -0,0 +1,45 @@
1
+ // src/rules/rules-validate-scan.js — Zero Trust sur les règles du scan de patch reçues du serveur (lot Pro) :
2
+ // listes de chaînes bornées, expressions compilables, textes présents. La signature prouve l'origine, ceci
3
+ // prouve la FORME. Toute anomalie lève une erreur typée ; rien n'est « réparé » en silence.
4
+
5
+ const isObj = (/** @type {unknown} */ v) => !!v && typeof v === "object" && !Array.isArray(v);
6
+ const isStr = (/** @type {unknown} */ v) => typeof v === "string" && v.length > 0 && v.length <= 2000;
7
+ const strs = (/** @type {unknown} */ v) => Array.isArray(v) && v.length <= 200 && v.every(isStr);
8
+ /** @param {string} m @returns {Error} */
9
+ const bad = (m) => new Error(`Règles PipCode invalides (scan : ${m}).`);
10
+
11
+ /** @param {unknown} src @param {string} what */
12
+ function regex(src, what) {
13
+ if (!isStr(src)) throw bad(what);
14
+ try { new RegExp(/** @type {string} */ (src)); } catch { throw bad(`${what} non compilable`); }
15
+ }
16
+ /** @param {unknown} m @param {string} what */
17
+ function msg(m, what) {
18
+ const part = (/** @type {unknown} */ v) => isStr(v) || (isObj(v) && isStr(/** @type {Record<string, unknown>} */ (v).js) && isStr(/** @type {Record<string, unknown>} */ (v).py));
19
+ const o = /** @type {Record<string, unknown>} */ (m);
20
+ if (!isObj(m) || !part(o.rule) || !part(o.alt)) throw bad(`message ${what}`);
21
+ }
22
+
23
+ /** @param {unknown} scan @returns {ScanRules} */
24
+ export function parseScan(scan) {
25
+ const s = /** @type {Record<string, Record<string, unknown>>} */ (scan);
26
+ if (!isObj(scan) || !isObj(s.ast) || !isObj(s.graph) || !isObj(s.cheat) || !isObj(s.design)) throw bad("sections");
27
+ const { ast, graph, cheat, design } = s;
28
+ const callees = /** @type {Record<string, Record<string, unknown>>} */ (ast.callees);
29
+ if (!isObj(callees) || !isObj(callees.js) || !isObj(callees.py)) throw bad("callees");
30
+ for (const k of ["dangerous", "shell", "xssWrites", "xssCalls", "stringEval"]) if (!strs(callees.js[k])) throw bad(`callees.js.${k}`);
31
+ if (!strs(callees.py.dangerous) || !strs(ast.xssWriteAll) || !strs(ast.jsxSinks)) throw bad("listes ast");
32
+ for (const r of /** @type {string[]} */ (ast.xssWriteAll)) regex(r, "xssWriteAll");
33
+ regex(ast.secretNames, "secretNames");
34
+ if (!Number.isInteger(ast.minString) || /** @type {number} */ (ast.minString) < 1 || /** @type {number} */ (ast.minString) > 64) throw bad("minString");
35
+ const msgs = /** @type {Record<string, unknown>} */ (ast.msgs);
36
+ for (const k of ["dangerous", "shell", "stringEval", "xssCall", "xssWrite", "secret", "jsx"]) msg(msgs?.[k], `ast.${k}`);
37
+ msg(graph.cycle, "graph.cycle"); msg(graph.orphan, "graph.orphan");
38
+ for (const k of ["testFile", "tauto", "assert", "emptyCatch", "skip", "commented", "callAssign", "stub"]) regex(cheat[k], `cheat.${k}`);
39
+ const rules = /** @type {{ rule?: unknown, alt?: unknown }[]} */ (cheat.rules);
40
+ if (!Number.isInteger(cheat.commentedMin) || !Array.isArray(rules) || rules.length !== 5 || !rules.every((r) => isObj(r) && isStr(r.rule) && isStr(r.alt))) throw bad("cheat.rules");
41
+ const shell = /** @type {{ rule?: unknown, patterns?: unknown }[]} */ (design.shellInUi);
42
+ if (!Array.isArray(shell) || !shell.every((v) => isObj(v) && isStr(v.rule) && strs(v.patterns)) || !isStr(design.shellAlt) || !isStr(design.charterAlt)) throw bad("design");
43
+ return /** @type {ScanRules} */ (scan);
44
+ }
45
+ // MODULE_COMPLETE
@@ -0,0 +1,53 @@
1
+ // src/rules/rules-validate.js — Zero Trust sur les règles reçues du serveur : la signature Ed25519 prouve
2
+ // l'origine, cette validation prouve la FORME (objets simples, chaînes bornées) avant tout usage par le
3
+ // moteur. Toute anomalie lève une erreur typée ; rien n'est « réparé » en silence.
4
+
5
+ import { parseScan } from "./rules-validate-scan.js";
6
+ import { parsePricing } from "./rules-validate-pricing.js";
7
+
8
+ export const SKILL_PLACEHOLDER = "{{SKILL_CONTENT}}";
9
+ const MAX_TEXT = 200_000;
10
+ const isObj = (/** @type {unknown} */ v) => !!v && typeof v === "object" && !Array.isArray(v);
11
+ const isStrArr = (/** @type {unknown} */ v) => Array.isArray(v) && v.every((s) => typeof s === "string");
12
+ const isText = (/** @type {unknown} */ v) => typeof v === "string" && v.length > 0 && v.length <= MAX_TEXT;
13
+
14
+ /** @param {string} m @returns {Error} */
15
+ const bad = (m) => new Error(`Règles PipCode invalides (${m}).`);
16
+
17
+ /** @param {string} text @returns {Record<string, unknown>} */
18
+ function parseObject(text) {
19
+ if (typeof text !== "string" || text.length > 1_000_000) throw bad("taille");
20
+ /** @type {unknown} */ let o;
21
+ try { o = JSON.parse(text); } catch { throw bad("JSON illisible"); }
22
+ if (!isObj(o) || /** @type {Record<string, unknown>} */ (o).v !== 1) throw bad("version");
23
+ return /** @type {Record<string, unknown>} */ (o);
24
+ }
25
+
26
+ /** Lot « base » (accessible à tous) → champs du registre. @param {string} text */
27
+ export function parseBaseRules(text) {
28
+ const o = parseObject(text);
29
+ const prompts = /** @type {Record<string, unknown>} */ (o.prompts);
30
+ if (!isObj(o.domains) || !isObj(o.patterns) || !isObj(o.glossary) || !isObj(prompts)) throw bad("lot base incomplet");
31
+ const plan = /** @type {Record<string, unknown>} */ (o.plan);
32
+ const imp = /** @type {Record<string, unknown>} */ (plan?.impact);
33
+ if (!isObj(plan) || !isStrArr(plan.steps) || !isObj(imp) || !["base", "perDomain", "perRole", "perRule", "perFiche", "filesPerDomain", "filesBase"].every((k) => Number.isFinite(imp[k]))) throw bad("plan (étapes, impact)");
34
+ if (!isText(prompts.analysis) || !isText(prompts.mission) || !isText(prompts.master)) throw bad("prompts de base");
35
+ if (/** @type {string} */ (prompts.master).split(SKILL_PLACEHOLDER).length !== 2) throw bad("prompt maître : emplacement de fiche");
36
+ for (const d of Object.values(/** @type {Record<string, unknown>} */ (o.domains))) {
37
+ const x = /** @type {Record<string, unknown>} */ (d);
38
+ if (!isObj(x) || typeof x.label !== "string" || !isStrArr(x.keywords) || !isStrArr(x.roles) || !isStrArr(x.fiches)) throw bad("domaine");
39
+ }
40
+ return { domains: /** @type {Record<string, BusinessDomain>} */ (o.domains), patterns: /** @type {EngineRules["patterns"]} */ (o.patterns), glossary: /** @type {EngineRules["glossary"]} */ (o.glossary), analysis: /** @type {string} */ (prompts.analysis), mission: /** @type {string} */ (prompts.mission), master: /** @type {string} */ (prompts.master), plan: /** @type {EngineRules["plan"]} */ (plan), pricing: parsePricing(o.pricing) };
41
+ }
42
+
43
+ /** Lot « pro » (essai / Pro) → UX + prompt de patch. @param {string} text */
44
+ export function parseProRules(text) {
45
+ const o = parseObject(text);
46
+ const ux = /** @type {Record<string, unknown>} */ (o.ux);
47
+ const prompts = /** @type {Record<string, unknown>} */ (o.prompts);
48
+ const prefix = /** @type {Record<string, unknown>} */ (o.prefix);
49
+ if (!isObj(ux) || !isObj(ux.design) || !isStrArr(ux.universal) || !isObj(prompts) || !isText(prompts.patch) || !isText(prompts.decomp) || !isText(prompts.control)) throw bad("lot pro incomplet");
50
+ if (!isObj(prefix) || !Object.values(prefix).every((s) => typeof s === "string" && s.length <= 400)) throw bad("préfixe de mission");
51
+ return { ux: /** @type {EngineRules["ux"]} */ (ux), patch: /** @type {string} */ (prompts.patch), decomp: /** @type {string} */ (prompts.decomp), control: /** @type {string} */ (prompts.control), prefix: /** @type {Record<string, string>} */ (prefix), scan: parseScan(o.scan) };
52
+ }
53
+ // MODULE_COMPLETE
@@ -0,0 +1,31 @@
1
+ // src/teardown/consent.js — Consentement interactif avant suppression (Phase 6).
2
+ // Requis en interactif. Implicite en non-interactif : le hook npm postuninstall
3
+ // et la CI n'ont pas de TTY pour répondre à une invite (le teardown ne touche
4
+ // que des artefacts appartenant à PipCode — inversion de l'empreinte setup).
5
+
6
+ import readline from "node:readline/promises";
7
+
8
+ /** @typedef {{ yes: boolean, dryRun: boolean }} ConsentFlags */
9
+
10
+ /** @param {ConsentFlags} flags @param {() => Promise<boolean>} [ask] @returns {Promise<boolean>} */
11
+ export async function requestConsent(flags, ask = askInteractively) {
12
+ if (flags.yes || flags.dryRun) return true;
13
+ if (!process.stdin.isTTY) {
14
+ console.log(" ℹ️ Contexte non interactif (hook de désinstallation / CI) : consentement implicite.");
15
+ return true;
16
+ }
17
+ return ask();
18
+ }
19
+
20
+ // Invite interactive y/N (accepte oui/yes/o/y ; tout le reste = refus, fail-safe).
21
+ /** @returns {Promise<boolean>} */
22
+ async function askInteractively() {
23
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
24
+ try {
25
+ const answer = (await rl.question(" ⚠️ Supprimer les artefacts PipCode listés ci-dessus ? [y/N] ")).trim().toLowerCase();
26
+ return answer === "y" || answer === "yes" || answer === "o" || answer === "oui";
27
+ } finally {
28
+ rl.close();
29
+ }
30
+ }
31
+ // MODULE_COMPLETE
@@ -0,0 +1,39 @@
1
+ // src/teardown/flags.js — Parsing des options de désinstallation (Phase 6).
2
+ // --yes (hooks npm/CI), --dry-run (plan sans écriture), --keep-config (épargne
3
+ // la config partagée), --ide-only / --config-only (périmètre), --help.
4
+
5
+ // Aide CLI du teardown (affichée par --help).
6
+ export const TEARDOWN_HELP = [
7
+ "Usage : npx pipcode teardown [options]",
8
+ "",
9
+ "Désinstallation propre de PipCode : retire l'entrée MCP PipCode de chaque",
10
+ "config IDE détectée (sans altérer les autres clés) et supprime la config",
11
+ "partagée ~/.pipcode/config.json (dossier retiré seulement s'il devient vide).",
12
+ "",
13
+ "Options :",
14
+ " --yes, -y Supprime sans invite (hooks npm / CI)",
15
+ " --dry-run Affiche le plan sans rien écrire",
16
+ " --keep-config Conserve la config partagée (licences / clés BYOK)",
17
+ " --ide-only Ne touche que les entrées MCP des configs IDE",
18
+ " --config-only Ne touche que la config partagée ~/.pipcode",
19
+ " --help, -h Affiche cette aide",
20
+ ].join("\n");
21
+
22
+ /** @param {string[]} argv @returns {TeardownFlags} */
23
+ export function parseTeardownFlags(argv) {
24
+ /** @type {TeardownFlags} */
25
+ const flags = { yes: false, dryRun: false, keepConfig: false, configOnly: false, ideOnly: false, help: false };
26
+ for (const a of argv) {
27
+ if (a === "--yes" || a === "-y") flags.yes = true;
28
+ else if (a === "--dry-run") flags.dryRun = true;
29
+ else if (a === "--keep-config") flags.keepConfig = true;
30
+ else if (a === "--config-only") flags.configOnly = true;
31
+ else if (a === "--ide-only") flags.ideOnly = true;
32
+ else if (a === "--help" || a === "-h") flags.help = true;
33
+ else throw new Error(`Option inconnue : "${a}". Essayez : npx pipcode teardown --help`);
34
+ }
35
+ if (flags.ideOnly && flags.configOnly) throw new Error("--ide-only et --config-only sont contradictoires.");
36
+ if (flags.configOnly && flags.keepConfig) throw new Error("--config-only et --keep-config sont contradictoires.");
37
+ return flags;
38
+ }
39
+ // MODULE_COMPLETE
@@ -0,0 +1,41 @@
1
+ // src/teardown/main.js — Orchestration du teardown (Phase 6) : flags → plan
2
+ // (dry-run affiché) → consentement → exécution best-effort → bilan.
3
+
4
+ import os from "node:os";
5
+ import { detectOS } from "../cli/detect-os.js";
6
+ import { resolvePlugctoRoot } from "../fs/home-root.js";
7
+ import { parseTeardownFlags, TEARDOWN_HELP } from "./flags.js";
8
+ import { buildTeardownPlan } from "./plan.js";
9
+ import { requestConsent } from "./consent.js";
10
+ import { removeIdeEntry } from "./remove-entry.js";
11
+ import { removeSharedConfig } from "./remove-file.js";
12
+ import { printPlan, printResults } from "./report.js";
13
+
14
+ /** @param {TeardownCtx} [ctx] @returns {Promise<TeardownSummary>} */
15
+ export async function runTeardown(ctx = {}) {
16
+ const env = ctx.env || process.env;
17
+ const home = ctx.home || os.homedir();
18
+ const flags = parseTeardownFlags(ctx.argv || process.argv.slice(2));
19
+ if (flags.help) { console.log(TEARDOWN_HELP); return { removed: 0, absent: 0, errors: 0, dryRun: true }; }
20
+ const configDir = resolvePlugctoRoot(env); // même racine résiliente que le setup
21
+ const plan = buildTeardownPlan(flags, { configDir, osName: ctx.osName || detectOS(), env, home });
22
+ console.log("\n🧹 Teardown PipCode — artefacts détectés :");
23
+ printPlan(plan);
24
+ if (flags.dryRun || !plan.length) {
25
+ console.log(flags.dryRun ? "\n (dry-run : aucun changement effectué)" : "\n ✅ Rien à désinstaller.");
26
+ return { removed: 0, absent: 0, errors: 0, dryRun: flags.dryRun };
27
+ }
28
+ if (!(await requestConsent(flags))) {
29
+ console.log(" ✅ Annulé — aucun changement effectué.");
30
+ return { removed: 0, absent: 0, errors: 0, dryRun: false };
31
+ }
32
+ const results = [];
33
+ for (const a of plan) {
34
+ const r = a.kind === "ide-entry"
35
+ ? await removeIdeEntry(a.path, a.schema || "mcpServers")
36
+ : await removeSharedConfig(a.path);
37
+ results.push({ ...r, path: a.path, label: a.label });
38
+ }
39
+ return printResults(results);
40
+ }
41
+ // MODULE_COMPLETE
@@ -0,0 +1,31 @@
1
+ // src/teardown/plan.js — Inventaire des artefacts installés par setup (Phase 6).
2
+ // Inversion exacte de l'empreinte : entrée MCP `pipcode` dans les configs IDE
3
+ // (ideConfigPaths = source unique de vérité, aucun chemin codé en dur) +
4
+ // config partagée ~/.pipcode/config.json. Les configs IDE inexistantes sont
5
+ // exclues du plan (rien à retirer).
6
+
7
+ import path from "node:path";
8
+ import { ideConfigPaths } from "../cli/ide-paths.js";
9
+ import { sharedConfigPath } from "../fs/config-path.js";
10
+
11
+ /**
12
+ * @param {TeardownFlags} flags
13
+ * @param {{ configDir: string, osName?: string, env?: Record<string, string | undefined>, home?: string }} ctx
14
+ * @returns {TeardownAction[]}
15
+ */
16
+ export function buildTeardownPlan(flags, ctx) {
17
+ /** @type {TeardownAction[]} */
18
+ const actions = [];
19
+ if (!flags.configOnly) {
20
+ for (const e of ideConfigPaths(ctx.osName, ctx.env, ctx.home)) {
21
+ if (e.configExists) {
22
+ actions.push({ kind: "ide-entry", path: e.path, label: e.name, schema: e.schema || "mcpServers" });
23
+ }
24
+ }
25
+ }
26
+ if (!flags.ideOnly && !flags.keepConfig) {
27
+ actions.push({ kind: "config", path: sharedConfigPath(ctx.configDir), label: "Config partagée " + path.join(ctx.configDir, "config.json") });
28
+ }
29
+ return actions;
30
+ }
31
+ // MODULE_COMPLETE
@@ -0,0 +1,39 @@
1
+ // src/teardown/remove-entry.js — Retrait chirurgical de l'entrée MCP `pipcode`
2
+ // d'une config IDE (Phase 6). Préserve toutes les autres clés du fichier. Si le
3
+ // fichier ne contient plus RIEN après retrait (fichier créé par setup), il est
4
+ // supprimé : inversion exacte d'applySetup (merge → unmerge, created → delete).
5
+
6
+ import fs from "node:fs/promises";
7
+ import { loadConfig } from "../fs/load-config.js";
8
+ import { writeConfigAtomic } from "../fs/atomic-write.js";
9
+ import { SERVER_KEY } from "../cli/server-entry.js";
10
+ import { LEGACY_SERVER_KEYS } from "../cli/legacy-entry.js";
11
+ import { removeTomlEntry } from "./remove-toml.js";
12
+
13
+ /** @typedef {Error & { code?: string }} NodeErr */
14
+
15
+ /** @param {string} filePath @param {"mcpServers" | "servers" | "context_servers" | "toml"} [schema] @returns {Promise<RemoveResult>} */
16
+ export async function removeIdeEntry(filePath, schema = "mcpServers") {
17
+ if (schema === "toml") return removeTomlEntry(filePath);
18
+ try {
19
+ const config = await loadConfig(filePath);
20
+ const root = config[schema];
21
+ const bucket = /** @type {Record<string, unknown> | undefined} */ (root);
22
+ const keys = bucket && typeof bucket === "object" ? [SERVER_KEY, ...LEGACY_SERVER_KEYS].filter((k) => k in bucket) : [];
23
+ if (!bucket || keys.length === 0) return { status: "absent" }; // fichier inexistant, sans notre entrée (nom actuel ou ancien), ou schéma inattendu
24
+ for (const k of keys) delete bucket[k];
25
+ // Fichier « créé par setup » = config réduite à une racine de schéma vide
26
+ // (ex. { mcpServers: {} }) → suppression du fichier (inversion de created).
27
+ const onlyEmptySchemaRoot = Object.keys(config).length === 1 && Object.keys(bucket).length === 0;
28
+ if (onlyEmptySchemaRoot) {
29
+ await fs.rm(filePath, { force: true });
30
+ return { status: "file-removed" };
31
+ }
32
+ await writeConfigAtomic(filePath, config);
33
+ return { status: "removed" };
34
+ } catch (err) {
35
+ const e = /** @type {NodeErr} */ (err);
36
+ return { status: "error", error: e.message }; // best-effort : ne bloque pas les autres fichiers
37
+ }
38
+ }
39
+ // MODULE_COMPLETE
@@ -0,0 +1,37 @@
1
+ // src/teardown/remove-file.js — Suppression sécurisée de la config partagée
2
+ // ~/.pipcode/config.json (Phase 6). Zero Trust : le fichier n'est supprimé que
3
+ // s'il ressemble à une config PipCode (champs licenseKey/email/primary) — un
4
+ // fichier illisible ou étranger est conservé. Le dossier parent est retiré
5
+ // uniquement s'il devient vide (rmdir non-récursif : jamais rm -rf).
6
+
7
+ import fs from "node:fs/promises";
8
+ import path from "node:path";
9
+ import { warnIfBlocked } from "../fs/os-errors.js";
10
+
11
+ /** @typedef {Error & { code?: string }} NodeErr */
12
+
13
+ /** @param {string} configPath @returns {Promise<RemoveResult>} */
14
+ export async function removeSharedConfig(configPath) {
15
+ try {
16
+ let raw;
17
+ try {
18
+ raw = await fs.readFile(configPath, "utf8");
19
+ } catch (err) {
20
+ const e = /** @type {NodeErr} */ (err);
21
+ if (e && e.code === "ENOENT") return { status: "absent" };
22
+ throw err;
23
+ }
24
+ let cfg;
25
+ try { cfg = JSON.parse(raw); } catch { return { status: "kept-foreign" }; } // illisible : non vérifiable, conservé
26
+ if (!cfg || typeof cfg !== "object" || Array.isArray(cfg)) return { status: "kept-foreign" };
27
+ if (!("licenseKey" in cfg) && !("email" in cfg) && !("primary" in cfg)) return { status: "kept-foreign" };
28
+ await fs.rm(configPath, { force: true });
29
+ try { await fs.rmdir(path.dirname(configPath)); } catch { /* dossier non vide : conservé */ }
30
+ return { status: "removed" };
31
+ } catch (err) {
32
+ const e = /** @type {NodeErr} */ (err);
33
+ warnIfBlocked(`suppression de ${configPath}`, err); // AV/droits : averti proprement, pas de crash
34
+ return { status: "error", error: e.message }; // best-effort : listé au bilan
35
+ }
36
+ }
37
+ // MODULE_COMPLETE
@@ -0,0 +1,33 @@
1
+ // src/teardown/remove-toml.js — Retrait chirurgical de nos tables MCP `pipcode`
2
+ // du config.toml de Codex (inversion de apply-toml.js). Tout le reste du fichier
3
+ // est conservé ; si plus rien ne reste (fichier créé par setup), il est supprimé.
4
+ // Fichier que toml-merge refuse de traiter (chaînes multilignes) → status "error"
5
+ // honnête, jamais de réécriture à l'aveugle. Best-effort : ne bloque pas les autres.
6
+
7
+ import fs from "node:fs/promises";
8
+ import { SERVER_KEY } from "../cli/server-entry.js";
9
+ import { LEGACY_SERVER_KEYS } from "../cli/legacy-entry.js";
10
+ import { removeToml } from "../cli/toml-merge.js";
11
+ import { writeTextAtomic } from "../fs/atomic-text.js";
12
+
13
+ /** @typedef {Error & { code?: string }} NodeErr */
14
+
15
+ /** @param {string} filePath @returns {Promise<RemoveResult>} */
16
+ export async function removeTomlEntry(filePath) {
17
+ try {
18
+ const raw = await fs.readFile(filePath, "utf8");
19
+ const steps = [SERVER_KEY, ...LEGACY_SERVER_KEYS].reduce((acc, k) => { const r = removeToml(acc.text, k); return { text: r.text, changed: acc.changed || r.changed }; }, { text: raw, changed: false }); // nom actuel puis anciens noms
20
+ const { text, changed } = steps;
21
+ if (!changed) return { status: "absent" };
22
+ if (!text.trim()) {
23
+ await fs.rm(filePath, { force: true });
24
+ return { status: "file-removed" };
25
+ }
26
+ await writeTextAtomic(filePath, text);
27
+ return { status: "removed" };
28
+ } catch (err) {
29
+ const e = /** @type {NodeErr} */ (err);
30
+ return e.code === "ENOENT" ? { status: "absent" } : { status: "error", error: e.message };
31
+ }
32
+ }
33
+ // MODULE_COMPLETE
@@ -0,0 +1,34 @@
1
+ // src/teardown/report.js — Rendu du plan (dry-run) et du bilan de suppression
2
+ // (Phase 6). Best-effort : chaque échec est listé sans interrompre les autres.
3
+
4
+ const STATUS_LABEL = {
5
+ removed: "entrée PipCode retirée (fichier conservé)",
6
+ "file-removed": "fichier vidé puis supprimé (créé par setup, vide après retrait)",
7
+ absent: "déjà absent",
8
+ "kept-foreign": "conservé (contenu non PipCode — rien supprimé)",
9
+ error: "échec (non bloquant)",
10
+ };
11
+
12
+ /** @param {TeardownAction[]} plan @returns {void} */
13
+ export function printPlan(plan) {
14
+ if (!plan.length) { console.log(" (aucun artefact détecté)"); return; }
15
+ for (const a of plan) {
16
+ const detail = a.kind === "config" ? "suppression (dossier retiré seulement si vide)" : "retrait de l'entrée PipCode uniquement";
17
+ console.log(` • ${a.label} → ${a.path} (${detail})`);
18
+ }
19
+ }
20
+
21
+ /** @param {TeardownResult[]} results @returns {TeardownSummary} */
22
+ export function printResults(results) {
23
+ let removed = 0, absent = 0, errors = 0;
24
+ for (const r of results) {
25
+ const icon = r.status === "error" ? "⚠️ " : "✓";
26
+ console.log(` ${icon} ${r.label} : ${STATUS_LABEL[r.status]}${r.error ? " — " + r.error : ""}`);
27
+ if (r.status === "removed" || r.status === "file-removed") removed++;
28
+ else if (r.status === "absent" || r.status === "kept-foreign") absent++;
29
+ else errors++;
30
+ }
31
+ console.log(`\n Bilan : ${removed} retiré(s), ${absent} déjà absent(s)/conservé(s), ${errors} échec(s).`);
32
+ return { removed, absent, errors, dryRun: false };
33
+ }
34
+ // MODULE_COMPLETE
@@ -0,0 +1,40 @@
1
+ // src/types/ast.d.ts — Contrats du scanner AST (Tree-sitter WASM, v1.1).
2
+
3
+ // Node Tree-sitter (subset strict utilisé par le scanner).
4
+ interface AstNode {
5
+ type: string; text: string;
6
+ firstChild: AstNode | null; lastChild: AstNode | null;
7
+ firstNamedChild: AstNode | null; nextSibling: AstNode | null;
8
+ childCount: number; rootNode: AstNode;
9
+ child(index: number): AstNode | null;
10
+ }
11
+
12
+ // Parser initialisé avec une grammaire.
13
+ interface AstParser {
14
+ setLanguage(l: unknown): void;
15
+ parse(s: string): { rootNode: AstNode | null } | null;
16
+ }
17
+
18
+ // Runtime WASM chargé (Parser + grammaires par clé de langage).
19
+ interface AstRuntime {
20
+ Parser: new () => AstParser;
21
+ langs: Record<string, unknown>;
22
+ }
23
+
24
+ // Contexte de règles AST calculé par langage (js|ts|tsx|py).
25
+ interface AstContext {
26
+ isPy: boolean; isJsx: boolean; callType: string;
27
+ dangerousCallees: Set<string>;
28
+ shellCallees: Set<string> | null;
29
+ xssMemberWrites: Set<string> | null;
30
+ xssMemberCalls: Set<string> | null;
31
+ stringEvalCallees: Set<string> | null;
32
+ xssWriteAll: RegExp[]; secretRe: RegExp; minString: number; jsxSinks: Set<string>;
33
+ msgs: ScanRules["ast"]["msgs"];
34
+ }
35
+
36
+ // Section fichier d'un patch Unified Diff (découpage patch-file-sections.js).
37
+ interface Section {
38
+ file: string; added: string[]; removed: string[]; isNew: boolean;
39
+ }
40
+ // MODULE_COMPLETE
@@ -0,0 +1,6 @@
1
+ // src/types/auto-ask.d.ts — Pause « ASK_USER » du Mode Auto (fusion de déclarations, ambient global) : le plan attend la réponse de l'utilisateur
2
+ // (ce n'est pas un échec) ; `answer` = réponse transmise à la reprise.
3
+
4
+ interface AutoResult { asking?: boolean; question?: string; cancelled?: boolean; }
5
+ interface ResumeArgs { answer?: string; }
6
+ // MODULE_COMPLETE
@@ -0,0 +1,59 @@
1
+ // src/types/auto-orch.d.ts — Types de l'orchestrateur Auto (args, résultat, deps).
2
+ // Ambient global (aucun import/export). Référence PlugConfig/ProviderPrimary/
3
+ // CallLLMArgs/OrchestratorArgs/OrchestratorResult/MissionPlan/AmnesiaContext/AutoState.
4
+
5
+ /** Args de buildAutoPlan (need + projet + pcfg + cfg). */
6
+ interface AutoPlanArgs { need: string; /** Ajustements demandés sur le plan précédent. */ adjust?: string; projectPath: string; pcfg: { primary: ProviderPrimary }; cfg: PlugConfig; /** Instructions confidentielles (serveur) : transmises à la décomposition, JAMAIS persistées. */ instructions?: string; }
7
+
8
+ /** Args de runAutoStep (projet + consentement + pcfg + cfg). */
9
+ interface AutoStepArgs { projectPath: string; confirmed?: boolean; pcfg: { primary: ProviderPrimary }; cfg: PlugConfig; }
10
+
11
+ /** Args de runAutoRun (projet + consentement + maxSteps + pcfg + cfg). */
12
+ interface AutoRunArgs { projectPath: string; confirmed?: boolean; maxSteps?: number; pcfg: { primary: ProviderPrimary }; cfg: PlugConfig; }
13
+
14
+ /** Args de resumeAuto (projet + maxSteps + pcfg + cfg). */
15
+ interface ResumeArgs { projectPath: string; maxSteps?: number; pcfg: { primary: ProviderPrimary }; cfg: PlugConfig; }
16
+
17
+ /** Résultat lâche d'une opération Auto (branches isError/done/failed/needsConsent). */
18
+ interface AutoResult {
19
+ isError?: boolean; text?: string; runId?: string; tasks?: AutoTask[];
20
+ budget?: AutoBudget | AutoBudgetResult; quote?: string; consent?: boolean; status?: string;
21
+ needsConsent?: boolean; done?: boolean; failed?: boolean; task?: AutoTask;
22
+ error?: string; violations?: GuardViolation[]; progress?: string; summary?: string;
23
+ diff?: string; commit?: string; steps?: AutoResult[]; last?: AutoResult;
24
+ }
25
+
26
+ /** Dépendances injectées par index.js (anti-import circulaire). */
27
+ interface AutoDeps {
28
+ callLLM: (args: CallLLMArgs) => Promise<string>;
29
+ readProviderConfig?: unknown;
30
+ orchestrateLLM: (args: OrchestratorArgs, pcfg: { primary: ProviderPrimary }) => Promise<OrchestratorResult>;
31
+ readMissionContext: (missionPath: string) => Promise<MissionPlan | null>;
32
+ extractMission: (need: string, pcfg: { primary: ProviderPrimary } | null) => Promise<MissionPlan>;
33
+ writeMission: (mission: MissionPlan, missionPath: string) => Promise<void>;
34
+ missionContextPrefix: (mission: MissionPlan | null) => string;
35
+ loadAllDoctrine: (cfg: PlugConfig) => Promise<string>;
36
+ checkMissionGuard: (result: OrchestratorResult | null, mission: MissionPlan | null) => GuardResult;
37
+ parseJsonLoose: (raw: string, opts?: { arrays?: boolean; recover?: boolean }) => unknown;
38
+ logIteration: (missionPath: string, line: string) => Promise<void>;
39
+ patchMaxTokens: (bytes: number) => number;
40
+ ANALYSIS_MAX_TOKENS: number;
41
+ }
42
+
43
+ /** Contexte partagé des sous-fonctions de runAutoStep (évite la prolifération de params). */
44
+ interface StepCtx { deps: AutoDeps; state: AutoState; doctrine: string; missionContext: string; mission: MissionPlan; task: AutoTask; fileContent: string; pcfg: { primary: ProviderPrimary }; idx: number; projectPath: string; missionPath: string; }
45
+
46
+ /** Interface de l'orchestrateur Auto (retour de createAutoOrchestrator). */
47
+ interface AutoOrchestrator {
48
+ buildAutoPlan: (arg: AutoPlanArgs) => Promise<AutoResult>;
49
+ runAutoStep: (arg: AutoStepArgs) => Promise<AutoResult>;
50
+ runAutoRun: (arg: AutoRunArgs) => Promise<AutoResult>;
51
+ resumeAuto: (arg: ResumeArgs) => Promise<AutoResult>;
52
+ applyDiffSafe: (arg: ApplyDiffArgs) => Promise<{ commit: string; touched: string[] }>;
53
+ estimateRunBudget: (tasks: AutoTask[], mission: MissionPlan, fileSizes: Record<string, number>, pcfg: { primary: ProviderPrimary }) => AutoBudgetResult;
54
+ buildAmnesiaContext: (state: AutoState | null, doctrine: string, missionContext: string) => AmnesiaContext;
55
+ buildCorrectionSignal: (violations: GuardViolation[] | null | undefined) => string;
56
+ loadAutoState: (projectPath: string) => Promise<AutoState | null>;
57
+ saveAutoState: (projectPath: string, state: AutoState) => Promise<void>;
58
+ }
59
+ // MODULE_COMPLETE
@@ -0,0 +1,45 @@
1
+ // src/types/auto.d.ts — Types primitifs du Mode Auto (pricing, git, guard, budget).
2
+ // Ambient global (aucun import/export) : utilisables via JSDoc sans import.
3
+
4
+ /** Paire de prix modèle (USD pour 1 000 000 de tokens, in/out). */
5
+ interface PricePair { in: number; out: number; }
6
+
7
+ /** Table publique de prix modèles (provider → modèle → prix). */
8
+ type PricingTable = Record<string, Record<string, PricePair>>;
9
+
10
+ /** Config retry/backoff (maxRetries, baseMs). */
11
+ interface RetryConfig { maxRetries: number; baseMs: number; }
12
+
13
+ /** Erreur git enrichie (stderr capturé). */
14
+ interface GitError extends Error { stderr?: string; }
15
+
16
+ /** Violation émise par un Hook déterministe (re-attaque QA). */
17
+ interface GuardViolation { kind?: string; rule?: string; alternative?: string; }
18
+
19
+ /** Résultat du gate mission : bloqué (violations) ou autorisé. */
20
+ interface GuardResult {
21
+ blocked: boolean;
22
+ message?: string | null;
23
+ violations?: GuardViolation[];
24
+ }
25
+
26
+ /** Devis budgétaire agrégé (tokens + coût estimé). */
27
+ interface BudgetQuote { tokensEst: number; costUsdEst: number; }
28
+
29
+ /** Devis budgétaire détaillé (per-task) — champs relais additifs (optionnels). */
30
+ interface AutoBudgetResult {
31
+ tokensEst: number;
32
+ costUsdEst: number;
33
+ perTask: Array<{ id: string; file: string; tokens: number; relayTokens?: number }>;
34
+ relaysEst?: number;
35
+ relayTokensEst?: number;
36
+ }
37
+
38
+ /** Args d'applyDiffSafe (projet, fichier, diff, deps injectés). */
39
+ interface ApplyDiffArgs {
40
+ projectPath: string;
41
+ file: string;
42
+ diff: string;
43
+ deps: AutoDeps;
44
+ }
45
+ // MODULE_COMPLETE
@@ -0,0 +1,12 @@
1
+ // src/types/capability.d.ts — Types globaux du pré-flight de capacités (cap-*.js,
2
+ // preflight.js) : capacité requise, verdict par capacité, rapport d'un modèle.
3
+
4
+ type Capability = "vision" | "tools" | "media_generation";
5
+ /** Verdict d'une capacité : true/false CONNU, null = non confirmé. `source` = d'où ça vient. */
6
+ interface CapVerdict { cap: Capability; value: boolean | null; source: string; }
7
+ /** Rapport d'évaluation d'UN modèle (même forme pour Modèle 1 et Modèle 2). */
8
+ interface CapReport { ok: boolean; detail: CapVerdict[]; probed: boolean; }
9
+ /** Modèle à évaluer : sous-ensemble de ProviderPrimary (provider, base, key, model). */
10
+ interface CapModel { provider: ProviderName; base: string; key: string; model: string; }
11
+ /** Métadonnées niveau 1 (0 token) : capacités connues + libellé de la source. */
12
+ interface CapMeta { caps: Partial<Record<Capability, boolean>>; source: string; }
@@ -0,0 +1,45 @@
1
+ // src/types/cli-auto-gate.d.ts — Types du gate Mode Auto CLI (flags + dépendances).
2
+ // Ambient global (aucun import/export) : utilisables via JSDoc sans import.
3
+
4
+ /** Erreur Node enrichie (code errno + status HTTP pour les erreurs Worker). */
5
+ interface NodeErr extends Error {
6
+ code?: string;
7
+ status?: number;
8
+ }
9
+
10
+ /** Flags CLI parsés par parseAutoFlags (--need / --project / --max-steps / --yes / --require). */
11
+ interface AutoFlags {
12
+ need: string;
13
+ /** Remarques de l'utilisateur sur le plan proposé (--adjust). */
14
+ adjust?: string;
15
+ project: string;
16
+ maxSteps: number;
17
+ yes: boolean;
18
+ /** Réponse de l'utilisateur à une question en pause (`auto resume --answer`). */
19
+ answer?: string;
20
+ /** Capacités requises (pré-flight) : "vision,tools,media_generation". */
21
+ require?: string;
22
+ /** Tâche à instructions serveur (`auto plan --task audit`) ; ignorée par run/resume/ask. */
23
+ task?: string;
24
+ }
25
+
26
+ /** Résolution de session/essai des gates : tier + failure MCP éventuelle. */
27
+ interface SessionResolution {
28
+ session: LicenseSession | null;
29
+ tier: "pro" | "trial" | "lite";
30
+ failure?: McpTextContent[];
31
+ }
32
+
33
+ /** Dépendances injectées à gateAutoCli (helpers d'index.js chargés paresseusement). */
34
+ interface GateAutoDeps {
35
+ loadConfig: () => Promise<PlugConfig>;
36
+ ensureSession: (cfg: PlugConfig) => Promise<LicenseSession>;
37
+ readProviderConfig: () => { primary: ProviderPrimary | null };
38
+ resolveTrial: (cfg: PlugConfig) => Promise<SessionResolution>;
39
+ }
40
+
41
+ /** Résultat du gate Auto CLI : autorisé (cfg/pcfg/tier) ou bloqué (message). */
42
+ type GateAutoResult =
43
+ | { ok: true; cfg: PlugConfig; pcfg: { primary: ProviderPrimary }; tier: string }
44
+ | { ok: false; message: string };
45
+ // MODULE_COMPLETE