thevoidforge 21.0.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/dist/scripts/vault-read.d.ts +11 -0
- package/dist/scripts/vault-read.js +89 -0
- package/dist/scripts/voidforge.d.ts +20 -0
- package/dist/scripts/voidforge.js +404 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/wizard/api/auth.d.ts +5 -0
- package/dist/wizard/api/auth.js +133 -0
- package/dist/wizard/api/blueprint.d.ts +45 -0
- package/dist/wizard/api/blueprint.js +184 -0
- package/dist/wizard/api/cloud-providers.d.ts +16 -0
- package/dist/wizard/api/cloud-providers.js +363 -0
- package/dist/wizard/api/credentials.d.ts +1 -0
- package/dist/wizard/api/credentials.js +258 -0
- package/dist/wizard/api/danger-room.d.ts +18 -0
- package/dist/wizard/api/danger-room.js +401 -0
- package/dist/wizard/api/deploy.d.ts +4 -0
- package/dist/wizard/api/deploy.js +164 -0
- package/dist/wizard/api/prd.d.ts +1 -0
- package/dist/wizard/api/prd.js +363 -0
- package/dist/wizard/api/project.d.ts +1 -0
- package/dist/wizard/api/project.js +239 -0
- package/dist/wizard/api/projects.d.ts +6 -0
- package/dist/wizard/api/projects.js +648 -0
- package/dist/wizard/api/provision.d.ts +4 -0
- package/dist/wizard/api/provision.js +535 -0
- package/dist/wizard/api/terminal.d.ts +25 -0
- package/dist/wizard/api/terminal.js +241 -0
- package/dist/wizard/api/users.d.ts +6 -0
- package/dist/wizard/api/users.js +244 -0
- package/dist/wizard/api/war-room.d.ts +14 -0
- package/dist/wizard/api/war-room.js +45 -0
- package/dist/wizard/lib/ad-platform-core.d.ts +6 -0
- package/dist/wizard/lib/ad-platform-core.js +1 -0
- package/dist/wizard/lib/adapters/index.d.ts +52 -0
- package/dist/wizard/lib/adapters/index.js +38 -0
- package/dist/wizard/lib/adapters/sandbox-bank.d.ts +17 -0
- package/dist/wizard/lib/adapters/sandbox-bank.js +77 -0
- package/dist/wizard/lib/adapters/sandbox.d.ts +39 -0
- package/dist/wizard/lib/adapters/sandbox.js +174 -0
- package/dist/wizard/lib/adapters/stripe.d.ts +19 -0
- package/dist/wizard/lib/adapters/stripe.js +143 -0
- package/dist/wizard/lib/adapters/types.d.ts +9 -0
- package/dist/wizard/lib/adapters/types.js +10 -0
- package/dist/wizard/lib/agent-memory.d.ts +36 -0
- package/dist/wizard/lib/agent-memory.js +114 -0
- package/dist/wizard/lib/anomaly-detection.d.ts +59 -0
- package/dist/wizard/lib/anomaly-detection.js +122 -0
- package/dist/wizard/lib/anthropic.d.ts +21 -0
- package/dist/wizard/lib/anthropic.js +105 -0
- package/dist/wizard/lib/asset-scanner.d.ts +23 -0
- package/dist/wizard/lib/asset-scanner.js +107 -0
- package/dist/wizard/lib/audit-log.d.ts +23 -0
- package/dist/wizard/lib/audit-log.js +70 -0
- package/dist/wizard/lib/autonomy-controller.d.ts +76 -0
- package/dist/wizard/lib/autonomy-controller.js +183 -0
- package/dist/wizard/lib/body-parser.d.ts +2 -0
- package/dist/wizard/lib/body-parser.js +36 -0
- package/dist/wizard/lib/build-analytics.d.ts +39 -0
- package/dist/wizard/lib/build-analytics.js +91 -0
- package/dist/wizard/lib/build-step.d.ts +21 -0
- package/dist/wizard/lib/build-step.js +104 -0
- package/dist/wizard/lib/campaign-proposer.d.ts +39 -0
- package/dist/wizard/lib/campaign-proposer.js +180 -0
- package/dist/wizard/lib/campaign-state-machine.d.ts +63 -0
- package/dist/wizard/lib/campaign-state-machine.js +114 -0
- package/dist/wizard/lib/ci-generator.d.ts +14 -0
- package/dist/wizard/lib/ci-generator.js +187 -0
- package/dist/wizard/lib/claude-merge.d.ts +38 -0
- package/dist/wizard/lib/claude-merge.js +115 -0
- package/dist/wizard/lib/codegen/erd-gen.d.ts +16 -0
- package/dist/wizard/lib/codegen/erd-gen.js +98 -0
- package/dist/wizard/lib/codegen/integrations.d.ts +18 -0
- package/dist/wizard/lib/codegen/integrations.js +189 -0
- package/dist/wizard/lib/codegen/openapi-gen.d.ts +15 -0
- package/dist/wizard/lib/codegen/openapi-gen.js +79 -0
- package/dist/wizard/lib/codegen/prisma-types.d.ts +15 -0
- package/dist/wizard/lib/codegen/prisma-types.js +44 -0
- package/dist/wizard/lib/codegen/seed-gen.d.ts +16 -0
- package/dist/wizard/lib/codegen/seed-gen.js +128 -0
- package/dist/wizard/lib/compliance.d.ts +51 -0
- package/dist/wizard/lib/compliance.js +112 -0
- package/dist/wizard/lib/correlation-engine.d.ts +59 -0
- package/dist/wizard/lib/correlation-engine.js +151 -0
- package/dist/wizard/lib/cost-estimator.d.ts +22 -0
- package/dist/wizard/lib/cost-estimator.js +72 -0
- package/dist/wizard/lib/cost-tracker.d.ts +27 -0
- package/dist/wizard/lib/cost-tracker.js +37 -0
- package/dist/wizard/lib/daemon-aggregator.d.ts +71 -0
- package/dist/wizard/lib/daemon-aggregator.js +204 -0
- package/dist/wizard/lib/daemon-core.d.ts +6 -0
- package/dist/wizard/lib/daemon-core.js +5 -0
- package/dist/wizard/lib/dashboard-data.d.ts +132 -0
- package/dist/wizard/lib/dashboard-data.js +336 -0
- package/dist/wizard/lib/dashboard-ws.d.ts +25 -0
- package/dist/wizard/lib/dashboard-ws.js +91 -0
- package/dist/wizard/lib/deep-current.d.ts +77 -0
- package/dist/wizard/lib/deep-current.js +234 -0
- package/dist/wizard/lib/deploy-coordinator.d.ts +40 -0
- package/dist/wizard/lib/deploy-coordinator.js +86 -0
- package/dist/wizard/lib/deploy-log.d.ts +28 -0
- package/dist/wizard/lib/deploy-log.js +52 -0
- package/dist/wizard/lib/desktop-notify.d.ts +27 -0
- package/dist/wizard/lib/desktop-notify.js +98 -0
- package/dist/wizard/lib/dns/cloudflare-dns.d.ts +35 -0
- package/dist/wizard/lib/dns/cloudflare-dns.js +216 -0
- package/dist/wizard/lib/dns/cloudflare-registrar.d.ts +31 -0
- package/dist/wizard/lib/dns/cloudflare-registrar.js +148 -0
- package/dist/wizard/lib/dns/types.d.ts +22 -0
- package/dist/wizard/lib/dns/types.js +4 -0
- package/dist/wizard/lib/document-discovery.d.ts +33 -0
- package/dist/wizard/lib/document-discovery.js +145 -0
- package/dist/wizard/lib/env-validator.d.ts +14 -0
- package/dist/wizard/lib/env-validator.js +205 -0
- package/dist/wizard/lib/env-writer.d.ts +13 -0
- package/dist/wizard/lib/env-writer.js +26 -0
- package/dist/wizard/lib/exec.d.ts +30 -0
- package/dist/wizard/lib/exec.js +52 -0
- package/dist/wizard/lib/experiment.d.ts +70 -0
- package/dist/wizard/lib/experiment.js +169 -0
- package/dist/wizard/lib/extensions.d.ts +20 -0
- package/dist/wizard/lib/extensions.js +183 -0
- package/dist/wizard/lib/financial/adapter-factory.d.ts +47 -0
- package/dist/wizard/lib/financial/adapter-factory.js +225 -0
- package/dist/wizard/lib/financial/billing/base.d.ts +6 -0
- package/dist/wizard/lib/financial/billing/base.js +1 -0
- package/dist/wizard/lib/financial/billing/google-billing.d.ts +56 -0
- package/dist/wizard/lib/financial/billing/google-billing.js +298 -0
- package/dist/wizard/lib/financial/billing/meta-billing.d.ts +54 -0
- package/dist/wizard/lib/financial/billing/meta-billing.js +243 -0
- package/dist/wizard/lib/financial/billing/tiktok-billing.d.ts +54 -0
- package/dist/wizard/lib/financial/billing/tiktok-billing.js +260 -0
- package/dist/wizard/lib/financial/campaign/base.d.ts +13 -0
- package/dist/wizard/lib/financial/campaign/base.js +1 -0
- package/dist/wizard/lib/financial/campaign/google-campaign.d.ts +42 -0
- package/dist/wizard/lib/financial/campaign/google-campaign.js +388 -0
- package/dist/wizard/lib/financial/campaign/meta-campaign.d.ts +41 -0
- package/dist/wizard/lib/financial/campaign/meta-campaign.js +311 -0
- package/dist/wizard/lib/financial/campaign/sandbox-campaign.d.ts +45 -0
- package/dist/wizard/lib/financial/campaign/sandbox-campaign.js +261 -0
- package/dist/wizard/lib/financial/campaign/tiktok-campaign.d.ts +40 -0
- package/dist/wizard/lib/financial/campaign/tiktok-campaign.js +350 -0
- package/dist/wizard/lib/financial/funding-auto.d.ts +44 -0
- package/dist/wizard/lib/financial/funding-auto.js +52 -0
- package/dist/wizard/lib/financial/funding-policy.d.ts +60 -0
- package/dist/wizard/lib/financial/funding-policy.js +179 -0
- package/dist/wizard/lib/financial/platform-planner.d.ts +47 -0
- package/dist/wizard/lib/financial/platform-planner.js +134 -0
- package/dist/wizard/lib/financial/reconciliation-engine.d.ts +78 -0
- package/dist/wizard/lib/financial/reconciliation-engine.js +193 -0
- package/dist/wizard/lib/financial/registry.d.ts +22 -0
- package/dist/wizard/lib/financial/registry.js +26 -0
- package/dist/wizard/lib/financial/reporting.d.ts +96 -0
- package/dist/wizard/lib/financial/reporting.js +198 -0
- package/dist/wizard/lib/financial/stablecoin/base.d.ts +6 -0
- package/dist/wizard/lib/financial/stablecoin/base.js +1 -0
- package/dist/wizard/lib/financial/stablecoin/circle.d.ts +54 -0
- package/dist/wizard/lib/financial/stablecoin/circle.js +367 -0
- package/dist/wizard/lib/financial/stablecoin/mercury.d.ts +24 -0
- package/dist/wizard/lib/financial/stablecoin/mercury.js +171 -0
- package/dist/wizard/lib/financial/stablecoin/sandbox-stablecoin.d.ts +47 -0
- package/dist/wizard/lib/financial/stablecoin/sandbox-stablecoin.js +202 -0
- package/dist/wizard/lib/financial/treasury-planner.d.ts +52 -0
- package/dist/wizard/lib/financial/treasury-planner.js +128 -0
- package/dist/wizard/lib/financial-core.d.ts +6 -0
- package/dist/wizard/lib/financial-core.js +5 -0
- package/dist/wizard/lib/financial-vault.d.ts +34 -0
- package/dist/wizard/lib/financial-vault.js +199 -0
- package/dist/wizard/lib/frontmatter.d.ts +30 -0
- package/dist/wizard/lib/frontmatter.js +96 -0
- package/dist/wizard/lib/gap-analysis.d.ts +37 -0
- package/dist/wizard/lib/gap-analysis.js +218 -0
- package/dist/wizard/lib/github.d.ts +22 -0
- package/dist/wizard/lib/github.js +261 -0
- package/dist/wizard/lib/headless-deploy.d.ts +14 -0
- package/dist/wizard/lib/headless-deploy.js +452 -0
- package/dist/wizard/lib/health-monitor.d.ts +15 -0
- package/dist/wizard/lib/health-monitor.js +91 -0
- package/dist/wizard/lib/health-poller.d.ts +9 -0
- package/dist/wizard/lib/health-poller.js +123 -0
- package/dist/wizard/lib/heartbeat.d.ts +15 -0
- package/dist/wizard/lib/heartbeat.js +827 -0
- package/dist/wizard/lib/http-helpers.d.ts +9 -0
- package/dist/wizard/lib/http-helpers.js +24 -0
- package/dist/wizard/lib/image-gen.d.ts +56 -0
- package/dist/wizard/lib/image-gen.js +159 -0
- package/dist/wizard/lib/instance-sizing.d.ts +26 -0
- package/dist/wizard/lib/instance-sizing.js +51 -0
- package/dist/wizard/lib/kongo/analytics.d.ts +29 -0
- package/dist/wizard/lib/kongo/analytics.js +179 -0
- package/dist/wizard/lib/kongo/campaigns.d.ts +52 -0
- package/dist/wizard/lib/kongo/campaigns.js +91 -0
- package/dist/wizard/lib/kongo/client.d.ts +58 -0
- package/dist/wizard/lib/kongo/client.js +221 -0
- package/dist/wizard/lib/kongo/jobs.d.ts +57 -0
- package/dist/wizard/lib/kongo/jobs.js +122 -0
- package/dist/wizard/lib/kongo/pages.d.ts +60 -0
- package/dist/wizard/lib/kongo/pages.js +150 -0
- package/dist/wizard/lib/kongo/provisioner.d.ts +64 -0
- package/dist/wizard/lib/kongo/provisioner.js +116 -0
- package/dist/wizard/lib/kongo/seed.d.ts +49 -0
- package/dist/wizard/lib/kongo/seed.js +237 -0
- package/dist/wizard/lib/kongo/types.d.ts +323 -0
- package/dist/wizard/lib/kongo/types.js +11 -0
- package/dist/wizard/lib/kongo/variants.d.ts +57 -0
- package/dist/wizard/lib/kongo/variants.js +88 -0
- package/dist/wizard/lib/kongo/webhooks.d.ts +41 -0
- package/dist/wizard/lib/kongo/webhooks.js +112 -0
- package/dist/wizard/lib/marker.d.ts +28 -0
- package/dist/wizard/lib/marker.js +79 -0
- package/dist/wizard/lib/migrator.d.ts +35 -0
- package/dist/wizard/lib/migrator.js +190 -0
- package/dist/wizard/lib/natural-language-deploy.d.ts +30 -0
- package/dist/wizard/lib/natural-language-deploy.js +186 -0
- package/dist/wizard/lib/network.d.ts +22 -0
- package/dist/wizard/lib/network.js +72 -0
- package/dist/wizard/lib/oauth-core.d.ts +6 -0
- package/dist/wizard/lib/oauth-core.js +5 -0
- package/dist/wizard/lib/open-browser.d.ts +1 -0
- package/dist/wizard/lib/open-browser.js +26 -0
- package/dist/wizard/lib/patterns/ad-billing-adapter.d.ts +209 -0
- package/dist/wizard/lib/patterns/ad-billing-adapter.js +269 -0
- package/dist/wizard/lib/patterns/ad-platform-adapter.d.ts +200 -0
- package/dist/wizard/lib/patterns/ad-platform-adapter.js +212 -0
- package/dist/wizard/lib/patterns/daemon-process.d.ts +88 -0
- package/dist/wizard/lib/patterns/daemon-process.js +271 -0
- package/dist/wizard/lib/patterns/financial-transaction.d.ts +161 -0
- package/dist/wizard/lib/patterns/financial-transaction.js +132 -0
- package/dist/wizard/lib/patterns/funding-plan.d.ts +136 -0
- package/dist/wizard/lib/patterns/funding-plan.js +200 -0
- package/dist/wizard/lib/patterns/oauth-token-lifecycle.d.ts +94 -0
- package/dist/wizard/lib/patterns/oauth-token-lifecycle.js +139 -0
- package/dist/wizard/lib/patterns/outbound-rate-limiter.d.ts +67 -0
- package/dist/wizard/lib/patterns/outbound-rate-limiter.js +216 -0
- package/dist/wizard/lib/patterns/revenue-source-adapter.d.ts +96 -0
- package/dist/wizard/lib/patterns/revenue-source-adapter.js +182 -0
- package/dist/wizard/lib/patterns/stablecoin-adapter.d.ts +218 -0
- package/dist/wizard/lib/patterns/stablecoin-adapter.js +264 -0
- package/dist/wizard/lib/prd-validator.d.ts +39 -0
- package/dist/wizard/lib/prd-validator.js +137 -0
- package/dist/wizard/lib/project-init.d.ts +24 -0
- package/dist/wizard/lib/project-init.js +193 -0
- package/dist/wizard/lib/project-registry.d.ts +86 -0
- package/dist/wizard/lib/project-registry.js +359 -0
- package/dist/wizard/lib/provision-manifest.d.ts +44 -0
- package/dist/wizard/lib/provision-manifest.js +164 -0
- package/dist/wizard/lib/provisioner-registry.d.ts +15 -0
- package/dist/wizard/lib/provisioner-registry.js +34 -0
- package/dist/wizard/lib/provisioners/aws-vps.d.ts +6 -0
- package/dist/wizard/lib/provisioners/aws-vps.js +643 -0
- package/dist/wizard/lib/provisioners/cloudflare.d.ts +6 -0
- package/dist/wizard/lib/provisioners/cloudflare.js +300 -0
- package/dist/wizard/lib/provisioners/docker.d.ts +6 -0
- package/dist/wizard/lib/provisioners/docker.js +75 -0
- package/dist/wizard/lib/provisioners/http-client.d.ts +20 -0
- package/dist/wizard/lib/provisioners/http-client.js +79 -0
- package/dist/wizard/lib/provisioners/railway.d.ts +6 -0
- package/dist/wizard/lib/provisioners/railway.js +413 -0
- package/dist/wizard/lib/provisioners/scripts/caddyfile.d.ts +10 -0
- package/dist/wizard/lib/provisioners/scripts/caddyfile.js +54 -0
- package/dist/wizard/lib/provisioners/scripts/deploy-vps.d.ts +10 -0
- package/dist/wizard/lib/provisioners/scripts/deploy-vps.js +112 -0
- package/dist/wizard/lib/provisioners/scripts/docker-compose.d.ts +11 -0
- package/dist/wizard/lib/provisioners/scripts/docker-compose.js +91 -0
- package/dist/wizard/lib/provisioners/scripts/dockerfile.d.ts +5 -0
- package/dist/wizard/lib/provisioners/scripts/dockerfile.js +185 -0
- package/dist/wizard/lib/provisioners/scripts/ecosystem-config.d.ts +10 -0
- package/dist/wizard/lib/provisioners/scripts/ecosystem-config.js +36 -0
- package/dist/wizard/lib/provisioners/scripts/provision-vps.d.ts +14 -0
- package/dist/wizard/lib/provisioners/scripts/provision-vps.js +202 -0
- package/dist/wizard/lib/provisioners/scripts/rollback-vps.d.ts +10 -0
- package/dist/wizard/lib/provisioners/scripts/rollback-vps.js +67 -0
- package/dist/wizard/lib/provisioners/self-deploy.d.ts +41 -0
- package/dist/wizard/lib/provisioners/self-deploy.js +185 -0
- package/dist/wizard/lib/provisioners/static-s3.d.ts +6 -0
- package/dist/wizard/lib/provisioners/static-s3.js +235 -0
- package/dist/wizard/lib/provisioners/types.d.ts +40 -0
- package/dist/wizard/lib/provisioners/types.js +4 -0
- package/dist/wizard/lib/provisioners/vercel.d.ts +6 -0
- package/dist/wizard/lib/provisioners/vercel.js +287 -0
- package/dist/wizard/lib/pty-manager.d.ts +42 -0
- package/dist/wizard/lib/pty-manager.js +231 -0
- package/dist/wizard/lib/rate-limiter-core.d.ts +5 -0
- package/dist/wizard/lib/rate-limiter-core.js +5 -0
- package/dist/wizard/lib/reconciliation.d.ts +43 -0
- package/dist/wizard/lib/reconciliation.js +173 -0
- package/dist/wizard/lib/revenue-types.d.ts +5 -0
- package/dist/wizard/lib/revenue-types.js +1 -0
- package/dist/wizard/lib/route-optimizer.d.ts +28 -0
- package/dist/wizard/lib/route-optimizer.js +93 -0
- package/dist/wizard/lib/s3-deploy.d.ts +19 -0
- package/dist/wizard/lib/s3-deploy.js +156 -0
- package/dist/wizard/lib/safety-tiers.d.ts +76 -0
- package/dist/wizard/lib/safety-tiers.js +134 -0
- package/dist/wizard/lib/sentry-generator.d.ts +15 -0
- package/dist/wizard/lib/sentry-generator.js +116 -0
- package/dist/wizard/lib/server-config.d.ts +13 -0
- package/dist/wizard/lib/server-config.js +23 -0
- package/dist/wizard/lib/service-install.d.ts +18 -0
- package/dist/wizard/lib/service-install.js +182 -0
- package/dist/wizard/lib/site-scanner.d.ts +80 -0
- package/dist/wizard/lib/site-scanner.js +262 -0
- package/dist/wizard/lib/ssh-deploy.d.ts +25 -0
- package/dist/wizard/lib/ssh-deploy.js +225 -0
- package/dist/wizard/lib/templates.d.ts +24 -0
- package/dist/wizard/lib/templates.js +219 -0
- package/dist/wizard/lib/totp.d.ts +35 -0
- package/dist/wizard/lib/totp.js +276 -0
- package/dist/wizard/lib/tower-auth.d.ts +43 -0
- package/dist/wizard/lib/tower-auth.js +352 -0
- package/dist/wizard/lib/tower-rate-limit.d.ts +14 -0
- package/dist/wizard/lib/tower-rate-limit.js +61 -0
- package/dist/wizard/lib/tower-session.d.ts +28 -0
- package/dist/wizard/lib/tower-session.js +119 -0
- package/dist/wizard/lib/treasury-backup.d.ts +23 -0
- package/dist/wizard/lib/treasury-backup.js +126 -0
- package/dist/wizard/lib/treasury-heartbeat.d.ts +82 -0
- package/dist/wizard/lib/treasury-heartbeat.js +1104 -0
- package/dist/wizard/lib/updater.d.ts +29 -0
- package/dist/wizard/lib/updater.js +190 -0
- package/dist/wizard/lib/user-manager.d.ts +39 -0
- package/dist/wizard/lib/user-manager.js +182 -0
- package/dist/wizard/lib/vault.d.ts +26 -0
- package/dist/wizard/lib/vault.js +161 -0
- package/dist/wizard/router.d.ts +5 -0
- package/dist/wizard/router.js +15 -0
- package/dist/wizard/server.d.ts +18 -0
- package/dist/wizard/server.js +436 -0
- package/package.json +59 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Autonomy Controller — Tier 2 supervised + Tier 3 full autonomy (v12.3-v12.4).
|
|
3
|
+
*
|
|
4
|
+
* Manages the autonomous execution loop: proposal → delay → execute/veto.
|
|
5
|
+
* Implements circuit breakers, kill switch, deploy freeze, strategic sync.
|
|
6
|
+
*
|
|
7
|
+
* PRD Reference: ROADMAP v12.3-v12.4, DEEP_CURRENT.md Autonomy Tiers + Security
|
|
8
|
+
*/
|
|
9
|
+
import { existsSync } from 'node:fs';
|
|
10
|
+
import { readFile, open, rename, mkdir } from 'node:fs/promises';
|
|
11
|
+
import { join } from 'node:path';
|
|
12
|
+
import { DEEP_CURRENT_DIR } from './deep-current.js';
|
|
13
|
+
const AUTONOMY_STATE_PATH = join(DEEP_CURRENT_DIR, 'autonomy-state.json');
|
|
14
|
+
const DEFAULT_STATE = {
|
|
15
|
+
tier: 1,
|
|
16
|
+
active: false,
|
|
17
|
+
stopped: false,
|
|
18
|
+
campaignsRun: 0,
|
|
19
|
+
consecutiveCampaigns: 0,
|
|
20
|
+
lastHumanReview: new Date().toISOString(),
|
|
21
|
+
lastStrategicSync: new Date().toISOString(),
|
|
22
|
+
circuitBreakers: {
|
|
23
|
+
driftScore: 0,
|
|
24
|
+
consecutiveCriticals: 0,
|
|
25
|
+
spendIncreaseStreak: 0,
|
|
26
|
+
roasBelow1: 0,
|
|
27
|
+
},
|
|
28
|
+
deployFreezeWindows: [],
|
|
29
|
+
};
|
|
30
|
+
// ── State Persistence ─────────────────────────────────
|
|
31
|
+
export async function loadAutonomyState() {
|
|
32
|
+
if (!existsSync(AUTONOMY_STATE_PATH))
|
|
33
|
+
return { ...DEFAULT_STATE };
|
|
34
|
+
try {
|
|
35
|
+
const content = await readFile(AUTONOMY_STATE_PATH, 'utf-8');
|
|
36
|
+
return JSON.parse(content);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return { ...DEFAULT_STATE };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// IG-R4 LOKI-001: Serialization queue prevents concurrent write corruption
|
|
43
|
+
let writeQueue = Promise.resolve();
|
|
44
|
+
function serialized(fn) {
|
|
45
|
+
const result = writeQueue.then(fn, () => fn());
|
|
46
|
+
writeQueue = result.then(() => { }, () => { });
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
export function saveAutonomyState(state) {
|
|
50
|
+
return serialized(async () => {
|
|
51
|
+
await mkdir(DEEP_CURRENT_DIR, { recursive: true });
|
|
52
|
+
// IG-R4 LOKI-001: Atomic write — temp+fsync+rename prevents kill switch reset on crash
|
|
53
|
+
const tmpPath = AUTONOMY_STATE_PATH + '.tmp';
|
|
54
|
+
const fh = await open(tmpPath, 'w', 0o600);
|
|
55
|
+
try {
|
|
56
|
+
await fh.writeFile(JSON.stringify(state, null, 2));
|
|
57
|
+
await fh.sync();
|
|
58
|
+
}
|
|
59
|
+
finally {
|
|
60
|
+
await fh.close();
|
|
61
|
+
}
|
|
62
|
+
await rename(tmpPath, AUTONOMY_STATE_PATH);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Check all circuit breakers. Returns whether autonomous operation should continue.
|
|
67
|
+
*/
|
|
68
|
+
export function checkCircuitBreakers(state) {
|
|
69
|
+
// Kill switch
|
|
70
|
+
if (state.stopped) {
|
|
71
|
+
return { safe: false, reason: 'Kill switch engaged (/current --stop)', action: 'stop' };
|
|
72
|
+
}
|
|
73
|
+
// Strategic drift > 30%
|
|
74
|
+
if (state.circuitBreakers.driftScore > 30) {
|
|
75
|
+
return { safe: false, reason: `Strategic drift score ${state.circuitBreakers.driftScore}% exceeds 30% threshold`, action: 'pause' };
|
|
76
|
+
}
|
|
77
|
+
// 3+ consecutive campaigns with increasing Criticals
|
|
78
|
+
if (state.circuitBreakers.consecutiveCriticals >= 3) {
|
|
79
|
+
return { safe: false, reason: `${state.circuitBreakers.consecutiveCriticals} consecutive campaigns with increasing Critical findings`, action: 'downgrade_to_tier1' };
|
|
80
|
+
}
|
|
81
|
+
// 7 consecutive days of increasing spend
|
|
82
|
+
if (state.circuitBreakers.spendIncreaseStreak >= 7) {
|
|
83
|
+
return { safe: false, reason: '7 consecutive days of increasing daily spend — human review required', action: 'pause' };
|
|
84
|
+
}
|
|
85
|
+
// ROAS < 1.0x for 7+ days
|
|
86
|
+
if (state.circuitBreakers.roasBelow1 >= 7) {
|
|
87
|
+
return { safe: false, reason: 'Blended ROAS below 1.0x for 7+ days — losing money', action: 'pause' };
|
|
88
|
+
}
|
|
89
|
+
// 30-day strategic sync overdue
|
|
90
|
+
const syncAge = Date.now() - new Date(state.lastStrategicSync).getTime();
|
|
91
|
+
const thirtyDays = 30 * 24 * 60 * 60 * 1000;
|
|
92
|
+
if (syncAge > thirtyDays) {
|
|
93
|
+
return { safe: false, reason: '30-day mandatory strategic sync overdue', action: 'pause' };
|
|
94
|
+
}
|
|
95
|
+
// 10-campaign human checkpoint (Tier 3 only)
|
|
96
|
+
if (state.tier === 3 && state.consecutiveCampaigns >= 10) {
|
|
97
|
+
return { safe: false, reason: '10 autonomous campaigns since last human review', action: 'pause' };
|
|
98
|
+
}
|
|
99
|
+
// Deploy freeze window check
|
|
100
|
+
if (isInDeployFreeze(state)) {
|
|
101
|
+
return { safe: false, reason: 'Currently in deploy freeze window', action: 'pause' };
|
|
102
|
+
}
|
|
103
|
+
return { safe: true };
|
|
104
|
+
}
|
|
105
|
+
function isInDeployFreeze(state) {
|
|
106
|
+
if (state.deployFreezeWindows.length === 0)
|
|
107
|
+
return false;
|
|
108
|
+
const now = new Date();
|
|
109
|
+
const dayOfWeek = now.getUTCDay();
|
|
110
|
+
const hour = now.getUTCHours();
|
|
111
|
+
return state.deployFreezeWindows.some(w => w.dayOfWeek === dayOfWeek && hour >= w.startHour && hour < w.endHour);
|
|
112
|
+
}
|
|
113
|
+
// ── Tier 2: Supervised Autonomy ───────────────────────
|
|
114
|
+
/**
|
|
115
|
+
* Queue a proposal for Tier 2 execution (24h delay).
|
|
116
|
+
*/
|
|
117
|
+
export function queueProposal(state, proposal) {
|
|
118
|
+
const proposedAt = new Date();
|
|
119
|
+
const executeAt = new Date(proposedAt.getTime() + 24 * 60 * 60 * 1000); // 24h delay
|
|
120
|
+
state.pendingProposal = {
|
|
121
|
+
proposal,
|
|
122
|
+
proposedAt: proposedAt.toISOString(),
|
|
123
|
+
executeAt: executeAt.toISOString(),
|
|
124
|
+
vetoed: false,
|
|
125
|
+
};
|
|
126
|
+
return state;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Check if a pending Tier 2 proposal is ready to execute.
|
|
130
|
+
*/
|
|
131
|
+
export function isProposalReady(state) {
|
|
132
|
+
if (!state.pendingProposal)
|
|
133
|
+
return false;
|
|
134
|
+
if (state.pendingProposal.vetoed)
|
|
135
|
+
return false;
|
|
136
|
+
if (state.tier === 3)
|
|
137
|
+
return true; // Tier 3: immediate execution
|
|
138
|
+
// Tier 2: execute after delay
|
|
139
|
+
return Date.now() >= new Date(state.pendingProposal.executeAt).getTime();
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Veto a pending Tier 2 proposal.
|
|
143
|
+
*/
|
|
144
|
+
export function vetoProposal(state) {
|
|
145
|
+
if (state.pendingProposal) {
|
|
146
|
+
state.pendingProposal.vetoed = true;
|
|
147
|
+
}
|
|
148
|
+
return state;
|
|
149
|
+
}
|
|
150
|
+
// ── Kill Switch ───────────────────────────────────────
|
|
151
|
+
export function engageKillSwitch(state) {
|
|
152
|
+
state.stopped = true;
|
|
153
|
+
state.active = false;
|
|
154
|
+
state.pendingProposal = undefined;
|
|
155
|
+
return state;
|
|
156
|
+
}
|
|
157
|
+
export function disengageKillSwitch(state) {
|
|
158
|
+
state.stopped = false;
|
|
159
|
+
return state;
|
|
160
|
+
}
|
|
161
|
+
// ── Strategic Sync ────────────────────────────────────
|
|
162
|
+
export function recordStrategicSync(state) {
|
|
163
|
+
state.lastStrategicSync = new Date().toISOString();
|
|
164
|
+
state.lastHumanReview = new Date().toISOString();
|
|
165
|
+
state.consecutiveCampaigns = 0;
|
|
166
|
+
return state;
|
|
167
|
+
}
|
|
168
|
+
export function recordCampaignComplete(state) {
|
|
169
|
+
state.campaignsRun += 1;
|
|
170
|
+
state.consecutiveCampaigns += 1;
|
|
171
|
+
state.pendingProposal = undefined;
|
|
172
|
+
return state;
|
|
173
|
+
}
|
|
174
|
+
const DEFAULT_SOFT_LIMITS = {
|
|
175
|
+
maxConsecutiveMissions: 5,
|
|
176
|
+
maxDeploysPerDay: 1,
|
|
177
|
+
aggregateDailySpendCeiling: 5000,
|
|
178
|
+
strategicDriftThreshold: 30,
|
|
179
|
+
explorationBudgetPercent: 10,
|
|
180
|
+
lessonDecayHalfLifeDays: 90,
|
|
181
|
+
minRoasBeforeFreeze: 1.0,
|
|
182
|
+
};
|
|
183
|
+
export { DEFAULT_STATE, DEFAULT_SOFT_LIMITS, AUTONOMY_STATE_PATH };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const MAX_BODY_SIZE = 1024 * 1024; // 1MB
|
|
2
|
+
export function parseJsonBody(req) {
|
|
3
|
+
return new Promise((resolve, reject) => {
|
|
4
|
+
const chunks = [];
|
|
5
|
+
let size = 0;
|
|
6
|
+
req.on('data', (chunk) => {
|
|
7
|
+
size += chunk.length;
|
|
8
|
+
if (size > MAX_BODY_SIZE) {
|
|
9
|
+
req.destroy();
|
|
10
|
+
reject(new Error('Request body too large'));
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
chunks.push(chunk);
|
|
14
|
+
});
|
|
15
|
+
req.on('end', () => {
|
|
16
|
+
const body = Buffer.concat(chunks).toString('utf-8');
|
|
17
|
+
if (!body) {
|
|
18
|
+
resolve({});
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
const parsed = JSON.parse(body);
|
|
23
|
+
// IG-R2: Reject non-object bodies (null, arrays, strings, numbers) at the parser level
|
|
24
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
25
|
+
reject(new Error('Request body must be a JSON object'));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
resolve(parsed);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
reject(new Error('Invalid JSON'));
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
req.on('error', reject);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build analytics — tracks metrics across projects for trend analysis.
|
|
3
|
+
* Stored at ~/.voidforge/analytics.json. No external dependencies.
|
|
4
|
+
*
|
|
5
|
+
* Wong guards the knowledge. The Sanctum grows.
|
|
6
|
+
*/
|
|
7
|
+
export interface PhaseMetric {
|
|
8
|
+
phase: string;
|
|
9
|
+
findingsCount: number;
|
|
10
|
+
fixesApplied: number;
|
|
11
|
+
/** Duration in seconds (optional — only if measurable) */
|
|
12
|
+
durationSeconds?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface BuildRecord {
|
|
15
|
+
projectName: string;
|
|
16
|
+
framework: string;
|
|
17
|
+
database: string;
|
|
18
|
+
deployTarget: string;
|
|
19
|
+
timestamp: string;
|
|
20
|
+
version: string;
|
|
21
|
+
phases: PhaseMetric[];
|
|
22
|
+
totalFindings: number;
|
|
23
|
+
totalFixes: number;
|
|
24
|
+
testCount?: number;
|
|
25
|
+
lessonsExtracted: number;
|
|
26
|
+
}
|
|
27
|
+
export interface AnalyticsStore {
|
|
28
|
+
builds: BuildRecord[];
|
|
29
|
+
}
|
|
30
|
+
/** Record a completed build. */
|
|
31
|
+
export declare function recordBuild(record: BuildRecord): Promise<void>;
|
|
32
|
+
/** Surface trends across past builds. Returns human-readable insights. */
|
|
33
|
+
export declare function surfaceTrends(currentFramework?: string): Promise<string[]>;
|
|
34
|
+
/** Get a summary of all recorded builds. */
|
|
35
|
+
export declare function getBuildHistory(): Promise<{
|
|
36
|
+
count: number;
|
|
37
|
+
frameworks: string[];
|
|
38
|
+
latestBuild: string | null;
|
|
39
|
+
}>;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build analytics — tracks metrics across projects for trend analysis.
|
|
3
|
+
* Stored at ~/.voidforge/analytics.json. No external dependencies.
|
|
4
|
+
*
|
|
5
|
+
* Wong guards the knowledge. The Sanctum grows.
|
|
6
|
+
*/
|
|
7
|
+
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
8
|
+
import { join } from 'node:path';
|
|
9
|
+
import { homedir } from 'node:os';
|
|
10
|
+
const ANALYTICS_DIR = join(homedir(), '.voidforge');
|
|
11
|
+
const ANALYTICS_FILE = join(ANALYTICS_DIR, 'analytics.json');
|
|
12
|
+
async function ensureDir() {
|
|
13
|
+
try {
|
|
14
|
+
await mkdir(ANALYTICS_DIR, { recursive: true });
|
|
15
|
+
}
|
|
16
|
+
catch { /* exists */ }
|
|
17
|
+
}
|
|
18
|
+
async function loadStore() {
|
|
19
|
+
try {
|
|
20
|
+
const raw = await readFile(ANALYTICS_FILE, 'utf-8');
|
|
21
|
+
return JSON.parse(raw);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return { builds: [] };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
async function saveStore(store) {
|
|
28
|
+
await ensureDir();
|
|
29
|
+
await writeFile(ANALYTICS_FILE, JSON.stringify(store, null, 2), 'utf-8');
|
|
30
|
+
}
|
|
31
|
+
/** Record a completed build. */
|
|
32
|
+
export async function recordBuild(record) {
|
|
33
|
+
const store = await loadStore();
|
|
34
|
+
store.builds.push(record);
|
|
35
|
+
// Keep last 100 builds to prevent unbounded growth
|
|
36
|
+
if (store.builds.length > 100) {
|
|
37
|
+
store.builds = store.builds.slice(-100);
|
|
38
|
+
}
|
|
39
|
+
await saveStore(store);
|
|
40
|
+
}
|
|
41
|
+
/** Surface trends across past builds. Returns human-readable insights. */
|
|
42
|
+
export async function surfaceTrends(currentFramework) {
|
|
43
|
+
const store = await loadStore();
|
|
44
|
+
const builds = store.builds;
|
|
45
|
+
if (builds.length < 2)
|
|
46
|
+
return [];
|
|
47
|
+
const insights = [];
|
|
48
|
+
// Finding hotspots — which phases consistently produce the most findings?
|
|
49
|
+
const phaseFindings = {};
|
|
50
|
+
for (const build of builds) {
|
|
51
|
+
for (const phase of build.phases) {
|
|
52
|
+
if (!phaseFindings[phase.phase])
|
|
53
|
+
phaseFindings[phase.phase] = [];
|
|
54
|
+
phaseFindings[phase.phase].push(phase.findingsCount);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
for (const [phase, counts] of Object.entries(phaseFindings)) {
|
|
58
|
+
const avg = counts.reduce((a, b) => a + b, 0) / counts.length;
|
|
59
|
+
if (avg > 5 && counts.length >= 2) {
|
|
60
|
+
insights.push(`Phase "${phase}" averages ${avg.toFixed(1)} findings across ${counts.length} builds — consider proactive checks in earlier phases.`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Framework-specific patterns
|
|
64
|
+
if (currentFramework) {
|
|
65
|
+
const frameworkBuilds = builds.filter(b => b.framework === currentFramework);
|
|
66
|
+
if (frameworkBuilds.length >= 2) {
|
|
67
|
+
const avgFindings = frameworkBuilds.reduce((a, b) => a + b.totalFindings, 0) / frameworkBuilds.length;
|
|
68
|
+
insights.push(`Your ${currentFramework} projects average ${avgFindings.toFixed(0)} findings per build (${frameworkBuilds.length} builds).`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Fix-to-finding ratio trend
|
|
72
|
+
const ratios = builds.map(b => b.totalFindings > 0 ? b.totalFixes / b.totalFindings : 1);
|
|
73
|
+
const recentRatios = ratios.slice(-5);
|
|
74
|
+
const avgRatio = recentRatios.reduce((a, b) => a + b, 0) / recentRatios.length;
|
|
75
|
+
if (avgRatio < 0.8) {
|
|
76
|
+
insights.push(`Fix-to-finding ratio is ${(avgRatio * 100).toFixed(0)}% — some findings are being deferred. Consider addressing all findings in each build.`);
|
|
77
|
+
}
|
|
78
|
+
// Lessons trend
|
|
79
|
+
const totalLessons = builds.reduce((a, b) => a + b.lessonsExtracted, 0);
|
|
80
|
+
if (totalLessons > 0) {
|
|
81
|
+
insights.push(`${totalLessons} lessons extracted across ${builds.length} builds. The forge is learning.`);
|
|
82
|
+
}
|
|
83
|
+
return insights;
|
|
84
|
+
}
|
|
85
|
+
/** Get a summary of all recorded builds. */
|
|
86
|
+
export async function getBuildHistory() {
|
|
87
|
+
const store = await loadStore();
|
|
88
|
+
const frameworks = [...new Set(store.builds.map(b => b.framework))];
|
|
89
|
+
const latest = store.builds.length > 0 ? store.builds[store.builds.length - 1].timestamp : null;
|
|
90
|
+
return { count: store.builds.length, frameworks, latestBuild: latest };
|
|
91
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre-deploy build step — framework-aware build before upload/push.
|
|
3
|
+
* Runs AFTER provisioning, BEFORE deploy actions (SSH/S3/platform).
|
|
4
|
+
* Uses exec.ts for process execution (ADR-013, ADR-016).
|
|
5
|
+
*/
|
|
6
|
+
import type { ProvisionEmitter } from './provisioners/types.js';
|
|
7
|
+
export interface BuildStepResult {
|
|
8
|
+
success: boolean;
|
|
9
|
+
outputDir: string;
|
|
10
|
+
error?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Run a framework-aware build step in the project directory.
|
|
14
|
+
* Returns success if the build output directory exists after the build.
|
|
15
|
+
*/
|
|
16
|
+
export declare function runBuildStep(projectDir: string, framework: string, emit: ProvisionEmitter, abortSignal?: AbortSignal): Promise<BuildStepResult>;
|
|
17
|
+
/**
|
|
18
|
+
* Get the expected build output directory for a framework.
|
|
19
|
+
* Used by deploy steps that need to know where to find build artifacts.
|
|
20
|
+
*/
|
|
21
|
+
export declare function getBuildOutputDir(framework: string): string;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre-deploy build step — framework-aware build before upload/push.
|
|
3
|
+
* Runs AFTER provisioning, BEFORE deploy actions (SSH/S3/platform).
|
|
4
|
+
* Uses exec.ts for process execution (ADR-013, ADR-016).
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync } from 'node:fs';
|
|
7
|
+
import { join } from 'node:path';
|
|
8
|
+
import { execCommand } from './exec.js';
|
|
9
|
+
/** Framework → build configuration mapping. */
|
|
10
|
+
const FRAMEWORK_BUILDS = {
|
|
11
|
+
'next.js': { command: 'npm', args: ['run', 'build'], outputDir: '.next' },
|
|
12
|
+
'express': { command: 'npm', args: ['run', 'build'], outputDir: 'dist' },
|
|
13
|
+
'vite': { command: 'npm', args: ['run', 'build'], outputDir: 'dist' },
|
|
14
|
+
'nuxt': { command: 'npm', args: ['run', 'build'], outputDir: '.output' },
|
|
15
|
+
'remix': { command: 'npm', args: ['run', 'build'], outputDir: 'build' },
|
|
16
|
+
'svelte': { command: 'npm', args: ['run', 'build'], outputDir: 'build' },
|
|
17
|
+
'sveltekit': { command: 'npm', args: ['run', 'build'], outputDir: 'build' },
|
|
18
|
+
'astro': { command: 'npm', args: ['run', 'build'], outputDir: 'dist' },
|
|
19
|
+
'gatsby': { command: 'npm', args: ['run', 'build'], outputDir: 'public' },
|
|
20
|
+
'django': { command: 'python', args: ['manage.py', 'collectstatic', '--noinput'], outputDir: 'staticfiles' },
|
|
21
|
+
'rails': { command: 'bundle', args: ['exec', 'rails', 'assets:precompile'], outputDir: 'public/assets' },
|
|
22
|
+
};
|
|
23
|
+
/** Default for unknown Node-based frameworks. */
|
|
24
|
+
const DEFAULT_BUILD = { command: 'npm', args: ['run', 'build'], outputDir: 'dist' };
|
|
25
|
+
/** Frameworks where the build step should be skipped. */
|
|
26
|
+
const SKIP_BUILD_FRAMEWORKS = new Set(['flask']);
|
|
27
|
+
/**
|
|
28
|
+
* Run a framework-aware build step in the project directory.
|
|
29
|
+
* Returns success if the build output directory exists after the build.
|
|
30
|
+
*/
|
|
31
|
+
export async function runBuildStep(projectDir, framework, emit, abortSignal) {
|
|
32
|
+
if (SKIP_BUILD_FRAMEWORKS.has(framework)) {
|
|
33
|
+
emit({ step: 'build', status: 'skipped', message: `${framework} — no build step required` });
|
|
34
|
+
return { success: true, outputDir: '' };
|
|
35
|
+
}
|
|
36
|
+
const config = FRAMEWORK_BUILDS[framework] || DEFAULT_BUILD;
|
|
37
|
+
const fullOutputDir = join(projectDir, config.outputDir);
|
|
38
|
+
// If output dir already exists, skip build (user may have built manually)
|
|
39
|
+
if (existsSync(fullOutputDir)) {
|
|
40
|
+
emit({ step: 'build', status: 'done', message: `Build output already exists at ${config.outputDir} — skipping build` });
|
|
41
|
+
return { success: true, outputDir: config.outputDir };
|
|
42
|
+
}
|
|
43
|
+
emit({ step: 'build', status: 'started', message: `Building project: ${config.command} ${config.args.join(' ')}` });
|
|
44
|
+
try {
|
|
45
|
+
// Check if package.json exists for Node-based builds
|
|
46
|
+
if (config.command === 'npm' && !existsSync(join(projectDir, 'package.json'))) {
|
|
47
|
+
emit({ step: 'build', status: 'skipped', message: 'No package.json found — skipping build' });
|
|
48
|
+
return { success: true, outputDir: '' };
|
|
49
|
+
}
|
|
50
|
+
// Install dependencies first for Node projects
|
|
51
|
+
if (config.command === 'npm' && existsSync(join(projectDir, 'package.json'))) {
|
|
52
|
+
emit({ step: 'build-deps', status: 'started', message: 'Installing dependencies (npm ci)' });
|
|
53
|
+
try {
|
|
54
|
+
await execCommand('npm', ['ci'], {
|
|
55
|
+
cwd: projectDir,
|
|
56
|
+
timeout: 300_000,
|
|
57
|
+
abortSignal,
|
|
58
|
+
});
|
|
59
|
+
emit({ step: 'build-deps', status: 'done', message: 'Dependencies installed' });
|
|
60
|
+
}
|
|
61
|
+
catch (depErr) {
|
|
62
|
+
// Fall back to npm install if npm ci fails (no lock file)
|
|
63
|
+
await execCommand('npm', ['install'], {
|
|
64
|
+
cwd: projectDir,
|
|
65
|
+
timeout: 300_000,
|
|
66
|
+
abortSignal,
|
|
67
|
+
});
|
|
68
|
+
emit({ step: 'build-deps', status: 'done', message: 'Dependencies installed (via npm install)' });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
await execCommand(config.command, config.args, {
|
|
72
|
+
cwd: projectDir,
|
|
73
|
+
timeout: 300_000, // 5 minutes for builds
|
|
74
|
+
abortSignal,
|
|
75
|
+
});
|
|
76
|
+
// Verify output directory was created
|
|
77
|
+
if (existsSync(fullOutputDir)) {
|
|
78
|
+
emit({ step: 'build', status: 'done', message: `Build complete — output at ${config.outputDir}` });
|
|
79
|
+
return { success: true, outputDir: config.outputDir };
|
|
80
|
+
}
|
|
81
|
+
// Output dir doesn't exist — check common alternatives
|
|
82
|
+
const alternatives = ['dist', 'build', 'out', '.next', 'public'];
|
|
83
|
+
for (const alt of alternatives) {
|
|
84
|
+
if (existsSync(join(projectDir, alt))) {
|
|
85
|
+
emit({ step: 'build', status: 'done', message: `Build complete — output found at ${alt} (expected ${config.outputDir})` });
|
|
86
|
+
return { success: true, outputDir: alt };
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
emit({ step: 'build', status: 'error', message: `Build command succeeded but output directory "${config.outputDir}" not found` });
|
|
90
|
+
return { success: false, outputDir: config.outputDir, error: `Build output directory "${config.outputDir}" not found after build` };
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
const message = err.message;
|
|
94
|
+
emit({ step: 'build', status: 'error', message: 'Build failed', detail: message });
|
|
95
|
+
return { success: false, outputDir: config.outputDir, error: message };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get the expected build output directory for a framework.
|
|
100
|
+
* Used by deploy steps that need to know where to find build artifacts.
|
|
101
|
+
*/
|
|
102
|
+
export function getBuildOutputDir(framework) {
|
|
103
|
+
return (FRAMEWORK_BUILDS[framework] || DEFAULT_BUILD).outputDir;
|
|
104
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tuvok's Campaign Proposer — generates data-driven campaign proposals (v12.1).
|
|
3
|
+
*
|
|
4
|
+
* Takes the situation model (with Seven's gap analysis) and generates a
|
|
5
|
+
* complete campaign proposal: name, missions, predicted impact, risk, alternatives.
|
|
6
|
+
*
|
|
7
|
+
* PRD Reference: ROADMAP v12.1, DEEP_CURRENT.md PROPOSE step
|
|
8
|
+
*/
|
|
9
|
+
import type { SituationModel } from './deep-current.js';
|
|
10
|
+
interface CampaignProposal {
|
|
11
|
+
id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
generatedAt: string;
|
|
14
|
+
trigger: string;
|
|
15
|
+
dimension: string;
|
|
16
|
+
dimensionScore: number;
|
|
17
|
+
theCase: string;
|
|
18
|
+
missions: ProposedMission[];
|
|
19
|
+
expectedImpact: string;
|
|
20
|
+
riskAssessment: string;
|
|
21
|
+
alternativesConsidered: string[];
|
|
22
|
+
autonomyRecommendation: 1 | 2 | 3;
|
|
23
|
+
estimatedSessions: number;
|
|
24
|
+
}
|
|
25
|
+
interface ProposedMission {
|
|
26
|
+
number: number;
|
|
27
|
+
name: string;
|
|
28
|
+
objective: string;
|
|
29
|
+
estimatedFiles: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Generate a campaign proposal targeting the weakest dimension.
|
|
33
|
+
*/
|
|
34
|
+
export declare function generateProposal(model: SituationModel): CampaignProposal;
|
|
35
|
+
/**
|
|
36
|
+
* Save a proposal to disk as markdown.
|
|
37
|
+
*/
|
|
38
|
+
export declare function saveProposal(proposal: CampaignProposal): Promise<string>;
|
|
39
|
+
export type { CampaignProposal, ProposedMission };
|