chore: add ion package, codesight wiki, work plans, ascli config

New @boocode/ion package (v0.0.1) for inference optimization network.
.codesight/ wiki artifacts for codebase documentation.
.omo/ work plans for openspec cleanup and enhanced file panel.
This commit is contained in:
2026-06-07 22:16:45 +00:00
parent ec48066a80
commit 02063072ab
63 changed files with 14025 additions and 0 deletions

View File

@@ -0,0 +1,55 @@
/**
* `workflow abandon` — Cancel a non-terminal workflow run.
*
* Marks the run as cancelled. Only works on runs that are not
* already in a terminal state (completed, failed, cancelled).
*
* @example
* workflow abandon abc123
* workflow abandon abc123 --json
*/
import type { CliOptions } from '../utils.js';
import { printJson } from '../utils.js';
// ---------------------------------------------------------------------------
// Stub: engine integration (not implemented yet)
// ---------------------------------------------------------------------------
interface AbandonResult {
runId: string;
abandoned: boolean;
message: string;
}
async function abandonWorkflowRun(_runId: string): Promise<AbandonResult> {
throw new Error('not implemented yet: abandonWorkflowRun');
}
// ---------------------------------------------------------------------------
// Command handler
// ---------------------------------------------------------------------------
export async function abandonCommand(
args: string[],
options: CliOptions,
): Promise<void> {
if (args.length === 0) {
throw new Error('Missing required argument: <run-id>\n\nUsage: workflow abandon <run-id> [--json]');
}
const runId = args[0]!;
const result = await abandonWorkflowRun(runId);
if (options.json) {
printJson(result);
return;
}
if (result.abandoned) {
console.log(`⊘ Run ${result.runId} abandoned (cancelled).`);
} else {
console.log(`Failed to abandon run ${result.runId}: ${result.message}`);
}
}

View File

@@ -0,0 +1,60 @@
/**
* `workflow approve` — Approve a paused workflow run.
*
* @example
* workflow approve abc123
* workflow approve abc123 "Looks good" --json
*/
import type { CliOptions } from '../utils.js';
import { printJson } from '../utils.js';
// ---------------------------------------------------------------------------
// Stub: engine integration (not implemented yet)
// ---------------------------------------------------------------------------
interface ApproveResult {
runId: string;
approved: boolean;
comment?: string;
message: string;
}
async function approveWorkflowRun(
_runId: string,
_comment?: string,
): Promise<ApproveResult> {
throw new Error('not implemented yet: approveWorkflowRun');
}
// ---------------------------------------------------------------------------
// Command handler
// ---------------------------------------------------------------------------
export async function approveCommand(
args: string[],
options: CliOptions,
): Promise<void> {
if (args.length === 0) {
throw new Error('Missing required argument: <run-id>\n\nUsage: workflow approve <run-id> [comment] [--json]');
}
const runId = args[0]!;
const comment = args.length > 1 ? args.slice(1).join(' ') : undefined;
const result = await approveWorkflowRun(runId, comment);
if (options.json) {
printJson(result);
return;
}
if (result.approved) {
console.log(`✓ Run ${result.runId} approved.`);
if (result.comment) {
console.log(` Comment: ${result.comment}`);
}
} else {
console.log(`✗ Failed to approve run ${result.runId}: ${result.message}`);
}
}

View File

@@ -0,0 +1,74 @@
/**
* `workflow cleanup` — Remove old workflow run artifacts.
*
* Default retention: 7 days. Removes run data older than the specified
* number of days.
*
* @example
* workflow cleanup
* workflow cleanup 30 --json
*/
import type { CliOptions } from '../utils.js';
import { printJson } from '../utils.js';
// ---------------------------------------------------------------------------
// Stub: engine integration (not implemented yet)
// ---------------------------------------------------------------------------
interface CleanupResult {
removedRuns: number;
removedEvents: number;
freedBytes: number;
retentionDays: number;
}
async function cleanupWorkflowRuns(
_days: number,
_cwd?: string,
): Promise<CleanupResult> {
throw new Error('not implemented yet: cleanupWorkflowRuns');
}
// ---------------------------------------------------------------------------
// Command handler
// ---------------------------------------------------------------------------
export async function cleanupCommand(
args: string[],
options: CliOptions,
): Promise<void> {
// First positional arg is the number of days (default 7).
const days = args.length > 0 ? parseInt(args[0]!, 10) : 7;
if (isNaN(days) || days < 1) {
throw new Error(`Invalid retention days: ${args[0]}. Must be a positive integer.`);
}
const result = await cleanupWorkflowRuns(days, options.cwd);
if (options.json) {
printJson(result);
return;
}
console.log(`Cleanup complete (retention: ${result.retentionDays} days).`);
console.log(` Runs removed: ${result.removedRuns}`);
console.log(` Events removed: ${result.removedEvents}`);
console.log(` Space freed: ${formatBytes(result.freedBytes)}`);
}
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
function formatBytes(bytes: number): string {
if (bytes === 0) return '0 B';
const units = ['B', 'KB', 'MB', 'GB'];
const i = Math.min(
Math.floor(Math.log(bytes) / Math.log(1024)),
units.length - 1,
);
const value = bytes / Math.pow(1024, i);
return `${value.toFixed(i === 0 ? 0 : 1)} ${units[i]}`;
}

View File

@@ -0,0 +1,62 @@
/**
* `workflow convert` — Convert a .sop.md file to a YAML workflow definition.
*
* Reads the SOP markdown file, parses its structure, and outputs
* a corresponding YAML workflow definition.
*
* @example
* workflow convert deploy.sop.md
* workflow convert deploy.sop.md --output workflows/deploy.yaml
*/
import type { CliOptions } from '../utils.js';
import { printJson } from '../utils.js';
// ---------------------------------------------------------------------------
// Stub: engine integration (not implemented yet)
// ---------------------------------------------------------------------------
interface ConvertResult {
inputFile: string;
outputFile: string;
workflowName: string;
nodeCount: number;
}
async function convertSopToYaml(
_inputPath: string,
_outputPath?: string,
): Promise<ConvertResult> {
throw new Error('not implemented yet: convertSopToYaml');
}
// ---------------------------------------------------------------------------
// Command handler
// ---------------------------------------------------------------------------
export async function convertCommand(
args: string[],
options: CliOptions,
): Promise<void> {
if (args.length === 0) {
throw new Error('Missing required argument: <file.sop.md>\n\nUsage: workflow convert <file.sop.md> [--output <path>]');
}
const inputPath = args[0]!;
if (!inputPath.endsWith('.sop.md')) {
throw new Error(`Input file must end with .sop.md, got: ${inputPath}`);
}
const result = await convertSopToYaml(inputPath, options.output);
if (options.json) {
printJson(result);
return;
}
console.log(`Converted: ${result.inputFile}`);
console.log(` Output: ${result.outputFile}`);
console.log(` Workflow: ${result.workflowName}`);
console.log(` Nodes: ${result.nodeCount}`);
}

View File

@@ -0,0 +1,59 @@
/**
* `workflow list` — List all available workflows.
*
* Discovers workflows from both bundled and project sources and displays
* them in a formatted table (or JSON with --json).
*
* @example
* workflow list
* workflow list --json
*/
import type { CliOptions } from '../utils.js';
import { printTable, printJson } from '../utils.js';
// ---------------------------------------------------------------------------
// Stub: engine integration (not implemented yet)
// ---------------------------------------------------------------------------
interface WorkflowEntry {
name: string;
description: string;
source: 'bundled' | 'project';
}
async function discoverWorkflows(_cwd?: string): Promise<WorkflowEntry[]> {
throw new Error('not implemented yet: discoverWorkflows');
}
// ---------------------------------------------------------------------------
// Command handler
// ---------------------------------------------------------------------------
export async function listCommand(
_args: string[],
options: CliOptions,
): Promise<void> {
const workflows = await discoverWorkflows(options.cwd);
if (options.json) {
printJson(workflows);
return;
}
console.log('Available workflows:');
console.log('');
printTable(
workflows.map((w) => ({
name: w.name,
description: w.description,
source: w.source,
})),
[
{ header: 'Name', field: 'name', minWidth: 20 },
{ header: 'Description', field: 'description', minWidth: 30 },
{ header: 'Source', field: 'source', minWidth: 10 },
],
);
}

View File

@@ -0,0 +1,62 @@
/**
* `workflow reject` — Reject a paused workflow run.
*
* Sets $REJECTION_REASON with the provided reason string.
*
* @example
* workflow reject abc123
* workflow reject abc123 "Not compliant" --json
*/
import type { CliOptions } from '../utils.js';
import { printJson } from '../utils.js';
// ---------------------------------------------------------------------------
// Stub: engine integration (not implemented yet)
// ---------------------------------------------------------------------------
interface RejectResult {
runId: string;
rejected: boolean;
reason?: string;
message: string;
}
async function rejectWorkflowRun(
_runId: string,
_reason?: string,
): Promise<RejectResult> {
throw new Error('not implemented yet: rejectWorkflowRun');
}
// ---------------------------------------------------------------------------
// Command handler
// ---------------------------------------------------------------------------
export async function rejectCommand(
args: string[],
options: CliOptions,
): Promise<void> {
if (args.length === 0) {
throw new Error('Missing required argument: <run-id>\n\nUsage: workflow reject <run-id> [reason] [--json]');
}
const runId = args[0]!;
const reason = args.length > 1 ? args.slice(1).join(' ') : undefined;
const result = await rejectWorkflowRun(runId, reason);
if (options.json) {
printJson(result);
return;
}
if (result.rejected) {
console.log(`✗ Run ${result.runId} rejected.`);
if (result.reason) {
console.log(` Reason: ${result.reason}`);
}
} else {
console.log(`Failed to reject run ${result.runId}: ${result.message}`);
}
}

View File

@@ -0,0 +1,55 @@
/**
* `workflow resume` — Resume a failed workflow run.
*
* Skips completed nodes and re-executes from the failure point.
*
* @example
* workflow resume abc123
* workflow resume abc123 --json
*/
import type { CliOptions } from '../utils.js';
import { printJson } from '../utils.js';
// ---------------------------------------------------------------------------
// Stub: engine integration (not implemented yet)
// ---------------------------------------------------------------------------
interface ResumeResult {
runId: string;
resumed: boolean;
message: string;
}
async function resumeWorkflowRun(_runId: string): Promise<ResumeResult> {
throw new Error('not implemented yet: resumeWorkflowRun');
}
// ---------------------------------------------------------------------------
// Command handler
// ---------------------------------------------------------------------------
export async function resumeCommand(
args: string[],
options: CliOptions,
): Promise<void> {
if (args.length === 0) {
throw new Error('Missing required argument: <run-id>\n\nUsage: workflow resume <run-id> [--json]');
}
const runId = args[0]!;
const result = await resumeWorkflowRun(runId);
if (options.json) {
printJson(result);
return;
}
if (result.resumed) {
console.log(`↻ Run ${result.runId} resumed.`);
console.log(` ${result.message}`);
} else {
console.log(`Failed to resume run ${result.runId}: ${result.message}`);
}
}

View File

@@ -0,0 +1,94 @@
/**
* `workflow run` — Execute a workflow by name.
*
* Resolves the workflow, passes message args, and shows real-time progress.
* With --detach, runs in background and returns the run ID immediately.
*
* @example
* workflow run deploy
* workflow run deploy --cwd /tmp/project --json
* workflow run deploy --detach
*/
import type { CliOptions } from '../utils.js';
import { printJson } from '../utils.js';
// ---------------------------------------------------------------------------
// Stub: engine integration (not implemented yet)
// ---------------------------------------------------------------------------
interface WorkflowRunResult {
id: string;
workflowName: string;
status: string;
output?: Record<string, unknown>;
error?: string;
startedAt: string;
completedAt?: string;
}
async function resolveWorkflow(
_name: string,
_cwd?: string,
): Promise<unknown> {
throw new Error('not implemented yet: resolveWorkflow');
}
async function executeWorkflow(
_workflow: unknown,
_messageArgs: string[],
_options: { cwd?: string; detach?: boolean },
): Promise<WorkflowRunResult> {
throw new Error('not implemented yet: executeWorkflow');
}
// ---------------------------------------------------------------------------
// Command handler
// ---------------------------------------------------------------------------
export async function runCommand(
args: string[],
options: CliOptions,
): Promise<void> {
if (args.length === 0) {
throw new Error('Missing required argument: <name>\n\nUsage: workflow run <name> [args...] [--cwd <path>] [--detach] [--json]');
}
const workflowName = args[0]!;
const messageArgs = args.slice(1);
const detach = options.json ? false : false; // --detach is a flag, not in CliOptions yet
// Parse --detach from raw args (it's a boolean flag).
// This is handled by the arg parser in the main entry point,
// but since CliOptions doesn't have detach, we check process.argv.
const isDetach = process.argv.includes('--detach');
const workflow = await resolveWorkflow(workflowName, options.cwd);
const result = await executeWorkflow(workflow, messageArgs, {
cwd: options.cwd,
detach: isDetach,
});
if (options.json) {
printJson(result);
return;
}
if (isDetach) {
console.log(`Workflow started in background.`);
console.log(`Run ID: ${result.id}`);
console.log(`Workflow: ${result.workflowName}`);
console.log(`Status: ${result.status}`);
} else {
console.log(`Workflow run completed.`);
console.log(` Run ID: ${result.id}`);
console.log(` Workflow: ${result.workflowName}`);
console.log(` Status: ${result.status}`);
if (result.output) {
console.log(` Output: ${JSON.stringify(result.output)}`);
}
if (result.error) {
console.log(` Error: ${result.error}`);
}
}
}

View File

@@ -0,0 +1,91 @@
/**
* `workflow runs` — List recent workflow runs with filters.
*
* @example
* workflow runs
* workflow runs --status failed --limit 10 --json
* workflow runs --all
*/
import type { CliOptions } from '../utils.js';
import { printTable, printJson, formatTimestamp, formatDuration } from '../utils.js';
// ---------------------------------------------------------------------------
// Stub: engine integration (not implemented yet)
// ---------------------------------------------------------------------------
interface RunRecord {
id: string;
workflowName: string;
status: string;
startedAt: string;
duration?: number; // ms, absent if still running
currentNode?: string;
}
async function listWorkflowRuns(_filters: {
status?: string;
limit?: number;
all?: boolean;
cwd?: string;
}): Promise<RunRecord[]> {
throw new Error('not implemented yet: listWorkflowRuns');
}
// ---------------------------------------------------------------------------
// Command handler
// ---------------------------------------------------------------------------
export async function runsCommand(
args: string[],
options: CliOptions,
): Promise<void> {
// Parse --status, --limit, --all from args/options.
// These are already extracted by parseArgs into options.
const status = typeof (options as Record<string, unknown>).status === 'string'
? (options as Record<string, unknown>).status as string
: undefined;
const limit = typeof (options as Record<string, unknown>).limit === 'string'
? parseInt((options as Record<string, unknown>).limit as string, 10)
: 50;
const all = (options as Record<string, unknown>).all === true;
const runs = await listWorkflowRuns({
status,
limit,
all,
cwd: options.cwd,
});
if (options.json) {
printJson(runs);
return;
}
if (runs.length === 0) {
console.log('No workflow runs found.');
return;
}
console.log(`Showing ${runs.length} run(s):`);
console.log('');
printTable(
runs.map((r) => ({
id: r.id,
workflow: r.workflowName,
status: r.status,
started: formatTimestamp(new Date(r.startedAt)),
duration: r.duration != null ? formatDuration(r.duration) : '-',
currentNode: r.currentNode ?? '-',
})),
[
{ header: 'ID', field: 'id', minWidth: 26 },
{ header: 'Workflow', field: 'workflow', minWidth: 20 },
{ header: 'Status', field: 'status', minWidth: 10 },
{ header: 'Started', field: 'started', minWidth: 19 },
{ header: 'Duration', field: 'duration', minWidth: 10 },
{ header: 'Node', field: 'currentNode', minWidth: 15 },
],
);
}

View File

@@ -0,0 +1,67 @@
/**
* `workflow status` — Show active (running + paused) workflow runs.
*
* @example
* workflow status
* workflow status --json
*/
import type { CliOptions } from '../utils.js';
import { printTable, printJson, formatDuration } from '../utils.js';
// ---------------------------------------------------------------------------
// Stub: engine integration (not implemented yet)
// ---------------------------------------------------------------------------
interface ActiveRun {
id: string;
workflowName: string;
status: string;
duration: number; // ms
currentNode?: string;
}
async function getActiveRuns(_cwd?: string): Promise<ActiveRun[]> {
throw new Error('not implemented yet: getActiveRuns');
}
// ---------------------------------------------------------------------------
// Command handler
// ---------------------------------------------------------------------------
export async function statusCommand(
_args: string[],
options: CliOptions,
): Promise<void> {
const runs = await getActiveRuns(options.cwd);
if (options.json) {
printJson(runs);
return;
}
if (runs.length === 0) {
console.log('No active workflow runs.');
return;
}
console.log('Active workflow runs:');
console.log('');
printTable(
runs.map((r) => ({
id: r.id,
workflow: r.workflowName,
status: r.status,
duration: formatDuration(r.duration),
currentNode: r.currentNode ?? '-',
})),
[
{ header: 'ID', field: 'id', minWidth: 26 },
{ header: 'Workflow', field: 'workflow', minWidth: 20 },
{ header: 'Status', field: 'status', minWidth: 10 },
{ header: 'Duration', field: 'duration', minWidth: 10 },
{ header: 'Current Node', field: 'currentNode', minWidth: 15 },
],
);
}

View File

@@ -0,0 +1,66 @@
/**
* `workflow validate` — Validate a workflow definition without executing.
*
* Loads the workflow, runs schema validation, and reports any errors.
*
* @example
* workflow validate deploy
* workflow validate deploy --json
*/
import type { CliOptions } from '../utils.js';
import { printJson } from '../utils.js';
// ---------------------------------------------------------------------------
// Stub: engine integration (not implemented yet)
// ---------------------------------------------------------------------------
interface ValidationError {
path: string;
message: string;
}
interface ValidateResult {
valid: boolean;
errors: ValidationError[];
workflowName: string;
}
async function validateWorkflow(
_name: string,
_cwd?: string,
): Promise<ValidateResult> {
throw new Error('not implemented yet: validateWorkflow');
}
// ---------------------------------------------------------------------------
// Command handler
// ---------------------------------------------------------------------------
export async function validateCommand(
args: string[],
options: CliOptions,
): Promise<void> {
if (args.length === 0) {
throw new Error('Missing required argument: <name>\n\nUsage: workflow validate <name> [--json]');
}
const workflowName = args[0]!;
const result = await validateWorkflow(workflowName, options.cwd);
if (options.json) {
printJson(result);
return;
}
if (result.valid) {
console.log(`✓ Workflow "${result.workflowName}" is valid.`);
} else {
console.log(`✗ Workflow "${result.workflowName}" has ${result.errors.length} error(s):`);
console.log('');
for (const err of result.errors) {
console.log(` ${err.path}: ${err.message}`);
}
}
}