SNAPKITTYWEST's picture
push from SNAPKITTYWEST/grisp-shadow-fleet
b8a03fa verified
Raw
History Blame Contribute Delete
6.49 kB
import { fileURLToPath } from 'node:url';
import { appendEvent, verifyChain, getLastSeal, type WormEvent } from './pages/00-worm/index.js';
import { StateImpl } from './pages/01-state/index.js';
import { GovernanceImpl, CapabilityValidator, crisisLanguageDeny } from './pages/02-governance/index.js';
import { WorkflowImpl, MockLLMNode } from './pages/03-workflow/index.js';
import type { IAction, IState_v1, IVerdict, IWorkflow_v1 } from './abstract/interfaces/index.js';
export interface TickResult {
readonly action: IAction;
readonly verdict: IVerdict;
readonly state: IState_v1;
readonly wormEvent: WormEvent;
readonly chainValid: boolean;
readonly lastSeal: string;
readonly trace: ReadonlyArray<PublicReasoningTraceEvent>;
}
export type PublicReasoningTracePhase =
| 'RECEIVED'
| 'GOVERNANCE_CHECK'
| 'STATE_TRANSITION'
| 'WORM_SEAL'
| 'COMPLETE';
export interface PublicReasoningTraceEvent {
readonly traceId: string;
readonly phase: PublicReasoningTracePhase;
readonly tick: number;
readonly agentId: string;
readonly actionId: string;
readonly summary: string;
readonly visibleToUser: true;
readonly timestamp: string;
readonly details?: Record<string, unknown>;
}
export type PublicReasoningTraceListener = (event: PublicReasoningTraceEvent) => void;
export class PublicReasoningTrace {
private readonly events: PublicReasoningTraceEvent[] = [];
private readonly listeners = new Set<PublicReasoningTraceListener>();
subscribe(listener: PublicReasoningTraceListener): () => void {
this.listeners.add(listener);
return () => this.listeners.delete(listener);
}
emit(
phase: PublicReasoningTracePhase,
action: IAction,
summary: string,
details: Record<string, unknown> = {},
): PublicReasoningTraceEvent {
const event: PublicReasoningTraceEvent = {
traceId: `${action.actionId}:${phase}:${this.events.length}`,
phase,
tick: action.tick,
agentId: action.agentId,
actionId: action.actionId,
summary,
visibleToUser: true,
timestamp: new Date().toISOString(),
details,
};
this.events.push(event);
for (const listener of this.listeners) listener(event);
return event;
}
snapshot(): ReadonlyArray<PublicReasoningTraceEvent> {
return [...this.events];
}
clear(): void {
this.events.splice(0, this.events.length);
}
}
export class ShadowOrchestrator {
private currentState: IState_v1;
readonly governance: GovernanceImpl;
readonly workflow: IWorkflow_v1;
readonly trace: PublicReasoningTrace;
constructor(opts: {
state?: StateImpl;
governance?: GovernanceImpl;
workflow?: IWorkflow_v1;
trace?: PublicReasoningTrace;
} = {}) {
this.currentState = opts.state ?? StateImpl.genesis();
this.governance = opts.governance ?? new GovernanceImpl(
[
new CapabilityValidator([
{
grantId: 'grant-demo-agent',
agentId: 'demo-agent',
allowedActionTypes: ['OBSERVE', 'PLAN', 'EXECUTE', 'REFLECT', 'mock_llm_output'],
deniedActionTypes: ['DESTROY'],
seal: 'capability-grant-demo-agent',
},
]),
],
[crisisLanguageDeny],
);
this.workflow = opts.workflow ?? new WorkflowImpl(new Map([
['mock-llm', new MockLLMNode('mock-llm', 'Mock LLM', [], { result: 'model-invariant mock output' })],
]));
this.trace = opts.trace ?? new PublicReasoningTrace();
}
get state(): IState_v1 {
return this.currentState;
}
tick(action: IAction): TickResult {
const traceStart = this.trace.snapshot().length;
this.trace.emit('RECEIVED', action, 'Action received by Shadow Orchestrator.', {
actionType: action.type,
});
const verdict = this.governance.evaluate(action, this.currentState);
this.trace.emit('GOVERNANCE_CHECK', action, `Governance returned ${verdict.kind}.`, {
verdict: verdict.kind,
reason: verdict.reason,
});
if (verdict.kind === 'ALLOW') {
this.currentState = this.currentState.transition(action);
this.trace.emit('STATE_TRANSITION', action, 'State transition applied.', {
stateId: this.currentState.id,
stateTick: this.currentState.tick,
});
} else {
this.trace.emit('STATE_TRANSITION', action, 'State transition blocked by governance.', {
stateId: this.currentState.id,
verdict: verdict.kind,
});
}
const wormEvent = appendEvent(action, this.currentState, verdict.kind);
const chainCheck = verifyChain();
const lastSeal = getLastSeal();
this.trace.emit('WORM_SEAL', action, 'Action verdict sealed to WORM chain.', {
eventIndex: wormEvent.index,
seal: lastSeal,
chainValid: chainCheck.valid,
});
this.trace.emit('COMPLETE', action, 'Public reasoning trace complete.', {
finalVerdict: verdict.kind,
chainValid: chainCheck.valid,
});
return {
action,
verdict,
state: this.currentState,
wormEvent,
chainValid: chainCheck.valid,
lastSeal,
trace: this.trace.snapshot().slice(traceStart),
};
}
}
export function createAction(
tick: number,
type: string,
payload: unknown,
agentId = 'demo-agent',
): IAction {
return {
actionId: `demo-action-${tick}-${type.toLowerCase()}`,
agentId,
type,
payload,
tick,
};
}
export async function runDemo(): Promise<TickResult[]> {
const orchestrator = new ShadowOrchestrator();
const actions = [
createAction(1, 'OBSERVE', { input: 'load shadow state' }),
createAction(2, 'PLAN', { objective: 'compose pages through main.ts' }),
createAction(3, 'EXECUTE', { step: 'append WORM event' }),
createAction(4, 'REFLECT', { check: 'verify chain' }),
createAction(5, 'EXECUTE', { step: 'complete demo run' }),
];
const results = actions.map(action => orchestrator.tick(action));
for (const result of results) {
console.log(JSON.stringify({
tick: result.action.tick,
actionType: result.action.type,
verdict: result.verdict.kind,
stateId: result.state.id,
wormSeal: result.lastSeal,
chainValid: result.chainValid,
trace: result.trace.map(event => ({
phase: event.phase,
summary: event.summary,
})),
}));
}
return results;
}
const isDirectRun = process.argv[1] === fileURLToPath(import.meta.url);
if (isDirectRun) {
await runDemo();
}