Skip to content
Open
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
19 changes: 19 additions & 0 deletions .agents/backlog-policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Backlog Policy

GitHub Project: https://github.com/users/espetro/projects/6

## Refined task fields

- **Milestone** — maps to iteration/quarter (e.g. `2026 Q3`). Create the milestone in the repo if it doesn't exist yet.
- **Size** — effort estimate: `XS`/`S`/`M`/`L`/`XL`. Include testing + bug potential per contact surface.
- **Start date** / **Target date** — scheduled window for the task.
- **Label** — classification, drives client positioning: `feature`, `bug`, `cosmetic`, `infra`. Create the label in the repo if it doesn't exist yet.

## Workflow

1. Create a GitHub issue in `espetro/calca` with title, body, classification label, milestone.
2. Add it to project 6: `gh project item-add 6 --owner espetro --url <issue-url>`.
3. Set Size/Start date/Target date via `gh project item-edit --project-id <id> --id <item-id> --field-id <field-id> ...`.
4. Reference the issue number in the PR description and in the corresponding `.agents/plans/` doc.

No orphan work: every plan/implementation must link back to a refined task here.
7 changes: 1 addition & 6 deletions apps/web/src/shared/types/canvas.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1 @@
export interface Point {
x: number;
y: number;
}

export type ToolMode = "select" | "draw-area" | "edit-component" | "comment";
export type { Point, ToolMode } from "@app/shared";
21 changes: 1 addition & 20 deletions apps/web/src/shared/types/comment.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1 @@
export type CommentStatus = "waiting" | "working" | "done";

export interface CommentMessage {
id: string;
role: "user" | "calca";
text: string;
createdAt: number;
}

export interface Comment {
id: string;
position: import("./canvas").Point; // Relative to the iteration
text: string;
number: number;
resolved?: boolean;
createdAt: number;
status?: CommentStatus;
aiResponse?: string;
thread?: CommentMessage[];
}
export type { Comment, CommentMessage, CommentStatus } from "@app/shared";
37 changes: 1 addition & 36 deletions apps/web/src/shared/types/design.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1 @@
export interface DesignIteration {
id: string;
html: string;
label: string;
position: import("./canvas").Point;
width: number;
height: number;
prompt: string;
comments: import("./comment").Comment[];
isLoading?: boolean;
isRegenerating?: boolean;
}

export interface SummaryData {
title: string;
rationale: string;
}

export interface GenerationGroup {
id: string;
prompt: string;
iterations: DesignIteration[];
position: import("./canvas").Point;
createdAt: number;
summary?: SummaryData;
}

export interface CanvasImage {
id: string;
dataUrl: string; // Base64 data URI
name: string;
width: number;
height: number;
position: import("./canvas").Point;
thumbnail: string; // Smaller version for UI
}
export type { CanvasImage, DesignIteration, GenerationGroup, SummaryData } from "@app/shared";
34 changes: 2 additions & 32 deletions apps/web/src/shared/types/pipeline.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,2 @@
/** Pipeline stages for multi-model generation */

export type PipelineStage =
| "queued"
| "layout"
| "images"
| "compositing"
| "review"
| "refining"
| "done"
| "error";

export interface PipelineStatus {
stage: PipelineStage;
progress: number; // 0-1
skipped?: boolean;
reason?: string;
}

export const STAGE_CONFIG: Record<
PipelineStage,
{ label: string; progress: number; icon: string }
> = {
compositing: { label: "Compositing…", progress: 0.65, icon: "🔧" },
done: { label: "Complete", progress: 1, icon: "✅" },
error: { label: "Error", progress: 0, icon: "❌" },
images: { label: "Adding images…", progress: 0.45, icon: "🎨" },
layout: { label: "Generating layout…", progress: 0.2, icon: "🏗️" },
queued: { label: "Queued", progress: 0, icon: "⏳" },
refining: { label: "Preparing next variation…", progress: 0.9, icon: "✨" },
review: { label: "Reviewing design…", progress: 0.8, icon: "👁️" },
};
export type { PipelineStage, PipelineStatus } from "@app/shared";
export { STAGE_CONFIG } from "@app/shared";
4 changes: 1 addition & 3 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"@ai-sdk/google": "^3.0.61",
"@ai-sdk/openai-compatible": "^2.0.41",
"@ai-sdk/provider": "3.0.8",
"@ai-sdk/provider-utils": "4.0.23",
"@ai-sdk/provider-utils": "^4.0.26",
"@app/logger": "workspace:*",
"ai": "^6.0.156",
"zod": "^4.3.6"
Expand Down
5 changes: 5 additions & 0 deletions packages/shared/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,8 @@ export {
validateSummary,
type SummaryOutput,
} from "./schemas/summary";

export * from "./types/canvas";
export * from "./types/design";
export * from "./types/comment";
export * from "./types/pipeline";
6 changes: 6 additions & 0 deletions packages/shared/src/types/canvas.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface Point {
x: number;
y: number;
}

export type ToolMode = "select" | "draw-area" | "edit-component" | "comment";
22 changes: 22 additions & 0 deletions packages/shared/src/types/comment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { Point } from "./canvas";

export type CommentStatus = "waiting" | "working" | "done";

export interface CommentMessage {
id: string;
role: "user" | "calca";
text: string;
createdAt: number;
}

export interface Comment {
id: string;
position: Point; // Relative to the iteration
text: string;
number: number;
resolved?: boolean;
createdAt: number;
status?: CommentStatus;
aiResponse?: string;
thread?: CommentMessage[];
}
39 changes: 39 additions & 0 deletions packages/shared/src/types/design.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type { Point } from "./canvas";
import type { Comment } from "./comment";

export interface DesignIteration {
id: string;
html: string;
label: string;
position: Point;
width: number;
height: number;
prompt: string;
comments: Comment[];
isLoading?: boolean;
isRegenerating?: boolean;
}

export interface SummaryData {
title: string;
rationale: string;
}

export interface GenerationGroup {
id: string;
prompt: string;
iterations: DesignIteration[];
position: Point;
createdAt: number;
summary?: SummaryData;
}

export interface CanvasImage {
id: string;
dataUrl: string; // Base64 data URI
name: string;
width: number;
height: number;
position: Point;
thumbnail: string; // Smaller version for UI
}
32 changes: 32 additions & 0 deletions packages/shared/src/types/pipeline.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/** Pipeline stages for multi-model generation */

export type PipelineStage =
| "queued"
| "layout"
| "images"
| "compositing"
| "review"
| "refining"
| "done"
| "error";

export interface PipelineStatus {
stage: PipelineStage;
progress: number; // 0-1
skipped?: boolean;
reason?: string;
}

export const STAGE_CONFIG: Record<
PipelineStage,
{ label: string; progress: number; icon: string }
> = {
compositing: { label: "Compositing…", progress: 0.65, icon: "🔧" },
done: { label: "Complete", progress: 1, icon: "✅" },
error: { label: "Error", progress: 0, icon: "❌" },
images: { label: "Adding images…", progress: 0.45, icon: "🎨" },
layout: { label: "Generating layout…", progress: 0.2, icon: "🏗️" },
queued: { label: "Queued", progress: 0, icon: "⏳" },
refining: { label: "Preparing next variation…", progress: 0.9, icon: "✨" },
review: { label: "Reviewing design…", progress: 0.8, icon: "👁️" },
};
Loading