@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,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* spec-store.ts — M12: First-class versioned END-STATE SPEC artifacts.
|
|
3
|
+
*
|
|
4
|
+
* Specs are markdown documents with a structured sidecar JSON (SpecArtifact).
|
|
5
|
+
* Versioning is NEVER destructive: refining produces v+1, never overwrites.
|
|
6
|
+
*
|
|
7
|
+
* Storage layout:
|
|
8
|
+
* <project>/.ashlr/specs/<slug>-v<N>.md ← markdown body
|
|
9
|
+
* <project>/.ashlr/specs/<slug>-v<N>.json ← SpecArtifact sidecar
|
|
10
|
+
*
|
|
11
|
+
* When no project is given, defaults to ~/.ashlr/specs (global store).
|
|
12
|
+
*/
|
|
13
|
+
import type { SpecArtifact, AshlrConfig } from '../types.js';
|
|
14
|
+
/**
|
|
15
|
+
* Returns the absolute path to the specs directory for a given project.
|
|
16
|
+
* - When `project` is given: `<project>/.ashlr/specs`
|
|
17
|
+
* - Otherwise (global): `~/.ashlr/specs`
|
|
18
|
+
* Creates the directory on demand (mkdirSync recursive).
|
|
19
|
+
*/
|
|
20
|
+
export declare function specsDir(project?: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* List all specs in the given project (or global), returning the NEWEST
|
|
23
|
+
* version of each spec id, sorted by updatedAt descending.
|
|
24
|
+
*/
|
|
25
|
+
export declare function listSpecs(project?: string): SpecArtifact[];
|
|
26
|
+
/**
|
|
27
|
+
* Load the HIGHEST version of a spec by id.
|
|
28
|
+
* Returns `{ meta, body }` or null if not found / unreadable.
|
|
29
|
+
*
|
|
30
|
+
* Search order (highest version across all readable dirs wins):
|
|
31
|
+
* 1. ~/.ashlr/specs (global store)
|
|
32
|
+
* 2. <cwd>/.ashlr/specs (project store when run from the project dir)
|
|
33
|
+
* 3. <project>/.ashlr/specs (explicit --project hint, when given)
|
|
34
|
+
*
|
|
35
|
+
* The optional `project` hint lets `spec show`/`refine` find a project-scoped
|
|
36
|
+
* spec without having to `cd` into the project first (symmetry with new/list).
|
|
37
|
+
*/
|
|
38
|
+
export declare function loadSpec(id: string, project?: string): {
|
|
39
|
+
meta: SpecArtifact;
|
|
40
|
+
body: string;
|
|
41
|
+
} | null;
|
|
42
|
+
/**
|
|
43
|
+
* Author a new spec from a goal string.
|
|
44
|
+
*
|
|
45
|
+
* Uses the LOCAL-first model provider to draft a structured end-state spec
|
|
46
|
+
* with sections: Context / North Star / Operating Principles / Pillars /
|
|
47
|
+
* Roadmap / Verification. Persists `<slug>-v1.md` + sidecar `<slug>-v1.json`.
|
|
48
|
+
*
|
|
49
|
+
* The model call is BOUNDED (small output budget). Never throws.
|
|
50
|
+
*/
|
|
51
|
+
export declare function authorSpec(goal: string, cfg: AshlrConfig, opts?: {
|
|
52
|
+
project?: string;
|
|
53
|
+
allowCloud?: boolean;
|
|
54
|
+
}): Promise<SpecArtifact>;
|
|
55
|
+
/**
|
|
56
|
+
* Refine an existing spec by id: reads the current highest version, calls the
|
|
57
|
+
* model with the refinement note, writes v+1 (NEVER destructive — never
|
|
58
|
+
* overwrites prior versions).
|
|
59
|
+
*
|
|
60
|
+
* Returns the new SpecArtifact (v+1). Never throws.
|
|
61
|
+
*/
|
|
62
|
+
export declare function refineSpec(id: string, note: string, cfg: AshlrConfig, project?: string): Promise<SpecArtifact>;
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* spec-store.ts — M12: First-class versioned END-STATE SPEC artifacts.
|
|
3
|
+
*
|
|
4
|
+
* Specs are markdown documents with a structured sidecar JSON (SpecArtifact).
|
|
5
|
+
* Versioning is NEVER destructive: refining produces v+1, never overwrites.
|
|
6
|
+
*
|
|
7
|
+
* Storage layout:
|
|
8
|
+
* <project>/.ashlr/specs/<slug>-v<N>.md ← markdown body
|
|
9
|
+
* <project>/.ashlr/specs/<slug>-v<N>.json ← SpecArtifact sidecar
|
|
10
|
+
*
|
|
11
|
+
* When no project is given, defaults to ~/.ashlr/specs (global store).
|
|
12
|
+
*/
|
|
13
|
+
import * as fs from 'node:fs';
|
|
14
|
+
import * as os from 'node:os';
|
|
15
|
+
import * as path from 'node:path';
|
|
16
|
+
import * as crypto from 'node:crypto';
|
|
17
|
+
import { getActiveClient } from '../run/provider-client.js';
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Constants
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
/** Char cap for spec body injected into a refinement prompt. */
|
|
22
|
+
const REFINE_BODY_CAP = 8_000;
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Directory helpers
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
/**
|
|
27
|
+
* Returns the absolute path to the specs directory for a given project.
|
|
28
|
+
* - When `project` is given: `<project>/.ashlr/specs`
|
|
29
|
+
* - Otherwise (global): `~/.ashlr/specs`
|
|
30
|
+
* Creates the directory on demand (mkdirSync recursive).
|
|
31
|
+
*/
|
|
32
|
+
export function specsDir(project) {
|
|
33
|
+
const dir = project
|
|
34
|
+
? path.join(project, '.ashlr', 'specs')
|
|
35
|
+
: path.join(os.homedir(), '.ashlr', 'specs');
|
|
36
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
37
|
+
return dir;
|
|
38
|
+
}
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// ID / slug helpers
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
/**
|
|
43
|
+
* Derive a stable slug from a goal string:
|
|
44
|
+
* lowercase, words joined with hyphens, max 48 chars, alphanumeric + hyphens only.
|
|
45
|
+
*/
|
|
46
|
+
function slugify(goal) {
|
|
47
|
+
return goal
|
|
48
|
+
.toLowerCase()
|
|
49
|
+
.replace(/[^a-z0-9\s-]/g, '')
|
|
50
|
+
.trim()
|
|
51
|
+
.replace(/\s+/g, '-')
|
|
52
|
+
.replace(/-+/g, '-')
|
|
53
|
+
.slice(0, 48)
|
|
54
|
+
.replace(/-$/, '');
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Generate a stable spec id from a goal. The id is the slug + a short hash
|
|
58
|
+
* so two similar goals don't silently collide.
|
|
59
|
+
*/
|
|
60
|
+
function generateSpecId(goal) {
|
|
61
|
+
const slug = slugify(goal);
|
|
62
|
+
const hash = crypto
|
|
63
|
+
.createHash('sha256')
|
|
64
|
+
.update(goal)
|
|
65
|
+
.digest('hex')
|
|
66
|
+
.slice(0, 6);
|
|
67
|
+
return `${slug}-${hash}`;
|
|
68
|
+
}
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
// File-path helpers
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
function mdPath(dir, id, version) {
|
|
73
|
+
return path.join(dir, `${id}-v${version}.md`);
|
|
74
|
+
}
|
|
75
|
+
function jsonPath(dir, id, version) {
|
|
76
|
+
return path.join(dir, `${id}-v${version}.json`);
|
|
77
|
+
}
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// Persistence helpers
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
/** Write sidecar JSON atomically (write-then-rename). */
|
|
82
|
+
function saveMeta(dir, meta) {
|
|
83
|
+
const target = jsonPath(dir, meta.id, meta.version);
|
|
84
|
+
const tmp = `${target}.tmp.${process.pid}`;
|
|
85
|
+
fs.writeFileSync(tmp, JSON.stringify(meta, null, 2), 'utf8');
|
|
86
|
+
fs.renameSync(tmp, target);
|
|
87
|
+
}
|
|
88
|
+
/** Write markdown body atomically. */
|
|
89
|
+
function saveBody(filePath, body) {
|
|
90
|
+
const tmp = `${filePath}.tmp.${process.pid}`;
|
|
91
|
+
fs.writeFileSync(tmp, body, 'utf8');
|
|
92
|
+
fs.renameSync(tmp, filePath);
|
|
93
|
+
}
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
// Spec listing / loading
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
/**
|
|
98
|
+
* List all specs in the given project (or global), returning the NEWEST
|
|
99
|
+
* version of each spec id, sorted by updatedAt descending.
|
|
100
|
+
*/
|
|
101
|
+
export function listSpecs(project) {
|
|
102
|
+
const dir = specsDir(project);
|
|
103
|
+
let entries;
|
|
104
|
+
try {
|
|
105
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
110
|
+
// Collect all .json sidecars → parse → keep highest version per id
|
|
111
|
+
const byId = new Map();
|
|
112
|
+
for (const entry of entries) {
|
|
113
|
+
if (!entry.isFile() || !entry.name.endsWith('.json'))
|
|
114
|
+
continue;
|
|
115
|
+
const fullPath = path.join(dir, entry.name);
|
|
116
|
+
try {
|
|
117
|
+
const raw = fs.readFileSync(fullPath, 'utf8');
|
|
118
|
+
const meta = JSON.parse(raw);
|
|
119
|
+
if (!meta.id || typeof meta.version !== 'number')
|
|
120
|
+
continue;
|
|
121
|
+
const existing = byId.get(meta.id);
|
|
122
|
+
if (!existing || meta.version > existing.version) {
|
|
123
|
+
byId.set(meta.id, meta);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// Corrupt or partial file — skip silently
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return Array.from(byId.values()).sort((a, b) => (b.updatedAt > a.updatedAt ? 1 : -1));
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Load the HIGHEST version of a spec by id.
|
|
134
|
+
* Returns `{ meta, body }` or null if not found / unreadable.
|
|
135
|
+
*
|
|
136
|
+
* Search order (highest version across all readable dirs wins):
|
|
137
|
+
* 1. ~/.ashlr/specs (global store)
|
|
138
|
+
* 2. <cwd>/.ashlr/specs (project store when run from the project dir)
|
|
139
|
+
* 3. <project>/.ashlr/specs (explicit --project hint, when given)
|
|
140
|
+
*
|
|
141
|
+
* The optional `project` hint lets `spec show`/`refine` find a project-scoped
|
|
142
|
+
* spec without having to `cd` into the project first (symmetry with new/list).
|
|
143
|
+
*/
|
|
144
|
+
export function loadSpec(id, project) {
|
|
145
|
+
// Try global, cwd, and (when given) the explicit project dir.
|
|
146
|
+
const candidates = [
|
|
147
|
+
path.join(os.homedir(), '.ashlr', 'specs'),
|
|
148
|
+
path.join(process.cwd(), '.ashlr', 'specs'),
|
|
149
|
+
];
|
|
150
|
+
if (project) {
|
|
151
|
+
const projDir = path.join(project, '.ashlr', 'specs');
|
|
152
|
+
if (!candidates.includes(projDir))
|
|
153
|
+
candidates.push(projDir);
|
|
154
|
+
}
|
|
155
|
+
let best = null;
|
|
156
|
+
let bestDir = '';
|
|
157
|
+
for (const dir of candidates) {
|
|
158
|
+
if (!fs.existsSync(dir))
|
|
159
|
+
continue;
|
|
160
|
+
let entries;
|
|
161
|
+
try {
|
|
162
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
for (const entry of entries) {
|
|
168
|
+
if (!entry.isFile() || !entry.name.endsWith('.json'))
|
|
169
|
+
continue;
|
|
170
|
+
if (!entry.name.startsWith(id + '-v'))
|
|
171
|
+
continue;
|
|
172
|
+
const fullPath = path.join(dir, entry.name);
|
|
173
|
+
try {
|
|
174
|
+
const raw = fs.readFileSync(fullPath, 'utf8');
|
|
175
|
+
const meta = JSON.parse(raw);
|
|
176
|
+
if (meta.id !== id)
|
|
177
|
+
continue;
|
|
178
|
+
if (!best || meta.version > best.version) {
|
|
179
|
+
best = meta;
|
|
180
|
+
bestDir = dir;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
catch {
|
|
184
|
+
// skip
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (!best)
|
|
189
|
+
return null;
|
|
190
|
+
const bodyFile = mdPath(bestDir, best.id, best.version);
|
|
191
|
+
let body = '';
|
|
192
|
+
try {
|
|
193
|
+
body = fs.readFileSync(bodyFile, 'utf8');
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
return { meta: best, body };
|
|
199
|
+
}
|
|
200
|
+
// ---------------------------------------------------------------------------
|
|
201
|
+
// Model helpers
|
|
202
|
+
// ---------------------------------------------------------------------------
|
|
203
|
+
/** The structured system prompt for spec authoring. */
|
|
204
|
+
const SPEC_SYSTEM_PROMPT = `You are an expert software architect and product strategist.
|
|
205
|
+
Your task is to draft a structured END-STATE SPEC — a concrete, ambitious, grounded document
|
|
206
|
+
describing the DESIRED END STATE of a software project or initiative.
|
|
207
|
+
|
|
208
|
+
The spec MUST have exactly these sections (use level-2 markdown headings):
|
|
209
|
+
|
|
210
|
+
## Context
|
|
211
|
+
Who is building this, for whom, what problem it solves, current state.
|
|
212
|
+
|
|
213
|
+
## North Star
|
|
214
|
+
A single crisp sentence capturing the ultimate outcome. What does "done" look like?
|
|
215
|
+
|
|
216
|
+
## Operating Principles
|
|
217
|
+
3–6 guiding constraints and values (e.g. local-first, no-runtime-deps, safety-first).
|
|
218
|
+
|
|
219
|
+
## Pillars
|
|
220
|
+
3–5 major capability pillars / feature clusters with brief descriptions.
|
|
221
|
+
|
|
222
|
+
## Roadmap
|
|
223
|
+
Phases (Phase 1, Phase 2, …). Each phase: name, goal, 2–5 key deliverables.
|
|
224
|
+
Keep concrete and achievable, not aspirational fluff.
|
|
225
|
+
|
|
226
|
+
## Verification
|
|
227
|
+
How will we know the spec is satisfied? 3–6 measurable acceptance criteria.
|
|
228
|
+
|
|
229
|
+
RULES:
|
|
230
|
+
- Be concrete, specific, and grounded. Avoid vague adjectives.
|
|
231
|
+
- No marketing copy. No fluff. Prefer bullet points over prose.
|
|
232
|
+
- Keep total length 600–1000 words. Quality over quantity.
|
|
233
|
+
- Do NOT include section numbers or table of contents.
|
|
234
|
+
- Return ONLY the markdown spec body — no preamble, no postamble.`;
|
|
235
|
+
/** Build the user prompt for authoring a new spec. */
|
|
236
|
+
function buildAuthorPrompt(goal) {
|
|
237
|
+
return `Draft an end-state spec for the following goal:\n\n> ${goal}\n\nReturn only the structured markdown spec body.`;
|
|
238
|
+
}
|
|
239
|
+
/** Build the user prompt for refining an existing spec. */
|
|
240
|
+
function buildRefinePrompt(goal, version, body, note) {
|
|
241
|
+
const truncatedBody = body.length > REFINE_BODY_CAP ? body.slice(0, REFINE_BODY_CAP) + '\n\n[...truncated]' : body;
|
|
242
|
+
return (`You are refining an existing end-state spec (currently v${version}) for the goal:\n\n` +
|
|
243
|
+
`> ${goal}\n\n` +
|
|
244
|
+
`--- CURRENT SPEC ---\n${truncatedBody}\n--- END CURRENT SPEC ---\n\n` +
|
|
245
|
+
`Refinement note / change request:\n> ${note}\n\n` +
|
|
246
|
+
`Produce an improved v${version + 1} of the spec, incorporating the note. ` +
|
|
247
|
+
`Preserve the same six-section structure. Return only the updated markdown spec body.`);
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Call the LOCAL-first model to produce a spec body string.
|
|
251
|
+
* Bounded to SPEC_MAX_TOKENS output. Never throws — returns a fallback stub on error.
|
|
252
|
+
*/
|
|
253
|
+
async function callModel(cfg, systemPrompt, userPrompt, allowCloud) {
|
|
254
|
+
try {
|
|
255
|
+
const client = await getActiveClient(cfg, { allowCloud });
|
|
256
|
+
const result = await client.chat([
|
|
257
|
+
{ role: 'system', content: systemPrompt },
|
|
258
|
+
{ role: 'user', content: userPrompt },
|
|
259
|
+
]);
|
|
260
|
+
return {
|
|
261
|
+
content: result.content.trim(),
|
|
262
|
+
usage: result.usage,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
catch (err) {
|
|
266
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
267
|
+
// Return a stub spec so spec-store never throws to the caller
|
|
268
|
+
const stub = buildStubSpec(userPrompt);
|
|
269
|
+
process.stderr.write(`[spec-store] model call failed (${msg}); returning stub spec\n`);
|
|
270
|
+
return { content: stub, usage: { tokensIn: 0, tokensOut: 0 } };
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
/** Minimal stub spec returned when no model is available. */
|
|
274
|
+
function buildStubSpec(hint) {
|
|
275
|
+
return `## Context\n_No model available — fill in context manually._\n\n` +
|
|
276
|
+
`## North Star\n_Define the desired end state here._\n\n` +
|
|
277
|
+
`## Operating Principles\n- Local-first\n- No secrets in logs\n\n` +
|
|
278
|
+
`## Pillars\n- _Pillar 1_\n- _Pillar 2_\n\n` +
|
|
279
|
+
`## Roadmap\n### Phase 1\n- _Deliverable 1_\n\n` +
|
|
280
|
+
`## Verification\n- _Acceptance criterion 1_\n\n` +
|
|
281
|
+
`<!-- hint: ${hint.slice(0, 80)} -->`;
|
|
282
|
+
}
|
|
283
|
+
// ---------------------------------------------------------------------------
|
|
284
|
+
// Public API
|
|
285
|
+
// ---------------------------------------------------------------------------
|
|
286
|
+
/**
|
|
287
|
+
* Author a new spec from a goal string.
|
|
288
|
+
*
|
|
289
|
+
* Uses the LOCAL-first model provider to draft a structured end-state spec
|
|
290
|
+
* with sections: Context / North Star / Operating Principles / Pillars /
|
|
291
|
+
* Roadmap / Verification. Persists `<slug>-v1.md` + sidecar `<slug>-v1.json`.
|
|
292
|
+
*
|
|
293
|
+
* The model call is BOUNDED (small output budget). Never throws.
|
|
294
|
+
*/
|
|
295
|
+
export async function authorSpec(goal, cfg, opts) {
|
|
296
|
+
const project = opts?.project ?? null;
|
|
297
|
+
const dir = specsDir(project ?? undefined);
|
|
298
|
+
const id = generateSpecId(goal);
|
|
299
|
+
const version = 1;
|
|
300
|
+
const now = new Date().toISOString();
|
|
301
|
+
// Check if v1 already exists for this id — if so, return it (idempotent)
|
|
302
|
+
const existing = loadSpec(id);
|
|
303
|
+
if (existing && existing.meta.version === 1) {
|
|
304
|
+
return existing.meta;
|
|
305
|
+
}
|
|
306
|
+
// Cloud allowance: when a caller EXPLICITLY passes opts.allowCloud, that
|
|
307
|
+
// decision OVERRIDES the chain-derived heuristic — so a caller (e.g. M28
|
|
308
|
+
// `goals plan` without --allow-cloud) can force local-only even when a cloud
|
|
309
|
+
// provider (anthropic) sits in the default providerChain. Only fall back to
|
|
310
|
+
// the chain heuristic when the caller did not express a preference.
|
|
311
|
+
const allowCloud = opts?.allowCloud ??
|
|
312
|
+
(cfg.models?.providerChain ?? []).some((p) => !['ollama', 'lmstudio', 'builtin'].includes(p));
|
|
313
|
+
const { content } = await callModel(cfg, SPEC_SYSTEM_PROMPT, buildAuthorPrompt(goal), allowCloud);
|
|
314
|
+
const bodyPath = mdPath(dir, id, version);
|
|
315
|
+
const meta = {
|
|
316
|
+
id,
|
|
317
|
+
goal,
|
|
318
|
+
version,
|
|
319
|
+
project,
|
|
320
|
+
path: bodyPath,
|
|
321
|
+
status: 'draft',
|
|
322
|
+
createdAt: now,
|
|
323
|
+
updatedAt: now,
|
|
324
|
+
};
|
|
325
|
+
saveBody(bodyPath, content);
|
|
326
|
+
saveMeta(dir, meta);
|
|
327
|
+
return meta;
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Refine an existing spec by id: reads the current highest version, calls the
|
|
331
|
+
* model with the refinement note, writes v+1 (NEVER destructive — never
|
|
332
|
+
* overwrites prior versions).
|
|
333
|
+
*
|
|
334
|
+
* Returns the new SpecArtifact (v+1). Never throws.
|
|
335
|
+
*/
|
|
336
|
+
export async function refineSpec(id, note, cfg, project) {
|
|
337
|
+
const existing = loadSpec(id, project);
|
|
338
|
+
if (!existing) {
|
|
339
|
+
throw new Error(`spec-store: spec not found: ${id}`);
|
|
340
|
+
}
|
|
341
|
+
const { meta: currentMeta, body: currentBody } = existing;
|
|
342
|
+
const nextVersion = currentMeta.version + 1;
|
|
343
|
+
const now = new Date().toISOString();
|
|
344
|
+
const dir = specsDir(currentMeta.project ?? undefined);
|
|
345
|
+
// Determine cloud allowance from config
|
|
346
|
+
const allowCloud = (cfg.models?.providerChain ?? []).some((p) => !['ollama', 'lmstudio', 'builtin'].includes(p));
|
|
347
|
+
const { content } = await callModel(cfg, SPEC_SYSTEM_PROMPT, buildRefinePrompt(currentMeta.goal, currentMeta.version, currentBody, note), allowCloud);
|
|
348
|
+
const bodyPath = mdPath(dir, id, nextVersion);
|
|
349
|
+
const newMeta = {
|
|
350
|
+
...currentMeta,
|
|
351
|
+
version: nextVersion,
|
|
352
|
+
path: bodyPath,
|
|
353
|
+
updatedAt: now,
|
|
354
|
+
};
|
|
355
|
+
saveBody(bodyPath, content);
|
|
356
|
+
saveMeta(dir, newMeta);
|
|
357
|
+
return newMeta;
|
|
358
|
+
}
|
|
359
|
+
//# sourceMappingURL=spec-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec-store.js","sourceRoot":"","sources":["../../../src/core/spec/spec-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AAGtC,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE5D,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E,gEAAgE;AAChE,MAAM,eAAe,GAAG,KAAK,CAAC;AAE9B,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAgB;IACvC,MAAM,GAAG,GAAG,OAAO;QACjB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC;QACvC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC/C,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,OAAO,GAAG,CAAC;AACb,CAAC;AAED,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E;;;GAGG;AACH,SAAS,OAAO,CAAC,IAAY;IAC3B,OAAO,IAAI;SACR,WAAW,EAAE;SACb,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC;SAC5B,IAAI,EAAE;SACN,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;SACZ,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AACvB,CAAC;AAED;;;GAGG;AACH,SAAS,cAAc,CAAC,IAAY;IAClC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,MAAM,IAAI,GAAG,MAAM;SAChB,UAAU,CAAC,QAAQ,CAAC;SACpB,MAAM,CAAC,IAAI,CAAC;SACZ,MAAM,CAAC,KAAK,CAAC;SACb,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACf,OAAO,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E,SAAS,MAAM,CAAC,GAAW,EAAE,EAAU,EAAE,OAAe;IACtD,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,OAAO,KAAK,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW,EAAE,EAAU,EAAE,OAAe;IACxD,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,OAAO,OAAO,CAAC,CAAC;AAClD,CAAC;AAED,8EAA8E;AAC9E,sBAAsB;AACtB,8EAA8E;AAE9E,yDAAyD;AACzD,SAAS,QAAQ,CAAC,GAAW,EAAE,IAAkB;IAC/C,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACpD,MAAM,GAAG,GAAG,GAAG,MAAM,QAAQ,OAAO,CAAC,GAAG,EAAE,CAAC;IAC3C,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAC7D,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AAC7B,CAAC;AAED,sCAAsC;AACtC,SAAS,QAAQ,CAAC,QAAgB,EAAE,IAAY;IAC9C,MAAM,GAAG,GAAG,GAAG,QAAQ,QAAQ,OAAO,CAAC,GAAG,EAAE,CAAC;IAC7C,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IACpC,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAC/B,CAAC;AAED,8EAA8E;AAC9E,yBAAyB;AACzB,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,OAAgB;IACxC,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC9B,IAAI,OAAoB,CAAC;IACzB,IAAI,CAAC;QACH,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,mEAAmE;IACnE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAwB,CAAC;IAC7C,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,SAAS;QAC/D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAiB,CAAC;YAC7C,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ;gBAAE,SAAS;YAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACnC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;gBACjD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YAC1B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,0CAA0C;QAC5C,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CACnC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAC/C,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,QAAQ,CACtB,EAAU,EACV,OAAgB;IAEhB,8DAA8D;IAC9D,MAAM,UAAU,GAAa;QAC3B,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC;QAC1C,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC;KAC5C,CAAC;IACF,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QACtD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC9D,CAAC;IAED,IAAI,IAAI,GAAwB,IAAI,CAAC;IACrC,IAAI,OAAO,GAAG,EAAE,CAAC;IAEjB,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAClC,IAAI,OAAoB,CAAC;QACzB,IAAI,CAAC;YACH,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAAE,SAAS;YAC/D,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,GAAG,IAAI,CAAC;gBAAE,SAAS;YAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAC5C,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;gBAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAiB,CAAC;gBAC7C,IAAI,IAAI,CAAC,EAAE,KAAK,EAAE;oBAAE,SAAS;gBAC7B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;oBACzC,IAAI,GAAG,IAAI,CAAC;oBACZ,OAAO,GAAG,GAAG,CAAC;gBAChB,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO;YACT,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvB,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACxD,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,IAAI,CAAC;QACH,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AAC9B,CAAC;AAED,8EAA8E;AAC9E,gBAAgB;AAChB,8EAA8E;AAE9E,uDAAuD;AACvD,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kEA8BuC,CAAC;AAEnE,sDAAsD;AACtD,SAAS,iBAAiB,CAAC,IAAY;IACrC,OAAO,wDAAwD,IAAI,oDAAoD,CAAC;AAC1H,CAAC;AAED,2DAA2D;AAC3D,SAAS,iBAAiB,CACxB,IAAY,EACZ,OAAe,EACf,IAAY,EACZ,IAAY;IAEZ,MAAM,aAAa,GACjB,IAAI,CAAC,MAAM,GAAG,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC,GAAG,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/F,OAAO,CACL,2DAA2D,OAAO,qBAAqB;QACvF,KAAK,IAAI,MAAM;QACf,yBAAyB,aAAa,gCAAgC;QACtE,wCAAwC,IAAI,MAAM;QAClD,wBAAwB,OAAO,GAAG,CAAC,wCAAwC;QAC3E,sFAAsF,CACvF,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,SAAS,CACtB,GAAgB,EAChB,YAAoB,EACpB,UAAkB,EAClB,UAAmB;IAEnB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;QAC1D,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAC9B;YACE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE;YACzC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE;SACtC,CACF,CAAC;QACF,OAAO;YACL,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE;YAC9B,KAAK,EAAE,MAAM,CAAC,KAAK;SACpB,CAAC;IACJ,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,8DAA8D;QAC9D,MAAM,IAAI,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;QACvC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mCAAmC,GAAG,0BAA0B,CAAC,CAAC;QACvF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;IACjE,CAAC;AACH,CAAC;AAED,6DAA6D;AAC7D,SAAS,aAAa,CAAC,IAAY;IACjC,OAAO,kEAAkE;QACvE,yDAAyD;QACzD,kEAAkE;QAClE,4CAA4C;QAC5C,gDAAgD;QAChD,iDAAiD;QACjD,cAAc,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC;AAC1C,CAAC;AAED,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,IAAY,EACZ,GAAgB,EAChB,IAAiD;IAEjD,MAAM,OAAO,GAAG,IAAI,EAAE,OAAO,IAAI,IAAI,CAAC;IACtC,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,IAAI,SAAS,CAAC,CAAC;IAE3C,MAAM,EAAE,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,OAAO,GAAG,CAAC,CAAC;IAClB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAErC,yEAAyE;IACzE,MAAM,QAAQ,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC9B,IAAI,QAAQ,IAAI,QAAQ,CAAC,IAAI,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;QAC5C,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED,yEAAyE;IACzE,yEAAyE;IACzE,6EAA6E;IAC7E,4EAA4E;IAC5E,oEAAoE;IACpE,MAAM,UAAU,GACd,IAAI,EAAE,UAAU;QAChB,CAAC,GAAG,CAAC,MAAM,EAAE,aAAa,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAExG,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,SAAS,CACjC,GAAG,EACH,kBAAkB,EAClB,iBAAiB,CAAC,IAAI,CAAC,EACvB,UAAU,CACX,CAAC;IAEF,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;IAE1C,MAAM,IAAI,GAAiB;QACzB,EAAE;QACF,IAAI;QACJ,OAAO;QACP,OAAO;QACP,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,OAAO;QACf,SAAS,EAAE,GAAG;QACd,SAAS,EAAE,GAAG;KACf,CAAC;IAEF,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC5B,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAEpB,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,EAAU,EACV,IAAY,EACZ,GAAgB,EAChB,OAAgB;IAEhB,MAAM,QAAQ,GAAG,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IACvC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,+BAA+B,EAAE,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,QAAQ,CAAC;IAC1D,MAAM,WAAW,GAAG,WAAW,CAAC,OAAO,GAAG,CAAC,CAAC;IAC5C,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAErC,MAAM,GAAG,GAAG,QAAQ,CAAC,WAAW,CAAC,OAAO,IAAI,SAAS,CAAC,CAAC;IAEvD,wCAAwC;IACxC,MAAM,UAAU,GACd,CAAC,GAAG,CAAC,MAAM,EAAE,aAAa,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAExG,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,SAAS,CACjC,GAAG,EACH,kBAAkB,EAClB,iBAAiB,CAAC,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,EAC3E,UAAU,CACX,CAAC;IAEF,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,EAAE,EAAE,EAAE,WAAW,CAAC,CAAC;IAE9C,MAAM,OAAO,GAAiB;QAC5B,GAAG,WAAW;QACd,OAAO,EAAE,WAAW;QACpB,IAAI,EAAE,QAAQ;QACd,SAAS,EAAE,GAAG;KACf,CAAC;IAEF,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC5B,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAEvB,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* core/swarm/gate.ts — M17 escalation gate.
|
|
3
|
+
*
|
|
4
|
+
* Two pure, deterministic, never-throwing exports:
|
|
5
|
+
* riskScan — heuristic detection of destructive/outward ops in text
|
|
6
|
+
* shouldEscalate — priority-ordered escalation kind selector
|
|
7
|
+
*
|
|
8
|
+
* Neither function has side-effects; the caller is responsible for persisting
|
|
9
|
+
* EscalationEvent records, setting status 'needs-approval', and stopping the
|
|
10
|
+
* swarm. No auto-approval path exists here.
|
|
11
|
+
*/
|
|
12
|
+
import type { EscalationReasonKind } from '../types.js';
|
|
13
|
+
/**
|
|
14
|
+
* Scan `text` for destructive or outward-facing operation patterns.
|
|
15
|
+
*
|
|
16
|
+
* Returns `{ risky: true, reason }` on the first match, or
|
|
17
|
+
* `{ risky: false, reason: '' }` if no pattern matches.
|
|
18
|
+
*
|
|
19
|
+
* Pure, case-insensitive, never throws.
|
|
20
|
+
*/
|
|
21
|
+
export declare function riskScan(text: string): {
|
|
22
|
+
risky: boolean;
|
|
23
|
+
reason: string;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Determine whether an escalation is needed, and which kind.
|
|
27
|
+
*
|
|
28
|
+
* Priority order (highest → lowest):
|
|
29
|
+
* tamper → verify-failed → over-budget → risk → low-confidence
|
|
30
|
+
*
|
|
31
|
+
* Returns the first applicable `EscalationReasonKind`, or `null` if none apply.
|
|
32
|
+
*
|
|
33
|
+
* PURE — no side-effects. The caller must:
|
|
34
|
+
* 1. Persist the EscalationEvent
|
|
35
|
+
* 2. Set swarm status to 'needs-approval'
|
|
36
|
+
* 3. STOP the swarm
|
|
37
|
+
* Never auto-approves; never throws.
|
|
38
|
+
*/
|
|
39
|
+
export declare function shouldEscalate(ctx: {
|
|
40
|
+
verifyFailed?: boolean;
|
|
41
|
+
overBudget?: boolean;
|
|
42
|
+
tamper?: boolean;
|
|
43
|
+
risk?: boolean;
|
|
44
|
+
lowConfidence?: boolean;
|
|
45
|
+
}): EscalationReasonKind | null;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* core/swarm/gate.ts — M17 escalation gate.
|
|
3
|
+
*
|
|
4
|
+
* Two pure, deterministic, never-throwing exports:
|
|
5
|
+
* riskScan — heuristic detection of destructive/outward ops in text
|
|
6
|
+
* shouldEscalate — priority-ordered escalation kind selector
|
|
7
|
+
*
|
|
8
|
+
* Neither function has side-effects; the caller is responsible for persisting
|
|
9
|
+
* EscalationEvent records, setting status 'needs-approval', and stopping the
|
|
10
|
+
* swarm. No auto-approval path exists here.
|
|
11
|
+
*/
|
|
12
|
+
const RISK_PATTERNS = [
|
|
13
|
+
// Filesystem destruction
|
|
14
|
+
{ re: /rm\s+-[a-z]*r[a-z]*f|rm\s+-[a-z]*f[a-z]*r/i, reason: 'rm -rf (recursive force delete) detected' },
|
|
15
|
+
{ re: /\brm\b.*--no-preserve-root/i, reason: 'rm --no-preserve-root detected' },
|
|
16
|
+
// Git destructive / outward ops
|
|
17
|
+
{ re: /git\s+push\s+.*--force(?:-with-lease)?(?:\s|$)/i, reason: 'git push --force detected' },
|
|
18
|
+
{ re: /git\s+push\s+.*-f(?:\s|$)/i, reason: 'git push -f detected' },
|
|
19
|
+
{ re: /force.?push/i, reason: 'force-push pattern detected' },
|
|
20
|
+
{ re: /git\s+reset\s+--hard/i, reason: 'git reset --hard detected' },
|
|
21
|
+
{ re: /git\s+clean\s+.*-[a-z]*f/i, reason: 'git clean -f detected' },
|
|
22
|
+
// Deploy / release ops
|
|
23
|
+
// Deploy/release intent. Tightened to match an ACTUAL deploy ACTION rather
|
|
24
|
+
// than the bare noun, so benign goal text ("Implement a deployment pipeline
|
|
25
|
+
// module", "Add deployment docs", "Create a deploy script that prints
|
|
26
|
+
// instructions") does NOT escalate. We require one of:
|
|
27
|
+
// • "deploy to <env>" — e.g. "deploy to production"
|
|
28
|
+
// • a deploy CLI token — vercel/netlify/fly/wrangler/heroku/kubectl
|
|
29
|
+
// + deploy/apply/publish, in either order
|
|
30
|
+
// • "git push" (covered by the force-push patterns above; bare push below)
|
|
31
|
+
// The previous bare-noun pattern over-fired on legitimate work (verified:
|
|
32
|
+
// "deployment pipeline configuration module" flagged), which — combined with
|
|
33
|
+
// the goal-risk approve flow — could strand benign tasks. False positives on
|
|
34
|
+
// softer noun mentions are now left to explicit deploy-action phrasing.
|
|
35
|
+
{ re: /\bdeploy(?:s|ed|ing)?\s+to\s+\w/i, reason: 'deploy to <target> operation detected' },
|
|
36
|
+
{ re: /\b(?:vercel|netlify|fly|flyctl|wrangler|heroku|kubectl|serverless|sst)\b[^\n]{0,40}\b(?:deploy|apply|publish|push|release)\b/i, reason: 'deploy CLI command detected' },
|
|
37
|
+
{ re: /\b(?:deploy|publish|ship|release)\b[^\n]{0,30}\b(?:to\s+)?(?:prod|production|staging|live)\b/i, reason: 'deploy/release to environment detected' },
|
|
38
|
+
{ re: /\bvercel\b.*--prod/i, reason: 'vercel --prod deployment detected' },
|
|
39
|
+
{ re: /\bnpm\s+publish\b/i, reason: 'npm publish detected' },
|
|
40
|
+
// SQL destructive ops
|
|
41
|
+
{ re: /\bDROP\s+(?:TABLE|DATABASE|SCHEMA|INDEX|VIEW)\b/i, reason: 'SQL DROP statement detected' },
|
|
42
|
+
{ re: /\bTRUNCATE\s+TABLE\b/i, reason: 'SQL TRUNCATE TABLE detected' },
|
|
43
|
+
{ re: /\bDELETE\s+FROM\b.*(?:WHERE\s+1|WHERE\s+true|;\s*$)/i, reason: 'potentially unbounded SQL DELETE detected' },
|
|
44
|
+
// Shell pipe executions (curl/wget | sh/bash)
|
|
45
|
+
{ re: /(?:curl|wget)\b.*\|\s*(?:ba)?sh\b/i, reason: 'remote script execution (curl|sh) detected' },
|
|
46
|
+
{ re: /\beval\s*\$\(/i, reason: 'eval $(...) shell injection pattern detected' },
|
|
47
|
+
// Dangerous permissions
|
|
48
|
+
{ re: /\bchmod\s+(?:a\+[rwx]*|[0-7]*7[0-7][0-7])\b/i, reason: 'chmod 777 or world-writable permission detected' },
|
|
49
|
+
// Secret / credential exfiltration patterns
|
|
50
|
+
{ re: /\bcurl\b.*(?:Authorization|Bearer|api.?key|secret|token|password|passwd|credential)/i, reason: 'potential credential exfiltration via curl detected' },
|
|
51
|
+
{ re: /\bwget\b.*(?:Authorization|Bearer|api.?key|secret|token|password|passwd|credential)/i, reason: 'potential credential exfiltration via wget detected' },
|
|
52
|
+
{ re: /(?:export|echo|print)\s+.*(?:SECRET|API_KEY|PASSWORD|TOKEN|PRIVATE_KEY)/i, reason: 'potential secret variable exposure detected' },
|
|
53
|
+
// Well-known credential identifiers paired with an EXPOSURE/EXFIL verb. The
|
|
54
|
+
// prior pattern flagged the bare identifier regardless of context, which
|
|
55
|
+
// over-fired on benign goals (verified: "Build a tokenizer for the API_KEY
|
|
56
|
+
// header field" flagged). We now require a read/print/send/leak-style verb
|
|
57
|
+
// near the identifier so handling-by-name is a signal but mere mention is not.
|
|
58
|
+
// (Direct exposure via export/echo/print is also covered by the pattern above,
|
|
59
|
+
// and exfil via curl/wget by the patterns above that.)
|
|
60
|
+
{ re: /\b(?:print|echo|log|dump|leak|expose|reveal|send|post|upload|exfil(?:trate)?|cat|read|copy|email|curl|wget|fetch)\b[^\n]{0,40}\b(?:[A-Z][A-Z0-9]*_)*(?:API_KEY|SECRET_ACCESS_KEY|ACCESS_KEY_ID|SECRET_KEY|PRIVATE_KEY|AUTH_TOKEN|ACCESS_TOKEN)\b/i, reason: 'potential credential identifier exposure detected' },
|
|
61
|
+
{ re: /\b(?:[A-Z][A-Z0-9]*_)*(?:API_KEY|SECRET_ACCESS_KEY|ACCESS_KEY_ID|SECRET_KEY|PRIVATE_KEY|AUTH_TOKEN|ACCESS_TOKEN)\b[^\n]{0,30}\b(?:to\s+)?(?:stdout|console|file|disk|remote|endpoint|url|http)\b/i, reason: 'potential credential identifier exposure detected' },
|
|
62
|
+
{ re: /\bcat\b.*(?:\.env|id_rsa|id_ed25519|\.pem|\.key)\b/i, reason: 'potential secret file read detected' },
|
|
63
|
+
{ re: /\bcp\b.*(?:id_rsa|id_ed25519|\.pem|\.key)\b/i, reason: 'potential private key copy detected' },
|
|
64
|
+
];
|
|
65
|
+
/**
|
|
66
|
+
* Scan `text` for destructive or outward-facing operation patterns.
|
|
67
|
+
*
|
|
68
|
+
* Returns `{ risky: true, reason }` on the first match, or
|
|
69
|
+
* `{ risky: false, reason: '' }` if no pattern matches.
|
|
70
|
+
*
|
|
71
|
+
* Pure, case-insensitive, never throws.
|
|
72
|
+
*/
|
|
73
|
+
export function riskScan(text) {
|
|
74
|
+
try {
|
|
75
|
+
for (const { re, reason } of RISK_PATTERNS) {
|
|
76
|
+
if (re.test(text)) {
|
|
77
|
+
return { risky: true, reason };
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return { risky: false, reason: '' };
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
// Defensive: should never reach here given static regexes, but never throw.
|
|
84
|
+
return { risky: false, reason: '' };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Determine whether an escalation is needed, and which kind.
|
|
89
|
+
*
|
|
90
|
+
* Priority order (highest → lowest):
|
|
91
|
+
* tamper → verify-failed → over-budget → risk → low-confidence
|
|
92
|
+
*
|
|
93
|
+
* Returns the first applicable `EscalationReasonKind`, or `null` if none apply.
|
|
94
|
+
*
|
|
95
|
+
* PURE — no side-effects. The caller must:
|
|
96
|
+
* 1. Persist the EscalationEvent
|
|
97
|
+
* 2. Set swarm status to 'needs-approval'
|
|
98
|
+
* 3. STOP the swarm
|
|
99
|
+
* Never auto-approves; never throws.
|
|
100
|
+
*/
|
|
101
|
+
export function shouldEscalate(ctx) {
|
|
102
|
+
if (ctx.tamper)
|
|
103
|
+
return 'tamper';
|
|
104
|
+
if (ctx.verifyFailed)
|
|
105
|
+
return 'verify-failed';
|
|
106
|
+
if (ctx.overBudget)
|
|
107
|
+
return 'over-budget';
|
|
108
|
+
if (ctx.risk)
|
|
109
|
+
return 'risk';
|
|
110
|
+
if (ctx.lowConfidence)
|
|
111
|
+
return 'low-confidence';
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate.js","sourceRoot":"","sources":["../../../src/core/swarm/gate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* core/swarm/planner.ts — M12 swarm planner.
|
|
3
|
+
*
|
|
4
|
+
* planSwarm({goal, specBody?}, cfg): Promise<SwarmPlan>
|
|
5
|
+
*
|
|
6
|
+
* Decomposes a goal (+ optional spec body) into a phased SwarmPlan via a
|
|
7
|
+
* single bounded model call (LOCAL-first). Guardrails:
|
|
8
|
+
* - Single model call; never throws — all failures fall back to a sensible
|
|
9
|
+
* default plan.
|
|
10
|
+
* - Tasks per phase capped at <= 6; total tasks capped at <= 18.
|
|
11
|
+
* - BUILD-phase tasks are independent (no intra-build deps); later phases
|
|
12
|
+
* carry deps on the tasks from the prior phase.
|
|
13
|
+
* - IDs are stable slugs: scaffold-1, build-1..N, integrate-1, verify-1, review-1.
|
|
14
|
+
*/
|
|
15
|
+
import type { SwarmPlan, AshlrConfig } from '../types.js';
|
|
16
|
+
/**
|
|
17
|
+
* Decompose a goal (+ optional spec body) into a phased SwarmPlan.
|
|
18
|
+
*
|
|
19
|
+
* CONTRACT (from docs/contracts/CONTRACT-M12.md):
|
|
20
|
+
* planSwarm(input: { goal: string; specBody?: string }, cfg: AshlrConfig): Promise<SwarmPlan>
|
|
21
|
+
*
|
|
22
|
+
* Guardrails:
|
|
23
|
+
* - Single bounded model call; never throws.
|
|
24
|
+
* - Tasks per phase <= 6; total tasks <= 18.
|
|
25
|
+
* - BUILD-phase tasks are independent (deps = scaffold tasks only).
|
|
26
|
+
* - Falls back to a sensible default plan on any failure.
|
|
27
|
+
* - LOCAL-first (opts.allowCloud defaults false).
|
|
28
|
+
*/
|
|
29
|
+
export declare function planSwarm(input: {
|
|
30
|
+
goal: string;
|
|
31
|
+
specBody?: string;
|
|
32
|
+
}, cfg: AshlrConfig): Promise<SwarmPlan>;
|