singularity-forge/src/headless-types.ts
Mikael Hugo d33e30e885 feat(notifications): NOTICE_KIND enum, schema v2 dedup, sf-db cleanup
- notification-store: schema v2 — repeatCount/lastTs merge for non-blocking
  notices; NOTICE_KIND enum (SYSTEM_NOTICE, TOOL_NOTICE, BLOCKING_NOTICE,
  USER_VISIBLE) for renderer classification without message parsing
- sf-db: remove gate_runs and audit_events tables (replaced by uok audit.js
  and trace-writer); schema reduced by ~370 lines
- notify-interceptor: tag auto-mode system notices with NOTICE_KIND.SYSTEM_NOTICE
- auto-prompts, guided-flow, system-context: use NOTICE_KIND on emit calls
- cli-status: expanded headless status surface + test coverage
- headless-types: new status fields
- Makefile/justfile: dev workflow improvements
- record-promoter, requirement-promoter: minor cleanup
- sf-db-migration tests: updated for dropped tables
- uok-gate-runner, uok-metrics, uok-outcome, uok-status tests: updated

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-10 20:13:58 +02:00

106 lines
3.6 KiB
TypeScript

/**
* headless-types.ts — shared types for the machine orchestrator surface.
*
* Purpose: provide a single source of truth for the structured result type
* emitted by the `sf headless` machine surface and the output format discriminator,
* so headless.ts, consumers, and tests agree on shape without circular deps.
*
* Consumer: headless.ts (machine orchestrator), external CI scripts parsing batch JSON.
*/
// ---------------------------------------------------------------------------
// Notification Metadata
// ---------------------------------------------------------------------------
/**
* Optional structured metadata that can be attached to a notify() call to
* allow classification without brittle string matching.
*
* When present, headless-events.ts checks these fields first and falls back
* to the legacy text heuristics only for untagged (metadata-absent) events.
*
* Consumer: headless-events.ts classifiers, notification-store.ts dedup.
*/
export interface NotificationMetadata {
/** Semantic kind of this notification. */
kind?: "notice" | "approval_request" | "progress" | "terminal";
/** Whether this notification halts the workflow and requires user action. */
blocking?: boolean;
/** Stable key for deduplication — collapses repeated notices of the same type. */
dedupe_key?: string;
/** Emission source label (extension name, "workflow", etc.). */
source?: string;
/** Long-lived classification for UI/transcript (see NOTICE_KIND in notification-store). */
noticeKind?:
| "system_notice"
| "tool_notice"
| "blocking_notice"
| "user_visible";
/** When false, duplicate rows are never merged (each notify appends a line). */
merge?: boolean;
}
// ---------------------------------------------------------------------------
// Output Format
// ---------------------------------------------------------------------------
/**
* Discriminates the three machine-surface output formats.
*
* Purpose: let callers declare the encoding of session results
* (human-readable text, single JSON blob, or streaming JSONL) without coupling
* output format to surface, protocol, run control, or permission profile.
*
* Consumer: parseHeadlessArgs in headless.ts when handling --output-format.
*/
export type OutputFormat = "text" | "json" | "stream-json";
/**
* Set of supported output-format string values.
*
* Purpose: guard against typos in CLI arguments and provide a fast
* membership test without repeating the literal list.
*
* Consumer: parseHeadlessArgs validation and unit tests.
*/
export const VALID_OUTPUT_FORMATS: ReadonlySet<string> = new Set([
"text",
"json",
"stream-json",
]);
// ---------------------------------------------------------------------------
// Structured JSON Result
// ---------------------------------------------------------------------------
/**
* Shape of the single JSON object written to stdout when --output-format json
* is used in batch (non-streaming) mode.
*
* Purpose: give non-interactive callers (CI pipelines, test harnesses,
* parent processes) a machine-readable contract for session outcome,
* cost, and metadata without scraping stderr.
*
* Consumer: emitBatchJsonResult in headless.ts; live-regression tests.
*/
export interface HeadlessJsonResult {
schemaVersion: 1;
status: "success" | "error" | "blocked" | "cancelled" | "timeout";
exitCode: number;
sessionId?: string;
duration: number;
cost: {
total: number;
input_tokens: number;
output_tokens: number;
cache_read_tokens: number;
cache_write_tokens: number;
};
toolCalls: number;
events: number;
milestone?: string;
phase?: string;
nextAction?: string;
artifacts?: string[];
commits?: string[];
}