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
42 changes: 42 additions & 0 deletions .github/workflows/sourceos-interaction-codegen.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: SourceOS Interaction Codegen

on:
pull_request:
branches: ["main"]
paths:
- "schemas/SourceOSInteractionEvent.json"
- "generated/typescript/sourceos-interaction-event.ts"
- "generated/python/sourceos_interaction_event.py"
- "tools/generate_sourceos_interaction_types.py"
- ".github/workflows/sourceos-interaction-codegen.yml"
- "docs/contract-additions/sourceos-interaction-catalog.md"
push:
branches: ["main", "work/interaction-codegen-116"]
paths:
- "schemas/SourceOSInteractionEvent.json"
- "generated/typescript/sourceos-interaction-event.ts"
- "generated/python/sourceos_interaction_event.py"
- "tools/generate_sourceos_interaction_types.py"
- ".github/workflows/sourceos-interaction-codegen.yml"
- "docs/contract-additions/sourceos-interaction-catalog.md"

permissions:
contents: read

jobs:
validate-interaction-codegen:
name: Validate generated interaction types
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Check generated files are current
run: python tools/generate_sourceos_interaction_types.py --check

- name: Compile generated Python type module
run: python -m py_compile generated/python/sourceos_interaction_event.py
39 changes: 36 additions & 3 deletions docs/contract-additions/sourceos-interaction-catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,41 @@ The key architectural rule is that Noetica and AgentTerm are separate surfaces o
| --- | --- |
| `schemas/SourceOSInteractionEvent.json` | Machine-readable JSON Schema for the shared interaction envelope. |
| `examples/sourceos-interaction-event.json` | Valid Noetica standalone completion example consumable by AgentTerm. |
| `generated/typescript/sourceos-interaction-event.ts` | Generated TypeScript interface/union definitions for downstream TypeScript consumers. |
| `generated/python/sourceos_interaction_event.py` | Generated Python `TypedDict` / `Literal` definitions for downstream Python consumers. |
| `tools/generate_sourceos_interaction_types.py` | Generator and stale-output checker for the generated artifacts. |
| `tools/validate_sourceos_interaction_examples.py` | Dedicated validator for the schema/example pair. |
| `.github/workflows/sourceos-interaction-substrate.yml` | CI workflow for the interaction-substrate slice. |
| `.github/workflows/sourceos-interaction-substrate.yml` | CI workflow for the interaction-substrate schema/example slice. |
| `.github/workflows/sourceos-interaction-codegen.yml` | CI workflow that checks generated artifacts are current. |
| `docs/contract-additions/sourceos-interaction-substrate.md` | Normative design and authority-boundary contract. |

## Generated type consumption

The canonical generation command is:

```bash
python tools/generate_sourceos_interaction_types.py
```

The canonical drift check is:

```bash
python tools/generate_sourceos_interaction_types.py --check
```

Downstream repositories may consume the generated artifacts by vendoring from a pinned `sourceos-spec` commit, importing from a subtree/submodule, or running the generator during their own contract-sync process.

Recommended downstream mapping:

| Consumer | Generated artifact |
| --- | --- |
| `SocioProphet/Noetica` | `generated/typescript/sourceos-interaction-event.ts` |
| `SourceOS-Linux/agent-term` | `generated/python/sourceos_interaction_event.py` |
| `SocioProphet/superconscious` | Python or TypeScript artifact depending on implementation lane |
| `SocioProphet/agentplane` | Python or TypeScript artifact depending on implementation lane |

Schema changes must update the generated artifacts in the same PR. CI should fail when the generated files are stale.

## Required downstream bindings

| Repository | Binding obligation |
Expand Down Expand Up @@ -67,10 +98,12 @@ AgentTerm Matrix or terminal command

## Completion status

Initial implementation status at catalog creation:
Initial implementation status after codegen tranche:

- SourceOS spec schema/example/validator/workflow: merged.
- AgentTerm fixture ingest/render path: merged.
- Noetica emitter path: merged.
- TypeScript and Python generated artifacts: present.
- Drift check workflow: present.

Future work should add generated types or schema-consumption automation when the downstream repositories are ready for a shared package or codegen path.
Future work should migrate Noetica and AgentTerm from local mirrors to the generated artifacts or a pinned contract-sync process.
106 changes: 106 additions & 0 deletions generated/python/sourceos_interaction_event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Generated from schemas/SourceOSInteractionEvent.json.
# Do not edit by hand. Run: python tools/generate_sourceos_interaction_types.py

from __future__ import annotations

from typing import Any, Literal, NotRequired, TypedDict


SOURCEOS_INTERACTION_EVENT_REQUIRED = ['interactionEventId', 'type', 'specVersion', 'eventClass', 'occurredAt', 'surface', 'mode', 'session', 'actor', 'payloadMode', 'governanceTrace']

SourceOSInteractionEventClass = Literal['interaction.session_started', 'interaction.message_posted', 'interaction.task_submitted', 'interaction.task_stream_delta', 'interaction.task_completed', 'interaction.task_failed', 'interaction.governance_trace', 'interaction.steering_intent', 'interaction.memory_scope_bound', 'interaction.context_pack_bound', 'interaction.policy_decision', 'interaction.approval_requested', 'interaction.approval_recorded', 'interaction.redacted']
SourceOSInteractionSurfaceKind = Literal['noetica', 'agent-term', 'matrix', 'prophet-workspace', 'superconscious', 'agentplane', 'api', 'other']
SourceOSInteractionMode = Literal['standalone', 'sourceos', 'dry-run', 'replay']
SourceOSInteractionActorKind = Literal['human', 'agent', 'service', 'bot', 'system']
SourceOSInteractionParticipantRole = Literal['user', 'assistant', 'operator', 'agent', 'provider', 'tool', 'observer']
SourceOSInteractionTaskStatus = Literal['submitted', 'streaming', 'success', 'failure', 'blocked', 'unavailable', 'not_configured']
SourceOSSteeringKind = Literal['none', 'neuronpedia_feature', 'local_sae', 'sourceos_local', 'other']
SourceOSSteeringStatus = Literal['requested', 'applied', 'noop', 'not_configured', 'blocked']
SourceOSInteractionPayloadMode = Literal['metadata-only', 'summary', 'ref-only', 'inline-bounded', 'redacted']


class SourceOSInteractionSurface(TypedDict):
surfaceKind: SourceOSInteractionSurfaceKind
sourcePlane: str
clientRef: NotRequired[str | None]


class SourceOSInteractionSession(TypedDict):
sessionId: str
conversationRef: NotRequired[str | None]
roomRef: NotRequired[str | None]
threadRef: NotRequired[str | None]
workroomRef: NotRequired[str | None]
topicRef: NotRequired[str | None]
opsHistoryEventRef: NotRequired[str | None]


class SourceOSInteractionActor(TypedDict):
actorRef: str
actorKind: SourceOSInteractionActorKind
agentRegistryRef: NotRequired[str | None]
onBehalfOfRef: NotRequired[str | None]


class SourceOSInteractionParticipant(TypedDict):
role: SourceOSInteractionParticipantRole
participantRef: str
agentRegistryRef: NotRequired[str | None]


class SourceOSInteractionTask(TypedDict, total=False):
taskRef: str | None
status: SourceOSInteractionTaskStatus
modelHint: str | None
modelRouted: str | None
provider: str | None
latencyMs: int | None


class SourceOSSteeringIntent(TypedDict, total=False):
steeringKind: SourceOSSteeringKind
featureRef: str | None
strength: float | None
status: SourceOSSteeringStatus


class SourceOSGovernanceTrace(TypedDict):
policyAdmitted: bool
memoryWritten: bool
policyRef: NotRequired[str | None]
policyDecisionRefs: NotRequired[list[str]]
grantRefs: NotRequired[list[str]]
memoryScopeRef: NotRequired[str | None]
contextPackRefs: NotRequired[list[str]]
requestHash: NotRequired[str | None]
evidenceHash: NotRequired[str | None]
providerRouteEvidenceRef: NotRequired[str | None]
agentPlaneRunRef: NotRequired[str | None]
evidenceRefs: NotRequired[list[str]]
replayRef: NotRequired[str | None]


class SourceOSInteractionIntegrity(TypedDict, total=False):
eventHash: str | None
signature: str | None


class SourceOSInteractionEvent(TypedDict):
interactionEventId: str
type: Literal["SourceOSInteractionEvent"]
specVersion: str
eventClass: SourceOSInteractionEventClass
occurredAt: str
surface: SourceOSInteractionSurface
mode: SourceOSInteractionMode
session: SourceOSInteractionSession
actor: SourceOSInteractionActor
payloadMode: SourceOSInteractionPayloadMode
governanceTrace: SourceOSGovernanceTrace
participants: NotRequired[list[SourceOSInteractionParticipant]]
task: NotRequired[SourceOSInteractionTask | None]
steeringIntent: NotRequired[SourceOSSteeringIntent | None]
payload: NotRequired[dict[str, Any] | None]
sourceEventRefs: NotRequired[list[str]]
redactionRefs: NotRequired[list[str]]
integrity: NotRequired[SourceOSInteractionIntegrity | None]
115 changes: 115 additions & 0 deletions generated/typescript/sourceos-interaction-event.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Generated from schemas/SourceOSInteractionEvent.json.
// Do not edit by hand. Run: python tools/generate_sourceos_interaction_types.py

export const SOURCEOS_INTERACTION_EVENT_REQUIRED = [
"interactionEventId",
"type",
"specVersion",
"eventClass",
"occurredAt",
"surface",
"mode",
"session",
"actor",
"payloadMode",
"governanceTrace"
] as const

export type SourceOSInteractionEventClass = "interaction.session_started" | "interaction.message_posted" | "interaction.task_submitted" | "interaction.task_stream_delta" | "interaction.task_completed" | "interaction.task_failed" | "interaction.governance_trace" | "interaction.steering_intent" | "interaction.memory_scope_bound" | "interaction.context_pack_bound" | "interaction.policy_decision" | "interaction.approval_requested" | "interaction.approval_recorded" | "interaction.redacted"
export type SourceOSInteractionSurfaceKind = "noetica" | "agent-term" | "matrix" | "prophet-workspace" | "superconscious" | "agentplane" | "api" | "other"
export type SourceOSInteractionMode = "standalone" | "sourceos" | "dry-run" | "replay"
export type SourceOSInteractionActorKind = "human" | "agent" | "service" | "bot" | "system"
export type SourceOSInteractionParticipantRole = "user" | "assistant" | "operator" | "agent" | "provider" | "tool" | "observer"
export type SourceOSInteractionTaskStatus = "submitted" | "streaming" | "success" | "failure" | "blocked" | "unavailable" | "not_configured"
export type SourceOSSteeringKind = "none" | "neuronpedia_feature" | "local_sae" | "sourceos_local" | "other"
export type SourceOSSteeringStatus = "requested" | "applied" | "noop" | "not_configured" | "blocked"
export type SourceOSInteractionPayloadMode = "metadata-only" | "summary" | "ref-only" | "inline-bounded" | "redacted"

export interface SourceOSInteractionSurface {
surfaceKind: SourceOSInteractionSurfaceKind
sourcePlane: string
clientRef?: string | null
}

export interface SourceOSInteractionSession {
sessionId: string
conversationRef?: string | null
roomRef?: string | null
threadRef?: string | null
workroomRef?: string | null
topicRef?: string | null
opsHistoryEventRef?: string | null
}

export interface SourceOSInteractionActor {
actorRef: string
actorKind: SourceOSInteractionActorKind
agentRegistryRef?: string | null
onBehalfOfRef?: string | null
}

export interface SourceOSInteractionParticipant {
role: SourceOSInteractionParticipantRole
participantRef: string
agentRegistryRef?: string | null
}

export interface SourceOSInteractionTask {
taskRef?: string | null
status?: SourceOSInteractionTaskStatus
modelHint?: string | null
modelRouted?: string | null
provider?: string | null
latencyMs?: number | null
}

export interface SourceOSSteeringIntent {
steeringKind?: SourceOSSteeringKind
featureRef?: string | null
strength?: number | null
status?: SourceOSSteeringStatus
}

export interface SourceOSGovernanceTrace {
policyAdmitted: boolean
policyRef?: string | null
policyDecisionRefs?: string[]
grantRefs?: string[]
memoryScopeRef?: string | null
memoryWritten: boolean
contextPackRefs?: string[]
requestHash?: string | null
evidenceHash?: string | null
providerRouteEvidenceRef?: string | null
agentPlaneRunRef?: string | null
evidenceRefs?: string[]
replayRef?: string | null
}

export interface SourceOSInteractionIntegrity {
eventHash?: string | null
signature?: string | null
}

export interface SourceOSInteractionEvent {
interactionEventId: string
type: "SourceOSInteractionEvent"
specVersion: string
eventClass: SourceOSInteractionEventClass
occurredAt: string
surface: SourceOSInteractionSurface
mode: SourceOSInteractionMode
session: SourceOSInteractionSession
actor: SourceOSInteractionActor
participants?: SourceOSInteractionParticipant[]
task?: SourceOSInteractionTask | null
steeringIntent?: SourceOSSteeringIntent | null
governanceTrace: SourceOSGovernanceTrace
payloadMode: SourceOSInteractionPayloadMode
payload?: Record<string, unknown> | null
sourceEventRefs?: string[]
redactionRefs?: string[]
integrity?: SourceOSInteractionIntegrity | null
}

// Required top-level fields in the canonical schema: interactionEventId, type, specVersion, eventClass, occurredAt, surface, mode, session, actor, payloadMode, governanceTrace
Loading
Loading