mnueron 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/INSTALL.md +125 -0
  2. package/LICENSE +28 -21
  3. package/NOTICE +164 -0
  4. package/README.md +443 -422
  5. package/dist/cli.js +114 -26
  6. package/dist/cli.js.map +1 -1
  7. package/dist/config.js +4 -1
  8. package/dist/config.js.map +1 -1
  9. package/dist/detectors/codex.js +138 -0
  10. package/dist/detectors/codex.js.map +1 -0
  11. package/dist/detectors/index.js +2 -0
  12. package/dist/detectors/index.js.map +1 -1
  13. package/dist/detectors/json_detector.js +1 -1
  14. package/dist/lib/context-engine/confidence.js +153 -0
  15. package/dist/lib/context-engine/confidence.js.map +1 -0
  16. package/dist/lib/context-engine/entities.js +179 -0
  17. package/dist/lib/context-engine/entities.js.map +1 -0
  18. package/dist/lib/context-engine/index.js +74 -0
  19. package/dist/lib/context-engine/index.js.map +1 -0
  20. package/dist/lib/context-engine/intent.js +139 -0
  21. package/dist/lib/context-engine/intent.js.map +1 -0
  22. package/dist/lib/context-engine/runbook-detector.js +206 -0
  23. package/dist/lib/context-engine/runbook-detector.js.map +1 -0
  24. package/dist/lib/date-anchors.js +351 -0
  25. package/dist/lib/date-anchors.js.map +1 -0
  26. package/dist/lib/temporal-intent.js +98 -0
  27. package/dist/lib/temporal-intent.js.map +1 -0
  28. package/dist/runbook/auto-extract.js +415 -0
  29. package/dist/runbook/auto-extract.js.map +1 -0
  30. package/dist/runbook/capture.js +214 -0
  31. package/dist/runbook/capture.js.map +1 -0
  32. package/dist/runbook/explain.js +154 -0
  33. package/dist/runbook/explain.js.map +1 -0
  34. package/dist/runbook/fingerprint.js +128 -0
  35. package/dist/runbook/fingerprint.js.map +1 -0
  36. package/dist/runbook/search.js +76 -0
  37. package/dist/runbook/search.js.map +1 -0
  38. package/dist/runbook/types.js +15 -0
  39. package/dist/runbook/types.js.map +1 -0
  40. package/dist/setup.js +32 -4
  41. package/dist/setup.js.map +1 -1
  42. package/dist/store/entity-extractor.js +69 -2
  43. package/dist/store/entity-extractor.js.map +1 -1
  44. package/dist/store/local-db.js +33 -0
  45. package/dist/store/local-db.js.map +1 -0
  46. package/dist/store/local.js +230 -229
  47. package/dist/store/local.js.map +1 -1
  48. package/dist/store/procedural.js +185 -0
  49. package/dist/store/procedural.js.map +1 -1
  50. package/dist/store/remote.js +73 -0
  51. package/dist/store/remote.js.map +1 -1
  52. package/dist/tools.js +393 -8
  53. package/dist/tools.js.map +1 -1
  54. package/package.json +63 -55
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/runbook/capture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,eAAe,EAAkB,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAc;IACpD,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,GAAG,GAAG,UAAU,EAAE,CAAC;IACzB,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACnC,6EAA6E;IAE7E,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAE7E,IAAI,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,8DAA8D,CAAC,CAAC;QAC5E,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAEhB,MAAM,cAAc,GAAG,MAAM,GAAG,CAAC,EAAE,EAAE,0CAA0C,CAAC,CAAC;QACjF,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC;YAC3B,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;YAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,kEAAkE,CAAC,CAAC;QAChF,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,EAAE,CAAC,CAAC;QACzC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;YACtB,OAAO,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,EAAE,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACnF,IAAI,EAAE,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CACT,eAAe,EAAE,CAAC,aAAa,UAAU,EAAE,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,0BAA0B,CACnI,CAAC;QACJ,CAAC;QAED,cAAc;QACd,MAAM,KAAK,GAAG,EAAE;aACb,OAAO,CACN;;kBAEU,CACX;aACA,GAAG,CAAC,KAAK,EAAE,CAAC,IAAI,IAAI,CAA8D,CAAC;QAEtF,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,oDAAoD,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC;YAC/E,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACrC,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,EAAE,EAAE,8CAA8C,CAAC,CAAC;YAC7E,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,GAAG,EAAE,CAAC;gBACxC,MAAM,cAAc,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,EAAE,cAAc,CAAC,CAAC;gBACvD,OAAO;YACT,CAAC;QACH,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,mEAAmE,CAAC,CAAC;QACjF,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,EAAE,CAAC,CAAC;QACjC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;YAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,EAAE,EAAE,6CAA6C,EAAE,IAAI,CAAC,CAAC;QAE1F,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,MAAM,WAAW,GAAG,WAAW,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC;QACpD,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,EAAE,EAAE,6BAA6B,WAAW,KAAK,CAAC,CAAC;QAC/E,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,WAAW,CAAC;QAE7C,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,EAAE,EAAE,wBAAwB,cAAc,CAAC,EAAE,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC;QAE/F,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,GAAG,CAAC,gBAAgB,IAAI,SAAS,CAAC;QAEtE,qBAAqB;QACrB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,kBAAkB,SAAS,EAAE,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,kBAAkB,OAAO,IAAI,cAAc,CAAC,EAAE,EAAE,cAAc,CAAC,EAAE,CAAC,CAAC;QAC/E,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC,IAAI,IAAI,WAAW,EAAE,CAAC,CAAC;QACxD,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,kBAAkB,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,6BAA6B,EAAE,CAAC,CAAC;QACnF,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACzB,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YACrC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACxF,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,EAAE,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;QACxD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC1B,OAAO;QACT,CAAC;QAED,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,EAAE,CAAC,OAAO,CACR;;;;0EAIoE,CACrE,CAAC,GAAG,CACH,EAAE,EACF,SAAS,EACT,IAAI,EACJ,OAAO,IAAI,cAAc,CAAC,EAAE,EAAE,cAAc,CAAC,EAC7C,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EACrB,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EACxC,GAAG,EACH,GAAG,EACH,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,2DAA2D;QAC/E,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EACzB,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EACjB,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EACtB,QAAQ,EAAE,EACV,EAAE,CAAC,IAAI,IAAI,IAAI,EACf,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EACjB,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EACjB,EAAE,CAAC,gBAAgB,EACnB,cAAc,CACf,CAAC;QAEF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,IAAI,GAAG,CAAC,CAAC;QAC7D,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,oEAAoE,CAAC,CAAC;QACpF,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,uFAAuF,CAAC,CAAC;QACvG,CAAC;IACH,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;IAED,KAAK,UAAU,cAAc,CAC3B,EAAa,EACb,SAAiB,EACjB,EAAuC,EACvC,cAAsB;QAEtB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,mEAAmE,CAAC,CAAC;QACjF,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,EAAE,CAAC,CAAC;QACjC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,EAAE,EAAE,wCAAwC,EAAE,IAAI,CAAC,CAAC;QACrF,oBAAoB,CAAC,EAAE,EAAE,SAAS,EAAE;YAClC,eAAe,EAAE,EAAE,CAAC,IAAI;YACxB,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;YAC1C,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;YACtC,EAAE,EAAE,QAAQ,EAAE;YACd,IAAI,EAAE,EAAE,CAAC,IAAI;YACb,cAAc;YACd,SAAS,EAAE,EAAE,CAAC,gBAAgB;YAC9B,UAAU,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;SACjD,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,qBAAqB,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;IAC7D,CAAC;AACH,CAAC;AAQD,SAAS,SAAS,CAAC,IAAc;IAC/B,MAAM,GAAG,GAAgB,EAAE,CAAC;IAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,aAAa;YAAE,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;aAC9D,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YACtC,OAAO,CAAC,GAAG,CAAC;;;iCAGe,CAAC,CAAC;YAC7B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,GAAG,CAAC,EAAa,EAAE,MAAc;IACxC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1E,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,EAAa;IACvC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QAClC,IAAI,IAAI,KAAK,EAAE;YAAE,MAAM;QACvB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,EAAa;IACnC,MAAM,KAAK,GAA2C,EAAE,CAAC;IACzD,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;YAAE,MAAM;QAC9B,sDAAsD;QACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QAC3D,IAAI,QAAQ,EAAE,CAAC;YACb,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACrE,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACpC,CAAC;QACD,CAAC,EAAE,CAAC;IACN,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,EAAa,EAAE,MAAc,EAAE,UAAmB;IACxE,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,GAAG,CAAC,CAAC;IACxC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE;QAAE,OAAO,UAAU,CAAC;IACnC,OAAO,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,WAAW,CAAC,EAAuC,EAAE,cAAsB;IAClF,kDAAkD;IAClD,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC;IAC3D,MAAM,IAAI,GAAG,EAAE,CAAC,IAAI,IAAI,GAAG,CAAC;IAC5B,OAAO,OAAO,IAAI,IAAI,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AAC9C,CAAC;AAED,SAAS,cAAc,CAAC,EAAuC,EAAE,cAAsB;IACrF,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrE,OAAO,EAAE,CAAC,IAAI;QACZ,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,wBAAwB,GAAG,GAAG;QAC9C,CAAC,CAAC,2BAA2B,GAAG,GAAG,CAAC;AACxC,CAAC"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * `mnueron explain-error` — paste-an-error → suggested fixes.
3
+ *
4
+ * The simplest, least-invasive entry point to the Terminal Copilot:
5
+ * user copies an error from their terminal, pastes it into a prompt,
6
+ * and gets back known fixes (with confidence labels) or a suggestion
7
+ * to capture a new runbook if nothing matches.
8
+ *
9
+ * Usage:
10
+ * mnueron explain-error (reads stdin, ends on EOF)
11
+ * mnueron explain-error --file path/to/error.log (reads file)
12
+ * mnueron explain-error --text "fatal: ..." (one-liner via flag)
13
+ * mnueron explain-error --ns mnueron (namespace scope)
14
+ * mnueron explain-error --json (machine-readable output)
15
+ */
16
+ import { readFile } from 'node:fs/promises';
17
+ import { loadConfig, makeProvider } from '../config.js';
18
+ import { openLocalDb } from '../store/local-db.js';
19
+ import { fingerprintError } from './fingerprint.js';
20
+ import { searchRunbooks } from './search.js';
21
+ export async function cmdExplainError(args) {
22
+ const opts = parseArgs(args);
23
+ const errorText = await readErrorInput(opts);
24
+ if (!errorText.trim()) {
25
+ console.error('No error text provided. Pipe an error in, use --file, or --text "..."');
26
+ process.exit(1);
27
+ }
28
+ const cfg = loadConfig();
29
+ const provider = makeProvider(cfg);
30
+ const db = openLocalDb(cfg.dbPath);
31
+ const fp = fingerprintError(errorText);
32
+ if (!opts.json) {
33
+ console.log('');
34
+ console.log(`Fingerprint: ${fp.hash}${fp.tool ? ` (tool: ${fp.tool})` : ''}`);
35
+ if (fp.redactedCount > 0) {
36
+ console.log(`Redacted ${fp.redactedCount} secret${fp.redactedCount > 1 ? 's' : ''}: ${fp.redactedKinds.join(', ')}`);
37
+ }
38
+ console.log('');
39
+ }
40
+ const hits = await searchRunbooks(fp, {
41
+ db,
42
+ provider,
43
+ namespace: opts.namespace,
44
+ });
45
+ if (opts.json) {
46
+ console.log(JSON.stringify({
47
+ fingerprint: { hash: fp.hash, tool: fp.tool, normalized: fp.normalized },
48
+ redacted: { count: fp.redactedCount, kinds: fp.redactedKinds },
49
+ hits,
50
+ }, null, 2));
51
+ return;
52
+ }
53
+ if (hits.length === 0) {
54
+ console.log('No matching runbooks found.');
55
+ console.log('');
56
+ console.log('If you solve this and want to remember the fix, run:');
57
+ console.log(' mnueron runbook capture');
58
+ return;
59
+ }
60
+ console.log(`Found ${hits.length} runbook${hits.length > 1 ? 's' : ''}:`);
61
+ console.log('');
62
+ for (const [i, hit] of hits.entries()) {
63
+ renderHit(hit, i + 1);
64
+ }
65
+ console.log('');
66
+ console.log('After you apply a fix that worked:');
67
+ console.log(' mnueron runbook capture (or update an existing one)');
68
+ }
69
+ function renderHit(hit, index) {
70
+ const tag = hit.confidence === 'high'
71
+ ? '★ high'
72
+ : hit.confidence === 'medium'
73
+ ? '○ medium'
74
+ : '· low';
75
+ console.log(`${index}. [${tag}] ${hit.name}${hit.verified ? ' ✓ verified' : ''}`);
76
+ console.log(` ${hit.summary || '(no summary)'}`);
77
+ console.log(` reason: ${hit.reason}`);
78
+ if (hit.successCount + hit.failureCount > 0) {
79
+ console.log(` record: ${hit.successCount} success / ${hit.failureCount} failure`);
80
+ }
81
+ if (hit.steps.length > 0) {
82
+ console.log(' steps:');
83
+ for (const [j, step] of hit.steps.entries()) {
84
+ console.log(` ${j + 1}. ${step.step}`);
85
+ if (step.code) {
86
+ const trimmed = step.code.length > 200 ? step.code.slice(0, 197) + '...' : step.code;
87
+ console.log(` > ${trimmed.replace(/\n/g, '\n > ')}`);
88
+ }
89
+ }
90
+ }
91
+ console.log('');
92
+ }
93
+ function parseArgs(args) {
94
+ const out = { json: false };
95
+ for (let i = 0; i < args.length; i++) {
96
+ const a = args[i];
97
+ if (a === '--file' || a === '-f')
98
+ out.file = args[++i];
99
+ else if (a === '--text' || a === '-t')
100
+ out.text = args[++i];
101
+ else if (a === '--ns' || a === '--namespace')
102
+ out.namespace = args[++i];
103
+ else if (a === '--json')
104
+ out.json = true;
105
+ else if (a === '--help' || a === '-h') {
106
+ printHelp();
107
+ process.exit(0);
108
+ }
109
+ else {
110
+ console.error(`Unknown argument: ${a}`);
111
+ printHelp();
112
+ process.exit(1);
113
+ }
114
+ }
115
+ return out;
116
+ }
117
+ function printHelp() {
118
+ console.log(`mnueron explain-error — match a terminal error against known runbooks
119
+
120
+ mnueron explain-error Read error from stdin
121
+ mnueron explain-error --file <path> Read error from a file
122
+ mnueron explain-error --text "<error string>" Pass error inline
123
+
124
+ Options:
125
+ --ns <name> Limit search to a namespace (default: search all)
126
+ --json Machine-readable output
127
+ -h, --help Show this help
128
+
129
+ Examples:
130
+ git push 2>&1 | mnueron explain-error
131
+ mnueron explain-error --file last-build.log
132
+ mnueron explain-error --text "fatal: Unable to create '.git/index.lock'"`);
133
+ }
134
+ async function readErrorInput(opts) {
135
+ if (opts.text)
136
+ return opts.text;
137
+ if (opts.file) {
138
+ return readFile(opts.file, 'utf8');
139
+ }
140
+ // Stdin path
141
+ if (process.stdin.isTTY) {
142
+ console.log('Paste your error, then press Ctrl+D (Ctrl+Z on Windows) when done:');
143
+ }
144
+ return readStdin();
145
+ }
146
+ function readStdin() {
147
+ return new Promise((resolve, reject) => {
148
+ const chunks = [];
149
+ process.stdin.on('data', (c) => chunks.push(c));
150
+ process.stdin.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
151
+ process.stdin.on('error', reject);
152
+ });
153
+ }
154
+ //# sourceMappingURL=explain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explain.js","sourceRoot":"","sources":["../../src/runbook/explain.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAc;IAClD,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,SAAS,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;IAE7C,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;QACtB,OAAO,CAAC,KAAK,CAAC,uEAAuE,CAAC,CAAC;QACvF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,GAAG,GAAG,UAAU,EAAE,CAAC;IACzB,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAEnC,MAAM,EAAE,GAAG,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAEvC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAChF,IAAI,EAAE,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CACT,YAAY,EAAE,CAAC,aAAa,UAAU,EAAE,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACxG,CAAC;QACJ,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,EAAE,EAAE;QACpC,EAAE;QACF,QAAQ;QACR,SAAS,EAAE,IAAI,CAAC,SAAS;KAC1B,CAAC,CAAC;IAEH,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CACT,IAAI,CAAC,SAAS,CACZ;YACE,WAAW,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,EAAE;YACxE,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,aAAa,EAAE,KAAK,EAAE,EAAE,CAAC,aAAa,EAAE;YAC9D,IAAI;SACL,EACD,IAAI,EACJ,CAAC,CACF,CACF,CAAC;QACF,OAAO;IACT,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC;QACpE,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;QACzC,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,MAAM,WAAW,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1E,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,KAAK,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;QACtC,SAAS,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,8DAA8D,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,SAAS,CAAC,GAAe,EAAE,KAAa;IAC/C,MAAM,GAAG,GACP,GAAG,CAAC,UAAU,KAAK,MAAM;QACvB,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,GAAG,CAAC,UAAU,KAAK,QAAQ;YAC7B,CAAC,CAAC,UAAU;YACZ,CAAC,CAAC,OAAO,CAAC;IACd,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,MAAM,GAAG,KAAK,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAClF,OAAO,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,OAAO,IAAI,cAAc,EAAE,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IACxC,IAAI,GAAG,CAAC,YAAY,GAAG,GAAG,CAAC,YAAY,GAAG,CAAC,EAAE,CAAC;QAC5C,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,CAAC,YAAY,cAAc,GAAG,CAAC,YAAY,UAAU,CAAC,CAAC;IACtF,CAAC;IACD,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACzB,KAAK,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YAC3C,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;gBACrF,OAAO,CAAC,GAAG,CAAC,aAAa,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,cAAc,CAAC,EAAE,CAAC,CAAC;YACrE,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC;AAWD,SAAS,SAAS,CAAC,IAAc;IAC/B,MAAM,GAAG,GAAgB,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI;YAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;aAClD,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI;YAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;aACvD,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,aAAa;YAAE,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;aACnE,IAAI,CAAC,KAAK,QAAQ;YAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;aACpC,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YACtC,SAAS,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC;YACxC,SAAS,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;2EAc6D,CAAC,CAAC;AAC7E,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,IAAiB;IAC7C,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC,IAAI,CAAC;IAChC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC;IACD,aAAa;IACb,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,oEAAoE,CAAC,CAAC;IACpF,CAAC;IACD,OAAO,SAAS,EAAE,CAAC;AACrB,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAChD,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC/E,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Error fingerprinting.
3
+ *
4
+ * A fingerprint is a stable, low-entropy hash designed to:
5
+ * - SURVIVE noise (paths, timestamps, UUIDs, hex IDs change every
6
+ * run; we strip them before hashing)
7
+ * - BREAK on category change (a git error and a typescript error
8
+ * should never share a fingerprint)
9
+ *
10
+ * Algorithm:
11
+ * 1. Redact secrets first (reuses the existing `redact()` helper, so
12
+ * any API tokens or PEM blocks vanish before they touch the hash).
13
+ * 2. Normalize: strip paths, UUIDs, hex digests, timestamps, line:col
14
+ * positions, and collapse whitespace + lowercase.
15
+ * 3. SHA-256 the normalized string, take the first 12 hex chars as
16
+ * the fingerprint. 12 chars = 48 bits of entropy — enough to avoid
17
+ * collisions across a reasonable error vocabulary while staying
18
+ * short for human display.
19
+ * 4. Detect the originating tool from keywords so the UI can hint
20
+ * "this looks like a git problem" before searching.
21
+ *
22
+ * Pure module — no I/O, no DB. Trivially unit-testable.
23
+ */
24
+ import { createHash } from 'node:crypto';
25
+ import { redact } from '../store/redactor.js';
26
+ /** Build a fingerprint from a raw error string. */
27
+ export function fingerprintError(raw) {
28
+ const redaction = redact(raw);
29
+ const normalized = normalize(redaction.content);
30
+ const hash = createHash('sha256').update(normalized).digest('hex').slice(0, 12);
31
+ return {
32
+ hash,
33
+ normalized,
34
+ tool: detectTool(normalized),
35
+ redactedOriginal: redaction.content,
36
+ redactedCount: redaction.count,
37
+ redactedKinds: redaction.kinds,
38
+ };
39
+ }
40
+ /**
41
+ * Strip variable noise so the same root-cause error normalizes to the
42
+ * same string regardless of where/when it happened.
43
+ *
44
+ * Order matters: do the most specific patterns first (URLs, UUIDs) so
45
+ * less-specific ones (hex IDs, timestamps) don't eat their tokens.
46
+ */
47
+ export function normalize(s) {
48
+ return (s
49
+ // URLs first — they contain hex/UUID-looking substrings that
50
+ // would otherwise be matched by the generic patterns below.
51
+ .replace(/https?:\/\/[^\s'"<>]+/g, '<URL>')
52
+ // Windows paths: C:\path\to\file or C:/path/to/file
53
+ .replace(/[A-Z]:[\\/][\w\\/.~ \-+@]+(?=[\s'"`)\],]|$)/g, '<PATH>')
54
+ // POSIX absolute paths: /usr/local/..., /Users/me/...
55
+ .replace(/(?<![\w/])\/[\w./~+-]{2,}/g, '<PATH>')
56
+ // UUIDs (8-4-4-4-12)
57
+ .replace(/\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/gi, '<UUID>')
58
+ // Long hex digests (git SHAs, content hashes, MD5, SHA-1, SHA-256)
59
+ .replace(/\b[0-9a-f]{7,}\b/gi, '<HEX>')
60
+ // ISO dates and times — 2026-05-25, 14:32:11, 14:32:11.456
61
+ .replace(/\b\d{4}-\d{2}-\d{2}([Tt ]\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:?\d{2})?)?\b/g, '<DATETIME>')
62
+ .replace(/\b\d{1,2}:\d{2}(:\d{2}(\.\d+)?)?\b/g, '<TIME>')
63
+ // file.ext:line:col patterns
64
+ .replace(/:\d+:\d+/g, ':<L>:<C>')
65
+ // Standalone bare line numbers in stack-trace format "at file:42"
66
+ .replace(/:(\d{2,})\b/g, ':<L>')
67
+ // PIDs and other ad-hoc numerics that vary run-to-run
68
+ .replace(/\bpid[: ]?\d+/gi, 'pid:<N>')
69
+ .replace(/\bport[: ]?\d+/gi, 'port:<N>')
70
+ // Bracketed placeholder noise — strip the surrounding brackets so
71
+ // `[<DATETIME>] fatal: ...` and `fatal: ...` normalize identically.
72
+ // Only matches a placeholder we just produced (uppercase token), so
73
+ // legitimate bracketed content like `error[42]:` survives... almost.
74
+ // We do strip `error[42]:` too because [42] would normalize to <L> first.
75
+ .replace(/\[<[A-Z_]+>\]\s*/g, '')
76
+ // Quoted strings collapsed (paths leak through in quotes sometimes)
77
+ .replace(/'([^']{0,200})'/g, (_, inner) =>
78
+ // Keep short identifiers (likely keywords like 'main'), strip long ones
79
+ inner.length > 30 ? `'<STR>'` : `'${inner}'`)
80
+ // Collapse whitespace
81
+ .replace(/\s+/g, ' ')
82
+ .trim()
83
+ .toLowerCase());
84
+ }
85
+ /**
86
+ * Best-effort tool detection from the normalized error text.
87
+ *
88
+ * Returns one of: 'git', 'npm', 'pnpm', 'yarn', 'typescript', 'postgres',
89
+ * 'supabase', 'powershell', 'docker', 'kubectl', 'python', 'node', or
90
+ * undefined if we can't tell.
91
+ *
92
+ * Used to:
93
+ * - Filter the search-by-tool branch
94
+ * - Display a friendly hint ("Looks like a git error") in `explain-error`
95
+ * - Stamp `tool` on captured runbooks so future "show me all my
96
+ * git runbooks" works cleanly
97
+ */
98
+ export function detectTool(normalized) {
99
+ // Order matters — first match wins. Sort by SPECIFICITY of the pattern,
100
+ // not by what tool is most common. PowerShell's "The term '...' is not
101
+ // recognized" / "The token '...' is not a valid statement separator"
102
+ // are essentially impossible to false-match, so they go first — they
103
+ // catch the cases where surrounding text mentions other tools (e.g. a
104
+ // PowerShell error inside a session that was running git commands).
105
+ const sigs = [
106
+ [
107
+ 'powershell',
108
+ /the term '[^']+' is not (recognized|valid)|the token '[^']+' is not (a valid|valid)|\bcmdlet\b|\bps[1-9]\b|\binvoke-\w+\b|parsererror|invalidendofline/,
109
+ ],
110
+ ['supabase', /\bsupabase\b|supabase_migrations/],
111
+ ['postgres', /\bpostgres\b|sqlstate\b|\brelation\b.+\b(exists|does not exist)\b|duplicate key value|schema_migrations/],
112
+ ['typescript', /\berror ts\d{4}\b|\bcannot find module\b|jsx element|tsconfig/],
113
+ ['git', /\bfatal:|\bgit\b|\.git[/\\]|index\.lock|merge conflict|head[\^~]|origin\/main/],
114
+ ['npm', /\bnpm err\b|\bnpm error\b|npm warn\b|package-lock\.json/],
115
+ ['pnpm', /\bpnpm err\b|pnpm-lock/],
116
+ ['yarn', /\byarn error\b|yarn\.lock/],
117
+ ['docker', /\bdocker(d|fil)?\b|container\s+\w+|image\s+\w+:\w+|oci runtime/],
118
+ ['kubectl', /\bkubectl\b|\bkube-?\w+\b|namespace .* not found|pod\/\w+/],
119
+ ['python', /\btraceback\b|pip install|importerror|modulenotfound|python\d/],
120
+ ['node', /\bnode:internal\b|cannot find module|err_module|process exited with code/],
121
+ ];
122
+ for (const [name, re] of sigs) {
123
+ if (re.test(normalized))
124
+ return name;
125
+ }
126
+ return undefined;
127
+ }
128
+ //# sourceMappingURL=fingerprint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../../src/runbook/fingerprint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Runbook search — the matching logic for `mnueron explain-error`.
3
+ *
4
+ * Three-leg parallel search:
5
+ * 1. Exact fingerprint match against the stored error_fingerprints array.
6
+ * A hit means "we've literally solved this exact error before" →
7
+ * confidence: 'high'.
8
+ * 2. Tool match — if the fingerprint detected a tool, find other
9
+ * verified runbooks under that tool. Confidence: 'medium'.
10
+ * 3. Hybrid recall via provider.search() against ANY memory (not just
11
+ * runbooks). May surface a note the user saved that solved the
12
+ * issue without being formalized into a runbook. Confidence: 'low'.
13
+ *
14
+ * Results dedup on runbookId and sort by confidence then verified-ness
15
+ * then recency.
16
+ */
17
+ import { matchByFingerprint, matchByTool, } from '../store/procedural.js';
18
+ /**
19
+ * Run the three-leg search and return a merged, ranked list of runbook hits.
20
+ *
21
+ * `fingerprint.normalized` is what we send to the hybrid-recall leg so
22
+ * we benefit from the same noise stripping the fingerprint did.
23
+ */
24
+ export async function searchRunbooks(fingerprint, opts) {
25
+ const perLegLimit = opts.perLegLimit ?? 5;
26
+ // Leg 1: exact fingerprint match
27
+ const fingerprintHits = matchByFingerprint(opts.db, fingerprint.hash, opts.namespace);
28
+ // Leg 2: tool match (only if we detected a tool)
29
+ const toolHits = fingerprint.tool
30
+ ? matchByTool(opts.db, fingerprint.tool, opts.namespace, perLegLimit)
31
+ : [];
32
+ // Leg 3: hybrid recall against any memory in the namespace.
33
+ // Note: provider.search returns Memory[] not ExtendedProcedural[], so
34
+ // we'll need to convert. We're using it as a "fuzzy signal" only; for
35
+ // anything it returns we look up the corresponding runbook (if any)
36
+ // by id-prefix match against procedural rows. In v1 of this MVP we
37
+ // simply skip leg 3 if no fingerprint/tool hits — the procedural
38
+ // table is the source of truth. This keeps the implementation tight.
39
+ // TODO Phase 2: implement true fuzzy-recall fallback that surfaces
40
+ // raw memories (not just runbooks).
41
+ // We invoke provider so the import is still useful and we leave a
42
+ // breadcrumb for future work.
43
+ void opts.provider;
44
+ // Merge + dedup
45
+ const seen = new Set();
46
+ const hits = [];
47
+ for (const r of fingerprintHits) {
48
+ if (seen.has(r.id))
49
+ continue;
50
+ seen.add(r.id);
51
+ hits.push(toHit(r, 'high', 'exact fingerprint match'));
52
+ }
53
+ for (const r of toolHits) {
54
+ if (seen.has(r.id))
55
+ continue;
56
+ seen.add(r.id);
57
+ hits.push(toHit(r, r.verified ? 'medium' : 'low', `verified runbook for tool=${fingerprint.tool}`));
58
+ }
59
+ return hits;
60
+ }
61
+ function toHit(r, confidence, reason) {
62
+ return {
63
+ runbookId: r.id,
64
+ name: r.name,
65
+ summary: r.summary,
66
+ steps: r.steps,
67
+ confidence,
68
+ reason,
69
+ successCount: r.success_count,
70
+ failureCount: r.failure_count,
71
+ verified: r.verified,
72
+ os: r.os ?? undefined,
73
+ tool: r.tool ?? undefined,
74
+ };
75
+ }
76
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/runbook/search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,EACL,kBAAkB,EAClB,WAAW,GAEZ,MAAM,wBAAwB,CAAC;AAehC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,WAAwB,EACxB,IAAmB;IAEnB,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC;IAE1C,iCAAiC;IACjC,MAAM,eAAe,GAAG,kBAAkB,CAAC,IAAI,CAAC,EAAE,EAAE,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IAEtF,iDAAiD;IACjD,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI;QAC/B,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC;QACrE,CAAC,CAAC,EAAE,CAAC;IAEP,4DAA4D;IAC5D,sEAAsE;IACtE,sEAAsE;IACtE,oEAAoE;IACpE,mEAAmE;IACnE,iEAAiE;IACjE,qEAAqE;IACrE,mEAAmE;IACnE,oCAAoC;IACpC,kEAAkE;IAClE,8BAA8B;IAC9B,KAAK,IAAI,CAAC,QAAQ,CAAC;IAEnB,gBAAgB;IAChB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,IAAI,GAAiB,EAAE,CAAC;IAE9B,KAAK,MAAM,CAAC,IAAI,eAAe,EAAE,CAAC;QAChC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAAE,SAAS;QAC7B,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,yBAAyB,CAAC,CAAC,CAAC;IACzD,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAAE,SAAS;QAC7B,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,CACP,KAAK,CACH,CAAC,EACD,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,EAC7B,6BAA6B,WAAW,CAAC,IAAI,EAAE,CAChD,CACF,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,KAAK,CACZ,CAAqB,EACrB,UAAoC,EACpC,MAAc;IAEd,OAAO;QACL,SAAS,EAAE,CAAC,CAAC,EAAE;QACf,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,UAAU;QACV,MAAM;QACN,YAAY,EAAE,CAAC,CAAC,aAAa;QAC7B,YAAY,EAAE,CAAC,CAAC,aAAa;QAC7B,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,SAAS;QACrB,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,SAAS;KAC1B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Mnueron Terminal Copilot — shared types.
3
+ *
4
+ * The Terminal Copilot recognizes repeated errors, looks them up in
5
+ * procedural memory, suggests prior fixes, and writes/updates runbooks
6
+ * on confirmation. This file holds the cross-module types.
7
+ *
8
+ * Storage strategy:
9
+ * We extend the existing `procedural_memories` table with optional
10
+ * columns (trigger_phrases, error_fingerprints, verified, os, tool,
11
+ * success_count, failure_count) rather than introducing a new table.
12
+ * Older runbooks remain valid — the new columns are nullable.
13
+ */
14
+ export {};
15
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/runbook/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
package/dist/setup.js CHANGED
@@ -10,6 +10,8 @@
10
10
  * → configure for hosted mode
11
11
  * mnueron setup --uninstall → remove from all tools
12
12
  */
13
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
14
+ import { homedir } from 'node:os';
13
15
  import { dirname, resolve } from 'node:path';
14
16
  import { fileURLToPath } from 'node:url';
15
17
  import { allDetectors } from './detectors/index.js';
@@ -22,6 +24,9 @@ export async function runSetup(opts = {}) {
22
24
  return runUninstall(detectors, opts);
23
25
  const entry = buildEntry(opts);
24
26
  const reports = [];
27
+ if (opts.hosted && opts.persistHosted !== false && !opts.dryRun) {
28
+ persistHostedConfig(opts.hosted.url, opts.hosted.token, opts.namespace);
29
+ }
25
30
  for (const d of detectors) {
26
31
  const status = d.status();
27
32
  if (!status.installed) {
@@ -82,14 +87,37 @@ function buildEntry(opts) {
82
87
  command: 'node',
83
88
  args: [MNUERON_ENTRY],
84
89
  };
90
+ const env = {};
85
91
  if (opts.hosted) {
86
- entry.env = {
87
- MNUERON_API_URL: opts.hosted.url,
88
- MNUERON_API_TOKEN: opts.hosted.token,
89
- };
92
+ env.MNUERON_API_URL = opts.hosted.url;
93
+ env.MNUERON_API_TOKEN = opts.hosted.token;
90
94
  }
95
+ if (opts.namespace)
96
+ env.MNUERON_NAMESPACE = opts.namespace;
97
+ if (Object.keys(env).length > 0)
98
+ entry.env = env;
91
99
  return entry;
92
100
  }
101
+ function persistHostedConfig(url, token, namespace) {
102
+ const dir = resolve(homedir(), '.mnueron');
103
+ const path = resolve(dir, 'config.json');
104
+ mkdirSync(dir, { recursive: true });
105
+ let existing = {};
106
+ if (existsSync(path)) {
107
+ try {
108
+ const raw = readFileSync(path, 'utf8');
109
+ existing = raw.trim() ? JSON.parse(raw) : {};
110
+ }
111
+ catch {
112
+ existing = {};
113
+ }
114
+ }
115
+ existing.apiUrl = url;
116
+ existing.apiToken = token;
117
+ if (namespace)
118
+ existing.defaultNamespace = namespace;
119
+ writeFileSync(path, JSON.stringify(existing, null, 2));
120
+ }
93
121
  /** Pretty-print the report for terminal output. */
94
122
  export function formatReport(reports) {
95
123
  const lines = [];
package/dist/setup.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"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"}
@@ -25,14 +25,71 @@ const MAX_CONTENT_CHARS = 12000;
25
25
  const MAX_ENTITIES = 25;
26
26
  const TIMEOUT_MS = 30000;
27
27
  export const ENTITY_EXTRACTION_ENABLED = (process.env.MNUERON_ENABLE_ENTITY_EXTRACTION ?? '').toLowerCase() === 'true';
28
+ // Process-wide circuit breaker. When either provider returns 429, we suspend
29
+ // extraction for a cooldown window so a single rate-limit hit doesn't turn
30
+ // into thousands of follow-on warnings (and doesn't keep consuming whatever
31
+ // quota remains in shorter time buckets). Saves continue with no entity tags.
32
+ //
33
+ // Cooldowns by detected scope:
34
+ // - "per day" -> 1 hour (daily quotas reset at the provider's midnight;
35
+ // an hour balances "stop spamming" vs. "retry if user upgrades")
36
+ // - "per minute" -> 60 seconds
37
+ // - "per second" -> 5 seconds
38
+ // - unknown -> 5 minutes
39
+ //
40
+ // One warn-line per disable event keeps the console clean.
41
+ let extractionDisabledUntil = 0;
42
+ let warnedThisCooldown = false;
43
+ function isExtractionRateLimited() {
44
+ if (Date.now() < extractionDisabledUntil)
45
+ return true;
46
+ if (extractionDisabledUntil !== 0 && Date.now() >= extractionDisabledUntil) {
47
+ // Cooldown elapsed -- clear so the next 429 can warn again.
48
+ extractionDisabledUntil = 0;
49
+ warnedThisCooldown = false;
50
+ }
51
+ return false;
52
+ }
53
+ function disableExtractionAfter429(provider, body) {
54
+ const lower = body.toLowerCase();
55
+ let durationMs = 5 * 60 * 1000; // default: 5 minutes
56
+ let scope = 'unknown';
57
+ if (lower.includes('per day')) {
58
+ durationMs = 60 * 60 * 1000;
59
+ scope = 'per-day';
60
+ }
61
+ else if (lower.includes('per minute')) {
62
+ durationMs = 60 * 1000;
63
+ scope = 'per-minute';
64
+ }
65
+ else if (lower.includes('per second')) {
66
+ durationMs = 5 * 1000;
67
+ scope = 'per-second';
68
+ }
69
+ extractionDisabledUntil = Math.max(extractionDisabledUntil, Date.now() + durationMs);
70
+ if (!warnedThisCooldown) {
71
+ warnedThisCooldown = true;
72
+ const mins = Math.round(durationMs / 60000);
73
+ console.warn(`[mnueron/entity-extractor] ${provider} returned 429 (${scope}). ` +
74
+ `Suspending entity extraction for ~${mins}m. ` +
75
+ `Saves will continue with no entity tags. ` +
76
+ `Set MNUERON_ENABLE_ENTITY_EXTRACTION=false to opt out permanently.`);
77
+ }
78
+ }
28
79
  /**
29
80
  * Per-call gate. Same shape as hosted-side `shouldExtractEntities`.
30
81
  *
31
82
  * Explicit per-call opt-in (metadata.extract_entities: true OR BYOK key)
32
83
  * always runs, even on short content. The length floor only applies to
33
84
  * the env-var default path, to keep that from burning money on noise.
85
+ *
86
+ * Circuit breaker: a recent 429 from either provider disables this gate
87
+ * across the whole process for the cooldown window. Saves still complete
88
+ * normally -- they just skip the LLM call that would have failed anyway.
34
89
  */
35
90
  export function shouldExtractEntities(contentLen, metadata, minChars = MIN_LENGTH_CHARS) {
91
+ if (isExtractionRateLimited())
92
+ return false;
36
93
  if (metadata?.extract_entities === true)
37
94
  return true;
38
95
  const a = metadata?.byok_anthropic_key;
@@ -153,7 +210,12 @@ async function extractViaAnthropic(content, apiKey) {
153
210
  });
154
211
  if (!resp.ok) {
155
212
  const body = await resp.text();
156
- console.warn('[mnueron/entity-extractor/anthropic] HTTP ' + resp.status + ': ' + body.slice(0, 200));
213
+ if (resp.status === 429) {
214
+ disableExtractionAfter429('anthropic', body);
215
+ }
216
+ else {
217
+ console.warn('[mnueron/entity-extractor/anthropic] HTTP ' + resp.status + ': ' + body.slice(0, 200));
218
+ }
157
219
  return [];
158
220
  }
159
221
  const data = (await resp.json());
@@ -195,7 +257,12 @@ async function extractViaOpenAI(content, apiKey) {
195
257
  });
196
258
  if (!resp.ok) {
197
259
  const body = await resp.text();
198
- console.warn('[mnueron/entity-extractor/openai] HTTP ' + resp.status + ': ' + body.slice(0, 200));
260
+ if (resp.status === 429) {
261
+ disableExtractionAfter429('openai', body);
262
+ }
263
+ else {
264
+ console.warn('[mnueron/entity-extractor/openai] HTTP ' + resp.status + ': ' + body.slice(0, 200));
265
+ }
199
266
  return [];
200
267
  }
201
268
  const data = (await resp.json());