tinybeeai 0.0.0-stage → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.railway/railway.ts +83 -0
- package/.railway/tsconfig.json +13 -0
- package/AGENTS.md +102 -0
- package/Dockerfile +108 -0
- package/LICENSE +21 -0
- package/README.md +275 -2
- package/bin/localdost.js +29 -0
- package/bin/tinybeeai.js +28 -0
- package/compose.yml +63 -0
- package/demo/payloads/ci_failure.json +46 -0
- package/demo/payloads/outage.json +18 -0
- package/demo/payloads/pr_comment_edited.json +50 -0
- package/demo/payloads/pr_merged.json +80 -0
- package/demo/payloads/pr_opened.json +69 -0
- package/demo/payloads/pr_synchronize.json +69 -0
- package/demo/payloads/ticket_created.json +138 -0
- package/demo/sample-app/playwright.config.ts +20 -0
- package/demo/sample-app/server.ts +163 -0
- package/demo/sample-app/tests/checkout.spec.ts +13 -0
- package/demo/sample-app/tests/smoke.spec.ts +8 -0
- package/dist/agent/approval-retries.js +59 -0
- package/dist/agent/approval-retries.js.map +1 -0
- package/dist/agent/approvals.js +390 -0
- package/dist/agent/approvals.js.map +1 -0
- package/dist/agent/chat-bridge.js +154 -0
- package/dist/agent/chat-bridge.js.map +1 -0
- package/dist/agent/chat-lead.js +475 -0
- package/dist/agent/chat-lead.js.map +1 -0
- package/dist/agent/chat-loop.js +106 -0
- package/dist/agent/chat-loop.js.map +1 -0
- package/dist/agent/chat-mcp.js +49 -0
- package/dist/agent/chat-mcp.js.map +1 -0
- package/dist/agent/chat-tool-blocks.js +453 -0
- package/dist/agent/chat-tool-blocks.js.map +1 -0
- package/dist/agent/chat-view.js +94 -0
- package/dist/agent/chat-view.js.map +1 -0
- package/dist/agent/chat-views.js +781 -0
- package/dist/agent/chat-views.js.map +1 -0
- package/dist/agent/chat.js +1703 -0
- package/dist/agent/chat.js.map +1 -0
- package/dist/agent/destinations.js +150 -0
- package/dist/agent/destinations.js.map +1 -0
- package/dist/agent/llm-cli.js +451 -0
- package/dist/agent/llm-cli.js.map +1 -0
- package/dist/agent/llm-codex.js +493 -0
- package/dist/agent/llm-codex.js.map +1 -0
- package/dist/agent/llm-openai.js +211 -0
- package/dist/agent/llm-openai.js.map +1 -0
- package/dist/agent/llm.js +1464 -0
- package/dist/agent/llm.js.map +1 -0
- package/dist/agent/memory.js +33 -0
- package/dist/agent/memory.js.map +1 -0
- package/dist/agent/mock-views.js +93 -0
- package/dist/agent/mock-views.js.map +1 -0
- package/dist/agent/model-availability.js +207 -0
- package/dist/agent/model-availability.js.map +1 -0
- package/dist/agent/model-errors.js +188 -0
- package/dist/agent/model-errors.js.map +1 -0
- package/dist/agent/model-guard.js +311 -0
- package/dist/agent/model-guard.js.map +1 -0
- package/dist/agent/prompts.js +374 -0
- package/dist/agent/prompts.js.map +1 -0
- package/dist/agent/qa-lenses/qa-auth.md +32 -0
- package/dist/agent/qa-lenses/qa-check-then-act.md +33 -0
- package/dist/agent/qa-lenses/qa-control-has-no-effect.md +32 -0
- package/dist/agent/qa-lenses/qa-dates.md +31 -0
- package/dist/agent/qa-lenses/qa-double-submit.md +34 -0
- package/dist/agent/qa-lenses/qa-feature-flag.md +29 -0
- package/dist/agent/qa-lenses/qa-migration.md +35 -0
- package/dist/agent/qa-lenses/qa-money.md +38 -0
- package/dist/agent/qa-lenses/qa-response-shape-break.md +33 -0
- package/dist/agent/qa-lenses/qa-validation.md +29 -0
- package/dist/agent/qa-prompts.js +660 -0
- package/dist/agent/qa-prompts.js.map +1 -0
- package/dist/agent/reasoning.js +55 -0
- package/dist/agent/reasoning.js.map +1 -0
- package/dist/agent/redact.js +48 -0
- package/dist/agent/redact.js.map +1 -0
- package/dist/agent/rules.js +927 -0
- package/dist/agent/rules.js.map +1 -0
- package/dist/agent/runs.js +440 -0
- package/dist/agent/runs.js.map +1 -0
- package/dist/agent/send-retry.js +62 -0
- package/dist/agent/send-retry.js.map +1 -0
- package/dist/agent/team-notes.js +288 -0
- package/dist/agent/team-notes.js.map +1 -0
- package/dist/agent/token-meter.js +31 -0
- package/dist/agent/token-meter.js.map +1 -0
- package/dist/agent/triage.js +506 -0
- package/dist/agent/triage.js.map +1 -0
- package/dist/api.js +1047 -0
- package/dist/api.js.map +1 -0
- package/dist/approval-targets.js +107 -0
- package/dist/approval-targets.js.map +1 -0
- package/dist/bee/cloudflared.js +108 -0
- package/dist/bee/cloudflared.js.map +1 -0
- package/dist/bee/health.js +99 -0
- package/dist/bee/health.js.map +1 -0
- package/dist/bee/hive-client.js +75 -0
- package/dist/bee/hive-client.js.map +1 -0
- package/dist/bee/identity.js +39 -0
- package/dist/bee/identity.js.map +1 -0
- package/dist/bee/models.js +510 -0
- package/dist/bee/models.js.map +1 -0
- package/dist/bee/pairing.js +351 -0
- package/dist/bee/pairing.js.map +1 -0
- package/dist/bee/relay-client.js +50 -0
- package/dist/bee/relay-client.js.map +1 -0
- package/dist/bee/routes.js +214 -0
- package/dist/bee/routes.js.map +1 -0
- package/dist/bee/setup-page.js +223 -0
- package/dist/bee/setup-page.js.map +1 -0
- package/dist/bee/state.js +41 -0
- package/dist/bee/state.js.map +1 -0
- package/dist/bee/status.js +117 -0
- package/dist/bee/status.js.map +1 -0
- package/dist/bee/tunnel-manager.js +245 -0
- package/dist/bee/tunnel-manager.js.map +1 -0
- package/dist/bee/updater.js +268 -0
- package/dist/bee/updater.js.map +1 -0
- package/dist/boot.js +41 -0
- package/dist/boot.js.map +1 -0
- package/dist/call/index.js +145 -0
- package/dist/call/index.js.map +1 -0
- package/dist/case-folders.js +294 -0
- package/dist/case-folders.js.map +1 -0
- package/dist/cases.js +554 -0
- package/dist/cases.js.map +1 -0
- package/dist/chat-blocks.js +709 -0
- package/dist/chat-blocks.js.map +1 -0
- package/dist/chat-parse-util.js +38 -0
- package/dist/chat-parse-util.js.map +1 -0
- package/dist/chat-results.js +96 -0
- package/dist/chat-results.js.map +1 -0
- package/dist/chat-stats.js +193 -0
- package/dist/chat-stats.js.map +1 -0
- package/dist/chat-view-specs.js +186 -0
- package/dist/chat-view-specs.js.map +1 -0
- package/dist/cli/doctor-ops.js +361 -0
- package/dist/cli/doctor-ops.js.map +1 -0
- package/dist/cli/doctor.js +289 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/dogfood.js +70 -0
- package/dist/cli/dogfood.js.map +1 -0
- package/dist/cli/env-file.js +34 -0
- package/dist/cli/env-file.js.map +1 -0
- package/dist/cli/eval-chat-cases.js +359 -0
- package/dist/cli/eval-chat-cases.js.map +1 -0
- package/dist/cli/eval-chat-results.js +85 -0
- package/dist/cli/eval-chat-results.js.map +1 -0
- package/dist/cli/eval-chat.js +508 -0
- package/dist/cli/eval-chat.js.map +1 -0
- package/dist/cli/eval-designer.js +67 -0
- package/dist/cli/eval-designer.js.map +1 -0
- package/dist/cli/eval-qa-review.js +284 -0
- package/dist/cli/eval-qa-review.js.map +1 -0
- package/dist/cli/golden-export.js +35 -0
- package/dist/cli/golden-export.js.map +1 -0
- package/dist/cli/index.js +90 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.js +746 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/scan-repo.js +199 -0
- package/dist/cli/scan-repo.js.map +1 -0
- package/dist/cli/seed.js +108 -0
- package/dist/cli/seed.js.map +1 -0
- package/dist/cli/tinybee.js +247 -0
- package/dist/cli/tinybee.js.map +1 -0
- package/dist/config.js +138 -0
- package/dist/config.js.map +1 -0
- package/dist/connect/aivision-local.js +833 -0
- package/dist/connect/aivision-local.js.map +1 -0
- package/dist/connect/aivision-token.js +84 -0
- package/dist/connect/aivision-token.js.map +1 -0
- package/dist/connect/crypto.js +65 -0
- package/dist/connect/crypto.js.map +1 -0
- package/dist/connect/deps.js +110 -0
- package/dist/connect/deps.js.map +1 -0
- package/dist/connect/engines.js +144 -0
- package/dist/connect/engines.js.map +1 -0
- package/dist/connect/github-access.js +74 -0
- package/dist/connect/github-access.js.map +1 -0
- package/dist/connect/github-app.js +129 -0
- package/dist/connect/github-app.js.map +1 -0
- package/dist/connect/index.js +9 -0
- package/dist/connect/index.js.map +1 -0
- package/dist/connect/model-choices.js +201 -0
- package/dist/connect/model-choices.js.map +1 -0
- package/dist/connect/providers.js +900 -0
- package/dist/connect/providers.js.map +1 -0
- package/dist/connect/readiness.js +232 -0
- package/dist/connect/readiness.js.map +1 -0
- package/dist/connect/redact.js +16 -0
- package/dist/connect/redact.js.map +1 -0
- package/dist/connect/registry.js +406 -0
- package/dist/connect/registry.js.map +1 -0
- package/dist/connect/store.js +283 -0
- package/dist/connect/store.js.map +1 -0
- package/dist/connect/tunnel.js +134 -0
- package/dist/connect/tunnel.js.map +1 -0
- package/dist/connect/types.js +8 -0
- package/dist/connect/types.js.map +1 -0
- package/dist/connections/index.js +5 -0
- package/dist/connections/index.js.map +1 -0
- package/dist/connections/manager.js +223 -0
- package/dist/connections/manager.js.map +1 -0
- package/dist/connections/presets.js +264 -0
- package/dist/connections/presets.js.map +1 -0
- package/dist/connections/store.js +132 -0
- package/dist/connections/store.js.map +1 -0
- package/dist/connections/tools.js +206 -0
- package/dist/connections/tools.js.map +1 -0
- package/dist/db-schema.js +355 -0
- package/dist/db-schema.js.map +1 -0
- package/dist/db.js +379 -0
- package/dist/db.js.map +1 -0
- package/dist/delivery.js +49 -0
- package/dist/delivery.js.map +1 -0
- package/dist/deploy-wait.js +701 -0
- package/dist/deploy-wait.js.map +1 -0
- package/dist/disk.js +243 -0
- package/dist/disk.js.map +1 -0
- package/dist/dot-health.js +966 -0
- package/dist/dot-health.js.map +1 -0
- package/dist/dot-remove.js +246 -0
- package/dist/dot-remove.js.map +1 -0
- package/dist/events.js +38 -0
- package/dist/events.js.map +1 -0
- package/dist/evidence-pack.js +423 -0
- package/dist/evidence-pack.js.map +1 -0
- package/dist/flows/answers.js +289 -0
- package/dist/flows/answers.js.map +1 -0
- package/dist/flows/change.js +811 -0
- package/dist/flows/change.js.map +1 -0
- package/dist/flows/checkStatus.js +524 -0
- package/dist/flows/checkStatus.js.map +1 -0
- package/dist/flows/ci.js +236 -0
- package/dist/flows/ci.js.map +1 -0
- package/dist/flows/ciFailure.js +76 -0
- package/dist/flows/ciFailure.js.map +1 -0
- package/dist/flows/common.js +522 -0
- package/dist/flows/common.js.map +1 -0
- package/dist/flows/default-branch.js +29 -0
- package/dist/flows/default-branch.js.map +1 -0
- package/dist/flows/defectDraft.js +447 -0
- package/dist/flows/defectDraft.js.map +1 -0
- package/dist/flows/defects.js +623 -0
- package/dist/flows/defects.js.map +1 -0
- package/dist/flows/digest.js +295 -0
- package/dist/flows/digest.js.map +1 -0
- package/dist/flows/impact.js +82 -0
- package/dist/flows/impact.js.map +1 -0
- package/dist/flows/index.js +23 -0
- package/dist/flows/index.js.map +1 -0
- package/dist/flows/intent-sources.js +72 -0
- package/dist/flows/intent-sources.js.map +1 -0
- package/dist/flows/mergeCases.js +169 -0
- package/dist/flows/mergeCases.js.map +1 -0
- package/dist/flows/nightlyRun.js +82 -0
- package/dist/flows/nightlyRun.js.map +1 -0
- package/dist/flows/outage.js +64 -0
- package/dist/flows/outage.js.map +1 -0
- package/dist/flows/postMerge.js +5 -0
- package/dist/flows/postMerge.js.map +1 -0
- package/dist/flows/prCheck.js +5 -0
- package/dist/flows/prCheck.js.map +1 -0
- package/dist/flows/prTarget.js +66 -0
- package/dist/flows/prTarget.js.map +1 -0
- package/dist/flows/qa.js +363 -0
- package/dist/flows/qa.js.map +1 -0
- package/dist/flows/questions.js +160 -0
- package/dist/flows/questions.js.map +1 -0
- package/dist/flows/recovery.js +64 -0
- package/dist/flows/recovery.js.map +1 -0
- package/dist/flows/rerun.js +50 -0
- package/dist/flows/rerun.js.map +1 -0
- package/dist/flows/testDesign.js +294 -0
- package/dist/flows/testDesign.js.map +1 -0
- package/dist/flows/testDesignJob.js +46 -0
- package/dist/flows/testDesignJob.js.map +1 -0
- package/dist/flows/testRepo.js +228 -0
- package/dist/flows/testRepo.js.map +1 -0
- package/dist/flows/testSavings.js +381 -0
- package/dist/flows/testSavings.js.map +1 -0
- package/dist/flows/testStatus.js +343 -0
- package/dist/flows/testStatus.js.map +1 -0
- package/dist/flows/ticketContext.js +425 -0
- package/dist/flows/ticketContext.js.map +1 -0
- package/dist/flows/ticketReview.js +249 -0
- package/dist/flows/ticketReview.js.map +1 -0
- package/dist/flows/ticks.js +73 -0
- package/dist/flows/ticks.js.map +1 -0
- package/dist/hive/admin.js +122 -0
- package/dist/hive/admin.js.map +1 -0
- package/dist/hive/auth.js +130 -0
- package/dist/hive/auth.js.map +1 -0
- package/dist/hive/billing.js +278 -0
- package/dist/hive/billing.js.map +1 -0
- package/dist/hive/config.js +63 -0
- package/dist/hive/config.js.map +1 -0
- package/dist/hive/db.js +186 -0
- package/dist/hive/db.js.map +1 -0
- package/dist/hive/embed.js +76 -0
- package/dist/hive/embed.js.map +1 -0
- package/dist/hive/errors.js +17 -0
- package/dist/hive/errors.js.map +1 -0
- package/dist/hive/google.js +75 -0
- package/dist/hive/google.js.map +1 -0
- package/dist/hive/index.js +25 -0
- package/dist/hive/index.js.map +1 -0
- package/dist/hive/jwt.js +57 -0
- package/dist/hive/jwt.js.map +1 -0
- package/dist/hive/keys.js +61 -0
- package/dist/hive/keys.js.map +1 -0
- package/dist/hive/mail.js +27 -0
- package/dist/hive/mail.js.map +1 -0
- package/dist/hive/native-push.js +255 -0
- package/dist/hive/native-push.js.map +1 -0
- package/dist/hive/pairing.js +342 -0
- package/dist/hive/pairing.js.map +1 -0
- package/dist/hive/presence.js +121 -0
- package/dist/hive/presence.js.map +1 -0
- package/dist/hive/push.js +185 -0
- package/dist/hive/push.js.map +1 -0
- package/dist/hive/relay.js +205 -0
- package/dist/hive/relay.js.map +1 -0
- package/dist/hive/routes.js +228 -0
- package/dist/hive/routes.js.map +1 -0
- package/dist/hive/server.js +12 -0
- package/dist/hive/server.js.map +1 -0
- package/dist/hive/session.js +28 -0
- package/dist/hive/session.js.map +1 -0
- package/dist/hive/tenants.js +287 -0
- package/dist/hive/tenants.js.map +1 -0
- package/dist/hive/tunnel/cloudflare.js +160 -0
- package/dist/hive/tunnel/cloudflare.js.map +1 -0
- package/dist/hive/tunnel/mock.js +52 -0
- package/dist/hive/tunnel/mock.js.map +1 -0
- package/dist/hive/tunnel/provider.js +19 -0
- package/dist/hive/tunnel/provider.js.map +1 -0
- package/dist/hive/updates.js +61 -0
- package/dist/hive/updates.js.map +1 -0
- package/dist/http-error.js +11 -0
- package/dist/http-error.js.map +1 -0
- package/dist/impact/classify.js +226 -0
- package/dist/impact/classify.js.map +1 -0
- package/dist/impact/find.js +259 -0
- package/dist/impact/find.js.map +1 -0
- package/dist/impact/pr.js +54 -0
- package/dist/impact/pr.js.map +1 -0
- package/dist/impact/store.js +365 -0
- package/dist/impact/store.js.map +1 -0
- package/dist/impact/text.js +158 -0
- package/dist/impact/text.js.map +1 -0
- package/dist/index.js +288 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/adf.js +397 -0
- package/dist/integrations/adf.js.map +1 -0
- package/dist/integrations/bot-marker.js +103 -0
- package/dist/integrations/bot-marker.js.map +1 -0
- package/dist/integrations/github-issues.js +705 -0
- package/dist/integrations/github-issues.js.map +1 -0
- package/dist/integrations/github.js +1284 -0
- package/dist/integrations/github.js.map +1 -0
- package/dist/integrations/issue-create.js +60 -0
- package/dist/integrations/issue-create.js.map +1 -0
- package/dist/integrations/jira.js +279 -0
- package/dist/integrations/jira.js.map +1 -0
- package/dist/integrations/linear.js +273 -0
- package/dist/integrations/linear.js.map +1 -0
- package/dist/integrations/own-identity-warm.js +47 -0
- package/dist/integrations/own-identity-warm.js.map +1 -0
- package/dist/integrations/own-identity.js +39 -0
- package/dist/integrations/own-identity.js.map +1 -0
- package/dist/integrations/status-change.js +42 -0
- package/dist/integrations/status-change.js.map +1 -0
- package/dist/lead-defects.js +202 -0
- package/dist/lead-defects.js.map +1 -0
- package/dist/lead-digest.js +333 -0
- package/dist/lead-digest.js.map +1 -0
- package/dist/lead-release.js +286 -0
- package/dist/lead-release.js.map +1 -0
- package/dist/lead.js +328 -0
- package/dist/lead.js.map +1 -0
- package/dist/legacy-names.js +51 -0
- package/dist/legacy-names.js.map +1 -0
- package/dist/limits.js +44 -0
- package/dist/limits.js.map +1 -0
- package/dist/link-trust.js +224 -0
- package/dist/link-trust.js.map +1 -0
- package/dist/links.js +219 -0
- package/dist/links.js.map +1 -0
- package/dist/loopback.js +35 -0
- package/dist/loopback.js.map +1 -0
- package/dist/model-cap.js +60 -0
- package/dist/model-cap.js.map +1 -0
- package/dist/model-usage.js +173 -0
- package/dist/model-usage.js.map +1 -0
- package/dist/monitor/backfill.js +39 -0
- package/dist/monitor/backfill.js.map +1 -0
- package/dist/monitor/browser-probe.js +198 -0
- package/dist/monitor/browser-probe.js.map +1 -0
- package/dist/monitor/catch-up.js +31 -0
- package/dist/monitor/catch-up.js.map +1 -0
- package/dist/monitor/pollers.js +1606 -0
- package/dist/monitor/pollers.js.map +1 -0
- package/dist/monitor/probes.js +178 -0
- package/dist/monitor/probes.js.map +1 -0
- package/dist/monitor/self-health.js +228 -0
- package/dist/monitor/self-health.js.map +1 -0
- package/dist/monitor/statuspage.js +105 -0
- package/dist/monitor/statuspage.js.map +1 -0
- package/dist/nightly-scheduler.js +127 -0
- package/dist/nightly-scheduler.js.map +1 -0
- package/dist/nightly.js +141 -0
- package/dist/nightly.js.map +1 -0
- package/dist/notify/headline.js +114 -0
- package/dist/notify/headline.js.map +1 -0
- package/dist/notify/push.js +174 -0
- package/dist/notify/push.js.map +1 -0
- package/dist/object-cards.js +585 -0
- package/dist/object-cards.js.map +1 -0
- package/dist/object-links.js +47 -0
- package/dist/object-links.js.map +1 -0
- package/dist/onboarding-checks.js +141 -0
- package/dist/onboarding-checks.js.map +1 -0
- package/dist/onboarding.js +401 -0
- package/dist/onboarding.js.map +1 -0
- package/dist/path-filters.js +62 -0
- package/dist/path-filters.js.map +1 -0
- package/dist/phone/alerts.js +67 -0
- package/dist/phone/alerts.js.map +1 -0
- package/dist/phone/auth.js +240 -0
- package/dist/phone/auth.js.map +1 -0
- package/dist/phone/pairing.js +442 -0
- package/dist/phone/pairing.js.map +1 -0
- package/dist/phone/prefs.js +27 -0
- package/dist/phone/prefs.js.map +1 -0
- package/dist/phone/tailscale.js +161 -0
- package/dist/phone/tailscale.js.map +1 -0
- package/dist/pr-scope.js +441 -0
- package/dist/pr-scope.js.map +1 -0
- package/dist/proc.js +156 -0
- package/dist/proc.js.map +1 -0
- package/dist/profile/cache.js +108 -0
- package/dist/profile/cache.js.map +1 -0
- package/dist/profile/ci.js +216 -0
- package/dist/profile/ci.js.map +1 -0
- package/dist/profile/index.js +8 -0
- package/dist/profile/index.js.map +1 -0
- package/dist/profile/job.js +135 -0
- package/dist/profile/job.js.map +1 -0
- package/dist/profile/queries/go-tags.scm +47 -0
- package/dist/profile/queries/java-tags.scm +25 -0
- package/dist/profile/queries/javascript-tags.scm +104 -0
- package/dist/profile/queries/python-tags.scm +19 -0
- package/dist/profile/queries/typescript-tags.scm +28 -0
- package/dist/profile/scan-thread.js +42 -0
- package/dist/profile/scan-thread.js.map +1 -0
- package/dist/profile/scan-worker.js +16 -0
- package/dist/profile/scan-worker.js.map +1 -0
- package/dist/profile/scan.js +351 -0
- package/dist/profile/scan.js.map +1 -0
- package/dist/profile/stack.js +528 -0
- package/dist/profile/stack.js.map +1 -0
- package/dist/profile/store.js +35 -0
- package/dist/profile/store.js.map +1 -0
- package/dist/profile/tests.js +399 -0
- package/dist/profile/tests.js.map +1 -0
- package/dist/queue.js +350 -0
- package/dist/queue.js.map +1 -0
- package/dist/refs.js +756 -0
- package/dist/refs.js.map +1 -0
- package/dist/release-notes.js +272 -0
- package/dist/release-notes.js.map +1 -0
- package/dist/reports/build.js +243 -0
- package/dist/reports/build.js.map +1 -0
- package/dist/reports/index.js +211 -0
- package/dist/reports/index.js.map +1 -0
- package/dist/reports/store.js +150 -0
- package/dist/reports/store.js.map +1 -0
- package/dist/reports/ticket-titles.js +124 -0
- package/dist/reports/ticket-titles.js.map +1 -0
- package/dist/reports/trace-map.js +1278 -0
- package/dist/reports/trace-map.js.map +1 -0
- package/dist/reports/traceability.js +422 -0
- package/dist/reports/traceability.js.map +1 -0
- package/dist/repos/mirror.js +356 -0
- package/dist/repos/mirror.js.map +1 -0
- package/dist/repos-github.js +108 -0
- package/dist/repos-github.js.map +1 -0
- package/dist/repos.js +891 -0
- package/dist/repos.js.map +1 -0
- package/dist/review/backend-anthropic.js +90 -0
- package/dist/review/backend-anthropic.js.map +1 -0
- package/dist/review/backend-cli.js +248 -0
- package/dist/review/backend-cli.js.map +1 -0
- package/dist/review/backend-codex.js +81 -0
- package/dist/review/backend-codex.js.map +1 -0
- package/dist/review/backend-mock.js +686 -0
- package/dist/review/backend-mock.js.map +1 -0
- package/dist/review/backend-only.js +168 -0
- package/dist/review/backend-only.js.map +1 -0
- package/dist/review/backend.js +105 -0
- package/dist/review/backend.js.map +1 -0
- package/dist/review/baseline/render-v1.js +483 -0
- package/dist/review/baseline/render-v1.js.map +1 -0
- package/dist/review/change-summary.js +197 -0
- package/dist/review/change-summary.js.map +1 -0
- package/dist/review/changelog.js +40 -0
- package/dist/review/changelog.js.map +1 -0
- package/dist/review/check.js +494 -0
- package/dist/review/check.js.map +1 -0
- package/dist/review/checkout.js +185 -0
- package/dist/review/checkout.js.map +1 -0
- package/dist/review/classify.js +178 -0
- package/dist/review/classify.js.map +1 -0
- package/dist/review/coverage.js +347 -0
- package/dist/review/coverage.js.map +1 -0
- package/dist/review/decision-eval.js +121 -0
- package/dist/review/decision-eval.js.map +1 -0
- package/dist/review/deliver.js +104 -0
- package/dist/review/deliver.js.map +1 -0
- package/dist/review/designer-eval.js +280 -0
- package/dist/review/designer-eval.js.map +1 -0
- package/dist/review/dogfood-digest.js +136 -0
- package/dist/review/dogfood-digest.js.map +1 -0
- package/dist/review/dogfood-eval.js +486 -0
- package/dist/review/dogfood-eval.js.map +1 -0
- package/dist/review/environment.js +109 -0
- package/dist/review/environment.js.map +1 -0
- package/dist/review/eval.js +405 -0
- package/dist/review/eval.js.map +1 -0
- package/dist/review/glob.js +110 -0
- package/dist/review/glob.js.map +1 -0
- package/dist/review/golden-export.js +219 -0
- package/dist/review/golden-export.js.map +1 -0
- package/dist/review/impact.js +406 -0
- package/dist/review/impact.js.map +1 -0
- package/dist/review/imports.js +542 -0
- package/dist/review/imports.js.map +1 -0
- package/dist/review/index.js +512 -0
- package/dist/review/index.js.map +1 -0
- package/dist/review/intent.js +128 -0
- package/dist/review/intent.js.map +1 -0
- package/dist/review/lenses.js +167 -0
- package/dist/review/lenses.js.map +1 -0
- package/dist/review/linked-tickets.js +293 -0
- package/dist/review/linked-tickets.js.map +1 -0
- package/dist/review/merge.js +370 -0
- package/dist/review/merge.js.map +1 -0
- package/dist/review/on-demand.js +218 -0
- package/dist/review/on-demand.js.map +1 -0
- package/dist/review/prompt-eval.js +299 -0
- package/dist/review/prompt-eval.js.map +1 -0
- package/dist/review/prompt-variants.js +37 -0
- package/dist/review/prompt-variants.js.map +1 -0
- package/dist/review/readability-eval.js +217 -0
- package/dist/review/readability-eval.js.map +1 -0
- package/dist/review/readability.js +295 -0
- package/dist/review/readability.js.map +1 -0
- package/dist/review/render.js +2409 -0
- package/dist/review/render.js.map +1 -0
- package/dist/review/repo.js +194 -0
- package/dist/review/repo.js.map +1 -0
- package/dist/review/report-plan.js +90 -0
- package/dist/review/report-plan.js.map +1 -0
- package/dist/review/routes.js +195 -0
- package/dist/review/routes.js.map +1 -0
- package/dist/review/run-summary.js +34 -0
- package/dist/review/run-summary.js.map +1 -0
- package/dist/review/run.js +245 -0
- package/dist/review/run.js.map +1 -0
- package/dist/review/scope.js +454 -0
- package/dist/review/scope.js.map +1 -0
- package/dist/review/security.js +432 -0
- package/dist/review/security.js.map +1 -0
- package/dist/review/signals.js +550 -0
- package/dist/review/signals.js.map +1 -0
- package/dist/review/specs.js +150 -0
- package/dist/review/specs.js.map +1 -0
- package/dist/review/ste.js +133 -0
- package/dist/review/ste.js.map +1 -0
- package/dist/review/test-repo-file.js +18 -0
- package/dist/review/test-repo-file.js.map +1 -0
- package/dist/review/test-repo-lines.js +53 -0
- package/dist/review/test-repo-lines.js.map +1 -0
- package/dist/review/ticket-on-demand.js +232 -0
- package/dist/review/ticket-on-demand.js.map +1 -0
- package/dist/review/yaml.js +298 -0
- package/dist/review/yaml.js.map +1 -0
- package/dist/room.js +361 -0
- package/dist/room.js.map +1 -0
- package/dist/routes/activity.js +219 -0
- package/dist/routes/activity.js.map +1 -0
- package/dist/routes/call.js +29 -0
- package/dist/routes/call.js.map +1 -0
- package/dist/routes/cards.js +40 -0
- package/dist/routes/cards.js.map +1 -0
- package/dist/routes/cases.js +133 -0
- package/dist/routes/cases.js.map +1 -0
- package/dist/routes/connect.js +268 -0
- package/dist/routes/connect.js.map +1 -0
- package/dist/routes/connection-presets.js +32 -0
- package/dist/routes/connection-presets.js.map +1 -0
- package/dist/routes/connections.js +177 -0
- package/dist/routes/connections.js.map +1 -0
- package/dist/routes/disk.js +19 -0
- package/dist/routes/disk.js.map +1 -0
- package/dist/routes/docs.js +71 -0
- package/dist/routes/docs.js.map +1 -0
- package/dist/routes/dot-suggest.js +1002 -0
- package/dist/routes/dot-suggest.js.map +1 -0
- package/dist/routes/evidence-pack.js +16 -0
- package/dist/routes/evidence-pack.js.map +1 -0
- package/dist/routes/health.js +121 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/impact.js +48 -0
- package/dist/routes/impact.js.map +1 -0
- package/dist/routes/lead.js +50 -0
- package/dist/routes/lead.js.map +1 -0
- package/dist/routes/links.js +13 -0
- package/dist/routes/links.js.map +1 -0
- package/dist/routes/markdown.js +62 -0
- package/dist/routes/markdown.js.map +1 -0
- package/dist/routes/onboarding.js +47 -0
- package/dist/routes/onboarding.js.map +1 -0
- package/dist/routes/phone.js +231 -0
- package/dist/routes/phone.js.map +1 -0
- package/dist/routes/release-notes.js +30 -0
- package/dist/routes/release-notes.js.map +1 -0
- package/dist/routes/reports.js +102 -0
- package/dist/routes/reports.js.map +1 -0
- package/dist/routes/repos.js +91 -0
- package/dist/routes/repos.js.map +1 -0
- package/dist/routes/review.js +283 -0
- package/dist/routes/review.js.map +1 -0
- package/dist/routes/roles.js +114 -0
- package/dist/routes/roles.js.map +1 -0
- package/dist/routes/room.js +21 -0
- package/dist/routes/room.js.map +1 -0
- package/dist/routes/runner.js +156 -0
- package/dist/routes/runner.js.map +1 -0
- package/dist/routes/runs.js +84 -0
- package/dist/routes/runs.js.map +1 -0
- package/dist/routes/setup.js +18 -0
- package/dist/routes/setup.js.map +1 -0
- package/dist/routes/test-runs.js +220 -0
- package/dist/routes/test-runs.js.map +1 -0
- package/dist/routes/ticket-status.js +17 -0
- package/dist/routes/ticket-status.js.map +1 -0
- package/dist/routes/traceability.js +143 -0
- package/dist/routes/traceability.js.map +1 -0
- package/dist/routes/true.js +142 -0
- package/dist/routes/true.js.map +1 -0
- package/dist/routes/updates.js +70 -0
- package/dist/routes/updates.js.map +1 -0
- package/dist/runner/adapters/index.js +12 -0
- package/dist/runner/adapters/index.js.map +1 -0
- package/dist/runner/adapters/playwright.js +68 -0
- package/dist/runner/adapters/playwright.js.map +1 -0
- package/dist/runner/aivision/cases.js +172 -0
- package/dist/runner/aivision/cases.js.map +1 -0
- package/dist/runner/aivision/cli.js +201 -0
- package/dist/runner/aivision/cli.js.map +1 -0
- package/dist/runner/aivision/index.js +281 -0
- package/dist/runner/aivision/index.js.map +1 -0
- package/dist/runner/aivision/server.js +394 -0
- package/dist/runner/aivision/server.js.map +1 -0
- package/dist/runner/aivision/shared.js +140 -0
- package/dist/runner/aivision/shared.js.map +1 -0
- package/dist/runner/artifact-cap.js +189 -0
- package/dist/runner/artifact-cap.js.map +1 -0
- package/dist/runner/artifacts.js +433 -0
- package/dist/runner/artifacts.js.map +1 -0
- package/dist/runner/command.js +564 -0
- package/dist/runner/command.js.map +1 -0
- package/dist/runner/copyfiles.js +221 -0
- package/dist/runner/copyfiles.js.map +1 -0
- package/dist/runner/engines.js +32 -0
- package/dist/runner/engines.js.map +1 -0
- package/dist/runner/evidence.js +114 -0
- package/dist/runner/evidence.js.map +1 -0
- package/dist/runner/host-env.js +160 -0
- package/dist/runner/host-env.js.map +1 -0
- package/dist/runner/index.js +1221 -0
- package/dist/runner/index.js.map +1 -0
- package/dist/runner/observe.js +603 -0
- package/dist/runner/observe.js.map +1 -0
- package/dist/runner/playwright-json.js +108 -0
- package/dist/runner/playwright-json.js.map +1 -0
- package/dist/runner/pwgen/exec.js +192 -0
- package/dist/runner/pwgen/exec.js.map +1 -0
- package/dist/runner/pwgen/explore.js +111 -0
- package/dist/runner/pwgen/explore.js.map +1 -0
- package/dist/runner/pwgen/index.js +423 -0
- package/dist/runner/pwgen/index.js.map +1 -0
- package/dist/runner/pwgen/propose.js +69 -0
- package/dist/runner/pwgen/propose.js.map +1 -0
- package/dist/runner/pwgen/source.js +632 -0
- package/dist/runner/pwgen/source.js.map +1 -0
- package/dist/runner/setup.js +222 -0
- package/dist/runner/setup.js.map +1 -0
- package/dist/runner/step-reporter.js +107 -0
- package/dist/runner/step-reporter.js.map +1 -0
- package/dist/runner/test-repo.js +326 -0
- package/dist/runner/test-repo.js.map +1 -0
- package/dist/runner/typed-value.js +46 -0
- package/dist/runner/typed-value.js.map +1 -0
- package/dist/runner/verify.js +133 -0
- package/dist/runner/verify.js.map +1 -0
- package/dist/runner/worktree.js +349 -0
- package/dist/runner/worktree.js.map +1 -0
- package/dist/sandbox.js +61 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/server.js +262 -0
- package/dist/server.js.map +1 -0
- package/dist/shadow-week.js +126 -0
- package/dist/shadow-week.js.map +1 -0
- package/dist/shutdown.js +92 -0
- package/dist/shutdown.js.map +1 -0
- package/dist/slack/index.js +645 -0
- package/dist/slack/index.js.map +1 -0
- package/dist/stages/config.js +147 -0
- package/dist/stages/config.js.map +1 -0
- package/dist/stages/index.js +41 -0
- package/dist/stages/index.js.map +1 -0
- package/dist/suites.js +293 -0
- package/dist/suites.js.map +1 -0
- package/dist/target-url.js +116 -0
- package/dist/target-url.js.map +1 -0
- package/dist/test-runs.js +662 -0
- package/dist/test-runs.js.map +1 -0
- package/dist/ticket-keys.js +97 -0
- package/dist/ticket-keys.js.map +1 -0
- package/dist/ticket-supersede.js +105 -0
- package/dist/ticket-supersede.js.map +1 -0
- package/dist/tinybee/ed25519.js +99 -0
- package/dist/tinybee/ed25519.js.map +1 -0
- package/dist/tinybee/models-routes.js +19 -0
- package/dist/tinybee/models-routes.js.map +1 -0
- package/dist/tinybee/pair-payload.js +41 -0
- package/dist/tinybee/pair-payload.js.map +1 -0
- package/dist/tinybee/update-manifest.js +77 -0
- package/dist/tinybee/update-manifest.js.map +1 -0
- package/dist/tinybee/well-known.js +64 -0
- package/dist/tinybee/well-known.js.map +1 -0
- package/dist/tinybee/workflows/activity.js +23 -0
- package/dist/tinybee/workflows/activity.js.map +1 -0
- package/dist/tinybee/workflows/cron.js +210 -0
- package/dist/tinybee/workflows/cron.js.map +1 -0
- package/dist/tinybee/workflows/engine.js +371 -0
- package/dist/tinybee/workflows/engine.js.map +1 -0
- package/dist/tinybee/workflows/from-text.js +203 -0
- package/dist/tinybee/workflows/from-text.js.map +1 -0
- package/dist/tinybee/workflows/routes.js +189 -0
- package/dist/tinybee/workflows/routes.js.map +1 -0
- package/dist/tinybee/workflows/scheduler.js +100 -0
- package/dist/tinybee/workflows/scheduler.js.map +1 -0
- package/dist/tinybee/workflows/skills.js +227 -0
- package/dist/tinybee/workflows/skills.js.map +1 -0
- package/dist/tinybee/workflows/store.js +205 -0
- package/dist/tinybee/workflows/store.js.map +1 -0
- package/dist/tinybee/workflows/types.js +180 -0
- package/dist/tinybee/workflows/types.js.map +1 -0
- package/dist/tinybee/workflows/yaml.js +323 -0
- package/dist/tinybee/workflows/yaml.js.map +1 -0
- package/dist/true/api.js +495 -0
- package/dist/true/api.js.map +1 -0
- package/dist/true/client.js +292 -0
- package/dist/true/client.js.map +1 -0
- package/dist/true/clock.js +36 -0
- package/dist/true/clock.js.map +1 -0
- package/dist/true/events.js +125 -0
- package/dist/true/events.js.map +1 -0
- package/dist/true/hosts.js +98 -0
- package/dist/true/hosts.js.map +1 -0
- package/dist/true/index.js +29 -0
- package/dist/true/index.js.map +1 -0
- package/dist/true/key.js +54 -0
- package/dist/true/key.js.map +1 -0
- package/dist/true/line.js +69 -0
- package/dist/true/line.js.map +1 -0
- package/dist/true/mask.js +31 -0
- package/dist/true/mask.js.map +1 -0
- package/dist/true/names.js +114 -0
- package/dist/true/names.js.map +1 -0
- package/dist/true/outbox.js +233 -0
- package/dist/true/outbox.js.map +1 -0
- package/dist/true/replay.js +164 -0
- package/dist/true/replay.js.map +1 -0
- package/dist/true/settings.js +123 -0
- package/dist/true/settings.js.map +1 -0
- package/dist/true/status.js +189 -0
- package/dist/true/status.js.map +1 -0
- package/dist/true/sync-cases.js +222 -0
- package/dist/true/sync-cases.js.map +1 -0
- package/dist/true/sync-manual.js +295 -0
- package/dist/true/sync-manual.js.map +1 -0
- package/dist/true/sync-runs.js +109 -0
- package/dist/true/sync-runs.js.map +1 -0
- package/dist/true/worker.js +414 -0
- package/dist/true/worker.js.map +1 -0
- package/dist/types.js +32 -0
- package/dist/types.js.map +1 -0
- package/dist/updates/asks.js +38 -0
- package/dist/updates/asks.js.map +1 -0
- package/dist/updates/index.js +835 -0
- package/dist/updates/index.js.map +1 -0
- package/dist/updates/owner.js +24 -0
- package/dist/updates/owner.js.map +1 -0
- package/dist/updates/prefs.js +118 -0
- package/dist/updates/prefs.js.map +1 -0
- package/dist/updates/route.js +78 -0
- package/dist/updates/route.js.map +1 -0
- package/dist/updates/sources.js +345 -0
- package/dist/updates/sources.js.map +1 -0
- package/dist/updates/words.js +452 -0
- package/dist/updates/words.js.map +1 -0
- package/dist/version.js +53 -0
- package/dist/version.js.map +1 -0
- package/dist/view-compute.js +382 -0
- package/dist/view-compute.js.map +1 -0
- package/dist/view-spec.js +894 -0
- package/dist/view-spec.js.map +1 -0
- package/dist/web/apple-touch-icon.png +0 -0
- package/dist/web/assets/ApprovalCard-Br_z5z7G.css +1 -0
- package/dist/web/assets/ApprovalCard-CfGhGFo_.js +3 -0
- package/dist/web/assets/CardFromRef-BaTGmZ9c.js +2 -0
- package/dist/web/assets/CardFromRef-DO7i2uDd.css +1 -0
- package/dist/web/assets/Cases-8l_6UcLh.js +2 -0
- package/dist/web/assets/Cases-CpfED0uB.css +1 -0
- package/dist/web/assets/Chat-BKDiR0qt.js +3 -0
- package/dist/web/assets/Chat-DxjdyYUu.css +1 -0
- package/dist/web/assets/ConfirmDialog-CIMveD-b.js +2 -0
- package/dist/web/assets/ConnectSheet-Cm5vbZdR.js +4 -0
- package/dist/web/assets/Docs-HKGuY0WE.js +2 -0
- package/dist/web/assets/Docs-fodKx8S7.css +1 -0
- package/dist/web/assets/DotDetail-DskS3NWe.js +2 -0
- package/dist/web/assets/DotDetail-OWRSD_1x.css +1 -0
- package/dist/web/assets/DotStage-BZDclfzV.css +1 -0
- package/dist/web/assets/DotStage-CtMNzCN3.js +2 -0
- package/dist/web/assets/Dots-BqCsS34m.js +2 -0
- package/dist/web/assets/EvidencePack-DQ3kCJX4.js +2 -0
- package/dist/web/assets/EvidencePack-DV_9ETsA.css +1 -0
- package/dist/web/assets/FailedDeliveries-1F2kFcs9.js +2 -0
- package/dist/web/assets/FailedDeliveries-DXa2_VvI.css +1 -0
- package/dist/web/assets/Feed-5wiHRTFK.js +2 -0
- package/dist/web/assets/GfmView-C-NYaduC.js +4 -0
- package/dist/web/assets/ImpactList-C-RNuDB0.js +2 -0
- package/dist/web/assets/ImpactList-C612dFdw.css +1 -0
- package/dist/web/assets/Inbox-kc1bKVL_.js +2 -0
- package/dist/web/assets/JoinScreen-C3L4wmP3.js +2 -0
- package/dist/web/assets/JoinScreen-COeAUv5v.css +1 -0
- package/dist/web/assets/LeadDialog-N3Zul9Rw.js +8 -0
- package/dist/web/assets/LeadDialog-xyWjAuAS.css +1 -0
- package/dist/web/assets/ListeningLine-BRFNaczY.js +2 -0
- package/dist/web/assets/ListeningLine-pN8CgyiK.css +1 -0
- package/dist/web/assets/Mascots-pIyGpxtD.js +2 -0
- package/dist/web/assets/ModelChoices-BxO1zyyr.js +2 -0
- package/dist/web/assets/ModelChoices-DQJnVxfs.css +1 -0
- package/dist/web/assets/NewDotDialog-CDPUWmgN.js +2 -0
- package/dist/web/assets/NewDotDialog-DrPPqkSZ.css +1 -0
- package/dist/web/assets/NewTestRunDialog-BQBthVHE.js +2 -0
- package/dist/web/assets/NoBreakNames-Csxdqdt6.js +2 -0
- package/dist/web/assets/Pair-omex_K7H.js +2 -0
- package/dist/web/assets/PushSection-CmqHlE_2.js +2 -0
- package/dist/web/assets/ReleaseNotes-B6VqFewP.js +2 -0
- package/dist/web/assets/ReleaseNotes-DBJUL7Vm.css +1 -0
- package/dist/web/assets/ReportPage-BHS1xWEt.js +162 -0
- package/dist/web/assets/Reports-BEHnDIb1.js +2 -0
- package/dist/web/assets/ReviewChangeDialog-BVSt-cw-.js +2 -0
- package/dist/web/assets/ReviewChangeDialog-BbIlHRx0.css +1 -0
- package/dist/web/assets/Room-BoG_uge4.js +2 -0
- package/dist/web/assets/Room-evAfiW_e.css +1 -0
- package/dist/web/assets/RunActions-ZY7yf1AF.js +2 -0
- package/dist/web/assets/RunDetail-C8St20GQ.css +1 -0
- package/dist/web/assets/RunDetail-qADXjBvd.js +9 -0
- package/dist/web/assets/RunRow-BKEJv8ib.js +2 -0
- package/dist/web/assets/RunnerTry-Dgpp67-s.js +6 -0
- package/dist/web/assets/RunnerTry-DsweWOfO.css +1 -0
- package/dist/web/assets/Settings-fs-QJwNM.js +2 -0
- package/dist/web/assets/Setup-DI6hBEP-.js +2 -0
- package/dist/web/assets/TestRows-wh03T5Li.js +4 -0
- package/dist/web/assets/TestRun-DTOyF-Pv.js +2 -0
- package/dist/web/assets/TestRuns-ggDjm1Q8.js +2 -0
- package/dist/web/assets/TinyBeeAddLaptop-bc3pmh3T.js +2 -0
- package/dist/web/assets/TinyBeeAi-CkyOzhm5.js +2 -0
- package/dist/web/assets/TinyBeeConnections-B2K_P38u.js +2 -0
- package/dist/web/assets/TinyBeeHome-DSpxX5KS.js +3 -0
- package/dist/web/assets/TinyBeePlan-BamiLziu.js +2 -0
- package/dist/web/assets/TinyBeeSignup-vHcz0Wen.js +2 -0
- package/dist/web/assets/TinyBeeSkills-By9RLUse.js +2 -0
- package/dist/web/assets/TinyBeeWorkflow-DeNO7Jsh.js +2 -0
- package/dist/web/assets/TinyBeeWorkflowEditor-B6OGC2OT.js +2 -0
- package/dist/web/assets/TinyBeeWorkflows-BN4-h6lt.js +2 -0
- package/dist/web/assets/Trace-BBCI1aIB.css +1 -0
- package/dist/web/assets/Trace-aF92UWaH.js +2 -0
- package/dist/web/assets/UpdatesSection-CCWEbkue.js +2 -0
- package/dist/web/assets/Welcome-CCcy558Q.js +2 -0
- package/dist/web/assets/activity-C3qilrDm.css +1 -0
- package/dist/web/assets/activity-CBfTSxqw.js +2 -0
- package/dist/web/assets/authedMedia-BTYt_tyu.js +2 -0
- package/dist/web/assets/beeApi-BHW8Tx1s.js +2 -0
- package/dist/web/assets/data-CmXvx3Mj.js +2 -0
- package/dist/web/assets/engines-CfdJODFj.css +1 -0
- package/dist/web/assets/format-BBZ8vFyT.js +2 -0
- package/dist/web/assets/forms-Coc7p2UF.css +1 -0
- package/dist/web/assets/hivePush-DZJDokj7.js +2 -0
- package/dist/web/assets/impactModel-MY1OFuiP.js +2 -0
- package/dist/web/assets/index-B6qKm1NW.js +13 -0
- package/dist/web/assets/index-BvKyT1X7.css +1 -0
- package/dist/web/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- package/dist/web/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- package/dist/web/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- package/dist/web/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- package/dist/web/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/dist/web/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/dist/web/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- package/dist/web/assets/lead-BL_P_kri.css +1 -0
- package/dist/web/assets/model-BIQy5IVG.js +2 -0
- package/dist/web/assets/modelsApi-PUSySRQw.js +2 -0
- package/dist/web/assets/newDotModel-BaLLyw57.js +2 -0
- package/dist/web/assets/onboarding-bfKqnM4Z.css +1 -0
- package/dist/web/assets/phone-Rs7FoyG0.css +1 -0
- package/dist/web/assets/phoneApi-BG_1-M-D.js +3 -0
- package/dist/web/assets/releaseModel-EynYMVOC.js +2 -0
- package/dist/web/assets/releaseNotesModel-A1Rtv3cV.js +2 -0
- package/dist/web/assets/reports-BWaA1HhM.js +37 -0
- package/dist/web/assets/reports-DXwdWQsB.css +1 -0
- package/dist/web/assets/router-W6nZsQ33.js +2 -0
- package/dist/web/assets/runs-BY0Owv93.css +1 -0
- package/dist/web/assets/shadowWeekModel-BUUiww09.js +2 -0
- package/dist/web/assets/storage-yvL36AWt.js +2 -0
- package/dist/web/assets/store-IqrqHuFR.js +2 -0
- package/dist/web/assets/testruns-BzIZ0cR0.css +1 -0
- package/dist/web/assets/testruns-DyaqX4ji.js +2 -0
- package/dist/web/assets/true-9Q68cs5b.js +2 -0
- package/dist/web/assets/true-DPGBpoir.css +1 -0
- package/dist/web/assets/ui-DcmhYyYp.js +13 -0
- package/dist/web/assets/ui-DxEDgbIx.css +1 -0
- package/dist/web/assets/usePauseDot-BV60ZVy1.js +2 -0
- package/dist/web/assets/usePauseDot-NrSzMI1C.css +1 -0
- package/dist/web/assets/usePush-Dsm-TjlG.js +2 -0
- package/dist/web/assets/useRefChips-CbafNx59.js +68 -0
- package/dist/web/assets/useRestoreDot-D0B6W82H.js +2 -0
- package/dist/web/assets/view-worker-pyeVAhUT.js +2 -0
- package/dist/web/assets/workflowUi-QYsd3n9J.js +2 -0
- package/dist/web/favicon.png +0 -0
- package/dist/web/icon-192.png +0 -0
- package/dist/web/icon-512.png +0 -0
- package/dist/web/icon-maskable-512.png +0 -0
- package/dist/web/index.html +45 -0
- package/dist/web/manifest.webmanifest +23 -0
- package/dist/web/mascots/argus-attention.svg +7 -0
- package/dist/web/mascots/argus-ok.svg +7 -0
- package/dist/web/mascots/argus-outage.svg +7 -0
- package/dist/web/mascots/argus-running.svg +7 -0
- package/dist/web/mascots/bolt-attention.svg +7 -0
- package/dist/web/mascots/bolt-ok.svg +7 -0
- package/dist/web/mascots/bolt-outage.svg +7 -0
- package/dist/web/mascots/bolt-running.svg +7 -0
- package/dist/web/mascots/echo-attention.svg +7 -0
- package/dist/web/mascots/echo-ok.svg +7 -0
- package/dist/web/mascots/echo-outage.svg +7 -0
- package/dist/web/mascots/echo-running.svg +7 -0
- package/dist/web/mascots/lens-attention.svg +7 -0
- package/dist/web/mascots/lens-ok.svg +7 -0
- package/dist/web/mascots/lens-outage.svg +7 -0
- package/dist/web/mascots/lens-running.svg +7 -0
- package/dist/web/mascots/moss-attention.svg +7 -0
- package/dist/web/mascots/moss-ok.svg +7 -0
- package/dist/web/mascots/moss-outage.svg +7 -0
- package/dist/web/mascots/moss-running.svg +7 -0
- package/dist/web/mascots/nit-attention.svg +7 -0
- package/dist/web/mascots/nit-ok.svg +7 -0
- package/dist/web/mascots/nit-outage.svg +7 -0
- package/dist/web/mascots/nit-running.svg +7 -0
- package/dist/web/mascots/nova-attention.svg +7 -0
- package/dist/web/mascots/nova-ok.svg +7 -0
- package/dist/web/mascots/nova-outage.svg +7 -0
- package/dist/web/mascots/nova-running.svg +7 -0
- package/dist/web/mascots/penn-attention.svg +7 -0
- package/dist/web/mascots/penn-ok.svg +7 -0
- package/dist/web/mascots/penn-outage.svg +7 -0
- package/dist/web/mascots/penn-running.svg +7 -0
- package/dist/web/mascots/pip-attention.svg +7 -0
- package/dist/web/mascots/pip-ok.svg +7 -0
- package/dist/web/mascots/pip-outage.svg +7 -0
- package/dist/web/mascots/pip-running.svg +7 -0
- package/dist/web/mascots/ward-attention.svg +7 -0
- package/dist/web/mascots/ward-ok.svg +7 -0
- package/dist/web/mascots/ward-outage.svg +7 -0
- package/dist/web/mascots/ward-running.svg +7 -0
- package/dist/web/sw.js +98 -0
- package/dist/webhook-seen.js +53 -0
- package/dist/webhook-seen.js.map +1 -0
- package/dist/webhooks.js +625 -0
- package/dist/webhooks.js.map +1 -0
- package/dist/zip.js +63 -0
- package/dist/zip.js.map +1 -0
- package/docs/API-V2.md +532 -0
- package/docs/CHAT-EVAL.md +130 -0
- package/docs/CHAT-UI.md +416 -0
- package/docs/CONNECTIONS.md +89 -0
- package/docs/DATA-MODEL.md +518 -0
- package/docs/DEPLOY.md +577 -0
- package/docs/DOGFOOD-LEDGER.md +81 -0
- package/docs/GITHUB.md +148 -0
- package/docs/INTEGRATION-MODEL.md +200 -0
- package/docs/LEAD-DOT.md +553 -0
- package/docs/LIST-PATTERNS.md +52 -0
- package/docs/MULTI-REPO.md +766 -0
- package/docs/PARITY.md +276 -0
- package/docs/PR-REVIEW-QA.md +1266 -0
- package/docs/PR-REVIEW.md +357 -0
- package/docs/SANDBOX.md +320 -0
- package/docs/SETUP.md +776 -0
- package/docs/SLACK.md +80 -0
- package/docs/STAGES.md +619 -0
- package/docs/TRACE-MAP.md +89 -0
- package/docs/TRACKERS.md +225 -0
- package/docs/VOICE.md +36 -0
- package/docs/tinybee/00-README.md +45 -0
- package/docs/tinybee/01-PRD.md +216 -0
- package/docs/tinybee/02-architecture-pairing.md +199 -0
- package/docs/tinybee/03-local-agent.md +222 -0
- package/docs/tinybee/04-local-setup-ui.md +128 -0
- package/docs/tinybee/05-mobile-app-ux.md +199 -0
- package/docs/tinybee/06-environments-and-delivery.md +148 -0
- package/docs/tinybee/07-coding-agent-handoff.md +116 -0
- package/docs/tinybee/OPEN-QUESTIONS.md +26 -0
- package/docs/tinybee/PROGRESS.md +134 -0
- package/package.json +111 -4
|
@@ -0,0 +1,686 @@
|
|
|
1
|
+
// Rule-based backend for the PR review (docs/PR-REVIEW-QA.md section 4.4). No model call.
|
|
2
|
+
// It builds risks from signals of weight 3 or more (one per kind) and from length guards
|
|
3
|
+
// on added lines, picks existing tests from the spec links, writes one new scenario per
|
|
4
|
+
// risk, and takes the regression scope from the graph. It never verifies: every claim
|
|
5
|
+
// stays unverified. The same answer serves as the fallback when a live pass fails.
|
|
6
|
+
//
|
|
7
|
+
// The demo pr_opened payload (search debounce) yields one risk ("One-letter search returns
|
|
8
|
+
// no results"), one existing test and one new scenario, so the demo shows every section.
|
|
9
|
+
import { converse } from './backend.js';
|
|
10
|
+
import { fileOf, isCitable } from './scope.js';
|
|
11
|
+
import { checklistItem, isSecurityCheck } from './security.js';
|
|
12
|
+
import { dropScreenSteps, isBackendOnly } from './backend-only.js';
|
|
13
|
+
const RISK_KIND = {
|
|
14
|
+
money: 'money',
|
|
15
|
+
auth: 'auth',
|
|
16
|
+
dates: 'dates',
|
|
17
|
+
concurrency: 'concurrency',
|
|
18
|
+
migration: 'migration',
|
|
19
|
+
feature_flag: 'feature_flag',
|
|
20
|
+
validation_changed: 'validation',
|
|
21
|
+
guard_removed: 'guard_removed',
|
|
22
|
+
response_shape: 'response_shape',
|
|
23
|
+
ui_state: 'ui_state',
|
|
24
|
+
selector_drift: 'selector_drift',
|
|
25
|
+
route_changed: 'route',
|
|
26
|
+
public_api: 'public_api',
|
|
27
|
+
config_env: 'config',
|
|
28
|
+
dependency_bump: 'dependency',
|
|
29
|
+
i18n_text: 'i18n',
|
|
30
|
+
};
|
|
31
|
+
const TEXT = {
|
|
32
|
+
money: {
|
|
33
|
+
title: 'Amount calculation changed',
|
|
34
|
+
why: 'The changed line computes or rounds an amount that users pay or receive.',
|
|
35
|
+
impact: 'Users see a wrong total, charge or refund.',
|
|
36
|
+
scenario: 'Check the amount on the changed path at a rounding boundary.',
|
|
37
|
+
steps: ['Build an order whose total rounds at half a cent', 'Complete the flow that uses the changed code'],
|
|
38
|
+
expected: 'The amount matches on every screen and receipt.',
|
|
39
|
+
severity: 'critical',
|
|
40
|
+
},
|
|
41
|
+
auth: {
|
|
42
|
+
title: 'Access check changed',
|
|
43
|
+
why: 'The changed line decides who can see or change data.',
|
|
44
|
+
impact: 'Users reach data they should not see, or lose access they need.',
|
|
45
|
+
scenario: 'Try the changed path as a user with each role.',
|
|
46
|
+
steps: ['Sign in as a user without the role', 'Open the changed page or call the changed endpoint'],
|
|
47
|
+
expected: 'Only users with the role get through.',
|
|
48
|
+
severity: 'critical',
|
|
49
|
+
},
|
|
50
|
+
dates: {
|
|
51
|
+
title: 'Date handling changed',
|
|
52
|
+
why: 'The changed line parses, formats or shifts a date.',
|
|
53
|
+
impact: 'Users see the wrong day or time near midnight or a time zone change.',
|
|
54
|
+
scenario: 'Check the changed date path in two time zones and on a month end.',
|
|
55
|
+
steps: ['Set the browser time zone to UTC minus 8', 'Use a date on the last day of a month'],
|
|
56
|
+
expected: 'The same date shows in every time zone.',
|
|
57
|
+
severity: 'high',
|
|
58
|
+
},
|
|
59
|
+
concurrency: {
|
|
60
|
+
title: 'Repeated actions overlap',
|
|
61
|
+
why: 'The changed line starts async work that a second action can start again.',
|
|
62
|
+
impact: 'Users see duplicate results or a stale answer after fast input.',
|
|
63
|
+
scenario: 'Repeat the changed action quickly on a slow network.',
|
|
64
|
+
steps: ['Throttle the network to slow 3G', 'Trigger the changed action twice in one second'],
|
|
65
|
+
expected: 'One request wins and the screen shows its result only.',
|
|
66
|
+
severity: 'high',
|
|
67
|
+
},
|
|
68
|
+
migration: {
|
|
69
|
+
title: 'Schema change on existing data',
|
|
70
|
+
why: 'The changed migration alters a table that already holds rows.',
|
|
71
|
+
impact: 'Deploys fail or existing records lose data.',
|
|
72
|
+
scenario: 'Apply the migration to a copy of a populated database.',
|
|
73
|
+
steps: ['Restore a database snapshot with rows', 'Run the migration'],
|
|
74
|
+
expected: 'The migration finishes and every row keeps its data.',
|
|
75
|
+
severity: 'critical',
|
|
76
|
+
},
|
|
77
|
+
feature_flag: {
|
|
78
|
+
title: 'Flag default changed',
|
|
79
|
+
why: 'The changed line sets or reads a feature flag.',
|
|
80
|
+
impact: 'Users get the new behaviour before anyone tested it.',
|
|
81
|
+
scenario: 'Run the changed flow with the flag on and with the flag off.',
|
|
82
|
+
steps: ['Turn the flag off and use the flow', 'Turn the flag on and use the flow'],
|
|
83
|
+
expected: 'Both states work as designed.',
|
|
84
|
+
severity: 'high',
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
const GENERIC = {
|
|
88
|
+
title: 'Changed behaviour on a core path',
|
|
89
|
+
why: 'The changed line alters behaviour that users reach directly.',
|
|
90
|
+
impact: 'Users see a different result than before.',
|
|
91
|
+
scenario: 'Use the changed flow with typical and boundary input.',
|
|
92
|
+
steps: ['Open the flow that uses the changed code', 'Use typical input, then boundary input'],
|
|
93
|
+
expected: 'The flow gives the same result as before for typical input.',
|
|
94
|
+
severity: 'high',
|
|
95
|
+
};
|
|
96
|
+
/** Rule-based text per security and robustness question; `why` and the scenario come from the lead. */
|
|
97
|
+
const CHECK_TEXT = {
|
|
98
|
+
attacker_choice: {
|
|
99
|
+
impact: 'A forged event makes this machine check out and run code that the owner never approved.',
|
|
100
|
+
steps: ['Send a pull request event whose commit is not the head of that pull request', 'Watch the run steps and the working folder'],
|
|
101
|
+
expected: 'The run refuses the commit, and no code from it is checked out or run.',
|
|
102
|
+
severity: 'high',
|
|
103
|
+
},
|
|
104
|
+
path_safety: {
|
|
105
|
+
impact: 'A crafted checkout makes the server write outside the run folder, or a named pipe hangs the run.',
|
|
106
|
+
steps: [
|
|
107
|
+
'Make a folder on the copied path a symlink to a folder outside the checkout',
|
|
108
|
+
'Make one listed path a named pipe',
|
|
109
|
+
'Start a run that copies the listed files',
|
|
110
|
+
],
|
|
111
|
+
expected: 'Both paths are skipped with a note, no file appears outside the run folder, and the run does not hang.',
|
|
112
|
+
severity: 'high',
|
|
113
|
+
},
|
|
114
|
+
delete_in_flight: {
|
|
115
|
+
impact: 'A deleted item can still post a comment, create an approval or save rows that point at nothing.',
|
|
116
|
+
steps: ['Start a run and hold it on a slow step, such as the model review', 'Delete the item that owns the run', 'Let the slow step finish'],
|
|
117
|
+
expected: 'The run stops quietly: no comment, approval or new row appears after the delete.',
|
|
118
|
+
severity: 'high',
|
|
119
|
+
},
|
|
120
|
+
caller_access: {
|
|
121
|
+
impact: 'A phone token or a caller without a token can read or change data that only the owner token may reach.',
|
|
122
|
+
steps: ['Call the changed route with no token', 'Call it with a phone token', 'Call it with the owner token'],
|
|
123
|
+
expected: 'Only the owner token gets through; the other calls get 401 or 403.',
|
|
124
|
+
severity: 'high',
|
|
125
|
+
},
|
|
126
|
+
changed_contract: {
|
|
127
|
+
impact: 'A caller that relies on the old result fails at once or takes the wrong branch.',
|
|
128
|
+
steps: [],
|
|
129
|
+
expected: 'Every caller gives the same result as before, or was changed on purpose.',
|
|
130
|
+
severity: 'high',
|
|
131
|
+
},
|
|
132
|
+
temp_cleanup: {
|
|
133
|
+
impact: 'Each run leaves folders in the temp folder until the disk is full.',
|
|
134
|
+
steps: ['Run the changed code ten times, one run failing', 'Count its folders in the temp folder'],
|
|
135
|
+
expected: 'The temp folder holds no folder from the runs.',
|
|
136
|
+
severity: 'medium',
|
|
137
|
+
},
|
|
138
|
+
time_dependent_test: {
|
|
139
|
+
impact: 'The suite fails just after midnight or in another time zone, and blocks unrelated changes.',
|
|
140
|
+
steps: ['Set the clock or a fake timer to 00:30 local time', 'Run the test file', 'Run it again with TZ set to a zone ten hours away'],
|
|
141
|
+
expected: 'The test passes at every time of day and in every time zone.',
|
|
142
|
+
severity: 'medium',
|
|
143
|
+
},
|
|
144
|
+
open_status: {
|
|
145
|
+
impact: 'A check or an approval stays pending forever, and the pull request looks blocked.',
|
|
146
|
+
steps: ['Open the item that sets the pending status', 'Reject it, let a second one expire, and make a third one fail'],
|
|
147
|
+
expected: 'The status closes each time with the reason.',
|
|
148
|
+
severity: 'high',
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
function securityText(f) {
|
|
152
|
+
const t = CHECK_TEXT[f.check];
|
|
153
|
+
const steps = f.check === 'changed_contract' && f.callers?.length
|
|
154
|
+
? onePerFileFirst(f.callers)
|
|
155
|
+
.slice(0, 6)
|
|
156
|
+
.map((c) => `Run the caller at ${c.file}:${c.line} with the input the change treats differently`)
|
|
157
|
+
: t.steps;
|
|
158
|
+
return { ...t, title: f.title, why: f.scenario, scenario: scenarioFor(f), steps };
|
|
159
|
+
}
|
|
160
|
+
/** The first caller of each file, then the rest, so the steps reach every calling file. */
|
|
161
|
+
function onePerFileFirst(callers) {
|
|
162
|
+
const seen = new Set();
|
|
163
|
+
const first = callers.filter((c) => !seen.has(c.file) && seen.add(c.file));
|
|
164
|
+
return [...first, ...callers.filter((c) => !first.includes(c))];
|
|
165
|
+
}
|
|
166
|
+
function scenarioFor(f) {
|
|
167
|
+
switch (f.check) {
|
|
168
|
+
case 'attacker_choice':
|
|
169
|
+
return 'Send an event that names a commit other than the pull request head. No checkout or test run starts.';
|
|
170
|
+
case 'path_safety':
|
|
171
|
+
return 'Put a symlinked folder and a named pipe on the copied paths, then start a run. Nothing is written outside.';
|
|
172
|
+
case 'delete_in_flight':
|
|
173
|
+
return 'Delete the item while one of its runs waits on a slow step. Nothing posts or saves after the delete.';
|
|
174
|
+
case 'caller_access':
|
|
175
|
+
return 'Call the changed route with no token, a phone token and the owner token. Only the owner token gets through.';
|
|
176
|
+
case 'changed_contract':
|
|
177
|
+
return `Run every caller of ${f.fn ?? 'the changed function'} with the input the change treats differently. Each caller still works.`;
|
|
178
|
+
case 'temp_cleanup':
|
|
179
|
+
return 'Run the changed code ten times, one run failing, then check the temp folder. No folder is left.';
|
|
180
|
+
case 'time_dependent_test':
|
|
181
|
+
return 'Run the test at 00:30 local time and in another time zone. It passes both times.';
|
|
182
|
+
case 'open_status':
|
|
183
|
+
return 'Reject, expire and fail the item that opened the status. The status closes each time.';
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const NUMBER_WORDS = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten'];
|
|
187
|
+
function cap(s) {
|
|
188
|
+
return s ? s[0].toUpperCase() + s.slice(1) : s;
|
|
189
|
+
}
|
|
190
|
+
function clipWords(s, n) {
|
|
191
|
+
const w = s
|
|
192
|
+
.replace(/[\r\n]+/g, ' ')
|
|
193
|
+
.split(String.fromCharCode(0x2014))
|
|
194
|
+
.join(', ')
|
|
195
|
+
.trim()
|
|
196
|
+
.split(/\s+/)
|
|
197
|
+
.filter(Boolean);
|
|
198
|
+
return w.length > n ? `${w.slice(0, n).join(' ')} ...` : w.join(' ');
|
|
199
|
+
}
|
|
200
|
+
/** First citable line of a signal's range, or null. With `kind`, the first one whose text shows that kind's pattern wins. */
|
|
201
|
+
function citableLine(f, s, kind) {
|
|
202
|
+
if (!f)
|
|
203
|
+
return null;
|
|
204
|
+
const end = Math.max(s.line, s.lineEnd ?? s.line);
|
|
205
|
+
let first = null;
|
|
206
|
+
for (let n = s.line; n <= end; n++) {
|
|
207
|
+
if (!isCitable(f, n))
|
|
208
|
+
continue;
|
|
209
|
+
first ??= n;
|
|
210
|
+
if (!kind)
|
|
211
|
+
return n;
|
|
212
|
+
const text = lineText(f, n);
|
|
213
|
+
if (text !== undefined && matchesKind(kind, text))
|
|
214
|
+
return n;
|
|
215
|
+
}
|
|
216
|
+
return first;
|
|
217
|
+
}
|
|
218
|
+
/** New-side line span of the patch hunk holding a line, for grouping signals with a risk. */
|
|
219
|
+
function hunkSpan(f, line) {
|
|
220
|
+
for (const h of f.hunks) {
|
|
221
|
+
const nums = h.lines.map((l) => l.n).filter((n) => n !== undefined);
|
|
222
|
+
if (!nums.length)
|
|
223
|
+
continue;
|
|
224
|
+
const lo = Math.min(...nums);
|
|
225
|
+
const hi = Math.max(...nums);
|
|
226
|
+
if (line >= lo && line <= hi)
|
|
227
|
+
return [lo, hi];
|
|
228
|
+
}
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
// ---------- grounding (KAT-100) ----------
|
|
232
|
+
/**
|
|
233
|
+
* What the changed line must show for a risk of this kind. A kind with no entry keeps the citation
|
|
234
|
+
* check only. Each entry is a list: the line matches when any pattern does.
|
|
235
|
+
*/
|
|
236
|
+
const KIND_PATTERNS = {
|
|
237
|
+
money: [/amount|price|total|round|currency|tax/i],
|
|
238
|
+
auth: [/auth|token|permission|role|session|acl|isAdmin|login/i, /\bcan[A-Z]/],
|
|
239
|
+
dates: [/\bnew Date\b|\bDate\./, /moment|dayjs|toISOString|timezone/i],
|
|
240
|
+
concurrency: [/await|Promise|setTimeout|debounce|async|queue/i, /\block|lock\b|Lock/],
|
|
241
|
+
migration: [/ALTER|CREATE|DROP|migrat/i],
|
|
242
|
+
feature_flag: [/flag|feature|toggle|enabled/i],
|
|
243
|
+
validation: [/valid|required|\bmin\b|\bmax\b|pattern|regex|length|trim|match/i],
|
|
244
|
+
config: [/env|config|setting|secret|url|port|timeout/i],
|
|
245
|
+
i18n: [/i18n|locale|translat|\bt\(|intl|lang/i],
|
|
246
|
+
};
|
|
247
|
+
export const GROUNDED_WHY_PREFIX = 'Rule-based guess, not verified:';
|
|
248
|
+
export const UNGROUNDED_REASON = 'Rule-based review: the line does not show the pattern';
|
|
249
|
+
/** Source code without comments and string contents; `inString` keeps strings (SQL lives in strings). */
|
|
250
|
+
function codeOnly(text, keepStrings) {
|
|
251
|
+
let out = text.replace(/\/\*.*?\*\//g, ' ');
|
|
252
|
+
if (!keepStrings)
|
|
253
|
+
out = out.replace(/'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"|`(?:[^`\\]|\\.)*`/g, '""');
|
|
254
|
+
const slash = out.search(/(^|\s)\/\/|(^|\s)#(?!\w)|(^|\s)--(\s|$)/);
|
|
255
|
+
if (slash >= 0)
|
|
256
|
+
out = out.slice(0, slash);
|
|
257
|
+
return /^\s*(\*|\/\*)/.test(out) ? '' : out;
|
|
258
|
+
}
|
|
259
|
+
/** Text of the changed line a citation points at: an added line, or the removed text at a deletion anchor. */
|
|
260
|
+
function lineText(f, line) {
|
|
261
|
+
const added = f.added.get(line);
|
|
262
|
+
if (added !== undefined)
|
|
263
|
+
return added;
|
|
264
|
+
if (f.status === 'removed')
|
|
265
|
+
return f.removedRuns.flatMap((r) => r.lines).join('\n') || undefined;
|
|
266
|
+
const runs = f.removedRuns.filter((r) => r.anchor === line);
|
|
267
|
+
return runs.length ? runs.flatMap((r) => r.lines).join('\n') : undefined;
|
|
268
|
+
}
|
|
269
|
+
function matchesKind(kind, text) {
|
|
270
|
+
const patterns = KIND_PATTERNS[kind];
|
|
271
|
+
return !patterns || patterns.some((re) => re.test(text));
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* The one place that holds the rule-based review to the diff. A risk stays only when every evidence
|
|
275
|
+
* line is a changed line of a changed file and the line itself shows the pattern of the risk kind.
|
|
276
|
+
* A dropped risk takes its what-to-test items and test gaps with it, and its signals go to `dropped`.
|
|
277
|
+
* A risk that stays is a guess: medium at most, low when only a comment or a string shows the pattern.
|
|
278
|
+
*/
|
|
279
|
+
export function groundRisks(answer, scope, signals = []) {
|
|
280
|
+
const keep = [];
|
|
281
|
+
const goneIds = new Set();
|
|
282
|
+
const dropped = [...answer.dropped];
|
|
283
|
+
for (const r of answer.risks) {
|
|
284
|
+
let level = r.evidence.length ? 'ok' : 'bad';
|
|
285
|
+
for (const ev of r.evidence) {
|
|
286
|
+
const f = fileOf(scope, ev.file);
|
|
287
|
+
if (!f || !isCitable(f, ev.line)) {
|
|
288
|
+
level = 'bad';
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
291
|
+
const text = lineText(f, ev.line);
|
|
292
|
+
if (text === undefined || !matchesKind(r.kind, text)) {
|
|
293
|
+
level = 'bad';
|
|
294
|
+
break;
|
|
295
|
+
}
|
|
296
|
+
// The pattern must show in code. A match only in a comment or a string makes a weak guess.
|
|
297
|
+
if (!matchesKind(r.kind, codeOnly(text, r.kind === 'migration')))
|
|
298
|
+
level = 'comment_or_string';
|
|
299
|
+
}
|
|
300
|
+
if (level === 'bad') {
|
|
301
|
+
goneIds.add(r.id);
|
|
302
|
+
for (const id of r.signals) {
|
|
303
|
+
const sig = signals.find((s) => s.id === id);
|
|
304
|
+
const f = sig ? fileOf(scope, sig.file) : undefined;
|
|
305
|
+
const at = sig && f ? (citableLine(f, sig) ?? sig.line) : undefined;
|
|
306
|
+
dropped.push({
|
|
307
|
+
signal: id,
|
|
308
|
+
reason: UNGROUNDED_REASON,
|
|
309
|
+
evidence: sig && at !== undefined ? { file: sig.file, line: at } : (r.evidence[0] ?? { file: sig?.file ?? '', line: sig?.line ?? 0 }),
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
const severity = level === 'comment_or_string' ? 'low' : r.severity === 'critical' || r.severity === 'high' ? 'medium' : r.severity;
|
|
315
|
+
keep.push({ ...r, severity, why: r.why.startsWith(GROUNDED_WHY_PREFIX) ? r.why : `${GROUNDED_WHY_PREFIX} ${r.why}` });
|
|
316
|
+
}
|
|
317
|
+
const severityOf = new Map(keep.map((r) => [r.id, r.severity]));
|
|
318
|
+
const whatToTest = answer.whatToTest
|
|
319
|
+
.filter((t) => !(t.riskIds.length && t.riskIds.every((id) => goneIds.has(id)) && !t.existingTest))
|
|
320
|
+
.map((t) => {
|
|
321
|
+
const riskIds = t.riskIds.filter((id) => !goneIds.has(id));
|
|
322
|
+
// A new scenario is a must only while one of its risks is still high.
|
|
323
|
+
if (t.existingTest || !riskIds.length)
|
|
324
|
+
return { ...t, riskIds };
|
|
325
|
+
return {
|
|
326
|
+
...t,
|
|
327
|
+
riskIds,
|
|
328
|
+
priority: riskIds.some((id) => severityOf.get(id) === 'high' || severityOf.get(id) === 'critical') ? 'must' : 'should',
|
|
329
|
+
};
|
|
330
|
+
});
|
|
331
|
+
const testGaps = answer.testGaps
|
|
332
|
+
.filter((g) => !(g.riskIds.length && g.riskIds.every((id) => goneIds.has(id))))
|
|
333
|
+
.map((g) => ({ ...g, riskIds: g.riskIds.filter((id) => !goneIds.has(id)) }));
|
|
334
|
+
return { ...answer, risks: keep, whatToTest, testGaps, dropped };
|
|
335
|
+
}
|
|
336
|
+
/** Identifiers that hold text a user types. A length guard on anything else is not a search or form bug. */
|
|
337
|
+
const USER_TEXT_EXACT = /^(?:q|query|search|term|text|input|value|keyword|filter|name|title|str|s)$/i;
|
|
338
|
+
const USER_TEXT_SUFFIX = /(?:[a-z0-9](?:Query|Search|Term|Text|Input|Keyword|Filter)|_(?:query|search|term|text|input|keyword|filter))$/;
|
|
339
|
+
const userText = (id) => USER_TEXT_EXACT.test(id) || USER_TEXT_SUFFIX.test(id);
|
|
340
|
+
/** `const trimmed = debounced.trim();` and `const d = useDebounce(query, 300);`: a value that is still the user's text. */
|
|
341
|
+
const ALIAS_CALL = /^(?:use[A-Za-z]*(?:Debounce|Deferred)[A-Za-z]*|debounce|String)\(\s*([A-Za-z_$][\w$]*)\b/;
|
|
342
|
+
const ALIAS_CHAIN = /^([A-Za-z_$][\w$]*)\s*(?:\??\.\s*(?:trim|trimStart|trimEnd|toLowerCase|toUpperCase|normalize|slice|replace)\([^)]*\)\s*)*(?:(?:\?\?|\|\|)\s*[^;]*)?;?\s*$/;
|
|
343
|
+
/**
|
|
344
|
+
* True when `id` names user text, directly or because the file (changed and context lines) assigns it from
|
|
345
|
+
* a name that does, through trimming, case changes or a debounce hook. Three hops at most. A value filtered
|
|
346
|
+
* or computed from user text (`const items = search(query)`) is not user text.
|
|
347
|
+
*/
|
|
348
|
+
function holdsUserText(f, id, depth = 0, seen = new Set()) {
|
|
349
|
+
if (userText(id))
|
|
350
|
+
return true;
|
|
351
|
+
if (depth >= 3 || seen.has(id))
|
|
352
|
+
return false;
|
|
353
|
+
seen.add(id);
|
|
354
|
+
const assign = new RegExp(`(?:const|let|var)\\s+${id.replace(/[$]/g, '\\$')}\\s*=\\s*(.+)$`);
|
|
355
|
+
for (const text of [...f.added.values(), ...f.context.values()]) {
|
|
356
|
+
const rhs = assign.exec(text.trim())?.[1]?.trim();
|
|
357
|
+
if (!rhs)
|
|
358
|
+
continue;
|
|
359
|
+
const from = (ALIAS_CALL.exec(rhs) ?? ALIAS_CHAIN.exec(rhs))?.[1];
|
|
360
|
+
if (from && from !== id && holdsUserText(f, from, depth + 1, seen))
|
|
361
|
+
return true;
|
|
362
|
+
}
|
|
363
|
+
return false;
|
|
364
|
+
}
|
|
365
|
+
/** An area name that is a test file name or path, not a product area. */
|
|
366
|
+
function testLike(name) {
|
|
367
|
+
return /\.(?:test|spec)\b|\/|(?:^|[_-])(?:test|spec)s?(?:[_.-]|$)/i.test(name);
|
|
368
|
+
}
|
|
369
|
+
/** Builds the rule-based answer. Deterministic for the same input and hints. */
|
|
370
|
+
export function mockAnswer(x, ctl) {
|
|
371
|
+
const hints = ctl.hints ?? {};
|
|
372
|
+
const scope = x.scope;
|
|
373
|
+
const areas = x.impactDrafts.map((a) => ({
|
|
374
|
+
id: a.id,
|
|
375
|
+
area: a.area,
|
|
376
|
+
files: a.files.filter((p) => !!fileOf(scope, p)),
|
|
377
|
+
userFlows: a.userFlows.length ? a.userFlows : [`${a.area.toLowerCase()} from the main page`],
|
|
378
|
+
...(a.routes?.length ? { routes: a.routes } : {}),
|
|
379
|
+
confidence: a.confidence,
|
|
380
|
+
}));
|
|
381
|
+
const areaOf = (path) => areas.find((a) => a.files.includes(path));
|
|
382
|
+
const mapped = new Set(areas.flatMap((a) => a.files));
|
|
383
|
+
const unmappedFiles = scope.files
|
|
384
|
+
.filter((f) => (f.class === 'source' || f.class === 'config' || f.class === 'migration') && !mapped.has(f.path))
|
|
385
|
+
.map((f) => f.path);
|
|
386
|
+
const lensNames = new Set(x.lenses.map((l) => l.name));
|
|
387
|
+
const floorOf = (name) => x.lenses.find((l) => l.name === name)?.floor ?? 0;
|
|
388
|
+
const drafts = [];
|
|
389
|
+
const used = new Set();
|
|
390
|
+
const nextId = () => `r${drafts.length + 1}`;
|
|
391
|
+
// Length guards on added lines: `q.length >= 2` hides results for shorter input. Only user text counts:
|
|
392
|
+
// `items.length >= 2` or `password.length > 7` says nothing about a search box.
|
|
393
|
+
for (const f of scope.files) {
|
|
394
|
+
if (f.class !== 'source')
|
|
395
|
+
continue;
|
|
396
|
+
for (const [n, text] of [...f.added.entries()].sort((a, b) => a[0] - b[0])) {
|
|
397
|
+
const code = codeOnly(text, false);
|
|
398
|
+
const m = [...code.matchAll(/\b(\w+)\.length\s*(>=|>)\s*(\d+)/g)].find((g) => holdsUserText(f, g[1]));
|
|
399
|
+
if (!m)
|
|
400
|
+
continue;
|
|
401
|
+
const min = m[2] === '>=' ? Number(m[3]) : Number(m[3]) + 1;
|
|
402
|
+
if (min < 2 || min > 9)
|
|
403
|
+
continue;
|
|
404
|
+
const area = areaOf(f.path);
|
|
405
|
+
const noun = (area && !testLike(area.area) ? area.area : 'input').toLowerCase();
|
|
406
|
+
const span = hunkSpan(f, n);
|
|
407
|
+
const near = x.signals.filter((s) => s.file === f.path && span !== null && s.line >= span[0] && s.line <= span[1] && s.kind !== 'tests_untouched' && !used.has(s.id));
|
|
408
|
+
near.forEach((s) => used.add(s.id));
|
|
409
|
+
const short = min === 2 ? 'a single character' : `fewer than ${min} characters`;
|
|
410
|
+
const fewer = NUMBER_WORDS[min - 1];
|
|
411
|
+
drafts.push({
|
|
412
|
+
risk: {
|
|
413
|
+
id: nextId(),
|
|
414
|
+
title: `${cap(fewer)}-letter ${noun} returns no results`,
|
|
415
|
+
kind: 'ui_state',
|
|
416
|
+
severity: 'high',
|
|
417
|
+
likelihood: 'likely',
|
|
418
|
+
why: `The new guard skips ${noun} when the text has fewer than ${min} characters.`,
|
|
419
|
+
userImpact: `Users who type ${short} see no results and no message.`,
|
|
420
|
+
evidence: [{ file: f.path, line: n }],
|
|
421
|
+
...(area ? { areaId: area.id } : {}),
|
|
422
|
+
signals: near.map((s) => s.id),
|
|
423
|
+
source: null,
|
|
424
|
+
confidence: 0.7,
|
|
425
|
+
},
|
|
426
|
+
text: {
|
|
427
|
+
...GENERIC,
|
|
428
|
+
scenario: `Type ${fewer} letter${min - 1 === 1 ? '' : 's'}, then ${NUMBER_WORDS[min]} letters, in ${noun} and check the result list.`,
|
|
429
|
+
steps: [`Open the page with the ${noun} box`, `Type ${short} and wait one second`, 'Type one more character and wait one second'],
|
|
430
|
+
expected: `Short input shows a hint or results, and ${min} characters show matching results.`,
|
|
431
|
+
},
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
// Security and robustness pass: one risk per question, from its first lead on a changed line.
|
|
436
|
+
const leads = x.security?.findings ?? [];
|
|
437
|
+
const byCheck = new Map();
|
|
438
|
+
for (const s of x.signals) {
|
|
439
|
+
if (used.has(s.id) || !isSecurityCheck(s.kind))
|
|
440
|
+
continue;
|
|
441
|
+
const f = leads.find((l) => l.check === s.kind && l.file === s.file && l.line === s.line);
|
|
442
|
+
if (!f || citableLine(fileOf(scope, s.file), s) === null)
|
|
443
|
+
continue;
|
|
444
|
+
if (!byCheck.has(f.check))
|
|
445
|
+
byCheck.set(f.check, []);
|
|
446
|
+
byCheck.get(f.check).push({ s, f });
|
|
447
|
+
}
|
|
448
|
+
for (const [check, list] of byCheck) {
|
|
449
|
+
const { s, f } = list[0];
|
|
450
|
+
const area = areaOf(s.file);
|
|
451
|
+
list.forEach((l) => used.add(l.s.id));
|
|
452
|
+
const text = securityText(f);
|
|
453
|
+
drafts.push({
|
|
454
|
+
risk: {
|
|
455
|
+
id: nextId(),
|
|
456
|
+
title: text.title,
|
|
457
|
+
kind: checklistItem(check).riskKind,
|
|
458
|
+
severity: text.severity,
|
|
459
|
+
likelihood: 'possible',
|
|
460
|
+
why: text.why,
|
|
461
|
+
userImpact: text.impact,
|
|
462
|
+
evidence: [{ file: s.file, line: s.line }],
|
|
463
|
+
...(area ? { areaId: area.id } : {}),
|
|
464
|
+
signals: list.map((l) => l.s.id),
|
|
465
|
+
source: `security:${check}`,
|
|
466
|
+
confidence: 0.7,
|
|
467
|
+
},
|
|
468
|
+
text,
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
// One risk per signal kind with weight 3 or more.
|
|
472
|
+
const byKind = new Map();
|
|
473
|
+
for (const s of x.signals) {
|
|
474
|
+
if (used.has(s.id) || s.weight < 3 || !RISK_KIND[s.kind])
|
|
475
|
+
continue;
|
|
476
|
+
if (!byKind.has(s.kind))
|
|
477
|
+
byKind.set(s.kind, []);
|
|
478
|
+
byKind.get(s.kind).push(s);
|
|
479
|
+
}
|
|
480
|
+
for (const [kind, list] of byKind) {
|
|
481
|
+
const rk = RISK_KIND[kind];
|
|
482
|
+
const first = list.find((s) => citableLine(fileOf(scope, s.file), s) !== null);
|
|
483
|
+
if (!first)
|
|
484
|
+
continue;
|
|
485
|
+
const line = citableLine(fileOf(scope, first.file), first, rk);
|
|
486
|
+
const text = TEXT[rk] ?? GENERIC;
|
|
487
|
+
const lens = (first.lens ?? '').split(',').find((l) => lensNames.has(l));
|
|
488
|
+
const area = areaOf(first.file);
|
|
489
|
+
list.forEach((s) => used.add(s.id));
|
|
490
|
+
drafts.push({
|
|
491
|
+
risk: {
|
|
492
|
+
id: nextId(),
|
|
493
|
+
title: text.title,
|
|
494
|
+
kind: rk,
|
|
495
|
+
severity: text.severity,
|
|
496
|
+
likelihood: 'possible',
|
|
497
|
+
why: text.why,
|
|
498
|
+
userImpact: text.impact,
|
|
499
|
+
evidence: [{ file: first.file, line }],
|
|
500
|
+
...(area ? { areaId: area.id } : {}),
|
|
501
|
+
signals: list.map((s) => s.id),
|
|
502
|
+
source: lens ? `lens:${lens}` : null,
|
|
503
|
+
confidence: Math.max(0.7, lens ? floorOf(lens) : 0),
|
|
504
|
+
},
|
|
505
|
+
text,
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
const risks = drafts.map((d) => d.risk);
|
|
509
|
+
// Every other shown signal is dropped with its own line as evidence.
|
|
510
|
+
const dropped = [];
|
|
511
|
+
for (const s of x.signals) {
|
|
512
|
+
if (used.has(s.id))
|
|
513
|
+
continue;
|
|
514
|
+
const line = citableLine(fileOf(scope, s.file), s) ?? s.line;
|
|
515
|
+
dropped.push({
|
|
516
|
+
signal: s.id,
|
|
517
|
+
reason: s.kind === 'tests_untouched'
|
|
518
|
+
? 'Rule-based review: a missing test is a gap to plan, not a risk by itself.'
|
|
519
|
+
: `Rule-based review: weight ${s.weight} is below the risk threshold of 3.`,
|
|
520
|
+
evidence: { file: s.file, line },
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
// What to test: linked specs (or a smoke spec), then one new scenario per risk.
|
|
524
|
+
const testPaths = new Set(x.tests.map((t) => t.path));
|
|
525
|
+
const whatToTest = [];
|
|
526
|
+
const tid = () => `t${whatToTest.length + 1}`;
|
|
527
|
+
const fallbackArea = areas[0]?.id;
|
|
528
|
+
for (const a of areas) {
|
|
529
|
+
const risksHere = risks.filter((r) => r.areaId === a.id).map((r) => r.id);
|
|
530
|
+
const linked = (hints.specsByArea?.[a.id] ?? []).filter((p) => testPaths.has(p)).slice(0, 2);
|
|
531
|
+
for (const p of linked)
|
|
532
|
+
whatToTest.push({
|
|
533
|
+
id: tid(),
|
|
534
|
+
scenario: `Run the linked spec for ${a.area}.`,
|
|
535
|
+
type: 'e2e',
|
|
536
|
+
priority: 'should',
|
|
537
|
+
areaId: a.id,
|
|
538
|
+
riskIds: risksHere,
|
|
539
|
+
existingTest: p,
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
if (!whatToTest.length && fallbackArea) {
|
|
543
|
+
const smoke = (hints.smokeSpecs ?? []).find((p) => testPaths.has(p)) ?? x.tests[0]?.path;
|
|
544
|
+
if (smoke)
|
|
545
|
+
whatToTest.push({
|
|
546
|
+
id: tid(),
|
|
547
|
+
scenario: 'Run the smoke spec to confirm the app still loads.',
|
|
548
|
+
type: 'e2e',
|
|
549
|
+
priority: 'should',
|
|
550
|
+
areaId: fallbackArea,
|
|
551
|
+
riskIds: [],
|
|
552
|
+
existingTest: smoke,
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
const backendOnly = isBackendOnly(x.scope, x.impactDrafts);
|
|
556
|
+
for (const d of drafts) {
|
|
557
|
+
const areaId = d.risk.areaId ?? fallbackArea;
|
|
558
|
+
if (!areaId)
|
|
559
|
+
continue;
|
|
560
|
+
let how = {
|
|
561
|
+
steps: d.text.steps,
|
|
562
|
+
expected: d.text.expected,
|
|
563
|
+
data: 'Seed data that the changed flow lists or computes.',
|
|
564
|
+
};
|
|
565
|
+
// A change with no screen has no screen steps (KAT-385). What is left of the template stays; a check with no step left has none.
|
|
566
|
+
if (backendOnly) {
|
|
567
|
+
how = dropScreenSteps(how).item;
|
|
568
|
+
if (how.steps?.length && !how.expected)
|
|
569
|
+
how.expected = 'The call answers as the change intends, with no error.';
|
|
570
|
+
}
|
|
571
|
+
whatToTest.push({
|
|
572
|
+
id: tid(),
|
|
573
|
+
scenario: d.text.scenario,
|
|
574
|
+
type: 'e2e',
|
|
575
|
+
priority: d.risk.severity === 'critical' || d.risk.severity === 'high' ? 'must' : 'should',
|
|
576
|
+
areaId,
|
|
577
|
+
riskIds: [d.risk.id],
|
|
578
|
+
...how,
|
|
579
|
+
});
|
|
580
|
+
}
|
|
581
|
+
const testsAtRisk = [];
|
|
582
|
+
for (const k of hints.testsAtRiskDrafts ?? []) {
|
|
583
|
+
const f = fileOf(scope, k.evidence.file);
|
|
584
|
+
if (!f || !isCitable(f, k.evidence.line) || testsAtRisk.length >= 10)
|
|
585
|
+
continue;
|
|
586
|
+
testsAtRisk.push({
|
|
587
|
+
id: `k${testsAtRisk.length + 1}`,
|
|
588
|
+
path: k.path,
|
|
589
|
+
reason: `The test uses "${clipWords(k.value, 6)}", which the change removed or renamed.`,
|
|
590
|
+
evidence: { file: k.evidence.file, line: k.evidence.line },
|
|
591
|
+
testLine: k.testLine,
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
const testGaps = [];
|
|
595
|
+
for (const a of areas) {
|
|
596
|
+
const risksHere = risks.filter((r) => r.areaId === a.id).map((r) => r.id);
|
|
597
|
+
if (!risksHere.length || (hints.specsByArea?.[a.id] ?? []).length)
|
|
598
|
+
continue;
|
|
599
|
+
testGaps.push({
|
|
600
|
+
id: `g${testGaps.length + 1}`,
|
|
601
|
+
areaId: a.id,
|
|
602
|
+
missing: `No listed test covers the ${a.area} flow that the change touches.`,
|
|
603
|
+
type: 'e2e',
|
|
604
|
+
riskIds: risksHere,
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
const areaIds = new Set(areas.map((a) => a.id));
|
|
608
|
+
const hint = hints.scopeHint ?? {
|
|
609
|
+
level: areas.length ? 'area' : 'narrow',
|
|
610
|
+
areaIds: areas.map((a) => a.id),
|
|
611
|
+
reason: 'the change stays in its impact areas.',
|
|
612
|
+
};
|
|
613
|
+
const regressionScope = { level: hint.level, areaIds: hint.areaIds.filter((id) => areaIds.has(id)), reason: cap(hint.reason.replace(/\.?$/, '.')) };
|
|
614
|
+
const answer = groundRisks({
|
|
615
|
+
summary: '',
|
|
616
|
+
impactAreas: areas,
|
|
617
|
+
unmappedFiles,
|
|
618
|
+
risks,
|
|
619
|
+
whatToTest,
|
|
620
|
+
testsAtRisk,
|
|
621
|
+
testGaps,
|
|
622
|
+
regressionScope,
|
|
623
|
+
releaseNotesImpact: placeholderNotes(),
|
|
624
|
+
dropped,
|
|
625
|
+
}, scope, x.signals);
|
|
626
|
+
return describe(answer, x, scope);
|
|
627
|
+
}
|
|
628
|
+
function placeholderNotes() {
|
|
629
|
+
return { userVisible: false, note: null, audience: 'none', breaking: false };
|
|
630
|
+
}
|
|
631
|
+
/** Product areas for the summary: not test files, at most three names, then a count of the rest. */
|
|
632
|
+
function areaPhrase(areas, scope) {
|
|
633
|
+
const product = areas.filter((a) => {
|
|
634
|
+
if (testLike(a.area))
|
|
635
|
+
return false;
|
|
636
|
+
return a.files.some((p) => fileOf(scope, p)?.class !== 'test');
|
|
637
|
+
});
|
|
638
|
+
const names = [...new Set(product.map((a) => a.area))];
|
|
639
|
+
if (!names.length)
|
|
640
|
+
return 'no mapped area';
|
|
641
|
+
const shown = names.slice(0, 3);
|
|
642
|
+
const rest = names.length - shown.length;
|
|
643
|
+
if (rest > 0)
|
|
644
|
+
return `${shown.join(', ')} and ${rest} more area${rest === 1 ? '' : 's'}`;
|
|
645
|
+
return shown.length > 1 ? `${shown.slice(0, -1).join(', ')} and ${shown[shown.length - 1]}` : shown[0];
|
|
646
|
+
}
|
|
647
|
+
/** The summary and the release note, written after grounding so they describe only the risks that stayed. */
|
|
648
|
+
function describe(a, x, scope) {
|
|
649
|
+
const uiFile = scope.files.some((f) => f.class === 'source' && /\.(tsx|jsx|vue|svelte|html|css)$/.test(f.path));
|
|
650
|
+
const title = clipWords(x.event?.title ?? '', 18).replace(/[.!?]*$/, '');
|
|
651
|
+
const userVisible = uiFile || a.risks.length > 0;
|
|
652
|
+
const releaseNotesImpact = {
|
|
653
|
+
userVisible,
|
|
654
|
+
note: userVisible && title ? `${title}.` : null,
|
|
655
|
+
audience: userVisible ? 'end_users' : 'none',
|
|
656
|
+
breaking: false,
|
|
657
|
+
};
|
|
658
|
+
const lead = title ? `${title}.` : 'This change has no title.';
|
|
659
|
+
const summary = a.risks.length
|
|
660
|
+
? `${lead} It touches ${areaPhrase(a.impactAreas, scope)}; test ${a.risks[0].title.toLowerCase()} first.`
|
|
661
|
+
: `${lead} No rule-based risk fired; run the linked tests.`;
|
|
662
|
+
return { ...a, summary, releaseNotesImpact };
|
|
663
|
+
}
|
|
664
|
+
export class MockQaBackend {
|
|
665
|
+
name = 'mock';
|
|
666
|
+
qaReview(input, ctl) {
|
|
667
|
+
const answer = mockAnswer(input, ctl);
|
|
668
|
+
return converse({
|
|
669
|
+
role: 'reviewer',
|
|
670
|
+
backend: this.name,
|
|
671
|
+
model: 'rules',
|
|
672
|
+
check: ctl.check,
|
|
673
|
+
first: async () => {
|
|
674
|
+
// The rule-based answer reads every changed line from the scope.
|
|
675
|
+
ctl.delivery?.markFiles(input.scope.files.map((f) => f.path));
|
|
676
|
+
return { raw: answer };
|
|
677
|
+
},
|
|
678
|
+
correct: async () => ({ raw: answer }),
|
|
679
|
+
maxCorrections: 0,
|
|
680
|
+
});
|
|
681
|
+
}
|
|
682
|
+
async qaVerify(_input, _claims) {
|
|
683
|
+
return { role: 'verifier', backend: this.name, model: 'rules', answer: null, ok: false, rounds: 0, errors: [], durationMs: 0, skipped: true };
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
//# sourceMappingURL=backend-mock.js.map
|