@ashlr/hub 2.2.0
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/CHANGELOG.md +1158 -0
- package/LICENSE +21 -0
- package/README.md +833 -0
- package/bin/ashlr +8 -0
- package/dist/api/core.d.ts +28 -0
- package/dist/api/core.js +42 -0
- package/dist/api/core.js.map +1 -0
- package/dist/api/index.d.ts +9 -0
- package/dist/api/index.js +9 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/plugin.d.ts +12 -0
- package/dist/api/plugin.js +13 -0
- package/dist/api/plugin.js.map +1 -0
- package/dist/api/types.d.ts +9 -0
- package/dist/api/types.js +9 -0
- package/dist/api/types.js.map +1 -0
- package/dist/cli/args.d.ts +20 -0
- package/dist/cli/args.js +23 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/ask.d.ts +22 -0
- package/dist/cli/ask.js +240 -0
- package/dist/cli/ask.js.map +1 -0
- package/dist/cli/audit.d.ts +26 -0
- package/dist/cli/audit.js +199 -0
- package/dist/cli/audit.js.map +1 -0
- package/dist/cli/backlog.d.ts +26 -0
- package/dist/cli/backlog.js +322 -0
- package/dist/cli/backlog.js.map +1 -0
- package/dist/cli/completions.d.ts +18 -0
- package/dist/cli/completions.js +156 -0
- package/dist/cli/completions.js.map +1 -0
- package/dist/cli/daemon.d.ts +31 -0
- package/dist/cli/daemon.js +334 -0
- package/dist/cli/daemon.js.map +1 -0
- package/dist/cli/demo-sandbox.d.ts +78 -0
- package/dist/cli/demo-sandbox.js +227 -0
- package/dist/cli/demo-sandbox.js.map +1 -0
- package/dist/cli/demo.d.ts +76 -0
- package/dist/cli/demo.js +285 -0
- package/dist/cli/demo.js.map +1 -0
- package/dist/cli/digest.d.ts +46 -0
- package/dist/cli/digest.js +352 -0
- package/dist/cli/digest.js.map +1 -0
- package/dist/cli/doctor-init.d.ts +28 -0
- package/dist/cli/doctor-init.js +335 -0
- package/dist/cli/doctor-init.js.map +1 -0
- package/dist/cli/genome.d.ts +62 -0
- package/dist/cli/genome.js +1061 -0
- package/dist/cli/genome.js.map +1 -0
- package/dist/cli/gh.d.ts +27 -0
- package/dist/cli/gh.js +322 -0
- package/dist/cli/gh.js.map +1 -0
- package/dist/cli/goals.d.ts +55 -0
- package/dist/cli/goals.js +667 -0
- package/dist/cli/goals.js.map +1 -0
- package/dist/cli/health.d.ts +56 -0
- package/dist/cli/health.js +407 -0
- package/dist/cli/health.js.map +1 -0
- package/dist/cli/help.d.ts +51 -0
- package/dist/cli/help.js +436 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/inbox.d.ts +28 -0
- package/dist/cli/inbox.js +589 -0
- package/dist/cli/inbox.js.map +1 -0
- package/dist/cli/index.d.ts +41 -0
- package/dist/cli/index.js +1208 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/knowledge.d.ts +33 -0
- package/dist/cli/knowledge.js +575 -0
- package/dist/cli/knowledge.js.map +1 -0
- package/dist/cli/mcp.d.ts +26 -0
- package/dist/cli/mcp.js +487 -0
- package/dist/cli/mcp.js.map +1 -0
- package/dist/cli/models.d.ts +26 -0
- package/dist/cli/models.js +435 -0
- package/dist/cli/models.js.map +1 -0
- package/dist/cli/new.d.ts +32 -0
- package/dist/cli/new.js +565 -0
- package/dist/cli/new.js.map +1 -0
- package/dist/cli/notify.d.ts +20 -0
- package/dist/cli/notify.js +188 -0
- package/dist/cli/notify.js.map +1 -0
- package/dist/cli/onboard.d.ts +85 -0
- package/dist/cli/onboard.js +305 -0
- package/dist/cli/onboard.js.map +1 -0
- package/dist/cli/open.d.ts +38 -0
- package/dist/cli/open.js +86 -0
- package/dist/cli/open.js.map +1 -0
- package/dist/cli/orient.d.ts +14 -0
- package/dist/cli/orient.js +110 -0
- package/dist/cli/orient.js.map +1 -0
- package/dist/cli/picker.d.ts +21 -0
- package/dist/cli/picker.js +177 -0
- package/dist/cli/picker.js.map +1 -0
- package/dist/cli/plugins.d.ts +21 -0
- package/dist/cli/plugins.js +394 -0
- package/dist/cli/plugins.js.map +1 -0
- package/dist/cli/preflight.d.ts +29 -0
- package/dist/cli/preflight.js +131 -0
- package/dist/cli/preflight.js.map +1 -0
- package/dist/cli/pulse.d.ts +26 -0
- package/dist/cli/pulse.js +482 -0
- package/dist/cli/pulse.js.map +1 -0
- package/dist/cli/reflect.d.ts +42 -0
- package/dist/cli/reflect.js +381 -0
- package/dist/cli/reflect.js.map +1 -0
- package/dist/cli/run.d.ts +29 -0
- package/dist/cli/run.js +687 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/sandbox.d.ts +20 -0
- package/dist/cli/sandbox.js +345 -0
- package/dist/cli/sandbox.js.map +1 -0
- package/dist/cli/seams.d.ts +41 -0
- package/dist/cli/seams.js +167 -0
- package/dist/cli/seams.js.map +1 -0
- package/dist/cli/serve.d.ts +25 -0
- package/dist/cli/serve.js +249 -0
- package/dist/cli/serve.js.map +1 -0
- package/dist/cli/ship.d.ts +33 -0
- package/dist/cli/ship.js +433 -0
- package/dist/cli/ship.js.map +1 -0
- package/dist/cli/spec.d.ts +19 -0
- package/dist/cli/spec.js +478 -0
- package/dist/cli/spec.js.map +1 -0
- package/dist/cli/swarm.d.ts +42 -0
- package/dist/cli/swarm.js +1365 -0
- package/dist/cli/swarm.js.map +1 -0
- package/dist/cli/telemetry.d.ts +26 -0
- package/dist/cli/telemetry.js +364 -0
- package/dist/cli/telemetry.js.map +1 -0
- package/dist/cli/tui.d.ts +17 -0
- package/dist/cli/tui.js +52 -0
- package/dist/cli/tui.js.map +1 -0
- package/dist/cli/ui.d.ts +53 -0
- package/dist/cli/ui.js +66 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/cli/update.d.ts +38 -0
- package/dist/cli/update.js +682 -0
- package/dist/cli/update.js.map +1 -0
- package/dist/cli/vercel.d.ts +20 -0
- package/dist/cli/vercel.js +193 -0
- package/dist/cli/vercel.js.map +1 -0
- package/dist/cli/verify-safety.d.ts +96 -0
- package/dist/cli/verify-safety.js +509 -0
- package/dist/cli/verify-safety.js.map +1 -0
- package/dist/cli/wire.d.ts +22 -0
- package/dist/cli/wire.js +205 -0
- package/dist/cli/wire.js.map +1 -0
- package/dist/core/classify.d.ts +51 -0
- package/dist/core/classify.js +450 -0
- package/dist/core/classify.js.map +1 -0
- package/dist/core/config.d.ts +63 -0
- package/dist/core/config.js +474 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/daemon/loop.d.ts +74 -0
- package/dist/core/daemon/loop.js +618 -0
- package/dist/core/daemon/loop.js.map +1 -0
- package/dist/core/daemon/state.d.ts +66 -0
- package/dist/core/daemon/state.js +197 -0
- package/dist/core/daemon/state.js.map +1 -0
- package/dist/core/dashboard.d.ts +40 -0
- package/dist/core/dashboard.js +463 -0
- package/dist/core/dashboard.js.map +1 -0
- package/dist/core/digest/build.d.ts +51 -0
- package/dist/core/digest/build.js +230 -0
- package/dist/core/digest/build.js.map +1 -0
- package/dist/core/digest/deliver.d.ts +47 -0
- package/dist/core/digest/deliver.js +230 -0
- package/dist/core/digest/deliver.js.map +1 -0
- package/dist/core/digest/store.d.ts +57 -0
- package/dist/core/digest/store.js +223 -0
- package/dist/core/digest/store.js.map +1 -0
- package/dist/core/doctor-fix.d.ts +21 -0
- package/dist/core/doctor-fix.js +440 -0
- package/dist/core/doctor-fix.js.map +1 -0
- package/dist/core/doctor.d.ts +18 -0
- package/dist/core/doctor.js +806 -0
- package/dist/core/doctor.js.map +1 -0
- package/dist/core/env-bridge.d.ts +64 -0
- package/dist/core/env-bridge.js +103 -0
- package/dist/core/env-bridge.js.map +1 -0
- package/dist/core/genome/capture.d.ts +49 -0
- package/dist/core/genome/capture.js +352 -0
- package/dist/core/genome/capture.js.map +1 -0
- package/dist/core/genome/consolidate.d.ts +38 -0
- package/dist/core/genome/consolidate.js +426 -0
- package/dist/core/genome/consolidate.js.map +1 -0
- package/dist/core/genome/export.d.ts +29 -0
- package/dist/core/genome/export.js +102 -0
- package/dist/core/genome/export.js.map +1 -0
- package/dist/core/genome/playbook.d.ts +33 -0
- package/dist/core/genome/playbook.js +320 -0
- package/dist/core/genome/playbook.js.map +1 -0
- package/dist/core/genome/recall.d.ts +45 -0
- package/dist/core/genome/recall.js +293 -0
- package/dist/core/genome/recall.js.map +1 -0
- package/dist/core/genome/store.d.ts +62 -0
- package/dist/core/genome/store.js +711 -0
- package/dist/core/genome/store.js.map +1 -0
- package/dist/core/git.d.ts +34 -0
- package/dist/core/git.js +115 -0
- package/dist/core/git.js.map +1 -0
- package/dist/core/goals/advance.d.ts +82 -0
- package/dist/core/goals/advance.js +263 -0
- package/dist/core/goals/advance.js.map +1 -0
- package/dist/core/goals/planner.d.ts +58 -0
- package/dist/core/goals/planner.js +233 -0
- package/dist/core/goals/planner.js.map +1 -0
- package/dist/core/goals/store.d.ts +128 -0
- package/dist/core/goals/store.js +442 -0
- package/dist/core/goals/store.js.map +1 -0
- package/dist/core/inbox/apply.d.ts +36 -0
- package/dist/core/inbox/apply.js +407 -0
- package/dist/core/inbox/apply.js.map +1 -0
- package/dist/core/inbox/notify-proposal.d.ts +13 -0
- package/dist/core/inbox/notify-proposal.js +21 -0
- package/dist/core/inbox/notify-proposal.js.map +1 -0
- package/dist/core/inbox/store.d.ts +67 -0
- package/dist/core/inbox/store.js +258 -0
- package/dist/core/inbox/store.js.map +1 -0
- package/dist/core/index-engine.d.ts +62 -0
- package/dist/core/index-engine.js +486 -0
- package/dist/core/index-engine.js.map +1 -0
- package/dist/core/integrations/desktop-notify.d.ts +18 -0
- package/dist/core/integrations/desktop-notify.js +42 -0
- package/dist/core/integrations/desktop-notify.js.map +1 -0
- package/dist/core/integrations/editors.d.ts +50 -0
- package/dist/core/integrations/editors.js +216 -0
- package/dist/core/integrations/editors.js.map +1 -0
- package/dist/core/integrations/github.d.ts +66 -0
- package/dist/core/integrations/github.js +332 -0
- package/dist/core/integrations/github.js.map +1 -0
- package/dist/core/integrations/identity.d.ts +29 -0
- package/dist/core/integrations/identity.js +359 -0
- package/dist/core/integrations/identity.js.map +1 -0
- package/dist/core/integrations/notify.d.ts +23 -0
- package/dist/core/integrations/notify.js +96 -0
- package/dist/core/integrations/notify.js.map +1 -0
- package/dist/core/integrations/vercel.d.ts +37 -0
- package/dist/core/integrations/vercel.js +192 -0
- package/dist/core/integrations/vercel.js.map +1 -0
- package/dist/core/knowledge/ask.d.ts +34 -0
- package/dist/core/knowledge/ask.js +325 -0
- package/dist/core/knowledge/ask.js.map +1 -0
- package/dist/core/knowledge/graph.d.ts +51 -0
- package/dist/core/knowledge/graph.js +564 -0
- package/dist/core/knowledge/graph.js.map +1 -0
- package/dist/core/knowledge/index.d.ts +74 -0
- package/dist/core/knowledge/index.js +586 -0
- package/dist/core/knowledge/index.js.map +1 -0
- package/dist/core/learn/playbooks.d.ts +84 -0
- package/dist/core/learn/playbooks.js +241 -0
- package/dist/core/learn/playbooks.js.map +1 -0
- package/dist/core/learn/reflect.d.ts +87 -0
- package/dist/core/learn/reflect.js +435 -0
- package/dist/core/learn/reflect.js.map +1 -0
- package/dist/core/learn/store.d.ts +51 -0
- package/dist/core/learn/store.js +165 -0
- package/dist/core/learn/store.js.map +1 -0
- package/dist/core/learn/tuning.d.ts +48 -0
- package/dist/core/learn/tuning.js +201 -0
- package/dist/core/learn/tuning.js.map +1 -0
- package/dist/core/lifecycle/scaffold.d.ts +43 -0
- package/dist/core/lifecycle/scaffold.js +260 -0
- package/dist/core/lifecycle/scaffold.js.map +1 -0
- package/dist/core/lifecycle/ship.d.ts +48 -0
- package/dist/core/lifecycle/ship.js +513 -0
- package/dist/core/lifecycle/ship.js.map +1 -0
- package/dist/core/lifecycle/templates.d.ts +20 -0
- package/dist/core/lifecycle/templates.js +605 -0
- package/dist/core/lifecycle/templates.js.map +1 -0
- package/dist/core/mcp-gateway.d.ts +59 -0
- package/dist/core/mcp-gateway.js +385 -0
- package/dist/core/mcp-gateway.js.map +1 -0
- package/dist/core/mcp-native.d.ts +53 -0
- package/dist/core/mcp-native.js +507 -0
- package/dist/core/mcp-native.js.map +1 -0
- package/dist/core/mcp-registry.d.ts +36 -0
- package/dist/core/mcp-registry.js +180 -0
- package/dist/core/mcp-registry.js.map +1 -0
- package/dist/core/observability/budget-alert.d.ts +18 -0
- package/dist/core/observability/budget-alert.js +90 -0
- package/dist/core/observability/budget-alert.js.map +1 -0
- package/dist/core/observability/estimate.d.ts +27 -0
- package/dist/core/observability/estimate.js +188 -0
- package/dist/core/observability/estimate.js.map +1 -0
- package/dist/core/observability/forecast.d.ts +19 -0
- package/dist/core/observability/forecast.js +101 -0
- package/dist/core/observability/forecast.js.map +1 -0
- package/dist/core/observability/governance.d.ts +28 -0
- package/dist/core/observability/governance.js +101 -0
- package/dist/core/observability/governance.js.map +1 -0
- package/dist/core/observability/otlp.d.ts +88 -0
- package/dist/core/observability/otlp.js +217 -0
- package/dist/core/observability/otlp.js.map +1 -0
- package/dist/core/observability/rollup.d.ts +35 -0
- package/dist/core/observability/rollup.js +311 -0
- package/dist/core/observability/rollup.js.map +1 -0
- package/dist/core/observability/telemetry-sink.d.ts +63 -0
- package/dist/core/observability/telemetry-sink.js +350 -0
- package/dist/core/observability/telemetry-sink.js.map +1 -0
- package/dist/core/observability/usage-source.d.ts +60 -0
- package/dist/core/observability/usage-source.js +347 -0
- package/dist/core/observability/usage-source.js.map +1 -0
- package/dist/core/onboard.d.ts +27 -0
- package/dist/core/onboard.js +288 -0
- package/dist/core/onboard.js.map +1 -0
- package/dist/core/orient.d.ts +23 -0
- package/dist/core/orient.js +135 -0
- package/dist/core/orient.js.map +1 -0
- package/dist/core/phantom.d.ts +23 -0
- package/dist/core/phantom.js +279 -0
- package/dist/core/phantom.js.map +1 -0
- package/dist/core/plugins/host-api.d.ts +29 -0
- package/dist/core/plugins/host-api.js +113 -0
- package/dist/core/plugins/host-api.js.map +1 -0
- package/dist/core/plugins/integrity.d.ts +36 -0
- package/dist/core/plugins/integrity.js +73 -0
- package/dist/core/plugins/integrity.js.map +1 -0
- package/dist/core/plugins/manifest.d.ts +31 -0
- package/dist/core/plugins/manifest.js +316 -0
- package/dist/core/plugins/manifest.js.map +1 -0
- package/dist/core/plugins/registry.d.ts +87 -0
- package/dist/core/plugins/registry.js +415 -0
- package/dist/core/plugins/registry.js.map +1 -0
- package/dist/core/plugins/types.d.ts +182 -0
- package/dist/core/plugins/types.js +40 -0
- package/dist/core/plugins/types.js.map +1 -0
- package/dist/core/plugins/wrappers.d.ts +40 -0
- package/dist/core/plugins/wrappers.js +229 -0
- package/dist/core/plugins/wrappers.js.map +1 -0
- package/dist/core/portfolio/backlog.d.ts +40 -0
- package/dist/core/portfolio/backlog.js +177 -0
- package/dist/core/portfolio/backlog.js.map +1 -0
- package/dist/core/portfolio/scanners.d.ts +21 -0
- package/dist/core/portfolio/scanners.js +600 -0
- package/dist/core/portfolio/scanners.js.map +1 -0
- package/dist/core/providers.d.ts +34 -0
- package/dist/core/providers.js +250 -0
- package/dist/core/providers.js.map +1 -0
- package/dist/core/quality/conventions.d.ts +35 -0
- package/dist/core/quality/conventions.js +267 -0
- package/dist/core/quality/conventions.js.map +1 -0
- package/dist/core/quality/fixes.d.ts +56 -0
- package/dist/core/quality/fixes.js +209 -0
- package/dist/core/quality/fixes.js.map +1 -0
- package/dist/core/quality/health.d.ts +69 -0
- package/dist/core/quality/health.js +350 -0
- package/dist/core/quality/health.js.map +1 -0
- package/dist/core/quality/store.d.ts +56 -0
- package/dist/core/quality/store.js +195 -0
- package/dist/core/quality/store.js.map +1 -0
- package/dist/core/readiness.d.ts +112 -0
- package/dist/core/readiness.js +431 -0
- package/dist/core/readiness.js.map +1 -0
- package/dist/core/run/agent-loop.d.ts +40 -0
- package/dist/core/run/agent-loop.js +291 -0
- package/dist/core/run/agent-loop.js.map +1 -0
- package/dist/core/run/budget.d.ts +47 -0
- package/dist/core/run/budget.js +113 -0
- package/dist/core/run/budget.js.map +1 -0
- package/dist/core/run/engines.d.ts +75 -0
- package/dist/core/run/engines.js +199 -0
- package/dist/core/run/engines.js.map +1 -0
- package/dist/core/run/model-manager.d.ts +64 -0
- package/dist/core/run/model-manager.js +339 -0
- package/dist/core/run/model-manager.js.map +1 -0
- package/dist/core/run/orchestrator.d.ts +100 -0
- package/dist/core/run/orchestrator.js +1515 -0
- package/dist/core/run/orchestrator.js.map +1 -0
- package/dist/core/run/provider-client.d.ts +46 -0
- package/dist/core/run/provider-client.js +796 -0
- package/dist/core/run/provider-client.js.map +1 -0
- package/dist/core/run/retry.d.ts +19 -0
- package/dist/core/run/retry.js +68 -0
- package/dist/core/run/retry.js.map +1 -0
- package/dist/core/run/router.d.ts +50 -0
- package/dist/core/run/router.js +257 -0
- package/dist/core/run/router.js.map +1 -0
- package/dist/core/run/self-heal.d.ts +52 -0
- package/dist/core/run/self-heal.js +181 -0
- package/dist/core/run/self-heal.js.map +1 -0
- package/dist/core/run/streaming.d.ts +31 -0
- package/dist/core/run/streaming.js +122 -0
- package/dist/core/run/streaming.js.map +1 -0
- package/dist/core/run/verify.d.ts +30 -0
- package/dist/core/run/verify.js +204 -0
- package/dist/core/run/verify.js.map +1 -0
- package/dist/core/sandbox/audit.d.ts +31 -0
- package/dist/core/sandbox/audit.js +169 -0
- package/dist/core/sandbox/audit.js.map +1 -0
- package/dist/core/sandbox/policy.d.ts +61 -0
- package/dist/core/sandbox/policy.js +211 -0
- package/dist/core/sandbox/policy.js.map +1 -0
- package/dist/core/sandbox/worktree.d.ts +175 -0
- package/dist/core/sandbox/worktree.js +673 -0
- package/dist/core/sandbox/worktree.js.map +1 -0
- package/dist/core/seams/backlog.d.ts +47 -0
- package/dist/core/seams/backlog.js +47 -0
- package/dist/core/seams/backlog.js.map +1 -0
- package/dist/core/seams/daemon-coordinator.d.ts +72 -0
- package/dist/core/seams/daemon-coordinator.js +76 -0
- package/dist/core/seams/daemon-coordinator.js.map +1 -0
- package/dist/core/seams/genome.d.ts +45 -0
- package/dist/core/seams/genome.js +53 -0
- package/dist/core/seams/genome.js.map +1 -0
- package/dist/core/seams/identity.d.ts +40 -0
- package/dist/core/seams/identity.js +44 -0
- package/dist/core/seams/identity.js.map +1 -0
- package/dist/core/seams/inbox.d.ts +60 -0
- package/dist/core/seams/inbox.js +66 -0
- package/dist/core/seams/inbox.js.map +1 -0
- package/dist/core/seams/index.d.ts +20 -0
- package/dist/core/seams/index.js +21 -0
- package/dist/core/seams/index.js.map +1 -0
- package/dist/core/seams/portfolio.d.ts +50 -0
- package/dist/core/seams/portfolio.js +61 -0
- package/dist/core/seams/portfolio.js.map +1 -0
- package/dist/core/seams/registry.d.ts +42 -0
- package/dist/core/seams/registry.js +128 -0
- package/dist/core/seams/registry.js.map +1 -0
- package/dist/core/seams/run-swarm.d.ts +66 -0
- package/dist/core/seams/run-swarm.js +74 -0
- package/dist/core/seams/run-swarm.js.map +1 -0
- package/dist/core/seams/types.d.ts +123 -0
- package/dist/core/seams/types.js +35 -0
- package/dist/core/seams/types.js.map +1 -0
- package/dist/core/spec/spec-store.d.ts +62 -0
- package/dist/core/spec/spec-store.js +359 -0
- package/dist/core/spec/spec-store.js.map +1 -0
- package/dist/core/swarm/gate.d.ts +45 -0
- package/dist/core/swarm/gate.js +114 -0
- package/dist/core/swarm/gate.js.map +1 -0
- package/dist/core/swarm/planner.d.ts +32 -0
- package/dist/core/swarm/planner.js +293 -0
- package/dist/core/swarm/planner.js.map +1 -0
- package/dist/core/swarm/rollback.d.ts +56 -0
- package/dist/core/swarm/rollback.js +266 -0
- package/dist/core/swarm/rollback.js.map +1 -0
- package/dist/core/swarm/runner.d.ts +62 -0
- package/dist/core/swarm/runner.js +1263 -0
- package/dist/core/swarm/runner.js.map +1 -0
- package/dist/core/swarm/sign.d.ts +71 -0
- package/dist/core/swarm/sign.js +362 -0
- package/dist/core/swarm/sign.js.map +1 -0
- package/dist/core/swarm/store.d.ts +52 -0
- package/dist/core/swarm/store.js +195 -0
- package/dist/core/swarm/store.js.map +1 -0
- package/dist/core/tidy.d.ts +32 -0
- package/dist/core/tidy.js +354 -0
- package/dist/core/tidy.js.map +1 -0
- package/dist/core/tools-registry.d.ts +16 -0
- package/dist/core/tools-registry.js +308 -0
- package/dist/core/tools-registry.js.map +1 -0
- package/dist/core/types.d.ts +2545 -0
- package/dist/core/types.js +9 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/web/api.d.ts +53 -0
- package/dist/core/web/api.js +698 -0
- package/dist/core/web/api.js.map +1 -0
- package/dist/core/web/public/app.js +1906 -0
- package/dist/core/web/public/index.html +721 -0
- package/dist/core/web/public/styles.css +2007 -0
- package/dist/core/web/server.d.ts +18 -0
- package/dist/core/web/server.js +122 -0
- package/dist/core/web/server.js.map +1 -0
- package/dist/core/web/static.d.ts +18 -0
- package/dist/core/web/static.js +122 -0
- package/dist/core/web/static.js.map +1 -0
- package/dist/tui/app.d.ts +33 -0
- package/dist/tui/app.js +350 -0
- package/dist/tui/app.js.map +1 -0
- package/dist/tui/render.d.ts +20 -0
- package/dist/tui/render.js +558 -0
- package/dist/tui/render.js.map +1 -0
- package/package.json +80 -0
- package/schema/config.schema.json +223 -0
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* reflect.ts — M26 deterministic reflection metrics engine.
|
|
3
|
+
*
|
|
4
|
+
* Scores the org's OWN past swarms/usage/genome and computes a ReflectionReport:
|
|
5
|
+
* success rate, avg cost & tokens per swarm, local-vs-cloud share, clustered
|
|
6
|
+
* top failure modes, slowest/most-expensive goal categories, and week-over-week
|
|
7
|
+
* deltas vs the prior persisted snapshot.
|
|
8
|
+
*
|
|
9
|
+
* HARD SAFETY INVARIANTS (M26):
|
|
10
|
+
* 1. READ-ONLY over history. Reads listSwarms() / genomeHubHealth /
|
|
11
|
+
* collectUsageEvents() ONLY — the HUB-ONLY genome reader (no portfolio
|
|
12
|
+
* disk scan). Writes nothing here (the CLI persists the snapshot via
|
|
13
|
+
* learn/store.ts under ~/.ashlr/learn/).
|
|
14
|
+
* 2. NO TUNING. This module never proposes or applies anything — pure metrics.
|
|
15
|
+
* 3. LOCAL-FIRST / NO LLM. buildReflection is DETERMINISTIC and makes ZERO
|
|
16
|
+
* network connections. No getActiveClient, no fetch. Narrative generation
|
|
17
|
+
* lives in playbooks.ts, never here.
|
|
18
|
+
* 4. BOUNDED. Reads at most `maxRuns` recent swarms (default DEFAULT_MAX_RUNS)
|
|
19
|
+
* and/or those within `sinceMs`. listSwarms() is itself capped at 200.
|
|
20
|
+
* 5. NEVER THROWS. Degrades to a zeroed report on any failure.
|
|
21
|
+
*
|
|
22
|
+
* METADATA ONLY — never reads/retains secret values or raw code/payloads.
|
|
23
|
+
*/
|
|
24
|
+
import { listSwarms } from '../swarm/store.js';
|
|
25
|
+
import { genomeHubHealth } from '../genome/store.js';
|
|
26
|
+
import { collectUsageEvents } from '../observability/usage-source.js';
|
|
27
|
+
import { isLocalProviderModel } from '../observability/rollup.js';
|
|
28
|
+
import { loadPreviousReport } from './store.js';
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// Bounds
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
/** Default cap on how many recent swarms to analyze (bounds work). */
|
|
33
|
+
export const DEFAULT_MAX_RUNS = 100;
|
|
34
|
+
/**
|
|
35
|
+
* Default usage-window lookback (ms) applied when NO --since window is given.
|
|
36
|
+
* Bounds collectUsageEvents() so the default path never streams the entire
|
|
37
|
+
* historical transcript corpus — it matches the report's week-over-week
|
|
38
|
+
* framing. `--since all` (sinceMs explicitly 0) is the opt-in to scan all
|
|
39
|
+
* history (still bounded by the per-file caps in usage-source.ts).
|
|
40
|
+
*/
|
|
41
|
+
export const DEFAULT_USAGE_LOOKBACK_MS = 30 * 86_400_000;
|
|
42
|
+
/** Max distinct failure-mode clusters surfaced on a report. */
|
|
43
|
+
const MAX_FAILURE_MODES = 8;
|
|
44
|
+
/** Max representative swarm ids retained per failure cluster. */
|
|
45
|
+
const MAX_FAILURE_EXAMPLES = 3;
|
|
46
|
+
/** Coarse goal categories (keyword heuristic; deterministic). */
|
|
47
|
+
const GOAL_CATEGORIES = [
|
|
48
|
+
'feature',
|
|
49
|
+
'bugfix',
|
|
50
|
+
'refactor',
|
|
51
|
+
'test',
|
|
52
|
+
'docs',
|
|
53
|
+
'chore',
|
|
54
|
+
'other',
|
|
55
|
+
];
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
// Pure helpers (exported for unit testing) — NO I/O, NO LLM
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
/**
|
|
60
|
+
* Bucket a swarm goal string into one coarse GOAL_CATEGORIES label using a
|
|
61
|
+
* deterministic keyword heuristic. Pure; never throws.
|
|
62
|
+
*
|
|
63
|
+
* Order matters: the first matching category wins (most-specific verbs first).
|
|
64
|
+
*/
|
|
65
|
+
export function classifyGoal(goal) {
|
|
66
|
+
const g = (goal ?? '').toLowerCase();
|
|
67
|
+
if (!g.trim())
|
|
68
|
+
return 'other';
|
|
69
|
+
// bugfix: fix / bug / crash / regression / hotfix
|
|
70
|
+
if (/\b(fix|fixes|fixed|bug|bugs|crash|regression|hotfix|defect|broken)\b/.test(g)) {
|
|
71
|
+
return 'bugfix';
|
|
72
|
+
}
|
|
73
|
+
// test: test / spec / coverage / vitest / jest
|
|
74
|
+
if (/\b(test|tests|testing|spec|specs|coverage|vitest|jest)\b/.test(g)) {
|
|
75
|
+
return 'test';
|
|
76
|
+
}
|
|
77
|
+
// docs: doc / readme / comment / changelog
|
|
78
|
+
if (/\b(doc|docs|document|documentation|readme|changelog|comment|comments)\b/.test(g)) {
|
|
79
|
+
return 'docs';
|
|
80
|
+
}
|
|
81
|
+
// refactor: refactor / cleanup / rename / restructure / simplify
|
|
82
|
+
if (/\b(refactor|refactors|refactoring|cleanup|clean-up|rename|restructure|simplify|tidy|dedupe)\b/.test(g)) {
|
|
83
|
+
return 'refactor';
|
|
84
|
+
}
|
|
85
|
+
// chore: chore / bump / deps / config / ci / lint / format / upgrade
|
|
86
|
+
if (/\b(chore|bump|deps|dependency|dependencies|config|ci|lint|format|upgrade|version)\b/.test(g)) {
|
|
87
|
+
return 'chore';
|
|
88
|
+
}
|
|
89
|
+
// feature: add / implement / build / create / feature / support / new
|
|
90
|
+
if (/\b(feature|features|add|adds|implement|implements|build|create|support|introduce|new)\b/.test(g)) {
|
|
91
|
+
return 'feature';
|
|
92
|
+
}
|
|
93
|
+
// GOAL_CATEGORIES is the single source of truth for the valid labels; the
|
|
94
|
+
// fallthrough returns the final ('other') bucket from it.
|
|
95
|
+
return GOAL_CATEGORIES[GOAL_CATEGORIES.length - 1];
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Normalize a raw task.error string into a stable cluster key (lowercase,
|
|
99
|
+
* stripped of ids/paths/numbers/hashes) so similar errors cluster together.
|
|
100
|
+
* Pure; never throws.
|
|
101
|
+
*/
|
|
102
|
+
export function normalizeErrorKey(error) {
|
|
103
|
+
if (typeof error !== 'string')
|
|
104
|
+
return '';
|
|
105
|
+
let s = error.toLowerCase().trim();
|
|
106
|
+
if (!s)
|
|
107
|
+
return '';
|
|
108
|
+
// Strip uuids first (more specific than the generic hash rule below).
|
|
109
|
+
s = s.replace(/\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/g, '<uuid>');
|
|
110
|
+
// Strip absolute/relative paths to a placeholder.
|
|
111
|
+
s = s.replace(/(?:\/[\w.\-@]+)+/g, ' <path> ');
|
|
112
|
+
// Strip hex hashes.
|
|
113
|
+
s = s.replace(/\b[0-9a-f]{8,}\b/g, '<hash>');
|
|
114
|
+
// Strip standalone numbers (line/col/byte counts, ports, durations).
|
|
115
|
+
s = s.replace(/\b\d+(?:\.\d+)?(?:ms|s)?\b/g, '<n>');
|
|
116
|
+
// Strip quoted identifiers so 'foo'/"bar" don't fragment the cluster.
|
|
117
|
+
s = s.replace(/['"`][^'"`]*['"`]/g, '<id>');
|
|
118
|
+
// Collapse whitespace and cap length so the key stays stable + bounded.
|
|
119
|
+
s = s.replace(/\s+/g, ' ').trim();
|
|
120
|
+
return s.slice(0, 120);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Cluster failed tasks across swarms into the top FailureMode buckets, most
|
|
124
|
+
* frequent first, capped at MAX_FAILURE_MODES. Pure over the provided swarms;
|
|
125
|
+
* never throws.
|
|
126
|
+
*/
|
|
127
|
+
export function clusterFailures(swarms) {
|
|
128
|
+
const buckets = new Map();
|
|
129
|
+
try {
|
|
130
|
+
for (const s of swarms) {
|
|
131
|
+
const tasks = Array.isArray(s.tasks) ? s.tasks : [];
|
|
132
|
+
for (const t of tasks) {
|
|
133
|
+
if (t.status !== 'failed')
|
|
134
|
+
continue;
|
|
135
|
+
const raw = (t.error ?? '').trim();
|
|
136
|
+
// Fall back to the phase name when no error string is present, so a
|
|
137
|
+
// failed task with no message still clusters by phase.
|
|
138
|
+
const key = normalizeErrorKey(raw) || `phase:${t.phase ?? 'unknown'}`;
|
|
139
|
+
const label = raw ? raw.slice(0, 100) : `failed in ${t.phase ?? 'unknown'} phase`;
|
|
140
|
+
let bucket = buckets.get(key);
|
|
141
|
+
if (!bucket) {
|
|
142
|
+
bucket = { label, count: 0, phases: new Set(), examples: new Set() };
|
|
143
|
+
buckets.set(key, bucket);
|
|
144
|
+
}
|
|
145
|
+
bucket.count++;
|
|
146
|
+
if (t.phase)
|
|
147
|
+
bucket.phases.add(String(t.phase));
|
|
148
|
+
if (s.id && bucket.examples.size < MAX_FAILURE_EXAMPLES) {
|
|
149
|
+
bucket.examples.add(s.id);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
return [];
|
|
156
|
+
}
|
|
157
|
+
const modes = [];
|
|
158
|
+
for (const [key, b] of buckets) {
|
|
159
|
+
modes.push({
|
|
160
|
+
key,
|
|
161
|
+
label: b.label,
|
|
162
|
+
count: b.count,
|
|
163
|
+
phases: [...b.phases].sort(),
|
|
164
|
+
exampleSwarmIds: [...b.examples],
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
// Most frequent first; tiebreak on key for determinism.
|
|
168
|
+
modes.sort((a, b) => (b.count - a.count) || (a.key < b.key ? -1 : a.key > b.key ? 1 : 0));
|
|
169
|
+
return modes.slice(0, MAX_FAILURE_MODES);
|
|
170
|
+
}
|
|
171
|
+
/** Total (in+out) tokens for a swarm's cumulative usage. Pure. */
|
|
172
|
+
function swarmTokens(s) {
|
|
173
|
+
const u = s.usage;
|
|
174
|
+
if (!u)
|
|
175
|
+
return 0;
|
|
176
|
+
const ti = typeof u.tokensIn === 'number' ? u.tokensIn : 0;
|
|
177
|
+
const to = typeof u.tokensOut === 'number' ? u.tokensOut : 0;
|
|
178
|
+
return ti + to;
|
|
179
|
+
}
|
|
180
|
+
/** Estimated USD cost for a swarm. Pure. */
|
|
181
|
+
function swarmCost(s) {
|
|
182
|
+
const c = s.usage?.estCostUsd;
|
|
183
|
+
return typeof c === 'number' && Number.isFinite(c) ? c : 0;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Aggregate per-goal-category cost/token/success stats over the swarms,
|
|
187
|
+
* most-expensive (avgCostUsd) first. Pure; never throws.
|
|
188
|
+
*/
|
|
189
|
+
export function summarizeGoalCategories(swarms) {
|
|
190
|
+
const buckets = new Map();
|
|
191
|
+
try {
|
|
192
|
+
for (const s of swarms) {
|
|
193
|
+
const cat = classifyGoal(s.goal ?? '');
|
|
194
|
+
let b = buckets.get(cat);
|
|
195
|
+
if (!b) {
|
|
196
|
+
b = { swarms: 0, cost: 0, tokens: 0, done: 0 };
|
|
197
|
+
buckets.set(cat, b);
|
|
198
|
+
}
|
|
199
|
+
b.swarms++;
|
|
200
|
+
b.cost += swarmCost(s);
|
|
201
|
+
b.tokens += swarmTokens(s);
|
|
202
|
+
if (s.status === 'done')
|
|
203
|
+
b.done++;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
return [];
|
|
208
|
+
}
|
|
209
|
+
const stats = [];
|
|
210
|
+
for (const [category, b] of buckets) {
|
|
211
|
+
if (b.swarms === 0)
|
|
212
|
+
continue;
|
|
213
|
+
stats.push({
|
|
214
|
+
category,
|
|
215
|
+
swarms: b.swarms,
|
|
216
|
+
avgCostUsd: b.cost / b.swarms,
|
|
217
|
+
avgTokens: b.tokens / b.swarms,
|
|
218
|
+
successRate: b.done / b.swarms,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
// Most-expensive first; tiebreak on category for determinism.
|
|
222
|
+
stats.sort((a, b) => b.avgCostUsd - a.avgCostUsd ||
|
|
223
|
+
(a.category < b.category ? -1 : a.category > b.category ? 1 : 0));
|
|
224
|
+
return stats;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Compute week-over-week deltas vs a prior snapshot. Pure; never throws.
|
|
228
|
+
* When `previous` is null, returns a no-prior delta (all numeric fields null).
|
|
229
|
+
*
|
|
230
|
+
* `currentWindow` (the window/scope label of the CURRENT report) is compared
|
|
231
|
+
* against `previous.window`. When they differ, the metrics were computed over
|
|
232
|
+
* DIFFERENT populations, so the headline is annotated '(windows differ)' to
|
|
233
|
+
* flag that the delta is apples-to-oranges. Omitting it (or passing the same
|
|
234
|
+
* label) leaves the headline unannotated.
|
|
235
|
+
*/
|
|
236
|
+
export function computeDelta(current, previous, currentWindow) {
|
|
237
|
+
if (!previous) {
|
|
238
|
+
return {
|
|
239
|
+
previousAt: null,
|
|
240
|
+
effectivenessPct: null,
|
|
241
|
+
costPct: null,
|
|
242
|
+
localSharePct: null,
|
|
243
|
+
headline: 'No prior snapshot — this is the first reflection.',
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
const round1 = (n) => Math.round(n * 10) / 10;
|
|
247
|
+
// Effectiveness: signed percentage-POINT change of success rate.
|
|
248
|
+
const effectivenessPct = round1((current.successRate - previous.successRate) * 100);
|
|
249
|
+
// Cost: signed PERCENT change in avg cost per swarm. Guard divide-by-zero.
|
|
250
|
+
let costPct;
|
|
251
|
+
if (previous.avgCostUsd > 0) {
|
|
252
|
+
costPct = round1(((current.avgCostUsd - previous.avgCostUsd) / previous.avgCostUsd) * 100);
|
|
253
|
+
}
|
|
254
|
+
else if (current.avgCostUsd > 0) {
|
|
255
|
+
// Was free, now costs something — represent as +100% (newly non-zero).
|
|
256
|
+
costPct = 100;
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
costPct = 0;
|
|
260
|
+
}
|
|
261
|
+
// Local share: signed percentage-POINT change.
|
|
262
|
+
const localSharePct = round1((current.localShare - previous.localShare) * 100);
|
|
263
|
+
// Only annotate when BOTH windows are known and actually differ — comparing
|
|
264
|
+
// metrics across different windows/scopes makes the delta apples-to-oranges.
|
|
265
|
+
const windowsDiffer = currentWindow !== undefined &&
|
|
266
|
+
(previous.window ?? null) !== (currentWindow ?? null);
|
|
267
|
+
const baseHeadline = composeHeadline(effectivenessPct, costPct, localSharePct);
|
|
268
|
+
const headline = windowsDiffer
|
|
269
|
+
? `${baseHeadline} (windows differ: prior ${previous.window ?? 'all'} vs current ${currentWindow ?? 'all'})`
|
|
270
|
+
: baseHeadline;
|
|
271
|
+
return { previousAt: previous.generatedAt, effectivenessPct, costPct, localSharePct, headline };
|
|
272
|
+
}
|
|
273
|
+
/** Compose the deterministic week-over-week headline string. Pure. */
|
|
274
|
+
function composeHeadline(effPct, costPct, localPct) {
|
|
275
|
+
const parts = [];
|
|
276
|
+
if (effPct > 0)
|
|
277
|
+
parts.push(`${effPct.toFixed(1)}% more effective`);
|
|
278
|
+
else if (effPct < 0)
|
|
279
|
+
parts.push(`${Math.abs(effPct).toFixed(1)}% less effective`);
|
|
280
|
+
else
|
|
281
|
+
parts.push('equally effective');
|
|
282
|
+
if (costPct < 0)
|
|
283
|
+
parts.push(`${Math.abs(costPct).toFixed(1)}% cheaper`);
|
|
284
|
+
else if (costPct > 0)
|
|
285
|
+
parts.push(`${costPct.toFixed(1)}% more expensive`);
|
|
286
|
+
else
|
|
287
|
+
parts.push('cost unchanged');
|
|
288
|
+
if (localPct > 0)
|
|
289
|
+
parts.push(`${localPct.toFixed(1)} pts more local`);
|
|
290
|
+
else if (localPct < 0)
|
|
291
|
+
parts.push(`${Math.abs(localPct).toFixed(1)} pts less local`);
|
|
292
|
+
return `Since the last reflection, the org got ${parts.join(', ')}.`;
|
|
293
|
+
}
|
|
294
|
+
// ---------------------------------------------------------------------------
|
|
295
|
+
// Public: buildReflection — DETERMINISTIC, NO LLM, NO NETWORK
|
|
296
|
+
// ---------------------------------------------------------------------------
|
|
297
|
+
/**
|
|
298
|
+
* Build a ReflectionReport from the user's OWN local history.
|
|
299
|
+
*
|
|
300
|
+
* Reads (READ-ONLY):
|
|
301
|
+
* - listSwarms() — capped to the most-recent `maxRuns` and/or `sinceMs` window.
|
|
302
|
+
* - collectUsageEvents(sinceMs) — for the local-vs-cloud token share.
|
|
303
|
+
* - genomeHubHealth — HUB-ONLY entry counts (no portfolio disk scan).
|
|
304
|
+
*
|
|
305
|
+
* Computes: success rate, avg cost & tokens per swarm, local share, top failure
|
|
306
|
+
* modes, goal-category stats, and week-over-week deltas vs loadPreviousReport().
|
|
307
|
+
*
|
|
308
|
+
* DETERMINISTIC: makes ZERO network connections and uses NO LLM. Never throws —
|
|
309
|
+
* returns a zeroed report on any failure.
|
|
310
|
+
*/
|
|
311
|
+
export function buildReflection(
|
|
312
|
+
// cfg is retained for API compatibility (callers pass it positionally) but is
|
|
313
|
+
// no longer consumed: genomeHubHealth() reads ONLY the local hub store and
|
|
314
|
+
// takes no config (no portfolio walk, no embeddings probe).
|
|
315
|
+
_cfg, opts = {}) {
|
|
316
|
+
const now = new Date().toISOString();
|
|
317
|
+
// Window resolution:
|
|
318
|
+
// - opts.sinceMs === undefined => NO explicit window: apply the bounded
|
|
319
|
+
// DEFAULT_USAGE_LOOKBACK_MS so the default path never streams the entire
|
|
320
|
+
// historical corpus.
|
|
321
|
+
// - opts.sinceMs === 0 => explicit '--since all': scan all history
|
|
322
|
+
// (the caller opted in; still bounded by usage-source's per-file caps).
|
|
323
|
+
// - opts.sinceMs > 0 => an explicit Nd window.
|
|
324
|
+
const explicitAll = opts.sinceMs === 0;
|
|
325
|
+
const sinceMs = opts.sinceMs === undefined ? Date.now() - DEFAULT_USAGE_LOOKBACK_MS : opts.sinceMs;
|
|
326
|
+
const maxRuns = opts.maxRuns ?? DEFAULT_MAX_RUNS;
|
|
327
|
+
// --- Read swarm history (READ-ONLY, BOUNDED) ---
|
|
328
|
+
let swarms = [];
|
|
329
|
+
try {
|
|
330
|
+
const all = listSwarms(); // already capped at 200 + sorted most-recent first
|
|
331
|
+
swarms = all
|
|
332
|
+
.filter((s) => {
|
|
333
|
+
if (sinceMs <= 0)
|
|
334
|
+
return true;
|
|
335
|
+
const t = Date.parse(s.createdAt ?? '');
|
|
336
|
+
return Number.isFinite(t) ? t >= sinceMs : true;
|
|
337
|
+
})
|
|
338
|
+
.slice(0, Math.max(0, maxRuns));
|
|
339
|
+
}
|
|
340
|
+
catch {
|
|
341
|
+
swarms = [];
|
|
342
|
+
}
|
|
343
|
+
// --- Success / cost / token aggregates ---
|
|
344
|
+
let swarmsDone = 0;
|
|
345
|
+
let swarmsFailed = 0;
|
|
346
|
+
let totalCostUsd = 0;
|
|
347
|
+
let totalTokens = 0;
|
|
348
|
+
for (const s of swarms) {
|
|
349
|
+
if (s.status === 'done')
|
|
350
|
+
swarmsDone++;
|
|
351
|
+
else if (s.status === 'failed' || s.status === 'aborted')
|
|
352
|
+
swarmsFailed++;
|
|
353
|
+
totalCostUsd += swarmCost(s);
|
|
354
|
+
totalTokens += swarmTokens(s);
|
|
355
|
+
}
|
|
356
|
+
const swarmsAnalyzed = swarms.length;
|
|
357
|
+
// Success rate is computed over TERMINAL swarms only ('done'|'failed'|
|
|
358
|
+
// 'aborted'); in-flight statuses ('planning'|'running'|'needs-approval') are
|
|
359
|
+
// NOT counted as non-successes in the denominator (that would understate
|
|
360
|
+
// effectiveness and corrupt the week-over-week delta when in-flight counts
|
|
361
|
+
// differ between snapshots). swarmsAnalyzed still reports how many were read.
|
|
362
|
+
const swarmsTerminal = swarmsDone + swarmsFailed;
|
|
363
|
+
const successRate = swarmsTerminal > 0 ? swarmsDone / swarmsTerminal : 0;
|
|
364
|
+
// Cost/token averages stay over all analyzed swarms (in-flight runs still
|
|
365
|
+
// incur real spend that belongs in the per-swarm average).
|
|
366
|
+
const avgCostUsd = swarmsAnalyzed > 0 ? totalCostUsd / swarmsAnalyzed : 0;
|
|
367
|
+
const avgTokens = swarmsAnalyzed > 0 ? totalTokens / swarmsAnalyzed : 0;
|
|
368
|
+
// --- Local-vs-cloud token share from usage events (READ-ONLY) ---
|
|
369
|
+
let localShare = 0;
|
|
370
|
+
try {
|
|
371
|
+
const events = collectUsageEvents(explicitAll ? 0 : sinceMs);
|
|
372
|
+
let localTokens = 0;
|
|
373
|
+
let allTokens = 0;
|
|
374
|
+
for (const e of events) {
|
|
375
|
+
const tok = (e.tokensIn ?? 0) + (e.tokensOut ?? 0);
|
|
376
|
+
if (tok <= 0)
|
|
377
|
+
continue;
|
|
378
|
+
allTokens += tok;
|
|
379
|
+
if (isLocalProviderModel(e.model))
|
|
380
|
+
localTokens += tok;
|
|
381
|
+
}
|
|
382
|
+
localShare = allTokens > 0 ? localTokens / allTokens : 0;
|
|
383
|
+
}
|
|
384
|
+
catch {
|
|
385
|
+
localShare = 0;
|
|
386
|
+
}
|
|
387
|
+
// --- Failure clustering + goal categories (pure) ---
|
|
388
|
+
const topFailures = clusterFailures(swarms);
|
|
389
|
+
const goalCategories = summarizeGoalCategories(swarms);
|
|
390
|
+
// --- Week-over-week delta vs the prior snapshot ---
|
|
391
|
+
// currentWindow lets computeDelta annotate the headline when the prior
|
|
392
|
+
// snapshot covered a DIFFERENT window/scope (apples-to-oranges deltas).
|
|
393
|
+
const currentWindow = explicitAll ? 'all' : opts.window ?? null;
|
|
394
|
+
const delta = computeDelta({ successRate, avgCostUsd, localShare }, loadPreviousReport(now), currentWindow);
|
|
395
|
+
// --- Genome health snapshot (HUB-ONLY: no portfolio disk scan) ---
|
|
396
|
+
// Reads ONLY ~/.ashlr/genome/hub.jsonl via genomeHubHealth — it does NOT walk
|
|
397
|
+
// the configured portfolio roots, honouring invariant #4 (operate only on the
|
|
398
|
+
// user's OWN local hub history, never a portfolio disk scan).
|
|
399
|
+
let genome;
|
|
400
|
+
try {
|
|
401
|
+
genome = genomeHubHealth();
|
|
402
|
+
}
|
|
403
|
+
catch {
|
|
404
|
+
genome = {
|
|
405
|
+
totalEntries: 0,
|
|
406
|
+
projects: 0,
|
|
407
|
+
hubEntries: 0,
|
|
408
|
+
sizeBytes: 0,
|
|
409
|
+
lastLearnedAt: null,
|
|
410
|
+
embeddingsAvailable: false,
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
return {
|
|
414
|
+
generatedAt: now,
|
|
415
|
+
// Record the analysis lower bound. For '--since all' (explicitAll) there is
|
|
416
|
+
// no lower bound, so we record the sentinel 'all' rather than the Unix epoch
|
|
417
|
+
// (which would misrender as a 1970 window). An Nd / default window records
|
|
418
|
+
// its concrete ISO lower bound.
|
|
419
|
+
since: explicitAll ? 'all' : new Date(sinceMs).toISOString(),
|
|
420
|
+
window: explicitAll ? 'all' : opts.window ?? null,
|
|
421
|
+
swarmsAnalyzed,
|
|
422
|
+
swarmsDone,
|
|
423
|
+
swarmsFailed,
|
|
424
|
+
successRate,
|
|
425
|
+
avgCostUsd,
|
|
426
|
+
avgTokens,
|
|
427
|
+
totalCostUsd,
|
|
428
|
+
localShare,
|
|
429
|
+
topFailures,
|
|
430
|
+
goalCategories,
|
|
431
|
+
delta,
|
|
432
|
+
genome,
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
//# sourceMappingURL=reflect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reflect.js","sourceRoot":"","sources":["../../../src/core/learn/reflect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* store.ts — M26 reflection report persistence (~/.ashlr/learn/).
|
|
3
|
+
*
|
|
4
|
+
* Persists + loads ReflectionReport snapshots so each run can compute
|
|
5
|
+
* week-over-week deltas against the previous snapshot.
|
|
6
|
+
*
|
|
7
|
+
* Layout:
|
|
8
|
+
* ~/.ashlr/learn/reports/<generatedAt-ms>.json — one pretty-printed
|
|
9
|
+
* ReflectionReport per run
|
|
10
|
+
*
|
|
11
|
+
* HARD SAFETY INVARIANTS (M26):
|
|
12
|
+
* - READ-ONLY over history: this module READS swarms/genome/usage via the
|
|
13
|
+
* reflect engine; it WRITES ONLY under ~/.ashlr/learn/. It NEVER writes
|
|
14
|
+
* CONFIG_PATH / saveConfig() / router policy / prompts, and NEVER touches a
|
|
15
|
+
* user repo working tree.
|
|
16
|
+
* - Atomic-ish write: tmp-write + rename (POSIX-atomic), mirroring
|
|
17
|
+
* core/swarm/store.ts and core/inbox/store.ts.
|
|
18
|
+
* - Bounded: listReports caps how many snapshot files it reads.
|
|
19
|
+
* - Never throws: all exported functions swallow errors and return safe
|
|
20
|
+
* defaults (null / []).
|
|
21
|
+
*/
|
|
22
|
+
import type { ReflectionReport } from '../types.js';
|
|
23
|
+
/**
|
|
24
|
+
* Absolute path to the reports directory: `~/.ashlr/learn/reports`.
|
|
25
|
+
* Created lazily by saveReport — this function does NOT create it.
|
|
26
|
+
*/
|
|
27
|
+
export declare function reportsDir(): string;
|
|
28
|
+
/**
|
|
29
|
+
* Persist a ReflectionReport snapshot under ~/.ashlr/learn/reports/.
|
|
30
|
+
*
|
|
31
|
+
* Returns the absolute path written, or null on failure. Never throws.
|
|
32
|
+
*
|
|
33
|
+
* Atomic tmp-write + rename of `JSON.stringify(report, null, 2) + '\n'` to
|
|
34
|
+
* `reportsDir()/<reportStem(report.generatedAt)>.json`.
|
|
35
|
+
* MUST NOT write anywhere outside reportsDir().
|
|
36
|
+
*/
|
|
37
|
+
export declare function saveReport(report: ReflectionReport): string | null;
|
|
38
|
+
/**
|
|
39
|
+
* List persisted ReflectionReport snapshots, most-recent first by
|
|
40
|
+
* `generatedAt`. Reads at most MAX_REPORTS files. Never throws; returns [] on
|
|
41
|
+
* any error and silently skips unreadable/malformed files.
|
|
42
|
+
*/
|
|
43
|
+
export declare function listReports(): ReflectionReport[];
|
|
44
|
+
/**
|
|
45
|
+
* Load the most recent previously-persisted snapshot (the prior report used to
|
|
46
|
+
* compute week-over-week deltas), or null when none exists.
|
|
47
|
+
*
|
|
48
|
+
* `before` (optional ISO ts) excludes snapshots at/after it so a freshly-saved
|
|
49
|
+
* current report is not compared against itself.
|
|
50
|
+
*/
|
|
51
|
+
export declare function loadPreviousReport(before?: string): ReflectionReport | null;
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* store.ts — M26 reflection report persistence (~/.ashlr/learn/).
|
|
3
|
+
*
|
|
4
|
+
* Persists + loads ReflectionReport snapshots so each run can compute
|
|
5
|
+
* week-over-week deltas against the previous snapshot.
|
|
6
|
+
*
|
|
7
|
+
* Layout:
|
|
8
|
+
* ~/.ashlr/learn/reports/<generatedAt-ms>.json — one pretty-printed
|
|
9
|
+
* ReflectionReport per run
|
|
10
|
+
*
|
|
11
|
+
* HARD SAFETY INVARIANTS (M26):
|
|
12
|
+
* - READ-ONLY over history: this module READS swarms/genome/usage via the
|
|
13
|
+
* reflect engine; it WRITES ONLY under ~/.ashlr/learn/. It NEVER writes
|
|
14
|
+
* CONFIG_PATH / saveConfig() / router policy / prompts, and NEVER touches a
|
|
15
|
+
* user repo working tree.
|
|
16
|
+
* - Atomic-ish write: tmp-write + rename (POSIX-atomic), mirroring
|
|
17
|
+
* core/swarm/store.ts and core/inbox/store.ts.
|
|
18
|
+
* - Bounded: listReports caps how many snapshot files it reads.
|
|
19
|
+
* - Never throws: all exported functions swallow errors and return safe
|
|
20
|
+
* defaults (null / []).
|
|
21
|
+
*/
|
|
22
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, writeFileSync, } from 'node:fs';
|
|
23
|
+
import { join } from 'node:path';
|
|
24
|
+
import { learnDir } from '../config.js';
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// Bounds
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
/** Never read more than this many snapshot files at once (bounds I/O). */
|
|
29
|
+
const MAX_REPORTS = 200;
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// Path helpers (re-resolved at call time so tests can relocate HOME)
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
/**
|
|
34
|
+
* Absolute path to the reports directory: `~/.ashlr/learn/reports`.
|
|
35
|
+
* Created lazily by saveReport — this function does NOT create it.
|
|
36
|
+
*/
|
|
37
|
+
export function reportsDir() {
|
|
38
|
+
return join(learnDir(), 'reports');
|
|
39
|
+
}
|
|
40
|
+
/** Ensure a directory exists, silently creating it if needed. */
|
|
41
|
+
function ensureDir(dir) {
|
|
42
|
+
try {
|
|
43
|
+
if (!existsSync(dir))
|
|
44
|
+
mkdirSync(dir, { recursive: true });
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// Best-effort; a subsequent write will fail gracefully in its try/catch.
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** Derive a filename-safe, chronologically-sortable stem from an ISO ts. */
|
|
51
|
+
function reportStem(generatedAt) {
|
|
52
|
+
// Epoch-ms keeps lexicographic order == chronological order. Fall back to a
|
|
53
|
+
// sanitized ISO string if the timestamp is unparseable.
|
|
54
|
+
const ms = Date.parse(generatedAt);
|
|
55
|
+
if (Number.isFinite(ms))
|
|
56
|
+
return String(ms);
|
|
57
|
+
return generatedAt.replace(/[^\w.-]+/g, '-');
|
|
58
|
+
}
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
// Persist
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
/**
|
|
63
|
+
* Persist a ReflectionReport snapshot under ~/.ashlr/learn/reports/.
|
|
64
|
+
*
|
|
65
|
+
* Returns the absolute path written, or null on failure. Never throws.
|
|
66
|
+
*
|
|
67
|
+
* Atomic tmp-write + rename of `JSON.stringify(report, null, 2) + '\n'` to
|
|
68
|
+
* `reportsDir()/<reportStem(report.generatedAt)>.json`.
|
|
69
|
+
* MUST NOT write anywhere outside reportsDir().
|
|
70
|
+
*/
|
|
71
|
+
export function saveReport(report) {
|
|
72
|
+
try {
|
|
73
|
+
const dir = reportsDir();
|
|
74
|
+
ensureDir(dir);
|
|
75
|
+
const dest = join(dir, `${reportStem(report.generatedAt)}.json`);
|
|
76
|
+
const tmp = dest + '.tmp';
|
|
77
|
+
writeFileSync(tmp, JSON.stringify(report, null, 2) + '\n', 'utf8');
|
|
78
|
+
renameSync(tmp, dest);
|
|
79
|
+
return dest;
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
// Load
|
|
87
|
+
// ---------------------------------------------------------------------------
|
|
88
|
+
/** Light structural guard so we never return garbage from the store. */
|
|
89
|
+
function isReport(parsed) {
|
|
90
|
+
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
const r = parsed;
|
|
94
|
+
return (typeof r['generatedAt'] === 'string' &&
|
|
95
|
+
typeof r['since'] === 'string' &&
|
|
96
|
+
typeof r['successRate'] === 'number');
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* List persisted ReflectionReport snapshots, most-recent first by
|
|
100
|
+
* `generatedAt`. Reads at most MAX_REPORTS files. Never throws; returns [] on
|
|
101
|
+
* any error and silently skips unreadable/malformed files.
|
|
102
|
+
*/
|
|
103
|
+
export function listReports() {
|
|
104
|
+
try {
|
|
105
|
+
const dir = reportsDir();
|
|
106
|
+
if (!existsSync(dir))
|
|
107
|
+
return [];
|
|
108
|
+
let files;
|
|
109
|
+
try {
|
|
110
|
+
// Filename stems are epoch-ms, so a lexicographic descending sort of the
|
|
111
|
+
// filenames already orders newest-first; sort here so the slice keeps the
|
|
112
|
+
// MOST-RECENT MAX_REPORTS rather than an arbitrary directory order.
|
|
113
|
+
files = readdirSync(dir)
|
|
114
|
+
.filter((f) => f.endsWith('.json') && !f.endsWith('.tmp'))
|
|
115
|
+
.sort((a, b) => (a < b ? 1 : a > b ? -1 : 0))
|
|
116
|
+
.slice(0, MAX_REPORTS);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return [];
|
|
120
|
+
}
|
|
121
|
+
const reports = [];
|
|
122
|
+
for (const file of files) {
|
|
123
|
+
try {
|
|
124
|
+
const raw = readFileSync(join(dir, file), 'utf8');
|
|
125
|
+
const parsed = JSON.parse(raw);
|
|
126
|
+
if (isReport(parsed))
|
|
127
|
+
reports.push(parsed);
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
// Unreadable or malformed — skip silently.
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Most-recent first by generatedAt (ISO strings sort lexicographically).
|
|
134
|
+
reports.sort((a, b) => a.generatedAt < b.generatedAt ? 1 : a.generatedAt > b.generatedAt ? -1 : 0);
|
|
135
|
+
return reports;
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return [];
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Load the most recent previously-persisted snapshot (the prior report used to
|
|
143
|
+
* compute week-over-week deltas), or null when none exists.
|
|
144
|
+
*
|
|
145
|
+
* `before` (optional ISO ts) excludes snapshots at/after it so a freshly-saved
|
|
146
|
+
* current report is not compared against itself.
|
|
147
|
+
*/
|
|
148
|
+
export function loadPreviousReport(before) {
|
|
149
|
+
try {
|
|
150
|
+
const all = listReports();
|
|
151
|
+
if (all.length === 0)
|
|
152
|
+
return null;
|
|
153
|
+
if (before === undefined)
|
|
154
|
+
return all[0] ?? null;
|
|
155
|
+
for (const r of all) {
|
|
156
|
+
if (r.generatedAt < before)
|
|
157
|
+
return r;
|
|
158
|
+
}
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=store.js.map
|