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
package/commands/goal.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: goal
|
|
3
|
+
description: Create a goal, decompose it into milestones, and advance the next one as a sandboxed proposal-only run.
|
|
4
|
+
argument-hint: '"<objective>" [--project <repo>] [--allow-cloud] [--plan-only] [--direct]'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Registers an objective with the ashlr fleet, plans it into milestones, and runs
|
|
8
|
+
the next one sandboxed — filing a **PENDING** inbox proposal. Nothing is applied
|
|
9
|
+
until you review and accept via `ashlr inbox`.
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
/goal "<objective>" [--project <repo>] [--allow-cloud] [--plan-only] [--direct]
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Flags:
|
|
18
|
+
|
|
19
|
+
- `--project <repo>` — target repo path (required with `--direct`; optional otherwise)
|
|
20
|
+
- `--allow-cloud` — permit cloud-tier backends for the sandboxed run
|
|
21
|
+
- `--plan-only` — stop after milestone planning; do not advance yet
|
|
22
|
+
- `--direct` — skip milestone decomposition; run the objective verbatim as a
|
|
23
|
+
single sandboxed frontier-engine run (same dispatch path as the daemon).
|
|
24
|
+
Requires `--project`.
|
|
25
|
+
|
|
26
|
+
## Steps
|
|
27
|
+
|
|
28
|
+
### If `$ARGUMENTS` is empty
|
|
29
|
+
|
|
30
|
+
Print the following and stop:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
Usage: ashlr goal "<objective>" [--project <repo>] [--allow-cloud] [--plan-only] [--direct]
|
|
34
|
+
|
|
35
|
+
Create a goal, plan it into milestones, and advance the next one as a
|
|
36
|
+
sandboxed, PROPOSAL-ONLY run (review it via `ashlr inbox`). Routed across
|
|
37
|
+
the polyglot backend roster by capability + trust tier.
|
|
38
|
+
|
|
39
|
+
--direct Skip milestone decomposition. Run the objective verbatim as a
|
|
40
|
+
SINGLE sandboxed proposal-only frontier-engine run (same path as
|
|
41
|
+
the daemon's non-builtin dispatch). Requires --project.
|
|
42
|
+
Ideal for concrete tasks that need no Design->Implement->Test split.
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Otherwise
|
|
46
|
+
|
|
47
|
+
Run the following Bash command and relay its output verbatim:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
ashlr goal $ARGUMENTS
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
After the command completes, if a proposal ID appears in the output, relay it
|
|
54
|
+
and add exactly one reminder line:
|
|
55
|
+
|
|
56
|
+
> Review the proposal with `ashlr inbox` — nothing was applied to the working tree.
|
|
57
|
+
|
|
58
|
+
No preamble, no trailing summary beyond the above reminder.
|
package/commands/loop.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: loop
|
|
3
|
+
description: Run the goal-aware fleet conductor over every enrolled repo — one tick (default) or continuous.
|
|
4
|
+
argument-hint: "[--watch] [--dry-run]"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Runs the ashlr fleet conductor over every enrolled repo: discovers work, routes
|
|
8
|
+
each item across the polyglot backend roster by trust tier, runs it sandboxed,
|
|
9
|
+
and files **PENDING** inbox proposals. Default is one tick (safe — will not hang
|
|
10
|
+
the terminal). Nothing is applied until you review via `ashlr inbox`.
|
|
11
|
+
|
|
12
|
+
The conductor is **goal-aware**: active goals are prioritised over the general
|
|
13
|
+
backlog. The kill-switch (`~/.ashlr/KILL`) and daily budget are respected;
|
|
14
|
+
auto-merge and intelligence posture are read from your config at runtime.
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
/loop [--watch] [--dry-run]
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Flags:
|
|
23
|
+
|
|
24
|
+
- `--watch` — run the continuous loop (Ctrl-C to stop). Default: one tick.
|
|
25
|
+
- `--dry-run` — simulate work discovery and routing without spawning any engine runs.
|
|
26
|
+
|
|
27
|
+
## Steps
|
|
28
|
+
|
|
29
|
+
Run the following Bash command and relay its output verbatim:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
ashlr loop $ARGUMENTS
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
After the command completes, relay the final summary line from the output and
|
|
36
|
+
add exactly one reminder line:
|
|
37
|
+
|
|
38
|
+
> Any proposals filed await review in `ashlr inbox` — nothing was applied.
|
|
39
|
+
|
|
40
|
+
No preamble, no trailing summary beyond the above reminder.
|
package/docs/CNAME
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
plugin.ashlr.ai
|
package/docs/PRO_TIER.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# ashlr Pro — Your Team Learns Together
|
|
2
|
+
|
|
3
|
+
_Version: v1.31.0 · Updated: 2026-05-08_
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## The core idea
|
|
8
|
+
|
|
9
|
+
Free ashlr builds a genome that lives on your machine. Every session starts
|
|
10
|
+
from context you've already derived — but it's yours alone. The moment a team
|
|
11
|
+
forms, everyone re-derives the same codebase patterns from scratch.
|
|
12
|
+
|
|
13
|
+
Pro solves this. The genome becomes a shared, encrypted, versioned layer every
|
|
14
|
+
teammate retrieves from. One engineer's grep hit — a tricky auth flow, an
|
|
15
|
+
undocumented API edge case — becomes context for everyone who touches that code
|
|
16
|
+
next. New engineers onboard into accumulated knowledge, not silence.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Pro ($12/mo or $120/yr) — individual cloud
|
|
21
|
+
|
|
22
|
+
- **Cross-machine sync** — savings ledger, streak counter, and `/ashlr-dashboard`
|
|
23
|
+
follow you across machines automatically.
|
|
24
|
+
- **Cloud LLM summarizer** — `ashlr__read` and genome summarization run on
|
|
25
|
+
hosted Haiku. No local Ollama or GPU required.
|
|
26
|
+
- **Hosted embedding retrieval** — `ashlr__grep` uses a cloud pgvector index
|
|
27
|
+
refreshed on every push. Materially better recall on repos with > 5,000 files.
|
|
28
|
+
- **Weekly digest** — a personal summary of learnings, top tools, and streak
|
|
29
|
+
milestones via `/ashlr-resume`.
|
|
30
|
+
- **7-day free trial on first checkout** — no charge until the trial ends,
|
|
31
|
+
cancel any time.
|
|
32
|
+
|
|
33
|
+
Run `/ashlr-upgrade` from any Claude Code session to start.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Pro Team ($24/user/mo, min 3 seats · or $20/user/mo annual)
|
|
38
|
+
|
|
39
|
+
Everything in Pro, plus:
|
|
40
|
+
|
|
41
|
+
- **Shared encrypted team genome** — E2E AES-256-GCM encrypted. Every
|
|
42
|
+
section synced via vclock conflict detection. Divergent edits surface in
|
|
43
|
+
`/ashlr-genome-conflicts` for human resolution. No plaintext leaves the
|
|
44
|
+
client.
|
|
45
|
+
- **Org-wide savings dashboard** — aggregate savings, tool adoption, and
|
|
46
|
+
streak rankings across all team members. Deduped per-repo.
|
|
47
|
+
- **Weekly team digest** — top genome sections hit, new discoveries, savings
|
|
48
|
+
milestones across the team. Delivered via `/ashlr-resume` and optional email.
|
|
49
|
+
- **Policy packs** — centrally managed allow/deny lists for `ashlr__bash`,
|
|
50
|
+
`ashlr__sql`, and destructive ops, pushed to every seat via the hook
|
|
51
|
+
infrastructure. (Shipping — contact sales for early access.)
|
|
52
|
+
- **SSO + SCIM** — WorkOS integration for orgs that require it.
|
|
53
|
+
- **Audit log** — every non-read MCP tool call with commit linkage. SOC 2
|
|
54
|
+
evidence export on request.
|
|
55
|
+
|
|
56
|
+
Run `/ashlr-upgrade --tier team` to start.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## What's never paywalled
|
|
61
|
+
|
|
62
|
+
Every MCP tool (all 45), every skill (all 31), the genome format, the local
|
|
63
|
+
scribe loop, per-session savings accounting, the benchmark harness, local
|
|
64
|
+
Ollama semantic search — all MIT, forever. Pro adds cloud infrastructure; it
|
|
65
|
+
does not remove or degrade anything in the free tier.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Pricing summary
|
|
70
|
+
|
|
71
|
+
| Tier | Price | For |
|
|
72
|
+
|------|-------|-----|
|
|
73
|
+
| **Free** | $0, MIT forever | Every developer. Local-first. Full tool suite. Public-repo cloud genome. |
|
|
74
|
+
| **Pro** | $12/mo or $120/yr | One developer wanting cloud sync, hosted LLM, cross-machine dashboard. |
|
|
75
|
+
| **Pro Team** | $24/user/mo (min 3) or $20/user/mo annual | Engineering teams. Shared genome, org dashboard, policy packs, SSO. |
|
|
76
|
+
| **Enterprise** | Contact sales | On-prem, private inference, dedicated SLA, custom genome spec. |
|
|
77
|
+
|
|
78
|
+
**Downgrade path:** graceful. When a license lapses, the plugin routes to
|
|
79
|
+
free-tier fallbacks silently — no nag screens, no broken features. The genome
|
|
80
|
+
stays local. Cloud sync pauses.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Technical architecture
|
|
85
|
+
|
|
86
|
+
**No fork.** One codebase. Pro features activate when `~/.ashlr/license.json`
|
|
87
|
+
validates against the Pro license server (signed JWT, 24h cache, works offline
|
|
88
|
+
for 30 days once cached).
|
|
89
|
+
|
|
90
|
+
**Retrieval fallback chain (Pro → free, never breaks):**
|
|
91
|
+
```
|
|
92
|
+
hosted pgvector → local Ollama → TF-IDF
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Genome sync** — `_genome-sync.ts` client, inactive without
|
|
96
|
+
`ASHLR_TEAM_GENOME_ID`. Uses the existing `proposeUpdate` /
|
|
97
|
+
`consolidateProposals` path; on consolidation it publishes a delta encrypted
|
|
98
|
+
with the team key to the Postgres-backed sync hub.
|
|
99
|
+
|
|
100
|
+
**Stats sync** — `ashlr-pro-telemetry` hook POSTs deltas of the per-session
|
|
101
|
+
ledger to a lightweight ingest endpoint. Opt-in, per-user toggleable, zero PII.
|
|
102
|
+
|
|
103
|
+
For architecture details see `docs/team-genome.md` and
|
|
104
|
+
`docs/github-oauth-onboarding.md`.
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
> **Internal reference only.** Canonical public docs: [plugin.ashlr.ai/docs](https://plugin.ashlr.ai/docs) (source: `site/content/docs/`).
|
|
2
|
+
|
|
3
|
+
This directory contains internal architecture notes, runbooks, and operational docs for contributors and maintainers. It is not the public documentation site.
|
|
4
|
+
|
|
5
|
+
## Files in this directory
|
|
6
|
+
|
|
7
|
+
| File | Purpose |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `architecture.md` | Full system architecture reference for contributors |
|
|
10
|
+
| `benchmarks.md` | Benchmark methodology and raw data |
|
|
11
|
+
| `benchmarks.json` | Single-repo benchmark snapshot (ashlr-plugin source) |
|
|
12
|
+
| `benchmarks-v2.json` | Cross-language benchmark (TS + Python + Rust) |
|
|
13
|
+
| `telemetry.md` | Telemetry privacy contract — what is and isn't sent |
|
|
14
|
+
| `pricing.md` | Internal pricing model and tier definitions |
|
|
15
|
+
| `cloud-genome.md` | Cloud genome sync deep-dive |
|
|
16
|
+
| `multi-host-mcp.md` | Multi-host MCP setup (Cline, Claude Desktop, Codex CLI) |
|
|
17
|
+
| `operations.md` | Operations runbook |
|
|
18
|
+
| `deploy.md` | Deployment guide |
|
|
19
|
+
| `platform-support.md` | Windows / macOS / Linux platform matrix |
|
|
20
|
+
|
|
21
|
+
For public user-facing documentation, see `site/content/docs/` or visit [plugin.ashlr.ai/docs](https://plugin.ashlr.ai/docs).
|
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
# ashlr-plugin Architecture
|
|
2
|
+
|
|
3
|
+
Reference for contributors. Covers system shape, data flows, and conventions. All file references are relative to the plugin root unless otherwise noted.
|
|
4
|
+
|
|
5
|
+
> **Platform support:** ashlr-plugin runs on Windows, macOS, and Linux. All Claude Code hooks are TypeScript files invoked via `bun run`. There are no bash-only code paths in the hot loop. The legacy `.sh` files in `hooks/` remain for reference but `hooks/hooks.json` points exclusively at the `.ts` siblings. See [install-windows.md](install-windows.md) for Windows-specific notes.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Overview
|
|
10
|
+
|
|
11
|
+
ashlr-plugin is a multi-host plugin for Codex and Claude Code that wraps file, search, edit, and shell workflows with lower-token alternatives and adds a lightweight observability layer over tool usage and cost.
|
|
12
|
+
|
|
13
|
+
Two value propositions:
|
|
14
|
+
|
|
15
|
+
**Token efficiency.** `ashlr__read`, `ashlr__grep`, and `ashlr__edit` replace the built-in `Read`, `Grep`, and `Edit` tools. Large file reads are snip-compacted or LLM-summarized; grep calls route through a per-project genome index (RAG) when one exists, cutting tokens by ~84% on warm queries; edits send only diffs, not full file contents.
|
|
16
|
+
|
|
17
|
+
**Observability.** Every tool call is accounted in `~/.ashlr/stats.json` (per-session + lifetime counters) and appended to `~/.ashlr/session-log.jsonl`. Claude Code surfaces savings in the status line; Codex surfaces them through MCP tools, CLI commands, and skills. The genome scribe loop extracts architectural knowledge from tool results into `.ashlrcode/genome/`, which feeds back into future grep routing.
|
|
18
|
+
|
|
19
|
+
The Claude Code wiring entry point is `.claude-plugin/plugin.json`. The Codex wiring entry point is `.codex-plugin/plugin.json` with `.mcp.json` and `hooks/codex-hooks.json`.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 2. MCP Server Map
|
|
24
|
+
|
|
25
|
+
Source of truth: `.claude-plugin/plugin.json:mcpServers`. As of v1.13, **a single `ashlr` router entry** replaces the previous 16 per-server entries. The router at `servers/_router.ts` dispatches all 40 tools via a shared `registerTool` / `getTool` registry. `plugin.json` has one `mcpServers` entry:
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
"ashlr": {
|
|
29
|
+
"command": "bun",
|
|
30
|
+
"args": ["${CLAUDE_PLUGIN_ROOT}/scripts/bootstrap.mjs", "servers/_router.ts"]
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The node bootstrap (`scripts/bootstrap.mjs`) ensures Bun is available before handing off to the bun-native entrypoint (`scripts/mcp-entrypoint.ts`). The entrypoint replaces the legacy bash wrapper so the plugin runs on Windows without Git Bash. It handles first-run `bun install`, stale-sibling version cache cleanup, and `CLAUDE_SESSION_ID` forwarding. The dedicated `ashlr-mcp` bin launches the same router path for Codex and other MCP hosts without invoking the stats CLI.
|
|
35
|
+
|
|
36
|
+
`ASHLR_ROUTER_DISABLE=1` is retained as a kill switch for one release cycle (reverts to legacy per-server mode).
|
|
37
|
+
|
|
38
|
+
### Tool registry (all 40 tools)
|
|
39
|
+
|
|
40
|
+
| Tool | Origin server module | Replaces (native) |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| `ashlr__read` | `servers/efficiency-server.ts` | `Read` |
|
|
43
|
+
| `ashlr__grep` | `servers/efficiency-server.ts` | `Grep` |
|
|
44
|
+
| `ashlr__edit` | `servers/efficiency-server.ts` | `Edit` (baseline is `search+replace` bytes as of v1.18 Trust Pass) |
|
|
45
|
+
| `ashlr__edit_structural` | `servers/edit-structural-server.ts` | — (v2 as of v1.18: Unicode identifiers, cross-file rename with `anchorFile`/`maxFiles`/shadowing guard/dryRun, extract-function with return-value detection) |
|
|
46
|
+
| `ashlr__multi_edit` | `servers/multi-edit-server.ts` | — |
|
|
47
|
+
| `ashlr__savings` | `servers/efficiency-server.ts` | — |
|
|
48
|
+
| `ashlr__flush` | `servers/efficiency-server.ts` | — |
|
|
49
|
+
| `ashlr__bash` | `servers/bash-server.ts` | `Bash` (v1.18: process-group SIGKILL on timeout, pluggable summarizer registry) |
|
|
50
|
+
| `ashlr__bash_start` / `_stop` / `_tail` / `_list` | `servers/bash-server.ts` | — (long-running control plane) |
|
|
51
|
+
| `ashlr__diff` | `servers/diff-server.ts` | — |
|
|
52
|
+
| `ashlr__diff_semantic` | `servers/diff-semantic-server.ts` | — |
|
|
53
|
+
| `ashlr__sql` | `servers/sql-server.ts` | — |
|
|
54
|
+
| `ashlr__tree` | `servers/tree-server.ts` | — |
|
|
55
|
+
| `ashlr__http` | `servers/http-server.ts` | `WebFetch` |
|
|
56
|
+
| `ashlr__logs` | `servers/logs-server.ts` | — |
|
|
57
|
+
| `ashlr__genome_propose` / `_consolidate` / `_status` | `servers/genome-server.ts` | — |
|
|
58
|
+
| `ashlr__orient` | `servers/orient-server.ts` | — |
|
|
59
|
+
| `ashlr__issue` / `ashlr__pr` | `servers/github-server.ts` | — (wraps `gh` CLI) |
|
|
60
|
+
| `ashlr__pr_comment` / `ashlr__pr_approve` | `servers/github-server.ts` | — (v1.18 PR write ops; `pr:"current"` via `gh pr view`, self-approval guard, `ASHLR_REQUIRE_GH_CONFIRM=1`) |
|
|
61
|
+
| `ashlr__issue_create` / `ashlr__issue_close` | `servers/github-server.ts` | — (v1.18 issue write ops; no destructive ops) |
|
|
62
|
+
| `ashlr__glob` | `servers/glob-server.ts` | `Glob` |
|
|
63
|
+
| `ashlr__ls` | `servers/ls-server.ts` | — |
|
|
64
|
+
| `ashlr__webfetch` | `servers/webfetch-server.ts` | `WebFetch` (summarizes at 4 KB as of v1.18) |
|
|
65
|
+
| `ashlr__ask` | `servers/ask-server.ts` | — |
|
|
66
|
+
| `ashlr__test` | `servers/test-server.ts` | — (bun/vitest/jest/pytest/go test parser; v1.18: async spawn + `bun.lock` text detection) |
|
|
67
|
+
|
|
68
|
+
The router pattern: each server module calls `registerTool(name, handler)` at import time. The router's `CallToolRequestSchema` handler calls `getTool(name)(params)` — no per-server process spawning, one stdin/stdout pair.
|
|
69
|
+
|
|
70
|
+
### Shared infrastructure modules
|
|
71
|
+
|
|
72
|
+
- **`servers/_pricing.ts`** (v1.18) — single source of truth for $/MTok across the plugin. Consumed by `efficiency-server.ts`, `scripts/savings-dashboard.ts`, `scripts/savings-status-line.ts`, and `session-greet.ts`. Prior to v1.18 each surface hardcoded its own rate, producing three different dollar values for the same token count. `ASHLR_PRICING_MODEL` env var selects the model (default `sonnet-4.5` at $3/MTok input; `opus-4`, `haiku-4.5` also supported).
|
|
73
|
+
- **`servers/_bash-summarizers-registry.ts`** (v1.18) — pluggable registry of structured summarizers for `ashlr__bash` output. Keyed by command prefix, each entry returns a compact summary for matched output (`git log`, `git diff`, `git show`, unified test-runner output across jest/vitest/pytest/bun/mocha/npm/yarn/pnpm, `tsc`, package installs across the four major JS package managers). `bash-server.ts::tryStructuredSummary` falls back to `findSummarizer(command)` after the hardcoded branches, so new summarizers register without per-command edits.
|
|
74
|
+
- **`rawTotal` in stats** (v1.18) — new column in both `_stats.ts` (JSON) and `_stats-sqlite.ts` backends. Lets the dashboard display `saved / rawTotal` as a percentage. Backward-compat: missing values treat as 0. See section 3.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 2a. GitHub OAuth + Cloud Genome Pipeline
|
|
79
|
+
|
|
80
|
+
As of v1.13, sign-in with GitHub triggers an auto-genome build for any public repo the user picks. The pipeline links the CLI, backend, and `ashlr__grep` retrieval path.
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
User runs /ashlr-upgrade
|
|
84
|
+
│
|
|
85
|
+
▼
|
|
86
|
+
scripts/upgrade-flow.ts ──► "Sign in with GitHub" picker
|
|
87
|
+
│ (magic-link preserved as fallback)
|
|
88
|
+
▼
|
|
89
|
+
browser: plugin.ashlr.ai/auth/github
|
|
90
|
+
│ GitHub consent: read:user user:email public_repo
|
|
91
|
+
▼
|
|
92
|
+
server: /auth/github/callback
|
|
93
|
+
│ AES-256-GCM encrypt token → users.github_access_token_encrypted
|
|
94
|
+
│ write pending_auth_tokens by session_id
|
|
95
|
+
▼
|
|
96
|
+
CLI polls /auth/status?session=<sid> ──► receives token
|
|
97
|
+
│
|
|
98
|
+
▼
|
|
99
|
+
browser: /repo-picker
|
|
100
|
+
│ POST /genome/build → fire-and-forget buildGenomeFromGitHub()
|
|
101
|
+
│ git clone --depth 1 + genome-init --minimal
|
|
102
|
+
│ per-section AES-GCM encrypt → upsertSection
|
|
103
|
+
▼
|
|
104
|
+
hooks/session-start.ts
|
|
105
|
+
│ scripts/genome-cloud-pull.ts
|
|
106
|
+
│ parse cwd git remote → canonicalize repo URL
|
|
107
|
+
│ GET /genome/personal/find?repo_url=<canon>
|
|
108
|
+
│ download sections → ~/.ashlr/genomes/<projectHash>/
|
|
109
|
+
│ write .ashlr-cloud-genome marker
|
|
110
|
+
▼
|
|
111
|
+
ashlr__grep
|
|
112
|
+
├─ local .ashlrcode/genome/ (wins if present)
|
|
113
|
+
├─ ~/.ashlr/genomes/<hash>/ (cloud fallback via findParentGenome)
|
|
114
|
+
└─ ripgrep full-tree (last resort)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Full walkthrough: [docs/github-oauth-onboarding.md](github-oauth-onboarding.md)
|
|
118
|
+
Pipeline architecture: [docs/cloud-genome.md](cloud-genome.md)
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## 3. Stats Data Flow
|
|
123
|
+
|
|
124
|
+
### Per-session bucket shape
|
|
125
|
+
|
|
126
|
+
`~/.ashlr/stats.json` holds a `sessions` map keyed by `CLAUDE_SESSION_ID` (or a PPID-derived fallback when the env var is absent). Each bucket:
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
sessions: {
|
|
130
|
+
"<session-id>": {
|
|
131
|
+
calls: number, // tool invocations attributed to this session
|
|
132
|
+
tokensSaved: number,
|
|
133
|
+
costSaved: number,
|
|
134
|
+
startedAt: ISO-string,
|
|
135
|
+
byTool: { [toolName]: { calls, tokensSaved, costSaved } },
|
|
136
|
+
projects: { [cwd]: { calls, tokensSaved } },
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Lifetime totals live in `stats.lifetime` alongside the map and are never dropped.
|
|
142
|
+
|
|
143
|
+
### Write path
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
MCP tool handler (e.g. ashlr__read)
|
|
147
|
+
└─ recordSaving(tokens, cost, tool, cwd) servers/_stats.ts:recordSaving
|
|
148
|
+
└─ withSerializedWrite(fn) in-process Promise mutex (writeQueue chain)
|
|
149
|
+
└─ acquireLock() ~/.ashlr/stats.lock (O_EXCL, 200ms spin)
|
|
150
|
+
└─ readStats() JSON.parse(readFileSync)
|
|
151
|
+
└─ mutate bucket
|
|
152
|
+
└─ writeStatsAtomic()
|
|
153
|
+
└─ writeFile(tmpPath)
|
|
154
|
+
└─ fsync(fd) (via Bun's native fd)
|
|
155
|
+
└─ rename(tmp → stats.json)
|
|
156
|
+
└─ releaseLock()
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Two serialization layers — the in-process mutex (a chained Promise) prevents concurrent async calls within one server process from racing; the filesystem lock extends that to the 12 servers and hooks that can run simultaneously. The rename is atomic at the OS level, so readers never see a partial write.
|
|
160
|
+
|
|
161
|
+
### schemaVersion and migration
|
|
162
|
+
|
|
163
|
+
`stats.json` carries `"schemaVersion": 2`. On load, `_stats.ts:readStats` checks the version and migrates forward if needed (v1 had a single global `session` field; v2 moves that to the per-session map). The migration is additive and non-destructive — old lifetime counters are preserved.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## 4. Hook Graph
|
|
168
|
+
|
|
169
|
+
Hooks are declared in `hooks/hooks.json` and executed by the Claude Code harness. The file references below show where each hook lives.
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
Session opens
|
|
173
|
+
│
|
|
174
|
+
▼
|
|
175
|
+
SessionStart ──► hooks/session-start.ts
|
|
176
|
+
│ • Runs baseline scanner (project orientation)
|
|
177
|
+
│ • Calls initSessionBucket() in _stats.ts
|
|
178
|
+
│ • Emits session greeting to stderr
|
|
179
|
+
│
|
|
180
|
+
▼ (for each tool call)
|
|
181
|
+
PreToolUse (matcher: "Read") ──► hooks/pretooluse-read.ts
|
|
182
|
+
PreToolUse (matcher: "Grep") ──► hooks/pretooluse-grep.ts
|
|
183
|
+
PreToolUse (matcher: "Edit") ──► hooks/pretooluse-edit.ts
|
|
184
|
+
│ (as of v1.18: emits permissionDecision: "deny" with actionable
|
|
185
|
+
│ "call mcp__plugin_ashlr_ashlr__ashlr__* instead" message when
|
|
186
|
+
│ ASHLR_HOOK_MODE=redirect, which is the default. Safety nets:
|
|
187
|
+
│ paths outside cwd (realpath-canonicalized for macOS /tmp →
|
|
188
|
+
│ /private/tmp), paths inside CLAUDE_PLUGIN_ROOT, bypassSummary:true
|
|
189
|
+
│ are never redirected. Escape hatch: ASHLR_HOOK_MODE=nudge or
|
|
190
|
+
│ hookMode:"nudge" in ~/.ashlr/config.json.)
|
|
191
|
+
▼
|
|
192
|
+
[ tool executes ]
|
|
193
|
+
│
|
|
194
|
+
▼
|
|
195
|
+
PostToolUse (matcher: Write|Edit|MultiEdit|Bash|mcp__plugin_ashlr_ashlr__ashlr__*)
|
|
196
|
+
├──► hooks/genome-scribe-hook.ts (genome auto-propose; matcher expanded
|
|
197
|
+
│ in v1.18 to cover MultiEdit,
|
|
198
|
+
│ ashlr__multi_edit, ashlr__edit_structural)
|
|
199
|
+
└──► hooks/session-log-append.ts (JSONL append)
|
|
200
|
+
│
|
|
201
|
+
▼
|
|
202
|
+
SessionEnd
|
|
203
|
+
├──► hooks/session-end-consolidate.ts (genome consolidation; v1.17+ fires
|
|
204
|
+
│ scripts/genome-cloud-push.ts afterwards
|
|
205
|
+
│ when .cloud-id present)
|
|
206
|
+
└──► hooks/session-end-stats-gc.ts (drop session bucket, append summary to log)
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
PreToolUse hooks are matcher-filtered — Claude Code only fires them for the named tool. PostToolUse has a pipe-separated matcher covering both native tools and the ashlr MCP variants (canonical prefix `mcp__plugin_ashlr_ashlr__ashlr__*` as of v1.13 router consolidation; all matchers in `hooks/hooks.json` renamed to this form in v1.18 after legacy `mcp__ashlr-efficiency__*` / `mcp__ashlr-multi-edit__*` stopped matching post-router-migration).
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## 5. Genome Lifecycle
|
|
214
|
+
|
|
215
|
+
The genome is a per-project knowledge base stored under `.ashlrcode/genome/`. It powers genome-aware `ashlr__grep` routing and surfaces architectural context during sessions.
|
|
216
|
+
|
|
217
|
+
**Init** — `scripts/genome-init.ts` (invoked by the `/ashlr-genome-init` skill). Creates the scaffold via `@ashlr/core-efficiency/genome:initGenome`, then writes three knowledge files: `knowledge/architecture.md` (baseline scanner output), `knowledge/conventions.md` (detected from config files), and `knowledge/decisions.md` (ADR-0000 placeholder).
|
|
218
|
+
|
|
219
|
+
**Propose (edit-triggered)** — `hooks/post-tool-use-genome.sh` fires on every Write/Edit/MultiEdit/Bash call. It pipes the PostToolUse payload to `scripts/genome-auto-propose.ts`, which:
|
|
220
|
+
1. Skips trivial tools via a whitelist.
|
|
221
|
+
2. Regex-matches architecture/decision signals in the result text.
|
|
222
|
+
3. Deduplicates by SHA-256 of the first 500 chars against a persisted set at `~/.ashlr/genome-proposals-seen.json` (capped at 10K entries).
|
|
223
|
+
4. Walks up from `cwd` to find `.ashlrcode/genome/`.
|
|
224
|
+
5. Appends a JSONL record to `proposals.jsonl` with the current generation number.
|
|
225
|
+
|
|
226
|
+
**Consolidate (session-end or threshold)** — `hooks/session-end-consolidate.sh` runs at SessionEnd. It also fires mid-session when the proposal count crosses a threshold. Consolidation calls `ashlr__genome_consolidate` (via `servers/genome-server.ts`), which delegates to `@ashlr/core-efficiency/scribe.ts` to merge pending proposals into the genome files. If a local LLM is reachable it summarizes the diffs; otherwise it does a line-level merge. Progress is logged to `~/.ashlr/genome-consolidation.log`.
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## 6. Status Line Rendering
|
|
231
|
+
|
|
232
|
+
Claude Code calls the `statusLine.command` from `plugin.json` periodically and renders the first stdout line in its UI bar.
|
|
233
|
+
|
|
234
|
+
Pipeline:
|
|
235
|
+
|
|
236
|
+
```
|
|
237
|
+
stats.json
|
|
238
|
+
└─ readCurrentSession(sessionId) servers/_stats.ts
|
|
239
|
+
└─ buildStatusLine() scripts/savings-status-line.ts
|
|
240
|
+
├─ formatTokens(saved) → "1.2K", "450K", "2.1M"
|
|
241
|
+
├─ readDailyHistory() → last-N-day savings array
|
|
242
|
+
├─ renderSparkline(history) scripts/ui-animation.ts:renderSparkline
|
|
243
|
+
│ └─ 16-rung Unicode bars (ASCII fallback for non-Unicode terminals)
|
|
244
|
+
├─ renderGradient(sparkline) scripts/ui-animation.ts:renderGradient
|
|
245
|
+
│ └─ truecolor sweep (single brand color fallback)
|
|
246
|
+
├─ renderHeartbeat(pulse) scripts/ui-animation.ts
|
|
247
|
+
└─ applyColor(line) scripts/savings-status-line.ts
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
**Capability detection.** `scripts/savings-status-line.ts` reads terminal capability flags before rendering. Unicode glyphs are suppressed when the terminal can't display them. Color is suppressed when `NO_COLOR` is set or when the terminal reports no color support. Animation is suppressed when `ASHLR_STATUS_ANIMATE=0`.
|
|
251
|
+
|
|
252
|
+
**Width budget.** The output target is 80 characters. `visibleWidth()` in `scripts/ui-animation.ts:visibleWidth` strips ANSI escapes and counts code points to measure rendered width, independent of color sequences. The status line truncates segments to stay within budget.
|
|
253
|
+
|
|
254
|
+
**Context-pressure widget.** A micro-widget `ctx: NN%` is inserted between the sparkline and the `session +N` segment when Claude Code pipes a session-state JSON payload on stdin. The widget is hidden entirely when the payload is absent or contains no usable fields — it never guesses. Color tiers (truecolor only):
|
|
255
|
+
|
|
256
|
+
| Range | Color |
|
|
257
|
+
|--------|---------------------|
|
|
258
|
+
| 0–60% | dim brand-green |
|
|
259
|
+
| 60–80% | yellow (`#d4a72c`) |
|
|
260
|
+
| 80–95% | orange (`#d9793a`) |
|
|
261
|
+
| 95%+ | red + bold (`#e15b5b`) |
|
|
262
|
+
|
|
263
|
+
Payload fields tried (in priority order):
|
|
264
|
+
1. `context_used_tokens` + `context_limit_tokens` (explicit used/limit pair — most precise)
|
|
265
|
+
2. All other fields (`input_tokens`, `context_tokens`, `total_tokens`, `total_tokens_used`, `sessionTokens`) require a paired limit field to compute a percentage; without one the widget is hidden.
|
|
266
|
+
|
|
267
|
+
The stdin reader in `import.meta.main` has a hard 50ms deadline and never blocks the terminal. The widget counts toward the 80-char visible-width budget. Drop-order under tight budget: tip is dropped first, then the context widget; the brand + session + lifetime core is never truncated mid-word.
|
|
268
|
+
|
|
269
|
+
**Settings toggles** (under `ashlr` key in `~/.claude/settings.json`):
|
|
270
|
+
- `statusLine` — master on/off switch (default: true)
|
|
271
|
+
- `statusLineSession` — show "session +N" segment
|
|
272
|
+
- `statusLineLifetime` — show "lifetime +N" segment
|
|
273
|
+
- `statusLineTips` — rotate a helpful tip at the tail
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## 7. Session Log
|
|
278
|
+
|
|
279
|
+
`~/.ashlr/session-log.jsonl` is an append-only JSONL file. Each line is a flat JSON record.
|
|
280
|
+
|
|
281
|
+
**Append path** — `hooks/session-log-append.sh` fires PostToolUse. It uses `bun` to parse the hook payload and emit a structured record; falls back to a minimal bash-built record if bun is unavailable. Self-rotates at 10 MB to `session-log.jsonl.1`.
|
|
282
|
+
|
|
283
|
+
**Record schema:**
|
|
284
|
+
```json
|
|
285
|
+
{ "ts": "ISO-8601", "agent": "claude-code", "event": "tool_call",
|
|
286
|
+
"tool": "ashlr__read", "cwd": "/abs/path", "session": "sess-id",
|
|
287
|
+
"input_size": 42, "output_size": 310 }
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
**Session-end summary** — `hooks/session-end-stats-gc.ts` appends one final record per session with `event: "session_end"` carrying `calls`, `tokens_saved`, and `started_at` from the bucket being dropped.
|
|
291
|
+
|
|
292
|
+
**Planned events** — `tool_fallback` (LLM summarization fell back to snip-compact) and `tool_escalate` (agent escalated from haiku to sonnet) are reserved event types.
|
|
293
|
+
|
|
294
|
+
**Aggregator** — `scripts/session-log-report.ts` reads the log (+ rotated `.1`) and produces a plain-text report covering top tools by call count, per-project breakdowns, 24h vs lifetime comparison, and recent session summaries. Exposed via the `/ashlr-usage` skill.
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## 8. Summarization
|
|
299
|
+
|
|
300
|
+
Source: `servers/_summarize.ts`.
|
|
301
|
+
|
|
302
|
+
**When it fires.** Each tool that handles large output (read, grep, edit, bash, sql, diff) checks if the raw result exceeds ~2KB. If so it calls `summarize(content, toolName)`.
|
|
303
|
+
|
|
304
|
+
**Local-first.** Default endpoint is `http://localhost:1234/v1` (LM Studio). Override via `ASHLR_LLM_URL` + `ASHLR_LLM_KEY` for cloud. Cloud only fires when explicitly set; the plugin has no account requirement and telemetry is off by default.
|
|
305
|
+
|
|
306
|
+
**Cache.** SHA-256 of the input is used as cache key. Cache files live at `~/.ashlr/summary-cache/<hash>.txt` with a 1-hour TTL. A cache hit costs zero tokens.
|
|
307
|
+
|
|
308
|
+
**Fallback.** If the LLM endpoint is unreachable or times out (5s), `summarize` falls back to snipCompact truncation and appends `[LLM unreachable, fell back to truncation]` so the agent can see what happened. `bypassSummary: true` on any tool call skips LLM and snip-compacts directly.
|
|
309
|
+
|
|
310
|
+
**Per-tool prompts.** `_summarize.ts:TOOL_PROMPTS` maps tool names to system prompts tuned for each output type: file contents preserve imports and signatures; bash preserves errors and final result lines; SQL preserves first/last rows and counts. Reading from the end of the file gives the full prompt set.
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## 9. Adding a New MCP Tool
|
|
315
|
+
|
|
316
|
+
With the consolidated router, adding a tool no longer requires a new `mcpServers` entry in `plugin.json`.
|
|
317
|
+
|
|
318
|
+
1. **Create or extend a server module** (e.g. `servers/foo-server.ts`):
|
|
319
|
+
- Import `registerTool` from `servers/_router.ts`.
|
|
320
|
+
- Call `registerTool("ashlr__foo", async (params) => { ... })` at module top level.
|
|
321
|
+
- Call `await recordSaving(tokensEstimate, costEstimate, "ashlr__foo", cwd)` after each successful call.
|
|
322
|
+
- Wrap handler body in `try/catch`; return `{ content: [...], isError: true }` on error.
|
|
323
|
+
|
|
324
|
+
2. **Import the module in `servers/_router.ts`** so `registerTool` runs at startup.
|
|
325
|
+
|
|
326
|
+
3. **Write tests in `__tests__/foo-server.test.ts`**. Use `mkdtemp` for an isolated `HOME` so no test touches `~/.ashlr`. Spawn the real server process and speak JSON-RPC over stdio (see `__tests__/efficiency-server.test.ts` for the `rpc()` helper pattern).
|
|
327
|
+
|
|
328
|
+
4. **Add to `CHANGELOG.md`** under the current version block.
|
|
329
|
+
|
|
330
|
+
5. **Update this document** — add a row to the tool registry table in section 2.
|
|
331
|
+
|
|
332
|
+
No `plugin.json` change is needed. The entrypoint script handles `bun install` automatically.
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
336
|
+
## 10. Testing Model
|
|
337
|
+
|
|
338
|
+
Test runner: `bun test`. All test files live in `__tests__/`.
|
|
339
|
+
|
|
340
|
+
**Isolation.** Every test suite that touches the filesystem creates a `mkdtemp` temp dir and passes it as `HOME` (or equivalent) to the code under test. No test reads or writes the real `~/.ashlr`. See `__tests__/session-log-report.test.ts:beforeEach` for the canonical pattern.
|
|
341
|
+
|
|
342
|
+
**Integration tests.** `__tests__/efficiency-server.test.ts` spawns the real MCP server process and sends JSON-RPC requests over stdio. This catches wiring bugs that unit tests miss. The `rpc(reqs, env)` helper in that file is reusable for other server tests.
|
|
343
|
+
|
|
344
|
+
**Fixture conventions.** Synthetic log/stats data is built inline as arrays of typed records, not from files on disk. This keeps tests hermetic and readable without fixture file management.
|
|
345
|
+
|
|
346
|
+
**Special test groups:**
|
|
347
|
+
- `__tests__/integration/` — multi-server or end-to-end scenarios.
|
|
348
|
+
- `__tests__/quality/` — snapshot/regression tests for rendered output (savings report, status line).
|
|
349
|
+
|
|
350
|
+
**Running:**
|
|
351
|
+
```
|
|
352
|
+
bun test # all tests
|
|
353
|
+
bun test __tests__/foo.test.ts # single file
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
Tests that require a live database are skipped automatically when `$TEST_DATABASE_URL` is absent.
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
## 11. Release Flow
|
|
361
|
+
|
|
362
|
+
Script: `scripts/publish.sh`. Accepts `--dry-run`.
|
|
363
|
+
|
|
364
|
+
Steps:
|
|
365
|
+
1. Checks `gh auth status`.
|
|
366
|
+
2. Creates the `ashlr-plugin` GitHub repo (public) if it doesn't exist, then pushes `main`.
|
|
367
|
+
3. Optionally creates and pushes `@ashlr/core-efficiency` if the sibling repo exists locally.
|
|
368
|
+
4. Enables GitHub Pages from `/docs` (POST then PUT — idempotent).
|
|
369
|
+
|
|
370
|
+
Version bumping is manual: edit `plugin.json:version` and `CHANGELOG.md` before running the script. There is no automated semver bump. The `scripts/mcp-entrypoint.ts` reads the version from `plugin.json` to identify stale sibling cache dirs and clean them up.
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## 12. Design Principles
|
|
375
|
+
|
|
376
|
+
These are the non-obvious decisions baked into the codebase.
|
|
377
|
+
|
|
378
|
+
**Local-first LLM, opt-in telemetry.** The summarization helper calls `localhost:1234` by default. No summarization payload leaves the machine unless the user explicitly sets `ASHLR_LLM_URL`; telemetry is off by default and has to be enabled separately.
|
|
379
|
+
|
|
380
|
+
**Atomic stats writes.** A two-layer write protocol (in-process Promise chain + `O_EXCL` lockfile + `rename`) ensures that N concurrent MCP servers and hooks never corrupt `stats.json`. Any approach that just does `JSON.parse` → mutate → `writeFile` will lose updates under load. The lockfile spin is capped at 200ms; if it can't acquire, it skips the write rather than blocking the tool call.
|
|
381
|
+
|
|
382
|
+
**Per-session accounting.** The old `stats.json` had a single global `session` field. With multiple Claude Code terminals open, every server clobbered each other's counter. v2 uses `CLAUDE_SESSION_ID` as a bucket key. The TypeScript MCP entrypoint mirrors this value to `ASHLR_SESSION_ID` before launching the router.
|
|
383
|
+
|
|
384
|
+
**Width-stable status line.** The status line must not reflow the UI on every refresh. `visibleWidth()` strips ANSI escapes before measuring. Segments are truncated (not wrapped) to stay within 80 chars. The sparkline always occupies the same number of columns regardless of savings magnitude.
|
|
385
|
+
|
|
386
|
+
**Genome is fire-and-forget.** The auto-propose hook, the consolidation hook, and the genome server are all written to never throw and never block the agent. A genome write failure is invisible to the user. This is intentional — genome is an optimization layer, not a correctness requirement.
|
|
387
|
+
|
|
388
|
+
**GC at session end.** Per-session buckets are dropped from `stats.json` when the session closes (`hooks/session-end-stats-gc.ts`). Lifetime counters are never dropped. This bounds `stats.json` size without losing the numbers that matter.
|
|
389
|
+
|
|
390
|
+
---
|
|
391
|
+
|
|
392
|
+
## Supported Platforms
|
|
393
|
+
|
|
394
|
+
ashlr-plugin is tested in CI on three operating systems via a matrix strategy in `.github/workflows/ci.yml`. The `typecheck`, `test`, and `smoke` jobs all run on every OS on every push.
|
|
395
|
+
|
|
396
|
+
| Platform | Runner | Status |
|
|
397
|
+
|---|---|---|
|
|
398
|
+
| Linux | `ubuntu-latest` (Ubuntu 22.04) | Full support |
|
|
399
|
+
| macOS | `macos-latest` (macOS 14 Sonoma) | Full support |
|
|
400
|
+
| Windows | `windows-latest` (Windows Server 2022) | Full support — see caveats below |
|
|
401
|
+
|
|
402
|
+
### Caveats
|
|
403
|
+
|
|
404
|
+
**ripgrep install.** The install step is platform-specific: `apt-get` on Linux, `brew` on macOS, `winget` (falling back to `choco`) on Windows. The plugin itself does not bundle ripgrep; it must be on `PATH`.
|
|
405
|
+
|
|
406
|
+
**File permissions.** Three tests are skipped on Windows with `test.skipIf(process.platform === "win32")` because Windows does not honour POSIX `chmod` mode bits:
|
|
407
|
+
- `genome-crypto.test.ts` — key file mode 0600 check
|
|
408
|
+
- `genome-init.test.ts` — unreadable dir (chmod 000) fallback
|
|
409
|
+
- `doctor.test.ts` — non-executable hook warnings / chmod +x fix
|
|
410
|
+
|
|
411
|
+
**bash-server.** The `ashlr-bash` MCP server spawns `sh -c` commands. On Windows this requires Git Bash or WSL in the user's `PATH`. The server tests are Linux/macOS only in practice; Windows users who need `ashlr__bash` should install Git for Windows. On POSIX, v1.18 spawns with `detached: true` and kills the process group (`-pid`) on timeout so forked grandchildren (`npm install`, `cargo build`) don't leak past the timeout. Policy-enforce cache path uses `os.tmpdir()` (v1.18) so the hook works on Windows.
|
|
412
|
+
|
|
413
|
+
**CRLF line endings.** The checkout step sets `core.autocrlf false` in all matrix jobs to prevent git from converting LF to CRLF on Windows, which would break hash-based cache keys and diff expectations.
|
|
414
|
+
|
|
415
|
+
**Integration tests.** The `integration` job runs on Linux only. These tests spawn the backend server process; the server is deployed on Linux in production, so Linux e2e parity is sufficient. See `docs/platform-support.md` for the full matrix of what runs where.
|