diff --git a/CLAUDE.md b/CLAUDE.md index 5c27925..6fc7c5b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -13,7 +13,7 @@ Daystrom is a CLI and library providing full operational coverage over **Palo Al pnpm install # Install deps pnpm run build # tsc compile to dist/ pnpm run dev # Run CLI via tsx (any subcommand) -pnpm run generate # Interactive guardrail generation loop +pnpm run generate # Interactive guardrail generation loop (deprecated alias) # Test pnpm test # All tests (vitest run) @@ -41,15 +41,15 @@ TypeScript ESM, Node 20+, pnpm. LangChain.js w/ structured output (Zod). `@cdot6 ``` src/ -├── cli/ # CLI entry, 8 command groups, interactive prompts, renderer -│ ├── index.ts # Commander program — registers generate/resume/report/list/runtime/audit/redteam/model-security +├── cli/ # CLI entry, 3 top-level groups + deprecated aliases, prompts, renderer +│ ├── index.ts # Commander program — registers runtime/redteam/model-security + deprecated top-level aliases │ ├── commands/ -│ │ ├── generate.ts # Main loop orchestration, wires all services -│ │ ├── resume.ts # Resume paused/failed run from disk -│ │ ├── report.ts # View run results by ID -│ │ ├── list.ts # List all saved runs -│ │ ├── runtime.ts # Runtime scanning (scan, bulk-scan, resume-poll) + config management (profiles, topics, api-keys, customer-apps, deployment-profiles, dlp-profiles, scan-logs) -│ │ ├── audit.ts # Profile-level multi-topic evaluation +│ │ ├── generate.ts # Main loop orchestration, wires all services (registered under runtime topics) +│ │ ├── resume.ts # Resume paused/failed run from disk (registered under runtime topics) +│ │ ├── report.ts # View run results by ID (registered under runtime topics) +│ │ ├── list.ts # List all saved runs (registered as "runs" under runtime topics) +│ │ ├── runtime.ts # Runtime scanning + config management + guardrail generation (topics) + audit (profiles) +│ │ ├── audit.ts # Profile-level multi-topic evaluation (registered under runtime profiles) │ │ ├── redteam.ts # Red team operations (scan, targets CRUD, prompt-sets CRUD, prompts CRUD, properties) │ │ └── modelsecurity.ts # Model security operations (groups, rules, rule-instances, scans, labels, pypi-auth) │ ├── bulk-scan-state.ts # Save/load bulk scan IDs for resume after poll failure @@ -172,13 +172,14 @@ tests/ - Bulk scan IDs are saved to `~/.daystrom/bulk-scans/` before polling — survives rate limit crashes - CLI: `daystrom runtime resume-poll [--output ]` — resume polling from saved scan IDs - CLI config management subcommand groups (all via `ManagementClient` OAuth2): - - `daystrom runtime profiles {list,get,create,update,delete}` — security profile CRUD (supports `--force --updated-by`) - - `daystrom runtime topics {list,get,create,update,delete}` — custom topic CRUD (supports `--force --updated-by`) + - `daystrom runtime profiles {list,create,update,delete,audit}` — security profile CRUD + profile audit (supports `--force --updated-by`) + - `daystrom runtime topics {list,create,update,delete,generate,resume,report,runs}` — custom topic CRUD + guardrail generation (supports `--force --updated-by`) - `daystrom runtime api-keys {list,create,regenerate,delete}` — API key management (`regenerate` takes `--interval`/`--unit`) - `daystrom runtime customer-apps {list,get,update,delete}` — customer app CRUD - `daystrom runtime deployment-profiles {list}` — deployment profile listing (`--unactivated` filter) - `daystrom runtime dlp-profiles {list}` — DLP profile listing - `daystrom runtime scan-logs {query}` — scan log querying (`--interval`/`--unit hours`/`--filter`) +- Deprecated top-level aliases (`generate`, `resume`, `report`, `list`, `audit`) still work with deprecation warnings ### Red Team (`src/airs/redteam.ts`, `src/airs/promptsets.ts`) - `SdkRedTeamService` wraps `RedTeamClient` for scan CRUD, polling, reports, **target CRUD** diff --git a/README.md b/README.md index 83594e9..99e1992 100644 --- a/README.md +++ b/README.md @@ -20,19 +20,20 @@ Requires **Node.js >= 20**. ```bash cp .env.example .env # add your API keys -daystrom generate # interactive guardrail generation +daystrom runtime topics generate # interactive guardrail generation ``` ## Commands | Command | Description | |---------|-------------| -| `generate` | LLM-driven guardrail generation with iterative refinement | -| `resume` | Resume a paused or failed generation run | -| `report` | View results for a saved run (terminal, JSON, HTML) | -| `list` | List all saved runs | -| `runtime` | Prompt scanning + config management (profiles, topics, API keys, apps, scan logs) | -| `audit` | Multi-topic profile evaluation with conflict detection | +| `runtime scan` | Single prompt scanning against AIRS profiles | +| `runtime bulk-scan` | Batch prompt scanning with CSV output | +| `runtime topics` | Custom topic CRUD + guardrail generation (`generate`, `resume`, `report`, `runs`) | +| `runtime profiles` | Security profile CRUD + multi-topic `audit` | +| `runtime api-keys` | API key management | +| `runtime customer-apps` | Customer app CRUD | +| `runtime scan-logs` | Scan log querying | | `redteam` | Adversarial scanning — targets, prompt sets, scans, reports | | `model-security` | ML model supply chain security — groups, rules, scans, labels | diff --git a/docs/features/guardrail-generation.md b/docs/features/guardrail-generation.md index ed80221..381bdaf 100644 --- a/docs/features/guardrail-generation.md +++ b/docs/features/guardrail-generation.md @@ -17,20 +17,29 @@ Daystrom's guardrail generation capability uses an LLM-driven feedback loop to c ## CLI Usage +Guardrail generation lives under `daystrom runtime topics`: + ```bash # Interactive mode — prompts for all inputs -daystrom generate +daystrom runtime topics generate # Non-interactive with all options -daystrom generate \ - --topic-name "weapons-discussion" \ - --description "Block discussions about weapons manufacturing" \ +daystrom runtime topics generate \ + --topic "Block discussions about weapons manufacturing" \ --intent block \ --profile my-security-profile \ - --target-coverage 0.9 \ + --target-coverage 90 \ --max-iterations 5 + +# Resume, report, list runs +daystrom runtime topics resume +daystrom runtime topics report +daystrom runtime topics runs ``` +!!! note "Backward compatibility" + Top-level aliases (`daystrom generate`, `daystrom resume`, etc.) still work but print a deprecation warning. Use the `runtime topics` paths going forward. + ## Key Concepts - **Intent**: `block` (detect violating prompts) or `allow` (detect benign prompts that should pass through) diff --git a/docs/features/runtime-security.md b/docs/features/runtime-security.md index 5233e54..2ff5d76 100644 --- a/docs/features/runtime-security.md +++ b/docs/features/runtime-security.md @@ -157,26 +157,40 @@ prompt,action,category,triggered,scan_id,report_id Daystrom exposes full CRUD over AIRS runtime configuration resources via `daystrom runtime` subcommand groups. All config management commands require Management API credentials (`PANW_MGMT_CLIENT_ID`, `PANW_MGMT_CLIENT_SECRET`, `PANW_MGMT_TSG_ID`). -### Security Profiles +### Security Profiles & Profile Audit ```bash +# CRUD daystrom runtime profiles list daystrom runtime profiles create --config profile.json daystrom runtime profiles update --config profile.json daystrom runtime profiles delete daystrom runtime profiles delete --force --updated-by user@example.com + +# Audit all topics in a profile +daystrom runtime profiles audit +daystrom runtime profiles audit --format html --output audit.html ``` -### Custom Topics +### Custom Topics & Guardrail Generation ```bash +# CRUD daystrom runtime topics list daystrom runtime topics create --config topic.json daystrom runtime topics update --config topic.json daystrom runtime topics delete daystrom runtime topics delete --force --updated-by user@example.com + +# Guardrail generation (LLM-driven iterative refinement) +daystrom runtime topics generate +daystrom runtime topics resume +daystrom runtime topics report +daystrom runtime topics runs ``` +See [Guardrail Generation](guardrail-generation.md) for details on the generation loop. + ### API Keys ```bash diff --git a/docs/reference/cli-commands.md b/docs/reference/cli-commands.md index 986ad74..bb8629e 100644 --- a/docs/reference/cli-commands.md +++ b/docs/reference/cli-commands.md @@ -2,166 +2,13 @@ Binary: `daystrom` (or `pnpm run dev` during development). -Eight command groups covering all Prisma AIRS capabilities. - ---- - -## generate - -Start a new guardrail generation run. - -```bash -daystrom generate [options] -``` - -### Options - -| Flag | Default | What it does | -|------|---------|-------------| -| `--provider ` | `claude-api` | LLM provider (`claude-api`, `claude-vertex`, `claude-bedrock`, `gemini-api`, `gemini-vertex`, `gemini-bedrock`) | -| `--model ` | per-provider | Override default model | -| `--profile ` | _(prompted)_ | AIRS security profile name | -| `--topic ` | _(prompted)_ | Natural language description of content to detect | -| `--intent ` | `block` | Whether matching prompts are blocked or allowed | -| `--max-iterations ` | `20` | Maximum refinement iterations | -| `--target-coverage ` | `90` | Coverage percentage to stop at | -| `--max-regressions ` | `3` | Stop after N consecutive coverage regressions (0 = disable) | -| `--accumulate-tests` | off | Carry forward test prompts across iterations | -| `--max-accumulated-tests ` | unlimited | Cap on accumulated test count | -| `--no-memory` | memory on | Disable cross-run learning | -| `--debug-scans` | off | Dump raw AIRS scan responses to JSONL for debugging | -| `--create-prompt-set` | off | Create custom prompt set in AI Red Team from test cases | -| `--prompt-set-name ` | auto | Override auto-generated prompt set name | - -!!! tip "Skip all prompts" - When both `--topic` and `--profile` are provided, interactive mode is skipped entirely. - -### Interactive Mode - -When flags are omitted, Daystrom walks you through: - -1. Topic description -2. Intent (block or allow) -3. Security profile name -4. Seed examples (optional) -5. Max iterations -6. Target coverage % -7. Accumulate tests across iterations (yes/no) -8. Max accumulated tests (if accumulation enabled) - -### Examples - -```bash -# Interactive — prompts for everything -daystrom generate - -# Non-interactive — all inputs via flags -daystrom generate \ - --provider claude-api \ - --profile my-security-profile \ - --topic "Block discussions about building explosives" \ - --intent block \ - --target-coverage 90 - -# With test accumulation -daystrom generate \ - --topic "Allow recipe discussions" \ - --intent allow \ - --profile cooking-policy \ - --accumulate-tests \ - --max-accumulated-tests 60 -``` - ---- - -## resume - -Pick up a paused or failed run from where it left off. - -```bash -daystrom resume [options] -``` - -| Flag | Default | What it does | -|------|---------|-------------| -| `--max-iterations ` | `20` | Additional iterations from current position | -| `--debug-scans` | off | Dump raw AIRS scan responses to JSONL for debugging | -| `--create-prompt-set` | off | Create custom prompt set in AI Red Team from test cases | -| `--prompt-set-name ` | auto | Override auto-generated prompt set name | - -```bash -daystrom resume abc123xyz --max-iterations 10 -``` - -!!! note - The run must exist in the data directory (`~/.daystrom/runs/`). Use `daystrom list` to find run IDs. Settings like `accumulateTests` are inherited from the original run. - ---- - -## report - -View results for a saved run. - -```bash -daystrom report [options] -``` - -| Flag | Default | What it does | -|------|---------|-------------| -| `--iteration ` | _(best)_ | Show a specific iteration instead of the best | -| `--format ` | `terminal` | Output format: `terminal`, `json`, `html` | -| `--tests` | _(off)_ | Include per-test-case details | -| `--diff ` | _(none)_ | Compare with another run side-by-side | -| `--output ` | `-report.html` | Output file path (html format only) | - -```bash -# Best iteration (terminal) -daystrom report abc123xyz - -# Specific iteration -daystrom report abc123xyz --iteration 3 - -# JSON export (to stdout) -daystrom report abc123xyz --format json --tests - -# HTML report with test details -daystrom report abc123xyz --format html --tests --output my-report.html - -# Compare two runs -daystrom report abc123xyz --diff def456uvw -``` - ---- - -## list - -Show all saved runs. - -```bash -daystrom list -``` - -#### Example Output - -``` - Saved Runs: - - 7A6KX0oSvt-TWEJTvzXUM - Status: completed Coverage: 60.0% Iterations: 10 - Topic: Tax and regulatory advice covers specific tax filing instructions... - Created: 2026-03-04T21:13:14.504Z - - wfvv9PRTLpO096S-QbcSm - Status: completed Coverage: 70.0% Iterations: 20 - Topic: Tax guidance and recommendations - Created: 2026-03-06T19:34:35.563Z -``` +Three top-level command groups: `runtime`, `redteam`, `model-security`. --- ## runtime -Runtime prompt scanning and AIRS configuration management. +Runtime prompt scanning, AIRS configuration management, guardrail generation, and profile audits. ### runtime scan @@ -283,7 +130,7 @@ daystrom runtime resume-poll [--output ] ### runtime profiles -Security profile CRUD. +Security profile CRUD and profile-level audit. ```bash daystrom runtime profiles list @@ -291,6 +138,7 @@ daystrom runtime profiles create --config daystrom runtime profiles update --config daystrom runtime profiles delete daystrom runtime profiles delete --force --updated-by +daystrom runtime profiles audit [options] ``` | Subcommand | Flags | @@ -299,17 +147,40 @@ daystrom runtime profiles delete --force --updated-by | `create` | `--config ` (required) | | `update ` | `--config ` (required) | | `delete ` | `--force`, `--updated-by ` | +| `audit ` | `--max-tests-per-topic ` (default 20), `--format ` (terminal/json/html), `--output `, `--provider `, `--model ` | + +#### runtime profiles audit + +Evaluate all topics in an AIRS security profile. Generates tests per topic, scans them, computes per-topic and composite metrics, and detects cross-topic conflicts. + +```bash +# Audit all topics in a profile +daystrom runtime profiles audit my-security-profile + +# JSON export +daystrom runtime profiles audit my-security-profile --format json + +# HTML report +daystrom runtime profiles audit my-security-profile --format html --output audit-report.html +``` ### runtime topics -Custom topic CRUD. +Custom topic CRUD and guardrail generation. ```bash +# CRUD daystrom runtime topics list daystrom runtime topics create --config daystrom runtime topics update --config daystrom runtime topics delete daystrom runtime topics delete --force --updated-by + +# Guardrail generation +daystrom runtime topics generate [options] +daystrom runtime topics resume [options] +daystrom runtime topics report [options] +daystrom runtime topics runs ``` | Subcommand | Flags | @@ -319,6 +190,91 @@ daystrom runtime topics delete --force --updated-by | `update ` | `--config ` (required) | | `delete ` | `--force`, `--updated-by ` | +#### runtime topics generate + +Start a new guardrail generation run. + +| Flag | Default | What it does | +|------|---------|-------------| +| `--provider ` | `claude-api` | LLM provider (`claude-api`, `claude-vertex`, `claude-bedrock`, `gemini-api`, `gemini-vertex`, `gemini-bedrock`) | +| `--model ` | per-provider | Override default model | +| `--profile ` | _(prompted)_ | AIRS security profile name | +| `--topic ` | _(prompted)_ | Natural language description of content to detect | +| `--intent ` | `block` | Whether matching prompts are blocked or allowed | +| `--max-iterations ` | `20` | Maximum refinement iterations | +| `--target-coverage ` | `90` | Coverage percentage to stop at | +| `--max-regressions ` | `3` | Stop after N consecutive coverage regressions (0 = disable) | +| `--accumulate-tests` | off | Carry forward test prompts across iterations | +| `--max-accumulated-tests ` | unlimited | Cap on accumulated test count | +| `--no-memory` | memory on | Disable cross-run learning | +| `--debug-scans` | off | Dump raw AIRS scan responses to JSONL for debugging | +| `--create-prompt-set` | off | Create custom prompt set in AI Red Team from test cases | +| `--prompt-set-name ` | auto | Override auto-generated prompt set name | + +!!! tip "Skip all prompts" + When both `--topic` and `--profile` are provided, interactive mode is skipped entirely. + +```bash +# Interactive — prompts for everything +daystrom runtime topics generate + +# Non-interactive — all inputs via flags +daystrom runtime topics generate \ + --provider claude-api \ + --profile my-security-profile \ + --topic "Block discussions about building explosives" \ + --intent block \ + --target-coverage 90 + +# With test accumulation +daystrom runtime topics generate \ + --topic "Allow recipe discussions" \ + --intent allow \ + --profile cooking-policy \ + --accumulate-tests \ + --max-accumulated-tests 60 +``` + +#### runtime topics resume + +Pick up a paused or failed run from where it left off. + +| Flag | Default | What it does | +|------|---------|-------------| +| `--max-iterations ` | `20` | Additional iterations from current position | +| `--debug-scans` | off | Dump raw AIRS scan responses to JSONL for debugging | +| `--create-prompt-set` | off | Create custom prompt set in AI Red Team from test cases | +| `--prompt-set-name ` | auto | Override auto-generated prompt set name | + +```bash +daystrom runtime topics resume abc123xyz --max-iterations 10 +``` + +#### runtime topics report + +View results for a saved run. + +| Flag | Default | What it does | +|------|---------|-------------| +| `--iteration ` | _(best)_ | Show a specific iteration instead of the best | +| `--format ` | `terminal` | Output format: `terminal`, `json`, `html` | +| `--tests` | _(off)_ | Include per-test-case details | +| `--diff ` | _(none)_ | Compare with another run side-by-side | +| `--output ` | `-report.html` | Output file path (html format only) | + +```bash +daystrom runtime topics report abc123xyz --format html --tests +daystrom runtime topics report abc123xyz --diff def456uvw +``` + +#### runtime topics runs + +List all saved generation runs. + +```bash +daystrom runtime topics runs +``` + ### runtime api-keys API key management. @@ -390,39 +346,17 @@ daystrom runtime scan-logs query --interval --unit [options] --- -## audit - -Evaluate all topics in an AIRS security profile. Generates tests per topic, scans them, computes per-topic and composite metrics, and detects cross-topic conflicts. - -```bash -daystrom audit [options] -``` - -### Options +## Deprecated Top-Level Aliases -| Flag | Default | What it does | -|------|---------|-------------| -| `--max-tests-per-topic ` | `20` | Max test cases generated per topic | -| `--format ` | `terminal` | Output format: `terminal`, `json`, `html` | -| `--output ` | `-audit.html` | Output file path (html format only) | -| `--provider ` | `claude-api` | LLM provider | -| `--model ` | per-provider | Override default model | +The following top-level commands still work but print a deprecation warning. Use the `runtime` subcommand paths instead: -### Examples - -```bash -# Audit all topics in a profile -daystrom audit my-security-profile - -# JSON export -daystrom audit my-security-profile --format json - -# HTML report -daystrom audit my-security-profile --format html --output audit-report.html - -# Limit test generation -daystrom audit my-security-profile --max-tests-per-topic 20 -``` +| Deprecated | New path | +|-----------|----------| +| `daystrom generate` | `daystrom runtime topics generate` | +| `daystrom resume` | `daystrom runtime topics resume` | +| `daystrom report` | `daystrom runtime topics report` | +| `daystrom list` | `daystrom runtime topics runs` | +| `daystrom audit` | `daystrom runtime profiles audit` | --- diff --git a/package.json b/package.json index a72229d..5bb5513 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@cdot65/daystrom", "packageManager": "pnpm@10.6.5", - "version": "1.14.2", + "version": "1.15.0", "description": "CLI and library for Palo Alto Prisma AIRS — guardrail refinement, AI red teaming, model security scanning, profile audits", "type": "module", "main": "dist/index.js", diff --git a/src/cli/commands/audit.ts b/src/cli/commands/audit.ts index 0bb397a..64e20b6 100644 --- a/src/cli/commands/audit.ts +++ b/src/cli/commands/audit.ts @@ -17,8 +17,8 @@ import { } from '../renderer/index.js'; /** Register the `audit` command — evaluate all topics in a profile. */ -export function registerAuditCommand(program: Command): void { - program +export function registerAuditCommand(parent: Command): void { + parent .command('audit ') .description('Evaluate all topics in a security profile') .option('--max-tests-per-topic ', 'Max tests per topic', '20') diff --git a/src/cli/commands/generate.ts b/src/cli/commands/generate.ts index 6eb74d9..189f15f 100644 --- a/src/cli/commands/generate.ts +++ b/src/cli/commands/generate.ts @@ -33,8 +33,8 @@ import { } from '../renderer/index.js'; /** Register the `generate` command — starts a new guardrail generation loop. */ -export function registerGenerateCommand(program: Command): void { - program +export function registerGenerateCommand(parent: Command): void { + parent .command('generate') .description('Start a new guardrail generation loop') .option('--provider ', 'LLM provider') diff --git a/src/cli/commands/list.ts b/src/cli/commands/list.ts index 400e54f..cb8e2c2 100644 --- a/src/cli/commands/list.ts +++ b/src/cli/commands/list.ts @@ -3,11 +3,11 @@ import { loadConfig } from '../../config/loader.js'; import { JsonFileStore } from '../../persistence/store.js'; import { renderError, renderHeader, renderRunList } from '../renderer/index.js'; -/** Register the `list` command — lists all saved runs. */ -export function registerListCommand(program: Command): void { - program - .command('list') - .description('List all saved runs') +/** Register the `list` (or `runs`) command — lists all saved runs. */ +export function registerListCommand(parent: Command, commandName = 'list'): void { + parent + .command(commandName) + .description('List all saved generation runs') .action(async () => { try { renderHeader(); diff --git a/src/cli/commands/report.ts b/src/cli/commands/report.ts index e539928..6d35453 100644 --- a/src/cli/commands/report.ts +++ b/src/cli/commands/report.ts @@ -15,8 +15,8 @@ import { } from '../renderer/index.js'; /** Register the `report` command — view detailed results for a run. */ -export function registerReportCommand(program: Command): void { - program +export function registerReportCommand(parent: Command): void { + parent .command('report ') .description('View detailed report for a run') .option('--iteration ', 'Show specific iteration') diff --git a/src/cli/commands/resume.ts b/src/cli/commands/resume.ts index 5c39f18..758913b 100644 --- a/src/cli/commands/resume.ts +++ b/src/cli/commands/resume.ts @@ -25,8 +25,8 @@ import { } from '../renderer/index.js'; /** Register the `resume` command — resumes a paused or failed run. */ -export function registerResumeCommand(program: Command): void { - program +export function registerResumeCommand(parent: Command): void { + parent .command('resume ') .description('Resume a paused or failed run') .option('--max-iterations ', 'Additional iterations to run', '10') diff --git a/src/cli/commands/runtime.ts b/src/cli/commands/runtime.ts index 1c363e2..31acce2 100644 --- a/src/cli/commands/runtime.ts +++ b/src/cli/commands/runtime.ts @@ -23,6 +23,11 @@ import { renderTopicDetail, renderTopicList, } from '../renderer/index.js'; +import { registerAuditCommand } from './audit.js'; +import { registerGenerateCommand } from './generate.js'; +import { registerListCommand } from './list.js'; +import { registerReportCommand } from './report.js'; +import { registerResumeCommand } from './resume.js'; function renderScanResult(result: RuntimeScanResult): void { const actionColor = result.action === 'block' ? chalk.red : chalk.green; @@ -308,10 +313,15 @@ export function registerRuntimeCommand(program: Command): void { } }); + // Register audit under profiles + registerAuditCommand(profiles); + // ----------------------------------------------------------------------- - // runtime topics — custom topic CRUD subcommands + // runtime topics — custom topic CRUD + guardrail generation subcommands // ----------------------------------------------------------------------- - const topics = runtime.command('topics').description('Manage AIRS custom topics'); + const topics = runtime + .command('topics') + .description('Manage AIRS custom topics and guardrail generation'); topics .command('list') @@ -395,6 +405,12 @@ export function registerRuntimeCommand(program: Command): void { } }); + // Register guardrail generation commands under topics + registerGenerateCommand(topics); + registerResumeCommand(topics); + registerReportCommand(topics); + registerListCommand(topics, 'runs'); + // ----------------------------------------------------------------------- // runtime api-keys — API key management subcommands // ----------------------------------------------------------------------- diff --git a/src/cli/index.ts b/src/cli/index.ts index 9fd24f0..7ed583e 100644 --- a/src/cli/index.ts +++ b/src/cli/index.ts @@ -4,6 +4,7 @@ import { readFileSync } from 'node:fs'; import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; import 'dotenv/config'; +import chalk from 'chalk'; import { Command } from 'commander'; import { registerAuditCommand } from './commands/audit.js'; import { registerGenerateCommand } from './commands/generate.js'; @@ -26,13 +27,35 @@ program ) .version(pkg.version); -registerGenerateCommand(program); -registerResumeCommand(program); -registerReportCommand(program); -registerListCommand(program); +// Primary command groups registerRuntimeCommand(program); registerRedteamCommand(program); registerModelSecurityCommand(program); -registerAuditCommand(program); + +// --------------------------------------------------------------------------- +// Backward-compatible top-level aliases (deprecated — use runtime subcommands) +// --------------------------------------------------------------------------- +const deprecationNotice = (oldCmd: string, newCmd: string) => + chalk.yellow(`[deprecated] "daystrom ${oldCmd}" → use "daystrom ${newCmd}"`); + +function registerDeprecated( + registerFn: (parent: Command, name?: string) => void, + oldCmd: string, + newCmd: string, +) { + registerFn(program); + const cmd = program.commands.find((c) => c.name() === oldCmd); + if (cmd) { + cmd.hook('preAction', () => { + console.error(deprecationNotice(oldCmd, newCmd)); + }); + } +} + +registerDeprecated(registerGenerateCommand, 'generate', 'runtime topics generate'); +registerDeprecated(registerResumeCommand, 'resume', 'runtime topics resume'); +registerDeprecated(registerReportCommand, 'report', 'runtime topics report'); +registerDeprecated(registerListCommand, 'list', 'runtime topics runs'); +registerDeprecated(registerAuditCommand, 'audit', 'runtime profiles audit'); program.parse();