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,447 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* _manifest-v2.ts — Genome 2.0 manifest schema (additive, backward-compatible).
|
|
3
|
+
*
|
|
4
|
+
* v1 (core-efficiency) → v2 (this module) is purely ADDITIVE:
|
|
5
|
+
* - All v1 fields remain canonical and unchanged.
|
|
6
|
+
* - Section meta gains three optional freshness fields:
|
|
7
|
+
* lastUpdatedAt — ISO timestamp of last refresh (mirrors updatedAt for v1)
|
|
8
|
+
* sourceTrust — "static" | "commit" | "pr" | "issue" | "test"
|
|
9
|
+
* confidence — 0..1 float (heuristic, optional)
|
|
10
|
+
* - A new section type is introduced for commit-diff awareness:
|
|
11
|
+
* commit sections live at `commits/<sha>.json` (not markdown) and carry
|
|
12
|
+
* structured CommitSection metadata in addition to the SectionMeta entry.
|
|
13
|
+
* - schemaVersion is bumped to 2. v1 manifests auto-upgrade IN-MEMORY on load
|
|
14
|
+
* and persist v2 on the next write. v1 readers will still parse v2 because
|
|
15
|
+
* the only new top-level field is the optional `schemaVersion`; v1 keys
|
|
16
|
+
* (`version`, `project`, `sections`, etc.) remain untouched.
|
|
17
|
+
*
|
|
18
|
+
* This module deliberately does NOT modify `node_modules/@ashlr/core-efficiency`.
|
|
19
|
+
* It wraps the loader so existing call sites keep working with `loadManifest`
|
|
20
|
+
* from core-efficiency and only opt-in to v2 by going through
|
|
21
|
+
* `loadManifestV2` / `saveManifestV2` here.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { existsSync } from "fs";
|
|
25
|
+
import { mkdir, readFile, rename, writeFile } from "fs/promises";
|
|
26
|
+
import { dirname, join } from "path";
|
|
27
|
+
import {
|
|
28
|
+
type GenomeManifest as GenomeManifestV1,
|
|
29
|
+
type SectionMeta as SectionMetaV1,
|
|
30
|
+
manifestPath,
|
|
31
|
+
} from "@ashlr/core-efficiency/genome";
|
|
32
|
+
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
// Types
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
|
|
37
|
+
export type SourceTrust = "static" | "commit" | "pr" | "issue" | "test" | "synthesis";
|
|
38
|
+
|
|
39
|
+
/** v2 SectionMeta — adds freshness metadata. All new fields are optional. */
|
|
40
|
+
export interface SectionMetaV2 extends SectionMetaV1 {
|
|
41
|
+
/** ISO timestamp of the most recent refresh. Mirrors updatedAt by default. */
|
|
42
|
+
lastUpdatedAt?: string;
|
|
43
|
+
/** Where this section's content was derived from. Defaults to "static". */
|
|
44
|
+
sourceTrust?: SourceTrust;
|
|
45
|
+
/** Heuristic 0..1 — higher = more trustworthy. Defaults unset. */
|
|
46
|
+
confidence?: number;
|
|
47
|
+
/**
|
|
48
|
+
* Marker so retrieval can distinguish section kinds.
|
|
49
|
+
*
|
|
50
|
+
* Q3 added "pr" + "issue" — cloud-sync'd genome deltas from GitHub
|
|
51
|
+
* webhooks. Older v2 manifests written before Q3 don't carry these and
|
|
52
|
+
* default to "static" via upgradeManifest().
|
|
53
|
+
*/
|
|
54
|
+
kind?: "commit" | "static" | "discovery" | "pr" | "issue";
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Commit section payload — stored at `.ashlrcode/genome/commits/<sha>.json`.
|
|
59
|
+
* The manifest also gets a SectionMetaV2 entry pointing at this file with
|
|
60
|
+
* `kind: "commit"` and `sourceTrust: "commit"`.
|
|
61
|
+
*/
|
|
62
|
+
export interface CommitSection {
|
|
63
|
+
/** Full git SHA. */
|
|
64
|
+
sha: string;
|
|
65
|
+
/** Commit subject + body (raw, untruncated). */
|
|
66
|
+
message: string;
|
|
67
|
+
/** Author "Name <email>" line from `git show --pretty=fuller`. */
|
|
68
|
+
author: string;
|
|
69
|
+
/** ISO timestamp of the commit (author date). */
|
|
70
|
+
date: string;
|
|
71
|
+
/** Files changed in this commit (relative paths from repo root). */
|
|
72
|
+
filesChanged: string[];
|
|
73
|
+
/** Markdown body — typically a short summary + diff highlights. */
|
|
74
|
+
summary: string;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface GenomeManifestV2 extends Omit<GenomeManifestV1, "version"> {
|
|
78
|
+
/** v1 manifests have `version: 1`. v2 manifests carry both for compat. */
|
|
79
|
+
version: 1;
|
|
80
|
+
/** v2 schema marker. Absent on v1 manifests on disk. */
|
|
81
|
+
schemaVersion?: 2;
|
|
82
|
+
sections: SectionMetaV2[];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
// Constants
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
|
|
89
|
+
/** Subdirectory under .ashlrcode/genome/ where commit sections live. */
|
|
90
|
+
export const COMMITS_SUBDIR = "commits";
|
|
91
|
+
|
|
92
|
+
/** Hard cap on commit sections kept on disk. Older ones are pruned. */
|
|
93
|
+
export const COMMIT_RETENTION_LIMIT = 50;
|
|
94
|
+
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
// Migration
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Upgrade a v1 manifest to v2 in-memory.
|
|
101
|
+
* Idempotent — running on an already-v2 manifest is a no-op.
|
|
102
|
+
*
|
|
103
|
+
* Sets defaults for each section:
|
|
104
|
+
* - lastUpdatedAt ← updatedAt
|
|
105
|
+
* - sourceTrust ← "static"
|
|
106
|
+
* - kind ← "static"
|
|
107
|
+
*
|
|
108
|
+
* The original `updatedAt` field is preserved so v1 readers stay happy.
|
|
109
|
+
*/
|
|
110
|
+
export function upgradeManifest(manifest: GenomeManifestV1 | GenomeManifestV2): GenomeManifestV2 {
|
|
111
|
+
const m = manifest as GenomeManifestV2;
|
|
112
|
+
if (m.schemaVersion === 2) {
|
|
113
|
+
// Already v2 — still backfill any missing per-section defaults so old v2
|
|
114
|
+
// manifests written before this defaulting existed pick up the fields.
|
|
115
|
+
for (const s of m.sections) {
|
|
116
|
+
if (!s.lastUpdatedAt) s.lastUpdatedAt = s.updatedAt;
|
|
117
|
+
if (!s.sourceTrust) s.sourceTrust = s.kind === "commit" ? "commit" : "static";
|
|
118
|
+
if (!s.kind) s.kind = "static";
|
|
119
|
+
}
|
|
120
|
+
return m;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// True v1 → v2 upgrade.
|
|
124
|
+
const upgraded: GenomeManifestV2 = {
|
|
125
|
+
...(manifest as GenomeManifestV1),
|
|
126
|
+
schemaVersion: 2,
|
|
127
|
+
sections: (manifest.sections as SectionMetaV1[]).map((s) => ({
|
|
128
|
+
...s,
|
|
129
|
+
lastUpdatedAt: (s as SectionMetaV2).lastUpdatedAt ?? s.updatedAt,
|
|
130
|
+
sourceTrust: (s as SectionMetaV2).sourceTrust ?? "static",
|
|
131
|
+
kind: (s as SectionMetaV2).kind ?? "static",
|
|
132
|
+
})),
|
|
133
|
+
};
|
|
134
|
+
return upgraded;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// ---------------------------------------------------------------------------
|
|
138
|
+
// Load / Save (v2-aware)
|
|
139
|
+
// ---------------------------------------------------------------------------
|
|
140
|
+
|
|
141
|
+
export async function loadManifestV2(cwd: string): Promise<GenomeManifestV2 | null> {
|
|
142
|
+
const p = manifestPath(cwd);
|
|
143
|
+
if (!existsSync(p)) return null;
|
|
144
|
+
try {
|
|
145
|
+
const raw = await readFile(p, "utf-8");
|
|
146
|
+
const parsed = JSON.parse(raw) as GenomeManifestV1 | GenomeManifestV2;
|
|
147
|
+
return upgradeManifest(parsed);
|
|
148
|
+
} catch {
|
|
149
|
+
// Corrupt / partial — treat as missing, same policy as v1 loader.
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export async function saveManifestV2(cwd: string, manifest: GenomeManifestV2): Promise<void> {
|
|
155
|
+
const target = manifestPath(cwd);
|
|
156
|
+
const dir = dirname(target);
|
|
157
|
+
if (!existsSync(dir)) {
|
|
158
|
+
await mkdir(dir, { recursive: true });
|
|
159
|
+
}
|
|
160
|
+
manifest.updatedAt = new Date().toISOString();
|
|
161
|
+
if (!manifest.schemaVersion) manifest.schemaVersion = 2;
|
|
162
|
+
const tmp = target + ".tmp";
|
|
163
|
+
try {
|
|
164
|
+
await writeFile(tmp, JSON.stringify(manifest, null, 2), "utf-8");
|
|
165
|
+
await rename(tmp, target);
|
|
166
|
+
} catch (e) {
|
|
167
|
+
const { unlink } = await import("fs/promises");
|
|
168
|
+
await unlink(tmp).catch(() => {});
|
|
169
|
+
throw e;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// ---------------------------------------------------------------------------
|
|
174
|
+
// Commit-section file helpers
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
|
|
177
|
+
export function commitsDir(cwd: string): string {
|
|
178
|
+
return join(cwd, ".ashlrcode", "genome", COMMITS_SUBDIR);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export function commitSectionPath(cwd: string, sha: string): string {
|
|
182
|
+
// Relative path INSIDE the genome dir (matches SectionMetaV2.path convention).
|
|
183
|
+
return join(COMMITS_SUBDIR, `${sha}.json`);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function commitSectionAbsPath(cwd: string, sha: string): string {
|
|
187
|
+
return join(commitsDir(cwd), `${sha}.json`);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Write a commit section JSON file (separate from the manifest update).
|
|
192
|
+
* Returns the relative path stored in the manifest's `sections[].path`.
|
|
193
|
+
*/
|
|
194
|
+
export async function writeCommitSectionFile(
|
|
195
|
+
cwd: string,
|
|
196
|
+
payload: CommitSection,
|
|
197
|
+
): Promise<string> {
|
|
198
|
+
const abs = commitSectionAbsPath(cwd, payload.sha);
|
|
199
|
+
const dir = dirname(abs);
|
|
200
|
+
if (!existsSync(dir)) {
|
|
201
|
+
await mkdir(dir, { recursive: true });
|
|
202
|
+
}
|
|
203
|
+
await writeFile(abs, JSON.stringify(payload, null, 2), "utf-8");
|
|
204
|
+
return commitSectionPath(cwd, payload.sha);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export async function readCommitSectionFile(
|
|
208
|
+
cwd: string,
|
|
209
|
+
sha: string,
|
|
210
|
+
): Promise<CommitSection | null> {
|
|
211
|
+
const abs = commitSectionAbsPath(cwd, sha);
|
|
212
|
+
if (!existsSync(abs)) return null;
|
|
213
|
+
try {
|
|
214
|
+
const raw = await readFile(abs, "utf-8");
|
|
215
|
+
return JSON.parse(raw) as CommitSection;
|
|
216
|
+
} catch {
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// ---------------------------------------------------------------------------
|
|
222
|
+
// Discovery sections (Q2 AI-Native Synthesis)
|
|
223
|
+
// ---------------------------------------------------------------------------
|
|
224
|
+
|
|
225
|
+
/** Subdirectory under .ashlrcode/genome/ where discovery sections live. */
|
|
226
|
+
export const DISCOVERIES_SUBDIR = "discoveries";
|
|
227
|
+
|
|
228
|
+
/** Hard cap on discovery sections kept on disk. Older ones are pruned. */
|
|
229
|
+
export const DISCOVERY_RETENTION_LIMIT = 30;
|
|
230
|
+
|
|
231
|
+
/** Evidence anchor for a discovery — points back at concrete code or files. */
|
|
232
|
+
export interface DiscoveryEvidence {
|
|
233
|
+
path: string;
|
|
234
|
+
lineRange?: [number, number];
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Discovery section payload — stored at
|
|
239
|
+
* `.ashlrcode/genome/discoveries/<id>.json`. The manifest also gets a
|
|
240
|
+
* SectionMetaV2 entry pointing at this file with `kind: "discovery"` and
|
|
241
|
+
* `sourceTrust: "synthesis"`.
|
|
242
|
+
*
|
|
243
|
+
* Discoveries are AI-synthesized insights ("3 files use this util wrong",
|
|
244
|
+
* "auth refactor introduced a flaky test pattern"). Lower-confidence than
|
|
245
|
+
* commit sections (which are straight from git) but still actionable.
|
|
246
|
+
*/
|
|
247
|
+
export interface DiscoverySection {
|
|
248
|
+
/** Stable ID — hash of summary + sourceCommits, used as filename. */
|
|
249
|
+
id: string;
|
|
250
|
+
/** 1-2 sentence insight written by the synthesizer. */
|
|
251
|
+
summary: string;
|
|
252
|
+
/** Anchors to concrete code — paths + optional line ranges. */
|
|
253
|
+
evidence: DiscoveryEvidence[];
|
|
254
|
+
/** SHAs of commit sections that inspired this discovery. */
|
|
255
|
+
sourceCommits: string[];
|
|
256
|
+
/** ISO timestamp of when the synthesizer produced this. */
|
|
257
|
+
synthesizedAt: string;
|
|
258
|
+
/** 0..1 confidence set by the synthesizer (LLM-self-reported, clamped). */
|
|
259
|
+
confidence: number;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export function discoveriesDir(cwd: string): string {
|
|
263
|
+
return join(cwd, ".ashlrcode", "genome", DISCOVERIES_SUBDIR);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export function discoverySectionPath(_cwd: string, id: string): string {
|
|
267
|
+
return join(DISCOVERIES_SUBDIR, `${id}.json`);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export function discoverySectionAbsPath(cwd: string, id: string): string {
|
|
271
|
+
return join(discoveriesDir(cwd), `${id}.json`);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Write a discovery section JSON file (separate from the manifest update).
|
|
276
|
+
* Returns the relative path stored in the manifest's `sections[].path`.
|
|
277
|
+
*/
|
|
278
|
+
export async function writeDiscoverySectionFile(
|
|
279
|
+
cwd: string,
|
|
280
|
+
payload: DiscoverySection,
|
|
281
|
+
): Promise<string> {
|
|
282
|
+
const abs = discoverySectionAbsPath(cwd, payload.id);
|
|
283
|
+
const dir = dirname(abs);
|
|
284
|
+
if (!existsSync(dir)) {
|
|
285
|
+
await mkdir(dir, { recursive: true });
|
|
286
|
+
}
|
|
287
|
+
await writeFile(abs, JSON.stringify(payload, null, 2), "utf-8");
|
|
288
|
+
return discoverySectionPath(cwd, payload.id);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export async function readDiscoverySectionFile(
|
|
292
|
+
cwd: string,
|
|
293
|
+
id: string,
|
|
294
|
+
): Promise<DiscoverySection | null> {
|
|
295
|
+
const abs = discoverySectionAbsPath(cwd, id);
|
|
296
|
+
if (!existsSync(abs)) return null;
|
|
297
|
+
try {
|
|
298
|
+
const raw = await readFile(abs, "utf-8");
|
|
299
|
+
return JSON.parse(raw) as DiscoverySection;
|
|
300
|
+
} catch {
|
|
301
|
+
return null;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// ---------------------------------------------------------------------------
|
|
306
|
+
// PR sections (Q3 PR/Issue Retrieval)
|
|
307
|
+
// ---------------------------------------------------------------------------
|
|
308
|
+
|
|
309
|
+
/** Subdirectory under .ashlrcode/genome/sections/ where PR sections live. */
|
|
310
|
+
export const PRS_SUBDIR = "prs";
|
|
311
|
+
|
|
312
|
+
/** Hard cap on PR sections kept on disk. Older ones are pruned by mtime. */
|
|
313
|
+
export const PR_RETENTION_LIMIT = 100;
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* PR section payload — stored at `.ashlrcode/genome/sections/prs/<number>.json`.
|
|
317
|
+
* Populated from `pr_merged` deltas via genome-cloud-sync. The manifest carries
|
|
318
|
+
* a parallel SectionMetaV2 entry with `kind: "pr"` + `sourceTrust: "pr"`.
|
|
319
|
+
*
|
|
320
|
+
* Privacy: title + summary are already truncated server-side; no diffs.
|
|
321
|
+
*/
|
|
322
|
+
export interface PrSection {
|
|
323
|
+
/** PR number as a string id (matches sourceSha in the cloud delta). */
|
|
324
|
+
id: string;
|
|
325
|
+
/** PR title (already truncated to 512 chars by the webhook handler). */
|
|
326
|
+
title: string;
|
|
327
|
+
/** ISO timestamp when the PR merged. May be empty for backfilled rows. */
|
|
328
|
+
mergedAt: string;
|
|
329
|
+
/** GitHub login of the PR author. May be empty. */
|
|
330
|
+
author: string;
|
|
331
|
+
/** Paths only — webhook never ships diff content. May be empty. */
|
|
332
|
+
filesChanged: string[];
|
|
333
|
+
/** 2-3 sentence body summary, already truncated to 1024 chars. */
|
|
334
|
+
summary: string;
|
|
335
|
+
/** Canonical https://github.com/<owner>/<repo>/pull/<n> URL. */
|
|
336
|
+
url: string;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
export function prsDir(cwd: string): string {
|
|
340
|
+
return join(cwd, ".ashlrcode", "genome", "sections", PRS_SUBDIR);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export function prSectionPath(_cwd: string, id: string): string {
|
|
344
|
+
return join("sections", PRS_SUBDIR, `${id}.json`);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export function prSectionAbsPath(cwd: string, id: string): string {
|
|
348
|
+
return join(prsDir(cwd), `${id}.json`);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export async function writePrSectionFile(
|
|
352
|
+
cwd: string,
|
|
353
|
+
payload: PrSection,
|
|
354
|
+
): Promise<string> {
|
|
355
|
+
const abs = prSectionAbsPath(cwd, payload.id);
|
|
356
|
+
const dir = dirname(abs);
|
|
357
|
+
if (!existsSync(dir)) {
|
|
358
|
+
await mkdir(dir, { recursive: true });
|
|
359
|
+
}
|
|
360
|
+
await writeFile(abs, JSON.stringify(payload, null, 2), "utf-8");
|
|
361
|
+
return prSectionPath(cwd, payload.id);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
export async function readPrSectionFile(
|
|
365
|
+
cwd: string,
|
|
366
|
+
id: string,
|
|
367
|
+
): Promise<PrSection | null> {
|
|
368
|
+
const abs = prSectionAbsPath(cwd, id);
|
|
369
|
+
if (!existsSync(abs)) return null;
|
|
370
|
+
try {
|
|
371
|
+
const raw = await readFile(abs, "utf-8");
|
|
372
|
+
return JSON.parse(raw) as PrSection;
|
|
373
|
+
} catch {
|
|
374
|
+
return null;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// ---------------------------------------------------------------------------
|
|
379
|
+
// Issue sections (Q3 PR/Issue Retrieval)
|
|
380
|
+
// ---------------------------------------------------------------------------
|
|
381
|
+
|
|
382
|
+
/** Subdirectory under .ashlrcode/genome/sections/ where Issue sections live. */
|
|
383
|
+
export const ISSUES_SUBDIR = "issues";
|
|
384
|
+
|
|
385
|
+
/** Hard cap on Issue sections kept on disk. Older ones are pruned by mtime. */
|
|
386
|
+
export const ISSUE_RETENTION_LIMIT = 100;
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Issue section payload — stored at
|
|
390
|
+
* `.ashlrcode/genome/sections/issues/<number>.json`. Populated from
|
|
391
|
+
* `issue_closed` deltas via genome-cloud-sync.
|
|
392
|
+
*/
|
|
393
|
+
export interface IssueSection {
|
|
394
|
+
/** Issue number as a string id. */
|
|
395
|
+
id: string;
|
|
396
|
+
/** Issue title (already truncated to 512 chars). */
|
|
397
|
+
title: string;
|
|
398
|
+
/** ISO timestamp when the issue was closed. May be empty. */
|
|
399
|
+
closedAt: string;
|
|
400
|
+
/** GitHub login of the issue author. May be empty. */
|
|
401
|
+
author: string;
|
|
402
|
+
/** Issue labels — currently empty (webhook does not yet ship labels). */
|
|
403
|
+
labels: string[];
|
|
404
|
+
/** Issue body summary, truncated to 1024 chars. */
|
|
405
|
+
summary: string;
|
|
406
|
+
/** Canonical https://github.com/<owner>/<repo>/issues/<n> URL. */
|
|
407
|
+
url: string;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
export function issuesDir(cwd: string): string {
|
|
411
|
+
return join(cwd, ".ashlrcode", "genome", "sections", ISSUES_SUBDIR);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
export function issueSectionPath(_cwd: string, id: string): string {
|
|
415
|
+
return join("sections", ISSUES_SUBDIR, `${id}.json`);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
export function issueSectionAbsPath(cwd: string, id: string): string {
|
|
419
|
+
return join(issuesDir(cwd), `${id}.json`);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
export async function writeIssueSectionFile(
|
|
423
|
+
cwd: string,
|
|
424
|
+
payload: IssueSection,
|
|
425
|
+
): Promise<string> {
|
|
426
|
+
const abs = issueSectionAbsPath(cwd, payload.id);
|
|
427
|
+
const dir = dirname(abs);
|
|
428
|
+
if (!existsSync(dir)) {
|
|
429
|
+
await mkdir(dir, { recursive: true });
|
|
430
|
+
}
|
|
431
|
+
await writeFile(abs, JSON.stringify(payload, null, 2), "utf-8");
|
|
432
|
+
return issueSectionPath(cwd, payload.id);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
export async function readIssueSectionFile(
|
|
436
|
+
cwd: string,
|
|
437
|
+
id: string,
|
|
438
|
+
): Promise<IssueSection | null> {
|
|
439
|
+
const abs = issueSectionAbsPath(cwd, id);
|
|
440
|
+
if (!existsSync(abs)) return null;
|
|
441
|
+
try {
|
|
442
|
+
const raw = await readFile(abs, "utf-8");
|
|
443
|
+
return JSON.parse(raw) as IssueSection;
|
|
444
|
+
} catch {
|
|
445
|
+
return null;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-host MCP detection.
|
|
3
|
+
*
|
|
4
|
+
* The ashlr MCP server is consumable from any MCP-capable host (Claude Code,
|
|
5
|
+
* Cline, Claude Desktop, OpenAI Codex CLI, …). Most behavior is host-agnostic:
|
|
6
|
+
* - tool dispatch, snipCompact, genome retrieval, stats accounting all work
|
|
7
|
+
* regardless of who's calling.
|
|
8
|
+
* - PPID-derived session id (see `_stats.ts::ppidSessionId`) covers any host
|
|
9
|
+
* that doesn't forward `CLAUDE_SESSION_ID`.
|
|
10
|
+
* - `existsSync` guards on `~/.claude/` paths mean missing-CC-dirs are a
|
|
11
|
+
* no-op rather than a crash.
|
|
12
|
+
*
|
|
13
|
+
* But a few code paths are Claude-Code-specific (hook firing, status-line
|
|
14
|
+
* rendering, OAuth-token harvest from `~/.claude/.credentials.json`). The
|
|
15
|
+
* `ASHLR_MCP_HOST` env var declares which host launched us so those code
|
|
16
|
+
* paths can short-circuit cleanly when running under a non-CC host.
|
|
17
|
+
*
|
|
18
|
+
* Each host's MCP server config sets the env var:
|
|
19
|
+
*
|
|
20
|
+
* Claude Code (default, no change needed) → undefined or "claude-code"
|
|
21
|
+
* Cline (cline_mcp_settings.json) → "cline"
|
|
22
|
+
* Claude Desktop (claude_desktop_config.json) → "claude-desktop"
|
|
23
|
+
* Codex CLI (~/.codex/config.toml) → "codex-cli"
|
|
24
|
+
* Anything else → "generic"
|
|
25
|
+
*
|
|
26
|
+
* Backwards compat: when unset, we infer "claude-code" so existing installs
|
|
27
|
+
* keep their exact current behavior. The audit covered every gate; none of
|
|
28
|
+
* them change behavior when the env var is absent.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
export type McpHost =
|
|
32
|
+
| "claude-code"
|
|
33
|
+
| "cline"
|
|
34
|
+
| "claude-desktop"
|
|
35
|
+
| "codex-cli"
|
|
36
|
+
| "generic";
|
|
37
|
+
|
|
38
|
+
const KNOWN_HOSTS: ReadonlySet<McpHost> = new Set([
|
|
39
|
+
"claude-code",
|
|
40
|
+
"cline",
|
|
41
|
+
"claude-desktop",
|
|
42
|
+
"codex-cli",
|
|
43
|
+
"generic",
|
|
44
|
+
]);
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Resolve which MCP host launched this process.
|
|
48
|
+
*
|
|
49
|
+
* Precedence:
|
|
50
|
+
* 1. `ASHLR_MCP_HOST` env var (explicit, set by each host's config snippet).
|
|
51
|
+
* 2. Presence of `CLAUDE_SESSION_ID` or `CLAUDE_PLUGIN_ROOT` → "claude-code"
|
|
52
|
+
* (covers the default Claude Code install path so users who don't set
|
|
53
|
+
* the env var still see the original behavior).
|
|
54
|
+
* 3. Fallback "generic" — safe default; disables CC-only side effects.
|
|
55
|
+
*
|
|
56
|
+
* Never throws; never reads files; never logs. Cheap to call repeatedly.
|
|
57
|
+
*/
|
|
58
|
+
export function detectMcpHost(env: NodeJS.ProcessEnv = process.env): McpHost {
|
|
59
|
+
const explicit = env.ASHLR_MCP_HOST?.trim().toLowerCase();
|
|
60
|
+
if (explicit && KNOWN_HOSTS.has(explicit as McpHost)) {
|
|
61
|
+
return explicit as McpHost;
|
|
62
|
+
}
|
|
63
|
+
// Inference: any of these signals → Claude Code (preserves existing
|
|
64
|
+
// behavior for users who haven't set ASHLR_MCP_HOST).
|
|
65
|
+
if (
|
|
66
|
+
(env.CLAUDE_SESSION_ID && env.CLAUDE_SESSION_ID.trim().length > 0) ||
|
|
67
|
+
(env.CLAUDE_PLUGIN_ROOT && env.CLAUDE_PLUGIN_ROOT.trim().length > 0) ||
|
|
68
|
+
(env.CLAUDE_CODE_MODEL && env.CLAUDE_CODE_MODEL.trim().length > 0)
|
|
69
|
+
) {
|
|
70
|
+
return "claude-code";
|
|
71
|
+
}
|
|
72
|
+
// Generic is the safe non-CC default: hooks/status-line code paths
|
|
73
|
+
// short-circuit; stats + genome + dispatch still work normally.
|
|
74
|
+
return "generic";
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Convenience: are we running inside Claude Code (the default host)? */
|
|
78
|
+
export function isClaudeCodeHost(env: NodeJS.ProcessEnv = process.env): boolean {
|
|
79
|
+
return detectMcpHost(env) === "claude-code";
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Convenience: should we skip Claude-Code-specific side effects?
|
|
84
|
+
* Returns true for every non-CC host. Used by:
|
|
85
|
+
* - status-line install nudges (other hosts have their own UI)
|
|
86
|
+
* - `~/.claude/settings.json` writes (other hosts use their own config)
|
|
87
|
+
* - hook-firing assumptions (only CC fires PreToolUse/SessionEnd hooks)
|
|
88
|
+
*/
|
|
89
|
+
export function skipClaudeCodeSideEffects(
|
|
90
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
91
|
+
): boolean {
|
|
92
|
+
return detectMcpHost(env) !== "claude-code";
|
|
93
|
+
}
|