diff --git a/shared/.gitkeep b/shared/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/shared/package.json b/shared/package.json new file mode 100644 index 0000000..d46d3f5 --- /dev/null +++ b/shared/package.json @@ -0,0 +1,19 @@ +{ + "name": "@podman/shared", + "version": "0.0.0", + "private": true, + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + } + }, + "scripts": { + "build": "tsc -p tsconfig.json", + "dev": "tsc -p tsconfig.json --watch", + "typecheck": "tsc -p tsconfig.json --noEmit" + } +} diff --git a/shared/src/collision.ts b/shared/src/collision.ts new file mode 100644 index 0000000..84ecbaf --- /dev/null +++ b/shared/src/collision.ts @@ -0,0 +1,29 @@ +export type CollisionSeverity = 'info' | 'warn' | 'critical'; + +/** + * A detected overlap between two or more engineers' live work, fused from + * vision-derived contexts and GitHub state. + */ +export interface Collision { + id: string; + podId: string; + /** File both engineers are touching. */ + file: string; + /** Symbol-level overlap, if known. */ + symbol?: string; + /** Engineer ids involved in the overlap. */ + engineers: string[]; + severity: CollisionSeverity; + /** Snapshot of relevant GitHub state at detection time. */ + githubState?: GithubStateSnapshot; + detectedAt: string; +} + +export interface GithubStateSnapshot { + /** Open branches touching the file, keyed by engineer/login. */ + branches?: Record; + /** Open PR numbers touching the file. */ + openPrs?: number[]; + /** Whether any involved engineer has unpushed local changes. */ + unpushed?: boolean; +} diff --git a/shared/src/engineer.ts b/shared/src/engineer.ts new file mode 100644 index 0000000..53d94ab --- /dev/null +++ b/shared/src/engineer.ts @@ -0,0 +1,21 @@ +/** + * What PodMan currently believes an engineer is doing, derived from vision on + * their shared screen and refreshed every few seconds. This is the live, + * pre-push signal that the GitHub API cannot see. + */ +export interface EngineerContext { + engineerId: string; + podId: string; + /** File path PodMan sees open/active in the editor, e.g. "src/auth.ts". */ + currentFile?: string; + /** Function/class/symbol being edited, if vision can resolve it. */ + currentSymbol?: string; + /** Higher-level feature/action inferred from the screen. */ + activity?: string; + /** Whether the screen shows uncommitted/unpushed changes (gutter/diff). */ + hasUnpushedChanges?: boolean; + /** 0–1 confidence in this read of the screen. */ + confidence: number; + /** ISO timestamp of the observation this context came from. */ + observedAt: string; +} diff --git a/shared/src/index.ts b/shared/src/index.ts new file mode 100644 index 0000000..76de9c3 --- /dev/null +++ b/shared/src/index.ts @@ -0,0 +1,14 @@ +export type { Pod, Engineer } from './pod.js'; +export type { EngineerContext } from './engineer.js'; +export type { + Collision, + CollisionSeverity, + GithubStateSnapshot, +} from './collision.js'; +export type { + Intervention, + InterventionKind, + InterventionStatus, + SuggestedAction, + SuggestedActionKind, +} from './intervention.js'; diff --git a/shared/src/intervention.ts b/shared/src/intervention.ts new file mode 100644 index 0000000..0d4d606 --- /dev/null +++ b/shared/src/intervention.ts @@ -0,0 +1,24 @@ +export type InterventionKind = 'voice' | 'card'; + +export type InterventionStatus = 'pending' | 'delivered' | 'accepted' | 'dismissed'; + +export type SuggestedActionKind = 'open_sync_pr' | 'ping_teammate' | 'none'; + +/** What PodMan says/does about a collision — the product's hero output. */ +export interface Intervention { + id: string; + collisionId: string; + podId: string; + kind: InterventionKind; + /** Spoken/displayed message, e.g. "Karti and Yahya are both in auth.ts...". */ + message: string; + suggestedAction: SuggestedAction; + status: InterventionStatus; + createdAt: string; +} + +export interface SuggestedAction { + kind: SuggestedActionKind; + /** Free-form payload for the action (e.g. branch names for a sync PR). */ + params?: Record; +} diff --git a/shared/src/pod.ts b/shared/src/pod.ts new file mode 100644 index 0000000..6b25b2b --- /dev/null +++ b/shared/src/pod.ts @@ -0,0 +1,19 @@ +/** A pod is one room of engineers working together (one LiveKit room per pod). */ +export interface Pod { + id: string; + name: string; + /** GitHub repo the pod is working in, as "owner/name". */ + repo: string; + members: Engineer[]; + createdAt: string; +} + +export interface Engineer { + id: string; + /** Display name PodMan uses when it speaks ("Karti and Yahya are both..."). */ + name: string; + /** GitHub login, used to map vision context to GitHub state. */ + githubLogin?: string; + /** LiveKit participant identity for this engineer in the pod room. */ + participantId?: string; +} diff --git a/shared/tsconfig.json b/shared/tsconfig.json new file mode 100644 index 0000000..03ce790 --- /dev/null +++ b/shared/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../tsconfig.base.json", + "compilerOptions": { + "outDir": "./dist", + "rootDir": "./src" + }, + "include": ["src/**/*"] +}