Skip to content
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
2 changes: 1 addition & 1 deletion packages/scaffold-core/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@stackbilt/scaffold-core",
"sideEffects": false,
"version": "1.1.0",
"version": "1.2.0",
"description": "Zero-dependency scaffold engine core — pattern classification, knowledge, governance, codegen, and materializer",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
Expand Down
45 changes: 45 additions & 0 deletions packages/scaffold-core/src/__tests__/oracle-context.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { describe, expect, it } from 'vitest';
import { buildScaffold, buildOracleContext } from '../index';

describe('buildOracleContext', () => {
it('derives all required fields from a LocalScaffoldResult', () => {
const result = buildScaffold('Multi-tenant SaaS API with Stripe billing and JWT auth');
const ctx = buildOracleContext(result);

expect(ctx.intention).toBe(result.facts.intention);
expect(ctx.pattern).toBe(result.classification.pattern);
expect(ctx.meta.confidence).toBe(result.classification.confidence);
expect(ctx.meta.tier2Recommended).toBe(result.tier2Recommended);
expect(ctx.traits).toEqual(result.classification.traits);
expect(ctx.governance.threatModel).toBe(result.governance.threatModel);
expect(ctx.governance.adr001).toBe(result.governance.adr001);
expect(ctx.governance.testPlan).toBe(result.governance.testPlan);
expect(ctx.files.length).toBeGreaterThan(0);
expect(ctx.files.every(f => 'path' in f && 'content' in f && 'role' in f)).toBe(true);
});

it('maps runtime bindings correctly', () => {
const result = buildScaffold('Durable Object-based real-time collaboration service');
const ctx = buildOracleContext(result);

expect(Array.isArray(ctx.runtime.bindings)).toBe(true);
ctx.runtime.bindings.forEach(b => {
expect(b).toHaveProperty('type');
expect(b).toHaveProperty('name');
expect(b).toHaveProperty('binding');
});
});

it('caps topThreats at 5', () => {
const result = buildScaffold('Secure payment processing API with PCI compliance');
const ctx = buildOracleContext(result);
expect(ctx.knowledge.topThreats.length).toBeLessThanOrEqual(5);
});

it('sets adr002 to null when no compliance domains detected', () => {
const result = buildScaffold('Simple scheduled cron worker to clean up old records');
const ctx = buildOracleContext(result);
// adr002 only present for compliance-domain patterns; null otherwise
expect(ctx.governance.adr002 === null || typeof ctx.governance.adr002 === 'string').toBe(true);
});
});
52 changes: 51 additions & 1 deletion packages/scaffold-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export type {
// Top-level types
LocalScaffoldResult,
ScaffoldOptions,
OracleContext,
} from './types';

// ============================================================================
Expand All @@ -51,7 +52,7 @@ export { materializeScaffold } from './materializer/index';
// Orchestrator
// ============================================================================

import type { LocalScaffoldResult, ScaffoldOptions } from './types';
import type { LocalScaffoldResult, OracleContext, ScaffoldOptions } from './types';
import { classify } from './classify/index';
import { getKnowledge } from './knowledge/index';
import { buildGovernance } from './governance/index';
Expand Down Expand Up @@ -127,3 +128,52 @@ export function buildScaffold(
tier2Recommended: classification.confidence < 0.6,
};
}

/**
* Derive oracle context from a LocalScaffoldResult for use by an LLM polish pass.
*
* All fields are derived from the existing result — no additional inference or
* network calls required. Consumers pass this to the oracle instead of the
* old promptContext field that was stripped when migrating from the local shim.
*
* @see stackbilt-web oracle.ts
* @see charter#224
*/
export function buildOracleContext(result: LocalScaffoldResult): OracleContext {
const { classification, knowledge, governance, facts, files, tier2Recommended } = result;
return {
intention: facts.intention,
pattern: classification.pattern,
meta: {
confidence: classification.confidence,
tier2Recommended,
testingLevel: classification.qualityProfile.testingLevel,
complianceDomains: classification.qualityProfile.complianceDomains,
observability: classification.qualityProfile.observability,
authentication: classification.qualityProfile.authentication,
rateLimiting: classification.qualityProfile.rateLimiting,
},
traits: classification.traits,
runtime: {
bindings: facts.bindings.map(b => ({ type: b.type, name: b.name, binding: b.binding })),
piiHandling: classification.qualityProfile.piiHandling,
},
governance: {
threatModel: governance.threatModel,
adr001: governance.adr001,
adr002: governance.adr002 ?? null,
testPlan: governance.testPlan,
},
knowledge: {
adrContext: knowledge.adrContext,
adrDecision: knowledge.adrDecision,
topThreats: knowledge.threats.slice(0, 5).map(t => ({
id: t.id,
description: t.description,
mitigation: t.mitigation,
severity: t.severity,
})),
},
files: files.map(f => ({ path: f.path, content: f.content, role: f.role })),
};
}
41 changes: 41 additions & 0 deletions packages/scaffold-core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,44 @@ export interface ScaffoldOptions {
projectName?: string;
oracle?: boolean;
}

// ============================================================================
// Oracle context — structured input for LLM polish pass
// ============================================================================

/**
* Structured context derived from LocalScaffoldResult for use by an LLM
* oracle pass. All fields are derivable without a TarotScript round-trip.
*
* Build via: buildOracleContext(result: LocalScaffoldResult)
*/
export interface OracleContext {
intention: string;
pattern: string;
meta: {
confidence: number;
tier2Recommended: boolean;
testingLevel: string;
complianceDomains: string[];
observability: boolean;
authentication: boolean;
rateLimiting: boolean;
};
traits: string[];
runtime: {
bindings: Array<{ type: string; name: string; binding: string }>;
piiHandling: boolean;
};
governance: {
threatModel: string;
adr001: string;
adr002: string | null;
testPlan: string;
};
knowledge: {
adrContext: string;
adrDecision: string;
topThreats: Array<{ id: string; description: string; mitigation: string; severity: string }>;
};
files: Array<{ path: string; content: string; role: string }>;
}
Loading