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
76 changes: 44 additions & 32 deletions .agents/skills/lumina-pin/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ allowed-tools: Read, Write, Edit, Bash, AskUserQuestion, mcp__lumina__project_ge
## 🎯 核心定位与适用场景

- **约束发布方 (Producer)**:你在开发项目 A 时,修改了公共模块或 API 契约,这将直接影响项目 B、C。此时通过 `pin_push` 将约束推送到目标项目。
- **约束消费方 (Consumer)**:你在进入项目 B 开发时,通过 `pin_list` 和 `pin_consume` 按创建时间升序依序消费未处理的约束,确认适配并闭环。
- **约束消费方 (Consumer)**:你在进入项目 B 开发时,先通过 `pin_peek` 或 `pin_list` 只读读取待处理约束正文,评估影响并做出技术决策;完成代码适配或确认知晓后,再调用 `pin_consume` 显式确认消费并闭环。

---

Expand All @@ -33,11 +33,11 @@ allowed-tools: Read, Write, Edit, Bash, AskUserQuestion, mcp__lumina__project_ge
pin_push(to="B", priority, content) │
│ │
▼ (落库进入 B 的 FIFO 队列) │
[Pending] ──────────────────────────────▶ pin_list(project="B", status="pending")
│
[Pending] ──────────────────────────────▶ pin_peek(project="B") 或 pin_list
│ (只读读取正文,状态仍为 Pending,开展本地决策与适配)
▼
pin_consume(project="B")
│
pin_consume(project="B", id="...")
│ (代码适配完成,显式确认消费闭环)
▼
[Consumed] (状态单向归档)
```
Expand All @@ -63,8 +63,19 @@ pin_push(to="B", priority, content) │

---

### 2. 查阅项目约束队列 (`pin_list`)
进入目标项目工作区后,首先查看当前项目有哪些待处理约束:
### 2. 只读读取约束详情与决策评估 (`pin_peek` / `pin_list`) —— 只读不改状态
进入目标项目后,首先读取待处理约束并做出技术决策,**绝不改变任何状态(保持 pending)**:

#### 模式 A:只读预览队首待处理约束 (`pin_peek`)
传入 `project_name`(不传 `id`),直接只读获取队首待处理约束的完整标题与 Markdown 正文:
```json
{
"project_name": "Lumina-Frontend"
}
```

#### 模式 B:全览待处理列表及内容 (`pin_list`)
查看当前项目积压的待处理约束列表(每条均包含标题、正文、分类与优先级):
```json
{
"project_name": "Lumina-Frontend",
Expand All @@ -73,51 +84,52 @@ pin_push(to="B", priority, content) │
"size": 10
}
```
- 结果按 `createdAt` 升序排列(天然呈现 FIFO 顺序)。

#### 模式 C:精确查看指定 ID 约束 (`pin_peek`)
```json
{
"id": "1234567890123456789"
}
```

---

### 3. 消费与闭环约束 (`pin_consume`)
确认已在代码中适配或处理了该约束后,将其标记为已消费:
### 3. 本地代码适配与显式消费闭环 (`pin_consume`)
在本地审阅正文、完成决策并落实代码修改(或确认知晓)后,调用 `pin_consume` 显式将约束状态标记为已消费:

#### 模式 A:FIFO 队首消费(最常用)
不传 `id`,自动取出并消费最旧的一条 pending 约束:
#### 模式 A:精确 ID 消费(推荐)
针对性消费刚刚已处理完毕的特定约束:
```json
{
"project_name": "Lumina-Frontend"
"project_name": "Lumina-Frontend",
"id": "1234567890123456789"
}
```

#### 模式 B:精确 ID 消费
当针对性处理了某一条特定约束时,传入其雪花 ID:
#### 模式 B:FIFO 队首消费
不传 `id`,消费当前队首约束:
```json
{
"project_name": "Lumina-Frontend",
"id": "1234567890123456789"
"project_name": "Lumina-Frontend"
}
```

---

### 4. 只读回查与元数据调整

- **只读预览 (`pin_peek`)**:查看指定 Pin 的完整内容(不改变 pending / consumed 状态):
```json
{"id": "1234567890123456789"}
```
- **调整元数据 (`pin_update`)**:调整约束的优先级或分类(注意:状态不能通过此工具修改):
```json
{
"id": "1234567890123456789",
"priority": "medium",
"category": "notice"
}
```
### 4. 约束元数据调整 (`pin_update`)
调整约束的优先级或分类(状态只能通过 `pin_consume` 推进到 `consumed`):
```json
{
"id": "1234567890123456789",
"priority": "medium",
"category": "notice"
}
```

---

## ⛔ 核心红线 (Hard Rules)

1. **MUST**: 状态流转单向原子化。`pending` 转换为 `consumed` 只能通过 `pin_consume`,严禁通过任何其他方式绕过。
2. **MUST**: 消费前核对内容。消费代表“该约束已在当前项目中得到处理/知晓”,不可在未做任何处理时盲目批量清空队列。
2. **MUST**: 读取与消费分离。读取操作(`pin_peek` / `pin_list`)绝不修改状态,Agent 必须先读取正文、评估决策并完成本地处理,随后显式调用 `pin_consume` 确认闭环。
3. **NEVER**: 严禁将本地临时待办当作跨项目约束。Pin 专用于**跨仓库/跨项目**的契约传递。
46 changes: 33 additions & 13 deletions .agents/skills/lumina-pin/examples/push-and-consume.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,40 +19,60 @@ Output: 得到 Pin 的雪花 ID,状态 `pending`,落在目标项目 FIFO 队

## 消费端(项目 B · 前端)

进入前端仓库后先看队列:
### 阶段 1:只读读取约束并评估决策(不改变 pending 状态)

进入前端仓库后,只读预览队首待处理约束详情与正文:

```json
{
"project_name": "Lumina-Frontend",
"status": "pending",
"page": 1,
"size": 10
"project_name": "Lumina-Frontend"
}
```
(调用 `pin_peek`)

不确定内容时 `pin_peek`:
Output: 只读获得完整正文,状态仍为 `pending`:
```text
Pin 详情:

```json
{ "id": "1234567890123456789" }
ID: 1234567890123456789
标题: WebSocket 消息体新增 trace_id
内容:
## 接口变更
`qa_push_question` 广播体新增顶层 `trace_id`。interact 页错误上报需要带上该 ID。
分类: api_change
状态: pending
优先级: high
...
```

代码改完(上报带上 `trace_id`)再消费。只处理了这一条就精确消费:
或者调用 `pin_list` 查看全部待处理约束及其内容正文:

```json
{
"project_name": "Lumina-Frontend",
"id": "1234567890123456789"
"status": "pending",
"page": 1,
"size": 10
}
```

按时间挨个清队列时不传 `id`:
### 阶段 2:展开本地代码适配与修复

根据读取到的正文要求,在前端代码中进行适配(例如为 WebSocket 错误上报带上 `trace_id`),并运行测试确认无误。

### 阶段 3:显式消费闭环约束 (`pin_consume`)

代码修改完成并验证通过后,调用 `pin_consume` 显式确认闭环:

```json
{ "project_name": "Lumina-Frontend" }
{
"project_name": "Lumina-Frontend",
"id": "1234567890123456789"
}
```

## 反例

- 未改代码就 FIFO 连消三条 → 约束被归档,下游会漏适配
- 未看内容或未改代码就盲目批量调 `pin_consume` → 导致约束漏适配
- `pin_update` 把状态改成 consumed → 工具不允许,状态只能 `pin_consume`
- 把「记得跑一下测试」推进 Pin → 这不是跨项目契约
6 changes: 3 additions & 3 deletions .agents/skills/lumina-pin/references/fields.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@

## 队列

- `pin_list(status="pending")` 按 `createdAt` 升序,FIFO 可见。
- 不传 `id` 的 `pin_consume` 取最旧 pending;队列空时返回「暂无待处理约束」,不是错误。
- `pin_peek` 只读,不改状态。
- `pin_peek` 只读查看特定或队首待处理约束详情(包含完整正文),完全不改变状态,用于消费前的决策审阅。
- `pin_list(status="pending")` 按 `createdAt` 升序,包含正文内容,便于通览并决策。
- `pin_consume` 在代码适配完成后调用,显式将约束状态原子更新为 `consumed`;队列空时返回「暂无待处理约束」,不是错误。
- `pin_update` 只能改 `priority` / `category`,不能把状态改成 `consumed`。

## 不要当成 Pin 的东西
Expand Down
42 changes: 21 additions & 21 deletions components/src/motion/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Variants } from 'motion/react'
import type { Variants } from "motion/react";

/** 共享缓动 — 与登录页完全一致 */
export const ease: [number, number, number, number] = [0.16, 1, 0.3, 1]
export const ease: [number, number, number, number] = [0.16, 1, 0.3, 1];

/** 交错子元素入场(供子页面自驱动使用) */
export const staggerContainer: Variants = {
Expand All @@ -13,7 +13,7 @@ export const staggerContainer: Variants = {
delayChildren: 0.05,
},
},
}
};

/** 交错子元素入场 — Main 区域从右向左滑入 */
export const staggerItem: Variants = {
Expand All @@ -23,39 +23,39 @@ export const staggerItem: Variants = {
x: 0,
transition: { duration: 0.4, ease },
},
}
};

/** 交错子元素入场 — 从左向右滑入(仅标题行使用) */
/** 交错子元素入场 — 统一从右向左滑入 */
export const staggerItemLeft: Variants = {
hidden: { opacity: 0, x: -12 },
hidden: { opacity: 0, x: 20 },
visible: {
opacity: 1,
x: 0,
transition: { duration: 0.4, ease },
},
}
};

/** Sidebar 整体交错容器 — header → 各分组 → footer 按顺序载入 */
export const sidebarStaggerContainer: Variants = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: {
staggerChildren: 0.08,
delayChildren: 0.15,
staggerChildren: 0.025,
delayChildren: 0.03,
},
},
}
};

/** Sidebar 子项从左向右滑入 */
export const sidebarItem: Variants = {
hidden: { opacity: 0, x: -16 },
hidden: { opacity: 0, x: -10 },
visible: {
opacity: 1,
x: 0,
transition: { duration: 0.35, ease },
transition: { duration: 0.22, ease },
},
}
};

/**
* Sidebar 整块淡入 — 用于频繁重渲的侧边栏(如 Wiki Reader)。
Expand All @@ -67,7 +67,7 @@ export const sidebarBlockFade: Variants = {
opacity: 1,
transition: { duration: 0.25, ease },
},
}
};

/**
* Main 区域滑入 — 右侧内容切换时从右向左滑入。
Expand All @@ -85,43 +85,43 @@ export const mainSlideIn: Variants = {
x: -8,
transition: { duration: 0.15, ease },
},
}
};

/* ─── Landing 页面动画变体 ─────────────────────────────── */

/** 向上淡入 — 标题、描述、按钮等通用入场 */
export const fadeUp: Variants = {
hidden: { opacity: 0, y: 18 },
visible: { opacity: 1, y: 0 },
}
};

/** 纯淡入 — 装饰线等无位移元素 */
export const fadeIn: Variants = {
hidden: { opacity: 0 },
visible: { opacity: 1 },
}
};

/** 缩放淡入 — 代码块、卡片等强调元素 */
export const scaleIn: Variants = {
hidden: { opacity: 0, scale: 0.92 },
visible: { opacity: 1, scale: 1 },
}
};

/** Hero 区域交错容器 — staggerChildren 0.12, delayChildren 0.08 */
export const heroStagger: Variants = {
hidden: {},
visible: {
transition: { staggerChildren: 0.12, delayChildren: 0.08 },
},
}
};

/** Section 区域交错容器 — staggerChildren 0.1 */
export const sectionStagger: Variants = {
hidden: {},
visible: {
transition: { staggerChildren: 0.1 },
},
}
};

/** whileInView 视口配置 — 一次性触发,提前 80px 进入 */
export const viewportOnce = { once: true, margin: '-80px' } as const
export const viewportOnce = { once: true, margin: "-80px" } as const;
15 changes: 15 additions & 0 deletions internal/logic/pin.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,21 @@ func (l *PinLogic) Peek(ctx context.Context, id xSnowflake.SnowflakeID) (*apiPin
return l.toResponse(pin), nil
}

// PeekOldestPending 只读查看指定项目最旧的一条待处理 Pin(只读不改变状态)
// 供消费前的详情审阅与决策分析使用。
func (l *PinLogic) PeekOldestPending(ctx context.Context, projectID xSnowflake.SnowflakeID) (*apiPin.PinResponse, *xError.Error) {
l.log.Info(ctx, fmt.Sprintf("PeekOldestPending - 只读查看队首待处理 Pin [projectID=%d]", projectID.Int64()))

pin, xErr := l.repo.pin.GetOldestPending(ctx, projectID)
if xErr != nil {
return nil, xErr
}
if pin == nil {
return nil, xError.NewError(ctx, xError.NotFound, "暂无待处理约束", false, nil)
}
return l.toResponse(pin), nil
}

// toResponse 将 Pin 实体映射为响应 DTO
//
// 时间格式遵循 RFC3339(与项目模块 toResponse 保持一致)。
Expand Down
Loading
Loading