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,364 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* genome-refresh-worker.ts — Incremental genome refresh for edited files.
|
|
4
|
+
*
|
|
5
|
+
* Reads ~/.ashlr/pending-genome-refresh.txt, groups paths by their genome
|
|
6
|
+
* root, and incrementally refreshes affected genome sections using the
|
|
7
|
+
* in-process _genome-live refresh logic. Clears the pending list on success.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* bun run scripts/genome-refresh-worker.ts [--full] [--dry-run] [--quiet]
|
|
11
|
+
*
|
|
12
|
+
* --full Force a full genome rebuild (re-runs genome-init for each
|
|
13
|
+
* project). WARNING: may trigger LLM summarization if Ollama is
|
|
14
|
+
* available. Use sparingly.
|
|
15
|
+
* --dry-run Print what would be refreshed, but don't write anything.
|
|
16
|
+
* --quiet Suppress all output (used when invoked from session-end hook).
|
|
17
|
+
*
|
|
18
|
+
* Design rules:
|
|
19
|
+
* - Incremental refresh by default — never full LLM-rebuilds unless --full.
|
|
20
|
+
* - Kill switch: ASHLR_GENOME_AUTO=0 exits immediately.
|
|
21
|
+
* - Never throws — exits 0 always.
|
|
22
|
+
* - Safe to run concurrently (pending-file write uses atomic rename when possible).
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, unlinkSync } from "fs";
|
|
26
|
+
import { stat, writeFile } from "fs/promises";
|
|
27
|
+
import { homedir } from "os";
|
|
28
|
+
import { join, dirname, resolve, isAbsolute } from "path";
|
|
29
|
+
|
|
30
|
+
import { genomeExists } from "@ashlr/core-efficiency/genome";
|
|
31
|
+
import { refreshGenomeAfterEdit } from "../servers/_genome-live";
|
|
32
|
+
import { PENDING_FILE_NAME } from "../hooks/posttooluse-genome-refresh";
|
|
33
|
+
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
// Constants
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
/** Minimum ms since last pending-file write before triggering refresh. */
|
|
39
|
+
const DEBOUNCE_MS_DEFAULT = 2_000;
|
|
40
|
+
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
// CLI args
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
|
|
45
|
+
export interface WorkerArgs {
|
|
46
|
+
full: boolean;
|
|
47
|
+
dryRun: boolean;
|
|
48
|
+
quiet: boolean;
|
|
49
|
+
debounceMs: number;
|
|
50
|
+
home: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function parseArgs(argv: string[]): WorkerArgs {
|
|
54
|
+
let full = false;
|
|
55
|
+
let dryRun = false;
|
|
56
|
+
let quiet = false;
|
|
57
|
+
let debounceMs = DEBOUNCE_MS_DEFAULT;
|
|
58
|
+
let home = homedir();
|
|
59
|
+
|
|
60
|
+
for (let i = 0; i < argv.length; i++) {
|
|
61
|
+
const a = argv[i];
|
|
62
|
+
if (a === "--full") full = true;
|
|
63
|
+
else if (a === "--dry-run") dryRun = true;
|
|
64
|
+
else if (a === "--quiet") quiet = true;
|
|
65
|
+
else if (a === "--debounce" && argv[i + 1]) {
|
|
66
|
+
debounceMs = parseInt(argv[++i], 10) || DEBOUNCE_MS_DEFAULT;
|
|
67
|
+
} else if (a === "--home" && argv[i + 1]) {
|
|
68
|
+
home = argv[++i];
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return { full, dryRun, quiet, debounceMs, home };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
// Pending-file helpers
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
|
|
79
|
+
export function pendingFilePath(home: string): string {
|
|
80
|
+
return join(home, ".ashlr", PENDING_FILE_NAME);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Read pending file and return deduped absolute paths. */
|
|
84
|
+
export function readPendingPaths(home: string): string[] {
|
|
85
|
+
const file = pendingFilePath(home);
|
|
86
|
+
if (!existsSync(file)) return [];
|
|
87
|
+
try {
|
|
88
|
+
const lines = readFileSync(file, "utf-8").split("\n");
|
|
89
|
+
const seen = new Set<string>();
|
|
90
|
+
for (const line of lines) {
|
|
91
|
+
const t = line.trim();
|
|
92
|
+
if (t) {
|
|
93
|
+
const abs = isAbsolute(t) ? t : resolve(t);
|
|
94
|
+
seen.add(abs);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return [...seen];
|
|
98
|
+
} catch {
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Clear the pending file. */
|
|
104
|
+
export function clearPendingFile(home: string): void {
|
|
105
|
+
const file = pendingFilePath(home);
|
|
106
|
+
try {
|
|
107
|
+
if (existsSync(file)) unlinkSync(file);
|
|
108
|
+
} catch {
|
|
109
|
+
/* best-effort */
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
// Genome root resolution
|
|
115
|
+
// ---------------------------------------------------------------------------
|
|
116
|
+
|
|
117
|
+
const MAX_WALK = 8;
|
|
118
|
+
|
|
119
|
+
/** Walk up from `startDir` to find a directory containing .ashlrcode/genome/. */
|
|
120
|
+
export function findGenomeRoot(startDir: string): string | null {
|
|
121
|
+
let current = startDir;
|
|
122
|
+
for (let i = 0; i <= MAX_WALK; i++) {
|
|
123
|
+
if (genomeExists(current)) return current;
|
|
124
|
+
const parent = dirname(current);
|
|
125
|
+
if (parent === current) return null;
|
|
126
|
+
current = parent;
|
|
127
|
+
}
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Group file paths by their genome root. Paths with no genome root are dropped. */
|
|
132
|
+
export function groupByGenomeRoot(
|
|
133
|
+
paths: string[],
|
|
134
|
+
): Map<string, string[]> {
|
|
135
|
+
const map = new Map<string, string[]>();
|
|
136
|
+
for (const p of paths) {
|
|
137
|
+
const dir = dirname(p);
|
|
138
|
+
const root = findGenomeRoot(dir);
|
|
139
|
+
if (!root) continue;
|
|
140
|
+
const list = map.get(root) ?? [];
|
|
141
|
+
list.push(p);
|
|
142
|
+
map.set(root, list);
|
|
143
|
+
}
|
|
144
|
+
return map;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// ---------------------------------------------------------------------------
|
|
148
|
+
// Debounce check
|
|
149
|
+
// ---------------------------------------------------------------------------
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Return true when the pending file is "settled" — its mtime is older than
|
|
153
|
+
* `debounceMs`. If the file doesn't exist or we can't stat it, return true
|
|
154
|
+
* (nothing to debounce).
|
|
155
|
+
*/
|
|
156
|
+
export async function isDebounced(home: string, debounceMs: number): Promise<boolean> {
|
|
157
|
+
const file = pendingFilePath(home);
|
|
158
|
+
if (!existsSync(file)) return true;
|
|
159
|
+
try {
|
|
160
|
+
const s = await stat(file);
|
|
161
|
+
// Clamp ageMs to >= 0: on some CI filesystems mtime can round up past
|
|
162
|
+
// Date.now() (millisecond-grain mtime vs sub-ms Date.now), producing
|
|
163
|
+
// tiny negative values that wrongly fail the debounceMs=0 check.
|
|
164
|
+
const ageMs = Math.max(0, Date.now() - s.mtimeMs);
|
|
165
|
+
return ageMs >= debounceMs;
|
|
166
|
+
} catch {
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// ---------------------------------------------------------------------------
|
|
172
|
+
// Incremental refresh
|
|
173
|
+
// ---------------------------------------------------------------------------
|
|
174
|
+
|
|
175
|
+
export interface RefreshSummary {
|
|
176
|
+
filesProcessed: number;
|
|
177
|
+
sectionsUpdated: number;
|
|
178
|
+
sectionsInvalidated: number;
|
|
179
|
+
genomeRoots: string[];
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Incrementally refresh genome sections for the given file paths.
|
|
184
|
+
*
|
|
185
|
+
* For each file, calls refreshGenomeAfterEdit with empty before/after strings.
|
|
186
|
+
* With empty editBefore, the live-refresh logic will not find any verbatim
|
|
187
|
+
* match, causing it to check all sections that reference the file by name and
|
|
188
|
+
* invalidate them — which is the correct behavior for an "unknown what changed"
|
|
189
|
+
* refresh: mark the section stale so the propose queue can regenerate it.
|
|
190
|
+
*
|
|
191
|
+
* This is intentionally conservative: we never guess at content, we just
|
|
192
|
+
* invalidate anything that references the file.
|
|
193
|
+
*/
|
|
194
|
+
export async function refreshPaths(
|
|
195
|
+
paths: string[],
|
|
196
|
+
opts: { dryRun?: boolean; quiet?: boolean } = {},
|
|
197
|
+
): Promise<RefreshSummary> {
|
|
198
|
+
const summary: RefreshSummary = {
|
|
199
|
+
filesProcessed: 0,
|
|
200
|
+
sectionsUpdated: 0,
|
|
201
|
+
sectionsInvalidated: 0,
|
|
202
|
+
genomeRoots: [],
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
const grouped = groupByGenomeRoot(paths);
|
|
206
|
+
for (const root of grouped.keys()) {
|
|
207
|
+
if (!summary.genomeRoots.includes(root)) {
|
|
208
|
+
summary.genomeRoots.push(root);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (opts.dryRun) {
|
|
213
|
+
if (!opts.quiet) {
|
|
214
|
+
const total = paths.length;
|
|
215
|
+
const roots = summary.genomeRoots.length;
|
|
216
|
+
process.stderr.write(
|
|
217
|
+
`[genome-refresh-worker] dry-run: would refresh ${total} file(s) across ${roots} genome root(s)\n`,
|
|
218
|
+
);
|
|
219
|
+
for (const [root, filePaths] of grouped) {
|
|
220
|
+
process.stderr.write(` genome: ${root}\n`);
|
|
221
|
+
for (const p of filePaths) process.stderr.write(` ${p}\n`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return summary;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
for (const [, filePaths] of grouped) {
|
|
228
|
+
for (const filePath of filePaths) {
|
|
229
|
+
try {
|
|
230
|
+
// Pass empty strings: refreshGenomeAfterEdit will find sections that
|
|
231
|
+
// reference this file (by filename/path) and invalidate them since
|
|
232
|
+
// no verbatim match exists for "". This is the incremental-stale path.
|
|
233
|
+
const result = await refreshGenomeAfterEdit(filePath, "", "");
|
|
234
|
+
summary.filesProcessed++;
|
|
235
|
+
summary.sectionsUpdated += result.updated;
|
|
236
|
+
summary.sectionsInvalidated += result.skipped;
|
|
237
|
+
} catch {
|
|
238
|
+
/* individual file failures don't stop the batch */
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return summary;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// ---------------------------------------------------------------------------
|
|
247
|
+
// Full rebuild
|
|
248
|
+
// ---------------------------------------------------------------------------
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Trigger a full genome rebuild for each affected genome root.
|
|
252
|
+
* Calls genome-init.ts with --force --minimal so it skips LLM summarization.
|
|
253
|
+
* The caller can pass --full explicitly to also run Ollama summarization.
|
|
254
|
+
*/
|
|
255
|
+
export async function fullRebuild(
|
|
256
|
+
genomeRoots: string[],
|
|
257
|
+
opts: { quiet?: boolean; dryRun?: boolean } = {},
|
|
258
|
+
): Promise<void> {
|
|
259
|
+
const scriptDir = dirname(new URL(import.meta.url).pathname);
|
|
260
|
+
const initScript = join(scriptDir, "genome-init.ts");
|
|
261
|
+
|
|
262
|
+
if (!existsSync(initScript)) {
|
|
263
|
+
if (!opts.quiet)
|
|
264
|
+
process.stderr.write("[genome-refresh-worker] genome-init.ts not found — skipping full rebuild\n");
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
for (const root of genomeRoots) {
|
|
269
|
+
if (!opts.quiet)
|
|
270
|
+
process.stderr.write(`[genome-refresh-worker] full rebuild: ${root}\n`);
|
|
271
|
+
if (opts.dryRun) continue;
|
|
272
|
+
|
|
273
|
+
try {
|
|
274
|
+
const proc = Bun.spawn(
|
|
275
|
+
["bun", "run", initScript, "--dir", root, "--force", "--minimal"],
|
|
276
|
+
{ stdin: "ignore", stdout: "ignore", stderr: "pipe" },
|
|
277
|
+
);
|
|
278
|
+
await proc.exited;
|
|
279
|
+
} catch {
|
|
280
|
+
/* best-effort */
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// ---------------------------------------------------------------------------
|
|
286
|
+
// Main
|
|
287
|
+
// ---------------------------------------------------------------------------
|
|
288
|
+
|
|
289
|
+
export async function run(args: WorkerArgs): Promise<RefreshSummary> {
|
|
290
|
+
// Kill switch
|
|
291
|
+
if (process.env.ASHLR_GENOME_AUTO === "0") {
|
|
292
|
+
return {
|
|
293
|
+
filesProcessed: 0,
|
|
294
|
+
sectionsUpdated: 0,
|
|
295
|
+
sectionsInvalidated: 0,
|
|
296
|
+
genomeRoots: [],
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const paths = readPendingPaths(args.home);
|
|
301
|
+
if (paths.length === 0) {
|
|
302
|
+
if (!args.quiet) process.stderr.write("[genome-refresh-worker] no pending files\n");
|
|
303
|
+
return {
|
|
304
|
+
filesProcessed: 0,
|
|
305
|
+
sectionsUpdated: 0,
|
|
306
|
+
sectionsInvalidated: 0,
|
|
307
|
+
genomeRoots: [],
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Debounce: only proceed if the pending file is settled.
|
|
312
|
+
const settled = await isDebounced(args.home, args.debounceMs);
|
|
313
|
+
if (!settled) {
|
|
314
|
+
if (!args.quiet)
|
|
315
|
+
process.stderr.write(
|
|
316
|
+
`[genome-refresh-worker] debouncing — pending file was written < ${args.debounceMs}ms ago\n`,
|
|
317
|
+
);
|
|
318
|
+
return {
|
|
319
|
+
filesProcessed: 0,
|
|
320
|
+
sectionsUpdated: 0,
|
|
321
|
+
sectionsInvalidated: 0,
|
|
322
|
+
genomeRoots: [],
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (args.full) {
|
|
327
|
+
// Full rebuild path: identify genome roots, then re-init each one.
|
|
328
|
+
const grouped = groupByGenomeRoot(paths);
|
|
329
|
+
const roots = [...grouped.keys()];
|
|
330
|
+
await fullRebuild(roots, { quiet: args.quiet, dryRun: args.dryRun });
|
|
331
|
+
if (!args.dryRun) clearPendingFile(args.home);
|
|
332
|
+
return {
|
|
333
|
+
filesProcessed: paths.length,
|
|
334
|
+
sectionsUpdated: 0,
|
|
335
|
+
sectionsInvalidated: 0,
|
|
336
|
+
genomeRoots: roots,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Incremental path
|
|
341
|
+
const summary = await refreshPaths(paths, {
|
|
342
|
+
dryRun: args.dryRun,
|
|
343
|
+
quiet: args.quiet,
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
if (!args.dryRun) {
|
|
347
|
+
clearPendingFile(args.home);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (!args.quiet) {
|
|
351
|
+
process.stderr.write(
|
|
352
|
+
`[genome-refresh-worker] done: ${summary.filesProcessed} files, ` +
|
|
353
|
+
`${summary.sectionsUpdated} updated, ${summary.sectionsInvalidated} invalidated, ` +
|
|
354
|
+
`${summary.genomeRoots.length} genome root(s)\n`,
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
return summary;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
if (import.meta.main) {
|
|
362
|
+
const args = parseArgs(process.argv.slice(2));
|
|
363
|
+
run(args).finally(() => process.exit(0));
|
|
364
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* genome-rewrap.ts — re-wrap the team-cloud genome DEK for every team member
|
|
4
|
+
* with a current pubkey on file. Used after:
|
|
5
|
+
* - A teammate ran /ashlr-genome-keygen --force (their previous envelope no
|
|
6
|
+
* longer decrypts with their new private key).
|
|
7
|
+
* - A new teammate joined and ran /ashlr-genome-keygen so they now have a
|
|
8
|
+
* pubkey on file but no envelope yet.
|
|
9
|
+
* - --rotate-dek: the admin wants to invalidate every existing envelope by
|
|
10
|
+
* generating a fresh team DEK first.
|
|
11
|
+
*
|
|
12
|
+
* Implementation is a thin delegate to genome-team-init.ts so we don't
|
|
13
|
+
* duplicate the wrap logic; the only new behavior is argv translation.
|
|
14
|
+
*
|
|
15
|
+
* Exits 0 success / 2 prereq missing / 3 network or server error.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { spawnSync } from "child_process";
|
|
19
|
+
import { join } from "path";
|
|
20
|
+
|
|
21
|
+
interface Args {
|
|
22
|
+
rotateDek: boolean;
|
|
23
|
+
endpoint: string | null;
|
|
24
|
+
cwd: string | null;
|
|
25
|
+
help: boolean;
|
|
26
|
+
passthrough: string[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function parseArgs(argv: string[]): Args {
|
|
30
|
+
const parsed: Args = {
|
|
31
|
+
rotateDek: false,
|
|
32
|
+
endpoint: null,
|
|
33
|
+
cwd: null,
|
|
34
|
+
help: false,
|
|
35
|
+
passthrough: [],
|
|
36
|
+
};
|
|
37
|
+
for (let i = 0; i < argv.length; i++) {
|
|
38
|
+
const a = argv[i];
|
|
39
|
+
if (a === "-h" || a === "--help") parsed.help = true;
|
|
40
|
+
else if (a === "--rotate-dek") parsed.rotateDek = true;
|
|
41
|
+
else if (a === "--endpoint") parsed.endpoint = argv[++i] ?? null;
|
|
42
|
+
else if (a === "--cwd") parsed.cwd = argv[++i] ?? null;
|
|
43
|
+
else parsed.passthrough.push(a);
|
|
44
|
+
}
|
|
45
|
+
return parsed;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function printHelp(): void {
|
|
49
|
+
process.stderr.write(
|
|
50
|
+
"Usage: /ashlr-genome-rewrap [--rotate-dek] [--endpoint <url>] [--cwd <dir>]\n" +
|
|
51
|
+
"\n" +
|
|
52
|
+
"Re-wraps the team genome DEK for every member with a current pubkey.\n" +
|
|
53
|
+
"Run this after a teammate rotates their keypair (/ashlr-genome-keygen\n" +
|
|
54
|
+
"--force) or joins the team for the first time. Admin-only.\n" +
|
|
55
|
+
"\n" +
|
|
56
|
+
"Flags:\n" +
|
|
57
|
+
" --rotate-dek Generate a fresh team DEK first; invalidates every\n" +
|
|
58
|
+
" existing envelope. Use after a key compromise.\n" +
|
|
59
|
+
" --endpoint <url> Override default https://api.ashlr.ai\n" +
|
|
60
|
+
" --cwd <dir> Repo to operate on (default cwd)\n",
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function buildDelegatedArgs(args: Args): string[] {
|
|
65
|
+
// --rotate-dek maps to genome-team-init's --force (regenerates DEK) plus
|
|
66
|
+
// --wrap-all (re-wraps for every member with a pubkey).
|
|
67
|
+
// Otherwise just --wrap-all (preserves current DEK, refreshes envelopes).
|
|
68
|
+
const argv: string[] = [];
|
|
69
|
+
if (args.rotateDek) argv.push("--force");
|
|
70
|
+
argv.push("--wrap-all");
|
|
71
|
+
if (args.endpoint) argv.push("--endpoint", args.endpoint);
|
|
72
|
+
if (args.cwd) argv.push("--cwd", args.cwd);
|
|
73
|
+
argv.push(...args.passthrough);
|
|
74
|
+
return argv;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (import.meta.main) {
|
|
78
|
+
const args = parseArgs(process.argv.slice(2));
|
|
79
|
+
if (args.help) { printHelp(); process.exit(0); }
|
|
80
|
+
|
|
81
|
+
// Delegate to genome-team-init.ts. Sibling file in the same scripts/ dir.
|
|
82
|
+
const teamInit = join(import.meta.dir, "genome-team-init.ts");
|
|
83
|
+
const res = spawnSync("bun", ["run", teamInit, ...buildDelegatedArgs(args)], {
|
|
84
|
+
stdio: "inherit",
|
|
85
|
+
});
|
|
86
|
+
// Surface spawn-level failures (e.g. bun missing from PATH) so the user
|
|
87
|
+
// sees a real diagnostic instead of a silent exit 3.
|
|
88
|
+
if (res.error) process.stderr.write(`genome-rewrap: spawn failed: ${res.error.message}\n`);
|
|
89
|
+
process.exit(res.status ?? 3);
|
|
90
|
+
}
|