@minionry/minion 0.7.36

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 (476) hide show
  1. package/LICENSE +14 -0
  2. package/PRIVACY.md +357 -0
  3. package/README.md +57 -0
  4. package/THIRD_PARTY_NOTICES.md +245 -0
  5. package/bin/branding.js +4 -0
  6. package/bin/commands/browser-install.js +483 -0
  7. package/bin/commands/create-sandbox.js +542 -0
  8. package/bin/commands/fingerprint.js +101 -0
  9. package/bin/commands/login.js +400 -0
  10. package/bin/commands/logout.js +93 -0
  11. package/bin/commands/minions.js +211 -0
  12. package/bin/commands/sandboxes.js +309 -0
  13. package/bin/commands/status.js +298 -0
  14. package/bin/commands/whoami.js +153 -0
  15. package/bin/launch-env.js +35 -0
  16. package/bin/machine-identity.js +221 -0
  17. package/bin/machine-layout.js +200 -0
  18. package/bin/minion.js +839 -0
  19. package/bin/platform-endpoints.js +8 -0
  20. package/bin/postinstall.js +52 -0
  21. package/bin/pty-doctor.js +326 -0
  22. package/bin/pty-locator.js +110 -0
  23. package/bin/pty-provision.js +186 -0
  24. package/bin/sandbox/Dockerfile +78 -0
  25. package/bin/sandbox/entrypoint.sh +14 -0
  26. package/bin/sandbox/install-repo.sh +53 -0
  27. package/bin/sandbox/seccomp-userns.json +883 -0
  28. package/bin/sandbox-config.js +306 -0
  29. package/dist/bin/machine-identity.js +221 -0
  30. package/dist/bin/machine-layout.js +200 -0
  31. package/dist/electron-host/agent-lease.js +141 -0
  32. package/dist/electron-host/dom-driver.js +642 -0
  33. package/dist/electron-host/ipc-protocol.js +89 -0
  34. package/dist/electron-host/js-driver.js +216 -0
  35. package/dist/electron-host/view-manager.js +254 -0
  36. package/dist/server/cli/engine-resume.js +49 -0
  37. package/dist/server/cli/eta-estimator.js +278 -0
  38. package/dist/server/cli/headless/background-activity.js +109 -0
  39. package/dist/server/cli/headless/claude-invoker-process.js +614 -0
  40. package/dist/server/cli/headless/claude-invoker-stall.js +150 -0
  41. package/dist/server/cli/headless/claude-invoker-stream.js +555 -0
  42. package/dist/server/cli/headless/claude-invoker-tools.js +148 -0
  43. package/dist/server/cli/headless/claude-invoker.js +151 -0
  44. package/dist/server/cli/headless/engine-availability.js +92 -0
  45. package/dist/server/cli/headless/engine-notice.js +185 -0
  46. package/dist/server/cli/headless/haiku-assessments.js +293 -0
  47. package/dist/server/cli/headless/headless-logger.js +75 -0
  48. package/dist/server/cli/headless/index.js +9 -0
  49. package/dist/server/cli/headless/mcp-config.js +314 -0
  50. package/dist/server/cli/headless/native-timeout-detector.js +72 -0
  51. package/dist/server/cli/headless/output-utils.js +71 -0
  52. package/dist/server/cli/headless/prompt-utils.js +82 -0
  53. package/dist/server/cli/headless/resilient-runner.js +326 -0
  54. package/dist/server/cli/headless/retry-strategies.js +292 -0
  55. package/dist/server/cli/headless/runner.js +245 -0
  56. package/dist/server/cli/headless/stall-assessor.js +295 -0
  57. package/dist/server/cli/headless/tool-watchdog.js +447 -0
  58. package/dist/server/cli/headless/types.js +18 -0
  59. package/dist/server/cli/history-portability.js +85 -0
  60. package/dist/server/cli/improvisation-attachments.js +99 -0
  61. package/dist/server/cli/improvisation-history-store.js +121 -0
  62. package/dist/server/cli/improvisation-movements.js +137 -0
  63. package/dist/server/cli/improvisation-output-queue.js +34 -0
  64. package/dist/server/cli/improvisation-retry.js +8 -0
  65. package/dist/server/cli/improvisation-session-manager.js +1016 -0
  66. package/dist/server/cli/improvisation-types.js +31 -0
  67. package/dist/server/cli/plan-lifecycle.js +72 -0
  68. package/dist/server/cli/prompt-builders.js +371 -0
  69. package/dist/server/cli/retry/retry-best-result.js +28 -0
  70. package/dist/server/cli/retry/retry-context-loss.js +75 -0
  71. package/dist/server/cli/retry/retry-recovery-strategies.js +213 -0
  72. package/dist/server/cli/retry/retry-resume-strategy.js +20 -0
  73. package/dist/server/cli/retry/retry-runner-factory.js +92 -0
  74. package/dist/server/cli/retry/retry-tool-results.js +22 -0
  75. package/dist/server/cli/retry/retry-types.js +3 -0
  76. package/dist/server/engines/EngineEvent.js +57 -0
  77. package/dist/server/engines/claude/ClaudeCodeEngine.js +316 -0
  78. package/dist/server/engines/claude/claude-command.js +32 -0
  79. package/dist/server/engines/codex/CodexEngine.js +469 -0
  80. package/dist/server/engines/codex/codex-auth.js +203 -0
  81. package/dist/server/engines/codex/codex-invoker.js +205 -0
  82. package/dist/server/engines/codex/codex-provision.js +215 -0
  83. package/dist/server/engines/credentials/credential-probe.js +88 -0
  84. package/dist/server/engines/credentials/model-profiles.js +249 -0
  85. package/dist/server/engines/credentials/provider-credentials.js +146 -0
  86. package/dist/server/engines/engine-event-stream.js +52 -0
  87. package/dist/server/engines/execution/engine-session.js +380 -0
  88. package/dist/server/engines/factory.js +42 -0
  89. package/dist/server/engines/hermes/HermesEngine.js +628 -0
  90. package/dist/server/engines/hermes/hermes-auth.js +159 -0
  91. package/dist/server/engines/hermes/hermes-gateway-home.js +271 -0
  92. package/dist/server/engines/hermes/hermes-invoker.js +350 -0
  93. package/dist/server/engines/hermes/hermes-provision.js +318 -0
  94. package/dist/server/engines/read-only.js +20 -0
  95. package/dist/server/engines/types.js +27 -0
  96. package/dist/server/handlers/company-execution-registry.js +67 -0
  97. package/dist/server/handlers/company-handlers.js +514 -0
  98. package/dist/server/handlers/company-triggers.js +189 -0
  99. package/dist/server/handlers/company-types.js +3 -0
  100. package/dist/server/index.js +244 -0
  101. package/dist/server/mcp/app-tools-bridge.js +110 -0
  102. package/dist/server/mcp/app-tools-mcp-server.js +99 -0
  103. package/dist/server/mcp/bouncer-integration.js +744 -0
  104. package/dist/server/mcp/browser-mcp-server.js +915 -0
  105. package/dist/server/mcp/browser-redaction.js +103 -0
  106. package/dist/server/mcp/classifier/BouncerClassifier.js +3 -0
  107. package/dist/server/mcp/classifier/ClaudeBouncerClassifier.js +212 -0
  108. package/dist/server/mcp/classifier/factory.js +124 -0
  109. package/dist/server/mcp/classifier/health.js +54 -0
  110. package/dist/server/mcp/classifier/telemetry.js +0 -0
  111. package/dist/server/mcp/company-patterns.js +104 -0
  112. package/dist/server/mcp/department-profiles.js +133 -0
  113. package/dist/server/mcp/quality-bridge.js +153 -0
  114. package/dist/server/mcp/quality-mcp-server.js +105 -0
  115. package/dist/server/mcp/security-analysis.js +384 -0
  116. package/dist/server/mcp/security-audit.js +152 -0
  117. package/dist/server/mcp/security-patterns.js +314 -0
  118. package/dist/server/mcp/server.js +194 -0
  119. package/dist/server/mcp/test-utils/agent-simulator.js +301 -0
  120. package/dist/server/mcp/test-utils/e2e-agent.js +103 -0
  121. package/dist/server/mcp/test-utils/e2e-capture.js +92 -0
  122. package/dist/server/mcp/test-utils/e2e-client.js +116 -0
  123. package/dist/server/mcp/test-utils/e2e-fixtures.js +87 -0
  124. package/dist/server/mcp/test-utils/e2e-gating.js +8 -0
  125. package/dist/server/mcp/test-utils/e2e-harness.js +8 -0
  126. package/dist/server/mcp/test-utils/e2e-scenarios.js +105 -0
  127. package/dist/server/routes/files.js +18 -0
  128. package/dist/server/routes/improvise.js +64 -0
  129. package/dist/server/routes/index.js +7 -0
  130. package/dist/server/routes/instances.js +41 -0
  131. package/dist/server/routes/internal.js +900 -0
  132. package/dist/server/routes/notifications.js +110 -0
  133. package/dist/server/server-setup.js +282 -0
  134. package/dist/server/services/agent-push.js +148 -0
  135. package/dist/server/services/analytics.js +197 -0
  136. package/dist/server/services/apps/build.js +249 -0
  137. package/dist/server/services/apps/greenlight.js +199 -0
  138. package/dist/server/services/apps/install.js +101 -0
  139. package/dist/server/services/apps/layout.js +35 -0
  140. package/dist/server/services/apps/serve.js +665 -0
  141. package/dist/server/services/apps/space-apps.js +248 -0
  142. package/dist/server/services/auth.js +48 -0
  143. package/dist/server/services/browser/chrome-sandbox.js +245 -0
  144. package/dist/server/services/browser/chromium-launch-spec.js +51 -0
  145. package/dist/server/services/browser/claude-reasoner.js +669 -0
  146. package/dist/server/services/browser/debug-log.js +3 -0
  147. package/dist/server/services/browser/driver-state.js +546 -0
  148. package/dist/server/services/browser/electron-provision.js +256 -0
  149. package/dist/server/services/browser/host-internal.js +245 -0
  150. package/dist/server/services/browser/host-mock.js +334 -0
  151. package/dist/server/services/browser/host-types.js +3 -0
  152. package/dist/server/services/browser/host.js +1067 -0
  153. package/dist/server/services/browser/index.js +4 -0
  154. package/dist/server/services/browser/ipc-client.js +354 -0
  155. package/dist/server/services/browser/pipewire-sink.js +199 -0
  156. package/dist/server/services/browser/preflight.js +590 -0
  157. package/dist/server/services/browser/reasoning-agent.js +659 -0
  158. package/dist/server/services/browser/sandbox-policy.js +169 -0
  159. package/dist/server/services/browser/stderr-noise-filter.js +26 -0
  160. package/dist/server/services/browser/telemetry.js +107 -0
  161. package/dist/server/services/browser/xvfb-supervisor.js +139 -0
  162. package/dist/server/services/browser-frame-policy.js +56 -0
  163. package/dist/server/services/client-id.js +32 -0
  164. package/dist/server/services/collab/registry.js +408 -0
  165. package/dist/server/services/collab/session.js +489 -0
  166. package/dist/server/services/collab/text-diff.js +28 -0
  167. package/dist/server/services/collab/types.js +19 -0
  168. package/dist/server/services/e2ee-group-key.js +197 -0
  169. package/dist/server/services/e2ee-identity.js +203 -0
  170. package/dist/server/services/file-explorer-ops.js +328 -0
  171. package/dist/server/services/file-transfer-zip.js +188 -0
  172. package/dist/server/services/files.js +111 -0
  173. package/dist/server/services/git/branch-ops.js +62 -0
  174. package/dist/server/services/git/command.js +68 -0
  175. package/dist/server/services/git/commit-message.js +74 -0
  176. package/dist/server/services/git/diff-ops.js +56 -0
  177. package/dist/server/services/git/haiku.js +76 -0
  178. package/dist/server/services/git/head-watcher.js +226 -0
  179. package/dist/server/services/git/index.js +17 -0
  180. package/dist/server/services/git/log-ops.js +98 -0
  181. package/dist/server/services/git/merge-ops.js +314 -0
  182. package/dist/server/services/git/parsers.js +401 -0
  183. package/dist/server/services/git/remote-ops.js +192 -0
  184. package/dist/server/services/git/status-ops.js +105 -0
  185. package/dist/server/services/git/suggestion-ops.js +80 -0
  186. package/dist/server/services/git/tag-ops.js +36 -0
  187. package/dist/server/services/git/types.js +4 -0
  188. package/dist/server/services/git/worktree-ops.js +114 -0
  189. package/dist/server/services/instances.js +337 -0
  190. package/dist/server/services/model-catalog.js +247 -0
  191. package/dist/server/services/observability/posthog.js +153 -0
  192. package/dist/server/services/pathUtils.js +114 -0
  193. package/dist/server/services/plan/agent-loader.js +97 -0
  194. package/dist/server/services/plan/agent-manager.js +363 -0
  195. package/dist/server/services/plan/agent-resolver.js +74 -0
  196. package/dist/server/services/plan/agents/assess-stall.md +33 -0
  197. package/dist/server/services/plan/agents/browser-planner.md +53 -0
  198. package/dist/server/services/plan/agents/browser-reasoner.md +114 -0
  199. package/dist/server/services/plan/agents/check-injection.md +95 -0
  200. package/dist/server/services/plan/agents/classify-error.md +30 -0
  201. package/dist/server/services/plan/agents/code-review.md +142 -0
  202. package/dist/server/services/plan/agents/commit-message.md +28 -0
  203. package/dist/server/services/plan/agents/detect-context-loss.md +30 -0
  204. package/dist/server/services/plan/agents/execute-issue.md +58 -0
  205. package/dist/server/services/plan/agents/fix-quality.md +25 -0
  206. package/dist/server/services/plan/agents/plan-coordinator.md +72 -0
  207. package/dist/server/services/plan/agents/pr-description.md +29 -0
  208. package/dist/server/services/plan/agents/retry-task.md +27 -0
  209. package/dist/server/services/plan/agents/review-code.md +38 -0
  210. package/dist/server/services/plan/agents/review-quality.md +45 -0
  211. package/dist/server/services/plan/agents/triage-findings.md +78 -0
  212. package/dist/server/services/plan/agents/verify-review.md +57 -0
  213. package/dist/server/services/plan/approval-evaluator.js +143 -0
  214. package/dist/server/services/plan/board-archive.js +102 -0
  215. package/dist/server/services/plan/board-config.js +108 -0
  216. package/dist/server/services/plan/board-export.js +214 -0
  217. package/dist/server/services/plan/composer-prompt.js +115 -0
  218. package/dist/server/services/plan/composer.js +664 -0
  219. package/dist/server/services/plan/config-installer.js +103 -0
  220. package/dist/server/services/plan/dependency-resolver.js +137 -0
  221. package/dist/server/services/plan/executor.js +696 -0
  222. package/dist/server/services/plan/front-matter.js +43 -0
  223. package/dist/server/services/plan/issue-classification.js +10 -0
  224. package/dist/server/services/plan/issue-effort.js +182 -0
  225. package/dist/server/services/plan/issue-loader.js +35 -0
  226. package/dist/server/services/plan/issue-prompt-builder.js +152 -0
  227. package/dist/server/services/plan/issue-retry.js +42 -0
  228. package/dist/server/services/plan/issue-writer.js +102 -0
  229. package/dist/server/services/plan/metrics-collector.js +272 -0
  230. package/dist/server/services/plan/output-manager.js +77 -0
  231. package/dist/server/services/plan/parser-core.js +435 -0
  232. package/dist/server/services/plan/parser-migration.js +108 -0
  233. package/dist/server/services/plan/parser.js +258 -0
  234. package/dist/server/services/plan/plan-runner-factory.js +68 -0
  235. package/dist/server/services/plan/pm-timeline.js +320 -0
  236. package/dist/server/services/plan/progress-log.js +101 -0
  237. package/dist/server/services/plan/prompt-builder.js +142 -0
  238. package/dist/server/services/plan/quality-delta.js +274 -0
  239. package/dist/server/services/plan/readiness-planner.js +34 -0
  240. package/dist/server/services/plan/review-gate.js +409 -0
  241. package/dist/server/services/plan/review-report.js +134 -0
  242. package/dist/server/services/plan/review-verdict-stream.js +161 -0
  243. package/dist/server/services/plan/state-reconciler.js +238 -0
  244. package/dist/server/services/plan/template-diff.js +175 -0
  245. package/dist/server/services/plan/template-instantiator.js +516 -0
  246. package/dist/server/services/plan/template-manifest.js +56 -0
  247. package/dist/server/services/plan/template-types.js +3 -0
  248. package/dist/server/services/plan/trigger-evaluator.js +211 -0
  249. package/dist/server/services/plan/types.js +3 -0
  250. package/dist/server/services/plan/watcher.js +73 -0
  251. package/dist/server/services/platform-credentials.js +56 -0
  252. package/dist/server/services/platform-e2ee.js +421 -0
  253. package/dist/server/services/platform-envelope.js +102 -0
  254. package/dist/server/services/platform-heartbeat.js +88 -0
  255. package/dist/server/services/platform-reconnect.js +60 -0
  256. package/dist/server/services/platform-token-lifecycle.js +95 -0
  257. package/dist/server/services/platform-url.js +17 -0
  258. package/dist/server/services/platform.js +656 -0
  259. package/dist/server/services/runtime-info.js +9 -0
  260. package/dist/server/services/schedule/agent-schedule-store.js +232 -0
  261. package/dist/server/services/schedule/agent-scheduler.js +323 -0
  262. package/dist/server/services/schedule/daily-timing.js +105 -0
  263. package/dist/server/services/schedule/quality-schedule-launch.js +11 -0
  264. package/dist/server/services/schedule/quality-schedule-store.js +211 -0
  265. package/dist/server/services/schedule/quality-scheduler.js +215 -0
  266. package/dist/server/services/schedule/run-bootstrap.js +329 -0
  267. package/dist/server/services/schedule/schedule-store.js +238 -0
  268. package/dist/server/services/schedule/schedule-wire.js +77 -0
  269. package/dist/server/services/schedule/scheduler.js +310 -0
  270. package/dist/server/services/schedule/template-source.js +97 -0
  271. package/dist/server/services/sdk/agent-sessions.js +264 -0
  272. package/dist/server/services/sdk/agents.js +557 -0
  273. package/dist/server/services/sdk/app-endpoints.js +48 -0
  274. package/dist/server/services/sdk/app-tools.js +303 -0
  275. package/dist/server/services/sdk/audit.js +48 -0
  276. package/dist/server/services/sdk/browser-transport.js +188 -0
  277. package/dist/server/services/sdk/browser.js +605 -0
  278. package/dist/server/services/sdk/composer.js +129 -0
  279. package/dist/server/services/sdk/connect.js +273 -0
  280. package/dist/server/services/sdk/consent-cooldown.js +31 -0
  281. package/dist/server/services/sdk/endpoint-url.js +141 -0
  282. package/dist/server/services/sdk/endpoints.js +314 -0
  283. package/dist/server/services/sdk/file-change-notify.js +36 -0
  284. package/dist/server/services/sdk/files-app.js +163 -0
  285. package/dist/server/services/sdk/files-search.js +131 -0
  286. package/dist/server/services/sdk/files-transfer.js +279 -0
  287. package/dist/server/services/sdk/files-workspace.js +233 -0
  288. package/dist/server/services/sdk/git.js +520 -0
  289. package/dist/server/services/sdk/grant-store.js +318 -0
  290. package/dist/server/services/sdk/host-ops.js +84 -0
  291. package/dist/server/services/sdk/inference-claude.js +214 -0
  292. package/dist/server/services/sdk/inference.js +247 -0
  293. package/dist/server/services/sdk/live-registry.js +42 -0
  294. package/dist/server/services/sdk/local-app-bindings.js +71 -0
  295. package/dist/server/services/sdk/pipeline.js +190 -0
  296. package/dist/server/services/sdk/pm-execute.js +228 -0
  297. package/dist/server/services/sdk/pm-planning-tap.js +29 -0
  298. package/dist/server/services/sdk/pm-schedule.js +165 -0
  299. package/dist/server/services/sdk/pm.js +634 -0
  300. package/dist/server/services/sdk/quality-change-notify.js +20 -0
  301. package/dist/server/services/sdk/quality-schedule.js +165 -0
  302. package/dist/server/services/sdk/quality.js +602 -0
  303. package/dist/server/services/sdk/rate-limits.js +198 -0
  304. package/dist/server/services/sdk/registry.js +597 -0
  305. package/dist/server/services/sdk/revoke.js +86 -0
  306. package/dist/server/services/sdk/run-profile.js +41 -0
  307. package/dist/server/services/sdk/sandbox.js +89 -0
  308. package/dist/server/services/sdk/storage.js +110 -0
  309. package/dist/server/services/sdk/streams.js +147 -0
  310. package/dist/server/services/sdk/terminal.js +201 -0
  311. package/dist/server/services/sdk/test-utils/workshop-browser-app.js +466 -0
  312. package/dist/server/services/sentry.js +99 -0
  313. package/dist/server/services/settings.js +374 -0
  314. package/dist/server/services/snippets/expander.js +87 -0
  315. package/dist/server/services/snippets/index.js +6 -0
  316. package/dist/server/services/snippets/loader.js +119 -0
  317. package/dist/server/services/snippets/parser.js +52 -0
  318. package/dist/server/services/snippets/types.js +3 -0
  319. package/dist/server/services/snippets/watcher.js +60 -0
  320. package/dist/server/services/space-layout.js +80 -0
  321. package/dist/server/services/system-prompts.js +219 -0
  322. package/dist/server/services/terminal/pty-manager.js +206 -0
  323. package/dist/server/services/terminal/pty-utils.js +150 -0
  324. package/dist/server/services/timeline/assembler.js +890 -0
  325. package/dist/server/services/timeline/contract.js +196 -0
  326. package/dist/server/services/timeline/index.js +4 -0
  327. package/dist/server/services/websocket/agent-schedule-handlers.js +217 -0
  328. package/dist/server/services/websocket/apps-handlers.js +399 -0
  329. package/dist/server/services/websocket/ask-user-question-bridge.js +112 -0
  330. package/dist/server/services/websocket/autocomplete-index.js +415 -0
  331. package/dist/server/services/websocket/autocomplete-match.js +243 -0
  332. package/dist/server/services/websocket/autocomplete.js +407 -0
  333. package/dist/server/services/websocket/browser-agent-runtime.js +208 -0
  334. package/dist/server/services/websocket/browser-device-profile.js +46 -0
  335. package/dist/server/services/websocket/browser-handlers.js +377 -0
  336. package/dist/server/services/websocket/browser-host-broadcast.js +179 -0
  337. package/dist/server/services/websocket/browser-ice-config.js +121 -0
  338. package/dist/server/services/websocket/browser-payloads.js +222 -0
  339. package/dist/server/services/websocket/browser-viewer-lifecycle.js +84 -0
  340. package/dist/server/services/websocket/browser-viewer-registry.js +118 -0
  341. package/dist/server/services/websocket/collab-broadcast.js +11 -0
  342. package/dist/server/services/websocket/collab-handlers.js +116 -0
  343. package/dist/server/services/websocket/commit-suggestion-service.js +132 -0
  344. package/dist/server/services/websocket/debug-log.js +38 -0
  345. package/dist/server/services/websocket/dispatch-util.js +10 -0
  346. package/dist/server/services/websocket/engine-auth-handlers.js +323 -0
  347. package/dist/server/services/websocket/engine-credential-watcher.js +83 -0
  348. package/dist/server/services/websocket/engine-profile-handlers.js +92 -0
  349. package/dist/server/services/websocket/file-definition-handlers.js +180 -0
  350. package/dist/server/services/websocket/file-download-handler.js +291 -0
  351. package/dist/server/services/websocket/file-explorer-handlers.js +291 -0
  352. package/dist/server/services/websocket/file-search-handlers.js +267 -0
  353. package/dist/server/services/websocket/file-share-handlers.js +328 -0
  354. package/dist/server/services/websocket/file-transfer-http.js +361 -0
  355. package/dist/server/services/websocket/file-upload-handler.js +267 -0
  356. package/dist/server/services/websocket/file-utils.js +346 -0
  357. package/dist/server/services/websocket/git-branch-handlers.js +90 -0
  358. package/dist/server/services/websocket/git-diff-handlers.js +59 -0
  359. package/dist/server/services/websocket/git-handlers.js +212 -0
  360. package/dist/server/services/websocket/git-head-watcher.js +85 -0
  361. package/dist/server/services/websocket/git-log-handlers.js +104 -0
  362. package/dist/server/services/websocket/git-pr-handlers.js +56 -0
  363. package/dist/server/services/websocket/git-tag-handlers.js +53 -0
  364. package/dist/server/services/websocket/git-utils.js +11 -0
  365. package/dist/server/services/websocket/git-worktree-handlers.js +521 -0
  366. package/dist/server/services/websocket/handler-context.js +113 -0
  367. package/dist/server/services/websocket/handler.js +1197 -0
  368. package/dist/server/services/websocket/index.js +5 -0
  369. package/dist/server/services/websocket/movement-written-files.js +26 -0
  370. package/dist/server/services/websocket/msg-id-tracker.js +48 -0
  371. package/dist/server/services/websocket/plan-board-handlers.js +410 -0
  372. package/dist/server/services/websocket/plan-execution-handlers.js +244 -0
  373. package/dist/server/services/websocket/plan-handlers.js +67 -0
  374. package/dist/server/services/websocket/plan-helpers.js +161 -0
  375. package/dist/server/services/websocket/plan-issue-handlers.js +168 -0
  376. package/dist/server/services/websocket/plan-sprint-handlers.js +190 -0
  377. package/dist/server/services/websocket/plan-transfer-handlers.js +310 -0
  378. package/dist/server/services/websocket/pm-timeline-broadcast.js +28 -0
  379. package/dist/server/services/websocket/post-session-scan.js +132 -0
  380. package/dist/server/services/websocket/prompt-queue-handlers.js +96 -0
  381. package/dist/server/services/websocket/quality-agent-cost.js +229 -0
  382. package/dist/server/services/websocket/quality-agent-notes.js +113 -0
  383. package/dist/server/services/websocket/quality-change-activity.js +187 -0
  384. package/dist/server/services/websocket/quality-complexity.js +345 -0
  385. package/dist/server/services/websocket/quality-dependencies.js +445 -0
  386. package/dist/server/services/websocket/quality-duplication.js +162 -0
  387. package/dist/server/services/websocket/quality-eta.js +65 -0
  388. package/dist/server/services/websocket/quality-fingerprint.js +104 -0
  389. package/dist/server/services/websocket/quality-grading.js +575 -0
  390. package/dist/server/services/websocket/quality-handlers.js +48 -0
  391. package/dist/server/services/websocket/quality-linting.js +270 -0
  392. package/dist/server/services/websocket/quality-operations.js +54 -0
  393. package/dist/server/services/websocket/quality-persistence.js +410 -0
  394. package/dist/server/services/websocket/quality-review-agent.js +526 -0
  395. package/dist/server/services/websocket/quality-run.js +220 -0
  396. package/dist/server/services/websocket/quality-secrets.js +0 -0
  397. package/dist/server/services/websocket/quality-service.js +775 -0
  398. package/dist/server/services/websocket/quality-tools.js +383 -0
  399. package/dist/server/services/websocket/quality-triage-agent.js +101 -0
  400. package/dist/server/services/websocket/quality-types.js +149 -0
  401. package/dist/server/services/websocket/recommended-answers.js +28 -0
  402. package/dist/server/services/websocket/schedule-handlers.js +197 -0
  403. package/dist/server/services/websocket/sdk-agent-host.js +569 -0
  404. package/dist/server/services/websocket/sdk-browser-host.js +459 -0
  405. package/dist/server/services/websocket/sdk-composer-host.js +10 -0
  406. package/dist/server/services/websocket/sdk-git-host.js +115 -0
  407. package/dist/server/services/websocket/sdk-handlers.js +242 -0
  408. package/dist/server/services/websocket/sdk-pm-execution-host.js +63 -0
  409. package/dist/server/services/websocket/sdk-pm-schedule-host.js +21 -0
  410. package/dist/server/services/websocket/sdk-quality-schedule-host.js +34 -0
  411. package/dist/server/services/websocket/sdk-terminal-host.js +140 -0
  412. package/dist/server/services/websocket/session-handlers.js +565 -0
  413. package/dist/server/services/websocket/session-history.js +335 -0
  414. package/dist/server/services/websocket/session-initialization.js +315 -0
  415. package/dist/server/services/websocket/session-registry.js +340 -0
  416. package/dist/server/services/websocket/session-role-directory.js +39 -0
  417. package/dist/server/services/websocket/settings-handlers.js +276 -0
  418. package/dist/server/services/websocket/skill-handlers.js +324 -0
  419. package/dist/server/services/websocket/skill-watcher.js +83 -0
  420. package/dist/server/services/websocket/snippet-handlers.js +261 -0
  421. package/dist/server/services/websocket/tab-broadcast.js +35 -0
  422. package/dist/server/services/websocket/tab-event-buffer.js +110 -0
  423. package/dist/server/services/websocket/tab-event-replay.js +47 -0
  424. package/dist/server/services/websocket/tab-handlers.js +211 -0
  425. package/dist/server/services/websocket/terminal-handlers.js +268 -0
  426. package/dist/server/services/websocket/types.js +96 -0
  427. package/dist/server/types/company-messages.js +102 -0
  428. package/dist/server/utils/agent-manager.js +202 -0
  429. package/dist/server/utils/console-timestamps.js +24 -0
  430. package/dist/server/utils/file-store.js +112 -0
  431. package/dist/server/utils/paths.js +28 -0
  432. package/dist/server/utils/port-manager.js +43 -0
  433. package/dist/server/utils/port.js +204 -0
  434. package/electron-host/dist/agent-lease.js +141 -0
  435. package/electron-host/dist/capture-recovery.js +77 -0
  436. package/electron-host/dist/codec-policy.js +37 -0
  437. package/electron-host/dist/controller-channel.js +60 -0
  438. package/electron-host/dist/controller-handlers.js +153 -0
  439. package/electron-host/dist/device-emulator.js +106 -0
  440. package/electron-host/dist/dom-driver.js +642 -0
  441. package/electron-host/dist/domain-registry.js +159 -0
  442. package/electron-host/dist/domain-validators.js +308 -0
  443. package/electron-host/dist/editable-focus-reporter.js +143 -0
  444. package/electron-host/dist/fake-peer.test-util.js +105 -0
  445. package/electron-host/dist/host-log.js +31 -0
  446. package/electron-host/dist/host-wire.js +11 -0
  447. package/electron-host/dist/input-router.js +421 -0
  448. package/electron-host/dist/ipc-protocol.js +89 -0
  449. package/electron-host/dist/ipc-server.js +193 -0
  450. package/electron-host/dist/js-driver.js +216 -0
  451. package/electron-host/dist/main-guards.js +70 -0
  452. package/electron-host/dist/main.js +716 -0
  453. package/electron-host/dist/roster-sync.js +87 -0
  454. package/electron-host/dist/rpc-context.js +1 -0
  455. package/electron-host/dist/rpc-tab-methods.js +138 -0
  456. package/electron-host/dist/rpc-webrtc-methods.js +121 -0
  457. package/electron-host/dist/screen-capture-cache.js +147 -0
  458. package/electron-host/dist/sdk-injector.js +166 -0
  459. package/electron-host/dist/sdp.js +102 -0
  460. package/electron-host/dist/session-surface.js +78 -0
  461. package/electron-host/dist/surface-sizing.js +59 -0
  462. package/electron-host/dist/view-manager.js +254 -0
  463. package/electron-host/dist/viewer-registry.js +46 -0
  464. package/electron-host/dist/viewer-session.js +288 -0
  465. package/electron-host/dist/webrtc-channels.js +14 -0
  466. package/electron-host/dist/webrtc-controller.js +57 -0
  467. package/electron-host/dist/webrtc-ice-filter.js +13 -0
  468. package/electron-host/dist/webrtc-peer.js +45 -0
  469. package/electron-host/package.json +12 -0
  470. package/electron-host/tsconfig.json +23 -0
  471. package/electron-host/webrtc-controller-preload.cjs +3 -0
  472. package/electron-host/webrtc-controller.html +14 -0
  473. package/package.json +85 -0
  474. package/vendor/e2ee/LICENSE +14 -0
  475. package/vendor/e2ee/package.json +14 -0
  476. package/vendor/e2ee/src/index.js +310 -0
@@ -0,0 +1,104 @@
1
+ // Copyright (c) 2025-present Minionry, Inc.
2
+ // SPDX-License-Identifier: LicenseRef-Minionry-Software
3
+ import { createHash } from 'node:crypto';
4
+ import { readFileSync } from 'node:fs';
5
+ import { isAbsolute, relative, resolve } from 'node:path';
6
+ export function computeFingerprint(parts) {
7
+ return createHash('sha256').update(parts.join('\u0000'), 'utf8').digest('hex');
8
+ }
9
+ export function normalizeFindingPath(file, dirPath, baseDir) {
10
+ let rel = file;
11
+ if (isAbsolute(file))
12
+ rel = relative(dirPath, file);
13
+ else if (baseDir)
14
+ rel = relative(dirPath, resolve(baseDir, file));
15
+ return rel.replace(/\\/g, '/').replace(/^(\.\/)+/, '').replace(/\/+$/, '');
16
+ }
17
+ export function normalizeLineText(text) {
18
+ return text.replace(/\s+/g, ' ').trim();
19
+ }
20
+ export function lineTextOf(content, line) {
21
+ if (content === undefined || line === null || !Number.isInteger(line) || line < 1)
22
+ return '';
23
+ const lines = content.split('\n');
24
+ if (line > lines.length)
25
+ return '';
26
+ return normalizeLineText(lines[line - 1]);
27
+ }
28
+ export function digitlessTitle(title) {
29
+ return title.replace(/\d+/g, '');
30
+ }
31
+ export function ruleFindingParts(category, file, ruleKey, lineText) {
32
+ return [category, file, ruleKey, lineText];
33
+ }
34
+ export function templatedFindingParts(category, file, title) {
35
+ return [category, file, digitlessTitle(title)];
36
+ }
37
+ export function reviewFindingParts(category, file, lineText, evidence) {
38
+ const text = lineText || (evidence ? normalizeLineText(evidence) : '');
39
+ return [category, file, text];
40
+ }
41
+ export function duplicationParts(category, a, b) {
42
+ const [first, second] = a.file <= b.file ? [a, b] : [b, a];
43
+ return [category, first.file, second.file, first.lineText, second.lineText];
44
+ }
45
+ export function secretsParts(category, file, ruleId, ordinal) {
46
+ return [category, file, ruleId, String(ordinal)];
47
+ }
48
+ export function dependencyParts(category, file, packageName, advisoryId) {
49
+ return [category, file, packageName, advisoryId];
50
+ }
51
+ export function collectedContentReader(files) {
52
+ const byPath = new Map();
53
+ for (const f of files)
54
+ byPath.set(f.relativePath.replace(/\\/g, '/'), f.content);
55
+ return (file) => byPath.get(file);
56
+ }
57
+ export function diskContentReader(dirPath) {
58
+ const cache = new Map();
59
+ return (file) => {
60
+ if (cache.has(file))
61
+ return cache.get(file);
62
+ let content;
63
+ try {
64
+ content = readFileSync(resolve(dirPath, file), 'utf8');
65
+ }
66
+ catch {
67
+ content = undefined;
68
+ }
69
+ cache.set(file, content);
70
+ return content;
71
+ };
72
+ }
73
+ const REVIEW_CATEGORIES = new Set(['architecture', 'oop', 'security', 'bugs', 'performance', 'logic', 'maintainability']);
74
+ const TEMPLATED_CATEGORIES = new Set(['file-length', 'function-length']);
75
+ const RADON_TITLE = /\(\) has cyclomatic complexity \d+$/;
76
+ const PRODUCER_STAMPED_CATEGORIES = new Set(['duplication', 'secrets', 'dependencies']);
77
+ export function fingerprintParts(finding, ctx) {
78
+ const { category, title } = finding;
79
+ if (PRODUCER_STAMPED_CATEGORIES.has(category))
80
+ return null;
81
+ const file = normalizeFindingPath(finding.file, ctx.dirPath);
82
+ if (TEMPLATED_CATEGORIES.has(category) || (category === 'complexity' && RADON_TITLE.test(title))) {
83
+ return templatedFindingParts(category, file, title);
84
+ }
85
+ const lineText = lineTextOf(ctx.contentOf(file), finding.line);
86
+ if (REVIEW_CATEGORIES.has(category))
87
+ return reviewFindingParts(category, file, lineText, finding.evidence);
88
+ return ruleFindingParts(category, file, title, lineText);
89
+ }
90
+ export function fingerprintFinding(finding, ctx) {
91
+ const parts = fingerprintParts(finding, ctx);
92
+ return parts ? computeFingerprint(parts) : undefined;
93
+ }
94
+ export function stampFingerprints(findings, ctx) {
95
+ for (const finding of findings) {
96
+ finding.file = normalizeFindingPath(finding.file, ctx.dirPath);
97
+ if (finding.fingerprint)
98
+ continue;
99
+ const fingerprint = fingerprintFinding(finding, ctx);
100
+ if (fingerprint)
101
+ finding.fingerprint = fingerprint;
102
+ }
103
+ return findings;
104
+ }
@@ -0,0 +1,575 @@
1
+ // Copyright (c) 2025-present Minionry, Inc.
2
+ // SPDX-License-Identifier: LicenseRef-Minionry-Software
3
+ const SECURITY_CATEGORIES = new Set(['security', 'secrets', 'dependencies']);
4
+ const RELIABILITY_CATEGORIES = new Set([
5
+ 'bugs',
6
+ 'logic',
7
+ 'performance',
8
+ 'complexity',
9
+ 'build',
10
+ 'coverage',
11
+ 'error-handling',
12
+ ]);
13
+ const MAINTAINABILITY_CATEGORIES = new Set([
14
+ 'lint',
15
+ 'linting',
16
+ 'format',
17
+ 'file-length',
18
+ 'function-length',
19
+ 'parameters',
20
+ 'nesting',
21
+ 'returns',
22
+ 'tech-debt',
23
+ 'duplication',
24
+ 'documentation',
25
+ 'architecture',
26
+ 'oop',
27
+ 'maintainability',
28
+ ]);
29
+ export function categoryToDimension(category) {
30
+ if (SECURITY_CATEGORIES.has(category))
31
+ return 'security';
32
+ if (RELIABILITY_CATEGORIES.has(category))
33
+ return 'reliability';
34
+ if (MAINTAINABILITY_CATEGORIES.has(category))
35
+ return 'maintainability';
36
+ return 'maintainability';
37
+ }
38
+ const ARCHITECTURE_CATEGORIES = new Set(['architecture', 'oop']);
39
+ const BASE_BAND_TOP = {
40
+ A: 100,
41
+ B: 89,
42
+ C: 79,
43
+ F: 69,
44
+ };
45
+ const BASE_BAND_BOTTOM = {
46
+ A: 90,
47
+ B: 80,
48
+ C: 70,
49
+ F: 56,
50
+ };
51
+ export function scoreToGrade(score) {
52
+ if (score >= 97)
53
+ return 'A+';
54
+ if (score >= 93)
55
+ return 'A';
56
+ if (score >= 90)
57
+ return 'A-';
58
+ if (score >= 87)
59
+ return 'B+';
60
+ if (score >= 83)
61
+ return 'B';
62
+ if (score >= 80)
63
+ return 'B-';
64
+ if (score >= 77)
65
+ return 'C+';
66
+ if (score >= 73)
67
+ return 'C';
68
+ if (score >= 70)
69
+ return 'C-';
70
+ if (score >= 65)
71
+ return 'F+';
72
+ if (score >= 56)
73
+ return 'F';
74
+ return 'F-';
75
+ }
76
+ export function gradeFromScore(score) {
77
+ const full = scoreToGrade(score);
78
+ return baseGradeOf(full);
79
+ }
80
+ function baseGradeOf(g) {
81
+ if (g === 'N/A' || g === 'D')
82
+ return g;
83
+ if (g.startsWith('A'))
84
+ return 'A';
85
+ if (g.startsWith('B'))
86
+ return 'B';
87
+ if (g.startsWith('C'))
88
+ return 'C';
89
+ return 'F';
90
+ }
91
+ function scoreInBand(grade, position) {
92
+ const clamped = Math.max(0, Math.min(1, position));
93
+ const bottom = BASE_BAND_BOTTOM[grade];
94
+ const top = BASE_BAND_TOP[grade];
95
+ return Math.round(bottom + (top - bottom) * clamped);
96
+ }
97
+ function isSeverity(s) {
98
+ return s === 'critical' || s === 'high' || s === 'medium' || s === 'low';
99
+ }
100
+ function countSeverities(findings) {
101
+ const counts = { critical: 0, high: 0, medium: 0, low: 0, total: 0 };
102
+ for (const f of findings) {
103
+ if (!isSeverity(f.severity))
104
+ continue;
105
+ counts[f.severity]++;
106
+ counts.total++;
107
+ }
108
+ return counts;
109
+ }
110
+ function worstSeverity(counts) {
111
+ if (counts.critical > 0)
112
+ return 'critical';
113
+ if (counts.high > 0)
114
+ return 'high';
115
+ if (counts.medium > 0)
116
+ return 'medium';
117
+ if (counts.low > 0)
118
+ return 'low';
119
+ return null;
120
+ }
121
+ function gradeSecurity(findings) {
122
+ const counts = countSeverities(findings);
123
+ const worst = worstSeverity(counts);
124
+ if (counts.total === 0) {
125
+ return makeDimension('security', 100, '0 security findings', 0, null);
126
+ }
127
+ if (counts.critical > 0) {
128
+ return makeDimension('security', Math.max(0, 55 - counts.critical * 5), `${counts.critical} critical-severity security ${pluralize('issue', counts.critical)}`, counts.total, worst);
129
+ }
130
+ let baseGrade;
131
+ let position;
132
+ let rationale;
133
+ if (counts.high > 0) {
134
+ baseGrade = 'F';
135
+ position = 1 / (1 + counts.high);
136
+ rationale = `${counts.high} high-severity security ${pluralize('issue', counts.high)}`;
137
+ }
138
+ else if (counts.medium > 0) {
139
+ baseGrade = 'C';
140
+ position = 1 / (1 + counts.medium);
141
+ rationale = `${counts.medium} medium-severity security ${pluralize('issue', counts.medium)}`;
142
+ }
143
+ else {
144
+ baseGrade = 'B';
145
+ position = 1 / Math.max(1, counts.low);
146
+ rationale = `${counts.low} low-severity security ${pluralize('issue', counts.low)}`;
147
+ }
148
+ const score = scoreInBand(baseGrade, position);
149
+ return makeDimension('security', score, rationale, counts.total, worst);
150
+ }
151
+ function reliabilityByCount(n) {
152
+ const label = `${n} reliability ${pluralize('issue', n)}`;
153
+ if (n <= 2)
154
+ return { grade: 'A', position: 1 - n / 2, label };
155
+ if (n <= 6)
156
+ return { grade: 'B', position: 1 - (n - 2) / 4, label };
157
+ if (n <= 15)
158
+ return { grade: 'C', position: 1 - (n - 6) / 9, label };
159
+ return { grade: 'F', position: 1 / (1 + (n - 15) / 15), label };
160
+ }
161
+ function reliabilityByDensity(n, kloc) {
162
+ const density = n / kloc;
163
+ const label = `${roundOne(density)} reliability ${pluralize('issue', n)} / KLOC`;
164
+ if (density < 1.5)
165
+ return { grade: 'A', position: 1 - density / 1.5, label };
166
+ if (density < 4)
167
+ return { grade: 'B', position: 1 - (density - 1.5) / 2.5, label };
168
+ if (density < 8)
169
+ return { grade: 'C', position: 1 - (density - 4) / 4, label };
170
+ return { grade: 'F', position: 1 / (1 + (density - 8) / 8), label };
171
+ }
172
+ function reliabilityEscape(counts) {
173
+ if (counts.critical > 0) {
174
+ return { grade: 'F', note: `${counts.critical} critical-severity ${pluralize('bug', counts.critical)}` };
175
+ }
176
+ if (counts.high > 0) {
177
+ return { grade: 'C', note: `${counts.high} high-severity ${pluralize('bug', counts.high)}` };
178
+ }
179
+ return null;
180
+ }
181
+ function gradeReliability(findings, totalLines) {
182
+ const counts = countSeverities(findings);
183
+ const worst = worstSeverity(counts);
184
+ const kloc = Math.max(totalLines / 1000, 1.0);
185
+ if (counts.total === 0) {
186
+ return makeDimension('reliability', 100, '0 reliability findings', 0, null);
187
+ }
188
+ if (counts.low <= 1 && counts.medium === 0 && counts.high === 0 && counts.critical === 0) {
189
+ return makeDimension('reliability', scoreInBand('A', 0.5), '1 low-severity reliability issue', counts.total, worst);
190
+ }
191
+ const band = kloc < 5 ? reliabilityByCount(counts.total) : reliabilityByDensity(counts.total, kloc);
192
+ const severityCap = reliabilityEscape(counts);
193
+ const useCap = severityCap && baseIsWorse(severityCap.grade, band.grade);
194
+ const finalGrade = useCap ? severityCap.grade : band.grade;
195
+ const finalPosition = useCap ? 0.5 : band.position;
196
+ const rationale = useCap ? `${band.label}, ${severityCap.note}` : band.label;
197
+ return makeDimension('reliability', scoreInBand(finalGrade, finalPosition), rationale, counts.total, worst);
198
+ }
199
+ function maintainabilityByCount(n) {
200
+ const label = `${n} maintainability ${pluralize('issue', n)}`;
201
+ if (n <= 5)
202
+ return { grade: 'A', position: 1 - n / 5, label };
203
+ if (n <= 15)
204
+ return { grade: 'B', position: 1 - (n - 5) / 10, label };
205
+ if (n <= 30)
206
+ return { grade: 'C', position: 1 - (n - 15) / 15, label };
207
+ return { grade: 'F', position: 1 / (1 + (n - 30) / 30), label };
208
+ }
209
+ function maintainabilityByDensity(n, kloc) {
210
+ const density = n / kloc;
211
+ const label = `${roundOne(density)} ${pluralize('issue', n)} / KLOC`;
212
+ if (density < 5)
213
+ return { grade: 'A', position: 1 - density / 5, label };
214
+ if (density < 10)
215
+ return { grade: 'B', position: 1 - (density - 5) / 5, label };
216
+ if (density < 25)
217
+ return { grade: 'C', position: 1 - (density - 10) / 15, label };
218
+ return { grade: 'F', position: 1 / (1 + (density - 25) / 25), label };
219
+ }
220
+ function maintainabilityEscape(counts) {
221
+ if (counts.critical > 0) {
222
+ return { grade: 'F', note: `${counts.critical} critical-severity ${pluralize('issue', counts.critical)}` };
223
+ }
224
+ if (counts.high > 0) {
225
+ return { grade: 'C', note: `${counts.high} high-severity ${pluralize('issue', counts.high)}` };
226
+ }
227
+ return null;
228
+ }
229
+ function gradeMaintainability(findings, totalLines) {
230
+ const counts = countSeverities(findings);
231
+ const kloc = Math.max(totalLines / 1000, 1.0);
232
+ if (counts.total === 0) {
233
+ return makeDimension('maintainability', 100, '0 maintainability findings', 0, null);
234
+ }
235
+ const band = kloc < 5 ? maintainabilityByCount(counts.total) : maintainabilityByDensity(counts.total, kloc);
236
+ const severityCap = maintainabilityEscape(counts);
237
+ const useCap = severityCap && baseIsWorse(severityCap.grade, band.grade);
238
+ const finalGrade = useCap ? severityCap.grade : band.grade;
239
+ const finalPosition = useCap ? 0.5 : band.position;
240
+ const rationale = useCap ? `${band.label}, ${severityCap.note}` : band.label;
241
+ return makeDimension('maintainability', scoreInBand(finalGrade, finalPosition), rationale, counts.total, worstSeverity(counts));
242
+ }
243
+ function archDropCount(archFindings) {
244
+ let highCount = 0;
245
+ let criticalCount = 0;
246
+ for (const f of archFindings) {
247
+ if (f.severity === 'critical')
248
+ criticalCount++;
249
+ else if (f.severity === 'high')
250
+ highCount++;
251
+ }
252
+ if (criticalCount >= 1)
253
+ return 2;
254
+ if (highCount >= 2)
255
+ return 2;
256
+ if (highCount >= 1)
257
+ return 1;
258
+ return 0;
259
+ }
260
+ const BASE_LETTERS = ['A', 'B', 'C', 'F'];
261
+ function gradeModifier(grade) {
262
+ if (grade.endsWith('+'))
263
+ return '+';
264
+ if (grade.endsWith('-'))
265
+ return '-';
266
+ return '';
267
+ }
268
+ function applyModifierToTargetBase(targetBase, modifier) {
269
+ if (targetBase === 'F') {
270
+ if (modifier === '+')
271
+ return 'F+';
272
+ if (modifier === '-')
273
+ return 'F-';
274
+ return 'F';
275
+ }
276
+ if (modifier === '+')
277
+ return `${targetBase}+`;
278
+ if (modifier === '-')
279
+ return `${targetBase}-`;
280
+ return targetBase;
281
+ }
282
+ function dropGradeByLetters(grade, letters) {
283
+ if (letters <= 0 || grade === 'N/A' || grade === 'D')
284
+ return grade;
285
+ const baseLetter = baseGradeOf(grade);
286
+ const baseIdx = BASE_LETTERS.indexOf(baseLetter);
287
+ if (baseIdx === -1)
288
+ return grade;
289
+ const targetBaseIdx = baseIdx + letters;
290
+ if (targetBaseIdx > 3)
291
+ return 'F-';
292
+ const targetBase = BASE_LETTERS[targetBaseIdx];
293
+ return applyModifierToTargetBase(targetBase, gradeModifier(grade));
294
+ }
295
+ function applyArchPenalty(dim, archFindings) {
296
+ const drop = archDropCount(archFindings);
297
+ if (drop === 0)
298
+ return dim;
299
+ const dropped = dropGradeByLetters(dim.grade, drop);
300
+ if (dropped === dim.grade)
301
+ return dim;
302
+ const archCount = archFindings.length;
303
+ const noun = pluralize('architectural finding', archCount);
304
+ const note = `dropped ${drop} ${pluralize('letter', drop)} by ${archCount} ${noun}`;
305
+ return {
306
+ ...dim,
307
+ grade: dropped,
308
+ score: anchorScoreToGrade(dropped, dim.score),
309
+ rationale: dim.rationale === '0 maintainability findings' || dim.findingCount === 0
310
+ ? note
311
+ : `${dim.rationale}; ${note}`,
312
+ };
313
+ }
314
+ function anchorScoreToGrade(grade, originalScore) {
315
+ if (grade === 'N/A' || grade === 'D')
316
+ return originalScore;
317
+ const ranges = {
318
+ 'A+': [97, 100], A: [93, 96], 'A-': [90, 92],
319
+ 'B+': [87, 89], B: [83, 86], 'B-': [80, 82],
320
+ 'C+': [77, 79], C: [73, 76], 'C-': [70, 72],
321
+ 'F+': [65, 69], F: [56, 64], 'F-': [0, 55],
322
+ };
323
+ const [lo, hi] = ranges[grade];
324
+ if (originalScore >= lo && originalScore <= hi)
325
+ return originalScore;
326
+ return Math.round((lo + hi) / 2);
327
+ }
328
+ const BASE_RANK = { F: 1, C: 2, B: 3, A: 4 };
329
+ function baseIsWorse(a, b) {
330
+ return BASE_RANK[a] < BASE_RANK[b];
331
+ }
332
+ const FULL_RANK = {
333
+ 'F-': 0, F: 1, 'F+': 2,
334
+ 'C-': 3, C: 4, 'C+': 5,
335
+ 'B-': 6, B: 7, 'B+': 8,
336
+ 'A-': 9, A: 10, 'A+': 11,
337
+ };
338
+ function gradeRank(g) {
339
+ if (g === 'N/A')
340
+ return -1;
341
+ if (g === 'D')
342
+ return 1.5;
343
+ return FULL_RANK[g];
344
+ }
345
+ function worstOf(grades) {
346
+ let worst = 'A+';
347
+ for (const g of grades) {
348
+ if (g === 'N/A')
349
+ continue;
350
+ if (gradeRank(g) < gradeRank(worst))
351
+ worst = g;
352
+ }
353
+ return worst;
354
+ }
355
+ function pluralize(word, n) {
356
+ return n === 1 ? word : `${word}s`;
357
+ }
358
+ function roundOne(n) {
359
+ return Math.round(n * 10) / 10;
360
+ }
361
+ function dimensionDisplayName(name) {
362
+ return name.charAt(0).toUpperCase() + name.slice(1);
363
+ }
364
+ function makeDimension(name, score, rationale, findingCount, worst) {
365
+ return {
366
+ name,
367
+ score,
368
+ grade: scoreToGrade(score),
369
+ rationale,
370
+ available: true,
371
+ findingCount,
372
+ worstSeverity: worst,
373
+ };
374
+ }
375
+ function naDimension(name) {
376
+ return {
377
+ name,
378
+ score: 0,
379
+ grade: 'N/A',
380
+ rationale: 'No tools available to evaluate',
381
+ available: false,
382
+ findingCount: 0,
383
+ worstSeverity: null,
384
+ };
385
+ }
386
+ function bucketByDimension(findings) {
387
+ const security = [];
388
+ const reliability = [];
389
+ const maintainability = [];
390
+ const architecture = [];
391
+ for (const f of findings) {
392
+ if (ARCHITECTURE_CATEGORIES.has(f.category))
393
+ architecture.push(f);
394
+ const dim = categoryToDimension(f.category);
395
+ if (dim === 'security')
396
+ security.push(f);
397
+ else if (dim === 'reliability')
398
+ reliability.push(f);
399
+ else
400
+ maintainability.push(f);
401
+ }
402
+ return { security, reliability, maintainability, architecture };
403
+ }
404
+ function isDimensionAvailable(dim, hasFindings, options) {
405
+ if (options?.forceNA?.has(dim))
406
+ return false;
407
+ const explicit = options?.availableDimensions;
408
+ if (explicit)
409
+ return explicit.has(dim);
410
+ return dim === 'maintainability' ? true : hasFindings;
411
+ }
412
+ function computeOverall(availableDims) {
413
+ if (availableDims.length === 0) {
414
+ return { grade: 'N/A', score: 0 };
415
+ }
416
+ const grades = availableDims.map((d) => d.grade);
417
+ const scores = availableDims.map((d) => d.score);
418
+ const avg = scores.reduce((s, n) => s + n, 0) / scores.length;
419
+ const worst = worstOf(grades);
420
+ const blendedScore = Math.round(Math.min(avg, Math.min(...scores)));
421
+ return { grade: worst, score: anchorScoreToGrade(worst, blendedScore) };
422
+ }
423
+ export function computeQualityRating(allFindings, totalLines, options) {
424
+ const buckets = bucketByDimension(allFindings);
425
+ const security = isDimensionAvailable('security', buckets.security.length > 0, options)
426
+ ? gradeSecurity(buckets.security)
427
+ : naDimension('security');
428
+ const reliabilityRaw = isDimensionAvailable('reliability', buckets.reliability.length > 0, options)
429
+ ? gradeReliability(buckets.reliability, totalLines)
430
+ : naDimension('reliability');
431
+ const maintainabilityRaw = isDimensionAvailable('maintainability', true, options)
432
+ ? gradeMaintainability(buckets.maintainability, totalLines)
433
+ : naDimension('maintainability');
434
+ const archFindings = buckets.architecture;
435
+ const maintainability = maintainabilityRaw.available
436
+ ? applyArchPenalty(maintainabilityRaw, archFindings)
437
+ : maintainabilityRaw;
438
+ const dimensions = [security, reliabilityRaw, maintainability];
439
+ const availableDims = dimensions.filter((d) => d.available);
440
+ const overall = computeOverall(availableDims);
441
+ const qualityGate = computeQualityGate(security, reliabilityRaw, archFindings.length);
442
+ const gradeRationale = computeGradeRationale(availableDims, overall.grade, allFindings.length);
443
+ return {
444
+ overall,
445
+ dimensions,
446
+ qualityGate,
447
+ gradeRationale,
448
+ };
449
+ }
450
+ const READINESS_SECURITY_CATEGORIES = new Set(['security', 'secrets', 'dependencies']);
451
+ const READINESS_RELIABILITY_CATEGORIES = new Set(['build', 'bugs', 'logic', 'error-handling']);
452
+ const SEVERITY_RANK = { critical: 4, high: 3, medium: 2, low: 1 };
453
+ function worstSeverityRank(findings) {
454
+ let worst = 0;
455
+ for (const f of findings) {
456
+ if (isSeverity(f.severity))
457
+ worst = Math.max(worst, SEVERITY_RANK[f.severity]);
458
+ }
459
+ return worst;
460
+ }
461
+ function formatBlocker(f) {
462
+ const loc = f.line ? `${f.file}:${f.line}` : f.file;
463
+ return `${loc} — ${f.title}`;
464
+ }
465
+ function buildReadinessVerdict(level, security, reliability, maintBroken) {
466
+ const gating = [...security, ...reliability];
467
+ if (level === 'blocked') {
468
+ const crit = gating.filter((f) => f.severity === 'critical');
469
+ return {
470
+ level,
471
+ headline: 'Blocked',
472
+ rationale: `${crit.length} critical ${pluralize('issue', crit.length)} must be fixed before this can run.`,
473
+ blockers: crit.slice(0, 5).map(formatBlocker),
474
+ };
475
+ }
476
+ if (level === 'testing') {
477
+ const blocking = gating.filter((f) => f.severity === 'high' || (READINESS_SECURITY_CATEGORIES.has(f.category) && f.severity === 'medium'));
478
+ return {
479
+ level,
480
+ headline: 'Ready for testing',
481
+ rationale: 'Safe to run in a test environment. Resolve the flagged security/reliability issues before merging to develop.',
482
+ blockers: blocking.slice(0, 5).map(formatBlocker),
483
+ };
484
+ }
485
+ if (level === 'develop') {
486
+ return {
487
+ level,
488
+ headline: 'Ready for develop',
489
+ rationale: maintBroken
490
+ ? 'Safe to merge to the develop branch. Clean up maintainability before a production release.'
491
+ : 'Safe to merge to the develop branch. A few non-blocking issues remain before production.',
492
+ blockers: [],
493
+ };
494
+ }
495
+ if (level === 'insufficient-data') {
496
+ return {
497
+ level,
498
+ headline: 'Insufficient data',
499
+ rationale: 'Security and reliability were never assessed — no tools ran and no findings exist to judge. This is not a clean bill of health; it means nothing has been checked yet.',
500
+ blockers: [],
501
+ };
502
+ }
503
+ return {
504
+ level,
505
+ headline: 'Ready for production',
506
+ rationale: gating.length === 0
507
+ ? 'No blocking security or reliability issues — safe to ship.'
508
+ : 'Security and reliability are clean — safe to ship.',
509
+ blockers: [],
510
+ };
511
+ }
512
+ export function computeReadiness(dimensions, prodGatingFindings) {
513
+ const security = prodGatingFindings.filter((f) => READINESS_SECURITY_CATEGORIES.has(f.category));
514
+ const reliability = prodGatingFindings.filter((f) => READINESS_RELIABILITY_CATEGORIES.has(f.category));
515
+ const secRank = worstSeverityRank(security);
516
+ const relRank = worstSeverityRank(reliability);
517
+ const secDim = dimensions.find((d) => d.name === 'security');
518
+ const relDim = dimensions.find((d) => d.name === 'reliability');
519
+ const maint = dimensions.find((d) => d.name === 'maintainability');
520
+ const maintBroken = !!maint && maint.available && isFTier(maint.grade);
521
+ const maintHasSignal = !!maint && maint.available && maint.findingCount > 0;
522
+ const insufficientData = !secDim?.available && !relDim?.available && !maintHasSignal;
523
+ let level;
524
+ if (secRank >= SEVERITY_RANK.critical || relRank >= SEVERITY_RANK.critical) {
525
+ level = 'blocked';
526
+ }
527
+ else if (secRank >= SEVERITY_RANK.medium || relRank >= SEVERITY_RANK.high) {
528
+ level = 'testing';
529
+ }
530
+ else if (secRank <= SEVERITY_RANK.low && relRank <= SEVERITY_RANK.low && !maintBroken) {
531
+ level = insufficientData ? 'insufficient-data' : 'production';
532
+ }
533
+ else {
534
+ level = 'develop';
535
+ }
536
+ return buildReadinessVerdict(level, security, reliability, maintBroken);
537
+ }
538
+ function isFTier(g) {
539
+ return g === 'F+' || g === 'F' || g === 'F-' || g === 'D';
540
+ }
541
+ function isCorWorse(g) {
542
+ return baseGradeOf(g) === 'C' || isFTier(g);
543
+ }
544
+ function computeQualityGate(security, reliability, archFindingCount) {
545
+ const failingConditions = [];
546
+ if (security.available && isCorWorse(security.grade)) {
547
+ failingConditions.push(`Security grade ${security.grade} — ${security.rationale}`);
548
+ }
549
+ if (reliability.available && isFTier(reliability.grade)) {
550
+ failingConditions.push(`Reliability grade ${reliability.grade} — ${reliability.rationale}`);
551
+ }
552
+ if (archFindingCount >= 2) {
553
+ failingConditions.push(`${archFindingCount} architectural findings`);
554
+ }
555
+ return {
556
+ passed: failingConditions.length === 0,
557
+ failingConditions,
558
+ };
559
+ }
560
+ function computeGradeRationale(availableDims, overallGrade, totalFindingCount) {
561
+ if (totalFindingCount === 0) {
562
+ return 'Clean — no findings detected';
563
+ }
564
+ if (availableDims.length === 0 || overallGrade === 'N/A') {
565
+ return 'No dimensions available to grade';
566
+ }
567
+ const firstBase = baseGradeOf(availableDims[0].grade);
568
+ const allSameBase = availableDims.every((d) => baseGradeOf(d.grade) === firstBase);
569
+ if (allSameBase) {
570
+ return `All dimensions ${firstBase}-tier — consistent quality`;
571
+ }
572
+ const worstDim = availableDims.find((d) => d.grade === overallGrade) ??
573
+ availableDims[0];
574
+ return `Capped at ${overallGrade} by ${dimensionDisplayName(worstDim.name)} (${worstDim.rationale})`;
575
+ }