UNPKG

trellis

Version:

Agentic State Engine — event-sourced causal graph with branching, decision traces, and realtime sync for AI-native applications

261 lines (232 loc) 7.14 kB
<!DOCTYPE html> <html lang="en" data-trellis-band="L3"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Trellis — TML v0.1 (Kanban)</title> <link rel="stylesheet" href="/theme/runtime-theme.css"> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: var(--font); background: var(--bg); color: var(--text); padding: 24px; } header { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; flex-wrap: wrap; } h1 { font-size: 16px; font-weight: 700; } h1 span { color: var(--text3); font-weight: 400; font-size: 12px; margin-left: 8px; } .tag { font: 600 10px var(--mono); text-transform: uppercase; letter-spacing: .3px; color: var(--accent); border: 1px solid var(--accent); border-radius: 999px; padding: 3px 9px; } .kanban { display: flex; gap: 16px; overflow-x: auto; padding-bottom: 16px; min-height: 200px; } .kanban-col { min-width: 300px; max-width: 340px; flex: 1; display: flex; flex-direction: column; } .kanban-col-head { display: flex; align-items: center; gap: 8px; padding: 10px 12px; background: var(--surface); border: 1px solid var(--border); border-radius: 10px 10px 0 0; border-bottom: none; } .kanban-col-head .col-title { font: 600 12px var(--font); text-transform: uppercase; letter-spacing: .4px; } .kanban-col-body { flex: 1; display: flex; flex-direction: column; gap: 8px; padding: 10px; background: var(--tml-kanban-body-inset); border: 1px solid var(--border); border-top: none; border-radius: 0 0 10px 10px; min-height: 80px; } .issue-card { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 14px; flex: none; } .issue-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; margin-bottom: 8px; } .issue-card .issue-id { font: 600 12px var(--mono); color: var(--accent); } .issue-card .issue-title { font-size: 13px; color: var(--text); margin-bottom: 8px; line-height: 1.4; } .issue-card .issue-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; } .issue-card .lane-badge { font: 500 10px var(--mono); background: var(--tml-badge-success-bg); border: 1px solid var(--tml-badge-success-border); padding: 2px 8px; border-radius: 999px; color: var(--green); max-width: 140px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .issue-card .lane-badge.none { background: var(--surface2); border-color: var(--border); color: var(--text3); } .priority-badge { font: 600 10px var(--mono); text-transform: uppercase; letter-spacing: .3px; padding: 3px 8px; border-radius: 999px; white-space: nowrap; } .priority-badge.critical, .priority-badge.high { background: var(--tml-badge-critical-bg); color: var(--red); } .priority-badge.medium { background: var(--tml-badge-warning-bg); color: var(--yellow); } .priority-badge.low { background: var(--tml-badge-neutral-bg); color: var(--text3); } </style> </head> <body> <header> <h1>Trellis <span>TML v0.1 · Kanban</span></h1> <span class="tag">tml-*</span> </header> <!-- Three columns = ISSUE_COLUMNS collapse from lanes.html. Each .kanban-col-body is a tml-query list container; its child card is the per-row template. tml-live re-renders on every SSE snapshot. See docs/specs/tml-v0.1-kanban.md. --> <section id="board" class="kanban"> <div class="kanban-col"> <div class="kanban-col-head"><span class="col-title">Backlog</span></div> <div class="kanban-col-body" tml-query="find ?e where type = 'Issue' and not (status = 'in_progress' or status = 'paused' or status = 'closed')" tml-each="issue of issues" tml-live tml-ref="col-backlog"> <article class="issue-card" data-trellis-shell="card"> <div class="issue-card-head"> <span class="issue-id" tml-text="issue.id"></span> <span tml-text="issue.priority" tml-attr-class="'priority-badge ' + issue.priority"></span> </div> <div class="issue-title" tml-text="issue.title"></div> <div class="issue-meta" tml-if="issue.laneIds"> <span class="lane-badge" tml-text="issue.laneIds"></span> </div> </article> </div> </div> <div class="kanban-col"> <div class="kanban-col-head"><span class="col-title">In Progress</span></div> <div class="kanban-col-body" tml-query="find ?e where type = 'Issue' and (status = 'in_progress' or status = 'paused')" tml-each="issue of issues" tml-live tml-ref="col-in-progress"> <article class="issue-card" data-trellis-shell="card"> <div class="issue-card-head"> <span class="issue-id" tml-text="issue.id"></span> <span tml-text="issue.priority" tml-attr-class="'priority-badge ' + issue.priority"></span> </div> <div class="issue-title" tml-text="issue.title"></div> <div class="issue-meta" tml-if="issue.laneIds"> <span class="lane-badge" tml-text="issue.laneIds"></span> </div> </article> </div> </div> <div class="kanban-col"> <div class="kanban-col-head"><span class="col-title">Done</span></div> <div class="kanban-col-body" tml-query="find ?e where type = 'Issue' and status = 'closed'" tml-each="issue of issues" tml-live tml-ref="col-done"> <article class="issue-card" data-trellis-shell="card"> <div class="issue-card-head"> <span class="issue-id" tml-text="issue.id"></span> <span tml-text="issue.priority" tml-attr-class="'priority-badge ' + issue.priority"></span> </div> <div class="issue-title" tml-text="issue.title"></div> <div class="issue-meta" tml-if="issue.laneIds"> <span class="lane-badge" tml-text="issue.laneIds"></span> </div> </article> </div> </div> </section> <script type="module"> import { WebDriver, mount } from '/tml-runtime.js'; const driver = new WebDriver({ baseUrl: '' }); driver .connect({ snapshotUrl: '/api/lanes', streamUrl: '/api/lanes/stream?events=snapshot', }) .then(() => mount(document.getElementById('board'), driver)) .catch((e) => console.error('[tml] mount failed', e)); </script> </body> </html>