Commit 9ce3fa0c by DaiJiezhang

chore: configure matt-pocock workflow

parent 67e980ee
# 项目 Agent 规则
## 当前文档入口
- 当前领域背景和术语:`CONTEXT.md`
- 已确认的迁移期待办:`docs/migration-backlog.md`
- 历史需求、设计和任务:`docs/legacy/openspec/`
- 新的长期技术决定:未来按需创建 `docs/adr/`
历史 OpenSpec 只用于追溯,不作为当前任务清单。当前代码和当前文档优先于历史记录。
## Agent skills
### Engineering workflow
新需求按以下顺序处理:
```text
grill-with-docs
→ to-spec
→ to-tickets
→ implement
→ code-review
```
- `grill-with-docs`:澄清需求、领域词汇和技术决定。
- `to-spec`:把已讨论内容整理成 Spec。
- `to-tickets`:把 Spec 拆成可独立验收的 Ticket,并声明阻塞关系。
- `implement`:按 Spec 或 Ticket 开发、测试和提交。
- `code-review`:开发完成后检查变更。
### Issue tracker
正式 Spec 和 Ticket 使用本地 Markdown,位于 `.scratch/<feature-slug>/`,并提交到 Git。详细约定见 `docs/agents/issue-tracker.md`
GitLab 用于代码分支、Merge Request、代码审查和合并,不为同一事项重复创建 GitLab Issue。
### Triage labels
使用默认五类 triage 标签,详细映射见 `docs/agents/triage-labels.md`
### Domain docs
本项目使用单一上下文:`CONTEXT.md``docs/agents/domain.md`。未来新增长期技术决定时,再创建 `docs/adr/` 中的 ADR。
## 工作流边界
- 新需求从 matt-pocock 流程开始,不新建根目录 `openspec/``docs/legacy/openspec/changes/`
- 历史 `tasks.md` 不等同于当前任务清单;创建新 Ticket 前先核对当前代码和 `docs/migration-backlog.md`
- 正式 `.scratch/` 文件提交到 Git;临时讨论不写入 `.scratch/`
- 同一任务只选择 `.scratch/` 或 GitLab Issue 之一作为任务来源。
- 修改前先读取相关 `CONTEXT.md` 和适用的 ADR;修改后验证实际行为或文档链接。
# 项目上下文
## 项目定位
本项目是学有为内部资产管理后台,用于管理公司主体、人员、手机号、企微账号及其他业务资产。
## 当前技术结构
- 前端:Vue 3 + Vite,部署前缀为 `/asset/`
- 默认后端:TypeScript NestJS,前端开发代理默认指向 `127.0.0.1:7691`
- Java 后端:迁移期间保留,用作行为契约对拍基准,默认端口 `7690`
- 数据库:现有 MySQL 数据库,表名使用 `as_` 前缀;NestJS 的 Prisma schema 由现有数据库反向生成,只作只读映射。
- 前端包管理器:pnpm;`frontend/package.json` 中的 `packageManager``volta` 字段是版本约束。
## 迁移边界
NestJS 迁移期间,Java 和 NestJS 并行运行。契约对拍要求两个后端的行为保持一致,因此迁移期间确认过的行为变更记录在 `docs/migration-backlog.md`,在契约全绿并完成迁移前不主动修改。
当前已迁移的主要模块包括:
- 认证和系统账号;
- 公司档案和公司人员;
- 手机号资产;
- 企业微信账号;
- 设备资产。
## 领域词汇
| 术语 | 含义 |
|---|---|
| 公司主体 | 资产归属或业务注册所对应的公司档案 |
| 公司人员 | 公司主体下的人员信息 |
| 手机号资产 | 台账中的手机号记录,可能来自手动建档或其他业务资产 |
| 企微账号 | 企业微信账号及其与手机号资产的关联 |
| 设备资产 | 设备及其图片、归属等信息 |
| 资产来源 | 记录资产从哪类业务对象创建或关联而来 |
| 系统账号 | 登录后台并受角色、状态和页面权限控制的用户 |
| 契约对拍 | 用同一组请求对比 Java 和 NestJS 响应,确认迁移行为一致 |
## 当前规则
- 前端默认使用 NestJS;需要与 Java 对拍时使用 `pnpm dev:java`
- 两个后端共享现有数据库,禁止在迁移期间执行 Prisma migration 改动表结构。
- 资产来源关系是业务可追溯信息,修改资产关联规则时需要保留来源语义。
- 角色、会话、软删除和错误响应属于迁移契约的一部分,行为变更先记录到迁移待办,再单独决策。
## 文档优先级
```text
当前代码
> CONTEXT.md
> docs/migration-backlog.md
> docs/adr/ 中适用的当前 ADR
> docs/legacy/openspec/ 中的历史资料
```
OpenSpec 已封存到 `docs/legacy/openspec/`,不再作为新需求或当前任务的创建入口。
# Domain Docs
本项目是单一业务上下文,领域文档位于仓库根目录。
## 开始探索前读取
- `CONTEXT.md`:当前项目背景、领域术语和系统边界。
- `docs/adr/`:如果目录存在,读取与当前工作区域相关的 ADR。
- `docs/migration-backlog.md`:涉及 NestJS 迁移期间暂缓的行为变更时读取。
如果某个文档或目录尚不存在,继续当前工作,不要把它当作阻塞项;新的领域决定在确认后再创建对应文档。
## 术语约定
需求、Ticket、重构提案和测试名称使用 `CONTEXT.md` 中的领域词汇。需要的新概念不在词汇表中时,先确认它是项目真实概念还是临时命名。
## 决策冲突
如果新方案与已有 ADR 冲突,必须明确指出冲突的 ADR 和原因,不要静默覆盖旧决定。
# Issue tracker: Local Markdown
本项目的正式 Spec 和 Ticket 使用仓库内的 Markdown 文件,代码协作仍使用 GitLab 分支和 Merge Request。
## 目录约定
- 一个功能一个目录:`.scratch/<feature-slug>/`
- 功能 Spec:`.scratch/<feature-slug>/spec.md`
- 实施 Ticket:`.scratch/<feature-slug>/issues/<NN>-<slug>.md`
- Ticket 从 `01` 开始按依赖顺序编号,每个 Ticket 单独一个文件。
- Ticket 顶部使用 `Status:` 记录 triage 状态,标签映射见 `docs/agents/triage-labels.md`
- 评论和讨论追加到文件末尾的 `## Comments` 标题下。
## Git 约定
- 正式 Spec 和 Ticket 必须提交到 Git,确保不同 worktree 和电脑可以读取同一份任务记录。
- 临时讨论和一次性草稿不写入 `.scratch/`
- 同一事项只能选择 `.scratch/` 或 GitLab Issue 作为唯一任务来源,不重复创建。
- GitLab 继续负责代码分支、Merge Request、审查和合并,不承担本地 Spec/Ticket 的重复记录。
## Skill 行为
当 Skill 要“发布到 issue tracker”时,在 `.scratch/<feature-slug>/` 下创建或更新对应 Markdown 文件。
当 Skill 要“读取 Ticket”时,根据用户提供的功能目录或 Ticket 路径读取对应文件。
依赖关系写在每个 Ticket 的 `Blocked by:` 行中;只有所有阻塞 Ticket 完成后,后续 Ticket 才可开始。
# Triage Labels
matt-pocock Skills 使用五个标准 triage 角色。本项目使用相同的标签字符串。
| Skill 角色 | 本项目标签 | 含义 |
|---|---|---|
| `needs-triage` | `needs-triage` | 维护者需要评估事项 |
| `needs-info` | `needs-info` | 等待需求方补充信息 |
| `ready-for-agent` | `ready-for-agent` | 需求完整,可交给 Agent 实施 |
| `ready-for-human` | `ready-for-human` | 需要人工实施或决策 |
| `wontfix` | `wontfix` | 明确不处理 |
以后 Skill 提到标准 triage 角色时,使用右侧对应标签。
# OpenSpec → matt-pocock 迁移实施计划
> **执行要求:** 使用 `executing-plans` skill 按阶段执行;每个提交完成后先检查实际差异,再进入下一阶段。
**目标:** 将 OpenSpec 完整封存为历史记录,并从下一项新需求开始使用 matt-pocock 工作流。
**实施原则:** 只调整文档、项目规则和历史链接,不修改业务逻辑、数据库、NestJS、前端或 pnpm。旧任务不自动迁移,旧设计不重新包装为当前决策。
**工作分支:** `chore/migrate-openspec-to-matt-pocock`
**基线:** 最新 `origin/master`,已包含 NestJS 和 pnpm 迁移。
---
## 1. 迁移目标
切换后的工作方式:
```text
旧需求、旧设计、旧任务
→ 保留为历史记录
新需求
→ 讨论清楚
→ 写 Spec
→ 拆小任务
→ 开发
→ 测试
→ 审查
```
本次迁移不改变任何用户可见行为。
---
## 2. 当前状态
| 项目 | 状态 |
|---|---|
| 工作分支 | `chore/migrate-openspec-to-matt-pocock` |
| OpenSpec | 13 个历史 change、68 个文件 |
| 旧任务 | 99 条未勾选,但状态不能代表当前代码状态 |
| 当前真实待办 | `docs/migration-backlog.md` |
| 旧路径引用 | `.gitignore` 1 处、Java 注释 11 处 |
| 当前工作区 | 与 `lamprey` 的未提交 pnpm 草稿隔离 |
99 条未勾选 task 不等于 99 项未完成工作。部分任务已由当前代码完成,部分已被 NestJS 迁移替代,部分已写入 `docs/migration-backlog.md`
---
## 3. 范围
### 3.1 本次执行
- 完整封存 `openspec/`
- 建立历史索引并修复旧路径。
- 确认项目实际使用的 Skill 安装机制。
- 安装或锁定最小 matt-pocock Skill 集合。
- 建立 `AGENTS.md``docs/agents/` 配置。
- 建立描述当前事实的 `CONTEXT.md`
### 3.2 本次不执行
- 不修改 NestJS、Java、前端或数据库业务逻辑。
- 不修改 pnpm 配置。
- 不迁移 99 条旧 task。
- 不创建新的业务 Ticket。
- 不批量补写旧 ADR。
- 不修改 `docs/migration-backlog.md`
- 不触碰 `lamprey` worktree 的未提交文件。
---
## 4. 阶段一:封存 OpenSpec
### 4.1 移动历史目录
使用 Git 重命名:
```text
openspec/
docs/legacy/openspec/
```
必须完整保留:
```text
config.yaml
changes/*/proposal.md
changes/*/design.md
changes/*/tasks.md
changes/*/specs/*/spec.md
changes/*/.openspec.yaml
```
迁移后禁止新增 `openspec/changes/*`
迁移完成后必须同时遵守:
```text
禁止重新创建根目录 openspec/
禁止新增 docs/legacy/openspec/changes/*
禁止把历史 tasks.md 当作当前任务清单
禁止 OpenSpec 与 matt-pocock 两套流程并行增长
```
### 4.2 建立历史索引
新建:
```text
docs/legacy/openspec/ARCHIVE.md
```
内容要求:
- 说明 OpenSpec 已停止使用;
- 说明历史资料仅用于追溯,不代表当前规则;
- 列出 13 个历史 change;
- 状态只使用“历史完成”“历史待核对”“仅设计稿”;
- 指向 `CONTEXT.md``docs/migration-backlog.md` 和新工作流;
- 明确旧 task 的勾选状态不能代表当前实现状态。
文档权威顺序:
```text
当前代码
> CONTEXT.md
> docs/migration-backlog.md
> docs/legacy/openspec/
```
### 4.3 清理失效配置
修改 `.gitignore`,删除:
```text
openspec/changes/integrate-authentication-to-master/
```
### 4.4 修复 Java 注释链接
修改以下目录中的 11 个实体文件:
```text
backend/src/main/java/com/xyw/console/asset/entity/
```
涉及:
- `AssetDeviceEntity.java`
- `CompanyPersonEntity.java`
- `CompanyProfileEntity.java`
- `DomainAccountEntity.java`
- `DomainAssetEntity.java`
- `DouyinAccountEntity.java`
- `MerchantEntity.java`
- `PhoneAssetEntity.java`
- `SystemUserEntity.java`
- `WechatAccountEntity.java`
- `WecomAccountEntity.java`
原注释:
```text
关联文件:openspec/changes/rebuild-asset-application-foundation/design.md
```
调整为:
```text
历史设计参考:docs/legacy/openspec/changes/rebuild-asset-application-foundation/design.md
当前领域规则:CONTEXT.md
```
只修改注释,不修改 Java 行为。
### 4.5 阶段一提交
```text
chore: archive openspec history
```
提交内容:
- `openspec/` 移动到 `docs/legacy/openspec/`
- 新增 `ARCHIVE.md`
- 清理 `.gitignore`
- 修复 11 个 Java 注释链接。
---
## 5. 阶段二:确认并配置 matt-pocock Skills
### 5.1 确认安装机制
先确认项目实际使用的 Skill 安装命令、来源和 `skills-lock.json` 生成方式。
必须遵守:
```text
不手工编辑 skills-lock.json
```
如果当前环境只有用户级 Skill:
- 确认项目级锁定或恢复方式;
- 能可靠恢复时再由安装工具更新 `skills-lock.json`
- 若无法可靠锁定,则在 `AGENTS.md` 记录安装前提,不伪造 lockfile。
实施顺序:
1. 在迁移 worktree 运行 `npx skills --help`,确认可用命令和 lockfile 行为;
2. 通过安装工具支持的 `add` 流程从 `mattpocock/skills` 选择最小核心 Skill;
3. 检查 `.agents/skills/``.claude/skills/``skills-lock.json` 的实际结果;
4. 只有安装工具成功生成记录时,才提交 `skills-lock.json`
5. 如果安装工具不可用,继续完成 OpenSpec 封存,在 `AGENTS.md` 记录用户级 Skill 前提,并跳过 lockfile 修改。
Skill 安装失败不得阻塞阶段一的历史封存。
### 5.2 最小核心 Skill 集合
项目至少需要:
```text
setup-matt-pocock-skills
grill-with-docs
to-spec
to-tickets
implement
```
配套能力:
```text
grilling
domain-modeling
triage
tdd
code-review
```
验收条件:
- Skill 实际可用;
- 锁文件由安装工具生成;
- 新 worktree 或新电脑能够恢复;
- 不安装与本项目无关的额外 Skill。
---
## 6. 阶段三:建立项目工作流
### 6.1 新建 `AGENTS.md`
新建:
```text
AGENTS.md
```
记录:
```text
历史需求与设计:docs/legacy/openspec/
当前项目背景:CONTEXT.md
当前迁移后待办:docs/migration-backlog.md
未来技术决策:docs/adr/,有新决策时再创建
```
新需求流程:
```text
grill-with-docs
→ to-spec
→ to-tickets
→ implement
→ code-review
```
`AGENTS.md` 只记录项目规则,不复制用户级 `CLAUDE.md` 的个人规则。
### 6.2 新建 Agent 配置
新建:
```text
docs/agents/issue-tracker.md
docs/agents/triage-labels.md
docs/agents/domain.md
```
采用以下配置:
| 配置 | 方案 |
|---|---|
| 代码协作 | GitLab 分支和 MR |
| 开发任务草稿 | 本地 Markdown |
| 任务位置 | `.scratch/<功能>/issues/` |
| 领域背景 | `CONTEXT.md` |
| 技术决策 | 未来的 `docs/adr/` |
| triage 标签 | 默认五类标签 |
默认标签:
```text
needs-triage
needs-info
ready-for-agent
ready-for-human
wontfix
```
本次不创建 `.scratch/` 业务任务。
`.scratch/` 的职责必须明确:
```text
正式 Spec 和 Ticket → 提交到 Git,供不同 worktree 和电脑共享
临时讨论和一次性草稿 → 不写入 .scratch/
同一任务只能选择 .scratch/ 或 GitLab Issue 作为唯一来源,不得重复创建
```
当前 `.gitignore` 不忽略 `.scratch/`;未来创建正式任务时保持该约定。
### 6.3 新建 `CONTEXT.md`
只写当前仍然成立的事实:
#### 项目定位
内部资产管理后台。
#### 当前技术结构
```text
前端:Vue 3 + Vite
默认后端:NestJS
Java 后端:迁移期契约对拍基准
数据库:现有 MySQL 数据结构
```
#### 核心领域对象
```text
公司主体
公司人员
手机号资产
企微账号
设备资产
微信账号
抖音账号
域名
商户
系统账号
```
#### 关键边界
```text
账号角色和权限边界
手机号来源追踪
企微与手机号的关联
资产软删除约定
NestJS 与 Java 的迁移关系
```
禁止把旧 OpenSpec 原文整批复制到 `CONTEXT.md`
### 6.4 ADR 使用规则
本次不批量创建旧 ADR,也不创建空的 `docs/adr/` 目录。
```text
旧决定 → docs/legacy/openspec/
新决定 → 未来写入 docs/adr/
```
只有出现新的长期技术决定时才创建 ADR,例如:
- Java 后端下线时机;
- 手机号自动创建后的保留规则;
- 超级管理员密码重置权限;
- 账号操作审计日志;
- 数据库结构变化。
### 6.5 阶段二提交
```text
chore: configure matt-pocock workflow
```
提交内容:
- `AGENTS.md`
- `CONTEXT.md`
- `docs/agents/*`
- 由安装工具产生的 `skills-lock.json` 更新(如果安装机制确认可用)
- `docs/plans/2026-09-16-openspec-to-matt-pocock-migration.md`
---
## 7. 旧任务处理规则
本次不迁移 99 条旧 task。
以后遇到旧事项时,按以下顺序判断:
```text
当前代码
docs/migration-backlog.md
历史 OpenSpec
```
| 判断结果 | 处理方式 |
|---|---|
| 当前代码已经完成 | 不建新任务 |
| backlog 已记录 | 不重复创建 |
| 已过时 | 只保留历史 |
| 当前确实未完成 | 使用 `to-tickets` 创建新任务 |
创建新任务前,必须先向用户展示拆分结果并获得确认。
---
## 8. 文件变更清单
### 移动
```text
openspec/**
→ docs/legacy/openspec/**
```
### 新建
```text
docs/legacy/openspec/ARCHIVE.md
AGENTS.md
CONTEXT.md
docs/agents/issue-tracker.md
docs/agents/triage-labels.md
docs/agents/domain.md
docs/plans/2026-09-16-openspec-to-matt-pocock-migration.md
```
### 修改
```text
.gitignore
skills-lock.json(仅允许安装工具修改)
```
### 仅修改注释
```text
backend/src/main/java/com/xyw/console/asset/entity/*.java
```
### 明确不修改
```text
backend-nest/**
frontend/**
数据库文件
pnpm 配置
docs/migration-backlog.md
lamprey worktree
```
---
## 9. 验收标准
迁移完成后必须满足:
1. 根目录不存在 `openspec/`
2. 68 个旧 OpenSpec 文件完整移动到 `docs/legacy/openspec/`
3. 加上新建的 `ARCHIVE.md` 后,历史目录至少包含 69 个跟踪文件;
4. `ARCHIVE.md` 明确历史与当前文档边界;
5. `.gitignore` 不再引用旧 OpenSpec 路径;
6. 11 个 Java 注释链接全部有效;
7. `AGENTS.md` 明确新开发流程;
8. `CONTEXT.md` 只描述当前事实;
9. `docs/agents/` 配置完整;
10. 核心 Skill 实际可用,或 `AGENTS.md` 已明确记录用户级安装前提;
11. `skills-lock.json` 没有被手工伪造;
12. `.scratch/` 的 Git 跟踪和唯一任务来源规则已经写清楚;
13. 没有迁移 99 条旧 task;
14. 没有同时保留可继续增长的两套工作流;
15. 没有业务逻辑变化;
16. 计划书本身已包含在第二个提交中;
17. 没有触碰 `lamprey` 的 pnpm 草稿。
---
## 10. 验证方法
执行:
```bash
git diff --check
git diff --find-renames --summary
git status --short
git ls-files openspec
git ls-files docs/legacy/openspec | wc -l
git diff --name-only -- backend-nest frontend
```
检查:
- `git ls-files openspec` 没有输出;
- `docs/legacy/openspec` 至少有 69 个跟踪文件,其中 68 个为原文件、1 个为新建索引;
- Git rename 摘要能够识别原 OpenSpec 文件的移动关系;
- 仓库中不存在仍指向根目录 `openspec/` 的有效文档链接;
- 新文档互相引用正确;
- 业务源码只有 Java 注释变化;
- `backend-nest/``frontend/` 没有差异;
- 当前分支只包含本计划范围内的文件。
由于没有业务行为变化,不重复运行 NestJS 的 101 条单元测试。Java 文件仅修改注释,通过差异检查确认。
---
## 11. 风险与控制
| 风险 | 控制方法 |
|---|---|
| 旧资料丢失 | 使用 `git mv`,完整保留原文和 Git 历史 |
| 旧设计被误认为当前规则 | `docs/legacy/` 明确标记为历史 |
| 旧任务重复进入新系统 | 本次不迁移 99 条旧 task |
| Skill 只在当前电脑可用 | 确认安装机制并由工具更新 lockfile |
| 修改影响业务 | 不改业务逻辑,只改文档、配置和注释 |
| 本地任务不适合团队 | 后续可切换 GitLab Issues,不影响历史封存 |
| 新流程不适合 | 两个独立提交,可以分别回滚 |
---
## 12. 回滚方案
如果只撤销 matt-pocock 工作流:
```text
回滚 Commit 2
```
如果连 OpenSpec 封存也撤销:
```text
继续回滚 Commit 1
```
回滚不会影响 NestJS、pnpm、数据库或业务代码。
---
## 13. 最终结果
```text
旧 OpenSpec:完整保留,只作为历史
新 matt-pocock:从下一项新需求开始使用
旧 task:不自动继承,日后按当前代码逐项判断
```
核心原则:**只换开发流程,不重写历史,不碰业务。**
......@@ -31,6 +31,12 @@
"skillPath": "skills/gpt-tasteskill/SKILL.md",
"computedHash": "7bd1bfdda0e51016ca222693401a65fc0dd9bf9487e0bd5b1740ba510f6f963a"
},
"grill-with-docs": {
"source": "mattpocock/skills",
"sourceType": "github",
"skillPath": "skills/engineering/grill-with-docs/SKILL.md",
"computedHash": "a610223c9796f755b603f15ec114849a4b38b9ba3006acfa9bdf3cc56dd44dad"
},
"high-end-visual-design": {
"source": "Leonxlnx/taste-skill",
"sourceType": "github",
......@@ -55,6 +61,12 @@
"skillPath": "skills/imagegen-frontend-web/SKILL.md",
"computedHash": "27255c7c50181e58add156b2aa2bd5325285b85f04027e4c8b73742d98d7be0a"
},
"implement": {
"source": "mattpocock/skills",
"sourceType": "github",
"skillPath": "skills/engineering/implement/SKILL.md",
"computedHash": "130cac2d72bfde8cd526bf3b754211e2fe00e84bc4d9f9c56f749b9541a3afad"
},
"industrial-brutalist-ui": {
"source": "Leonxlnx/taste-skill",
"sourceType": "github",
......@@ -73,17 +85,35 @@
"skillPath": "skills/redesign-skill/SKILL.md",
"computedHash": "47eced3e960a2c961d3cbee11fa1216264f589344b586a5cbd03967cd6b9c54b"
},
"setup-matt-pocock-skills": {
"source": "mattpocock/skills",
"sourceType": "github",
"skillPath": "skills/engineering/setup-matt-pocock-skills/SKILL.md",
"computedHash": "a45163cba56f72f5f224c46557c047d51547147a29e383e5a769ec39eecd1188"
},
"shadcn": {
"source": "shadcn/ui",
"sourceType": "github",
"skillPath": "skills/shadcn/SKILL.md",
"computedHash": "0dc0edeeaec2ae491ae506806517866a3f9bd48d04e0458feb37e0252862891f"
"computedHash": "d04e43ec01e921558b93bb8046c14a42a22556689a2827243df900825a4e1604"
},
"stitch-design-taste": {
"source": "Leonxlnx/taste-skill",
"sourceType": "github",
"skillPath": "skills/stitch-skill/SKILL.md",
"computedHash": "c96b580192b34167efa01f460bbc669ff4315cf97f3cf6ff85ded8029aa720b8"
},
"to-spec": {
"source": "mattpocock/skills",
"sourceType": "github",
"skillPath": "skills/engineering/to-spec/SKILL.md",
"computedHash": "0ee8caf20fc7df94db53e76f42588fb01eee88c6f8dc97e7a3a0565be8978e74"
},
"to-tickets": {
"source": "mattpocock/skills",
"sourceType": "github",
"skillPath": "skills/engineering/to-tickets/SKILL.md",
"computedHash": "4aba8639f46b55ede011866f83e9e87ae10482b72c14848389e5801eba0b37bf"
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment