Skip to content
This repository was archived by the owner on Mar 14, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@cdot65/daystrom",
"name": "@cdot65/prisma-airs-cli",
"packageManager": "pnpm@10.6.5",
"version": "1.15.0",
"version": "2.0.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",
Expand All @@ -10,7 +10,7 @@
"dist"
],
"bin": {
"daystrom": "dist/cli/index.js"
"airs": "dist/cli/index.js"
},
"scripts": {
"build": "tsc",
Expand All @@ -25,18 +25,18 @@
"lint:fix": "biome check --write .",
"format": "biome format --write .",
"format:check": "biome format .",
"docker:build": "docker build -t daystrom:local .",
"docker:build:amd64": "docker buildx build --platform linux/amd64 --load -t daystrom:local-amd64 .",
"docker:build:arm64": "docker buildx build --platform linux/arm64 --load -t daystrom:local-arm64 .",
"docker:run": "docker run --rm -v ~/.daystrom:/root/.daystrom daystrom:local",
"docker:build": "docker build -t prisma-airs-cli:local .",
"docker:build:amd64": "docker buildx build --platform linux/amd64 --load -t prisma-airs-cli:local-amd64 .",
"docker:build:arm64": "docker buildx build --platform linux/arm64 --load -t prisma-airs-cli:local-arm64 .",
"docker:run": "docker run --rm -v ~/.prisma-airs:/root/.prisma-airs prisma-airs-cli:local",
"docker:push:arm64": "./scripts/docker-push-arm64.sh"
},
"engines": {
"node": ">=20.0.0"
},
"repository": {
"type": "git",
"url": "https://github.com/cdot65/daystrom.git"
"url": "https://github.com/cdot65/prisma-airs-cli.git"
},
"license": "MIT",
"dependencies": {
Expand Down
4 changes: 2 additions & 2 deletions src/audit/report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export function buildAuditReportHtml(result: AuditResult): string {
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Daystrom Audit — ${esc(result.profileName)}</title>
<title>Prisma AIRS CLI Audit — ${esc(result.profileName)}</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; max-width: 1200px; margin: 0 auto; padding: 2rem; background: #f8f9fa; color: #212529; }
Expand Down Expand Up @@ -151,7 +151,7 @@ export function buildAuditReportHtml(result: AuditResult): string {
</head>
<body>
<div class="header">
<h1>Daystrom Profile Audit</h1>
<h1>Prisma AIRS CLI Profile Audit</h1>
<p class="meta">Profile: ${esc(result.profileName)} | ${esc(result.timestamp)}</p>
</div>

Expand Down
4 changes: 2 additions & 2 deletions src/cli/commands/redteam.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,10 @@ export function registerRedteamCommand(program: Command): void {
console.log('\n');
renderScanStatus(completed);
console.log(` Job ID: ${completed.uuid}`);
console.log(' Run `daystrom redteam report <jobId>` to view results.\n');
console.log(' Run `airs redteam report <jobId>` to view results.\n');
} else {
console.log(` Job ID: ${job.uuid}`);
console.log(' Run `daystrom redteam status <jobId>` to check progress.\n');
console.log(' Run `airs redteam status <jobId>` to check progress.\n');
}
} catch (err) {
renderError(err instanceof Error ? err.message : String(err));
Expand Down
2 changes: 1 addition & 1 deletion src/cli/commands/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export function registerRuntimeCommand(program: Command): void {
process.exit(1);
}

const sessionId = opts.sessionId ?? `daystrom-bulk-${Date.now().toString(36)}`;
const sessionId = opts.sessionId ?? `prisma-airs-cli-bulk-${Date.now().toString(36)}`;

const service = new SdkRuntimeService(config.airsApiKey);
console.log(chalk.bold.cyan('\n Prisma AIRS Bulk Scan'));
Expand Down
4 changes: 2 additions & 2 deletions src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const pkg = JSON.parse(readFileSync(join(__dirname, '../../package.json'), 'utf-
const program = new Command();

program
.name('daystrom')
.name('airs')
.description(
'CLI and library for Palo Alto Prisma AIRS — guardrail refinement, AI red teaming, model security scanning, profile audits',
)
Expand All @@ -36,7 +36,7 @@ registerModelSecurityCommand(program);
// Backward-compatible top-level aliases (deprecated — use runtime subcommands)
// ---------------------------------------------------------------------------
const deprecationNotice = (oldCmd: string, newCmd: string) =>
chalk.yellow(`[deprecated] "daystrom ${oldCmd}" → use "daystrom ${newCmd}"`);
chalk.yellow(`[deprecated] "airs ${oldCmd}" → use "airs ${newCmd}"`);

function registerDeprecated(
registerFn: (parent: Command, name?: string) => void,
Expand Down
2 changes: 1 addition & 1 deletion src/config/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export async function loadConfig(
cliOverrides: Record<string, unknown> = {},
configFilePath?: string,
): Promise<Config> {
const filePath = configFilePath ?? join(homedir(), '.daystrom', 'config.json');
const filePath = configFilePath ?? join(homedir(), '.prisma-airs', 'config.json');
const fileConfig = await fromFile(filePath);
const envConfig = fromEnv();

Expand Down
4 changes: 2 additions & 2 deletions src/config/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ export const ConfigSchema = z.object({
maxAccumulatedTests: z.coerce.number().int().min(1).optional(),

// Persistence
dataDir: z.string().default('~/.daystrom/runs'),
dataDir: z.string().default('~/.prisma-airs/runs'),

// Memory
memoryEnabled: z.coerce.boolean().default(true),
memoryDir: z.string().default('~/.daystrom/memory'),
memoryDir: z.string().default('~/.prisma-airs/memory'),
maxMemoryChars: z.coerce.number().int().min(500).max(10000).default(3000),
});

Expand Down
8 changes: 4 additions & 4 deletions src/core/loop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ export async function* runLoop(
const probeResult = await deps.scanner.scan(
input.profileName,
probePrompt,
`daystrom-${runState.id.slice(0, 7)}-probe`,
`prisma-airs-cli-${runState.id.slice(0, 7)}-probe`,
);

const matched = probeResult.triggered;
Expand Down Expand Up @@ -471,7 +471,7 @@ export async function* runLoop(
accumulatedTests = allTests;

// Step 4: Run scans
const sessionId = `daystrom-${runState.id.slice(0, 7)}-iter${i}`;
const sessionId = `prisma-airs-cli-${runState.id.slice(0, 7)}-iter${i}`;
const testResults: TestResult[] = [];
const prompts = allTests.map((t) => t.prompt);
const scanResults = await deps.scanner.scanBatch(
Expand Down Expand Up @@ -630,10 +630,10 @@ export async function* runLoop(
// Create custom prompt set from best iteration's test cases if requested
if (input.createPromptSet && deps.promptSets && bestResult) {
const setName =
input.promptSetName ?? `daystrom-${bestResult.topic.name}-${runState.id.slice(0, 7)}`;
input.promptSetName ?? `prisma-airs-cli-${bestResult.topic.name}-${runState.id.slice(0, 7)}`;
const { uuid } = await deps.promptSets.createPromptSet(
setName,
`Generated by Daystrom run ${runState.id} — ${bestResult.testCases.length} prompts from iteration ${bestResult.iteration}`,
`Generated by Prisma AIRS CLI run ${runState.id} — ${bestResult.testCases.length} prompts from iteration ${bestResult.iteration}`,
);

for (const tc of bestResult.testCases) {
Expand Down
2 changes: 1 addition & 1 deletion src/core/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Core domain types — shared across all Daystrom modules.
* Core domain types — shared across all Prisma AIRS CLI modules.
*/

// ---------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Daystrom — Public library API
* Prisma AIRS CLI — Public library API
*
* Automated generation, testing, and iterative refinement of
* Palo Alto Prisma AIRS custom topic guardrails.
Expand Down
4 changes: 2 additions & 2 deletions src/report/html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ export function buildReportHtml(report: ReportOutput): string {
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Daystrom Report — ${esc(report.run.id)}</title>
<title>Prisma AIRS CLI Report — ${esc(report.run.id)}</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; max-width: 1200px; margin: 0 auto; padding: 2rem; background: #f8f9fa; color: #212529; }
Expand Down Expand Up @@ -196,7 +196,7 @@ export function buildReportHtml(report: ReportOutput): string {
</head>
<body>
<div class="header">
<h1>Daystrom Evaluation Report</h1>
<h1>Prisma AIRS CLI Evaluation Report</h1>
<p class="meta">Generated ${esc(report.generatedAt)} | Run ${esc(report.run.id)}</p>
</div>

Expand Down
2 changes: 1 addition & 1 deletion tests/integration/loop.integration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ describe('Loop Integration', () => {
if (psEvent?.type === 'promptset:created') {
expect(psEvent.promptSetId).toBe('ps-1');
expect(psEvent.promptCount).toBe(8); // 4 positive + 4 negative from deterministic LLM
expect(psEvent.promptSetName).toContain('daystrom-Weapons Discussion-');
expect(psEvent.promptSetName).toContain('prisma-airs-cli-Weapons Discussion-');
}

// Verify event ordering: promptset:created before loop:complete
Expand Down
8 changes: 4 additions & 4 deletions tests/unit/airs/promptsets.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,19 @@ describe('SdkPromptSetService', () => {
it('creates a prompt set and returns uuid + name', async () => {
mockCreatePromptSet.mockResolvedValue({
uuid: 'ps-abc',
name: 'daystrom-weapons-abc1234',
name: 'prisma-airs-cli-weapons-abc1234',
active: true,
archive: false,
status: 'active',
created_at: '2026-03-08T00:00:00Z',
updated_at: '2026-03-08T00:00:00Z',
});

const result = await service.createPromptSet('daystrom-weapons-abc1234', 'Test desc');
const result = await service.createPromptSet('prisma-airs-cli-weapons-abc1234', 'Test desc');
expect(result.uuid).toBe('ps-abc');
expect(result.name).toBe('daystrom-weapons-abc1234');
expect(result.name).toBe('prisma-airs-cli-weapons-abc1234');
expect(mockCreatePromptSet).toHaveBeenCalledWith({
name: 'daystrom-weapons-abc1234',
name: 'prisma-airs-cli-weapons-abc1234',
description: 'Test desc',
});
});
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/airs/redteam.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ describe('SdkRedTeamService', () => {
custom_attack_reports: [
{
prompt_set_id: 'ps-1',
prompt_set_name: 'daystrom-weapons',
prompt_set_name: 'prisma-airs-cli-weapons',
total_prompts: 20,
total_attacks: 20,
total_threats: 5,
Expand All @@ -371,7 +371,7 @@ describe('SdkRedTeamService', () => {
expect(result.score).toBe(80);
expect(result.asr).toBe(0.2);
expect(result.promptSets).toHaveLength(1);
expect(result.promptSets[0].promptSetName).toBe('daystrom-weapons');
expect(result.promptSets[0].promptSetName).toBe('prisma-airs-cli-weapons');
expect(result.promptSets[0].threatRate).toBe(0.25);
});

Expand Down
4 changes: 2 additions & 2 deletions tests/unit/airs/scanner.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,11 @@ describe('AirsScanService', () => {
prompt_detected: {},
});

await service.scan('prof', 'hello', 'daystrom-abc1234-iter1');
await service.scan('prof', 'hello', 'prisma-airs-cli-abc1234-iter1');
expect(mockSyncScan).toHaveBeenCalledWith(
expect.objectContaining({ profile_name: 'prof' }),
expect.anything(),
{ sessionId: 'daystrom-abc1234-iter1' },
{ sessionId: 'prisma-airs-cli-abc1234-iter1' },
);
});

Expand Down
6 changes: 3 additions & 3 deletions tests/unit/config/loader.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,13 @@ describe('loadConfig', () => {

it('expands ~ in dataDir', async () => {
const config = await loadConfig({}, configPath);
expect(config.dataDir).toBe(join(homedir(), '.daystrom/runs'));
expect(config.dataDir).toBe(join(homedir(), '.prisma-airs/runs'));
expect(config.dataDir).not.toContain('~');
});

it('expands ~ in memoryDir', async () => {
const config = await loadConfig({}, configPath);
expect(config.memoryDir).toBe(join(homedir(), '.daystrom/memory'));
expect(config.memoryDir).toBe(join(homedir(), '.prisma-airs/memory'));
});

it('treats empty strings as unset (stripUndefined)', async () => {
Expand All @@ -120,7 +120,7 @@ describe('loadConfig', () => {
});

it('uses default config file path when configFilePath not provided', async () => {
// loadConfig with no configFilePath reads from ~/.daystrom/config.json (likely missing)
// loadConfig with no configFilePath reads from ~/.prisma-airs/config.json (likely missing)
const config = await loadConfig({});
expect(config.llmProvider).toBe('claude-api');
});
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/config/schema.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ describe('ConfigSchema', () => {
expect(config.awsRegion).toBe('us-east-1');
expect(config.scanConcurrency).toBe(5);
expect(config.propagationDelayMs).toBe(10000);
expect(config.dataDir).toBe('~/.daystrom/runs');
expect(config.dataDir).toBe('~/.prisma-airs/runs');
expect(config.memoryEnabled).toBe(true);
expect(config.memoryDir).toBe('~/.daystrom/memory');
expect(config.memoryDir).toBe('~/.prisma-airs/memory');
expect(config.maxMemoryChars).toBe(3000);
});

Expand Down
2 changes: 1 addition & 1 deletion tests/unit/core/loop.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1852,7 +1852,7 @@ describe('runLoop', () => {
if (psEvent?.type === 'promptset:created') {
expect(psEvent.promptSetId).toBe('ps-1');
expect(psEvent.promptCount).toBe(4); // 2 positive + 2 negative from mock LLM
expect(psEvent.promptSetName).toContain('daystrom-');
expect(psEvent.promptSetName).toContain('prisma-airs-cli-');
}
});

Expand Down
Loading