feat: bootstrap coding specs with CC + Codex pipeline
Add Trellis spec files documenting all major architectural areas:
- plugs/composables: 7 Vue composables (useListTable, useModifyForm, etc.)
- plugs/api: 9 API modules with CRUD patterns
- plugs/element: Element Plus wrappers (listTableDialog, formatter, message, rule)
- plugs/http: 3 axios variants with AxiosOptions interface
- packages/base: 18 base Vue components
- packages/manage: Management UI (views, head, common)
- plugs/config+store+i18n: Styles, sizes, Vuex store, i18n, websocket
Each spec contains real code examples with file paths, anti-patterns
documented, and no placeholder text.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3 months ago
# Quality Guidelines
> Code quality standards for frontend development.
---
## Overview
<!--
Document your project's quality standards here.
Questions to answer:
- What patterns are forbidden?
- What linting rules do you enforce?
- What are your testing requirements?
- What code review standards apply?
-->
(To be filled by the team)
---
## Forbidden Patterns
<!-- Patterns that should never be used and why -->
(To be filled by the team)
---
## Required Patterns
<!-- Patterns that must always be used -->
(To be filled by the team)
---
## Testing Requirements
<!-- What level of testing is expected -->
(To be filled by the team)
---
## Development Workflow
### Package Changes Testing
When making changes to `packages/` directory and testing with `examples/` :
1. **Vite dev server auto-reloads** : The dev server (`bun run dev`) automatically reloads changes in `packages/` when you access the example pages
2. **Verify changes took effect** : Modify `DEV_MODE_TS` in `packages/manage/router/index.vue` - this string is displayed at `.el-menu .menu-footer` (bottom of sidebar menu). Changing it forces the app to refresh.
3. **Build before finishing** : Run `bun run build:lib` to ensure the library builds correctly with your changes
```typescript
// In packages/manage/router/index.vue - change this string to force refresh
const DEV_MODE_TS = "2026-03-26T03:50:00.000Z"; // Update timestamp to force reload
```
### Build Commands
This project uses **bun** as package manager:
| Command | Purpose | When to Use |
|---------|---------|-------------|
| `bun run dev` | Start Vite dev server | Testing example project |
| `bun run build` | Build examples project | **DO NOT USE** - examples don't need build |
| `bun run build:lib` | Build library for external repos | When done with changes, to verify build |
| `bun run lint` | Lint code | Before commit |
**Common mistake**: Running `bun run build` which builds the examples project unnecessarily. The examples project is for development only and Vite handles hot reload automatically.
### Quick Test Cycle
```bash
# 1. Make changes to packages/
# 2. Dev server auto-reloads when accessing example pages
# 3. Modify DEV_MODE_TS in packages/manage/router/index.vue if changes don't appear
# 4. Run build:lib when done to verify
bun run build:lib
```
### Browser Automation with agent-browser
When using `agent-browser` for testing:
**DO**: Use CSS selectors with `wait` instead of fixed timeouts
```bash
# Good - waits for element to appear
agent-browser wait ".el-table-v2__row" & & agent-browser snapshot
# Bad - arbitrary timeout, may be too short or waste time
agent-browser wait 3000
```
**DO**: Check console for errors after page interaction
```bash
agent-browser click "@e1" & & agent-browser console
```
**DO**: Navigate with hash routes properly
```bash
# Hash-based SPA routes need explicit navigation
agent-browser navigate http://localhost:5173/#/table-v2
```
**Common wait patterns**:
- `agent-browser wait --load networkidle` - for page navigation
- `agent-browser wait ".my-selector"` - for element appearance
- `agent-browser wait --url "**/pattern"` - for URL changes
---
## Common Mistakes / Gotchas
### el-table-v2 probe row timing
When using a probe row to dynamically measure row height for el-table-v2's virtual scrolling:
**Problem**: Using a single `requestAnimationFrame` causes inconsistent row heights (first 3 rows taller than rest).
**Cause**: el-table-v2's virtual scroller calculates positions based on `estimatedRowHeight` , but a single frame isn't enough for it to fully settle.
**Solution**: Use TWO `requestAnimationFrame` calls before measuring:
```typescript
await nextTick();
await new Promise(resolve => requestAnimationFrame(resolve)); // Frame 1
await new Promise(resolve => requestAnimationFrame(resolve)); // Frame 2 - el-table-v2 now settled
const height = probeRowRef.value?.offsetHeight;
```
**Verification**: All rows should have identical heights and consistent spacing.
### el-table-v2 resize with probe row (clear-then-set pattern)
When handling window/container resize with a probe row for dynamic row height:
**Problem**: Clearing `estimatedRowHeight` to trigger re-measure creates a visible flash (1-2 frames) where el-table-v2 uses default height.
**Root Cause**: The gap between clearing the old value and setting the new value is visible to el-table-v2.
**Solution**: Measure first (capturing new values), then use `queueMicrotask` to clear and set in the SAME microtask:
```typescript
// 1. Measure first while old values still set
const headerHeight = headerEl?.offsetHeight;
const rowHeight = firstRow?.offsetHeight;
const newHeader = headerHeight & & headerHeight > 0 ? headerHeight : estimatedHeaderHeight.value;
const newRow = rowHeight & & rowHeight > 0 ? rowHeight : estimatedRowHeight.value;
// 2. Clear then set in same microtask (before next paint)
estimatedRowHeight.value = undefined;
estimatedHeaderHeight.value = undefined;
queueMicrotask(() => {
estimatedRowHeight.value = newRow;
estimatedHeaderHeight.value = newHeader;
});
```
**Why queueMicrotask works**: It defers the set to the end of the current microtask queue, but BEFORE the next paint. So the sequence is:
- Microtask 1: `undefined` is set (triggers el-table-v2 re-measure)
- Microtask 2 (queued): New value is set
- Paint: Only one paint happens with the correct value
**Without queueMicrotask**: The clear and set happen in separate Vue reactivity updates, causing TWO paints (one with undefined, one with new value).
---
### Vue 3 Template: VNode Rendering
**Problem**: Using `{renderFunction()}` in Vue template renders the function's string representation, not the returned VNode.
**Why**: In Vue 3 templates, `{xxx}` is treated as literal text interpolation, not JSX expression.
**Correct Pattern**: Use functional components that delegate to render functions:
```typescript
// Define functional component that delegates to render function
const MiniTableCell = (params: CellRendererParams< T > ) => renderCellContent(params);
const MiniTableHeader = (params: HeaderCellRendererParams< T > ) => renderHeaderCellContent(params);
// Use in template as component (NOT as {MiniTableCell(...)})
< template >
< MiniTableCell :cellData = "value" :column :rowData / >
< / template >
```
**Why this works**: Vue functional components receive VNode params and return VNodes, which Vue renders correctly. Calling `renderFunction()` directly in template gives `{[object Promise]}` or stringified function output.
---
feat: bootstrap coding specs with CC + Codex pipeline
Add Trellis spec files documenting all major architectural areas:
- plugs/composables: 7 Vue composables (useListTable, useModifyForm, etc.)
- plugs/api: 9 API modules with CRUD patterns
- plugs/element: Element Plus wrappers (listTableDialog, formatter, message, rule)
- plugs/http: 3 axios variants with AxiosOptions interface
- packages/base: 18 base Vue components
- packages/manage: Management UI (views, head, common)
- plugs/config+store+i18n: Styles, sizes, Vuex store, i18n, websocket
Each spec contains real code examples with file paths, anti-patterns
documented, and no placeholder text.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3 months ago
## Code Review Checklist
<!-- What reviewers should check -->
(To be filled by the team)