Files
boardroom-map/startos/actions/grade-decks.ts
T
Jonathan KirkwoodandClaude Fable 5 b1d7aed9f4 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>
2026-07-06 14:15:12 -05:00

60 lines
1.8 KiB
TypeScript

import { startSdk } from '@start9labs/start-sdk'
import { sdk } from '../sdk'
/**
* 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 gradeDecks = sdk.Action.withoutInput(
'grade-decks',
async ({ effects }) => ({
name: 'Grade Decks',
description: 'Grade all decks currently in the inbox (inbox/<company-slug>/...).',
warning: null,
allowedStatuses: 'only-running',
group: null,
visibility: 'enabled',
}),
async ({ effects }) => {
const mounts = sdk.Mounts.of().mountVolume({
volumeId: 'main',
mountpoint: '/data',
subpath: null,
readonly: false,
})
let output: string
try {
const { stdout } = await startSdk.runCommand<typeof sdk.manifest>(
effects,
{ imageId: 'main' },
[
'sh',
'-c',
'mkdir -p /data/state && date +%s > /data/state/run_request && ' +
'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' } },
'grade-decks',
)
output = (stdout?.toString() || '').trim() || 'Grading requested.'
} catch (e: any) {
output = 'Could not request grading: ' + (e?.message || String(e))
}
return {
version: '1',
title: 'Grading Requested',
message:
output +
' 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 },
}
},
)