also looking at this
feat: add owned VTOL hover development
#76
30 files
+780
-111
| @@ -0,0 +1,27 @@ | ||
| 1 | import { defineCommand } from '@stacksjs/cli' | |
| 2 | import { print, printError } from '@stacksjs/cli/output' | |
| 3 | import { createVtolHoverProfile, vtolHoverScenarios } from '../../resources/functions/drone/vehicles/vtol' | |
| 4 | import { runVehicleSimulation } from '../../resources/functions/drone/vehicles/runtime' | |
| 5 | ||
| 6 | export default defineCommand({ | |
| 7 | name: 'vtol:hover', | |
| 8 | description: 'Exercise the fictional lift-and-cruise airframe in hover only; no wing transition or physical control', | |
| 9 | options: { | |
| 10 | '--scenario <name>': { description: vtolHoverScenarios.join(', '), default: 'hover' }, | |
| 11 | '--seconds <n>': { description: 'Maximum virtual duration, 2..180 seconds', default: '60' }, | |
| 12 | }, | |
| 13 | handle(options) { | |
| 14 | try { | |
| 15 | const result = runVehicleSimulation(createVtolHoverProfile(options.scenario), { scenario: options.scenario, seconds: Number(options.seconds) }) | |
| 16 | const { trace, path, ...report } = result | |
| 17 | const expectedStatus = options.scenario === 'hover' ? 'completed' : options.scenario === 'host-loss' ? 'host-lost' : 'blocked' | |
| 18 | const observedFlight = path.some(row => row.truthPositionM[2] < -1 && row.actuators.slice(0, 4).some(n => n > 0)) | |
| 19 | const boardNeutral = result.board.actuators.every(n => n === 0) && result.board.expiresAtMs === null | |
| 20 | const hoverOnly = path.every(row => row.actuators.slice(4).every(n => n === 0)) | |
| 21 | const demonstrationMatched = result.status === expectedStatus && observedFlight && boardNeutral && hoverOnly | |
| 22 | print(JSON.stringify({ ...report, scope: 'development-hover-only', transitionsImplemented: false, expectedStatus, demonstrationMatched, observedFlight, boardNeutral, hoverOnly, recordedMissionRows: trace.rows.length, evaluatedPathRows: path.length }, (_key, value) => typeof value === 'bigint' ? String(value) : value, 2)) | |
| 23 | if (!demonstrationMatched) process.exitCode = 1 | |
| 24 | } | |
| 25 | catch (error) { printError(error instanceof Error ? error.message : String(error)); process.exitCode = 1 } | |
| 26 | }, | |
| 27 | }) | |