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,263 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* _genome-live.ts — in-process genome section refresh after ashlr__edit.
|
|
3
|
+
*
|
|
4
|
+
* When ashlr__edit writes a file, call refreshGenomeAfterEdit to patch any
|
|
5
|
+
* genome sections that embed the edited content verbatim. Sections that only
|
|
6
|
+
* summarize the file (no literal content match) are invalidated (deleted) so
|
|
7
|
+
* the propose queue regenerates them.
|
|
8
|
+
*
|
|
9
|
+
* Design constraints:
|
|
10
|
+
* - Never throws — returns {updated:0,skipped:0} on any failure.
|
|
11
|
+
* - Fire-and-forget safe: callers use .catch(()=>{}) and never await.
|
|
12
|
+
* - Honors ASHLR_GENOME_AUTO=0 as a kill switch.
|
|
13
|
+
* - File-level serialization via a simple in-process mutex Map.
|
|
14
|
+
* - Calls _clearCache() so the LRU evicts stale genome retrievals.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { readFile, writeFile, unlink } from "fs/promises";
|
|
18
|
+
import { existsSync } from "fs";
|
|
19
|
+
import { dirname, basename, join } from "path";
|
|
20
|
+
|
|
21
|
+
import {
|
|
22
|
+
genomeExists,
|
|
23
|
+
loadManifest,
|
|
24
|
+
saveManifest,
|
|
25
|
+
sectionPath,
|
|
26
|
+
type GenomeManifest,
|
|
27
|
+
} from "@ashlr/core-efficiency/genome";
|
|
28
|
+
import { _clearCache } from "./_genome-cache";
|
|
29
|
+
|
|
30
|
+
const MAX_GENOME_WALK = 8;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Walk up from `startDir` (inclusive) looking for a directory that contains
|
|
34
|
+
* `.ashlrcode/genome/manifest.json`. No $HOME cap — this is an internal
|
|
35
|
+
* helper used only after a write, so we trust the path is valid.
|
|
36
|
+
*/
|
|
37
|
+
function findGenomeRoot(startDir: string): string | null {
|
|
38
|
+
let current = startDir;
|
|
39
|
+
for (let i = 0; i <= MAX_GENOME_WALK; i++) {
|
|
40
|
+
if (genomeExists(current)) return current;
|
|
41
|
+
const parent = dirname(current);
|
|
42
|
+
if (parent === current) return null; // filesystem root
|
|
43
|
+
current = parent;
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// Public API
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
|
|
52
|
+
export interface RefreshResult {
|
|
53
|
+
updated: number;
|
|
54
|
+
skipped: number;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* After a successful ashlr__edit, patch genome sections that reference the
|
|
59
|
+
* edited file. Verbatim sections get a string-replace; summarized sections
|
|
60
|
+
* are deleted so the propose queue can regenerate them.
|
|
61
|
+
*
|
|
62
|
+
* @param absolutePath Absolute path of the file that was edited.
|
|
63
|
+
* @param editBefore The `search` string that was replaced.
|
|
64
|
+
* @param editAfter The `replace` string that was inserted.
|
|
65
|
+
*/
|
|
66
|
+
export async function refreshGenomeAfterEdit(
|
|
67
|
+
absolutePath: string,
|
|
68
|
+
editBefore: string,
|
|
69
|
+
editAfter: string,
|
|
70
|
+
): Promise<RefreshResult> {
|
|
71
|
+
// Kill switch — same flag genome-auto-propose.ts respects.
|
|
72
|
+
if (process.env.ASHLR_GENOME_AUTO === "0") {
|
|
73
|
+
return { updated: 0, skipped: 0 };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
return await _refreshSafe(absolutePath, editBefore, editAfter);
|
|
78
|
+
} catch {
|
|
79
|
+
return { updated: 0, skipped: 0 };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
// Internal implementation
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Simple per-genomeRoot serialization mutex.
|
|
89
|
+
* Two concurrent edits to files under the same genome root are sequenced so
|
|
90
|
+
* both manifest read-modify-writes land coherently.
|
|
91
|
+
*/
|
|
92
|
+
const locks = new Map<string, Promise<unknown>>();
|
|
93
|
+
|
|
94
|
+
function withLock<T>(key: string, fn: () => Promise<T>): Promise<T> {
|
|
95
|
+
const prev = locks.get(key) ?? Promise.resolve();
|
|
96
|
+
const next: Promise<T> = prev.then(fn, fn as () => Promise<T>);
|
|
97
|
+
// best-effort: this `settled` shadow exists only to break rejection chaining for the *next* lock waiter; the real error still rides on `next` and is returned to the caller.
|
|
98
|
+
const settled = next.catch(() => {});
|
|
99
|
+
locks.set(key, settled);
|
|
100
|
+
settled.then(() => {
|
|
101
|
+
if (locks.get(key) === settled) locks.delete(key);
|
|
102
|
+
});
|
|
103
|
+
return next;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async function _refreshSafe(
|
|
107
|
+
absolutePath: string,
|
|
108
|
+
editBefore: string,
|
|
109
|
+
editAfter: string,
|
|
110
|
+
): Promise<RefreshResult> {
|
|
111
|
+
// Resolve genome root — walk up from the file's directory checking for a
|
|
112
|
+
// genome at each level. We check the file's own dir first (unlike
|
|
113
|
+
// findParentGenome which skips startDir), then ancestors up to 8 levels.
|
|
114
|
+
// We don't apply the $HOME cap here because edited files may be anywhere
|
|
115
|
+
// (e.g. tmpdir during tests, or monorepo subdirs outside HOME).
|
|
116
|
+
const fileDir = dirname(absolutePath) || "/";
|
|
117
|
+
const genomeRoot = findGenomeRoot(fileDir);
|
|
118
|
+
|
|
119
|
+
if (!genomeRoot) return { updated: 0, skipped: 0 };
|
|
120
|
+
|
|
121
|
+
return withLock(genomeRoot, () =>
|
|
122
|
+
_refreshUnderLock(genomeRoot!, absolutePath, editBefore, editAfter),
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async function _refreshUnderLock(
|
|
127
|
+
genomeRoot: string,
|
|
128
|
+
absolutePath: string,
|
|
129
|
+
editBefore: string,
|
|
130
|
+
editAfter: string,
|
|
131
|
+
): Promise<RefreshResult> {
|
|
132
|
+
const manifest = await loadManifest(genomeRoot);
|
|
133
|
+
if (!manifest) return { updated: 0, skipped: 0 };
|
|
134
|
+
|
|
135
|
+
// Find sections that reference this file. The heuristic: a section's path
|
|
136
|
+
// component or its content will mention the file's basename / relative path.
|
|
137
|
+
// We check section *content* for the actual literal match — not the section
|
|
138
|
+
// path — because a section can embed any number of files.
|
|
139
|
+
const matchingSections = await findSectionsForFile(
|
|
140
|
+
genomeRoot,
|
|
141
|
+
manifest,
|
|
142
|
+
absolutePath,
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
if (matchingSections.length === 0) return { updated: 0, skipped: 0 };
|
|
146
|
+
|
|
147
|
+
let updated = 0;
|
|
148
|
+
let skipped = 0;
|
|
149
|
+
let manifestDirty = false;
|
|
150
|
+
|
|
151
|
+
for (const sectionRel of matchingSections) {
|
|
152
|
+
const absSection = sectionPath(genomeRoot, sectionRel);
|
|
153
|
+
let sectionContent: string;
|
|
154
|
+
try {
|
|
155
|
+
sectionContent = await readFile(absSection, "utf-8");
|
|
156
|
+
} catch {
|
|
157
|
+
skipped++;
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (isVerbatim(sectionContent, editBefore)) {
|
|
162
|
+
// Literal content found — patch in place.
|
|
163
|
+
const patched = sectionContent.split(editBefore).join(editAfter);
|
|
164
|
+
try {
|
|
165
|
+
await writeFile(absSection, patched, "utf-8");
|
|
166
|
+
// Update the section's updatedAt in the manifest.
|
|
167
|
+
const idx = manifest.sections.findIndex((s) => s.path === sectionRel);
|
|
168
|
+
if (idx >= 0) {
|
|
169
|
+
manifest.sections[idx]!.updatedAt = new Date().toISOString();
|
|
170
|
+
manifestDirty = true;
|
|
171
|
+
}
|
|
172
|
+
updated++;
|
|
173
|
+
} catch {
|
|
174
|
+
skipped++;
|
|
175
|
+
}
|
|
176
|
+
} else {
|
|
177
|
+
// Summarized section — invalidate by deleting. The propose queue will
|
|
178
|
+
// regenerate it on the next SessionEnd or ≥3-proposal flush.
|
|
179
|
+
try {
|
|
180
|
+
await unlink(absSection);
|
|
181
|
+
// Remove the section from the manifest.
|
|
182
|
+
const idx = manifest.sections.findIndex((s) => s.path === sectionRel);
|
|
183
|
+
if (idx >= 0) {
|
|
184
|
+
manifest.sections.splice(idx, 1);
|
|
185
|
+
manifestDirty = true;
|
|
186
|
+
}
|
|
187
|
+
skipped++; // counted as skipped (invalidated, not patched)
|
|
188
|
+
} catch {
|
|
189
|
+
skipped++;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (manifestDirty) {
|
|
195
|
+
manifest.updatedAt = new Date().toISOString();
|
|
196
|
+
await saveManifest(genomeRoot, manifest);
|
|
197
|
+
// Evict in-process LRU so future ashlr__grep calls re-read from disk.
|
|
198
|
+
_clearCache();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return { updated, skipped };
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// ---------------------------------------------------------------------------
|
|
205
|
+
// Helpers
|
|
206
|
+
// ---------------------------------------------------------------------------
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Find section relative paths whose content references `absolutePath`.
|
|
210
|
+
*
|
|
211
|
+
* Strategy: read each section file and check whether it mentions the file
|
|
212
|
+
* (by absolute path, or by the filename). We only look at sections that have
|
|
213
|
+
* a non-trivial probability of embedding the file — sections whose title,
|
|
214
|
+
* summary, or tags contain the filename are strong candidates; we also check
|
|
215
|
+
* all sections by content to catch unlabeled embeds.
|
|
216
|
+
*/
|
|
217
|
+
async function findSectionsForFile(
|
|
218
|
+
genomeRoot: string,
|
|
219
|
+
manifest: GenomeManifest,
|
|
220
|
+
absolutePath: string,
|
|
221
|
+
): Promise<string[]> {
|
|
222
|
+
const fileName = basename(absolutePath);
|
|
223
|
+
const results: string[] = [];
|
|
224
|
+
|
|
225
|
+
for (const section of manifest.sections) {
|
|
226
|
+
const absSection = sectionPath(genomeRoot, section.path);
|
|
227
|
+
if (!existsSync(absSection)) continue;
|
|
228
|
+
|
|
229
|
+
// Fast pre-filter: does the manifest metadata hint at this file?
|
|
230
|
+
const metaHint =
|
|
231
|
+
section.title.includes(fileName) ||
|
|
232
|
+
section.summary.includes(fileName) ||
|
|
233
|
+
section.tags.some((t) => t.includes(fileName)) ||
|
|
234
|
+
section.path.includes(fileName);
|
|
235
|
+
|
|
236
|
+
let sectionContent: string;
|
|
237
|
+
try {
|
|
238
|
+
sectionContent = await readFile(absSection, "utf-8");
|
|
239
|
+
} catch {
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Check if the section content references the file path or filename.
|
|
244
|
+
if (
|
|
245
|
+
metaHint ||
|
|
246
|
+
sectionContent.includes(absolutePath) ||
|
|
247
|
+
sectionContent.includes(fileName)
|
|
248
|
+
) {
|
|
249
|
+
results.push(section.path);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return results;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Return true when the section content contains a fenced code block that
|
|
258
|
+
* includes `editBefore` verbatim, OR when `editBefore` appears literally
|
|
259
|
+
* anywhere in the section content (covers inline snippets too).
|
|
260
|
+
*/
|
|
261
|
+
function isVerbatim(sectionContent: string, editBefore: string): boolean {
|
|
262
|
+
return sectionContent.includes(editBefore);
|
|
263
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* _genome-prs.ts — surface merged-PR sections in ashlr__grep retrieval.
|
|
3
|
+
*
|
|
4
|
+
* Q3 cousin of _genome-commits.ts. PR sections are written by
|
|
5
|
+
* scripts/genome-cloud-sync.ts when a `pr_merged` cloud delta arrives. The
|
|
6
|
+
* grep handler calls retrievePrSections() to surface relevant merged PRs
|
|
7
|
+
* alongside code matches — so `ashlr__grep "auth bug"` can return both the
|
|
8
|
+
* code and the PR that recently fixed it.
|
|
9
|
+
*
|
|
10
|
+
* Unlike commits + discoveries (which gate retrieval on the v2 manifest),
|
|
11
|
+
* PR retrieval scans the on-disk `sections/prs/` directory directly because
|
|
12
|
+
* cloud-sync writes those files OUT-OF-BAND from the manifest. This keeps
|
|
13
|
+
* the cloud path simple — no manifest mutation per delta — and means
|
|
14
|
+
* retrieval still works when a teammate runs `ashlr-genome-pull` and then
|
|
15
|
+
* immediately greps before the next save bumps the manifest.
|
|
16
|
+
*
|
|
17
|
+
* Best-effort, fails-silent. Any I/O failure returns [].
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { readFile, readdir, stat } from "fs/promises";
|
|
21
|
+
import { existsSync } from "fs";
|
|
22
|
+
import { join } from "path";
|
|
23
|
+
import { type PrSection, prsDir } from "./_manifest-v2";
|
|
24
|
+
import { scoreSectionMeta, tokenize } from "./_genome-commits";
|
|
25
|
+
import { formatFreshness } from "./_genome-freshness";
|
|
26
|
+
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
// Public API
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
|
|
31
|
+
export interface RetrievedPr {
|
|
32
|
+
id: string;
|
|
33
|
+
title: string;
|
|
34
|
+
mergedAt: string;
|
|
35
|
+
author: string;
|
|
36
|
+
filesChanged: string[];
|
|
37
|
+
summary: string;
|
|
38
|
+
url: string;
|
|
39
|
+
score: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Retrieve up to `limit` PR sections from `sections/prs/` matching `query`.
|
|
44
|
+
*
|
|
45
|
+
* @param cwd genome root (the directory containing `.ashlrcode/`)
|
|
46
|
+
* @param query keyword query — same scorer the commit + discovery
|
|
47
|
+
* retrievers use (tag/title/summary weighted)
|
|
48
|
+
* @param limit max results (default 3)
|
|
49
|
+
* @param sinceDays optional freshness filter — drop PRs merged longer than
|
|
50
|
+
* N days ago. `undefined` disables the filter.
|
|
51
|
+
*
|
|
52
|
+
* Returns [] when no PRs match, when the dir doesn't exist, when the
|
|
53
|
+
* manifest is missing — never throws.
|
|
54
|
+
*/
|
|
55
|
+
export async function retrievePrSections(
|
|
56
|
+
cwd: string,
|
|
57
|
+
query: string,
|
|
58
|
+
limit = 3,
|
|
59
|
+
sinceDays?: number,
|
|
60
|
+
): Promise<RetrievedPr[]> {
|
|
61
|
+
try {
|
|
62
|
+
const dir = prsDir(cwd);
|
|
63
|
+
if (!existsSync(dir)) return [];
|
|
64
|
+
|
|
65
|
+
let entries: string[];
|
|
66
|
+
try {
|
|
67
|
+
entries = await readdir(dir);
|
|
68
|
+
} catch {
|
|
69
|
+
return [];
|
|
70
|
+
}
|
|
71
|
+
const files = entries.filter((n) => n.endsWith(".json"));
|
|
72
|
+
if (files.length === 0) return [];
|
|
73
|
+
|
|
74
|
+
const cutoff =
|
|
75
|
+
typeof sinceDays === "number" && Number.isFinite(sinceDays) && sinceDays > 0
|
|
76
|
+
? Date.now() - sinceDays * 24 * 60 * 60 * 1000
|
|
77
|
+
: null;
|
|
78
|
+
|
|
79
|
+
// Load every PR file. The retention limit caps this at PR_RETENTION_LIMIT
|
|
80
|
+
// (100 default) so even a full scan is cheap. We deliberately don't
|
|
81
|
+
// route through the v2 manifest: cloud-sync writes PR files out-of-band
|
|
82
|
+
// (no manifest update per delta) so the manifest may not yet list them.
|
|
83
|
+
const loaded: Array<{ section: PrSection; mtimeMs: number }> = [];
|
|
84
|
+
for (const file of files) {
|
|
85
|
+
const abs = join(dir, file);
|
|
86
|
+
try {
|
|
87
|
+
const [raw, st] = await Promise.all([readFile(abs, "utf-8"), stat(abs)]);
|
|
88
|
+
const section = JSON.parse(raw) as PrSection;
|
|
89
|
+
if (!section || typeof section !== "object") continue;
|
|
90
|
+
loaded.push({ section, mtimeMs: st.mtimeMs });
|
|
91
|
+
} catch {
|
|
92
|
+
// Skip corrupt file, keep going.
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const queryTerms = new Set(tokenize(query));
|
|
97
|
+
|
|
98
|
+
// Build a SectionMetaV2-shaped object on the fly so we can reuse the
|
|
99
|
+
// same scorer the commit + discovery retrievers use. Tags pull from the
|
|
100
|
+
// PR author + filesChanged so file-path queries can still hit ("login"
|
|
101
|
+
// → tag "auth/login.ts" → score boost).
|
|
102
|
+
const scored = loaded
|
|
103
|
+
.map(({ section, mtimeMs }) => {
|
|
104
|
+
// Freshness filter — drop PRs older than the cutoff.
|
|
105
|
+
if (cutoff !== null) {
|
|
106
|
+
const t = section.mergedAt ? Date.parse(section.mergedAt) : NaN;
|
|
107
|
+
if (Number.isFinite(t) && t < cutoff) {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const tags = [
|
|
112
|
+
"pr",
|
|
113
|
+
"pull-request",
|
|
114
|
+
section.id,
|
|
115
|
+
...(section.author ? [section.author.toLowerCase()] : []),
|
|
116
|
+
...section.filesChanged.slice(0, 10).map((p) => p.toLowerCase()),
|
|
117
|
+
];
|
|
118
|
+
const meta = {
|
|
119
|
+
path: `prs/${section.id}.json`,
|
|
120
|
+
title: section.title,
|
|
121
|
+
summary: section.summary,
|
|
122
|
+
tags,
|
|
123
|
+
tokens: Math.ceil((section.title.length + section.summary.length) / 4),
|
|
124
|
+
updatedAt: section.mergedAt || new Date(mtimeMs).toISOString(),
|
|
125
|
+
};
|
|
126
|
+
let score: number;
|
|
127
|
+
if (queryTerms.size === 0) {
|
|
128
|
+
// No meaningful query — surface the most recently merged PRs.
|
|
129
|
+
score = 1;
|
|
130
|
+
} else {
|
|
131
|
+
score = scoreSectionMeta(meta, queryTerms);
|
|
132
|
+
}
|
|
133
|
+
return { section, score, mtimeMs };
|
|
134
|
+
})
|
|
135
|
+
.filter((x): x is { section: PrSection; score: number; mtimeMs: number } => x !== null && x.score > 0);
|
|
136
|
+
|
|
137
|
+
if (scored.length === 0) return [];
|
|
138
|
+
|
|
139
|
+
// Sort by score desc, then mergedAt desc (most recent wins ties).
|
|
140
|
+
scored.sort((a, b) => {
|
|
141
|
+
if (b.score !== a.score) return b.score - a.score;
|
|
142
|
+
const ad = a.section.mergedAt || new Date(a.mtimeMs).toISOString();
|
|
143
|
+
const bd = b.section.mergedAt || new Date(b.mtimeMs).toISOString();
|
|
144
|
+
return bd > ad ? 1 : bd < ad ? -1 : 0;
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
return scored.slice(0, limit).map(({ section, score }) => ({
|
|
148
|
+
id: section.id,
|
|
149
|
+
title: section.title,
|
|
150
|
+
mergedAt: section.mergedAt,
|
|
151
|
+
author: section.author,
|
|
152
|
+
filesChanged: section.filesChanged,
|
|
153
|
+
summary: section.summary,
|
|
154
|
+
url: section.url,
|
|
155
|
+
score,
|
|
156
|
+
}));
|
|
157
|
+
} catch {
|
|
158
|
+
return [];
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Format a list of retrieved PR sections as a markdown block suitable for
|
|
164
|
+
* prepending to grep output. Each PR gets a distinct `[PR #<n> - <date>]`
|
|
165
|
+
* header so the model + user know it's GitHub history, not static code.
|
|
166
|
+
*
|
|
167
|
+
* Freshness badge is decorated when mergedAt parses. Matches the
|
|
168
|
+
* `_genome-commits` formatter conventions.
|
|
169
|
+
*/
|
|
170
|
+
export function formatPrsForPrompt(prs: RetrievedPr[], now: Date = new Date()): string {
|
|
171
|
+
if (prs.length === 0) return "";
|
|
172
|
+
const parts = prs.map((p) => {
|
|
173
|
+
const dateShort = p.mergedAt ? p.mergedAt.slice(0, 10) : "unknown";
|
|
174
|
+
const badge = formatFreshness(p.mergedAt || undefined, now);
|
|
175
|
+
const badgeFragment = badge ? ` · ${badge.slice(1, -1)}` : "";
|
|
176
|
+
const files =
|
|
177
|
+
p.filesChanged.length === 0
|
|
178
|
+
? ""
|
|
179
|
+
: `\n_files: ${p.filesChanged.slice(0, 6).join(", ")}${
|
|
180
|
+
p.filesChanged.length > 6 ? ` (+${p.filesChanged.length - 6})` : ""
|
|
181
|
+
}_\n`;
|
|
182
|
+
const author = p.author ? `_author: ${p.author}_\n` : "";
|
|
183
|
+
const link = p.url ? `_${p.url}_\n` : "";
|
|
184
|
+
return `### [PR #${p.id} - ${dateShort}${badgeFragment}] ${p.title}${files}${author}${link}
|
|
185
|
+
${p.summary}`;
|
|
186
|
+
});
|
|
187
|
+
return `## Pull Requests\n\n${parts.join("\n\n---\n\n")}`;
|
|
188
|
+
}
|