Skip to content

Commit f6461da

Browse files
committed
fix(workspace): harden credential redaction
Merge current main and resolve the workspace runner conflict. Redact authenticated clone URLs, Docker environment arguments, and clone errors before they reach logs or callers.
2 parents 65b327a + b6693e2 commit f6461da

272 files changed

Lines changed: 30288 additions & 4194 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.design-sync/NOTES.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Virtual Engineer — design-sync notes
2+
3+
## Repo shape
4+
5+
- Full-stack Hono/React app; admin UI lives in `src/admin/ui/`
6+
- UI components are NOT compiled to a distributable — `tsconfig.admin-ui.json` has `"noEmit": true` (required by `"allowImportingTsExtensions": true`)
7+
- No `.d.ts` output → all props declared via `dtsPropsFor` in config
8+
- No pre-built `dist/``--entry .design-sync/bundle-entry.tsx` (synth-entry mode)
9+
10+
## Vite-only feature shims
11+
12+
Two source files use `import.meta.glob` which esbuild cannot handle:
13+
- `src/admin/ui/components/Icon.tsx` → shimmed at `.design-sync/shims/Icon.tsx`
14+
- `src/admin/ui/components/ProviderGlyph.tsx` → shimmed at `.design-sync/shims/ProviderGlyph.tsx`
15+
16+
`Stat`, `Drawer`, and `Modal` import `Icon` internally — they also have shims in `.design-sync/shims/` with corrected import paths. If you add a new component that imports `Icon`, check if it needs a shim too.
17+
18+
## CSS entry
19+
20+
`global.css` has `@import "@fontsource/..."` and `@import "./tokens.css"` which are bare module specifiers that don't resolve in the bundle context. Fixed by:
21+
- `cssEntry: ".design-sync/style-entry.css"` — manually merged copy of `global.css` + `tokens.css` with @fontsource imports removed
22+
- `extraFonts: [...]`@fontsource CSS files processed by the converter to extract @font-face rules and copy woff2 files to `fonts/`
23+
24+
If `tokens.css` or `global.css` change significantly, update `.design-sync/style-entry.css` to match.
25+
26+
## Component grouping
27+
28+
The converter places components based on their source file path relative to `srcDir = src/admin/ui`. Since all components are in `src/admin/ui/components/` and `components` is a generic dir name (in GENERIC_DIR), all components fall into the `general` group. Shim components (in `.design-sync/shims/`) are placed in the `shims` group. This is a cosmetic distinction — the design agent sees both equally.
29+
30+
## Fonts
31+
32+
39 `@font-face` rules from 7 @fontsource CSS files. Both woff and woff2 formats are included (79 font files total). The @fontsource packages cover 5 unicode subsets for IBM Plex Mono and 6 for IBM Plex Sans.
33+
34+
## States and tones
35+
36+
`TONE` palette and `STATES` catalog live in `src/admin/ui/states.ts`. The shim at `.design-sync/shims/states.ts` is a copy with the `"../types.ts"` import corrected to `"./types.ts"`. If states change upstream, update both files.
37+
38+
## Re-sync risks
39+
40+
- `style-entry.css` is a manual copy — will silently drift if `global.css` or `tokens.css` change
41+
- Shim files (Icon, ProviderGlyph, Stat, Drawer, Modal, states) are manual copies — will drift if originals change
42+
- `dtsPropsFor` in config is hand-written — needs update when component APIs change
43+
- Icon path list in `shims/Icon.tsx` covers 33 icons as of 2026-07-02; new icons added to `src/admin/ui/icons/` won't appear in the shim automatically
44+
- `states.ts` shim covers 17 TaskState values as of 2026-07-02; new states need to be added to both the shim and the shim's `dtsPropsFor` entry
45+
46+
## Build command
47+
48+
```
49+
node .ds-sync/package-build.mjs \
50+
--config .design-sync/config.json \
51+
--node-modules ./node_modules \
52+
--entry .design-sync/bundle-entry.tsx \
53+
--out ./ds-bundle
54+
```

.design-sync/bundle-entry.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Synthetic bundle entry for the Virtual Engineer UI design system.
2+
// Components with Vite-only imports (import.meta.glob) are replaced by shims.
3+
// Stat/Drawer/Modal shims also fix transitive Icon imports.
4+
5+
export { Bars } from "../src/admin/ui/components/Bars.tsx";
6+
export { Drawer, DetailSection, DetailRow, StatusBanner } from "./shims/Drawer.tsx";
7+
export { Icon } from "./shims/Icon.tsx";
8+
export { Meta } from "../src/admin/ui/components/Meta.tsx";
9+
export {
10+
Modal, Field, FieldInput, FieldSelect,
11+
FieldTextarea, FormError, FormRow, FormActions,
12+
} from "./shims/Modal.tsx";
13+
export { ProviderGlyph } from "./shims/ProviderGlyph.tsx";
14+
export { RowCard } from "../src/admin/ui/components/RowCard.tsx";
15+
export { Stat } from "./shims/Stat.tsx";
16+
export { StatePill } from "../src/admin/ui/components/StatePill.tsx";
17+
export { Tabs, TabPanel } from "../src/admin/ui/components/Tabs.tsx";
18+
export { Tag } from "../src/admin/ui/components/Tag.tsx";
19+
export { Toggle } from "../src/admin/ui/components/Toggle.tsx";

.design-sync/config.json

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
{
2+
"projectId": "aec2a18e-3c79-4107-b509-4f9adfc9c58e",
3+
"pkg": "virtual-engineer",
4+
"globalName": "VE",
5+
"shape": "package",
6+
"srcDir": "src/admin/ui",
7+
"cssEntry": ".design-sync/style-entry.css",
8+
"extraFonts": [
9+
"node_modules/@fontsource/ibm-plex-sans/400.css",
10+
"node_modules/@fontsource/ibm-plex-sans/500.css",
11+
"node_modules/@fontsource/ibm-plex-sans/600.css",
12+
"node_modules/@fontsource/ibm-plex-sans/700.css",
13+
"node_modules/@fontsource/ibm-plex-mono/400.css",
14+
"node_modules/@fontsource/ibm-plex-mono/500.css",
15+
"node_modules/@fontsource/ibm-plex-mono/600.css"
16+
],
17+
"buildCmd": "node .ds-sync/package-build.mjs --config .design-sync/config.json --node-modules ./node_modules --entry .design-sync/bundle-entry.tsx --out ./ds-bundle",
18+
"readmeHeader": ".design-sync/conventions.md",
19+
"overrides": {
20+
"Icon": { "cardMode": "column" }
21+
},
22+
"componentSrcMap": {
23+
"Bars": "src/admin/ui/components/Bars.tsx",
24+
"Drawer": ".design-sync/shims/Drawer.tsx",
25+
"DetailSection": ".design-sync/shims/Drawer.tsx",
26+
"DetailRow": ".design-sync/shims/Drawer.tsx",
27+
"StatusBanner": ".design-sync/shims/Drawer.tsx",
28+
"Icon": ".design-sync/shims/Icon.tsx",
29+
"Meta": "src/admin/ui/components/Meta.tsx",
30+
"Modal": ".design-sync/shims/Modal.tsx",
31+
"Field": ".design-sync/shims/Modal.tsx",
32+
"FieldInput": ".design-sync/shims/Modal.tsx",
33+
"FieldSelect": ".design-sync/shims/Modal.tsx",
34+
"FieldTextarea": ".design-sync/shims/Modal.tsx",
35+
"FormError": ".design-sync/shims/Modal.tsx",
36+
"FormRow": ".design-sync/shims/Modal.tsx",
37+
"FormActions": ".design-sync/shims/Modal.tsx",
38+
"ProviderGlyph": ".design-sync/shims/ProviderGlyph.tsx",
39+
"RowCard": "src/admin/ui/components/RowCard.tsx",
40+
"Stat": ".design-sync/shims/Stat.tsx",
41+
"StatePill": "src/admin/ui/components/StatePill.tsx",
42+
"Tabs": "src/admin/ui/components/Tabs.tsx",
43+
"TabPanel": "src/admin/ui/components/Tabs.tsx",
44+
"Tag": "src/admin/ui/components/Tag.tsx",
45+
"Toggle": "src/admin/ui/components/Toggle.tsx"
46+
},
47+
"dtsPropsFor": {
48+
"Bars": "data: number[]; height?: number; tone?: 'active' | 'ok' | 'warn' | 'danger' | 'info' | 'muted';",
49+
"Drawer": "eyebrow?: string; title: string; glyph?: React.ReactNode; onClose: () => void; footer?: React.ReactNode; children: React.ReactNode;",
50+
"DetailSection": "label?: string; children: React.ReactNode;",
51+
"DetailRow": "k: string; mono?: boolean; children?: React.ReactNode;",
52+
"StatusBanner": "tone: 'active' | 'ok' | 'warn' | 'danger' | 'info' | 'muted'; icon: string; title: string; sub?: string;",
53+
"Icon": "name: string; size?: number; style?: React.CSSProperties; className?: string;",
54+
"Meta": "label: string; children: React.ReactNode; mono?: boolean; accent?: boolean;",
55+
"Modal": "title: string; sub?: string; onClose: () => void; children: React.ReactNode; footer?: React.ReactNode; wide?: boolean; width?: number;",
56+
"Field": "label: string; required?: boolean; children: React.ReactNode; hint?: string;",
57+
"FieldInput": "value?: string | number; placeholder?: string; disabled?: boolean; type?: string; onChange?: React.ChangeEventHandler<HTMLInputElement>;",
58+
"FieldSelect": "value?: string; disabled?: boolean; onChange?: React.ChangeEventHandler<HTMLSelectElement>; children?: React.ReactNode;",
59+
"FieldTextarea": "value?: string; placeholder?: string; disabled?: boolean; rows?: number; onChange?: React.ChangeEventHandler<HTMLTextAreaElement>;",
60+
"FormError": "msg: string | null;",
61+
"FormRow": "children: React.ReactNode;",
62+
"FormActions": "children: React.ReactNode;",
63+
"ProviderGlyph": "provider: string; size?: number;",
64+
"RowCard": "children: React.ReactNode; onClick?: () => void;",
65+
"Stat": "label: string; value: number | string; sub?: string; tone?: 'active' | 'ok' | 'warn' | 'danger' | 'info' | 'muted'; icon?: string; big?: boolean;",
66+
"StatePill": "state: 'DETECTED' | 'CONTEXT_BUILDING' | 'AGENT_RUNNING' | 'IN_REVIEW' | 'FEEDBACK_PROCESSING' | 'RETRY_CYCLE' | 'MERGED' | 'CLOSING' | 'DONE' | 'FAILED' | 'ABANDONED' | 'REVIEW_PENDING' | 'REVIEW_RUNNING' | 'REVIEW_COMMENTING' | 'REVIEW_WATCHING' | 'REVIEW_DONE' | 'REVIEW_FAILED'; size?: 'sm' | 'md'; pulse?: boolean;",
67+
"Tabs": "tabs: Array<{ id: string; label: string; count?: number | null }>; value: string; onChange: (id: string) => void; size?: 'sm' | 'md';",
68+
"TabPanel": "children: React.ReactNode;",
69+
"Tag": "children: React.ReactNode; tone?: 'active' | 'ok' | 'warn' | 'danger' | 'info' | 'muted'; mono?: boolean;",
70+
"Toggle": "on: boolean; onChange?: (on: boolean) => void; disabled?: boolean;"
71+
}
72+
}

.design-sync/conventions.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Virtual Engineer UI — Design Conventions
2+
3+
## Design system overview
4+
5+
Virtual Engineer uses a **dark-first OKLCH token system** with a light-theme override via `[data-theme="light"]`. The palette is cool-neutral (hue 258°) with a purple accent (hue 248°) and semantic state hues for ok/warn/danger/info/muted.
6+
7+
## Token system
8+
9+
All tokens are CSS custom properties on `:root`. Key categories:
10+
11+
| Group | Tokens |
12+
|---|---|
13+
| Accent | `--accent`, `--accent-strong`, `--accent-soft`, `--accent-line` (hue controllable via `--accent-h`) |
14+
| Backgrounds | `--bg`, `--bg-grad`, `--panel`, `--panel-2`, `--panel-3`, `--rail` |
15+
| Borders | `--border`, `--border-soft`, `--border-strong` |
16+
| Text | `--text`, `--text-dim`, `--text-faint`, `--text-ghost` |
17+
| State | `--ok/--ok-soft`, `--warn/--warn-soft`, `--danger/--danger-soft`, `--info/--info-soft`, `--muted-state/--muted-state-soft` |
18+
| Shape | `--radius` (10px), `--radius-sm` (7px), `--radius-lg` (14px), `--ease` |
19+
| Typography | `--font-sans` (IBM Plex Sans), `--font-mono` (IBM Plex Mono) |
20+
21+
State tones map to the `ToneKey` type: `"active" | "ok" | "warn" | "danger" | "info" | "muted"`.
22+
23+
## Typography
24+
25+
- **Body**: IBM Plex Sans, 14px, 1.45 line-height
26+
- **Monospace** (code, commit hashes, branch names): IBM Plex Mono — apply via `.mono` class or `font-family: var(--font-mono)`
27+
- **Eyebrow** labels: use `.eyebrow` class (10.5px, 600, uppercase, letter-spacing)
28+
29+
## Component groups
30+
31+
- **`general/`** — app-level primitives: `Bars`, `Meta`, `RowCard`, `StatePill`, `Tabs`/`TabPanel`, `Tag`, `Toggle`
32+
- **`shims/`** — overlays and form system: `Drawer` (+`DetailSection`, `DetailRow`, `StatusBanner`), `Icon`, `Modal` (+`Field`, `FieldInput`, `FieldSelect`, `FieldTextarea`, `FormError`, `FormRow`, `FormActions`), `ProviderGlyph`, `Stat`
33+
34+
## CSS utility classes
35+
36+
Available globally via `styles.css`:
37+
38+
| Class | Purpose |
39+
|---|---|
40+
| `.btn` / `.btn.primary` / `.btn.danger` / `.btn.sm` | Standard button variants |
41+
| `.iconbtn` | Square icon-only button (30×30px) |
42+
| `.card` | Surface with panel background and soft border |
43+
| `.pill` | Compact label with optional `.dot` |
44+
| `.eyebrow` | Section heading / label text |
45+
| `.mono` | Monospace text |
46+
| `.fade-up` | Entrance animation |
47+
| `.live-dot` | Pulsing status indicator |
48+
| `.metric-val` | Tabular numeral formatting |
49+
| `.modal-scrim` / `.modal` / `.modal-head` / `.modal-body` / `.modal-foot` | Modal layout skeleton |
50+
| `.drawer-scrim` / `.drawer` / `.drawer-head` / `.drawer-body` / `.drawer-foot` | Drawer layout skeleton |
51+
| `.detail-rows` / `.detail-row` / `.detail-key` / `.detail-val` | Key-value detail lists |
52+
| `.pick-card` / `.pick-card.sel` | Selectable option cards |
53+
54+
## State machine
55+
56+
`StatePill` takes a `state` prop from the full `TaskState` union (17 values). States group into:
57+
- **Generation**: `DETECTED → CONTEXT_BUILDING → AGENT_RUNNING → IN_REVIEW → FEEDBACK_PROCESSING → RETRY_CYCLE → MERGED → CLOSING → DONE / FAILED / ABANDONED`
58+
- **Review**: `REVIEW_PENDING → REVIEW_RUNNING → REVIEW_COMMENTING → REVIEW_WATCHING → REVIEW_DONE / REVIEW_FAILED`
59+
60+
## Layout patterns
61+
62+
- **Drawer**: slides from the right; app shell shifts left via `body.ve-drawer-open → .app { padding-right: 460px }`. Use `Drawer` + `DetailSection` + `DetailRow` for entity detail panels.
63+
- **Modal**: centered overlay with backdrop blur; uses `Modal` + `FormRow` + `Field` + form atoms for forms.
64+
- **Stats grid**: `Stat` components in a flex row with `flex: 1` each.
65+
- **Row list**: `RowCard` in a vertical stack for table-like entity lists.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import React from "react";
2+
import { DetailSection, DetailRow } from "virtual-engineer";
3+
4+
export function TaskDetails() {
5+
return (
6+
<div style={{ padding: 24, display: "flex", flexDirection: "column", gap: 20 }}>
7+
<DetailSection label="Ticket">
8+
<DetailRow k="Source">GitHub Issue #128</DetailRow>
9+
<DetailRow k="Title">Fix auth session timeout on mobile</DetailRow>
10+
<DetailRow k="Assignee">Fadi Shehadeh</DetailRow>
11+
<DetailRow k="Created">2 hours ago</DetailRow>
12+
</DetailSection>
13+
14+
<DetailSection label="Work">
15+
<DetailRow k="Branch" mono>fix/auth-session-mobile</DetailRow>
16+
<DetailRow k="Commit" mono>a29c08e</DetailRow>
17+
<DetailRow k="PR">#142 — Fix mobile auth session</DetailRow>
18+
</DetailSection>
19+
</div>
20+
);
21+
}
22+
23+
export function MinimalSection() {
24+
return (
25+
<div style={{ padding: 24 }}>
26+
<DetailSection>
27+
<DetailRow k="Status">Running</DetailRow>
28+
<DetailRow k="Duration">3m 42s</DetailRow>
29+
<DetailRow k="Agent">Claude Sonnet 4</DetailRow>
30+
</DetailSection>
31+
</div>
32+
);
33+
}

.design-sync/previews/Field.tsx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import React from "react";
2+
import { Field, FieldInput, FieldSelect, FieldTextarea } from "virtual-engineer";
3+
4+
export function TextInput() {
5+
return (
6+
<div style={{ padding: 24, display: "flex", flexDirection: "column", gap: 16, maxWidth: 400 }}>
7+
<Field label="Repository URL" required hint="The HTTPS URL of the repository to monitor.">
8+
<FieldInput placeholder="https://github.com/owner/repo" />
9+
</Field>
10+
<Field label="Branch" required>
11+
<FieldInput placeholder="main" defaultValue="main" />
12+
</Field>
13+
</div>
14+
);
15+
}
16+
17+
export function SelectAndTextarea() {
18+
return (
19+
<div style={{ padding: 24, display: "flex", flexDirection: "column", gap: 16, maxWidth: 400 }}>
20+
<Field label="Provider">
21+
<FieldSelect>
22+
<option value="github">GitHub</option>
23+
<option value="gitlab">GitLab</option>
24+
<option value="gerrit">Gerrit</option>
25+
</FieldSelect>
26+
</Field>
27+
<Field label="Agent prompt" hint="Instructions passed to the coding agent.">
28+
<FieldTextarea
29+
rows={4}
30+
placeholder="You are a coding assistant. When a task is detected…"
31+
/>
32+
</Field>
33+
</div>
34+
);
35+
}
36+
37+
export function Disabled() {
38+
return (
39+
<div style={{ padding: 24, display: "flex", flexDirection: "column", gap: 16, maxWidth: 400 }}>
40+
<Field label="Project ID">
41+
<FieldInput value="proj_a1b2c3d4" disabled />
42+
</Field>
43+
<Field label="Status">
44+
<FieldSelect disabled>
45+
<option>Active</option>
46+
</FieldSelect>
47+
</Field>
48+
</div>
49+
);
50+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import React from "react";
2+
import { FormActions } from "virtual-engineer";
3+
4+
export function SaveCancel() {
5+
return (
6+
<div style={{ padding: 24, maxWidth: 400 }}>
7+
<FormActions>
8+
<button className="btn">Cancel</button>
9+
<button className="btn primary">Save Integration</button>
10+
</FormActions>
11+
</div>
12+
);
13+
}
14+
15+
export function WithDanger() {
16+
return (
17+
<div style={{ padding: 24, maxWidth: 400 }}>
18+
<FormActions>
19+
<button className="btn danger">Delete</button>
20+
<span style={{ flex: 1 }} />
21+
<button className="btn">Cancel</button>
22+
<button className="btn primary">Confirm</button>
23+
</FormActions>
24+
</div>
25+
);
26+
}
27+
28+
export function Loading() {
29+
return (
30+
<div style={{ padding: 24, maxWidth: 400 }}>
31+
<FormActions>
32+
<button className="btn">Cancel</button>
33+
<button className="btn primary" disabled style={{ opacity: 0.7 }}>
34+
Connecting…
35+
</button>
36+
</FormActions>
37+
</div>
38+
);
39+
}

.design-sync/previews/FormRow.tsx

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import React from "react";
2+
import { FormRow, Field, FieldInput, FieldSelect, FormError } from "virtual-engineer";
3+
4+
export function IntegrationForm() {
5+
return (
6+
<div style={{ padding: 24, maxWidth: 420 }}>
7+
<FormRow>
8+
<Field label="Name" required>
9+
<FieldInput placeholder="My GitHub Repo" />
10+
</Field>
11+
<Field label="Provider">
12+
<FieldSelect>
13+
<option>GitHub</option>
14+
<option>GitLab</option>
15+
<option>Gerrit</option>
16+
</FieldSelect>
17+
</Field>
18+
<Field label="Repository URL" required hint="HTTPS clone URL">
19+
<FieldInput placeholder="https://github.com/owner/repo" />
20+
</Field>
21+
<Field label="Branch">
22+
<FieldInput placeholder="main" />
23+
</Field>
24+
</FormRow>
25+
</div>
26+
);
27+
}
28+
29+
export function WithError() {
30+
return (
31+
<div style={{ padding: 24, maxWidth: 420 }}>
32+
<FormRow>
33+
<FormError msg="Could not connect to the repository. Check the URL and your access token." />
34+
<Field label="Repository URL" required>
35+
<FieldInput
36+
placeholder="https://github.com/owner/repo"
37+
defaultValue="https://github.com/bad/url"
38+
style={{ borderColor: "var(--danger)" }}
39+
/>
40+
</Field>
41+
</FormRow>
42+
</div>
43+
);
44+
}

0 commit comments

Comments
 (0)