ashlr-plugin 1.36.4
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/.agents/plugins/marketplace.json +20 -0
- package/.claude-plugin/marketplace.json +39 -0
- package/.claude-plugin/plugin.json +36 -0
- package/.codex/agents/README.md +9 -0
- package/.codex/agents/ashlr-explorer.md +36 -0
- package/.codex/agents/ashlr-worker.md +38 -0
- package/.codex-plugin/plugin.json +45 -0
- package/.mcp.json +14 -0
- package/LICENSE +21 -0
- package/README.md +311 -0
- package/agents/ashlr-code.md +69 -0
- package/agents/ashlr-explore.md +44 -0
- package/agents/ashlr-plan.md +54 -0
- package/bench/fixtures/notebook-large.ipynb +660 -0
- package/bench/fixtures/notebook-small.ipynb +39 -0
- package/bench/fixtures/tasklist-closed.json +62 -0
- package/bench/fixtures/tasklist-large-mixed.json +27 -0
- package/bench/fixtures/tasklist-sprint-open.json +79 -0
- package/bench/fixtures/websearch-bun-runtime.json +32 -0
- package/bench/fixtures/websearch-react-hooks-patterns.json +32 -0
- package/bench/fixtures/websearch-typescript-generics.json +38 -0
- package/bench/refs/node-sdk/.refrev +1 -0
- package/bench/refs/node-sdk/README.md +17 -0
- package/bench/refs/node-sdk/src/agent/agent.ts +163 -0
- package/bench/refs/node-sdk/src/agent/create-agent-ui-stream.ts +83 -0
- package/bench/refs/node-sdk/src/agent/tool-loop-agent.ts +238 -0
- package/bench/refs/node-sdk/src/embed/embed-many.ts +409 -0
- package/bench/refs/node-sdk/src/embed/embed-result.ts +50 -0
- package/bench/refs/node-sdk/src/embed/embed.ts +257 -0
- package/bench/refs/node-sdk/src/error/invalid-argument-error.ts +34 -0
- package/bench/refs/node-sdk/src/error/invalid-tool-input-error.ts +33 -0
- package/bench/refs/node-sdk/src/error/no-object-generated-error.ts +70 -0
- package/bench/refs/node-sdk/src/generate-image/generate-image-result.ts +42 -0
- package/bench/refs/node-sdk/src/generate-image/generate-image.ts +362 -0
- package/bench/refs/node-sdk/src/generate-object/generate-object-result.ts +67 -0
- package/bench/refs/node-sdk/src/generate-object/generate-object.ts +501 -0
- package/bench/refs/node-sdk/src/generate-object/inject-json-instruction.ts +30 -0
- package/bench/refs/node-sdk/src/generate-object/output-strategy.ts +415 -0
- package/bench/refs/node-sdk/src/generate-object/repair-text.ts +12 -0
- package/bench/refs/node-sdk/src/generate-object/stream-object.ts +960 -0
- package/bench/refs/node-sdk/src/generate-speech/generate-speech.ts +191 -0
- package/bench/refs/node-sdk/src/generate-text/generate-text.ts +1484 -0
- package/bench/refs/node-sdk/src/generate-text/stream-text.ts +2708 -0
- package/bench/refs/node-sdk/src/generate-text/tool-call.ts +59 -0
- package/bench/refs/node-sdk/src/generate-text/tool-result.ts +36 -0
- package/bench/refs/node-sdk/src/telemetry/create-telemetry-dispatcher.ts +146 -0
- package/bench/refs/node-sdk/src/telemetry/telemetry-registry.ts +15 -0
- package/bench/refs/node-sdk/src/telemetry/telemetry.ts +223 -0
- package/bench/refs/node-sdk/src/util/async-iterable-stream.ts +94 -0
- package/bench/refs/node-sdk/src/util/consume-stream.ts +31 -0
- package/bench/refs/node-sdk/src/util/create-stitchable-stream.ts +112 -0
- package/bench/refs/node-sdk/src/util/download/download.ts +74 -0
- package/bench/refs/node-sdk/src/util/error-handler.ts +1 -0
- package/bench/refs/node-sdk/src/util/fix-json.ts +401 -0
- package/bench/refs/node-sdk/src/util/merge-objects.ts +79 -0
- package/bench/refs/python-lib/.refrev +1 -0
- package/bench/refs/python-lib/README.md +18 -0
- package/bench/refs/python-lib/pandas/core/_numba/executor.py +249 -0
- package/bench/refs/python-lib/pandas/core/_numba/extensions.py +586 -0
- package/bench/refs/python-lib/pandas/core/_numba/kernels/mean_.py +198 -0
- package/bench/refs/python-lib/pandas/core/_numba/kernels/min_max_.py +178 -0
- package/bench/refs/python-lib/pandas/core/_numba/kernels/sum_.py +255 -0
- package/bench/refs/python-lib/pandas/core/_numba/kernels/var_.py +251 -0
- package/bench/refs/python-lib/pandas/core/accessor.py +520 -0
- package/bench/refs/python-lib/pandas/core/api.py +138 -0
- package/bench/refs/python-lib/pandas/core/array_algos/masked_accumulations.py +97 -0
- package/bench/refs/python-lib/pandas/core/array_algos/masked_reductions.py +252 -0
- package/bench/refs/python-lib/pandas/core/array_algos/putmask.py +150 -0
- package/bench/refs/python-lib/pandas/core/array_algos/quantile.py +232 -0
- package/bench/refs/python-lib/pandas/core/array_algos/replace.py +159 -0
- package/bench/refs/python-lib/pandas/core/array_algos/take.py +609 -0
- package/bench/refs/python-lib/pandas/core/arraylike.py +534 -0
- package/bench/refs/python-lib/pandas/core/arrays/_arrow_string_mixins.py +434 -0
- package/bench/refs/python-lib/pandas/core/arrays/_mixins.py +630 -0
- package/bench/refs/python-lib/pandas/core/arrays/_ranges.py +276 -0
- package/bench/refs/python-lib/pandas/core/arrays/_utils.py +77 -0
- package/bench/refs/python-lib/pandas/core/arrays/arrow/accessors.py +521 -0
- package/bench/refs/python-lib/pandas/core/arrays/arrow/extension_types.py +174 -0
- package/bench/refs/python-lib/pandas/core/arrays/boolean.py +454 -0
- package/bench/refs/python-lib/pandas/core/arrays/floating.py +192 -0
- package/bench/refs/python-lib/pandas/core/arrays/integer.py +296 -0
- package/bench/refs/python-lib/pandas/core/arrays/masked.py +2140 -0
- package/bench/refs/python-lib/pandas/core/arrays/numeric.py +305 -0
- package/bench/refs/python-lib/pandas/core/arrays/numpy_.py +701 -0
- package/bench/refs/python-lib/pandas/core/arrays/period.py +1586 -0
- package/bench/refs/python-lib/pandas/core/arrays/sparse/accessor.py +505 -0
- package/bench/refs/python-lib/pandas/core/arrays/sparse/scipy_sparse.py +208 -0
- package/bench/refs/rust-project/.refrev +1 -0
- package/bench/refs/rust-project/README.md +17 -0
- package/bench/refs/rust-project/tokio/src/doc/os.rs +68 -0
- package/bench/refs/rust-project/tokio/src/fs/dir_builder.rs +129 -0
- package/bench/refs/rust-project/tokio/src/fs/file.rs +1113 -0
- package/bench/refs/rust-project/tokio/src/fs/mocks.rs +176 -0
- package/bench/refs/rust-project/tokio/src/fs/mod.rs +324 -0
- package/bench/refs/rust-project/tokio/src/fs/open_options.rs +856 -0
- package/bench/refs/rust-project/tokio/src/fs/read.rs +80 -0
- package/bench/refs/rust-project/tokio/src/fs/read_dir.rs +357 -0
- package/bench/refs/rust-project/tokio/src/fs/write.rs +99 -0
- package/bench/refs/rust-project/tokio/src/future/maybe_done.rs +123 -0
- package/bench/refs/rust-project/tokio/src/future/try_join.rs +82 -0
- package/bench/refs/rust-project/tokio/src/io/async_buf_read.rs +117 -0
- package/bench/refs/rust-project/tokio/src/io/async_read.rs +133 -0
- package/bench/refs/rust-project/tokio/src/io/async_seek.rs +96 -0
- package/bench/refs/rust-project/tokio/src/io/async_write.rs +402 -0
- package/bench/refs/rust-project/tokio/src/io/blocking.rs +339 -0
- package/bench/refs/rust-project/tokio/src/io/interest.rs +345 -0
- package/bench/refs/rust-project/tokio/src/io/join.rs +130 -0
- package/bench/refs/rust-project/tokio/src/io/mod.rs +308 -0
- package/bench/refs/rust-project/tokio/src/io/poll_evented.rs +319 -0
- package/bench/refs/rust-project/tokio/src/io/read_buf.rs +344 -0
- package/bench/refs/rust-project/tokio/src/io/ready.rs +322 -0
- package/bench/refs/rust-project/tokio/src/io/split.rs +166 -0
- package/bench/refs/rust-project/tokio/src/io/stderr.rs +148 -0
- package/bench/refs/rust-project/tokio/src/io/stdin.rs +98 -0
- package/bench/refs/rust-project/tokio/src/io/stdio_common.rs +222 -0
- package/bench/refs/rust-project/tokio/src/io/stdout.rs +197 -0
- package/bench/refs/rust-project/tokio/src/io/util/buf_reader.rs +311 -0
- package/bench/refs/rust-project/tokio/src/io/util/buf_stream.rs +207 -0
- package/bench/refs/rust-project/tokio/src/io/util/buf_writer.rs +310 -0
- package/bench/refs/rust-project/tokio/src/io/util/chain.rs +144 -0
- package/commands/_spawn-patterns.json +32 -0
- package/commands/ashlr-allow.md +21 -0
- package/commands/ashlr-benchmark.md +53 -0
- package/commands/ashlr-brief.md +97 -0
- package/commands/ashlr-budget.md +76 -0
- package/commands/ashlr-compact.md +54 -0
- package/commands/ashlr-dashboard.md +37 -0
- package/commands/ashlr-doctor.md +56 -0
- package/commands/ashlr-eco-mode.md +92 -0
- package/commands/ashlr-genome-init.md +24 -0
- package/commands/ashlr-genome-keygen.md +36 -0
- package/commands/ashlr-genome-loop.md +118 -0
- package/commands/ashlr-genome-push.md +36 -0
- package/commands/ashlr-genome-rewrap.md +48 -0
- package/commands/ashlr-genome-team-init.md +67 -0
- package/commands/ashlr-handoff.md +23 -0
- package/commands/ashlr-help.md +86 -0
- package/commands/ashlr-hook-timings.md +30 -0
- package/commands/ashlr-leaderboard.md +50 -0
- package/commands/ashlr-ollama-setup.md +39 -0
- package/commands/ashlr-orchestrate-status.md +72 -0
- package/commands/ashlr-orchestrate.md +83 -0
- package/commands/ashlr-parallelize.md +63 -0
- package/commands/ashlr-report-crash.md +33 -0
- package/commands/ashlr-resume.md +72 -0
- package/commands/ashlr-savings.md +24 -0
- package/commands/ashlr-settings.md +50 -0
- package/commands/ashlr-spawn.md +61 -0
- package/commands/ashlr-start.md +60 -0
- package/commands/ashlr-status.md +64 -0
- package/commands/ashlr-team-invite.md +47 -0
- package/commands/ashlr-tier.md +122 -0
- package/commands/ashlr-tour.md +60 -0
- package/commands/ashlr-update.md +155 -0
- package/commands/ashlr-upgrade.md +96 -0
- package/commands/goal.md +58 -0
- package/commands/loop.md +40 -0
- package/docs/CNAME +1 -0
- package/docs/PRO_TIER.md +104 -0
- package/docs/README.md +21 -0
- package/docs/architecture.md +415 -0
- package/docs/ashlr-pipe.md +161 -0
- package/docs/assets/logo.svg +19 -0
- package/docs/assets/og.png +0 -0
- package/docs/assets/og.svg +41 -0
- package/docs/benchmarks-v2.json +355 -0
- package/docs/benchmarks.json +102 -0
- package/docs/benchmarks.md +211 -0
- package/docs/billing.md +185 -0
- package/docs/cloud-genome.md +155 -0
- package/docs/competitive-wozcode.md +92 -0
- package/docs/deploy.md +325 -0
- package/docs/email-templates.md +113 -0
- package/docs/embed-tuning.md +103 -0
- package/docs/genome.md +120 -0
- package/docs/github-oauth-onboarding.md +127 -0
- package/docs/hero-video-script.md +129 -0
- package/docs/index.html +2262 -0
- package/docs/install-prompt.md +78 -0
- package/docs/install-windows.md +132 -0
- package/docs/install.ps1 +171 -0
- package/docs/install.sh +146 -0
- package/docs/launch/README.md +114 -0
- package/docs/launch/hn.md +49 -0
- package/docs/launch/reddit.md +45 -0
- package/docs/launch/x.md +65 -0
- package/docs/launch-post.md +112 -0
- package/docs/legal.md +78 -0
- package/docs/llm-providers.md +99 -0
- package/docs/multi-host-mcp.md +217 -0
- package/docs/multi-turn-architecture.md +108 -0
- package/docs/operations/deployment.md +108 -0
- package/docs/operations/error-monitoring.md +70 -0
- package/docs/operations/weekly-digest.md +70 -0
- package/docs/operations.md +494 -0
- package/docs/platform-support.md +133 -0
- package/docs/policy-packs.md +188 -0
- package/docs/press-kit/fact-sheet.md +78 -0
- package/docs/press-kit/founder-bio.md +3 -0
- package/docs/press-kit/logo.svg +33 -0
- package/docs/press-kit/screenshots.md +146 -0
- package/docs/pricing.md +251 -0
- package/docs/pro-backend-architecture.md +523 -0
- package/docs/producthunt.md +52 -0
- package/docs/router-migration.md +110 -0
- package/docs/session-log-schema.md +68 -0
- package/docs/social.md +95 -0
- package/docs/team-genome.md +528 -0
- package/docs/telemetry.md +194 -0
- package/docs/test-isolation.md +100 -0
- package/docs/upgrade.md +159 -0
- package/hooks/_hook-errors.ts +87 -0
- package/hooks/_hook-perf-emit.ts +113 -0
- package/hooks/_hook-timing-ledger.ts +1133 -0
- package/hooks/_nudge-throttle.ts +127 -0
- package/hooks/_recent-blocks.ts +127 -0
- package/hooks/audit-upload.ts +86 -0
- package/hooks/codex-hooks.json +171 -0
- package/hooks/commit-attribution.ts +179 -0
- package/hooks/edit-batching-nudge.ts +154 -0
- package/hooks/genome-scribe-hook.ts +219 -0
- package/hooks/hooks.json +294 -0
- package/hooks/orient-nudge-hook.ts +242 -0
- package/hooks/policy-enforce.ts +214 -0
- package/hooks/post-tool-use-embedding.ts +93 -0
- package/hooks/post-tool-use-genome.sh +37 -0
- package/hooks/post-tool-use-genome.ts +69 -0
- package/hooks/posttooluse-correlate.ts +122 -0
- package/hooks/posttooluse-dedupe-output.ts +241 -0
- package/hooks/posttooluse-genome-refresh.ts +223 -0
- package/hooks/posttooluse-native-nudge.ts +205 -0
- package/hooks/posttooluse-stale-result.ts +277 -0
- package/hooks/pretooluse-bash.ts +63 -0
- package/hooks/pretooluse-budget-guard.ts +318 -0
- package/hooks/pretooluse-common.ts +985 -0
- package/hooks/pretooluse-eco-router.ts +196 -0
- package/hooks/pretooluse-edit.sh +93 -0
- package/hooks/pretooluse-edit.ts +197 -0
- package/hooks/pretooluse-glob.ts +70 -0
- package/hooks/pretooluse-grep.sh +85 -0
- package/hooks/pretooluse-grep.ts +96 -0
- package/hooks/pretooluse-notebookedit.ts +121 -0
- package/hooks/pretooluse-read.sh +118 -0
- package/hooks/pretooluse-read.ts +118 -0
- package/hooks/pretooluse-task.ts +130 -0
- package/hooks/pretooluse-webfetch.ts +66 -0
- package/hooks/pretooluse-websearch.ts +85 -0
- package/hooks/pretooluse-write.ts +128 -0
- package/hooks/pulse-emit.ts +197 -0
- package/hooks/session-end-consolidate.sh +35 -0
- package/hooks/session-end-consolidate.ts +188 -0
- package/hooks/session-end-stats-gc.ts +80 -0
- package/hooks/session-log-append.sh +94 -0
- package/hooks/session-log-append.ts +116 -0
- package/hooks/session-start.ts +993 -0
- package/hooks/sessionend-hook-health-nudge.ts +451 -0
- package/hooks/sessionend-savings-nudge.ts +318 -0
- package/hooks/sessionend-status-line-nudge.ts +296 -0
- package/hooks/sessionstart-brief.ts +140 -0
- package/hooks/sessionstart-cost-refactor.ts +95 -0
- package/hooks/sessionstart-efficient.ts +110 -0
- package/hooks/sessionstart-genome-author.ts +93 -0
- package/hooks/sessionstart-lean-tools.ts +98 -0
- package/hooks/sessionstart-search.ts +97 -0
- package/hooks/stop-accounting.ts +152 -0
- package/hooks/subagent-stop-rollup.ts +162 -0
- package/hooks/userpromptsubmit-brief-trigger.ts +156 -0
- package/package.json +56 -0
- package/ports/README.md +108 -0
- package/ports/cursor/mcp.json +11 -0
- package/ports/goose/recipe.yaml +26 -0
- package/scripts/ashlr-mcp.ts +40 -0
- package/scripts/auto-update.ts +177 -0
- package/scripts/baseline-scan.ts +831 -0
- package/scripts/bench-orchestrate.ts +377 -0
- package/scripts/benchmark-refs.ts +292 -0
- package/scripts/bootstrap.mjs +100 -0
- package/scripts/brief-eval.ts +234 -0
- package/scripts/bump-version.ts +82 -0
- package/scripts/bun-resolve.d.mts +11 -0
- package/scripts/bun-resolve.mjs +59 -0
- package/scripts/calibrate-grep.ts +467 -0
- package/scripts/capture-grep-workload.ts +260 -0
- package/scripts/check-tier.ts +61 -0
- package/scripts/check-version-sync.ts +97 -0
- package/scripts/cli-orchestrate-status.ts +386 -0
- package/scripts/cli-orchestrate.ts +303 -0
- package/scripts/cli.ts +478 -0
- package/scripts/cloud-smoke-test.ts +313 -0
- package/scripts/coach-report.ts +373 -0
- package/scripts/context-db-migrate.ts +137 -0
- package/scripts/context-status.ts +43 -0
- package/scripts/demo-run.ts +255 -0
- package/scripts/deploy-smoke.sh +140 -0
- package/scripts/doctor.ts +992 -0
- package/scripts/embed-file-worker.ts +104 -0
- package/scripts/embed-tune.ts +308 -0
- package/scripts/errors-report.ts +428 -0
- package/scripts/find-test-leak.ts +69 -0
- package/scripts/generate-badge.ts +357 -0
- package/scripts/genome-auto-consolidate.ts +533 -0
- package/scripts/genome-auto-propose.ts +578 -0
- package/scripts/genome-cloud-pull.ts +363 -0
- package/scripts/genome-cloud-push.ts +382 -0
- package/scripts/genome-cloud-sync.ts +587 -0
- package/scripts/genome-commit-watcher.ts +295 -0
- package/scripts/genome-init.ts +986 -0
- package/scripts/genome-key.ts +233 -0
- package/scripts/genome-keygen.ts +168 -0
- package/scripts/genome-link.ts +59 -0
- package/scripts/genome-refresh-worker.ts +364 -0
- package/scripts/genome-rewrap.ts +90 -0
- package/scripts/genome-synthesizer.ts +679 -0
- package/scripts/genome-team-init.ts +312 -0
- package/scripts/handoff-pack.ts +438 -0
- package/scripts/hook-bootstrap.mjs +75 -0
- package/scripts/hook-timing-reader.ts +371 -0
- package/scripts/hook-timings-report.ts +554 -0
- package/scripts/install-genome-hooks.ts +196 -0
- package/scripts/install-onnx-model.ts +154 -0
- package/scripts/install-permissions.ts +276 -0
- package/scripts/install-status-line.ts +150 -0
- package/scripts/mcp-entrypoint.sh +78 -0
- package/scripts/mcp-entrypoint.ts +130 -0
- package/scripts/mdx-angle-bracket-lint.ts +152 -0
- package/scripts/measure-cold-start.ts +126 -0
- package/scripts/migrate-stats-to-sqlite.ts +86 -0
- package/scripts/ollama-setup.ts +498 -0
- package/scripts/onboarding-wizard.ts +1691 -0
- package/scripts/orchestrate-emit-telemetry.ts +177 -0
- package/scripts/orchestrate-expand.ts +517 -0
- package/scripts/orchestrate-run.ts +744 -0
- package/scripts/print-legend.ts +50 -0
- package/scripts/product-metadata.ts +38 -0
- package/scripts/prune-old-memories.ts +208 -0
- package/scripts/publish.sh +88 -0
- package/scripts/read-calibration.ts +122 -0
- package/scripts/report-crash.ts +226 -0
- package/scripts/run-benchmark.ts +750 -0
- package/scripts/run-root-tests.ts +28 -0
- package/scripts/savings-dashboard.ts +1258 -0
- package/scripts/savings-report-extras.ts +447 -0
- package/scripts/savings-status-line.ts +873 -0
- package/scripts/session-event-emit.ts +266 -0
- package/scripts/session-greet.ts +686 -0
- package/scripts/session-log-report.ts +551 -0
- package/scripts/session-resume.ts +614 -0
- package/scripts/set-hook-mode.ts +83 -0
- package/scripts/smoke-cross-platform.ts +117 -0
- package/scripts/smoke-realtime.ts +257 -0
- package/scripts/smoke-tools.ts +21 -0
- package/scripts/stats-cloud-pull.ts +213 -0
- package/scripts/stats-cloud-sync.ts +261 -0
- package/scripts/telemetry-flush.ts +160 -0
- package/scripts/telemetry-status.ts +266 -0
- package/scripts/timing-budget.ts +35 -0
- package/scripts/ui-animation.ts +120 -0
- package/scripts/ui.ts +431 -0
- package/scripts/upgrade-flow.ts +775 -0
- package/scripts/weekly-digest.ts +394 -0
- package/servers/_accounting.ts +78 -0
- package/servers/_ask-router.ts +84 -0
- package/servers/_ast-chunker.ts +434 -0
- package/servers/_ast-helpers.ts +183 -0
- package/servers/_ast-languages.ts +153 -0
- package/servers/_ast-refactor/_shared.ts +221 -0
- package/servers/_ast-refactor/cross-file-rename.ts +560 -0
- package/servers/_ast-refactor/extract-function.ts +357 -0
- package/servers/_ast-refactor/file-local-rename.ts +172 -0
- package/servers/_ast-refactor.ts +41 -0
- package/servers/_ast-skeleton.ts +107 -0
- package/servers/_bash-summarizers-registry.ts +1096 -0
- package/servers/_crash-dump.ts +210 -0
- package/servers/_cwd-clamp.ts +342 -0
- package/servers/_edit-log.ts +28 -0
- package/servers/_edit-match.ts +236 -0
- package/servers/_edit-validate.ts +196 -0
- package/servers/_embed-calibration.ts +123 -0
- package/servers/_embedding-cache.ts +401 -0
- package/servers/_embedding-model.ts +329 -0
- package/servers/_events.ts +113 -0
- package/servers/_genome-cache.ts +154 -0
- package/servers/_genome-commits.ts +172 -0
- package/servers/_genome-crypto-v2.ts +242 -0
- package/servers/_genome-crypto.ts +259 -0
- package/servers/_genome-discoveries.ts +140 -0
- package/servers/_genome-embed-populator.ts +216 -0
- package/servers/_genome-freshness.ts +134 -0
- package/servers/_genome-issues.ts +171 -0
- package/servers/_genome-live.ts +263 -0
- package/servers/_genome-prs.ts +188 -0
- package/servers/_genome-search.ts +479 -0
- package/servers/_genome-sync.ts +297 -0
- package/servers/_history-tracker.ts +279 -0
- package/servers/_http-helpers.ts +151 -0
- package/servers/_identity-hash.ts +151 -0
- package/servers/_llm-providers/anthropic.ts +132 -0
- package/servers/_llm-providers/cloud.ts +195 -0
- package/servers/_llm-providers/index.ts +350 -0
- package/servers/_llm-providers/local.ts +127 -0
- package/servers/_llm-providers/onnx.ts +393 -0
- package/servers/_llm-providers/types.ts +27 -0
- package/servers/_manifest-v2.ts +447 -0
- package/servers/_mcp-host.ts +93 -0
- package/servers/_nudge-events.ts +451 -0
- package/servers/_orchestrate-executor.ts +316 -0
- package/servers/_prefetch.ts +435 -0
- package/servers/_pricing.ts +256 -0
- package/servers/_pro.ts +381 -0
- package/servers/_read-cache.ts +44 -0
- package/servers/_router-handlers.ts +46 -0
- package/servers/_router.ts +55 -0
- package/servers/_run-with-timeout.ts +173 -0
- package/servers/_savings-render.ts +214 -0
- package/servers/_stats-sqlite.ts +640 -0
- package/servers/_stats.ts +1183 -0
- package/servers/_status-line-cells.ts +469 -0
- package/servers/_streaks.ts +162 -0
- package/servers/_summarize.ts +208 -0
- package/servers/_task-graph-render.ts +217 -0
- package/servers/_task-graph.ts +545 -0
- package/servers/_telemetry.ts +719 -0
- package/servers/_test-parsers.ts +530 -0
- package/servers/_test-watch.ts +626 -0
- package/servers/_text-helpers.ts +37 -0
- package/servers/_token-measure.ts +160 -0
- package/servers/_tool-base.ts +248 -0
- package/servers/_weekly-digest.ts +391 -0
- package/servers/ask-server-handlers.ts +49 -0
- package/servers/ask-server.ts +174 -0
- package/servers/bash-server-handlers.ts +138 -0
- package/servers/bash-server.ts +1136 -0
- package/servers/bench.ts +186 -0
- package/servers/diff-semantic-server-handlers.ts +39 -0
- package/servers/diff-semantic-server.ts +566 -0
- package/servers/diff-server-handlers.ts +317 -0
- package/servers/diff-server.ts +20 -0
- package/servers/edit-server-handlers.ts +31 -0
- package/servers/edit-server.ts +209 -0
- package/servers/edit-structural-server-handlers.ts +322 -0
- package/servers/efficiency-server-handlers.ts +161 -0
- package/servers/efficiency-server.ts +1135 -0
- package/servers/flush-server-handlers.ts +21 -0
- package/servers/flush-server.ts +19 -0
- package/servers/genome-server-handlers.ts +118 -0
- package/servers/genome-server.ts +397 -0
- package/servers/github-server-handlers.ts +187 -0
- package/servers/github-server.ts +856 -0
- package/servers/glob-server-handlers.ts +233 -0
- package/servers/glob-server.ts +20 -0
- package/servers/grep-server-handlers.ts +61 -0
- package/servers/grep-server.ts +564 -0
- package/servers/http-server-handlers.ts +36 -0
- package/servers/http-server.ts +149 -0
- package/servers/logs-server-handlers.ts +42 -0
- package/servers/logs-server.ts +359 -0
- package/servers/ls-server-handlers.ts +166 -0
- package/servers/ls-server.ts +20 -0
- package/servers/multi-edit-server-handlers.ts +51 -0
- package/servers/multi-edit-server.ts +422 -0
- package/servers/notebook-edit-server-handlers.ts +34 -0
- package/servers/notebook-edit-server.ts +181 -0
- package/servers/orient-server-handlers.ts +52 -0
- package/servers/orient-server.ts +436 -0
- package/servers/pipe-server-handlers.ts +68 -0
- package/servers/pipe-server.ts +300 -0
- package/servers/read-server-handlers.ts +42 -0
- package/servers/read-server.ts +206 -0
- package/servers/rename-file-server-handlers.ts +67 -0
- package/servers/rename-file-server.ts +699 -0
- package/servers/savings-server-handlers.ts +27 -0
- package/servers/savings-server.ts +54 -0
- package/servers/search-replace-regex-server-handlers.ts +96 -0
- package/servers/search-replace-regex-server.ts +751 -0
- package/servers/sql-server-handlers.ts +58 -0
- package/servers/sql-server.ts +505 -0
- package/servers/task-server-handlers.ts +358 -0
- package/servers/task-server.ts +24 -0
- package/servers/test-server-handlers.ts +351 -0
- package/servers/test-server.ts +20 -0
- package/servers/tree-server-handlers.ts +503 -0
- package/servers/tree-server.ts +20 -0
- package/servers/webfetch-server-handlers.ts +166 -0
- package/servers/webfetch-server.ts +20 -0
- package/servers/websearch-server-handlers.ts +215 -0
- package/servers/websearch-server.ts +19 -0
- package/servers/write-server-handlers.ts +27 -0
- package/servers/write-server.ts +97 -0
- package/skills/ashlr-brief/SKILL.md +80 -0
- package/skills/ashlr-codex-doctor/SKILL.md +21 -0
- package/skills/ashlr-codex-efficient-tools/SKILL.md +17 -0
- package/skills/ashlr-codex-genome-refresh/SKILL.md +20 -0
- package/skills/ashlr-codex-parallel-explore/SKILL.md +20 -0
- package/skills/ashlr-codex-savings/SKILL.md +17 -0
- package/skills/ashlr-cost-refactor/SKILL.md +50 -0
- package/skills/ashlr-efficient/SKILL.md +64 -0
- package/skills/ashlr-genome-author/SKILL.md +43 -0
- package/skills/ashlr-lean-tools/SKILL.md +43 -0
- package/skills/ashlr-search/SKILL.md +46 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Multi-Turn Recompression Architecture
|
|
2
|
+
|
|
3
|
+
## Phase 1: What Claude Code Exposes to Plugins
|
|
4
|
+
|
|
5
|
+
### Hooks Available
|
|
6
|
+
|
|
7
|
+
Claude Code's plugin hook system (as of v1.25 investigation, April 2026) exposes four hook events:
|
|
8
|
+
|
|
9
|
+
| Hook | When it fires | Plugin sees |
|
|
10
|
+
|------|---------------|-------------|
|
|
11
|
+
| `SessionStart` | Once at session open | stdin: `{}` (no payload). `CLAUDE_PROJECT_DIR`, `CLAUDE_SESSION_ID`, `CLAUDE_PLUGIN_ROOT` via env. |
|
|
12
|
+
| `PreToolUse` | Before every tool call | stdin: `{ tool_name, tool_input }` |
|
|
13
|
+
| `PostToolUse` | After every tool call | stdin: `{ tool_name, tool_input, tool_result }` |
|
|
14
|
+
| `SessionEnd` | Once at session close | stdin: `{}` |
|
|
15
|
+
|
|
16
|
+
### What's NOT Exposed
|
|
17
|
+
|
|
18
|
+
**Critical finding: no `PreCompletion` / `PreModel` hook exists.**
|
|
19
|
+
|
|
20
|
+
Claude Code does NOT expose:
|
|
21
|
+
- A hook that fires before the LLM is invoked with the full conversation.
|
|
22
|
+
- The conversation history (prior turns' messages, tool results, assistant text).
|
|
23
|
+
- Any `prompts/list` MCP surface with history-aware context.
|
|
24
|
+
- A hook that can mutate or summarize the in-flight context window before model invocation.
|
|
25
|
+
- Total token count for the current context.
|
|
26
|
+
|
|
27
|
+
The only writable surface is `additionalContext` in `PostToolUse` and `SessionStart` responses, which is appended (never replaces) the context window.
|
|
28
|
+
|
|
29
|
+
### What IS Possible as Pure Plugin Code
|
|
30
|
+
|
|
31
|
+
1. **Result size tracking**: `PostToolUse` provides `tool_result` content, so we can measure every tool result's byte size as it leaves the hook.
|
|
32
|
+
2. **Per-turn freshness modeling**: Since we know when each result was emitted (by recording it at `PostToolUse` time), we can estimate staleness by counting subsequent tool calls.
|
|
33
|
+
3. **Nudge injection**: `additionalContext` from `PostToolUse` is injected into the agent's next turn context — not the full history, but visible to the model in the next request.
|
|
34
|
+
4. **Session-scoped JSONL log**: `~/.ashlr/session-history/<sessionId>.jsonl` can store a running record of every ashlr tool result emitted, enabling staleness queries at any later point in the session.
|
|
35
|
+
|
|
36
|
+
### The Fundamental Gap
|
|
37
|
+
|
|
38
|
+
A true "stale result rewrite" would require intercepting the conversation array that Claude Code assembles before sending to Anthropic. This array includes all prior tool results verbatim. Without a `PreModel` hook that exposes and allows mutation of this array, the plugin cannot truncate or summarize old results.
|
|
39
|
+
|
|
40
|
+
**Verdict: Phase 3 (true rewrite) is NOT possible with current Claude Code.** The 20-40% savings estimate is contingent on Anthropic exposing a `PreModel` hook in a future release. Until then, the plugin can deliver 5-10% improvement through visibility + user-driven recompression (Phase 2).
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Phase 2: What We Build Now
|
|
45
|
+
|
|
46
|
+
### Architecture Overview
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
PostToolUse (any ashlr__* or Read/Grep call)
|
|
50
|
+
└─> posttooluse-stale-result.ts
|
|
51
|
+
├── writes to servers/_history-tracker.ts
|
|
52
|
+
│ └── ~/.ashlr/session-history/<sessionId>.jsonl
|
|
53
|
+
└── checks stale byte threshold
|
|
54
|
+
└── if >50KB stale → additionalContext nudge (once/session)
|
|
55
|
+
|
|
56
|
+
/ashlr-compact (slash command)
|
|
57
|
+
└─> reads session-history JSONL
|
|
58
|
+
└─> identifies results >5 turns old
|
|
59
|
+
└─> prints savings estimate to user
|
|
60
|
+
└─> injects additionalContext to re-run stale reads
|
|
61
|
+
|
|
62
|
+
orient-nudge-hook.ts (extended)
|
|
63
|
+
└─> checks stale result total
|
|
64
|
+
└─> injects stale-accumulation nudge (once/session, threshold 50KB)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Freshness Decay Model
|
|
68
|
+
|
|
69
|
+
Turn delta is measured in subsequent tool calls (not wall-clock time) because "turns" in LLM context are tool-call boundaries.
|
|
70
|
+
|
|
71
|
+
| Turns since result emitted | Freshness score |
|
|
72
|
+
|---------------------------|-----------------|
|
|
73
|
+
| 0–4 | 1.0 (fresh) |
|
|
74
|
+
| 5–14 | 0.5 (stale) |
|
|
75
|
+
| 15+ | 0.2 (very stale) |
|
|
76
|
+
|
|
77
|
+
These starting coefficients are intentionally conservative. v1.26 will tune via telemetry from `multi_turn_stale_estimate` events.
|
|
78
|
+
|
|
79
|
+
### Session ID Strategy
|
|
80
|
+
|
|
81
|
+
Uses `CLAUDE_SESSION_ID` (available in hook env) when present, falling back to the same `derivedSessionId` pattern established in `session-start.ts`. This ensures history files match across PostToolUse calls within the same session.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Phase 3: What's Needed from Claude Code
|
|
86
|
+
|
|
87
|
+
For true conversation-history recompression, Anthropic would need to add a `PreModel` hook with:
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
// Hypothetical future hook contract
|
|
91
|
+
interface PreModelPayload {
|
|
92
|
+
messages: ConversationMessage[]; // full history
|
|
93
|
+
systemPrompt: string;
|
|
94
|
+
}
|
|
95
|
+
interface PreModelOutput {
|
|
96
|
+
messages?: ConversationMessage[]; // mutated history (plugin can compress)
|
|
97
|
+
additionalSystemContext?: string;
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
With this, the plugin could:
|
|
102
|
+
1. Walk the `messages` array and find `tool_result` entries from ashlr tools.
|
|
103
|
+
2. For results older than N turns with no downstream references, replace the content with a stub: `"[ashlr: result summarized — N bytes removed]"`.
|
|
104
|
+
3. Return the compressed message array.
|
|
105
|
+
|
|
106
|
+
Estimated impact once available: 20-40% context reduction on sessions with >20 turns of file-heavy work.
|
|
107
|
+
|
|
108
|
+
**Request to Anthropic**: add a `PreModel` hook that provides the full `messages` array and allows returning a mutated copy.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Deployment Guide
|
|
2
|
+
|
|
3
|
+
## Environment Variables
|
|
4
|
+
|
|
5
|
+
### Required for boot — server will not start without these
|
|
6
|
+
|
|
7
|
+
| Variable | What it does | Default when unset | How to get |
|
|
8
|
+
|---|---|---|---|
|
|
9
|
+
| `DATABASE_URL` | *(reserved — SQLite path uses `ASHLR_DB_PATH`)* | — | n/a |
|
|
10
|
+
| `ASHLR_DB_PATH` | Absolute path to the SQLite `.db` file | `server/ashlr.db` (sibling of `src/`) | Set to a persistent volume path in production (e.g. `/data/ashlr.db`) |
|
|
11
|
+
| `ASHLR_MASTER_KEY` | AES-256-GCM master key for encrypting secrets at rest (GitHub OAuth tokens, genome DEKs). Must decode to exactly 32 bytes base64. | Throws in production. Dev: set `ASHLR_MASTER_KEY_DEV=1` for an ephemeral key. | `node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"` |
|
|
12
|
+
|
|
13
|
+
### Required for features — server starts but feature degrades without these
|
|
14
|
+
|
|
15
|
+
| Variable | What it does | Default when unset |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| `SENDGRID_API_KEY` | Sends transactional email (magic-link auth, weekly digest, status alerts). | Email is silently skipped; log line emitted. |
|
|
18
|
+
| `STRIPE_SECRET_KEY` | Stripe API client for checkout sessions, portal, subscription management. | `getStripeClient()` throws; billing routes 500. |
|
|
19
|
+
| `STRIPE_WEBHOOK_SECRET` | Verifies Stripe webhook HMAC signatures (`/webhooks/stripe`). | Webhook handler returns 400 on every event. |
|
|
20
|
+
| `GITHUB_CLIENT_ID` | GitHub OAuth app client ID for `/auth/github/start` and scope-upgrade flow. | GitHub OAuth endpoints return 500. |
|
|
21
|
+
| `GITHUB_CLIENT_SECRET` | GitHub OAuth app client secret. | Same as above. |
|
|
22
|
+
| `GITHUB_WEBHOOK_SECRET` | HMAC secret for validating GitHub push webhooks (`/webhooks/github`). | Webhook rejected with 400. |
|
|
23
|
+
| `SENTRY_DSN` | Sentry error-reporting DSN. | No-op; errors are still logged via pino. |
|
|
24
|
+
|
|
25
|
+
### Optional / overrides — have safe defaults
|
|
26
|
+
|
|
27
|
+
| Variable | What it does | Default |
|
|
28
|
+
|---|---|---|
|
|
29
|
+
| `PORT` | HTTP listen port. | `3001` |
|
|
30
|
+
| `NODE_ENV` | Controls pino pretty-print (`development`) vs JSON (`production`). | `development` |
|
|
31
|
+
| `LOG_LEVEL` | pino log level (`trace`, `debug`, `info`, `warn`, `error`). | `debug` in dev, `info` in production. |
|
|
32
|
+
| `BASE_URL` | Public API base URL, used in OAuth redirect URIs and Stripe callback URLs. | `https://api.ashlr.ai` |
|
|
33
|
+
| `SITE_URL` | Public site URL for Stripe cancel/return redirects. | `https://plugin.ashlr.ai` |
|
|
34
|
+
| `FRONTEND_URL` | Frontend app URL for GitHub OAuth callback redirects. | `https://plugin.ashlr.ai` |
|
|
35
|
+
| `ASHLR_SITE_URL` | Used by the weekly-digest cron for unsubscribe link base. | `https://plugin.ashlr.ai` |
|
|
36
|
+
| `STATUS_BASE_URL` | Base URL for status page links. | `https://status.ashlr.ai` |
|
|
37
|
+
| `API_BASE_URL` | API base for health-check worker synthetic probes. | `https://api.ashlr.ai` |
|
|
38
|
+
| `PLUGIN_BASE_URL` | Plugin CDN base for health-check worker probes. | `https://plugin.ashlr.ai` |
|
|
39
|
+
| `DOCS_BASE_URL` | Docs base for health-check worker probes. | `https://docs.ashlr.ai` |
|
|
40
|
+
| `ASHLR_DISABLE_TRIAL` | Set to `"1"` to disable free-trial eligibility on new Pro checkouts. | Trial enabled. |
|
|
41
|
+
| `ASHLR_MASTER_KEY_DEV` | Set to `"1"` to use an ephemeral (non-persistent) master key. Dev/test only. | Off. |
|
|
42
|
+
| `METRICS_USER` | HTTP Basic auth username for the `/metrics` endpoint. | Endpoint open to all IPs. |
|
|
43
|
+
| `METRICS_PASS` | HTTP Basic auth password for the `/metrics` endpoint. | — |
|
|
44
|
+
| `METRICS_ALLOWED_IPS` | Comma-separated IPs allowed to scrape `/metrics`. | All IPs allowed. |
|
|
45
|
+
| `SENTRY_ORG` | Sentry org slug for source-map upload in CI. | — |
|
|
46
|
+
| `SENTRY_PROJECT` | Sentry project slug for source-map upload in CI. | — |
|
|
47
|
+
| `SENTRY_INTERNAL_TOKEN` | Sentry auth token for source-map upload CLI in CI. | — |
|
|
48
|
+
| `TESTING` | Set to `"1"` by the test harness. Enables Stripe stub client and skips real email sends. | Off. |
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Deployment Checklist
|
|
53
|
+
|
|
54
|
+
### Secrets
|
|
55
|
+
|
|
56
|
+
- [ ] `ASHLR_MASTER_KEY` set to a fresh 32-byte base64 secret — **NOT the dev default**
|
|
57
|
+
- [ ] `SENDGRID_API_KEY` set (required for magic-link login and weekly digest)
|
|
58
|
+
- [ ] `STRIPE_SECRET_KEY` set (live key for production, test key for staging)
|
|
59
|
+
- [ ] `STRIPE_WEBHOOK_SECRET` set and Stripe webhook configured to POST to `https://<host>/webhooks/stripe`
|
|
60
|
+
- [ ] `GITHUB_CLIENT_ID` + `GITHUB_CLIENT_SECRET` set (GitHub OAuth App, callback URL: `https://<host>/auth/github/callback`)
|
|
61
|
+
- [ ] `GITHUB_WEBHOOK_SECRET` set and GitHub webhook configured on any repos using genome auto-build
|
|
62
|
+
|
|
63
|
+
### Infrastructure
|
|
64
|
+
|
|
65
|
+
- [ ] `ASHLR_DB_PATH` points to a persistent volume (not ephemeral container storage)
|
|
66
|
+
- [ ] Persistent volume backed up (SQLite WAL — snapshot the `.db` file and `-wal`/`-shm` when idle, or use Litestream)
|
|
67
|
+
- [ ] `PORT` set (or load balancer configured for default `3001`)
|
|
68
|
+
- [ ] `NODE_ENV=production` — enables JSON logging
|
|
69
|
+
|
|
70
|
+
### Observability
|
|
71
|
+
|
|
72
|
+
- [ ] `SENTRY_DSN` set — error tracking active (see `docs/operations/error-monitoring.md`)
|
|
73
|
+
- [ ] `LOG_LEVEL` set (recommend `info` for production)
|
|
74
|
+
- [ ] Metrics scraper configured — set `METRICS_USER`/`METRICS_PASS` or `METRICS_ALLOWED_IPS`, point Prometheus at `/metrics`
|
|
75
|
+
- [ ] `/healthz` returns `200` from the deployed instance
|
|
76
|
+
- [ ] `/readyz` returns `200` (confirms SQLite is reachable)
|
|
77
|
+
|
|
78
|
+
### CI / Cron
|
|
79
|
+
|
|
80
|
+
- [ ] `SENTRY_ORG`, `SENTRY_PROJECT`, `SENTRY_INTERNAL_TOKEN` added to GitHub Actions secrets (for source-map upload)
|
|
81
|
+
- [ ] Weekly-digest cron scheduled (GitHub Actions or Render Cron: `0 14 * * 0` → `bun server/src/jobs/weekly-digest-cron.ts`)
|
|
82
|
+
- [ ] Cron environment variables include `ASHLR_DB_PATH`, `ASHLR_MASTER_KEY`, `SENDGRID_API_KEY`, `ASHLR_SITE_URL`
|
|
83
|
+
|
|
84
|
+
### DNS / TLS
|
|
85
|
+
|
|
86
|
+
- [ ] TLS termination in place (reverse proxy or platform-managed)
|
|
87
|
+
- [ ] CORS origin list reviewed (`BASE_URL`, `FRONTEND_URL`)
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Running Migrations
|
|
92
|
+
|
|
93
|
+
Migrations run automatically on every server boot via `getDb()` in `server/src/db/connection.ts`. They are fully idempotent — safe to re-run on a running DB.
|
|
94
|
+
|
|
95
|
+
For CI pipelines, pre-deploy verification, or dry-run checks before a production deploy, use the migration CLI:
|
|
96
|
+
|
|
97
|
+
```sh
|
|
98
|
+
# Check what migrations are pending without applying them (exits 1 if any pending)
|
|
99
|
+
bun server/src/db/migrate.ts --check
|
|
100
|
+
|
|
101
|
+
# Apply all pending migrations (safe to run multiple times)
|
|
102
|
+
bun server/src/db/migrate.ts
|
|
103
|
+
|
|
104
|
+
# Target a specific DB file
|
|
105
|
+
bun server/src/db/migrate.ts --db /data/ashlr.db
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The CLI reports each migration step and exits `0` when up-to-date, `1` if `--check` found pending migrations.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Error Monitoring
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Error monitoring is handled by `server/src/lib/sentry.ts`. Sentry is optional — the integration is a no-op when `SENTRY_DSN` is unset (local dev, tests). All errors are always logged via pino structured logs regardless.
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
### Environment variables
|
|
10
|
+
|
|
11
|
+
| Variable | Purpose |
|
|
12
|
+
|---|---|
|
|
13
|
+
| `SENTRY_DSN` | Sentry DSN — obtainable from Sentry project settings → Client Keys. When absent, the module is never imported. |
|
|
14
|
+
| `SENTRY_ORG` | Org slug for `sentry-cli` source-map upload in CI. |
|
|
15
|
+
| `SENTRY_PROJECT` | Project slug for source-map upload in CI. |
|
|
16
|
+
| `SENTRY_INTERNAL_TOKEN` | Auth token for `sentry-cli` in CI (GitHub Actions secret). |
|
|
17
|
+
|
|
18
|
+
### Initialization
|
|
19
|
+
|
|
20
|
+
`initSentry(release?)` is called once at the top of `server/src/index.ts` before any routes are mounted. It reads `SENTRY_DSN` and, if present, dynamically imports `@sentry/bun` to avoid any side-effects in DSN-less environments (tests, local dev).
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
initSentry(`ashlr-server@${pluginVersion}`);
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The `release` tag is set to `ashlr-server@<version>` read from `plugin.json`. This enables source-map lookup in Sentry for each deployed version.
|
|
27
|
+
|
|
28
|
+
### Error handler
|
|
29
|
+
|
|
30
|
+
`sentryErrorHandler` is mounted as Hono's `onError` hook (last in the chain):
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
app.onError(sentryErrorHandler);
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
It captures the exception with request metadata (method, path, x-request-id, user_id) and always returns `{"error": "Internal server error"}` with status 500.
|
|
37
|
+
|
|
38
|
+
### Manual capture
|
|
39
|
+
|
|
40
|
+
Use `captureException(err, extras?)` from `server/src/lib/sentry.ts` for non-HTTP errors (cron jobs, background workers):
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { captureException } from "../lib/sentry.js";
|
|
44
|
+
captureException(err, { job: "weekly-digest", userId });
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## PII Redaction
|
|
48
|
+
|
|
49
|
+
Events are scrubbed before send via `beforeSend`. The following keys are redacted in the full event payload:
|
|
50
|
+
|
|
51
|
+
- `text`, `systemPrompt` — LLM content
|
|
52
|
+
- `email`, `authorization`, `cookie`, `password` — credentials and identity
|
|
53
|
+
|
|
54
|
+
The redactor does a deep JSON walk so nested occurrences are caught. Log extras passed to `captureException` are also scoped — never include raw email addresses, full URLs with tokens, or unhashed session IDs in the `extras` argument.
|
|
55
|
+
|
|
56
|
+
**Policy**: never pass raw `email` strings in extras. Use `user_id` (opaque UUID) instead. Never include `authorization` header values or Stripe/GitHub secrets in error context.
|
|
57
|
+
|
|
58
|
+
## Accessing dashboards
|
|
59
|
+
|
|
60
|
+
- Project: `https://sentry.io/organizations/<SENTRY_ORG>/projects/<SENTRY_PROJECT>/`
|
|
61
|
+
- Issues: filter by `release:ashlr-server@<version>` to scope to a specific deploy.
|
|
62
|
+
- Recommended alert: notify on first occurrence of any new issue with `level:error`.
|
|
63
|
+
|
|
64
|
+
## Trace sampling
|
|
65
|
+
|
|
66
|
+
`tracesSampleRate` is set to `0.1` (10%). Increase for debugging high-traffic paths; decrease or set to `0` in cost-sensitive environments.
|
|
67
|
+
|
|
68
|
+
## Fallback: pino logs
|
|
69
|
+
|
|
70
|
+
When Sentry is not configured, all exceptions still surface in pino JSON logs. In production, pipe logs to your preferred log aggregator (Datadog, Logtail, CloudWatch). The structured fields on every error log include `requestId`, `method`, `path`, and `user_id`.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Weekly Digest — Operations Guide
|
|
2
|
+
|
|
3
|
+
## Schedule
|
|
4
|
+
|
|
5
|
+
Runs every **Sunday at 14:00 UTC** via GitHub Actions (`.github/workflows/weekly-digest.yml`).
|
|
6
|
+
|
|
7
|
+
Eligible recipients: Pro and Team tier users with `weekly_digest_opt_in = 1` who have not received a digest in the last 6 days (dedupe window prevents double-sends on retries).
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Manual trigger
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Production send (requires repo write access)
|
|
15
|
+
gh workflow run weekly-digest.yml --ref main
|
|
16
|
+
|
|
17
|
+
# Dry-run (renders emails, no sends, no DB writes)
|
|
18
|
+
gh workflow run weekly-digest.yml --ref main -f dry_run=true
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Or via GitHub UI: **Actions → Weekly Digest → Run workflow**.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Local dry-run
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
cd server
|
|
29
|
+
ASHLR_MASTER_KEY=<key> SENDGRID_API_KEY=<key> DATABASE_URL=<url> \
|
|
30
|
+
bun src/jobs/weekly-digest-cron.ts --dry-run
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
No emails are sent; rendered output is written to stderr.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Debugging a failed run
|
|
38
|
+
|
|
39
|
+
1. **GitHub Actions logs** — go to Actions → Weekly Digest → failed run. The job streams structured pino JSON; search for `"event":"cron_end"` to see final counts, or `"event":"cron_start"` to confirm the job started.
|
|
40
|
+
|
|
41
|
+
2. **Key log lines to look for:**
|
|
42
|
+
|
|
43
|
+
| Field | Meaning |
|
|
44
|
+
|-------|---------|
|
|
45
|
+
| `event: "cron_start"` | Job began, includes `dryRun` flag |
|
|
46
|
+
| `event: "cron_end"` | Job finished; `sent`, `skipped`, `failed`, `durationMs` |
|
|
47
|
+
| `weekly-digest: failed for user` | Per-user error with `userId` and `err` |
|
|
48
|
+
|
|
49
|
+
3. **Partial failure is safe** — users whose send failed are not marked as sent in the DB, so the next scheduled run retries them automatically.
|
|
50
|
+
|
|
51
|
+
4. **Re-running manually** — trigger via `gh workflow run` above. The 6-day dedupe window means already-sent users are skipped; only failed/missed users receive the email.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Failure visibility
|
|
56
|
+
|
|
57
|
+
GitHub Actions emails the repo owner on any job failure by default. No additional configuration needed.
|
|
58
|
+
|
|
59
|
+
To add Slack/PagerDuty alerts, add a notification step at the end of the `send` job in `.github/workflows/weekly-digest.yml`.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## User opt-out
|
|
64
|
+
|
|
65
|
+
Users can unsubscribe via:
|
|
66
|
+
|
|
67
|
+
- **Unsubscribe link** in every digest email → `GET /unsubscribe?token=<signed-token>` → sets `weekly_digest_opt_in = 0`
|
|
68
|
+
- **Email preferences API** → `GET/POST /api/email-prefs` (see `docs/email-templates.md` for the full unsubscribe flow)
|
|
69
|
+
|
|
70
|
+
Opted-out users are excluded at query time; no re-opt-in happens automatically.
|