mirror of
https://github.com/saymrwulf/BraiinsRatchet.git
synced 2026-05-14 20:37:52 +00:00
Add app reality mirror layer
This commit is contained in:
parent
2c3308a69a
commit
a77493fb3f
11 changed files with 620 additions and 5 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -6,6 +6,7 @@ __pycache__/
|
|||
data/*.sqlite
|
||||
data/*.sqlite-shm
|
||||
data/*.sqlite-wal
|
||||
data/app_visual_state.*
|
||||
data/raw/
|
||||
*.log
|
||||
macos/BraiinsRatchet/.build/
|
||||
|
|
|
|||
13
README.md
13
README.md
|
|
@ -46,6 +46,19 @@ This builds `macos/build/Braiins Ratchet.app`, closes any stale `BraiinsRatchetM
|
|||
|
||||
The app is a native Tahoe Flight Deck: animated hashfield background, real SwiftUI Liquid Glass controls, Hashflow, Ratchet, Bid Lab, Exposure, and Evidence. The design rationale is in `docs/APP_DESIGN_RESEARCH.md`.
|
||||
|
||||
The app also has a `Reality Mirror` self-reflection layer. It writes the exact semantic state the SwiftUI app believes it is showing to:
|
||||
|
||||
```text
|
||||
data/app_visual_state.md
|
||||
data/app_visual_state.json
|
||||
```
|
||||
|
||||
Print the latest mirror snapshot:
|
||||
|
||||
```bash
|
||||
./scripts/ratchet mirror
|
||||
```
|
||||
|
||||
Advanced fallback for a 6-hour CLI monitoring session:
|
||||
|
||||
```bash
|
||||
|
|
|
|||
|
|
@ -76,6 +76,20 @@ The app is organized as:
|
|||
4. `Bid Lab`: shadow order, expected net, breakeven, and loss boundary.
|
||||
5. `Exposure`: record or close manually executed Braiins exposure.
|
||||
6. `Evidence`: raw cockpit, report, and ledger artifacts for diagnostics.
|
||||
7. `Reality Mirror`: self-reflective BED view that shows what the app believes it is rendering right now.
|
||||
|
||||
The small `Reality Mirror` HUD writes the current visual/operator truth to:
|
||||
|
||||
```text
|
||||
data/app_visual_state.md
|
||||
data/app_visual_state.json
|
||||
```
|
||||
|
||||
If you ask for help, this file is the fastest way to show the exact app state instead of describing it from memory:
|
||||
|
||||
```bash
|
||||
./scripts/ratchet mirror
|
||||
```
|
||||
|
||||
## Research Pathway
|
||||
|
||||
|
|
@ -140,6 +154,7 @@ Use these only if the native app cannot be opened or you are debugging:
|
|||
./scripts/ratchet position list
|
||||
./scripts/ratchet report
|
||||
./scripts/ratchet experiments
|
||||
./scripts/ratchet mirror
|
||||
./scripts/ratchet guide
|
||||
./scripts/ratchet operator-guide
|
||||
```
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ Use `./scripts/ratchet guide` for the user-facing operating story.
|
|||
|
||||
Use `./scripts/ratchet operator-guide` for architecture, installation, migration, backup, recovery, and diagnostics.
|
||||
|
||||
Use `./scripts/ratchet mirror` to print the native app's latest self-written visual-state snapshot from `data/app_visual_state.md`.
|
||||
|
||||
The raw Python CLI is documented below for debugging and development.
|
||||
|
||||
All raw commands should be run from the repository root.
|
||||
|
|
@ -50,6 +52,16 @@ These are wrapper commands, not raw Python subcommands:
|
|||
|
||||
`operator-guide` prints `docs/OPERATOR_GUIDE.md`.
|
||||
|
||||
## Wrapper Reality Mirror Command
|
||||
|
||||
This is a wrapper command, not a raw Python subcommand:
|
||||
|
||||
```bash
|
||||
./scripts/ratchet mirror
|
||||
```
|
||||
|
||||
It prints `data/app_visual_state.md`, which is written by the SwiftUI app whenever it refreshes state or changes visible sections. If no snapshot exists yet, open the app with `./scripts/ratchet app` and refresh or open `Reality Mirror`.
|
||||
|
||||
## `pipeline`
|
||||
|
||||
Prints a monitor-only automation proposal and asks for `yes` or `no`.
|
||||
|
|
|
|||
|
|
@ -43,7 +43,8 @@ The current stack is:
|
|||
6. SQLite durable state at `data/ratchet.sqlite`.
|
||||
7. Markdown evidence reports under `reports/`.
|
||||
8. Bash launchers in `scripts/`.
|
||||
9. Git and GitHub on branch `master`.
|
||||
9. SwiftUI self-reflection snapshots at `data/app_visual_state.md` and `data/app_visual_state.json`.
|
||||
10. Git and GitHub on branch `master`.
|
||||
|
||||
### Runtime Layers
|
||||
|
||||
|
|
@ -71,6 +72,10 @@ Layer 6 is the background engine.
|
|||
|
||||
`src/braiins_ratchet/engine.py` starts a detached monitor-only supervisor, writes `data/supervisor.pid`, and logs to `logs/supervisor.log`.
|
||||
|
||||
Layer 7 is the visual self-reflection layer.
|
||||
|
||||
The SwiftUI app renders a `Reality Mirror` HUD and tab. It writes the semantic state it believes it is showing to `data/app_visual_state.md` and `data/app_visual_state.json`. This is not screenshot OCR; it is the app's own rendered-state ledger.
|
||||
|
||||
### Data Flow
|
||||
|
||||
Normal data flow:
|
||||
|
|
@ -105,8 +110,10 @@ Operational files:
|
|||
1. `data/supervisor.pid`: PID for the background engine.
|
||||
2. `logs/supervisor.log`: background engine output.
|
||||
3. `reports/ACTIVE_WATCH.json`: marker for a running watch.
|
||||
4. `.venv`: local Python environment, disposable.
|
||||
5. `macos/build/Braiins Ratchet.app`: generated app bundle, disposable.
|
||||
4. `data/app_visual_state.md`: latest human-readable visual self-reflection snapshot.
|
||||
5. `data/app_visual_state.json`: latest machine-readable visual self-reflection snapshot.
|
||||
6. `.venv`: local Python environment, disposable.
|
||||
7. `macos/build/Braiins Ratchet.app`: generated app bundle, disposable.
|
||||
|
||||
Source files:
|
||||
|
||||
|
|
@ -559,6 +566,12 @@ Check app state:
|
|||
./scripts/ratchet app-state
|
||||
```
|
||||
|
||||
Check what the visible app surface believes it is showing:
|
||||
|
||||
```bash
|
||||
./scripts/ratchet mirror
|
||||
```
|
||||
|
||||
Check latest plain report:
|
||||
|
||||
```bash
|
||||
|
|
|
|||
|
|
@ -73,9 +73,44 @@ The normal app tabs are:
|
|||
4. `Bid Lab`: shadow order, breakeven, expected net, and loss budget.
|
||||
5. `Exposure`: manual Braiins position recorder.
|
||||
6. `Evidence`: raw reports and diagnostic text.
|
||||
7. `Reality Mirror`: the app's self-reflective BED view.
|
||||
|
||||
If you are unsure, stay on `Flight Deck`.
|
||||
|
||||
## Reality Mirror
|
||||
|
||||
The `Reality Mirror` is the app looking at itself.
|
||||
|
||||
BED means `Backstage Evidence Deck`.
|
||||
|
||||
It exists because generic advice is not enough. The app writes what it believes it is rendering right now:
|
||||
|
||||
1. Visible section.
|
||||
2. Giant decision word.
|
||||
3. Control owner.
|
||||
4. Next action.
|
||||
5. Engine state.
|
||||
6. Strategy action.
|
||||
7. Braiins freshness.
|
||||
8. Active watch, cooldown, or manual exposure.
|
||||
9. Buttons it believes are visible.
|
||||
10. Operator truths for the current state.
|
||||
|
||||
The files are:
|
||||
|
||||
```text
|
||||
data/app_visual_state.md
|
||||
data/app_visual_state.json
|
||||
```
|
||||
|
||||
If you ask for help, run:
|
||||
|
||||
```bash
|
||||
./scripts/ratchet mirror
|
||||
```
|
||||
|
||||
That prints the latest self-written visual state, so the helper can reason about what is actually on your app surface.
|
||||
|
||||
## Flight Deck Reading Order
|
||||
|
||||
Read the screen in this order every time:
|
||||
|
|
@ -333,8 +368,9 @@ Use this order:
|
|||
2. `Ratchet`: where the experiment is in the loop.
|
||||
3. `Bid Lab`: why the current proposal exists.
|
||||
4. `Exposure`: whether real money blocks new experiments.
|
||||
5. `Evidence`: raw report and ledger.
|
||||
6. `docs/OPERATOR_GUIDE.md`: installation, recovery, migration, and diagnostics.
|
||||
5. `Reality Mirror`: what the app believes it is showing right now.
|
||||
6. `Evidence`: raw report and ledger.
|
||||
7. `docs/OPERATOR_GUIDE.md`: installation, recovery, migration, and diagnostics.
|
||||
|
||||
## Glossary
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ This builds `macos/build/Braiins Ratchet.app`, closes any stale `BraiinsRatchetM
|
|||
- Forever Engine controls for the monitor-only background lifecycle.
|
||||
- Manual exposure recording and closing controls.
|
||||
- Evidence view for raw artifacts and backend diagnostics.
|
||||
- Reality Mirror BED layer plus `data/app_visual_state.md/json` self-reflection snapshots.
|
||||
- Monitor-only. It never places Braiins orders.
|
||||
|
||||
## Product Direction
|
||||
|
|
|
|||
|
|
@ -112,6 +112,17 @@ final class RatchetStore: ObservableObject {
|
|||
closePositionId = ""
|
||||
}
|
||||
|
||||
func writeRealitySnapshot(section: AppSection?) {
|
||||
let reality = RenderedReality.make(
|
||||
section: section ?? .deck,
|
||||
appState: appState,
|
||||
isWorking: isWorking,
|
||||
operation: operation,
|
||||
errorMessage: errorMessage
|
||||
)
|
||||
RealitySnapshotWriter.write(reality)
|
||||
}
|
||||
|
||||
private func run(label: String, arguments: [String], refreshAfterwards: Bool) async {
|
||||
operation = label
|
||||
rawTitle = label
|
||||
|
|
@ -135,12 +146,22 @@ struct FlightDeckApp: View {
|
|||
root
|
||||
.task {
|
||||
await store.refresh()
|
||||
store.writeRealitySnapshot(section: selection)
|
||||
}
|
||||
.onAppear {
|
||||
withAnimation(.easeInOut(duration: 4.8).repeatForever(autoreverses: true)) {
|
||||
pulse = true
|
||||
}
|
||||
}
|
||||
.onChange(of: selection) { _, newValue in
|
||||
store.writeRealitySnapshot(section: newValue)
|
||||
}
|
||||
.onChange(of: store.appState?.generatedAt) { _, _ in
|
||||
store.writeRealitySnapshot(section: selection)
|
||||
}
|
||||
.onChange(of: store.operation) { _, _ in
|
||||
store.writeRealitySnapshot(section: selection)
|
||||
}
|
||||
}
|
||||
|
||||
private var root: some View {
|
||||
|
|
@ -158,6 +179,17 @@ struct FlightDeckApp: View {
|
|||
selectedView
|
||||
.safeAreaPadding(.horizontal, 30)
|
||||
.safeAreaPadding(.vertical, 24)
|
||||
VStack {
|
||||
Spacer()
|
||||
HStack {
|
||||
Spacer()
|
||||
RealityHUD(store: store, section: selection ?? .deck) {
|
||||
selection = .mirror
|
||||
}
|
||||
.padding(.trailing, 24)
|
||||
.padding(.bottom, 20)
|
||||
}
|
||||
}
|
||||
}
|
||||
.toolbar { toolbarContent }
|
||||
.searchable(text: $store.query, placement: .toolbar, prompt: "Search reports, prices, OCEAN, Braiins")
|
||||
|
|
@ -218,6 +250,8 @@ struct FlightDeckApp: View {
|
|||
ExposureView(store: store)
|
||||
case .vault:
|
||||
EvidenceVaultView(store: store)
|
||||
case .mirror:
|
||||
RealityMirrorView(store: store, section: selection ?? .mirror)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -229,6 +263,7 @@ enum AppSection: String, CaseIterable, Identifiable {
|
|||
case bidlab
|
||||
case exposure
|
||||
case vault
|
||||
case mirror
|
||||
|
||||
var id: String { rawValue }
|
||||
|
||||
|
|
@ -240,6 +275,7 @@ enum AppSection: String, CaseIterable, Identifiable {
|
|||
case .bidlab: "Bid Lab"
|
||||
case .exposure: "Exposure"
|
||||
case .vault: "Evidence"
|
||||
case .mirror: "Reality Mirror"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -251,6 +287,7 @@ enum AppSection: String, CaseIterable, Identifiable {
|
|||
case .bidlab: "shadow order optics"
|
||||
case .exposure: "manual position lock"
|
||||
case .vault: "reports and raw state"
|
||||
case .mirror: "BED: app sees itself"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -262,6 +299,7 @@ enum AppSection: String, CaseIterable, Identifiable {
|
|||
case .bidlab: "slider.horizontal.3"
|
||||
case .exposure: "lock.shield"
|
||||
case .vault: "archivebox"
|
||||
case .mirror: "eye.square"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1089,6 +1127,156 @@ struct EvidenceVaultView: View {
|
|||
}
|
||||
}
|
||||
|
||||
struct RealityHUD: View {
|
||||
@ObservedObject var store: RatchetStore
|
||||
let section: AppSection
|
||||
let openMirror: () -> Void
|
||||
|
||||
private var reality: RenderedReality {
|
||||
RenderedReality.make(
|
||||
section: section,
|
||||
appState: store.appState,
|
||||
isWorking: store.isWorking,
|
||||
operation: store.operation,
|
||||
errorMessage: store.errorMessage
|
||||
)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
LiquidGlassSurface(tint: .white.opacity(0.10), cornerRadius: 24) {
|
||||
VStack(alignment: .leading, spacing: 10) {
|
||||
HStack {
|
||||
Label("Reality Mirror", systemImage: "eye")
|
||||
.font(.caption.weight(.heavy))
|
||||
.textCase(.uppercase)
|
||||
.foregroundStyle(.secondary)
|
||||
Spacer()
|
||||
Button("Open") {
|
||||
openMirror()
|
||||
}
|
||||
.buttonStyle(.glass)
|
||||
.controlSize(.small)
|
||||
}
|
||||
Text(reality.decisionTitle)
|
||||
.font(.title2.weight(.black))
|
||||
.foregroundStyle(reality.decisionTint)
|
||||
Text(reality.currentInstruction)
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.lineLimit(3)
|
||||
Text("writes data/app_visual_state.md")
|
||||
.font(.caption2.monospaced())
|
||||
.foregroundStyle(.tertiary)
|
||||
}
|
||||
.padding(14)
|
||||
.frame(width: 330, alignment: .leading)
|
||||
}
|
||||
.accessibilityLabel("Reality Mirror heads-up display, current decision \(reality.decisionTitle)")
|
||||
}
|
||||
}
|
||||
|
||||
struct RealityMirrorView: View {
|
||||
@ObservedObject var store: RatchetStore
|
||||
let section: AppSection
|
||||
|
||||
private var reality: RenderedReality {
|
||||
RenderedReality.make(
|
||||
section: section,
|
||||
appState: store.appState,
|
||||
isWorking: store.isWorking,
|
||||
operation: store.operation,
|
||||
errorMessage: store.errorMessage
|
||||
)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
VStack(alignment: .leading, spacing: 22) {
|
||||
SectionHeader("Reality Mirror", "BED: Backstage Evidence Deck. This is the app reflecting the concrete state it is rendering now, not generic advice.")
|
||||
|
||||
HStack(alignment: .top, spacing: 18) {
|
||||
LiquidGlassSurface(tint: reality.decisionTint.opacity(0.22), cornerRadius: 38) {
|
||||
VStack(alignment: .leading, spacing: 14) {
|
||||
Label("What I am showing", systemImage: "eye.fill")
|
||||
.font(.title2.weight(.black))
|
||||
Text(reality.decisionTitle)
|
||||
.font(.system(size: 56, weight: .black, design: .rounded))
|
||||
.foregroundStyle(reality.decisionTint)
|
||||
Text(reality.decisionExplanation)
|
||||
.font(.title3.weight(.semibold))
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
Text(reality.currentInstruction)
|
||||
.font(.callout)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
.padding(24)
|
||||
}
|
||||
|
||||
LiquidGlassSurface(tint: .cyan.opacity(0.16), cornerRadius: 38) {
|
||||
VStack(alignment: .leading, spacing: 14) {
|
||||
Label("Snapshot artifact", systemImage: "doc.text.magnifyingglass")
|
||||
.font(.title2.weight(.black))
|
||||
Text("The SwiftUI app writes exactly this semantic view state into the repo.")
|
||||
.font(.callout)
|
||||
.foregroundStyle(.secondary)
|
||||
Button {
|
||||
store.writeRealitySnapshot(section: section)
|
||||
} label: {
|
||||
Label("Write Snapshot Now", systemImage: "square.and.arrow.down")
|
||||
}
|
||||
.buttonStyle(.glassProminent)
|
||||
.tint(.cyan)
|
||||
Text("data/app_visual_state.md\n data/app_visual_state.json")
|
||||
.font(.body.monospaced())
|
||||
.foregroundStyle(.secondary)
|
||||
.textSelection(.enabled)
|
||||
}
|
||||
.padding(24)
|
||||
}
|
||||
}
|
||||
|
||||
LiquidGlassSurface(tint: .white.opacity(0.08), cornerRadius: 34) {
|
||||
VStack(alignment: .leading, spacing: 14) {
|
||||
Label("Current visible facts", systemImage: "list.bullet.rectangle")
|
||||
.font(.title2.weight(.black))
|
||||
ValueGrid(rows: reality.factGridRows)
|
||||
}
|
||||
.padding(22)
|
||||
}
|
||||
|
||||
LiquidGlassSurface(tint: .green.opacity(0.12), cornerRadius: 34) {
|
||||
VStack(alignment: .leading, spacing: 14) {
|
||||
Label("Buttons I believe are visible", systemImage: "cursorarrow.click.2")
|
||||
.font(.title2.weight(.black))
|
||||
ForEach(reality.visibleButtons, id: \.self) { button in
|
||||
Text(button)
|
||||
.font(.body.monospaced())
|
||||
.textSelection(.enabled)
|
||||
}
|
||||
}
|
||||
.padding(22)
|
||||
}
|
||||
|
||||
LiquidGlassSurface(tint: .orange.opacity(0.12), cornerRadius: 34) {
|
||||
VStack(alignment: .leading, spacing: 14) {
|
||||
Label("Operator truth", systemImage: "exclamationmark.shield")
|
||||
.font(.title2.weight(.black))
|
||||
ForEach(reality.operatorTruths, id: \.self) { truth in
|
||||
Text(truth)
|
||||
.font(.callout)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
}
|
||||
.padding(22)
|
||||
}
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
store.writeRealitySnapshot(section: section)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SectionHeader: View {
|
||||
let title: String
|
||||
let subtitle: String
|
||||
|
|
@ -1323,6 +1511,305 @@ enum ControlOwner {
|
|||
}
|
||||
}
|
||||
|
||||
struct RealityRow: Codable, Hashable {
|
||||
let label: String
|
||||
let value: String
|
||||
let unit: String
|
||||
}
|
||||
|
||||
struct RenderedReality: Codable {
|
||||
let snapshotGeneratedAt: String
|
||||
let source: String
|
||||
let visibleSection: String
|
||||
let visibleSectionSubtitle: String
|
||||
let decisionTitle: String
|
||||
let decisionExplanation: String
|
||||
let controlTitle: String
|
||||
let controlDetail: String
|
||||
let nextTitle: String
|
||||
let nextDetail: String
|
||||
let currentInstruction: String
|
||||
let engineRunning: Bool
|
||||
let engineDetail: String
|
||||
let operation: String
|
||||
let errorMessage: String
|
||||
let latestStrategyAction: String
|
||||
let latestReport: String
|
||||
let activeWatch: String
|
||||
let completedWatch: String
|
||||
let activeManualExposure: String
|
||||
let braiinsFreshness: String
|
||||
let latestOceanSample: String
|
||||
let latestBraiinsSample: String
|
||||
let instrumentRows: [RealityRow]
|
||||
let visibleButtons: [String]
|
||||
let operatorTruths: [String]
|
||||
|
||||
var factRows: [RealityRow] {
|
||||
[
|
||||
RealityRow(label: "visible section", value: visibleSection, unit: "screen"),
|
||||
RealityRow(label: "decision", value: decisionTitle, unit: "giant word"),
|
||||
RealityRow(label: "control", value: controlTitle, unit: "owner"),
|
||||
RealityRow(label: "next", value: nextTitle, unit: "action"),
|
||||
RealityRow(label: "engine", value: engineRunning ? "running" : "stopped", unit: "state"),
|
||||
RealityRow(label: "strategy", value: latestStrategyAction, unit: "proposal"),
|
||||
RealityRow(label: "braiins", value: braiinsFreshness, unit: "freshness"),
|
||||
RealityRow(label: "manual exposure", value: activeManualExposure, unit: "blocker"),
|
||||
] + instrumentRows
|
||||
}
|
||||
|
||||
var factGridRows: [(String, String, String)] {
|
||||
factRows.map { ($0.label, $0.value, $0.unit) }
|
||||
}
|
||||
|
||||
var decisionTint: Color {
|
||||
switch decisionTitle {
|
||||
case "ENGINE LIVE", "REFRESH", "WATCH", "REVIEW":
|
||||
.green
|
||||
case "WORKING", "HOLD", "WAIT", "COOLDOWN":
|
||||
.orange
|
||||
default:
|
||||
.secondary
|
||||
}
|
||||
}
|
||||
|
||||
static func make(
|
||||
section: AppSection,
|
||||
appState: AppStatePayload?,
|
||||
isWorking: Bool,
|
||||
operation: String?,
|
||||
errorMessage: String?
|
||||
) -> RenderedReality {
|
||||
let decision = Decision.from(appState, isWorking: isWorking)
|
||||
let control = ControlOwner.from(appState, isWorking: isWorking)
|
||||
let next = nextAction(appState)
|
||||
let latest = appState?.latest
|
||||
let operatorState = appState?.operatorState
|
||||
let engineStatus = appState?.engineStatus
|
||||
let activePositions = operatorState?.activeManualPositions ?? []
|
||||
let completedWatch = operatorState?.completedWatch
|
||||
let buttons = visibleButtons(section: section, appState: appState, isWorking: isWorking)
|
||||
let truths = operatorTruths(
|
||||
decision: decision,
|
||||
appState: appState,
|
||||
activePositions: activePositions,
|
||||
completedWatch: completedWatch
|
||||
)
|
||||
|
||||
return RenderedReality(
|
||||
snapshotGeneratedAt: ISO8601DateFormatter().string(from: Date()),
|
||||
source: "SwiftUI rendered semantic state; this is not a screenshot or generic documentation.",
|
||||
visibleSection: section.title,
|
||||
visibleSectionSubtitle: section.subtitle,
|
||||
decisionTitle: decision.title,
|
||||
decisionExplanation: decision.explanation,
|
||||
controlTitle: control.title,
|
||||
controlDetail: control.detail,
|
||||
nextTitle: next.title,
|
||||
nextDetail: next.detail,
|
||||
currentInstruction: next.instruction,
|
||||
engineRunning: engineStatus?.running == true,
|
||||
engineDetail: engineStatus?.detail ?? "engine state not loaded",
|
||||
operation: operation ?? "none",
|
||||
errorMessage: errorMessage ?? "none",
|
||||
latestStrategyAction: operatorState?.action ?? "none",
|
||||
latestReport: operatorState?.latestReport ?? "none",
|
||||
activeWatch: operatorState?.activeWatch ?? "none",
|
||||
completedWatch: completedWatch.map { "\($0.reportPath), remaining \($0.remainingMinutes)m, earliest \($0.earliestActionLocal)" } ?? "none",
|
||||
activeManualExposure: activePositions.isEmpty ? "none" : activePositions.joined(separator: "; "),
|
||||
braiinsFreshness: freshnessText(operatorState),
|
||||
latestOceanSample: operatorState?.latestOceanTimestamp ?? "none",
|
||||
latestBraiinsSample: operatorState?.latestMarketTimestamp ?? "none",
|
||||
instrumentRows: [
|
||||
RealityRow(label: "braiins price", value: marketValue(latest, "fillable_price_btc_per_eh_day", fallback: marketValue(latest, "best_ask_btc_per_eh_day")), unit: "BTC/EH/day"),
|
||||
RealityRow(label: "ocean hashrate", value: oceanValue(latest, "pool_hashrate_eh_s"), unit: "EH/s"),
|
||||
RealityRow(label: "pool window", value: oceanValue(latest, "avg_block_time_hours"), unit: "h/block"),
|
||||
RealityRow(label: "expected net", value: sats(proposalValue(latest, "expected_net_btc")), unit: "model"),
|
||||
],
|
||||
visibleButtons: buttons,
|
||||
operatorTruths: truths
|
||||
)
|
||||
}
|
||||
|
||||
private static func nextAction(_ appState: AppStatePayload?) -> (title: String, detail: String, instruction: String) {
|
||||
guard let state = appState else {
|
||||
return ("Load state", "Reading durable SQLite state.", "Wait for the app-state load to finish.")
|
||||
}
|
||||
if state.engineStatus.running {
|
||||
return (
|
||||
"Engine owns it",
|
||||
"No babysitting. The background engine waits, samples, watches, and writes evidence.",
|
||||
"Do nothing unless you intentionally want to stop the engine or record manual exposure."
|
||||
)
|
||||
}
|
||||
if state.operatorState.activeWatch != nil {
|
||||
return (
|
||||
"Wait for watch",
|
||||
"A passive watch is already running.",
|
||||
"Do not start another watch. Wait for the current run report."
|
||||
)
|
||||
}
|
||||
if let watch = state.operatorState.completedWatch {
|
||||
return (
|
||||
"Wait \(watch.remainingMinutes)m",
|
||||
"Earliest useful action: \(watch.earliestActionLocal).",
|
||||
"Cooldown is active. Do not repeat the same experiment yet."
|
||||
)
|
||||
}
|
||||
if !state.operatorState.activeManualPositions.isEmpty {
|
||||
return (
|
||||
"Hold exposure",
|
||||
"A manually recorded Braiins position blocks new experiments.",
|
||||
"Supervise the real position. Close it only when it is truly finished."
|
||||
)
|
||||
}
|
||||
let step = state.automationPlan.steps.first ?? "No passive action is useful right now."
|
||||
return (state.automationPlan.title, step, step)
|
||||
}
|
||||
|
||||
private static func visibleButtons(section: AppSection, appState: AppStatePayload?, isWorking: Bool) -> [String] {
|
||||
var buttons = ["Toolbar: Refresh"]
|
||||
if appState?.engineStatus.running == true {
|
||||
buttons.append("Toolbar: Stop Engine")
|
||||
} else {
|
||||
buttons.append("Toolbar: Start Engine")
|
||||
}
|
||||
switch section {
|
||||
case .deck:
|
||||
buttons.append(contentsOf: ["Flight Deck: Start Forever Engine", "Flight Deck: Stop", "Flight Deck: One Sample"])
|
||||
case .exposure:
|
||||
buttons.append(contentsOf: ["Exposure: Record Exposure", "Exposure: Close Exposure"])
|
||||
case .vault:
|
||||
buttons.append(contentsOf: ["Evidence: Cockpit", "Evidence: Report", "Evidence: Ledger"])
|
||||
case .mirror:
|
||||
buttons.append("Reality Mirror: Write Snapshot Now")
|
||||
default:
|
||||
break
|
||||
}
|
||||
if isWorking {
|
||||
buttons.append("State: some buttons are disabled because an operation is running")
|
||||
}
|
||||
return buttons
|
||||
}
|
||||
|
||||
private static func operatorTruths(
|
||||
decision: Decision,
|
||||
appState: AppStatePayload?,
|
||||
activePositions: [String],
|
||||
completedWatch: CompletedWatchPayload?
|
||||
) -> [String] {
|
||||
if appState == nil {
|
||||
return ["The app has not loaded structured backend state yet."]
|
||||
}
|
||||
if !activePositions.isEmpty {
|
||||
return [
|
||||
"Real manual exposure is recorded.",
|
||||
"New watch experiments should remain blocked until the exposure is closed."
|
||||
]
|
||||
}
|
||||
if appState?.engineStatus.running == true {
|
||||
return [
|
||||
"The forever engine owns passive research.",
|
||||
"The safest operator workload is zero unless you need to record real exposure."
|
||||
]
|
||||
}
|
||||
if let completedWatch {
|
||||
return [
|
||||
"A watch already produced evidence.",
|
||||
"Earliest useful next action is \(completedWatch.earliestActionLocal)."
|
||||
]
|
||||
}
|
||||
switch decision {
|
||||
case .watch:
|
||||
return ["A passive watch or the forever engine is the current research action; no BTC is spent by the app."]
|
||||
case .review:
|
||||
return ["Manual review is required before any Braiins action; the app still cannot spend BTC."]
|
||||
case .observe:
|
||||
return ["No useful action window is visible; doing nothing is the intended action."]
|
||||
default:
|
||||
return [decision.explanation]
|
||||
}
|
||||
}
|
||||
|
||||
private static func freshnessText(_ state: OperatorStatePayload?) -> String {
|
||||
guard let minutes = state?.freshnessMinutes else { return "unknown" }
|
||||
return minutes <= 30 ? "fresh (\(minutes)m)" : "stale (\(minutes)m)"
|
||||
}
|
||||
|
||||
private static func marketValue(_ latest: LatestPayload?, _ key: String, fallback: String = "n/a") -> String {
|
||||
latest?.market?[key]?.description ?? fallback
|
||||
}
|
||||
|
||||
private static func oceanValue(_ latest: LatestPayload?, _ key: String) -> String {
|
||||
latest?.ocean?[key]?.description ?? "n/a"
|
||||
}
|
||||
|
||||
private static func proposalValue(_ latest: LatestPayload?, _ key: String) -> String {
|
||||
latest?.proposal?[key]?.description ?? "n/a"
|
||||
}
|
||||
}
|
||||
|
||||
enum RealitySnapshotWriter {
|
||||
static func write(_ reality: RenderedReality) {
|
||||
guard let repoRoot = RatchetProcess.repoRootURL() else { return }
|
||||
let dataDir = repoRoot.appendingPathComponent("data", isDirectory: true)
|
||||
do {
|
||||
try FileManager.default.createDirectory(at: dataDir, withIntermediateDirectories: true)
|
||||
let encoder = JSONEncoder()
|
||||
encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
|
||||
let jsonData = try encoder.encode(reality)
|
||||
try jsonData.write(to: dataDir.appendingPathComponent("app_visual_state.json"), options: .atomic)
|
||||
try renderMarkdown(reality).write(
|
||||
to: dataDir.appendingPathComponent("app_visual_state.md"),
|
||||
atomically: true,
|
||||
encoding: .utf8
|
||||
)
|
||||
} catch {
|
||||
// This is diagnostic output only. UI operation must never fail because the mirror file cannot be written.
|
||||
}
|
||||
}
|
||||
|
||||
private static func renderMarkdown(_ reality: RenderedReality) -> String {
|
||||
var lines = [
|
||||
"# App Visual State",
|
||||
"",
|
||||
"This file is written by the SwiftUI app. It records the app's semantic rendered state, not generic documentation.",
|
||||
"",
|
||||
"- snapshot_generated_at: \(reality.snapshotGeneratedAt)",
|
||||
"- visible_section: \(reality.visibleSection)",
|
||||
"- decision: \(reality.decisionTitle)",
|
||||
"- decision_explanation: \(reality.decisionExplanation)",
|
||||
"- control: \(reality.controlTitle)",
|
||||
"- control_detail: \(reality.controlDetail)",
|
||||
"- next: \(reality.nextTitle)",
|
||||
"- next_detail: \(reality.nextDetail)",
|
||||
"- current_instruction: \(reality.currentInstruction)",
|
||||
"- engine_running: \(reality.engineRunning ? "yes" : "no")",
|
||||
"- engine_detail: \(reality.engineDetail)",
|
||||
"- operation: \(reality.operation)",
|
||||
"- error_message: \(reality.errorMessage)",
|
||||
"- latest_strategy_action: \(reality.latestStrategyAction)",
|
||||
"- braiins_freshness: \(reality.braiinsFreshness)",
|
||||
"- latest_ocean_sample: \(reality.latestOceanSample)",
|
||||
"- latest_braiins_sample: \(reality.latestBraiinsSample)",
|
||||
"- latest_report: \(reality.latestReport)",
|
||||
"- active_watch: \(reality.activeWatch)",
|
||||
"- completed_watch: \(reality.completedWatch)",
|
||||
"- active_manual_exposure: \(reality.activeManualExposure)",
|
||||
"",
|
||||
"## Instruments",
|
||||
"",
|
||||
]
|
||||
lines.append(contentsOf: reality.instrumentRows.map { "- \($0.label): \($0.value) \($0.unit)" })
|
||||
lines.append(contentsOf: ["", "## Visible Buttons", ""])
|
||||
lines.append(contentsOf: reality.visibleButtons.map { "- \($0)" })
|
||||
lines.append(contentsOf: ["", "## Operator Truths", ""])
|
||||
lines.append(contentsOf: reality.operatorTruths.map { "- \($0)" })
|
||||
lines.append("")
|
||||
return lines.joined(separator: "\n")
|
||||
}
|
||||
}
|
||||
|
||||
enum ResearchPhase {
|
||||
case loading
|
||||
case refresh
|
||||
|
|
@ -1561,6 +2048,10 @@ enum AppIconFactory {
|
|||
}
|
||||
|
||||
enum RatchetProcess {
|
||||
static func repoRootURL() -> URL? {
|
||||
findRepoRoot()
|
||||
}
|
||||
|
||||
static func loadAppState() async -> AppStateLoadResult {
|
||||
await Task.detached {
|
||||
guard let repoRoot = findRepoRoot() else {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ Commands:
|
|||
supervise Run the durable forever lifecycle supervisor.
|
||||
engine Start/stop/status for the background monitor engine.
|
||||
app Build and open the native macOS app.
|
||||
mirror Print the app's latest self-written visual-state snapshot.
|
||||
position Record/list/close manually executed Braiins exposure.
|
||||
report Print the latest stored report without fetching new data.
|
||||
app-state Print structured JSON for the native macOS app.
|
||||
|
|
@ -36,6 +37,7 @@ Examples:
|
|||
./scripts/ratchet supervise
|
||||
./scripts/ratchet engine status
|
||||
./scripts/ratchet app
|
||||
./scripts/ratchet mirror
|
||||
./scripts/ratchet position list
|
||||
./scripts/ratchet report
|
||||
./scripts/ratchet experiments
|
||||
|
|
@ -142,6 +144,17 @@ cmd_app() {
|
|||
open "$app_path"
|
||||
}
|
||||
|
||||
cmd_mirror() {
|
||||
local path="$ROOT_DIR/data/app_visual_state.md"
|
||||
if [[ ! -f "$path" ]]; then
|
||||
echo "No app visual-state snapshot exists yet."
|
||||
echo "Open the native app with: ./scripts/ratchet app"
|
||||
echo "Then refresh or open the Reality Mirror tab."
|
||||
return 0
|
||||
fi
|
||||
cat "$path"
|
||||
}
|
||||
|
||||
cmd_position() {
|
||||
run_python -m braiins_ratchet.cli position "$@"
|
||||
}
|
||||
|
|
@ -194,6 +207,7 @@ main() {
|
|||
supervise|daemon) cmd_supervise "$@" ;;
|
||||
engine) cmd_engine "$@" ;;
|
||||
app|mac-app) cmd_app "$@" ;;
|
||||
mirror|reality) cmd_mirror "$@" ;;
|
||||
position|positions) cmd_position "$@" ;;
|
||||
report) cmd_report "$@" ;;
|
||||
app-state) cmd_app_state "$@" ;;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@ class DocumentationContractTests(unittest.TestCase):
|
|||
self.assertIn("Immediate", text)
|
||||
self.assertIn("Midterm", text)
|
||||
self.assertIn("Longterm", text)
|
||||
self.assertIn("Reality Mirror", text)
|
||||
self.assertIn("Backstage Evidence Deck", text)
|
||||
self.assertIn("data/app_visual_state.md", text)
|
||||
self.assertIn("Potential Findings", text)
|
||||
self.assertIn("manual_canary", text)
|
||||
self.assertIn("manual_bid", text)
|
||||
|
|
@ -37,6 +40,8 @@ class DocumentationContractTests(unittest.TestCase):
|
|||
self.assertIn("SQLite durable state", text)
|
||||
self.assertIn("Switching To Another macOS Host", text)
|
||||
self.assertIn("State Recovery", text)
|
||||
self.assertIn("visual self-reflection layer", text)
|
||||
self.assertIn("data/app_visual_state.json", text)
|
||||
self.assertIn("data/ratchet.sqlite*", text)
|
||||
self.assertIn("reports/EXPERIMENT_LOG.md", text)
|
||||
self.assertIn("git clone -b master", text)
|
||||
|
|
@ -51,10 +56,13 @@ class DocumentationContractTests(unittest.TestCase):
|
|||
self.assertIn("docs/OPERATOR_GUIDE.md", readme)
|
||||
self.assertIn("./scripts/ratchet guide", readme)
|
||||
self.assertIn("./scripts/ratchet operator-guide", readme)
|
||||
self.assertIn("./scripts/ratchet mirror", readme)
|
||||
self.assertIn("./scripts/ratchet guide", start_here)
|
||||
self.assertIn("./scripts/ratchet operator-guide", start_here)
|
||||
self.assertIn("./scripts/ratchet mirror", start_here)
|
||||
self.assertIn("guide|user-guide|explain", wrapper)
|
||||
self.assertIn("operator-guide|operator", wrapper)
|
||||
self.assertIn("mirror|reality", wrapper)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ class MacAppPackagingTest(unittest.TestCase):
|
|||
self.assertIn("cmd_app", text)
|
||||
self.assertIn("app-state", text)
|
||||
self.assertIn("engine", text)
|
||||
self.assertIn("mirror|reality", text)
|
||||
self.assertIn("app_visual_state.md", text)
|
||||
self.assertIn("pkill -x BraiinsRatchetMac", text)
|
||||
self.assertNotIn("swift run BraiinsRatchetMac", text)
|
||||
|
||||
|
|
@ -87,9 +89,14 @@ class MacAppPackagingTest(unittest.TestCase):
|
|||
self.assertIn("RatchetMapView", text)
|
||||
self.assertIn("BidLabView", text)
|
||||
self.assertIn("EvidenceVaultView", text)
|
||||
self.assertIn("RealityMirrorView", text)
|
||||
self.assertIn("RealityHUD", text)
|
||||
self.assertIn("RenderedReality", text)
|
||||
self.assertIn("RealitySnapshotWriter", text)
|
||||
self.assertIn("AppStatePayload", text)
|
||||
self.assertIn("EngineStatusPayload", text)
|
||||
self.assertIn("loadAppState", text)
|
||||
self.assertIn("repoRootURL", text)
|
||||
self.assertIn("Start Forever Engine", text)
|
||||
self.assertIn("glassEffect", text)
|
||||
self.assertIn("GlassEffectContainer", text)
|
||||
|
|
@ -97,6 +104,10 @@ class MacAppPackagingTest(unittest.TestCase):
|
|||
self.assertIn("backgroundExtensionEffect", text)
|
||||
self.assertIn("searchable", text)
|
||||
self.assertIn("Flight Deck", text)
|
||||
self.assertIn("Reality Mirror", text)
|
||||
self.assertIn("BED: Backstage Evidence Deck", text)
|
||||
self.assertIn("app_visual_state.md", text)
|
||||
self.assertIn("app_visual_state.json", text)
|
||||
self.assertIn("Bid Lab", text)
|
||||
self.assertNotIn("MissionControlView", text)
|
||||
self.assertNotIn("MiningStackView", text)
|
||||
|
|
|
|||
Loading…
Reference in a new issue