Implement BDEF v1.1 grading: scoring core, per-deck pipeline, ledger, dashboard, StartOS layer

- Deterministic scoring.py (quant 60 / qual 40 / flags -15, profitability heaviest)
- Per-company JSON ledger with forecast-target chaining deck N-1 -> N
- Single-shot sandbox agent with guided-JSON fallback ladder (no tool loop)
- Portfolio dashboard with sparklines, KPI hit rates, BDEF category bars
- 48 unit tests green; endpoints smoke-tested; npm check+build green

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jonathan Kirkwood
2026-07-06 14:15:12 -05:00
co-authored by Claude Fable 5
parent 1dde915540
commit b1d7aed9f4
48 changed files with 4907 additions and 971 deletions
+12 -12
View File
@@ -2,17 +2,17 @@ import { startSdk } from '@start9labs/start-sdk'
import { sdk } from '../sdk'
/**
* Trigger a review of whatever is currently in the inbox. The running job-runner
* Trigger grading of whatever is currently in the inbox. The running job-runner
* thread polls for /data/state/run_request and starts a job when it appears, so
* this action just drops that request file (decoupled from the daemon — no need
* to reach its HTTP port from the action's one-shot container).
*/
export const runReview = sdk.Action.withoutInput(
'run-review',
export const gradeDecks = sdk.Action.withoutInput(
'grade-decks',
async ({ effects }) => ({
name: 'Run Review',
description: 'Convene the panel now over the documents currently in the inbox.',
name: 'Grade Decks',
description: 'Grade all decks currently in the inbox (inbox/<company-slug>/...).',
warning: null,
allowedStatuses: 'only-running',
group: null,
@@ -36,23 +36,23 @@ export const runReview = sdk.Action.withoutInput(
'sh',
'-c',
'mkdir -p /data/state && date +%s > /data/state/run_request && ' +
'n=$(ls -1 /data/inbox 2>/dev/null | wc -l | tr -d " "); ' +
'echo "Review requested. $n file(s) in the inbox."',
'n=$(find /data/inbox -type f 2>/dev/null | wc -l | tr -d " "); ' +
'echo "Grading requested. $n deck file(s) in the inbox."',
],
{ mounts, env: { BM_DATA_DIR: '/data' } },
'run-review',
'grade-decks',
)
output = (stdout?.toString() || '').trim() || 'Review requested.'
output = (stdout?.toString() || '').trim() || 'Grading requested.'
} catch (e: any) {
output = 'Could not request a review: ' + (e?.message || String(e))
output = 'Could not request grading: ' + (e?.message || String(e))
}
return {
version: '1',
title: 'Review Requested',
title: 'Grading Requested',
message:
output +
' Watch the Web UI for progress; reports appear there and via "View Latest Report".',
' Watch the Web UI for progress; scorecards appear there and via "View Latest Scorecard".',
result: { type: 'single', value: output, copyable: false, qr: false, masked: false },
}
},