@reticlehq/server 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +105 -0
- package/README.md +17 -0
- package/dist/bridge-security.d.ts +23 -0
- package/dist/bridge-security.d.ts.map +1 -0
- package/dist/bridge-security.js +44 -0
- package/dist/bridge-security.js.map +1 -0
- package/dist/bridge.d.ts +42 -0
- package/dist/bridge.d.ts.map +1 -0
- package/dist/bridge.js +281 -0
- package/dist/bridge.js.map +1 -0
- package/dist/bridge.test-harness.d.ts +42 -0
- package/dist/bridge.test-harness.d.ts.map +1 -0
- package/dist/bridge.test-harness.js +192 -0
- package/dist/bridge.test-harness.js.map +1 -0
- package/dist/cli-launch.d.ts +53 -0
- package/dist/cli-launch.d.ts.map +1 -0
- package/dist/cli-launch.js +109 -0
- package/dist/cli-launch.js.map +1 -0
- package/dist/cli-parse.d.ts +74 -0
- package/dist/cli-parse.d.ts.map +1 -0
- package/dist/cli-parse.js +321 -0
- package/dist/cli-parse.js.map +1 -0
- package/dist/cli-port.d.ts +26 -0
- package/dist/cli-port.d.ts.map +1 -0
- package/dist/cli-port.js +57 -0
- package/dist/cli-port.js.map +1 -0
- package/dist/cli-verify.d.ts +46 -0
- package/dist/cli-verify.d.ts.map +1 -0
- package/dist/cli-verify.js +181 -0
- package/dist/cli-verify.js.map +1 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +337 -0
- package/dist/cli.js.map +1 -0
- package/dist/cloud/cloud-sync.d.ts +50 -0
- package/dist/cloud/cloud-sync.d.ts.map +1 -0
- package/dist/cloud/cloud-sync.js +47 -0
- package/dist/cloud/cloud-sync.js.map +1 -0
- package/dist/crawl/crawl-tools.d.ts +8 -0
- package/dist/crawl/crawl-tools.d.ts.map +1 -0
- package/dist/crawl/crawl-tools.js +61 -0
- package/dist/crawl/crawl-tools.js.map +1 -0
- package/dist/crawl/crawl.d.ts +45 -0
- package/dist/crawl/crawl.d.ts.map +1 -0
- package/dist/crawl/crawl.js +106 -0
- package/dist/crawl/crawl.js.map +1 -0
- package/dist/daemon-resilience.d.ts +17 -0
- package/dist/daemon-resilience.d.ts.map +1 -0
- package/dist/daemon-resilience.js +23 -0
- package/dist/daemon-resilience.js.map +1 -0
- package/dist/daemon.d.ts +26 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +122 -0
- package/dist/daemon.js.map +1 -0
- package/dist/domain/domain-model.d.ts +64 -0
- package/dist/domain/domain-model.d.ts.map +1 -0
- package/dist/domain/domain-model.js +127 -0
- package/dist/domain/domain-model.js.map +1 -0
- package/dist/domain/domain-tools.d.ts +9 -0
- package/dist/domain/domain-tools.d.ts.map +1 -0
- package/dist/domain/domain-tools.js +66 -0
- package/dist/domain/domain-tools.js.map +1 -0
- package/dist/domain/flow-risk.d.ts +34 -0
- package/dist/domain/flow-risk.d.ts.map +1 -0
- package/dist/domain/flow-risk.js +81 -0
- package/dist/domain/flow-risk.js.map +1 -0
- package/dist/ee/audit-log.d.ts +15 -0
- package/dist/ee/audit-log.d.ts.map +1 -0
- package/dist/ee/audit-log.js +12 -0
- package/dist/ee/audit-log.js.map +1 -0
- package/dist/events/event-filters.d.ts +65 -0
- package/dist/events/event-filters.d.ts.map +1 -0
- package/dist/events/event-filters.js +98 -0
- package/dist/events/event-filters.js.map +1 -0
- package/dist/events/predicate-eval.d.ts +91 -0
- package/dist/events/predicate-eval.d.ts.map +1 -0
- package/dist/events/predicate-eval.js +299 -0
- package/dist/events/predicate-eval.js.map +1 -0
- package/dist/events/predicate.d.ts +19 -0
- package/dist/events/predicate.d.ts.map +1 -0
- package/dist/events/predicate.js +188 -0
- package/dist/events/predicate.js.map +1 -0
- package/dist/events/reaction.d.ts +34 -0
- package/dist/events/reaction.d.ts.map +1 -0
- package/dist/events/reaction.js +60 -0
- package/dist/events/reaction.js.map +1 -0
- package/dist/events/ring-buffer.d.ts +32 -0
- package/dist/events/ring-buffer.d.ts.map +1 -0
- package/dist/events/ring-buffer.js +75 -0
- package/dist/events/ring-buffer.js.map +1 -0
- package/dist/flows/annotate-tools.d.ts +16 -0
- package/dist/flows/annotate-tools.d.ts.map +1 -0
- package/dist/flows/annotate-tools.js +136 -0
- package/dist/flows/annotate-tools.js.map +1 -0
- package/dist/flows/annotate.d.ts +22 -0
- package/dist/flows/annotate.d.ts.map +1 -0
- package/dist/flows/annotate.js +134 -0
- package/dist/flows/annotate.js.map +1 -0
- package/dist/flows/annotation-store.d.ts +23 -0
- package/dist/flows/annotation-store.d.ts.map +1 -0
- package/dist/flows/annotation-store.js +51 -0
- package/dist/flows/annotation-store.js.map +1 -0
- package/dist/flows/decision.d.ts +13 -0
- package/dist/flows/decision.d.ts.map +1 -0
- package/dist/flows/decision.js +111 -0
- package/dist/flows/decision.js.map +1 -0
- package/dist/flows/flow-classify.d.ts +52 -0
- package/dist/flows/flow-classify.d.ts.map +1 -0
- package/dist/flows/flow-classify.js +99 -0
- package/dist/flows/flow-classify.js.map +1 -0
- package/dist/flows/flow-replay-run.d.ts +15 -0
- package/dist/flows/flow-replay-run.d.ts.map +1 -0
- package/dist/flows/flow-replay-run.js +120 -0
- package/dist/flows/flow-replay-run.js.map +1 -0
- package/dist/flows/flow-replay.d.ts +49 -0
- package/dist/flows/flow-replay.d.ts.map +1 -0
- package/dist/flows/flow-replay.js +391 -0
- package/dist/flows/flow-replay.js.map +1 -0
- package/dist/flows/flow-report.d.ts +23 -0
- package/dist/flows/flow-report.d.ts.map +1 -0
- package/dist/flows/flow-report.js +106 -0
- package/dist/flows/flow-report.js.map +1 -0
- package/dist/flows/flow-scope.d.ts +25 -0
- package/dist/flows/flow-scope.d.ts.map +1 -0
- package/dist/flows/flow-scope.js +32 -0
- package/dist/flows/flow-scope.js.map +1 -0
- package/dist/flows/flow-success.d.ts +33 -0
- package/dist/flows/flow-success.d.ts.map +1 -0
- package/dist/flows/flow-success.js +131 -0
- package/dist/flows/flow-success.js.map +1 -0
- package/dist/flows/flow-tools.d.ts +4 -0
- package/dist/flows/flow-tools.d.ts.map +1 -0
- package/dist/flows/flow-tools.js +460 -0
- package/dist/flows/flow-tools.js.map +1 -0
- package/dist/flows/flows.d.ts +86 -0
- package/dist/flows/flows.d.ts.map +1 -0
- package/dist/flows/flows.js +319 -0
- package/dist/flows/flows.js.map +1 -0
- package/dist/flows/heal.d.ts +43 -0
- package/dist/flows/heal.d.ts.map +1 -0
- package/dist/flows/heal.js +98 -0
- package/dist/flows/heal.js.map +1 -0
- package/dist/flows/recordings.d.ts +46 -0
- package/dist/flows/recordings.d.ts.map +1 -0
- package/dist/flows/recordings.js +43 -0
- package/dist/flows/recordings.js.map +1 -0
- package/dist/flows/replay.d.ts +23 -0
- package/dist/flows/replay.d.ts.map +1 -0
- package/dist/flows/replay.js +160 -0
- package/dist/flows/replay.js.map +1 -0
- package/dist/http-server.d.ts +39 -0
- package/dist/http-server.d.ts.map +1 -0
- package/dist/http-server.js +145 -0
- package/dist/http-server.js.map +1 -0
- package/dist/idle-shutdown.d.ts +34 -0
- package/dist/idle-shutdown.d.ts.map +1 -0
- package/dist/idle-shutdown.js +68 -0
- package/dist/idle-shutdown.js.map +1 -0
- package/dist/index.d.ts +135 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +371 -0
- package/dist/index.js.map +1 -0
- package/dist/init/cursor.d.ts +25 -0
- package/dist/init/cursor.d.ts.map +1 -0
- package/dist/init/cursor.js +49 -0
- package/dist/init/cursor.js.map +1 -0
- package/dist/init/detect.d.ts +49 -0
- package/dist/init/detect.d.ts.map +1 -0
- package/dist/init/detect.js +84 -0
- package/dist/init/detect.js.map +1 -0
- package/dist/init/mcp.d.ts +40 -0
- package/dist/init/mcp.d.ts.map +1 -0
- package/dist/init/mcp.js +55 -0
- package/dist/init/mcp.js.map +1 -0
- package/dist/init/node-io.d.ts +8 -0
- package/dist/init/node-io.d.ts.map +1 -0
- package/dist/init/node-io.js +57 -0
- package/dist/init/node-io.js.map +1 -0
- package/dist/init/plan.d.ts +72 -0
- package/dist/init/plan.d.ts.map +1 -0
- package/dist/init/plan.js +280 -0
- package/dist/init/plan.js.map +1 -0
- package/dist/init/project-id.d.ts +17 -0
- package/dist/init/project-id.d.ts.map +1 -0
- package/dist/init/project-id.js +38 -0
- package/dist/init/project-id.js.map +1 -0
- package/dist/init/run.d.ts +42 -0
- package/dist/init/run.d.ts.map +1 -0
- package/dist/init/run.js +171 -0
- package/dist/init/run.js.map +1 -0
- package/dist/init/snippets.d.ts +33 -0
- package/dist/init/snippets.d.ts.map +1 -0
- package/dist/init/snippets.js +117 -0
- package/dist/init/snippets.js.map +1 -0
- package/dist/init/vite-config.d.ts +25 -0
- package/dist/init/vite-config.d.ts.map +1 -0
- package/dist/init/vite-config.js +45 -0
- package/dist/init/vite-config.js.map +1 -0
- package/dist/input/network-mock-tools.d.ts +3 -0
- package/dist/input/network-mock-tools.d.ts.map +1 -0
- package/dist/input/network-mock-tools.js +94 -0
- package/dist/input/network-mock-tools.js.map +1 -0
- package/dist/input/network-mock.d.ts +55 -0
- package/dist/input/network-mock.d.ts.map +1 -0
- package/dist/input/network-mock.js +62 -0
- package/dist/input/network-mock.js.map +1 -0
- package/dist/input/real-input.d.ts +174 -0
- package/dist/input/real-input.d.ts.map +1 -0
- package/dist/input/real-input.js +289 -0
- package/dist/input/real-input.js.map +1 -0
- package/dist/input/scroll-find.d.ts +41 -0
- package/dist/input/scroll-find.d.ts.map +1 -0
- package/dist/input/scroll-find.js +59 -0
- package/dist/input/scroll-find.js.map +1 -0
- package/dist/input/scroll-tools.d.ts +8 -0
- package/dist/input/scroll-tools.d.ts.map +1 -0
- package/dist/input/scroll-tools.js +68 -0
- package/dist/input/scroll-tools.js.map +1 -0
- package/dist/input/viewport-tools.d.ts +3 -0
- package/dist/input/viewport-tools.d.ts.map +1 -0
- package/dist/input/viewport-tools.js +65 -0
- package/dist/input/viewport-tools.js.map +1 -0
- package/dist/license/license.d.ts +108 -0
- package/dist/license/license.d.ts.map +1 -0
- package/dist/license/license.js +203 -0
- package/dist/license/license.js.map +1 -0
- package/dist/log.d.ts +6 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +9 -0
- package/dist/log.js.map +1 -0
- package/dist/mcp-proxy.d.ts +16 -0
- package/dist/mcp-proxy.d.ts.map +1 -0
- package/dist/mcp-proxy.js +168 -0
- package/dist/mcp-proxy.js.map +1 -0
- package/dist/mcp.d.ts +14 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +101 -0
- package/dist/mcp.js.map +1 -0
- package/dist/pairing-token.d.ts +28 -0
- package/dist/pairing-token.d.ts.map +1 -0
- package/dist/pairing-token.js +62 -0
- package/dist/pairing-token.js.map +1 -0
- package/dist/pool/browser-pool.d.ts +90 -0
- package/dist/pool/browser-pool.d.ts.map +1 -0
- package/dist/pool/browser-pool.js +221 -0
- package/dist/pool/browser-pool.js.map +1 -0
- package/dist/pool/lease-reaper.d.ts +16 -0
- package/dist/pool/lease-reaper.d.ts.map +1 -0
- package/dist/pool/lease-reaper.js +41 -0
- package/dist/pool/lease-reaper.js.map +1 -0
- package/dist/pool/playwright-launcher.d.ts +19 -0
- package/dist/pool/playwright-launcher.d.ts.map +1 -0
- package/dist/pool/playwright-launcher.js +51 -0
- package/dist/pool/playwright-launcher.js.map +1 -0
- package/dist/project/baselines.d.ts +22 -0
- package/dist/project/baselines.d.ts.map +1 -0
- package/dist/project/baselines.js +45 -0
- package/dist/project/baselines.js.map +1 -0
- package/dist/project/fs-port.d.ts +27 -0
- package/dist/project/fs-port.d.ts.map +1 -0
- package/dist/project/fs-port.js +32 -0
- package/dist/project/fs-port.js.map +1 -0
- package/dist/project/project-store.d.ts +32 -0
- package/dist/project/project-store.d.ts.map +1 -0
- package/dist/project/project-store.js +127 -0
- package/dist/project/project-store.js.map +1 -0
- package/dist/project/project-tools.d.ts +9 -0
- package/dist/project/project-tools.d.ts.map +1 -0
- package/dist/project/project-tools.js +118 -0
- package/dist/project/project-tools.js.map +1 -0
- package/dist/project/reticle-dir.d.ts +61 -0
- package/dist/project/reticle-dir.d.ts.map +1 -0
- package/dist/project/reticle-dir.js +144 -0
- package/dist/project/reticle-dir.js.map +1 -0
- package/dist/runs/build-verification-run.d.ts +30 -0
- package/dist/runs/build-verification-run.d.ts.map +1 -0
- package/dist/runs/build-verification-run.js +71 -0
- package/dist/runs/build-verification-run.js.map +1 -0
- package/dist/runs/profile-redact.d.ts +16 -0
- package/dist/runs/profile-redact.d.ts.map +1 -0
- package/dist/runs/profile-redact.js +32 -0
- package/dist/runs/profile-redact.js.map +1 -0
- package/dist/runs/render-report.d.ts +9 -0
- package/dist/runs/render-report.d.ts.map +1 -0
- package/dist/runs/render-report.js +70 -0
- package/dist/runs/render-report.js.map +1 -0
- package/dist/runs/repair-prompt.d.ts +15 -0
- package/dist/runs/repair-prompt.d.ts.map +1 -0
- package/dist/runs/repair-prompt.js +59 -0
- package/dist/runs/repair-prompt.js.map +1 -0
- package/dist/runs/replay-mapping.d.ts +12 -0
- package/dist/runs/replay-mapping.d.ts.map +1 -0
- package/dist/runs/replay-mapping.js +35 -0
- package/dist/runs/replay-mapping.js.map +1 -0
- package/dist/runs/reticle-runner.d.ts +48 -0
- package/dist/runs/reticle-runner.d.ts.map +1 -0
- package/dist/runs/reticle-runner.js +56 -0
- package/dist/runs/reticle-runner.js.map +1 -0
- package/dist/runs/risk-classify.d.ts +27 -0
- package/dist/runs/risk-classify.d.ts.map +1 -0
- package/dist/runs/risk-classify.js +76 -0
- package/dist/runs/risk-classify.js.map +1 -0
- package/dist/runs/run-store.d.ts +40 -0
- package/dist/runs/run-store.d.ts.map +1 -0
- package/dist/runs/run-store.js +118 -0
- package/dist/runs/run-store.js.map +1 -0
- package/dist/runs/run-tools.d.ts +10 -0
- package/dist/runs/run-tools.d.ts.map +1 -0
- package/dist/runs/run-tools.js +69 -0
- package/dist/runs/run-tools.js.map +1 -0
- package/dist/runs/runner-port.d.ts +14 -0
- package/dist/runs/runner-port.d.ts.map +1 -0
- package/dist/runs/runner-port.js +23 -0
- package/dist/runs/runner-port.js.map +1 -0
- package/dist/runs/verify-http.d.ts +34 -0
- package/dist/runs/verify-http.d.ts.map +1 -0
- package/dist/runs/verify-http.js +102 -0
- package/dist/runs/verify-http.js.map +1 -0
- package/dist/runs/verify-server.d.ts +26 -0
- package/dist/runs/verify-server.d.ts.map +1 -0
- package/dist/runs/verify-server.js +99 -0
- package/dist/runs/verify-server.js.map +1 -0
- package/dist/server-version.d.ts +3 -0
- package/dist/server-version.d.ts.map +1 -0
- package/dist/server-version.js +5 -0
- package/dist/server-version.js.map +1 -0
- package/dist/session/control-envelope.d.ts +49 -0
- package/dist/session/control-envelope.d.ts.map +1 -0
- package/dist/session/control-envelope.js +44 -0
- package/dist/session/control-envelope.js.map +1 -0
- package/dist/session/live-control-tools.d.ts +16 -0
- package/dist/session/live-control-tools.d.ts.map +1 -0
- package/dist/session/live-control-tools.js +204 -0
- package/dist/session/live-control-tools.js.map +1 -0
- package/dist/session/output-budget.d.ts +41 -0
- package/dist/session/output-budget.d.ts.map +1 -0
- package/dist/session/output-budget.js +54 -0
- package/dist/session/output-budget.js.map +1 -0
- package/dist/session/presenter-args.d.ts +8 -0
- package/dist/session/presenter-args.d.ts.map +1 -0
- package/dist/session/presenter-args.js +15 -0
- package/dist/session/presenter-args.js.map +1 -0
- package/dist/session/review-store.d.ts +40 -0
- package/dist/session/review-store.d.ts.map +1 -0
- package/dist/session/review-store.js +61 -0
- package/dist/session/review-store.js.map +1 -0
- package/dist/session/session-health.d.ts +22 -0
- package/dist/session/session-health.d.ts.map +1 -0
- package/dist/session/session-health.js +26 -0
- package/dist/session/session-health.js.map +1 -0
- package/dist/session/session-manager.d.ts +43 -0
- package/dist/session/session-manager.d.ts.map +1 -0
- package/dist/session/session-manager.js +155 -0
- package/dist/session/session-manager.js.map +1 -0
- package/dist/session/session-readiness.d.ts +35 -0
- package/dist/session/session-readiness.d.ts.map +1 -0
- package/dist/session/session-readiness.js +32 -0
- package/dist/session/session-readiness.js.map +1 -0
- package/dist/session/session-reaper.d.ts +37 -0
- package/dist/session/session-reaper.d.ts.map +1 -0
- package/dist/session/session-reaper.js +94 -0
- package/dist/session/session-reaper.js.map +1 -0
- package/dist/session/session-recommendation.d.ts +18 -0
- package/dist/session/session-recommendation.d.ts.map +1 -0
- package/dist/session/session-recommendation.js +14 -0
- package/dist/session/session-recommendation.js.map +1 -0
- package/dist/session/session-tools.d.ts +9 -0
- package/dist/session/session-tools.d.ts.map +1 -0
- package/dist/session/session-tools.js +43 -0
- package/dist/session/session-tools.js.map +1 -0
- package/dist/session/session.d.ts +166 -0
- package/dist/session/session.d.ts.map +1 -0
- package/dist/session/session.js +408 -0
- package/dist/session/session.js.map +1 -0
- package/dist/session/state-select.d.ts +8 -0
- package/dist/session/state-select.d.ts.map +1 -0
- package/dist/session/state-select.js +8 -0
- package/dist/session/state-select.js.map +1 -0
- package/dist/token-auth.d.ts +24 -0
- package/dist/token-auth.d.ts.map +1 -0
- package/dist/token-auth.js +71 -0
- package/dist/token-auth.js.map +1 -0
- package/dist/tools/act-tools.d.ts +3 -0
- package/dist/tools/act-tools.d.ts.map +1 -0
- package/dist/tools/act-tools.js +327 -0
- package/dist/tools/act-tools.js.map +1 -0
- package/dist/tools/act-view.d.ts +19 -0
- package/dist/tools/act-view.d.ts.map +1 -0
- package/dist/tools/act-view.js +46 -0
- package/dist/tools/act-view.js.map +1 -0
- package/dist/tools/assert-grade.d.ts +21 -0
- package/dist/tools/assert-grade.d.ts.map +1 -0
- package/dist/tools/assert-grade.js +52 -0
- package/dist/tools/assert-grade.js.map +1 -0
- package/dist/tools/browser-tools.d.ts +3 -0
- package/dist/tools/browser-tools.d.ts.map +1 -0
- package/dist/tools/browser-tools.js +52 -0
- package/dist/tools/browser-tools.js.map +1 -0
- package/dist/tools/contract-tools.d.ts +8 -0
- package/dist/tools/contract-tools.d.ts.map +1 -0
- package/dist/tools/contract-tools.js +62 -0
- package/dist/tools/contract-tools.js.map +1 -0
- package/dist/tools/dynamic-tools.d.ts +7 -0
- package/dist/tools/dynamic-tools.d.ts.map +1 -0
- package/dist/tools/dynamic-tools.js +103 -0
- package/dist/tools/dynamic-tools.js.map +1 -0
- package/dist/tools/error-recovery.d.ts +31 -0
- package/dist/tools/error-recovery.d.ts.map +1 -0
- package/dist/tools/error-recovery.js +52 -0
- package/dist/tools/error-recovery.js.map +1 -0
- package/dist/tools/invoke-tool.d.ts +23 -0
- package/dist/tools/invoke-tool.d.ts.map +1 -0
- package/dist/tools/invoke-tool.js +99 -0
- package/dist/tools/invoke-tool.js.map +1 -0
- package/dist/tools/lease-tools.d.ts +31 -0
- package/dist/tools/lease-tools.d.ts.map +1 -0
- package/dist/tools/lease-tools.js +164 -0
- package/dist/tools/lease-tools.js.map +1 -0
- package/dist/tools/observe-tools.d.ts +3 -0
- package/dist/tools/observe-tools.d.ts.map +1 -0
- package/dist/tools/observe-tools.js +259 -0
- package/dist/tools/observe-tools.js.map +1 -0
- package/dist/tools/profiles.d.ts +33 -0
- package/dist/tools/profiles.d.ts.map +1 -0
- package/dist/tools/profiles.js +105 -0
- package/dist/tools/profiles.js.map +1 -0
- package/dist/tools/query-paginate.d.ts +15 -0
- package/dist/tools/query-paginate.d.ts.map +1 -0
- package/dist/tools/query-paginate.js +31 -0
- package/dist/tools/query-paginate.js.map +1 -0
- package/dist/tools/read-tools.d.ts +3 -0
- package/dist/tools/read-tools.d.ts.map +1 -0
- package/dist/tools/read-tools.js +329 -0
- package/dist/tools/read-tools.js.map +1 -0
- package/dist/tools/snapshot-delta.d.ts +59 -0
- package/dist/tools/snapshot-delta.d.ts.map +1 -0
- package/dist/tools/snapshot-delta.js +0 -0
- package/dist/tools/snapshot-delta.js.map +1 -0
- package/dist/tools/tool-invoker.d.ts +15 -0
- package/dist/tools/tool-invoker.d.ts.map +1 -0
- package/dist/tools/tool-invoker.js +20 -0
- package/dist/tools/tool-invoker.js.map +1 -0
- package/dist/tools/tool-kit.d.ts +60 -0
- package/dist/tools/tool-kit.d.ts.map +1 -0
- package/dist/tools/tool-kit.js +33 -0
- package/dist/tools/tool-kit.js.map +1 -0
- package/dist/tools/tool-names.d.ts +89 -0
- package/dist/tools/tool-names.d.ts.map +1 -0
- package/dist/tools/tool-names.js +88 -0
- package/dist/tools/tool-names.js.map +1 -0
- package/dist/tools/tools-helpers.d.ts +12 -0
- package/dist/tools/tools-helpers.d.ts.map +1 -0
- package/dist/tools/tools-helpers.js +22 -0
- package/dist/tools/tools-helpers.js.map +1 -0
- package/dist/tools/tools.d.ts +4 -0
- package/dist/tools/tools.d.ts.map +1 -0
- package/dist/tools/tools.js +268 -0
- package/dist/tools/tools.js.map +1 -0
- package/dist/update/update-checker.d.ts +20 -0
- package/dist/update/update-checker.d.ts.map +1 -0
- package/dist/update/update-checker.js +94 -0
- package/dist/update/update-checker.js.map +1 -0
- package/dist/update/update-tools.d.ts +3 -0
- package/dist/update/update-tools.d.ts.map +1 -0
- package/dist/update/update-tools.js +94 -0
- package/dist/update/update-tools.js.map +1 -0
- package/dist/update/updater.d.ts +31 -0
- package/dist/update/updater.d.ts.map +1 -0
- package/dist/update/updater.js +120 -0
- package/dist/update/updater.js.map +1 -0
- package/dist/visual/visual-diff.d.ts +46 -0
- package/dist/visual/visual-diff.d.ts.map +1 -0
- package/dist/visual/visual-diff.js +100 -0
- package/dist/visual/visual-diff.js.map +1 -0
- package/dist/visual/visual-store.d.ts +22 -0
- package/dist/visual/visual-store.d.ts.map +1 -0
- package/dist/visual/visual-store.js +60 -0
- package/dist/visual/visual-store.js.map +1 -0
- package/dist/visual/visual-tools.d.ts +9 -0
- package/dist/visual/visual-tools.d.ts.map +1 -0
- package/dist/visual/visual-tools.js +182 -0
- package/dist/visual/visual-tools.js.map +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { ActionType, CRAWL_DEFAULTS, CrawlAnomalyKind, DANGEROUS_ACTION_CONFIRM_ARG, EventType, ReticleCommand, } from '@reticlehq/core';
|
|
2
|
+
import { parseInteractive, asRecord, asNumber, asString } from '../tools/tools-helpers.js';
|
|
3
|
+
/** Any buffer event that proves the app reacted to a click (vs a dead/no-op control). */
|
|
4
|
+
function isActivity(e) {
|
|
5
|
+
return (e.type === EventType.NET_REQUEST ||
|
|
6
|
+
e.type === EventType.DOM_ADDED ||
|
|
7
|
+
e.type === EventType.DOM_REMOVED ||
|
|
8
|
+
e.type === EventType.DOM_ATTR ||
|
|
9
|
+
e.type === EventType.DOM_TEXT ||
|
|
10
|
+
e.type === EventType.ROUTE_CHANGE ||
|
|
11
|
+
e.type === EventType.SIGNAL ||
|
|
12
|
+
e.type === EventType.ANIM_START ||
|
|
13
|
+
e.type === EventType.ANIM_END);
|
|
14
|
+
}
|
|
15
|
+
function isConsoleError(e) {
|
|
16
|
+
return e.type === EventType.CONSOLE_ERROR || e.type === EventType.ERROR_UNCAUGHT;
|
|
17
|
+
}
|
|
18
|
+
function failedRequests(events, floor) {
|
|
19
|
+
return events.filter((e) => {
|
|
20
|
+
if (e.type !== EventType.NET_REQUEST)
|
|
21
|
+
return false;
|
|
22
|
+
const status = asNumber(e.data['status']);
|
|
23
|
+
return status !== undefined && status >= floor;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The autonomous "smart monkey". Discovers every reachable interactive control once,
|
|
28
|
+
* then clicks each (bounded by maxSteps) and classifies the reaction into anomalies — console
|
|
29
|
+
* errors, failed requests, and DEAD controls (dispatched but the app did nothing). Pure
|
|
30
|
+
* orchestration over a CrawlSession: no browser/Node imports, fully unit-testable with a fake.
|
|
31
|
+
* Single-pass by design (no re-discovery) so it always terminates and never explodes on navigation.
|
|
32
|
+
*/
|
|
33
|
+
export async function crawl(session, opts, sleep) {
|
|
34
|
+
const maxSteps = opts.maxSteps ?? CRAWL_DEFAULTS.MAX_STEPS;
|
|
35
|
+
const settleMs = opts.settleMs ?? CRAWL_DEFAULTS.SETTLE_MS;
|
|
36
|
+
const snap = await session.command(ReticleCommand.SNAPSHOT, {
|
|
37
|
+
mode: 'interactive',
|
|
38
|
+
...(opts.scope !== undefined ? { scope: opts.scope } : {}),
|
|
39
|
+
});
|
|
40
|
+
const tree = snap.ok ? ((snap.result ?? {}).tree ?? '') : '';
|
|
41
|
+
const items = parseInteractive(tree);
|
|
42
|
+
const anomalies = [];
|
|
43
|
+
const visited = [];
|
|
44
|
+
const counts = { consoleErrors: 0, failedRequests: 0, deadControls: 0 };
|
|
45
|
+
const seen = new Set();
|
|
46
|
+
let stepsRun = 0;
|
|
47
|
+
for (const item of items) {
|
|
48
|
+
if (stepsRun >= maxSteps)
|
|
49
|
+
break;
|
|
50
|
+
if (seen.has(item.desc))
|
|
51
|
+
continue; // don't re-click an identical control
|
|
52
|
+
seen.add(item.desc);
|
|
53
|
+
stepsRun += 1;
|
|
54
|
+
visited.push(item.desc);
|
|
55
|
+
const since = session.elapsed();
|
|
56
|
+
const act = await session.command(ReticleCommand.ACT, {
|
|
57
|
+
ref: item.ref,
|
|
58
|
+
action: ActionType.CLICK,
|
|
59
|
+
args: opts.confirmDangerous === true ? { [DANGEROUS_ACTION_CONFIRM_ARG]: true } : {},
|
|
60
|
+
});
|
|
61
|
+
await sleep(settleMs);
|
|
62
|
+
const events = session.eventsSince(since);
|
|
63
|
+
const errs = events.filter(isConsoleError);
|
|
64
|
+
for (const e of errs) {
|
|
65
|
+
counts.consoleErrors += 1;
|
|
66
|
+
anomalies.push({
|
|
67
|
+
kind: CrawlAnomalyKind.CONSOLE_ERROR,
|
|
68
|
+
ref: item.ref,
|
|
69
|
+
desc: item.desc,
|
|
70
|
+
detail: asString(e.data['message']) ?? e.type,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
for (const e of failedRequests(events, CRAWL_DEFAULTS.FAILED_STATUS)) {
|
|
74
|
+
counts.failedRequests += 1;
|
|
75
|
+
const method = asString(e.data['method']) ?? '';
|
|
76
|
+
const url = asString(e.data['url']) ?? '';
|
|
77
|
+
const status = asNumber(e.data['status']);
|
|
78
|
+
anomalies.push({
|
|
79
|
+
kind: CrawlAnomalyKind.FAILED_REQUEST,
|
|
80
|
+
ref: item.ref,
|
|
81
|
+
desc: item.desc,
|
|
82
|
+
detail: `${method} ${url} → ${status ?? ''}`.trim(),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
// DEAD: the click dispatched but the app produced no activity and no error to explain it.
|
|
86
|
+
const dispatched = asRecord(act.result)['dispatched'] !== false && act.ok;
|
|
87
|
+
if (dispatched && errs.length === 0 && !events.some(isActivity)) {
|
|
88
|
+
counts.deadControls += 1;
|
|
89
|
+
anomalies.push({
|
|
90
|
+
kind: CrawlAnomalyKind.DEAD_CONTROL,
|
|
91
|
+
ref: item.ref,
|
|
92
|
+
desc: item.desc,
|
|
93
|
+
detail: 'clicked but the app did nothing (no DOM/network/route/signal change)',
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
interactiveFound: items.length,
|
|
99
|
+
stepsRun,
|
|
100
|
+
anomalies,
|
|
101
|
+
counts,
|
|
102
|
+
visited,
|
|
103
|
+
truncated: items.length > stepsRun,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=crawl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crawl.js","sourceRoot":"","sources":["../../src/crawl/crawl.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process-level resilience for the long-running daemon. The daemon serves many agents at once, so a
|
|
3
|
+
* single stray error must not take the whole fleet down:
|
|
4
|
+
*
|
|
5
|
+
* - unhandledRejection (a fire-and-forget promise nobody awaited — the common case in async WS/pool
|
|
6
|
+
* code) → LOG and keep running. One agent's async slip-up can't crash the daemon for everyone.
|
|
7
|
+
* - uncaughtException (a synchronous throw escaped all try/catch) → the process state is undefined
|
|
8
|
+
* per Node's guidance, so LOG a clear reason and exit cleanly; the next `reticle mcp` respawns a fresh
|
|
9
|
+
* daemon, which beats crashing silently or limping along corrupt.
|
|
10
|
+
*/
|
|
11
|
+
export interface ProcessLike {
|
|
12
|
+
on(event: string, listener: (arg: unknown) => void): unknown;
|
|
13
|
+
}
|
|
14
|
+
type LogFn = (event: string, data: Record<string, unknown>) => void;
|
|
15
|
+
export declare function installDaemonResilience(proc: ProcessLike, log: LogFn, onFatal: () => void): void;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=daemon-resilience.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon-resilience.d.ts","sourceRoot":"","sources":["../src/daemon-resilience.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,WAAW,WAAW;IAC1B,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC;CAC9D;AAED,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;AAMpE,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI,CAQhG"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process-level resilience for the long-running daemon. The daemon serves many agents at once, so a
|
|
3
|
+
* single stray error must not take the whole fleet down:
|
|
4
|
+
*
|
|
5
|
+
* - unhandledRejection (a fire-and-forget promise nobody awaited — the common case in async WS/pool
|
|
6
|
+
* code) → LOG and keep running. One agent's async slip-up can't crash the daemon for everyone.
|
|
7
|
+
* - uncaughtException (a synchronous throw escaped all try/catch) → the process state is undefined
|
|
8
|
+
* per Node's guidance, so LOG a clear reason and exit cleanly; the next `reticle mcp` respawns a fresh
|
|
9
|
+
* daemon, which beats crashing silently or limping along corrupt.
|
|
10
|
+
*/
|
|
11
|
+
function describe(value) {
|
|
12
|
+
return value instanceof Error ? value.message : String(value);
|
|
13
|
+
}
|
|
14
|
+
export function installDaemonResilience(proc, log, onFatal) {
|
|
15
|
+
proc.on('unhandledRejection', (reason) => {
|
|
16
|
+
log('reticle_daemon_unhandled_rejection', { reason: describe(reason) });
|
|
17
|
+
});
|
|
18
|
+
proc.on('uncaughtException', (err) => {
|
|
19
|
+
log('reticle_daemon_uncaught_exception', { error: describe(err) });
|
|
20
|
+
onFatal();
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=daemon-resilience.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon-resilience.js","sourceRoot":"","sources":["../src/daemon-resilience.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAQH,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,IAAiB,EAAE,GAAU,EAAE,OAAmB;IACxF,IAAI,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,MAAe,EAAE,EAAE;QAChD,GAAG,CAAC,oCAAoC,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IACH,IAAI,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,GAAY,EAAE,EAAE;QAC5C,GAAG,CAAC,mCAAmC,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACnE,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/daemon.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export declare function logPath(port: number): string;
|
|
2
|
+
export declare function readPid(port: number): number | null;
|
|
3
|
+
export declare function isAlive(pid: number): boolean;
|
|
4
|
+
export declare function writePid(port: number): void;
|
|
5
|
+
export declare function removePid(port: number): void;
|
|
6
|
+
export declare function isRunning(port: number): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Find the port of a live reticle daemon by scanning ~/.reticle/daemon-<port>.pid files — so `reticle open`
|
|
9
|
+
* can "find the port" itself instead of making the user reconcile it. Returns the first live one
|
|
10
|
+
* (lowest port, deterministic), or null when none is running.
|
|
11
|
+
*/
|
|
12
|
+
export declare function discoverDaemonPort(): number | null;
|
|
13
|
+
/**
|
|
14
|
+
* Sweep ~/.reticle for daemon-<port>.pid files whose process is no longer alive and delete them, so a
|
|
15
|
+
* crashed daemon never leaves a stale pidfile that confuses discovery or makes a port look "taken".
|
|
16
|
+
* Returns the ports reclaimed. `home` and `pidAlive` are injectable for testing (default to the real
|
|
17
|
+
* ~/.reticle and the process.kill(pid,0) liveness probe).
|
|
18
|
+
*/
|
|
19
|
+
export declare function reclaimStaleDaemons(home?: string, pidAlive?: (pid: number) => boolean): number[];
|
|
20
|
+
/**
|
|
21
|
+
* Spawn the reticle daemon as a detached background process, redirecting output to the log file.
|
|
22
|
+
* Writes the PID file from the parent before returning so callers can call isRunning()
|
|
23
|
+
* immediately without a race window.
|
|
24
|
+
*/
|
|
25
|
+
export declare function spawnDaemon(nodeExec: string, scriptPath: string, args: string[], port: number): void;
|
|
26
|
+
//# sourceMappingURL=daemon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon.d.ts","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"AAmBA,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKnD;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAO5C;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAG3C;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAG5C;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAG/C;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,IAAI,CAclD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,GAAE,MAAqB,EAC3B,QAAQ,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAiB,GAC3C,MAAM,EAAE,CA6BV;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EAAE,EACd,IAAI,EAAE,MAAM,GACX,IAAI,CAWN"}
|
package/dist/daemon.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { mkdirSync, readFileSync, writeFileSync, existsSync, unlinkSync, openSync, readdirSync, } from 'node:fs';
|
|
4
|
+
import { spawn } from 'node:child_process';
|
|
5
|
+
const RETICLE_HOME = join(homedir(), '.reticle');
|
|
6
|
+
function pidPath(port) {
|
|
7
|
+
return join(RETICLE_HOME, `daemon-${port}.pid`);
|
|
8
|
+
}
|
|
9
|
+
export function logPath(port) {
|
|
10
|
+
return join(RETICLE_HOME, `daemon-${port}.log`);
|
|
11
|
+
}
|
|
12
|
+
export function readPid(port) {
|
|
13
|
+
const path = pidPath(port);
|
|
14
|
+
if (!existsSync(path))
|
|
15
|
+
return null;
|
|
16
|
+
const n = parseInt(readFileSync(path, 'utf8').trim(), 10);
|
|
17
|
+
return isNaN(n) ? null : n;
|
|
18
|
+
}
|
|
19
|
+
export function isAlive(pid) {
|
|
20
|
+
try {
|
|
21
|
+
process.kill(pid, 0);
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export function writePid(port) {
|
|
29
|
+
mkdirSync(RETICLE_HOME, { recursive: true });
|
|
30
|
+
writeFileSync(pidPath(port), String(process.pid), 'utf8');
|
|
31
|
+
}
|
|
32
|
+
export function removePid(port) {
|
|
33
|
+
const path = pidPath(port);
|
|
34
|
+
if (existsSync(path))
|
|
35
|
+
unlinkSync(path);
|
|
36
|
+
}
|
|
37
|
+
export function isRunning(port) {
|
|
38
|
+
const pid = readPid(port);
|
|
39
|
+
return pid !== null && isAlive(pid);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Find the port of a live reticle daemon by scanning ~/.reticle/daemon-<port>.pid files — so `reticle open`
|
|
43
|
+
* can "find the port" itself instead of making the user reconcile it. Returns the first live one
|
|
44
|
+
* (lowest port, deterministic), or null when none is running.
|
|
45
|
+
*/
|
|
46
|
+
export function discoverDaemonPort() {
|
|
47
|
+
reclaimStaleDaemons(); // sweep crashed daemons' stale pidfiles before scanning for live ones
|
|
48
|
+
let found = null;
|
|
49
|
+
try {
|
|
50
|
+
for (const file of readdirSync(RETICLE_HOME)) {
|
|
51
|
+
const m = /^daemon-(\d+)\.pid$/.exec(file);
|
|
52
|
+
if (m === null)
|
|
53
|
+
continue;
|
|
54
|
+
const port = Number(m[1]);
|
|
55
|
+
if (isRunning(port) && (found === null || port < found))
|
|
56
|
+
found = port;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// no ~/.reticle yet → nothing running
|
|
61
|
+
}
|
|
62
|
+
return found;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Sweep ~/.reticle for daemon-<port>.pid files whose process is no longer alive and delete them, so a
|
|
66
|
+
* crashed daemon never leaves a stale pidfile that confuses discovery or makes a port look "taken".
|
|
67
|
+
* Returns the ports reclaimed. `home` and `pidAlive` are injectable for testing (default to the real
|
|
68
|
+
* ~/.reticle and the process.kill(pid,0) liveness probe).
|
|
69
|
+
*/
|
|
70
|
+
export function reclaimStaleDaemons(home = RETICLE_HOME, pidAlive = isAlive) {
|
|
71
|
+
const reclaimed = [];
|
|
72
|
+
let files;
|
|
73
|
+
try {
|
|
74
|
+
files = readdirSync(home);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return reclaimed; // no ~/.reticle yet → nothing to reclaim
|
|
78
|
+
}
|
|
79
|
+
for (const file of files) {
|
|
80
|
+
const match = /^daemon-(\d+)\.pid$/.exec(file);
|
|
81
|
+
if (match === null)
|
|
82
|
+
continue;
|
|
83
|
+
const path = join(home, file);
|
|
84
|
+
let pid = null;
|
|
85
|
+
try {
|
|
86
|
+
pid = parseInt(readFileSync(path, 'utf8').trim(), 10);
|
|
87
|
+
if (isNaN(pid))
|
|
88
|
+
pid = null;
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
pid = null; // unreadable pidfile counts as stale
|
|
92
|
+
}
|
|
93
|
+
if (pid === null || !pidAlive(pid)) {
|
|
94
|
+
try {
|
|
95
|
+
unlinkSync(path);
|
|
96
|
+
reclaimed.push(Number(match[1]));
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// racing another reclaimer — fine, it's already gone
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return reclaimed;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Spawn the reticle daemon as a detached background process, redirecting output to the log file.
|
|
107
|
+
* Writes the PID file from the parent before returning so callers can call isRunning()
|
|
108
|
+
* immediately without a race window.
|
|
109
|
+
*/
|
|
110
|
+
export function spawnDaemon(nodeExec, scriptPath, args, port) {
|
|
111
|
+
mkdirSync(RETICLE_HOME, { recursive: true });
|
|
112
|
+
const fd = openSync(logPath(port), 'a');
|
|
113
|
+
const child = spawn(nodeExec, [scriptPath, ...args], {
|
|
114
|
+
detached: true,
|
|
115
|
+
stdio: ['ignore', fd, fd],
|
|
116
|
+
});
|
|
117
|
+
if (child.pid !== undefined) {
|
|
118
|
+
writeFileSync(pidPath(port), String(child.pid), 'utf8');
|
|
119
|
+
}
|
|
120
|
+
child.unref();
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=daemon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build a compact "domain model" of an app's testable surface for an agent to read BEFORE testing:
|
|
3
|
+
* the demonstrated flows, what each one actually asserts, and — the differentiator — the GAPS
|
|
4
|
+
* between declared intent (capabilities the app registered: signals/testids) and what any flow
|
|
5
|
+
* actually verifies.
|
|
6
|
+
*
|
|
7
|
+
* Why (grounded): automation "checks the DOM, not the intent" — tests pass while real,
|
|
8
|
+
* integrated-system bugs ship (Bolton; Fowler Assertion-Free Testing). An agent that can see "you
|
|
9
|
+
* declared the signal order:placed but no flow asserts it" knows where the real risk is, instead of
|
|
10
|
+
* re-deriving the app's flows by reading all the source. Pairs with the flow assertion grades
|
|
11
|
+
* (flow-classify) so "rigorous" and "domain-aware" reinforce each other.
|
|
12
|
+
*
|
|
13
|
+
* Pure: no IO, no clock. The tool layer loads flows + contract and calls this.
|
|
14
|
+
*/
|
|
15
|
+
import { type CapabilitiesContract, type FlowFile, type RunRecord } from '@reticlehq/core';
|
|
16
|
+
import { type FlowRisk } from './flow-risk.js';
|
|
17
|
+
export interface DomainFlowSummary {
|
|
18
|
+
name: string;
|
|
19
|
+
steps: number;
|
|
20
|
+
grade: string;
|
|
21
|
+
/** True when the flow asserts a real consequence (signal/net), not just presence. */
|
|
22
|
+
asserts: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* The success consequence that MUST hold for this flow to count as passing — the human-readable
|
|
25
|
+
* label of flow.success (e.g. a signal name or net URL). Undefined when the flow declares no
|
|
26
|
+
* success condition (then `asserts` is false: it tests nothing observable). This is the
|
|
27
|
+
* "what must hold for each flow" an agent needs before testing.
|
|
28
|
+
*/
|
|
29
|
+
mustHold?: string;
|
|
30
|
+
warning?: string;
|
|
31
|
+
signals: string[];
|
|
32
|
+
testids: string[];
|
|
33
|
+
/** Combined run-history + assertion-quality risk (present when run history is supplied). */
|
|
34
|
+
risk?: FlowRisk;
|
|
35
|
+
}
|
|
36
|
+
export interface DomainGaps {
|
|
37
|
+
/** Flows that act but don't assert a consequence (grade !== asserted). */
|
|
38
|
+
unassertedFlows: string[];
|
|
39
|
+
/** Signals the app declared in capabilities that NO flow asserts — untested intent. */
|
|
40
|
+
declaredUntestedSignals: string[];
|
|
41
|
+
/** Testids the app declared that no saved flow exercises. */
|
|
42
|
+
declaredUntestedTestids: string[];
|
|
43
|
+
}
|
|
44
|
+
export interface DomainModel {
|
|
45
|
+
flowCount: number;
|
|
46
|
+
flows: DomainFlowSummary[];
|
|
47
|
+
declared: {
|
|
48
|
+
testids: number;
|
|
49
|
+
signals: string[];
|
|
50
|
+
stores: string[];
|
|
51
|
+
};
|
|
52
|
+
coverage: {
|
|
53
|
+
asserted: number;
|
|
54
|
+
presenceOnly: number;
|
|
55
|
+
assertionFree: number;
|
|
56
|
+
};
|
|
57
|
+
gaps: DomainGaps;
|
|
58
|
+
/** Flow names worst-risk first (run-history + assertion quality). Empty without run history. */
|
|
59
|
+
riskRanked: string[];
|
|
60
|
+
/** One-line headline an agent (or human) can read at a glance. */
|
|
61
|
+
summary: string;
|
|
62
|
+
}
|
|
63
|
+
export declare function buildDomainModel(flows: readonly FlowFile[], contract: CapabilitiesContract | null, runs?: readonly RunRecord[]): DomainModel;
|
|
64
|
+
//# sourceMappingURL=domain-model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domain-model.d.ts","sourceRoot":"","sources":["../../src/domain/domain-model.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,QAAQ,EAEb,KAAK,SAAS,EACf,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAA8C,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE3F,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,qFAAqF;IACrF,OAAO,EAAE,OAAO,CAAC;IACjB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,4FAA4F;IAC5F,IAAI,CAAC,EAAE,QAAQ,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,0EAA0E;IAC1E,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,uFAAuF;IACvF,uBAAuB,EAAE,MAAM,EAAE,CAAC;IAClC,6DAA6D;IAC7D,uBAAuB,EAAE,MAAM,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,QAAQ,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACnE,QAAQ,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5E,IAAI,EAAE,UAAU,CAAC;IACjB,gGAAgG;IAChG,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,kEAAkE;IAClE,OAAO,EAAE,MAAM,CAAC;CACjB;AAiCD,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,SAAS,QAAQ,EAAE,EAC1B,QAAQ,EAAE,oBAAoB,GAAG,IAAI,EACrC,IAAI,GAAE,SAAS,SAAS,EAAO,GAC9B,WAAW,CA8Db"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build a compact "domain model" of an app's testable surface for an agent to read BEFORE testing:
|
|
3
|
+
* the demonstrated flows, what each one actually asserts, and — the differentiator — the GAPS
|
|
4
|
+
* between declared intent (capabilities the app registered: signals/testids) and what any flow
|
|
5
|
+
* actually verifies.
|
|
6
|
+
*
|
|
7
|
+
* Why (grounded): automation "checks the DOM, not the intent" — tests pass while real,
|
|
8
|
+
* integrated-system bugs ship (Bolton; Fowler Assertion-Free Testing). An agent that can see "you
|
|
9
|
+
* declared the signal order:placed but no flow asserts it" knows where the real risk is, instead of
|
|
10
|
+
* re-deriving the app's flows by reading all the source. Pairs with the flow assertion grades
|
|
11
|
+
* (flow-classify) so "rigorous" and "domain-aware" reinforce each other.
|
|
12
|
+
*
|
|
13
|
+
* Pure: no IO, no clock. The tool layer loads flows + contract and calls this.
|
|
14
|
+
*/
|
|
15
|
+
import { AnchorKind, } from '@reticlehq/core';
|
|
16
|
+
import { classifyFlowAssertions, FlowAssertionGrade } from '../flows/flow-classify.js';
|
|
17
|
+
import { successLabel } from '../flows/flow-success.js';
|
|
18
|
+
import { flowRisk, latestRun, rankByRisk, RiskLevel } from './flow-risk.js';
|
|
19
|
+
function flatten(steps) {
|
|
20
|
+
const out = [];
|
|
21
|
+
for (const s of steps) {
|
|
22
|
+
out.push(s);
|
|
23
|
+
if (s.steps !== undefined)
|
|
24
|
+
out.push(...flatten(s.steps));
|
|
25
|
+
}
|
|
26
|
+
return out;
|
|
27
|
+
}
|
|
28
|
+
function flowSignals(flow) {
|
|
29
|
+
const set = new Set();
|
|
30
|
+
for (const step of flatten(flow.steps)) {
|
|
31
|
+
if (step.anchor.kind === AnchorKind.SIGNAL)
|
|
32
|
+
set.add(step.anchor.name);
|
|
33
|
+
if (step.expect?.signal !== undefined)
|
|
34
|
+
set.add(step.expect.signal);
|
|
35
|
+
}
|
|
36
|
+
if (flow.success?.signal !== undefined)
|
|
37
|
+
set.add(flow.success.signal);
|
|
38
|
+
return [...set];
|
|
39
|
+
}
|
|
40
|
+
function flowTestids(flow) {
|
|
41
|
+
const set = new Set();
|
|
42
|
+
for (const step of flatten(flow.steps)) {
|
|
43
|
+
if (step.anchor.kind === AnchorKind.TESTID)
|
|
44
|
+
set.add(step.anchor.value);
|
|
45
|
+
if (step.expect?.element?.testid !== undefined)
|
|
46
|
+
set.add(step.expect.element.testid);
|
|
47
|
+
}
|
|
48
|
+
if (flow.success?.element?.testid !== undefined)
|
|
49
|
+
set.add(flow.success.element.testid);
|
|
50
|
+
return [...set];
|
|
51
|
+
}
|
|
52
|
+
const EMPTY_CONTRACT = { testids: [], signals: [], stores: [], flows: [] };
|
|
53
|
+
export function buildDomainModel(flows, contract, runs = []) {
|
|
54
|
+
const caps = contract ?? EMPTY_CONTRACT;
|
|
55
|
+
const hasHistory = runs.length > 0;
|
|
56
|
+
const flowSummaries = flows.map((flow) => {
|
|
57
|
+
const c = classifyFlowAssertions(flow);
|
|
58
|
+
const summary = {
|
|
59
|
+
name: flow.name,
|
|
60
|
+
steps: c.totalSteps,
|
|
61
|
+
grade: c.grade,
|
|
62
|
+
asserts: c.hasConsequenceAssertion,
|
|
63
|
+
signals: flowSignals(flow),
|
|
64
|
+
testids: flowTestids(flow),
|
|
65
|
+
};
|
|
66
|
+
if (flow.success !== undefined)
|
|
67
|
+
summary.mustHold = successLabel(flow.success);
|
|
68
|
+
if (c.warning !== undefined)
|
|
69
|
+
summary.warning = c.warning;
|
|
70
|
+
if (hasHistory)
|
|
71
|
+
summary.risk = flowRisk(c.grade, latestRun(flow.name, runs));
|
|
72
|
+
return summary;
|
|
73
|
+
});
|
|
74
|
+
const testedSignals = new Set(flowSummaries.flatMap((f) => f.signals));
|
|
75
|
+
const testedTestids = new Set(flowSummaries.flatMap((f) => f.testids));
|
|
76
|
+
const coverage = {
|
|
77
|
+
asserted: flowSummaries.filter((f) => f.grade === FlowAssertionGrade.ASSERTED).length,
|
|
78
|
+
presenceOnly: flowSummaries.filter((f) => f.grade === FlowAssertionGrade.PRESENCE_ONLY).length,
|
|
79
|
+
assertionFree: flowSummaries.filter((f) => f.grade === FlowAssertionGrade.ASSERTION_FREE)
|
|
80
|
+
.length,
|
|
81
|
+
};
|
|
82
|
+
const gaps = {
|
|
83
|
+
unassertedFlows: flowSummaries.filter((f) => !f.asserts).map((f) => f.name),
|
|
84
|
+
declaredUntestedSignals: caps.signals.filter((s) => !testedSignals.has(s)),
|
|
85
|
+
declaredUntestedTestids: caps.testids.filter((t) => !testedTestids.has(t)),
|
|
86
|
+
};
|
|
87
|
+
const riskRanked = hasHistory
|
|
88
|
+
? rankByRisk(flowSummaries
|
|
89
|
+
.filter((f) => f.risk !== undefined)
|
|
90
|
+
.map((f) => ({ name: f.name, risk: f.risk })))
|
|
91
|
+
: [];
|
|
92
|
+
// The most actionable fact — the riskiest flow to test first — when run history flagged one.
|
|
93
|
+
const top = riskRanked[0];
|
|
94
|
+
const topFlow = top === undefined ? undefined : flowSummaries.find((f) => f.name === top);
|
|
95
|
+
const topRisk = topFlow?.risk !== undefined &&
|
|
96
|
+
(topFlow.risk.level === RiskLevel.HIGH || topFlow.risk.level === RiskLevel.MEDIUM)
|
|
97
|
+
? { name: topFlow.name, reason: topFlow.risk.reason }
|
|
98
|
+
: undefined;
|
|
99
|
+
return {
|
|
100
|
+
flowCount: flows.length,
|
|
101
|
+
flows: flowSummaries,
|
|
102
|
+
declared: { testids: caps.testids.length, signals: caps.signals, stores: caps.stores },
|
|
103
|
+
coverage,
|
|
104
|
+
gaps,
|
|
105
|
+
riskRanked,
|
|
106
|
+
summary: buildSummary(flows.length, coverage, gaps, topRisk),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function buildSummary(flowCount, coverage, gaps, topRisk) {
|
|
110
|
+
if (flowCount === 0) {
|
|
111
|
+
return 'No saved flows yet — record the critical journeys (reticle_record_start) so the agent learns the app.';
|
|
112
|
+
}
|
|
113
|
+
const parts = [
|
|
114
|
+
`${String(flowCount)} flow${flowCount === 1 ? '' : 's'}: ${String(coverage.asserted)} asserted, ${String(coverage.presenceOnly)} presence-only, ${String(coverage.assertionFree)} assertion-free`,
|
|
115
|
+
];
|
|
116
|
+
if (topRisk !== undefined) {
|
|
117
|
+
parts.push(`test first: ${topRisk.name} (${topRisk.reason})`);
|
|
118
|
+
}
|
|
119
|
+
if (gaps.declaredUntestedSignals.length > 0) {
|
|
120
|
+
parts.push(`${String(gaps.declaredUntestedSignals.length)} declared signal(s) no flow asserts (${gaps.declaredUntestedSignals.join(', ')})`);
|
|
121
|
+
}
|
|
122
|
+
if (gaps.unassertedFlows.length > 0) {
|
|
123
|
+
parts.push(`${String(gaps.unassertedFlows.length)} flow(s) assert no consequence`);
|
|
124
|
+
}
|
|
125
|
+
return parts.join('. ') + '.';
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=domain-model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domain-model.js","sourceRoot":"","sources":["../../src/domain/domain-model.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ToolDef } from '../tools/tools.js';
|
|
2
|
+
/**
|
|
3
|
+
* reticle_domain — the "learn the app before testing it" tool. Synthesizes every saved flow + the
|
|
4
|
+
* registered capabilities into a compact domain model: the journeys, what each asserts, and the
|
|
5
|
+
* GAPS (declared signals/testids no flow verifies). An agent reads this once instead of crawling
|
|
6
|
+
* the whole app or reading all the source — and it points straight at untested intent.
|
|
7
|
+
*/
|
|
8
|
+
export declare const DOMAIN_TOOLS: ToolDef[];
|
|
9
|
+
//# sourceMappingURL=domain-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domain-tools.d.ts","sourceRoot":"","sources":["../../src/domain/domain-tools.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAY,MAAM,mBAAmB,CAAC;AAE3D;;;;;GAKG;AACH,eAAO,MAAM,YAAY,EAAE,OAAO,EA4DjC,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ReticleTool } from '../tools/tool-names.js';
|
|
3
|
+
import { readContract } from '../project/reticle-dir.js';
|
|
4
|
+
import { buildDomainModel } from './domain-model.js';
|
|
5
|
+
/**
|
|
6
|
+
* reticle_domain — the "learn the app before testing it" tool. Synthesizes every saved flow + the
|
|
7
|
+
* registered capabilities into a compact domain model: the journeys, what each asserts, and the
|
|
8
|
+
* GAPS (declared signals/testids no flow verifies). An agent reads this once instead of crawling
|
|
9
|
+
* the whole app or reading all the source — and it points straight at untested intent.
|
|
10
|
+
*/
|
|
11
|
+
export const DOMAIN_TOOLS = [
|
|
12
|
+
{
|
|
13
|
+
name: ReticleTool.DOMAIN,
|
|
14
|
+
description: 'Read the app domain model BEFORE testing: every saved flow with its assertion grade, the consequence that MUST hold for it (mustHold = what it actually tests), the anchors/signals it exercises, plus GAPS — declared signals/testids that NO flow asserts (untested intent), and flows that assert no observable consequence. Use this to decide what to test and where the real risk is, instead of crawling the whole app. Reads .reticle/flows/ + .reticle/contract.json (no browser needed).',
|
|
15
|
+
inputSchema: {},
|
|
16
|
+
outputSchema: {
|
|
17
|
+
flowCount: z.number(),
|
|
18
|
+
flows: z.array(z.object({
|
|
19
|
+
name: z.string(),
|
|
20
|
+
steps: z.number(),
|
|
21
|
+
grade: z.string(),
|
|
22
|
+
asserts: z.boolean(),
|
|
23
|
+
mustHold: z
|
|
24
|
+
.string()
|
|
25
|
+
.optional()
|
|
26
|
+
.describe('The success consequence that must hold for this flow (what it actually tests).'),
|
|
27
|
+
warning: z.string().optional(),
|
|
28
|
+
signals: z.array(z.string()),
|
|
29
|
+
testids: z.array(z.string()),
|
|
30
|
+
})),
|
|
31
|
+
declared: z.object({
|
|
32
|
+
testids: z.number(),
|
|
33
|
+
signals: z.array(z.string()),
|
|
34
|
+
stores: z.array(z.string()),
|
|
35
|
+
}),
|
|
36
|
+
coverage: z.object({
|
|
37
|
+
asserted: z.number(),
|
|
38
|
+
presenceOnly: z.number(),
|
|
39
|
+
assertionFree: z.number(),
|
|
40
|
+
}),
|
|
41
|
+
gaps: z.object({
|
|
42
|
+
unassertedFlows: z.array(z.string()),
|
|
43
|
+
declaredUntestedSignals: z.array(z.string()),
|
|
44
|
+
declaredUntestedTestids: z.array(z.string()),
|
|
45
|
+
}),
|
|
46
|
+
riskRanked: z
|
|
47
|
+
.array(z.string())
|
|
48
|
+
.describe('Flow names worst-risk first (run history + assertion quality). Test these first.'),
|
|
49
|
+
summary: z.string(),
|
|
50
|
+
},
|
|
51
|
+
handler: async (deps) => {
|
|
52
|
+
const names = await deps.flows.list();
|
|
53
|
+
const flows = [];
|
|
54
|
+
for (const name of names) {
|
|
55
|
+
const loaded = await deps.flows.load(name);
|
|
56
|
+
if (loaded.ok)
|
|
57
|
+
flows.push(loaded.value);
|
|
58
|
+
}
|
|
59
|
+
const contract = await readContract(deps.fs, deps.reticleRoot);
|
|
60
|
+
const project = await deps.project.read();
|
|
61
|
+
const runs = project.ok ? project.file.runs : [];
|
|
62
|
+
return buildDomainModel(flows, contract.ok ? contract.capabilities : null, runs);
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
];
|
|
66
|
+
//# sourceMappingURL=domain-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domain-tools.js","sourceRoot":"","sources":["../../src/domain/domain-tools.ts"],"names":[],"mappings":"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"}
|