@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,667 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI handler for `ashlr goals` — M28 GOAL PLANNING & SCHEDULING (Ashlr v2
|
|
3
|
+
* pillar F).
|
|
4
|
+
*
|
|
5
|
+
* High-level OBJECTIVES decompose into ordered MILESTONES; each milestone maps
|
|
6
|
+
* to a versioned spec; advancing a milestone runs a SANDBOXED, PROPOSAL-ONLY
|
|
7
|
+
* swarm (the exact M21/M24 pattern), producing a PENDING inbox proposal a human
|
|
8
|
+
* approves later. Milestones are TRACKED and STEERABLE (add/edit/reorder/pause/
|
|
9
|
+
* skip). The DEFAULT path is local + deterministic + read-mostly.
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* ashlr goals add "<objective>" [--project <enrolled-repo>]
|
|
13
|
+
* ashlr goals list [--json]
|
|
14
|
+
* ashlr goals show <id> [--json]
|
|
15
|
+
* ashlr goals plan <id> [--allow-cloud] [--max <n>] # decompose + author specs
|
|
16
|
+
* ashlr goals advance <id> # sandboxed, proposal-only run of the NEXT milestone
|
|
17
|
+
* ashlr goals status [--json] # tracking dashboard
|
|
18
|
+
* ashlr goals pause <id> [milestone]
|
|
19
|
+
* ashlr goals resume <id> [milestone]
|
|
20
|
+
* ashlr goals skip <id> <milestone>
|
|
21
|
+
* ashlr goals reorder <id> <m1> <m2> ...
|
|
22
|
+
* ashlr goals delete <id>
|
|
23
|
+
*
|
|
24
|
+
* HARD SAFETY INVARIANTS (M28) enforced by this surface:
|
|
25
|
+
* 1. SANDBOXED + PROPOSAL-ONLY: `advance` routes to core advanceGoal(), which
|
|
26
|
+
* ALWAYS calls runSwarm with { sandbox:true, requireSandbox:true,
|
|
27
|
+
* propose:true } + a hard budget. This CLI contains NO applyProposal /
|
|
28
|
+
* setStatus(approved) / git push / createPr / deploy.
|
|
29
|
+
* 2. ENROLLMENT-SCOPED: `add --project <repo>` and `advance` resolve() the
|
|
30
|
+
* repo and filter through isEnrolled() HERE (CLI layer) AND again in core
|
|
31
|
+
* (advanceGoal -> assertMayMutate); a non-enrolled path HARD-ERRORS (exit 1)
|
|
32
|
+
* before any swarm starts. (M25 lesson: filter at BOTH layers.)
|
|
33
|
+
* 3. LOCAL-FIRST: `plan` is deterministic by default; --allow-cloud (off by
|
|
34
|
+
* default) opens the local-first provider chain (cloud only with a key) and
|
|
35
|
+
* prints a warning, mirroring reflect.ts / ask.ts.
|
|
36
|
+
* 4. STEERABLE + BOUNDED: no auto-advance loop — `advance` is an explicit,
|
|
37
|
+
* single-milestone action. `plan` is bounded by --max.
|
|
38
|
+
* 5. READ-ONLY TRACKING: `list`/`show`/`status` only READ ~/.ashlr/goals +
|
|
39
|
+
* swarm/inbox state; they mutate nothing.
|
|
40
|
+
*
|
|
41
|
+
* Exit codes: 0 success, 1 runtime error / not-enrolled, 2 bad usage.
|
|
42
|
+
*/
|
|
43
|
+
import { resolve } from 'node:path';
|
|
44
|
+
import { pad, makeColors, isTty } from './ui.js';
|
|
45
|
+
import { parsePositiveInt } from './args.js';
|
|
46
|
+
let _core = undefined;
|
|
47
|
+
async function importCore() {
|
|
48
|
+
if (_core === undefined) {
|
|
49
|
+
try {
|
|
50
|
+
const [store, planner, advance, policy, config] = await Promise.all([
|
|
51
|
+
import('../core/goals/store.js'),
|
|
52
|
+
import('../core/goals/planner.js'),
|
|
53
|
+
import('../core/goals/advance.js'),
|
|
54
|
+
import('../core/sandbox/policy.js'),
|
|
55
|
+
import('../core/config.js'),
|
|
56
|
+
]);
|
|
57
|
+
_core = {
|
|
58
|
+
createGoal: store.createGoal,
|
|
59
|
+
loadGoal: store.loadGoal,
|
|
60
|
+
listGoals: store.listGoals,
|
|
61
|
+
addMilestone: store.addMilestone,
|
|
62
|
+
updateMilestoneStatus: store.updateMilestoneStatus,
|
|
63
|
+
pauseMilestone: store.pauseMilestone,
|
|
64
|
+
resumeMilestone: store.resumeMilestone,
|
|
65
|
+
skipMilestone: store.skipMilestone,
|
|
66
|
+
reorderMilestones: store.reorderMilestones,
|
|
67
|
+
clearMilestones: store.clearMilestones,
|
|
68
|
+
deleteGoal: store.deleteGoal,
|
|
69
|
+
decomposeGoal: planner.decomposeGoal,
|
|
70
|
+
planMilestoneSpec: planner.planMilestoneSpec,
|
|
71
|
+
advanceGoal: advance.advanceGoal,
|
|
72
|
+
progressOf: advance.progressOf,
|
|
73
|
+
isEnrolled: policy.isEnrolled,
|
|
74
|
+
loadConfig: config.loadConfig,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
_core = null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return _core ?? null;
|
|
82
|
+
}
|
|
83
|
+
const SUBS = [
|
|
84
|
+
'add',
|
|
85
|
+
'list',
|
|
86
|
+
'show',
|
|
87
|
+
'plan',
|
|
88
|
+
'advance',
|
|
89
|
+
'status',
|
|
90
|
+
'pause',
|
|
91
|
+
'resume',
|
|
92
|
+
'skip',
|
|
93
|
+
'reorder',
|
|
94
|
+
'delete',
|
|
95
|
+
];
|
|
96
|
+
function parseGoalsArgs(args) {
|
|
97
|
+
const parsed = {
|
|
98
|
+
sub: 'list',
|
|
99
|
+
arg1: undefined,
|
|
100
|
+
arg2: undefined,
|
|
101
|
+
positionals: [],
|
|
102
|
+
project: undefined,
|
|
103
|
+
max: undefined,
|
|
104
|
+
json: false,
|
|
105
|
+
allowCloud: false,
|
|
106
|
+
replace: false,
|
|
107
|
+
help: false,
|
|
108
|
+
error: undefined,
|
|
109
|
+
};
|
|
110
|
+
if (args.length === 0)
|
|
111
|
+
return parsed;
|
|
112
|
+
const positionals = [];
|
|
113
|
+
let i = 0;
|
|
114
|
+
let subSeen = false;
|
|
115
|
+
for (; i < args.length; i++) {
|
|
116
|
+
const a = args[i];
|
|
117
|
+
if (a === '--help' || a === '-h') {
|
|
118
|
+
parsed.help = true;
|
|
119
|
+
}
|
|
120
|
+
else if (a === '--json') {
|
|
121
|
+
parsed.json = true;
|
|
122
|
+
}
|
|
123
|
+
else if (a === '--allow-cloud') {
|
|
124
|
+
parsed.allowCloud = true;
|
|
125
|
+
}
|
|
126
|
+
else if (a === '--replace') {
|
|
127
|
+
parsed.replace = true;
|
|
128
|
+
}
|
|
129
|
+
else if (a === '--project') {
|
|
130
|
+
const val = args[++i];
|
|
131
|
+
if (val === undefined) {
|
|
132
|
+
parsed.error = '--project requires a repo path';
|
|
133
|
+
return parsed;
|
|
134
|
+
}
|
|
135
|
+
parsed.project = val;
|
|
136
|
+
}
|
|
137
|
+
else if (a.startsWith('--project=')) {
|
|
138
|
+
parsed.project = a.slice('--project='.length);
|
|
139
|
+
}
|
|
140
|
+
else if (a === '--max') {
|
|
141
|
+
const r = parsePositiveInt('max', args[++i]);
|
|
142
|
+
if ('error' in r) {
|
|
143
|
+
parsed.error = r.error;
|
|
144
|
+
return parsed;
|
|
145
|
+
}
|
|
146
|
+
parsed.max = r.n;
|
|
147
|
+
}
|
|
148
|
+
else if (a.startsWith('--max=')) {
|
|
149
|
+
const r = parsePositiveInt('max', a.slice('--max='.length));
|
|
150
|
+
if ('error' in r) {
|
|
151
|
+
parsed.error = r.error;
|
|
152
|
+
return parsed;
|
|
153
|
+
}
|
|
154
|
+
parsed.max = r.n;
|
|
155
|
+
}
|
|
156
|
+
else if (a.startsWith('-') && a !== '-') {
|
|
157
|
+
parsed.error = `unknown flag: ${a}`;
|
|
158
|
+
return parsed;
|
|
159
|
+
}
|
|
160
|
+
else if (!subSeen) {
|
|
161
|
+
// First positional is the subcommand.
|
|
162
|
+
if (!SUBS.includes(a)) {
|
|
163
|
+
parsed.error = `unknown subcommand: ${a}`;
|
|
164
|
+
return parsed;
|
|
165
|
+
}
|
|
166
|
+
parsed.sub = a;
|
|
167
|
+
subSeen = true;
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
positionals.push(a);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
parsed.arg1 = positionals[0];
|
|
174
|
+
parsed.arg2 = positionals[1];
|
|
175
|
+
parsed.positionals = positionals;
|
|
176
|
+
return parsed;
|
|
177
|
+
}
|
|
178
|
+
// ─── Help ─────────────────────────────────────────────────────────────────────
|
|
179
|
+
function printHelp() {
|
|
180
|
+
const tty = isTty();
|
|
181
|
+
const { bold, cyan, gray, dim } = makeColors(tty);
|
|
182
|
+
const out = (s) => {
|
|
183
|
+
process.stdout.write(s + '\n');
|
|
184
|
+
};
|
|
185
|
+
out('');
|
|
186
|
+
out(bold(' ashlr goals') + gray(' — plan, track, and steer high-level objectives'));
|
|
187
|
+
out('');
|
|
188
|
+
out(bold(' Usage'));
|
|
189
|
+
out(` ${cyan('ashlr goals add "<objective>"')} [--project <enrolled-repo>]`);
|
|
190
|
+
out(` ${cyan('ashlr goals list')} [--json]`);
|
|
191
|
+
out(` ${cyan('ashlr goals show <id>')} [--json]`);
|
|
192
|
+
out(` ${cyan('ashlr goals plan <id>')} [--allow-cloud] [--max <n>] [--replace]`);
|
|
193
|
+
out(` ${cyan('ashlr goals advance <id>')}`);
|
|
194
|
+
out(` ${cyan('ashlr goals status')} [--json]`);
|
|
195
|
+
out(` ${cyan('ashlr goals pause <id>')} [milestone]`);
|
|
196
|
+
out(` ${cyan('ashlr goals resume <id>')} [milestone]`);
|
|
197
|
+
out(` ${cyan('ashlr goals skip <id> <milestone>')}`);
|
|
198
|
+
out(` ${cyan('ashlr goals reorder <id> <m1> <m2> ...')}`);
|
|
199
|
+
out(` ${cyan('ashlr goals delete <id>')}`);
|
|
200
|
+
out('');
|
|
201
|
+
out(bold(' Options'));
|
|
202
|
+
const opts = [
|
|
203
|
+
['--project <repo>', 'Bind a goal to an ENROLLED repo (required to advance).'],
|
|
204
|
+
['--max <n>', 'Cap how many milestones `plan` produces (bounded; default 8, max 16).'],
|
|
205
|
+
['--allow-cloud', 'Allow a CLOUD model for optional plan refinement + spec authoring. Off by default.'],
|
|
206
|
+
['--replace', 'On `plan`, clear an already-planned goal’s milestones before re-planning.'],
|
|
207
|
+
['--json', 'Machine-readable output on read paths (list/show/status).'],
|
|
208
|
+
['--help', 'Show this help.'],
|
|
209
|
+
];
|
|
210
|
+
for (const [flag, desc] of opts) {
|
|
211
|
+
out(` ${cyan(pad(flag, 18))} ${desc}`);
|
|
212
|
+
}
|
|
213
|
+
out('');
|
|
214
|
+
out(dim(' Planning is deterministic + local-only by default (no model, zero network).'));
|
|
215
|
+
out(dim(' `advance` is SANDBOXED + PROPOSAL-ONLY: it produces a PENDING inbox proposal'));
|
|
216
|
+
out(dim(' a human reviews with `ashlr inbox`. Nothing auto-applies; no real working'));
|
|
217
|
+
out(dim(' tree is ever mutated, pushed, or deployed.'));
|
|
218
|
+
out('');
|
|
219
|
+
}
|
|
220
|
+
// ─── Status glyphs ─────────────────────────────────────────────────────────────
|
|
221
|
+
function statusGlyph(s) {
|
|
222
|
+
switch (s) {
|
|
223
|
+
case 'done':
|
|
224
|
+
return '✓';
|
|
225
|
+
case 'proposed':
|
|
226
|
+
return '◆';
|
|
227
|
+
case 'in-progress':
|
|
228
|
+
return '⟳';
|
|
229
|
+
case 'blocked':
|
|
230
|
+
return '✗';
|
|
231
|
+
case 'paused':
|
|
232
|
+
return '⏸';
|
|
233
|
+
case 'skipped':
|
|
234
|
+
return '⊘';
|
|
235
|
+
default:
|
|
236
|
+
return '·';
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
// ─── Main export ─────────────────────────────────────────────────────────────
|
|
240
|
+
/**
|
|
241
|
+
* `ashlr goals <add|list|show|plan|advance|status|pause|resume|skip> ...`
|
|
242
|
+
*
|
|
243
|
+
* Default/`list`/`show`/`status`: read-only tracking over ~/.ashlr/goals +
|
|
244
|
+
* swarm/inbox state. `add` creates a Goal (ENROLLMENT-checked --project). `plan`
|
|
245
|
+
* decomposes + authors specs (deterministic; --allow-cloud opt-in). `advance`
|
|
246
|
+
* runs the NEXT milestone through the sandboxed, proposal-only swarm path
|
|
247
|
+
* (assertMayMutate-gated; produces a PENDING inbox proposal). pause/resume/skip
|
|
248
|
+
* STEER the plan. Nothing auto-applies; no real working tree is ever mutated.
|
|
249
|
+
*
|
|
250
|
+
* Exit codes: 0 success, 1 runtime error / not-enrolled, 2 bad usage.
|
|
251
|
+
*/
|
|
252
|
+
export async function cmdGoals(args) {
|
|
253
|
+
const parsed = parseGoalsArgs(args);
|
|
254
|
+
const tty = isTty();
|
|
255
|
+
const { red, green, yellow, bold, cyan, gray, dim } = makeColors(tty);
|
|
256
|
+
const out = (s) => {
|
|
257
|
+
process.stdout.write(s + '\n');
|
|
258
|
+
};
|
|
259
|
+
if (parsed.help) {
|
|
260
|
+
printHelp();
|
|
261
|
+
return 0;
|
|
262
|
+
}
|
|
263
|
+
if (parsed.error) {
|
|
264
|
+
process.stderr.write(red('error: ') + parsed.error + '\n');
|
|
265
|
+
process.stderr.write('Run `ashlr goals --help` for usage.\n');
|
|
266
|
+
return 2;
|
|
267
|
+
}
|
|
268
|
+
const core = await importCore();
|
|
269
|
+
if (!core) {
|
|
270
|
+
process.stderr.write(red('error: ') + 'goals command requires the M28 core (src/core/goals/*).\n');
|
|
271
|
+
return 1;
|
|
272
|
+
}
|
|
273
|
+
const cfg = core.loadConfig();
|
|
274
|
+
// LOCAL-FIRST privacy warning for --allow-cloud (mirror ask.ts / reflect.ts).
|
|
275
|
+
// Only meaningful on `plan` (the sole model-assisted path); printed to stderr
|
|
276
|
+
// so --json stdout stays clean.
|
|
277
|
+
if (parsed.allowCloud && parsed.sub === 'plan') {
|
|
278
|
+
process.stderr.write(yellow('warning: ') +
|
|
279
|
+
'--allow-cloud is set — objective + milestone text MAY be sent to a cloud model\n' +
|
|
280
|
+
' to refine the plan AND to author each milestone’s spec.\n' +
|
|
281
|
+
' Omit --allow-cloud to keep ALL planning + spec authoring deterministic +\n' +
|
|
282
|
+
' on-machine (default: zero non-localhost connections).\n');
|
|
283
|
+
}
|
|
284
|
+
switch (parsed.sub) {
|
|
285
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
286
|
+
case 'add': {
|
|
287
|
+
const objective = parsed.arg1;
|
|
288
|
+
if (!objective || objective.trim().length === 0) {
|
|
289
|
+
process.stderr.write(red('error: ') + 'add requires an objective string.\n');
|
|
290
|
+
return 2;
|
|
291
|
+
}
|
|
292
|
+
// ENROLLMENT-SCOPING (M25 lesson): resolve() + isEnrolled()-check --project
|
|
293
|
+
// HERE before persisting. Core enforces it again on advance.
|
|
294
|
+
let project = null;
|
|
295
|
+
if (parsed.project !== undefined) {
|
|
296
|
+
const abs = resolve(parsed.project);
|
|
297
|
+
if (!core.isEnrolled(abs)) {
|
|
298
|
+
process.stderr.write(red('error: ') +
|
|
299
|
+
`repo not enrolled for autonomous work: ${abs}\n` +
|
|
300
|
+
' Enroll it first (e.g. `ashlr sandbox enroll <repo>`) before binding a goal.\n');
|
|
301
|
+
return 1;
|
|
302
|
+
}
|
|
303
|
+
project = abs;
|
|
304
|
+
}
|
|
305
|
+
const goal = core.createGoal(objective.trim(), { project });
|
|
306
|
+
if (parsed.json) {
|
|
307
|
+
out(JSON.stringify(goal, null, 2));
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
out(green('✓ ') + bold('created goal ') + cyan(goal.id));
|
|
311
|
+
out(` objective: ${goal.objective}`);
|
|
312
|
+
out(` project: ${goal.project ?? gray('(none — planning only; cannot advance)')}`);
|
|
313
|
+
out('');
|
|
314
|
+
out(dim(' Next: `ashlr goals plan ' + goal.id + '` to decompose into milestones.'));
|
|
315
|
+
}
|
|
316
|
+
return 0;
|
|
317
|
+
}
|
|
318
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
319
|
+
case 'list': {
|
|
320
|
+
// READ-ONLY.
|
|
321
|
+
const goals = core.listGoals();
|
|
322
|
+
if (parsed.json) {
|
|
323
|
+
out(JSON.stringify(goals, null, 2));
|
|
324
|
+
return 0;
|
|
325
|
+
}
|
|
326
|
+
if (goals.length === 0) {
|
|
327
|
+
out(gray(' No goals yet. Create one with `ashlr goals add "<objective>"`.'));
|
|
328
|
+
return 0;
|
|
329
|
+
}
|
|
330
|
+
out('');
|
|
331
|
+
out(bold(' Goals') + gray(` (${goals.length})`));
|
|
332
|
+
out('');
|
|
333
|
+
for (const g of goals) {
|
|
334
|
+
const prog = core.progressOf(g);
|
|
335
|
+
const pct = Math.round(prog.fractionDone * 100);
|
|
336
|
+
out(` ${cyan(pad(g.id, 28))} ${pad(g.status, 10)} ` +
|
|
337
|
+
gray(`${prog.done}/${prog.total} done (${pct}%)`));
|
|
338
|
+
out(` ${gray(pad('', 28))} ${dim(g.objective.slice(0, 60))}`);
|
|
339
|
+
}
|
|
340
|
+
out('');
|
|
341
|
+
return 0;
|
|
342
|
+
}
|
|
343
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
344
|
+
case 'show': {
|
|
345
|
+
// READ-ONLY.
|
|
346
|
+
const id = parsed.arg1;
|
|
347
|
+
if (!id) {
|
|
348
|
+
process.stderr.write(red('error: ') + 'show requires a goal id.\n');
|
|
349
|
+
return 2;
|
|
350
|
+
}
|
|
351
|
+
const goal = core.loadGoal(id);
|
|
352
|
+
if (!goal) {
|
|
353
|
+
process.stderr.write(red('error: ') + `goal not found: ${id}\n`);
|
|
354
|
+
return 1;
|
|
355
|
+
}
|
|
356
|
+
if (parsed.json) {
|
|
357
|
+
out(JSON.stringify(goal, null, 2));
|
|
358
|
+
return 0;
|
|
359
|
+
}
|
|
360
|
+
out('');
|
|
361
|
+
out(bold(' ' + goal.objective));
|
|
362
|
+
out(` ${gray('id:')} ${cyan(goal.id)} ${gray('status:')} ${goal.status}`);
|
|
363
|
+
out(` ${gray('project:')} ${goal.project ?? gray('(none)')}`);
|
|
364
|
+
out('');
|
|
365
|
+
if (goal.milestones.length === 0) {
|
|
366
|
+
out(gray(' No milestones yet. Run `ashlr goals plan ' + goal.id + '`.'));
|
|
367
|
+
}
|
|
368
|
+
else {
|
|
369
|
+
out(bold(' Milestones'));
|
|
370
|
+
for (const m of goal.milestones) {
|
|
371
|
+
out(` ${statusGlyph(m.status)} ${cyan(pad(`#${m.order}`, 4))} ${pad(m.status, 12)} ${m.title}`);
|
|
372
|
+
const links = [];
|
|
373
|
+
if (m.specId)
|
|
374
|
+
links.push(`spec=${m.specId}`);
|
|
375
|
+
if (m.swarmId)
|
|
376
|
+
links.push(`swarm=${m.swarmId}`);
|
|
377
|
+
if (m.proposalId)
|
|
378
|
+
links.push(`proposal=${m.proposalId}`);
|
|
379
|
+
if (links.length > 0)
|
|
380
|
+
out(` ${gray(links.join(' '))}`);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
out('');
|
|
384
|
+
return 0;
|
|
385
|
+
}
|
|
386
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
387
|
+
case 'plan': {
|
|
388
|
+
const id = parsed.arg1;
|
|
389
|
+
if (!id) {
|
|
390
|
+
process.stderr.write(red('error: ') + 'plan requires a goal id.\n');
|
|
391
|
+
return 2;
|
|
392
|
+
}
|
|
393
|
+
const goal = core.loadGoal(id);
|
|
394
|
+
if (!goal) {
|
|
395
|
+
process.stderr.write(red('error: ') + `goal not found: ${id}\n`);
|
|
396
|
+
return 1;
|
|
397
|
+
}
|
|
398
|
+
// IDEMPOTENCY GUARD: `plan` appends milestones, so re-planning an already-
|
|
399
|
+
// planned goal would DUPLICATE the entire set (corrupting order, progress
|
|
400
|
+
// denominators, and nextActionableMilestone sequencing). Refuse unless the
|
|
401
|
+
// user explicitly asks to --replace, which clears the existing milestones
|
|
402
|
+
// first (a deliberate, destructive re-plan). Steering (reorder/skip/pause)
|
|
403
|
+
// is the non-destructive way to adjust an existing plan.
|
|
404
|
+
if (goal.milestones.length > 0 && !parsed.replace) {
|
|
405
|
+
process.stderr.write(red('error: ') +
|
|
406
|
+
`goal already planned (${goal.milestones.length} milestone(s)).\n` +
|
|
407
|
+
' Use `--replace` to clear + re-plan, or steer with ' +
|
|
408
|
+
'`reorder`/`skip`/`pause`,\n' +
|
|
409
|
+
' or create a new goal.\n');
|
|
410
|
+
return 1;
|
|
411
|
+
}
|
|
412
|
+
if (goal.milestones.length > 0 && parsed.replace) {
|
|
413
|
+
// --replace: clear the existing plan so we re-plan from a clean slate.
|
|
414
|
+
core.clearMilestones(goal.id);
|
|
415
|
+
}
|
|
416
|
+
// DETERMINISTIC by default; --allow-cloud opens the local-first chain.
|
|
417
|
+
const milestones = await core.decomposeGoal(goal.objective, cfg, {
|
|
418
|
+
allowCloud: parsed.allowCloud,
|
|
419
|
+
maxMilestones: parsed.max,
|
|
420
|
+
});
|
|
421
|
+
// Materialize milestones (bounded) then author + link a spec for each.
|
|
422
|
+
let working = core.loadGoal(goal.id) ?? goal;
|
|
423
|
+
const authored = [];
|
|
424
|
+
for (const m of milestones) {
|
|
425
|
+
const updated = core.addMilestone(working.id, { title: m.title, detail: m.detail });
|
|
426
|
+
if (!updated)
|
|
427
|
+
continue;
|
|
428
|
+
working = updated;
|
|
429
|
+
const newest = working.milestones[working.milestones.length - 1];
|
|
430
|
+
let specId = null;
|
|
431
|
+
try {
|
|
432
|
+
// LOCAL-FIRST: thread the user's explicit --allow-cloud decision into
|
|
433
|
+
// spec authoring. Default (no flag) is false => spec authoring can
|
|
434
|
+
// NEVER reach a cloud provider on the default `goals plan` path, even
|
|
435
|
+
// when a cloud provider sits in the configured providerChain.
|
|
436
|
+
const spec = await core.planMilestoneSpec(working, newest, cfg, {
|
|
437
|
+
allowCloud: parsed.allowCloud,
|
|
438
|
+
});
|
|
439
|
+
specId = spec.id;
|
|
440
|
+
const linked = core.updateMilestoneStatus(working.id, newest.id, 'pending', {
|
|
441
|
+
specId,
|
|
442
|
+
});
|
|
443
|
+
if (linked)
|
|
444
|
+
working = linked;
|
|
445
|
+
}
|
|
446
|
+
catch {
|
|
447
|
+
// Spec authoring is best-effort; the milestone still exists unplanned.
|
|
448
|
+
specId = null;
|
|
449
|
+
}
|
|
450
|
+
authored.push({ milestone: newest, specId });
|
|
451
|
+
}
|
|
452
|
+
if (parsed.json) {
|
|
453
|
+
out(JSON.stringify(core.loadGoal(working.id) ?? working, null, 2));
|
|
454
|
+
return 0;
|
|
455
|
+
}
|
|
456
|
+
out(green('✓ ') + bold('planned ') + cyan(`${authored.length}`) + bold(' milestone(s)') +
|
|
457
|
+
gray(` for ${working.id}`));
|
|
458
|
+
for (const a of authored) {
|
|
459
|
+
out(` ${cyan(pad(`#${a.milestone.order}`, 4))} ${a.milestone.title}` +
|
|
460
|
+
(a.specId ? gray(` spec=${a.specId}`) : gray(' (spec deferred)')));
|
|
461
|
+
}
|
|
462
|
+
out('');
|
|
463
|
+
out(dim(' Next: `ashlr goals advance ' + working.id + '` to run the next milestone'));
|
|
464
|
+
out(dim(' (sandboxed + proposal-only).'));
|
|
465
|
+
return 0;
|
|
466
|
+
}
|
|
467
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
468
|
+
case 'advance': {
|
|
469
|
+
const id = parsed.arg1;
|
|
470
|
+
if (!id) {
|
|
471
|
+
process.stderr.write(red('error: ') + 'advance requires a goal id.\n');
|
|
472
|
+
return 2;
|
|
473
|
+
}
|
|
474
|
+
const goal = core.loadGoal(id);
|
|
475
|
+
if (!goal) {
|
|
476
|
+
process.stderr.write(red('error: ') + `goal not found: ${id}\n`);
|
|
477
|
+
return 1;
|
|
478
|
+
}
|
|
479
|
+
// ENROLLMENT-SCOPING (M25 lesson): re-check the goal's project HERE before
|
|
480
|
+
// any core call that could start a swarm. Core (advanceGoal ->
|
|
481
|
+
// assertMayMutate) enforces this AGAIN.
|
|
482
|
+
if (!goal.project) {
|
|
483
|
+
process.stderr.write(red('error: ') + 'goal has no enrolled project; cannot advance.\n' +
|
|
484
|
+
' Bind a goal to an enrolled repo with `--project` on `add`.\n');
|
|
485
|
+
return 1;
|
|
486
|
+
}
|
|
487
|
+
const repo = resolve(goal.project);
|
|
488
|
+
if (!core.isEnrolled(repo)) {
|
|
489
|
+
process.stderr.write(red('error: ') + `repo not enrolled for autonomous work: ${repo}\n`);
|
|
490
|
+
return 1;
|
|
491
|
+
}
|
|
492
|
+
let run;
|
|
493
|
+
try {
|
|
494
|
+
// SANDBOXED + PROPOSAL-ONLY (core hardcodes sandbox+requireSandbox+propose).
|
|
495
|
+
run = await core.advanceGoal(id, cfg, { allowCloud: parsed.allowCloud });
|
|
496
|
+
}
|
|
497
|
+
catch (err) {
|
|
498
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
499
|
+
process.stderr.write(red('error: ') + msg + '\n');
|
|
500
|
+
return 1;
|
|
501
|
+
}
|
|
502
|
+
// Re-read the goal to surface the linked PENDING proposal id.
|
|
503
|
+
const after = core.loadGoal(id);
|
|
504
|
+
const advanced = after?.milestones.find((m) => m.swarmId === run.id);
|
|
505
|
+
const proposalId = advanced?.proposalId ?? null;
|
|
506
|
+
if (parsed.json) {
|
|
507
|
+
out(JSON.stringify({ goalId: id, swarmId: run.id, status: run.status, proposalId }, null, 2));
|
|
508
|
+
return 0;
|
|
509
|
+
}
|
|
510
|
+
if (proposalId) {
|
|
511
|
+
out(green('✓ ') + bold('advanced a milestone') + gray(` (swarm ${run.id}, ${run.status})`));
|
|
512
|
+
out('');
|
|
513
|
+
out(' A ' + bold('PENDING') + ' inbox proposal was produced — nothing was applied.');
|
|
514
|
+
out(` proposal: ${cyan(proposalId)}`);
|
|
515
|
+
out('');
|
|
516
|
+
out(dim(' Review and approve it (or not) with `ashlr inbox`.'));
|
|
517
|
+
out(dim(' No real working tree was mutated, pushed, or deployed.'));
|
|
518
|
+
}
|
|
519
|
+
else {
|
|
520
|
+
out(yellow('! ') +
|
|
521
|
+
`advance ran (swarm ${run.id}, status ${run.status}) but produced no PENDING proposal.`);
|
|
522
|
+
out(dim(' The milestone is marked blocked for human attention. Inspect `ashlr swarm`.'));
|
|
523
|
+
return 1;
|
|
524
|
+
}
|
|
525
|
+
return 0;
|
|
526
|
+
}
|
|
527
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
528
|
+
case 'status': {
|
|
529
|
+
// READ-ONLY tracking dashboard.
|
|
530
|
+
const goals = core.listGoals();
|
|
531
|
+
const rolled = goals.map((g) => ({ goal: g, progress: core.progressOf(g) }));
|
|
532
|
+
if (parsed.json) {
|
|
533
|
+
out(JSON.stringify(rolled.map((r) => r.progress), null, 2));
|
|
534
|
+
return 0;
|
|
535
|
+
}
|
|
536
|
+
if (rolled.length === 0) {
|
|
537
|
+
out(gray(' No goals to track yet.'));
|
|
538
|
+
return 0;
|
|
539
|
+
}
|
|
540
|
+
out('');
|
|
541
|
+
out(bold(' Goal tracking'));
|
|
542
|
+
out('');
|
|
543
|
+
for (const { goal, progress } of rolled) {
|
|
544
|
+
const pct = Math.round(progress.fractionDone * 100);
|
|
545
|
+
out(` ${cyan(pad(goal.id, 28))} ${pad(goal.status, 10)} ${gray(`${pct}%`)}`);
|
|
546
|
+
const segs = [];
|
|
547
|
+
for (const [st, n] of Object.entries(progress.byStatus)) {
|
|
548
|
+
segs.push(`${statusGlyph(st)} ${st}:${n}`);
|
|
549
|
+
}
|
|
550
|
+
out(` ${gray(pad('', 28))} ${dim(segs.join(' '))}`);
|
|
551
|
+
if (progress.nextActionableId) {
|
|
552
|
+
out(` ${gray(pad('', 28))} ${dim('next: ' + progress.nextActionableId)}`);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
out('');
|
|
556
|
+
return 0;
|
|
557
|
+
}
|
|
558
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
559
|
+
case 'pause': {
|
|
560
|
+
const id = parsed.arg1;
|
|
561
|
+
if (!id) {
|
|
562
|
+
process.stderr.write(red('error: ') + 'pause requires a goal id.\n');
|
|
563
|
+
return 2;
|
|
564
|
+
}
|
|
565
|
+
const updated = core.pauseMilestone(id, parsed.arg2);
|
|
566
|
+
if (!updated) {
|
|
567
|
+
process.stderr.write(red('error: ') + `goal or milestone not found: ${id}${parsed.arg2 ? ` / ${parsed.arg2}` : ''}\n`);
|
|
568
|
+
return 1;
|
|
569
|
+
}
|
|
570
|
+
if (parsed.json)
|
|
571
|
+
out(JSON.stringify(updated, null, 2));
|
|
572
|
+
else
|
|
573
|
+
out(green('✓ ') + (parsed.arg2 ? `paused milestone ${parsed.arg2}` : `paused goal ${id}`));
|
|
574
|
+
return 0;
|
|
575
|
+
}
|
|
576
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
577
|
+
case 'resume': {
|
|
578
|
+
const id = parsed.arg1;
|
|
579
|
+
if (!id) {
|
|
580
|
+
process.stderr.write(red('error: ') + 'resume requires a goal id.\n');
|
|
581
|
+
return 2;
|
|
582
|
+
}
|
|
583
|
+
const updated = core.resumeMilestone(id, parsed.arg2);
|
|
584
|
+
if (!updated) {
|
|
585
|
+
process.stderr.write(red('error: ') + `goal or milestone not found: ${id}${parsed.arg2 ? ` / ${parsed.arg2}` : ''}\n`);
|
|
586
|
+
return 1;
|
|
587
|
+
}
|
|
588
|
+
if (parsed.json)
|
|
589
|
+
out(JSON.stringify(updated, null, 2));
|
|
590
|
+
else
|
|
591
|
+
out(green('✓ ') + (parsed.arg2 ? `resumed milestone ${parsed.arg2}` : `resumed goal ${id}`));
|
|
592
|
+
return 0;
|
|
593
|
+
}
|
|
594
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
595
|
+
case 'skip': {
|
|
596
|
+
const id = parsed.arg1;
|
|
597
|
+
const milestoneId = parsed.arg2;
|
|
598
|
+
if (!id || !milestoneId) {
|
|
599
|
+
process.stderr.write(red('error: ') + 'skip requires a goal id and a milestone id.\n');
|
|
600
|
+
return 2;
|
|
601
|
+
}
|
|
602
|
+
const updated = core.skipMilestone(id, milestoneId);
|
|
603
|
+
if (!updated) {
|
|
604
|
+
process.stderr.write(red('error: ') + `goal or milestone not found: ${id} / ${milestoneId}\n`);
|
|
605
|
+
return 1;
|
|
606
|
+
}
|
|
607
|
+
if (parsed.json)
|
|
608
|
+
out(JSON.stringify(updated, null, 2));
|
|
609
|
+
else
|
|
610
|
+
out(green('✓ ') + `skipped milestone ${milestoneId}`);
|
|
611
|
+
return 0;
|
|
612
|
+
}
|
|
613
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
614
|
+
case 'reorder': {
|
|
615
|
+
// STEERABLE: rewrite milestone order to the given id sequence. Pure local
|
|
616
|
+
// edit (no swarm, no outward action). Any ids omitted keep their relative
|
|
617
|
+
// order after the listed ones.
|
|
618
|
+
const id = parsed.arg1;
|
|
619
|
+
const orderedIds = parsed.positionals.slice(1);
|
|
620
|
+
if (!id || orderedIds.length === 0) {
|
|
621
|
+
process.stderr.write(red('error: ') + 'reorder requires a goal id and at least one milestone id.\n');
|
|
622
|
+
return 2;
|
|
623
|
+
}
|
|
624
|
+
const updated = core.reorderMilestones(id, orderedIds);
|
|
625
|
+
if (!updated) {
|
|
626
|
+
process.stderr.write(red('error: ') + `goal not found: ${id}\n`);
|
|
627
|
+
return 1;
|
|
628
|
+
}
|
|
629
|
+
if (parsed.json)
|
|
630
|
+
out(JSON.stringify(updated, null, 2));
|
|
631
|
+
else {
|
|
632
|
+
out(green('✓ ') + `reordered milestones for ${id}`);
|
|
633
|
+
for (const m of updated.milestones) {
|
|
634
|
+
out(` ${cyan(pad(`#${m.order}`, 4))} ${m.title}`);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
return 0;
|
|
638
|
+
}
|
|
639
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
640
|
+
case 'delete': {
|
|
641
|
+
// STEERABLE: remove a goal record entirely. Pure local FS delete under
|
|
642
|
+
// ~/.ashlr/goals — never touches a user repo, never applies a proposal.
|
|
643
|
+
const id = parsed.arg1;
|
|
644
|
+
if (!id) {
|
|
645
|
+
process.stderr.write(red('error: ') + 'delete requires a goal id.\n');
|
|
646
|
+
return 2;
|
|
647
|
+
}
|
|
648
|
+
const goal = core.loadGoal(id);
|
|
649
|
+
if (!goal) {
|
|
650
|
+
process.stderr.write(red('error: ') + `goal not found: ${id}\n`);
|
|
651
|
+
return 1;
|
|
652
|
+
}
|
|
653
|
+
core.deleteGoal(id);
|
|
654
|
+
if (parsed.json)
|
|
655
|
+
out(JSON.stringify({ deleted: id }, null, 2));
|
|
656
|
+
else
|
|
657
|
+
out(green('✓ ') + `deleted goal ${id}`);
|
|
658
|
+
return 0;
|
|
659
|
+
}
|
|
660
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
661
|
+
default: {
|
|
662
|
+
printHelp();
|
|
663
|
+
return 2;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
//# sourceMappingURL=goals.js.map
|