@polderlabs/openkan 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +226 -0
- package/LICENSE +21 -0
- package/README.md +318 -0
- package/agents/openkan.md +254 -0
- package/bin/install-agent.mjs +63 -0
- package/bin/ok.mjs +17 -0
- package/bin/openkan.mjs +10 -0
- package/dist/.claude/skills/ok-planning/SKILL.md +285 -0
- package/dist/.claude/skills/ok-planning/references/integration.md +153 -0
- package/dist/.claude/skills/ok-planning/references/schemas.md +270 -0
- package/dist/.claude/skills/ok-planning/references/workflows.md +185 -0
- package/dist/.claude/skills/ok-planning/scripts/ok-init.sh +14 -0
- package/dist/.claude/skills/ok-planning/scripts/ok-resume.sh +38 -0
- package/dist/.claude/skills/ok-planning/scripts/ok-status.sh +24 -0
- package/dist/agents/openkan.md +254 -0
- package/dist/bin/install-agent.mjs +76 -0
- package/dist/bin/ok-install.js +58 -0
- package/dist/bin/ok.js +138 -0
- package/dist/bin/openkan.js +804 -0
- package/dist/commands/organize.md +15 -0
- package/dist/kanban/agent-profile.js +8 -0
- package/dist/kanban/archive.js +49 -0
- package/dist/kanban/bizar.js +242 -0
- package/dist/kanban/board.js +367 -0
- package/dist/kanban/bulk.js +139 -0
- package/dist/kanban/changelog.js +186 -0
- package/dist/kanban/chat.js +1280 -0
- package/dist/kanban/claude-state.js +974 -0
- package/dist/kanban/comments.js +80 -0
- package/dist/kanban/docs.js +144 -0
- package/dist/kanban/fs.js +163 -0
- package/dist/kanban/git.js +196 -0
- package/dist/kanban/images.js +140 -0
- package/dist/kanban/import.js +295 -0
- package/dist/kanban/inputs.js +94 -0
- package/dist/kanban/insights.js +140 -0
- package/dist/kanban/io.js +75 -0
- package/dist/kanban/mdx-render.js +348 -0
- package/dist/kanban/mdx.js +231 -0
- package/dist/kanban/projects.js +545 -0
- package/dist/kanban/search.js +121 -0
- package/dist/kanban/server.js +3296 -0
- package/dist/kanban/tags.js +124 -0
- package/dist/kanban/template.js +145 -0
- package/dist/kanban/tsx-sandbox.js +187 -0
- package/dist/kanban/watcher.js +270 -0
- package/dist/ok/commands/goal.js +65 -0
- package/dist/ok/commands/index.js +87 -0
- package/dist/ok/commands/init.js +15 -0
- package/dist/ok/commands/plan.js +155 -0
- package/dist/ok/commands/prd.js +202 -0
- package/dist/ok/commands/progress.js +31 -0
- package/dist/ok/commands/task.js +377 -0
- package/dist/ok/ids.js +98 -0
- package/dist/ok/lock.js +156 -0
- package/dist/ok/migrate.js +197 -0
- package/dist/ok/schemas.js +402 -0
- package/dist/ok/storage.js +222 -0
- package/dist/skills/openkan/SKILL.md +111 -0
- package/dist/skills/openkan/agents/openai.yaml +4 -0
- package/dist/skills/openkan/examples/simple-task.mdx +34 -0
- package/dist/skills/openkan/examples/with-ask.mdx +32 -0
- package/dist/skills/openkan/examples/with-choice.mdx +51 -0
- package/dist/skills/openkan/examples/with-preview.mdx +54 -0
- package/dist/skills/openkan/references/api.md +169 -0
- package/dist/skills/openkan/templates/task.mdx +46 -0
- package/dist/web/api.js +257 -0
- package/dist/web/app.js +4251 -0
- package/dist/web/bizar.js +39 -0
- package/dist/web/brand/agent-activity-sprite.svg +1 -0
- package/dist/web/brand/banner-docs.svg +24 -0
- package/dist/web/brand/banner.svg +32 -0
- package/dist/web/brand/empty-sessions.svg +17 -0
- package/dist/web/brand/empty-tasks.svg +17 -0
- package/dist/web/brand/favicon.svg +9 -0
- package/dist/web/brand/infinity-loader-animated.svg +220 -0
- package/dist/web/brand/infinity-loader-spritesheet.svg +230 -0
- package/dist/web/brand/logo-wordmark.svg +10 -0
- package/dist/web/brand/logo.svg +9 -0
- package/dist/web/brand/pixel-infinity-track.svg +1 -0
- package/dist/web/brand/social-card.svg +26 -0
- package/dist/web/changelog-view.js +456 -0
- package/dist/web/charts.js +269 -0
- package/dist/web/chat-sidebar.js +2397 -0
- package/dist/web/chat-status-motion.js +154 -0
- package/dist/web/claude-pane.js +820 -0
- package/dist/web/command-palette.js +381 -0
- package/dist/web/contributors-view.js +317 -0
- package/dist/web/cross-tab.js +102 -0
- package/dist/web/docs-view.js +168 -0
- package/dist/web/experience.css +165 -0
- package/dist/web/goals-view.js +45 -0
- package/dist/web/home-view.js +113 -0
- package/dist/web/images.js +311 -0
- package/dist/web/index.html +485 -0
- package/dist/web/insights.js +217 -0
- package/dist/web/keyboard.js +446 -0
- package/dist/web/mdx-viewer.js +600 -0
- package/dist/web/path-picker.js +787 -0
- package/dist/web/preview-frame.html +187 -0
- package/dist/web/settings.js +582 -0
- package/dist/web/style.css +8545 -0
- package/dist/web/task-view.js +1759 -0
- package/dist/web/vendor/gsap.min.js +11 -0
- package/dist/web/workspace.css +1513 -0
- package/package.json +71 -0
- package/skills/openkan/SKILL.md +111 -0
- package/skills/openkan/agents/openai.yaml +4 -0
- package/skills/openkan/examples/simple-task.mdx +34 -0
- package/skills/openkan/examples/with-ask.mdx +32 -0
- package/skills/openkan/examples/with-choice.mdx +51 -0
- package/skills/openkan/examples/with-preview.mdx +54 -0
- package/skills/openkan/references/api.md +169 -0
- package/skills/openkan/templates/task.mdx +46 -0
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<meta name="color-scheme" content="dark light" />
|
|
7
|
+
<title>OpenKan</title>
|
|
8
|
+
<link rel="stylesheet" href="style.css" />
|
|
9
|
+
<link rel="stylesheet" href="workspace.css?v=20260904-board-width" />
|
|
10
|
+
<link rel="stylesheet" href="experience.css" />
|
|
11
|
+
<!-- M-Brand: SVG favicon, mono-coral. No PNG fallback (spec: no rasters). -->
|
|
12
|
+
<link rel="icon" type="image/svg+xml" href="./brand/favicon.svg" />
|
|
13
|
+
</head>
|
|
14
|
+
<body>
|
|
15
|
+
<!-- M13: skip-link for keyboard / screen-reader users. Hidden until
|
|
16
|
+
focused, then promoted to the top-left of the viewport. -->
|
|
17
|
+
<a href="#board" class="skip-link">Skip to main content</a>
|
|
18
|
+
|
|
19
|
+
<header class="topbar" role="banner">
|
|
20
|
+
<div class="brand">
|
|
21
|
+
<!-- M-Brand: wordmark image replaces the inline K-mark span and the
|
|
22
|
+
OpenKan <h1>. The image uses currentColor for ink-80 in the
|
|
23
|
+
topbar context. -->
|
|
24
|
+
<span class="brand-wordmark" role="img" aria-label="OpenKan"></span>
|
|
25
|
+
<h1 class="visually-hidden">OpenKan</h1>
|
|
26
|
+
<!-- Brand-level project chip: clicking it opens the same project
|
|
27
|
+
switcher dropdown as the topbar-right chip. Owned by app.js. -->
|
|
28
|
+
<button id="brand-project-chip" class="brand-project-chip" type="button"
|
|
29
|
+
title="Switch project" aria-label="Switch project">
|
|
30
|
+
<span class="brand-project-label">Project</span>
|
|
31
|
+
<span class="brand-project-value">
|
|
32
|
+
<span class="brand-project-dot" aria-hidden="true"></span>
|
|
33
|
+
<span id="brand-project-name" class="brand-project-name">Loading…</span>
|
|
34
|
+
</span>
|
|
35
|
+
<span class="brand-project-caret" aria-hidden="true">▾</span>
|
|
36
|
+
</button>
|
|
37
|
+
</div>
|
|
38
|
+
<button id="home-page-btn" class="topbar-home" type="button" aria-label="Open workspace overview">
|
|
39
|
+
<span aria-hidden="true">⌂</span><span>Overview</span>
|
|
40
|
+
</button>
|
|
41
|
+
<div class="workspace-mode" role="group" aria-label="Workspace mode">
|
|
42
|
+
<button type="button" data-workspace-mode="tasks" class="active">Tasks</button>
|
|
43
|
+
<button type="button" data-workspace-mode="chat">Chat</button>
|
|
44
|
+
</div>
|
|
45
|
+
<nav class="topbar-tabs" role="tablist" aria-label="Dashboard sections">
|
|
46
|
+
<button type="button" class="tab" role="tab" data-tab="tasks" aria-selected="true">Tasks</button>
|
|
47
|
+
<button type="button" class="tab" role="tab" data-tab="docs" aria-selected="false">Docs</button>
|
|
48
|
+
<button type="button" class="tab" role="tab" data-tab="goals" aria-selected="false">Goals</button>
|
|
49
|
+
<button type="button" class="tab" role="tab" data-tab="agents" aria-selected="false">Agents</button>
|
|
50
|
+
</nav>
|
|
51
|
+
<div class="topbar-right">
|
|
52
|
+
<span id="status-pill" class="pill pill-disconnected" role="status" aria-live="polite">
|
|
53
|
+
<span class="pill-dot" aria-hidden="true"></span>
|
|
54
|
+
<span id="status-text">Disconnected</span>
|
|
55
|
+
</span>
|
|
56
|
+
<button id="new-task-btn" class="btn btn-primary topbar-create" type="button">
|
|
57
|
+
<span class="btn-symbol" aria-hidden="true">+</span>
|
|
58
|
+
<span class="btn-label">New task</span>
|
|
59
|
+
</button>
|
|
60
|
+
<!-- Project switcher: button shows the active project's name; clicking
|
|
61
|
+
opens a small popover listing every registered project. Owned by
|
|
62
|
+
web/app.js (OpenKanProjectSwitcher). -->
|
|
63
|
+
<div class="project-switcher" id="project-switcher">
|
|
64
|
+
<button id="project-switcher-btn" class="project-switcher-btn" type="button"
|
|
65
|
+
aria-haspopup="menu" aria-expanded="false"
|
|
66
|
+
title="Switch project">
|
|
67
|
+
<span class="project-switcher-dot" aria-hidden="true"></span>
|
|
68
|
+
<span id="project-switcher-label" class="project-switcher-label">…</span>
|
|
69
|
+
<span class="project-switcher-caret" aria-hidden="true">▾</span>
|
|
70
|
+
</button>
|
|
71
|
+
<div id="project-switcher-popover" class="project-switcher-popover" role="menu" hidden></div>
|
|
72
|
+
</div>
|
|
73
|
+
<div class="workspace-more">
|
|
74
|
+
<button id="workspace-more-btn" class="btn-icon" type="button" aria-label="More workspace pages" aria-haspopup="menu" aria-expanded="false" title="More workspace pages">•••</button>
|
|
75
|
+
<div id="workspace-more-menu" class="workspace-more-menu" role="menu" hidden>
|
|
76
|
+
<span class="workspace-more-label">Workspace mode</span>
|
|
77
|
+
<button type="button" role="menuitem" data-workspace-mode="tasks">Task mode</button>
|
|
78
|
+
<button type="button" role="menuitem" data-workspace-mode="chat">Chat mode</button>
|
|
79
|
+
<span class="workspace-more-separator"></span>
|
|
80
|
+
<button type="button" role="menuitem" data-workspace-page="changelog">Changelog</button>
|
|
81
|
+
<button type="button" role="menuitem" data-workspace-page="insights">Insights</button>
|
|
82
|
+
<button type="button" role="menuitem" data-workspace-page="contributors">Contributors</button>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
<button id="settings-btn" class="btn-icon" type="button" aria-label="Settings" title="Settings">⚙</button>
|
|
86
|
+
<button id="chat-sidebar-toggle-btn" class="btn-icon" type="button"
|
|
87
|
+
aria-label="Toggle chat sidebar" aria-controls="chat-sidebar"
|
|
88
|
+
aria-expanded="false" title="Chat sidebar (Alt+C)">💬</button>
|
|
89
|
+
<button id="palette-btn" class="btn-icon" type="button"
|
|
90
|
+
aria-label="Open command palette (Cmd/Ctrl K)"
|
|
91
|
+
title="Command palette (Cmd/Ctrl K)">⌘K</button>
|
|
92
|
+
</div>
|
|
93
|
+
</header>
|
|
94
|
+
|
|
95
|
+
<!-- Toast container (used by settings / changelog / contributors) -->
|
|
96
|
+
<div id="toast-container" class="toast-container" aria-live="polite" aria-atomic="true"></div>
|
|
97
|
+
|
|
98
|
+
<main class="dashboard">
|
|
99
|
+
<section id="tab-home" class="tab-pane" role="tabpanel" data-tab="home" hidden>
|
|
100
|
+
<div id="home-root" class="view-root"></div>
|
|
101
|
+
</section>
|
|
102
|
+
<!-- ─── TAB: Tasks ───────────────────────────────────────────────── -->
|
|
103
|
+
<section id="tab-tasks" class="tab-pane" role="tabpanel" data-tab="tasks">
|
|
104
|
+
<div class="workspace-intro">
|
|
105
|
+
<div>
|
|
106
|
+
<span class="workspace-eyebrow">Project workspace</span>
|
|
107
|
+
<h2>Move work forward</h2>
|
|
108
|
+
<p>Plan, coordinate, and review every task in one durable board.</p>
|
|
109
|
+
</div>
|
|
110
|
+
<div id="board-overview" class="board-overview" aria-label="Board summary">
|
|
111
|
+
<div class="overview-stat">
|
|
112
|
+
<span id="overview-total" class="overview-value">0</span>
|
|
113
|
+
<span class="overview-label">Visible</span>
|
|
114
|
+
</div>
|
|
115
|
+
<div class="overview-stat is-doing">
|
|
116
|
+
<span id="overview-doing" class="overview-value">0</span>
|
|
117
|
+
<span class="overview-label">In progress</span>
|
|
118
|
+
</div>
|
|
119
|
+
<div class="overview-stat is-review">
|
|
120
|
+
<span id="overview-review" class="overview-value">0</span>
|
|
121
|
+
<span class="overview-label">In review</span>
|
|
122
|
+
</div>
|
|
123
|
+
<div class="overview-stat is-done">
|
|
124
|
+
<span id="overview-done" class="overview-value">0</span>
|
|
125
|
+
<span class="overview-label">Done</span>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
|
|
130
|
+
<!-- Saved filter chips row (populated by app.js). Hidden when empty. -->
|
|
131
|
+
<div id="saved-filters-bar" class="saved-filters-bar" hidden>
|
|
132
|
+
<span class="filter-bar-label">Saved</span>
|
|
133
|
+
<div id="saved-filters-list" class="saved-filters-list"></div>
|
|
134
|
+
</div>
|
|
135
|
+
|
|
136
|
+
<!-- Category / tag / sort filter bar. Populated + wired up by app.js. -->
|
|
137
|
+
<div class="filter-bar" id="filter-bar" role="region" aria-label="Filter tasks">
|
|
138
|
+
<div class="filter-primary">
|
|
139
|
+
<div class="filter-bar-row search" id="filter-search">
|
|
140
|
+
<span class="search-icon" aria-hidden="true"></span>
|
|
141
|
+
<input type="search" id="search-input" autocomplete="off" spellcheck="false"
|
|
142
|
+
placeholder="Search titles, descriptions, tags, MDX content…"
|
|
143
|
+
aria-label="Search tasks" />
|
|
144
|
+
<span class="search-meta" id="search-meta" aria-live="polite"></span>
|
|
145
|
+
</div>
|
|
146
|
+
<div class="filter-bar-row controls" id="filter-controls">
|
|
147
|
+
<label class="select-wrap" id="sort-select-wrap">
|
|
148
|
+
<span class="sr-only">Sort tasks</span>
|
|
149
|
+
<select id="sort-select" aria-label="Sort tasks">
|
|
150
|
+
<option value="newest">Newest first</option>
|
|
151
|
+
<option value="oldest">Oldest first</option>
|
|
152
|
+
<option value="priority">Priority (urgent→low)</option>
|
|
153
|
+
<option value="effort">Effort (xl→xs)</option>
|
|
154
|
+
<option value="activity">Last activity</option>
|
|
155
|
+
</select>
|
|
156
|
+
</label>
|
|
157
|
+
<button type="button" id="filter-toggle-btn" class="filter-toggle-btn"
|
|
158
|
+
aria-expanded="false" aria-controls="filter-advanced">
|
|
159
|
+
Filters <span id="filter-count" class="filter-count" hidden>0</span>
|
|
160
|
+
</button>
|
|
161
|
+
<div class="archive-toggle" role="group" aria-label="Archive filter">
|
|
162
|
+
<button type="button" data-archive="active" class="active">Active</button>
|
|
163
|
+
<button type="button" data-archive="archived">Archived</button>
|
|
164
|
+
<button type="button" data-archive="both">Both</button>
|
|
165
|
+
</div>
|
|
166
|
+
</div>
|
|
167
|
+
</div>
|
|
168
|
+
|
|
169
|
+
<div id="filter-advanced" class="filter-advanced" hidden>
|
|
170
|
+
<div class="filter-bar-row categories" id="filter-categories">
|
|
171
|
+
<span class="filter-bar-label">Category</span>
|
|
172
|
+
<button type="button" data-category="all" class="all active">All</button>
|
|
173
|
+
<button type="button" data-category="frontend" class="c-frontend">frontend</button>
|
|
174
|
+
<button type="button" data-category="backend" class="c-backend">backend</button>
|
|
175
|
+
<button type="button" data-category="infra" class="c-infra">infra</button>
|
|
176
|
+
<button type="button" data-category="docs" class="c-docs">docs</button>
|
|
177
|
+
<button type="button" data-category="test" class="c-test">test</button>
|
|
178
|
+
<button type="button" data-category="design" class="c-design">design</button>
|
|
179
|
+
<button type="button" data-category="data" class="c-data">data</button>
|
|
180
|
+
<button type="button" data-category="security" class="c-security">security</button>
|
|
181
|
+
<button type="button" data-category="task" class="c-task">task</button>
|
|
182
|
+
</div>
|
|
183
|
+
<div class="filter-bar-row tags" id="filter-tags">
|
|
184
|
+
<span class="filter-bar-label">Tags</span>
|
|
185
|
+
<button type="button" data-tag="bug" class="t-bug">bug</button>
|
|
186
|
+
<button type="button" data-tag="feature" class="t-feature">feature</button>
|
|
187
|
+
<button type="button" data-tag="refactor" class="t-refactor">refactor</button>
|
|
188
|
+
<button type="button" data-tag="docs" class="t-docs">docs</button>
|
|
189
|
+
<button type="button" data-tag="test" class="t-test">test</button>
|
|
190
|
+
<button type="button" data-tag="perf" class="t-perf">perf</button>
|
|
191
|
+
<button type="button" data-tag="security" class="t-security">security</button>
|
|
192
|
+
<button type="button" data-tag="a11y" class="t-a11y">a11y</button>
|
|
193
|
+
</div>
|
|
194
|
+
<div class="filter-bar-row contributors" id="filter-contributors">
|
|
195
|
+
<span class="filter-bar-label">Contributors</span>
|
|
196
|
+
<button type="button" data-contributor="all" class="active">all</button>
|
|
197
|
+
<button type="button" data-contributor="@me" class="contributor-me">@me</button>
|
|
198
|
+
<!-- Other contributors are populated by app.js from /api/contributors -->
|
|
199
|
+
</div>
|
|
200
|
+
<div class="filter-advanced-actions">
|
|
201
|
+
<button type="button" id="save-filter-btn" class="filter-bar-save" title="Save current filter">Save view</button>
|
|
202
|
+
<button type="button" class="filter-bar-clear" id="filter-clear" aria-label="Clear filters">Clear filters</button>
|
|
203
|
+
</div>
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
206
|
+
|
|
207
|
+
<div id="main-content">
|
|
208
|
+
<main id="board" class="board" role="region" aria-label="Kanban board" tabindex="-1">
|
|
209
|
+
<!-- Columns are rendered by app.js -->
|
|
210
|
+
</main>
|
|
211
|
+
</div>
|
|
212
|
+
|
|
213
|
+
<!-- New Task Modal — Title + Project path (with Browse) + Description
|
|
214
|
+
+ Column / Agent / Model. Opened from the + New Task button in
|
|
215
|
+
the topbar. Lives inside <main class="dashboard"> which is fine:
|
|
216
|
+
the New Task button isn't reachable while the task view is open
|
|
217
|
+
(the topbar is overlaid by the task view), so the modal-collapse
|
|
218
|
+
bug doesn't apply here. -->
|
|
219
|
+
<div id="modal-backdrop" class="modal-backdrop" hidden>
|
|
220
|
+
<div class="modal" role="dialog" aria-modal="true" aria-labelledby="modal-title">
|
|
221
|
+
<header class="modal-header">
|
|
222
|
+
<h2 id="modal-title">New Task</h2>
|
|
223
|
+
<button class="btn-icon" type="button" data-close-modal aria-label="Close">×</button>
|
|
224
|
+
</header>
|
|
225
|
+
<form id="new-task-form" class="modal-body" novalidate>
|
|
226
|
+
<p id="task-create-project" class="task-create-context">Create a task in the current project.</p>
|
|
227
|
+
<label class="field">
|
|
228
|
+
<span>Task title <span class="field-required">Required</span></span>
|
|
229
|
+
<input name="title" type="text" required maxlength="200" autocomplete="off" placeholder="What needs to get done?" aria-describedby="task-create-error" />
|
|
230
|
+
</label>
|
|
231
|
+
<label class="field">
|
|
232
|
+
<span>Description <span class="field-optional">Optional</span></span>
|
|
233
|
+
<textarea name="description" rows="4" placeholder="Describe the outcome, context, and how to verify it. Markdown supported."></textarea>
|
|
234
|
+
</label>
|
|
235
|
+
<div class="field-row">
|
|
236
|
+
<label class="field">
|
|
237
|
+
<span>Status</span>
|
|
238
|
+
<select name="column">
|
|
239
|
+
<option value="backlog">Backlog</option>
|
|
240
|
+
<option value="todo" selected>To Do</option>
|
|
241
|
+
<option value="doing">In Progress</option>
|
|
242
|
+
<option value="review">Review</option>
|
|
243
|
+
<option value="done">Done</option>
|
|
244
|
+
</select>
|
|
245
|
+
</label>
|
|
246
|
+
<label class="field">
|
|
247
|
+
<span>Priority</span>
|
|
248
|
+
<select name="priority">
|
|
249
|
+
<option value="low">Low</option>
|
|
250
|
+
<option value="normal" selected>Normal</option>
|
|
251
|
+
<option value="high">High</option>
|
|
252
|
+
<option value="urgent">Urgent</option>
|
|
253
|
+
</select>
|
|
254
|
+
</label>
|
|
255
|
+
</div>
|
|
256
|
+
<details class="task-create-options">
|
|
257
|
+
<summary>Agent settings <span>Optional</span></summary>
|
|
258
|
+
<p>Assign an agent and model for later. Creating a task does not start an agent.</p>
|
|
259
|
+
<div class="field-row">
|
|
260
|
+
<label class="field"><span>Agent</span><input name="agent" type="text" placeholder="Use configured default" autocomplete="off" /></label>
|
|
261
|
+
<label class="field"><span>Model</span><input name="model" type="text" placeholder="Use configured default" autocomplete="off" /></label>
|
|
262
|
+
</div>
|
|
263
|
+
</details>
|
|
264
|
+
<input type="hidden" name="parentId" value="" />
|
|
265
|
+
<p id="task-create-error" role="alert" hidden></p>
|
|
266
|
+
<label class="task-create-open"><input name="openAfterCreate" type="checkbox" /> Open task after creating</label>
|
|
267
|
+
<footer class="modal-footer">
|
|
268
|
+
<span class="task-create-shortcut">Ctrl / ⌘ + Enter to create</span>
|
|
269
|
+
<button type="button" class="btn" id="task-discard-draft">Discard draft</button>
|
|
270
|
+
<button type="button" class="btn" data-close-modal>Close</button>
|
|
271
|
+
<button type="submit" class="btn btn-primary" id="task-create-submit">Create task</button>
|
|
272
|
+
</footer>
|
|
273
|
+
</form>
|
|
274
|
+
</div>
|
|
275
|
+
</div>
|
|
276
|
+
|
|
277
|
+
<!-- Per-task action menu (positioned dynamically) -->
|
|
278
|
+
<div id="action-menu" class="action-menu" hidden role="menu"></div>
|
|
279
|
+
|
|
280
|
+
<!-- Bulk action bar (shown when ≥ 1 card is selected via Ctrl/Cmd-click) -->
|
|
281
|
+
<div id="bulk-bar" class="bulk-bar" hidden role="toolbar" aria-label="Bulk actions for selected tasks">
|
|
282
|
+
<span class="bulk-bar-count" id="bulk-bar-count">0 selected</span>
|
|
283
|
+
<div class="bulk-bar-group">
|
|
284
|
+
<div class="bulk-bar-dropdown" id="bulk-move-dropdown">
|
|
285
|
+
<button type="button" class="bulk-bar-btn" id="bulk-move-btn" aria-haspopup="menu" aria-expanded="false">
|
|
286
|
+
Move <span class="bulk-bar-caret" aria-hidden="true">▾</span>
|
|
287
|
+
</button>
|
|
288
|
+
<div class="bulk-bar-menu" id="bulk-move-menu" role="menu" hidden>
|
|
289
|
+
<button type="button" data-column="backlog" role="menuitem">Backlog</button>
|
|
290
|
+
<button type="button" data-column="todo" role="menuitem">To Do</button>
|
|
291
|
+
<button type="button" data-column="doing" role="menuitem">In Progress</button>
|
|
292
|
+
<button type="button" data-column="review" role="menuitem">Review</button>
|
|
293
|
+
<button type="button" data-column="done" role="menuitem">Done</button>
|
|
294
|
+
</div>
|
|
295
|
+
</div>
|
|
296
|
+
<div class="bulk-bar-dropdown" id="bulk-priority-dropdown">
|
|
297
|
+
<button type="button" class="bulk-bar-btn" id="bulk-priority-btn" aria-haspopup="menu" aria-expanded="false">
|
|
298
|
+
Priority <span class="bulk-bar-caret" aria-hidden="true">▾</span>
|
|
299
|
+
</button>
|
|
300
|
+
<div class="bulk-bar-menu" id="bulk-priority-menu" role="menu" hidden>
|
|
301
|
+
<button type="button" data-priority="urgent" role="menuitem">🚨 Urgent</button>
|
|
302
|
+
<button type="button" data-priority="high" role="menuitem">⬆ High</button>
|
|
303
|
+
<button type="button" data-priority="normal" role="menuitem">➡ Normal</button>
|
|
304
|
+
<button type="button" data-priority="low" role="menuitem">⬇ Low</button>
|
|
305
|
+
</div>
|
|
306
|
+
</div>
|
|
307
|
+
<button type="button" class="bulk-bar-btn" id="bulk-archive-btn" title="Archive all selected">
|
|
308
|
+
Archive
|
|
309
|
+
</button>
|
|
310
|
+
<button type="button" class="bulk-bar-btn danger" id="bulk-delete-btn" title="Delete all selected">
|
|
311
|
+
Delete
|
|
312
|
+
</button>
|
|
313
|
+
</div>
|
|
314
|
+
<span class="bulk-bar-spacer"></span>
|
|
315
|
+
<button type="button" class="bulk-bar-btn ghost" id="bulk-clear-btn" title="Clear selection (Esc)">
|
|
316
|
+
Clear
|
|
317
|
+
</button>
|
|
318
|
+
</div>
|
|
319
|
+
</section>
|
|
320
|
+
|
|
321
|
+
<!-- ─── TAB: Changelog ──────────────────────────────────────────── -->
|
|
322
|
+
<section id="tab-changelog" class="tab-pane" role="tabpanel" data-tab="changelog" hidden>
|
|
323
|
+
<div id="changelog-root" class="view-root"></div>
|
|
324
|
+
</section>
|
|
325
|
+
|
|
326
|
+
<!-- ─── TAB: Contributors ───────────────────────────────────────── -->
|
|
327
|
+
<section id="tab-contributors" class="tab-pane" role="tabpanel" data-tab="contributors" hidden>
|
|
328
|
+
<div id="contributors-root" class="view-root"></div>
|
|
329
|
+
</section>
|
|
330
|
+
|
|
331
|
+
<!-- ─── TAB: Docs ───────────────────────────────────────────────── -->
|
|
332
|
+
<section id="tab-docs" class="tab-pane" role="tabpanel" data-tab="docs" hidden>
|
|
333
|
+
<div class="docs-tab" id="docs-root"></div>
|
|
334
|
+
</section>
|
|
335
|
+
|
|
336
|
+
<!-- ─── TAB: Agents ─────────────────────────────────────────────── -->
|
|
337
|
+
<section id="tab-goals" class="tab-pane" role="tabpanel" data-tab="goals" hidden>
|
|
338
|
+
<div id="goals-root"></div>
|
|
339
|
+
</section>
|
|
340
|
+
|
|
341
|
+
<section id="tab-agents" class="tab-pane" role="tabpanel" data-tab="agents" hidden>
|
|
342
|
+
<div id="claude-pane-root" class="claude-pane view-root"></div>
|
|
343
|
+
</section>
|
|
344
|
+
|
|
345
|
+
<!-- ─── TAB: Insights ───────────────────────────────────────────── -->
|
|
346
|
+
<section id="tab-insights" class="tab-pane" role="tabpanel" data-tab="insights" hidden>
|
|
347
|
+
<div id="insights-root" class="view-root"></div>
|
|
348
|
+
</section>
|
|
349
|
+
|
|
350
|
+
<!-- ─── Add Project + Settings modals are top-level (below) ─────────
|
|
351
|
+
They used to live inside <main class="dashboard">. When a task
|
|
352
|
+
view opens, the dashboard gets display:none and the modals
|
|
353
|
+
collapsed to 0×0. They're now direct children of <body> so
|
|
354
|
+
they stay reachable regardless of which view is on top. -->
|
|
355
|
+
</main>
|
|
356
|
+
|
|
357
|
+
<!-- ─── Add Project modal — top-level so it's reachable while the ────
|
|
358
|
+
task view is open (when .dashboard collapses to display:none).
|
|
359
|
+
Originally nested inside <main class="dashboard">. -->
|
|
360
|
+
<div id="project-backdrop" class="modal-backdrop" hidden>
|
|
361
|
+
<div class="modal" role="dialog" aria-modal="true" aria-labelledby="project-title">
|
|
362
|
+
<header class="modal-header">
|
|
363
|
+
<h2 id="project-title">Add project</h2>
|
|
364
|
+
<button class="btn-icon" type="button" data-close-project aria-label="Close">×</button>
|
|
365
|
+
</header>
|
|
366
|
+
<form id="project-form" class="modal-body">
|
|
367
|
+
<label class="field">
|
|
368
|
+
<span>Name</span>
|
|
369
|
+
<input name="name" type="text" required maxlength="80" autocomplete="off" />
|
|
370
|
+
</label>
|
|
371
|
+
<label class="field">
|
|
372
|
+
<span>Path</span>
|
|
373
|
+
<div class="field-row-with-button">
|
|
374
|
+
<input name="root" type="text" required autocomplete="off"
|
|
375
|
+
placeholder="/absolute/path/to/project" />
|
|
376
|
+
<button type="button" id="project-browse-btn" class="btn btn-sm"
|
|
377
|
+
aria-label="Browse for a project folder">📁 Browse…</button>
|
|
378
|
+
</div>
|
|
379
|
+
</label>
|
|
380
|
+
<footer class="modal-footer">
|
|
381
|
+
<button type="button" class="btn" data-close-project>Cancel</button>
|
|
382
|
+
<button type="submit" class="btn btn-primary">Add project</button>
|
|
383
|
+
</footer>
|
|
384
|
+
</form>
|
|
385
|
+
</div>
|
|
386
|
+
</div>
|
|
387
|
+
|
|
388
|
+
<!-- ─── Settings dialog — top-level for the same reason as the Add ──
|
|
389
|
+
Project modal above. Owned by web/settings.js. -->
|
|
390
|
+
<div id="settings-backdrop" class="modal-backdrop" hidden>
|
|
391
|
+
<div class="modal settings-dialog" role="dialog" aria-modal="true" aria-labelledby="settings-title">
|
|
392
|
+
<header class="modal-header">
|
|
393
|
+
<h2 id="settings-title">Settings</h2>
|
|
394
|
+
<button class="btn-icon" type="button" data-close-settings aria-label="Close">×</button>
|
|
395
|
+
</header>
|
|
396
|
+
<div class="settings-layout">
|
|
397
|
+
<nav id="settings-nav" class="settings-nav" aria-label="Settings sections"></nav>
|
|
398
|
+
<div class="settings-pane">
|
|
399
|
+
<div class="modal-body" id="settings-body">
|
|
400
|
+
<!-- Populated by settings.js on open. -->
|
|
401
|
+
</div>
|
|
402
|
+
<footer class="modal-footer" id="settings-footer">
|
|
403
|
+
<button type="button" class="btn" data-close-settings>Cancel</button>
|
|
404
|
+
<button type="button" id="settings-save" class="btn btn-primary">Save</button>
|
|
405
|
+
</footer>
|
|
406
|
+
</div>
|
|
407
|
+
</div>
|
|
408
|
+
</div>
|
|
409
|
+
</div>
|
|
410
|
+
|
|
411
|
+
<!-- ─── Template help modal (single instance, reused) ──────────────── -->
|
|
412
|
+
<div id="template-backdrop" class="modal-backdrop" hidden>
|
|
413
|
+
<div class="modal template-dialog" role="dialog" aria-modal="true" aria-labelledby="template-title">
|
|
414
|
+
<header class="modal-header">
|
|
415
|
+
<h2 id="template-title">Task Template</h2>
|
|
416
|
+
<button class="btn-icon" type="button" data-close-template aria-label="Close">×</button>
|
|
417
|
+
</header>
|
|
418
|
+
<div class="modal-body" id="template-body">
|
|
419
|
+
<!-- Populated by task-view.js on open. -->
|
|
420
|
+
</div>
|
|
421
|
+
<footer class="modal-footer">
|
|
422
|
+
<button type="button" class="btn" id="template-copy-btn">Copy to clipboard</button>
|
|
423
|
+
<button type="button" class="btn btn-primary" data-close-template>Done</button>
|
|
424
|
+
</footer>
|
|
425
|
+
</div>
|
|
426
|
+
</div>
|
|
427
|
+
|
|
428
|
+
<!-- Task detail view (hidden by default; lives outside the .dashboard
|
|
429
|
+
panes so it overlays everything when a card is clicked) -->
|
|
430
|
+
<div id="task-view" hidden></div>
|
|
431
|
+
|
|
432
|
+
<!-- Image lightbox overlay (filled by images.js when an image is opened). -->
|
|
433
|
+
<div id="image-lightbox" class="image-lightbox" role="dialog" aria-modal="true" aria-label="Image preview" hidden tabindex="-1">
|
|
434
|
+
<img class="image-lightbox-img" alt="" />
|
|
435
|
+
<button type="button" class="image-lightbox-close" aria-label="Close">×</button>
|
|
436
|
+
</div>
|
|
437
|
+
|
|
438
|
+
<footer class="footer">
|
|
439
|
+
<span>OpenKan v0.3.0 · local-first workspace</span>
|
|
440
|
+
</footer>
|
|
441
|
+
|
|
442
|
+
<!-- api.js MUST load first; it exposes window.OpenKanAPI used by the others. -->
|
|
443
|
+
<script src="api.js" defer></script>
|
|
444
|
+
<!-- cross-tab.js exposes OpenKanCrossTab for sibling-tab sync (M13). -->
|
|
445
|
+
<script src="cross-tab.js" defer></script>
|
|
446
|
+
<script src="images.js" defer></script>
|
|
447
|
+
<script src="mdx-viewer.js" defer></script>
|
|
448
|
+
<script src="task-view.js" defer></script>
|
|
449
|
+
<script src="settings.js" defer></script>
|
|
450
|
+
<script src="changelog-view.js" defer></script>
|
|
451
|
+
<script src="contributors-view.js" defer></script>
|
|
452
|
+
<script src="docs-view.js" defer></script>
|
|
453
|
+
<!-- claude-pane.js exposes window.OpenKanClaude. It must load BEFORE
|
|
454
|
+
app.js (which calls OpenKanClaude.mount(...) when the Claude tab
|
|
455
|
+
is activated) but AFTER api.js (so window.OpenKanAPI.api exists). -->
|
|
456
|
+
<script src="claude-pane.js" defer></script>
|
|
457
|
+
<!-- GSAP powers the concise, status-specific chat work indicators. -->
|
|
458
|
+
<script src="vendor/gsap.min.js" defer></script>
|
|
459
|
+
<script src="chat-status-motion.js" defer></script>
|
|
460
|
+
<!-- chat-sidebar.js exposes window.OpenKanChatSidebar. It depends on
|
|
461
|
+
claude-pane.js (for the activity footer) and api.js (for fetch +
|
|
462
|
+
storage). Loaded before app.js so the toggle button can wire up.
|
|
463
|
+
Loaded before keyboard.js so its capture-phase Cmd/Ctrl+K handler
|
|
464
|
+
registers first and can intercept the palette-open shortcut while
|
|
465
|
+
the sidebar is open. -->
|
|
466
|
+
<script src="chat-sidebar.js" defer></script>
|
|
467
|
+
<!-- M13: keyboard module loads before the palette so the palette can
|
|
468
|
+
subscribe to "palette.open" / "palette.close" / "palette.isOpen". -->
|
|
469
|
+
<script src="keyboard.js" defer></script>
|
|
470
|
+
<script src="command-palette.js" defer></script>
|
|
471
|
+
<!-- path-picker.js exposes window.OpenKanPathPicker. It registers a
|
|
472
|
+
command-palette action and a Cmd/Ctrl+Shift+O shortcut on boot, so it
|
|
473
|
+
must load after command-palette.js but before app.js (which wires the
|
|
474
|
+
Browse button in the Add Project modal). -->
|
|
475
|
+
<script src="path-picker.js" defer></script>
|
|
476
|
+
<!-- charts.js / insights.js expose window.OpenKanCharts and
|
|
477
|
+
window.OpenKanInsights. They load AFTER api.js (window.OpenKanAPI)
|
|
478
|
+
and BEFORE app.js (which calls them from the tab router). -->
|
|
479
|
+
<script src="charts.js" defer></script>
|
|
480
|
+
<script src="insights.js" defer></script>
|
|
481
|
+
<script src="goals-view.js" defer></script>
|
|
482
|
+
<script src="home-view.js" defer></script>
|
|
483
|
+
<script src="app.js" defer></script>
|
|
484
|
+
</body>
|
|
485
|
+
</html>
|