taskproof 0.4.0__tar.gz → 0.4.1__tar.gz

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.
Files changed (85) hide show
  1. {taskproof-0.4.0 → taskproof-0.4.1}/PKG-INFO +1 -1
  2. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/__init__.py +1 -1
  3. taskproof-0.4.0/src/taskproof/web/assets/MatrixView-ClSEIjZm.js → taskproof-0.4.1/src/taskproof/web/assets/MatrixView-CJ8fWUmX.js +61 -25
  4. taskproof-0.4.1/src/taskproof/web/assets/MatrixView-CJ8fWUmX.js.gz +0 -0
  5. taskproof-0.4.0/src/taskproof/web/assets/MatrixView-BM8nu9s2.css → taskproof-0.4.1/src/taskproof/web/assets/MatrixView-Dgb-l684.css +39 -39
  6. taskproof-0.4.1/src/taskproof/web/assets/MatrixView-Dgb-l684.css.gz +0 -0
  7. taskproof-0.4.0/src/taskproof/web/assets/ProjectsView-BXWsK6eF.js → taskproof-0.4.1/src/taskproof/web/assets/ProjectsView-Co9z_MiY.js +2 -2
  8. taskproof-0.4.1/src/taskproof/web/assets/ProjectsView-Co9z_MiY.js.gz +0 -0
  9. taskproof-0.4.0/src/taskproof/web/assets/SettingsView-Co6AsKsi.js → taskproof-0.4.1/src/taskproof/web/assets/SettingsView-BfOnYGw6.js +1 -1
  10. taskproof-0.4.1/src/taskproof/web/assets/SettingsView-BfOnYGw6.js.gz +0 -0
  11. taskproof-0.4.0/src/taskproof/web/assets/TaskDrawer-COqi93G5.js → taskproof-0.4.1/src/taskproof/web/assets/TaskDrawer-CUtASIW0.js +1 -1
  12. taskproof-0.4.1/src/taskproof/web/assets/TaskDrawer-CUtASIW0.js.gz +0 -0
  13. taskproof-0.4.0/src/taskproof/web/assets/TasksView-CgOmskO0.js → taskproof-0.4.1/src/taskproof/web/assets/TasksView-B4jcl2uP.js +2 -2
  14. taskproof-0.4.1/src/taskproof/web/assets/TasksView-B4jcl2uP.js.gz +0 -0
  15. taskproof-0.4.0/src/taskproof/web/assets/index-NKj7kbYl.css → taskproof-0.4.1/src/taskproof/web/assets/index-CKcNecNO.css +42 -42
  16. taskproof-0.4.0/src/taskproof/web/assets/index-NKj7kbYl.css.gz → taskproof-0.4.1/src/taskproof/web/assets/index-CKcNecNO.css.gz +0 -0
  17. taskproof-0.4.0/src/taskproof/web/assets/index-Cd1EoUu-.js → taskproof-0.4.1/src/taskproof/web/assets/index-DV5k90pQ.js +75 -33
  18. taskproof-0.4.1/src/taskproof/web/assets/index-DV5k90pQ.js.gz +0 -0
  19. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/web/index.html +2 -2
  20. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof.egg-info/PKG-INFO +1 -1
  21. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof.egg-info/SOURCES.txt +17 -16
  22. taskproof-0.4.1/tests/test_check_card.py +232 -0
  23. {taskproof-0.4.0 → taskproof-0.4.1}/tests/test_ledger.py +26 -9
  24. taskproof-0.4.0/src/taskproof/web/assets/MatrixView-BM8nu9s2.css.gz +0 -0
  25. taskproof-0.4.0/src/taskproof/web/assets/MatrixView-ClSEIjZm.js.gz +0 -0
  26. taskproof-0.4.0/src/taskproof/web/assets/ProjectsView-BXWsK6eF.js.gz +0 -0
  27. taskproof-0.4.0/src/taskproof/web/assets/SettingsView-Co6AsKsi.js.gz +0 -0
  28. taskproof-0.4.0/src/taskproof/web/assets/TaskDrawer-COqi93G5.js.gz +0 -0
  29. taskproof-0.4.0/src/taskproof/web/assets/TasksView-CgOmskO0.js.gz +0 -0
  30. taskproof-0.4.0/src/taskproof/web/assets/index-Cd1EoUu-.js.gz +0 -0
  31. {taskproof-0.4.0 → taskproof-0.4.1}/LICENSE +0 -0
  32. {taskproof-0.4.0 → taskproof-0.4.1}/README.md +0 -0
  33. {taskproof-0.4.0 → taskproof-0.4.1}/pyproject.toml +0 -0
  34. {taskproof-0.4.0 → taskproof-0.4.1}/setup.cfg +0 -0
  35. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/__main__.py +0 -0
  36. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/adapters/__init__.py +0 -0
  37. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/adapters/base.py +0 -0
  38. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/adapters/claude.py +0 -0
  39. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/adapters/codex.py +0 -0
  40. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/adapters/custom.py +0 -0
  41. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/adapters/gemini.py +0 -0
  42. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/adapters/opencode.py +0 -0
  43. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/api/__init__.py +0 -0
  44. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/api/server.py +0 -0
  45. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/cli.py +0 -0
  46. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/concurrency.py +0 -0
  47. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/dispatch.py +0 -0
  48. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/errors.py +0 -0
  49. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/ledger.py +0 -0
  50. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/models.py +0 -0
  51. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/registry.py +0 -0
  52. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/schemas/result.json +0 -0
  53. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/sql/schema.sql +0 -0
  54. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/storage.py +0 -0
  55. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/verify.py +0 -0
  56. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/web/assets/ProjectsView-CqNFL-fi.css +0 -0
  57. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/web/assets/SettingsView-aqTS3ubB.css +0 -0
  58. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/web/assets/TaskDrawer-N299VKzd.css +0 -0
  59. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/web/assets/TaskDrawer-N299VKzd.css.gz +0 -0
  60. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/web/assets/TasksView-Bn08731V.css +0 -0
  61. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof/web/assets/icon-Dw-ohsdc.png +0 -0
  62. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof.egg-info/dependency_links.txt +0 -0
  63. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof.egg-info/entry_points.txt +0 -0
  64. {taskproof-0.4.0 → taskproof-0.4.1}/src/taskproof.egg-info/top_level.txt +0 -0
  65. {taskproof-0.4.0 → taskproof-0.4.1}/tests/test_accept_rerun.py +0 -0
  66. {taskproof-0.4.0 → taskproof-0.4.1}/tests/test_adapters.py +0 -0
  67. {taskproof-0.4.0 → taskproof-0.4.1}/tests/test_adapters_parse.py +0 -0
  68. {taskproof-0.4.0 → taskproof-0.4.1}/tests/test_api.py +0 -0
  69. {taskproof-0.4.0 → taskproof-0.4.1}/tests/test_api_cors.py +0 -0
  70. {taskproof-0.4.0 → taskproof-0.4.1}/tests/test_api_log.py +0 -0
  71. {taskproof-0.4.0 → taskproof-0.4.1}/tests/test_board_cli.py +0 -0
  72. {taskproof-0.4.0 → taskproof-0.4.1}/tests/test_board_serve.py +0 -0
  73. {taskproof-0.4.0 → taskproof-0.4.1}/tests/test_cli.py +0 -0
  74. {taskproof-0.4.0 → taskproof-0.4.1}/tests/test_concurrency.py +0 -0
  75. {taskproof-0.4.0 → taskproof-0.4.1}/tests/test_concurrency_race.py +0 -0
  76. {taskproof-0.4.0 → taskproof-0.4.1}/tests/test_control_surface.py +0 -0
  77. {taskproof-0.4.0 → taskproof-0.4.1}/tests/test_dispatch.py +0 -0
  78. {taskproof-0.4.0 → taskproof-0.4.1}/tests/test_project_view.py +0 -0
  79. {taskproof-0.4.0 → taskproof-0.4.1}/tests/test_registry.py +0 -0
  80. {taskproof-0.4.0 → taskproof-0.4.1}/tests/test_registry_write.py +0 -0
  81. {taskproof-0.4.0 → taskproof-0.4.1}/tests/test_result_schema.py +0 -0
  82. {taskproof-0.4.0 → taskproof-0.4.1}/tests/test_scan_assets.py +0 -0
  83. {taskproof-0.4.0 → taskproof-0.4.1}/tests/test_scope.py +0 -0
  84. {taskproof-0.4.0 → taskproof-0.4.1}/tests/test_storage.py +0 -0
  85. {taskproof-0.4.0 → taskproof-0.4.1}/tests/test_verify.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: taskproof
3
- Version: 0.4.0
3
+ Version: 0.4.1
4
4
  Summary: A conveyor belt for AI coding agents: dispatch, independently verify, record.
5
5
  Author-email: HaoHaoP <HaoHaoP@HaoHaoP.com>
6
6
  License: Apache-2.0
@@ -8,7 +8,7 @@ import sys
8
8
 
9
9
  # The single source of the version: `pyproject.toml` reads it from here
10
10
  # (`[tool.setuptools.dynamic]`), so cutting a release bumps exactly one string.
11
- __version__ = "0.4.0"
11
+ __version__ = "0.4.1"
12
12
 
13
13
  # Fail early and in plain language. Without this, running from a source checkout
14
14
  # under an older interpreter surfaces as `ModuleNotFoundError: No module named
@@ -1,5 +1,5 @@
1
- import { d as defineComponent, u as useI18n, o as openBlock, c as createElementBlock, w as withKeys, a as withModifiers, b as createBaseVNode, e as createVNode, t as toDisplayString, f as unref, g as createCommentVNode, n as normalizeClass, h as computed, _ as _export_sfc, i as useBoardStore, j as useSettingsStore, k as watch, l as withCtx, m as normalizeStyle, F as Fragment, r as renderList, p as resolveComponent, q as boardQuery, s as useRoute, v as useRouter, H as HIDE_KEY, x as createBlock, R as RANGES, y as createTextVNode, z as columnLabelKey, I as ICONS, A as mergeProps, B as toHandlers, C as owningProject, D as parseBoardFilter, E as visibleProjects, G as visibleColumns, J as gridTracks, K as COLUMNS, L as capChipLabel, M as capMenuFor, N as hiddenTally, O as canGrowBudget, P as groupColumns, Q as filterBoard, S as DEFAULT_CAPS, T as columnWindow } from "./index-Cd1EoUu-.js";
2
- import { S as StatusMark, d as duration, T as TaskDrawer } from "./TaskDrawer-COqi93G5.js";
1
+ import { d as defineComponent, u as useI18n, o as openBlock, c as createElementBlock, w as withKeys, a as withModifiers, b as createBaseVNode, e as createVNode, t as toDisplayString, f as unref, g as createCommentVNode, n as normalizeClass, h as computed, _ as _export_sfc, i as useBoardStore, j as useSettingsStore, k as watch, l as withCtx, m as normalizeStyle, F as Fragment, r as renderList, p as resolveComponent, q as boardQuery, s as useRoute, v as useRouter, H as HIDE_KEY, x as createBlock, R as RANGES, y as createTextVNode, z as columnLabelKey, I as ICONS, A as mergeProps, B as toHandlers, C as owningProject, D as parseBoardFilter, E as visibleProjects, G as visibleColumns, J as gridTracks, K as COLUMNS, L as capChipLabel, M as capMenuFor, N as hiddenTally, O as canGrowBudget, P as projectTally, Q as projectsWithActivity, S as filterBoard, T as groupColumns, U as DEFAULT_CAPS, V as columnWindow } from "./index-DV5k90pQ.js";
2
+ import { S as StatusMark, d as duration, T as TaskDrawer } from "./TaskDrawer-CUtASIW0.js";
3
3
  function acceptancePassed(task) {
4
4
  return task.status === "blocked" && task.verify_exit === 0;
5
5
  }
@@ -135,14 +135,31 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
135
135
  const router = useRouter();
136
136
  const { t } = useI18n();
137
137
  const filter = computed(() => parseBoardFilter(route.query));
138
- const projects = computed(() => visibleProjects(store.projectGroups, filter.value));
138
+ const scopedProjects = computed(() => {
139
+ if (filter.value.range === "all") return store.projectGroups;
140
+ const active = new Set(
141
+ projectsWithActivity(store.tasks, store.laneProject, filter.value.range, Date.now())
142
+ );
143
+ return store.projectGroups.filter((group) => active.has(group.id));
144
+ });
145
+ const scopedProjectIds = computed(() => new Set(scopedProjects.value.map((group) => group.id)));
146
+ const projects = computed(() => {
147
+ if (filter.value.range === "all") return visibleProjects(store.projectGroups, filter.value);
148
+ return visibleProjects(scopedProjects.value, filter.value);
149
+ });
139
150
  const lanes = computed(() => visibleColumns(filter.value));
140
151
  const gridStyle = computed(() => ({ gridTemplateColumns: gridTracks(lanes.value.length) }));
141
- const allProjectIds = computed(() => store.projectGroups.map((group) => group.id));
142
- const selectedProjects = computed(() => filter.value.projects ?? allProjectIds.value);
143
- const columns = computed(
144
- () => groupColumns(filterBoard(store.tasks, filter.value, Date.now(), store.laneProject))
152
+ const allProjectIds = computed(
153
+ () => filter.value.range === "all" ? store.projectGroups.map((group) => group.id) : scopedProjects.value.map((group) => group.id)
154
+ );
155
+ const selectedProjects = computed(() => {
156
+ const scoped = new Set(allProjectIds.value);
157
+ return (filter.value.projects ?? allProjectIds.value).filter((id) => scoped.has(id));
158
+ });
159
+ const flat = computed(
160
+ () => filterBoard(store.tasks, filter.value, Date.now(), store.laneProject)
145
161
  );
162
+ const columns = computed(() => groupColumns(flat.value));
146
163
  function capFor(key) {
147
164
  return settings.settings.columnCaps[key] ?? DEFAULT_CAPS[key] ?? 0;
148
165
  }
@@ -182,16 +199,30 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
182
199
  (task) => owningProject(task, store.laneProject) === projectId
183
200
  );
184
201
  }
202
+ const rowTallies = computed(() => {
203
+ if (filter.value.range === "all") return null;
204
+ const out = {};
205
+ for (const group of projects.value) {
206
+ out[group.id] = projectTally(flat.value, group.id, store.laneProject);
207
+ }
208
+ return out;
209
+ });
185
210
  function laneCount(group) {
186
- return group.taskgroups.length;
211
+ return rowTallies.value?.[group.id]?.lanes ?? group.taskgroups.length;
187
212
  }
188
213
  function groupTasks(group) {
214
+ const tally = rowTallies.value?.[group.id];
215
+ if (tally) return tally.tasks;
189
216
  return Object.values(group.summary).reduce((sum, n) => sum + (n || 0), 0);
190
217
  }
191
218
  function groupFlying(group) {
219
+ const tally = rowTallies.value?.[group.id];
220
+ if (tally) return tally.flying;
192
221
  return (group.summary.running ?? 0) + (group.summary.verifying ?? 0);
193
222
  }
194
223
  function groupFailed(group) {
224
+ const tally = rowTallies.value?.[group.id];
225
+ if (tally) return tally.failed;
195
226
  return (group.summary.failed ?? 0) + (group.summary.timeout ?? 0);
196
227
  }
197
228
  function aliasHint(group) {
@@ -231,10 +262,11 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
231
262
  const isAll = value.length === all.length && all.every((id) => value.includes(id));
232
263
  applyFilter({ projects: isAll ? null : [...value] });
233
264
  }
234
- const allProjectsSelected = computed(() => filter.value.projects === null);
235
- const noProjectsSelected = computed(
236
- () => filter.value.projects !== null && filter.value.projects.length === 0
237
- );
265
+ const allProjectsSelected = computed(() => {
266
+ const selected = new Set(selectedProjects.value);
267
+ return selected.size === allProjectIds.value.length && allProjectIds.value.every((id) => selected.has(id));
268
+ });
269
+ const noProjectsSelected = computed(() => selectedProjects.value.length === 0);
238
270
  function selectAllProjects() {
239
271
  applyFilter({ projects: null });
240
272
  }
@@ -279,18 +311,22 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
279
311
  ]),
280
312
  default: withCtx(() => [
281
313
  (openBlock(true), createElementBlock(Fragment, null, renderList(unref(store).projectGroups, (group) => {
282
- return openBlock(), createBlock(_component_el_option, {
283
- key: group.id,
284
- value: group.id,
285
- label: group.id
286
- }, {
287
- default: withCtx(() => [
288
- createBaseVNode("span", {
289
- title: aliasHint(group) || void 0
290
- }, toDisplayString(group.id), 9, _hoisted_7)
291
- ]),
292
- _: 2
293
- }, 1032, ["value", "label"]);
314
+ return openBlock(), createElementBlock(Fragment, {
315
+ key: group.id
316
+ }, [
317
+ scopedProjectIds.value.has(group.id) ? (openBlock(), createBlock(_component_el_option, {
318
+ key: 0,
319
+ value: group.id,
320
+ label: group.id
321
+ }, {
322
+ default: withCtx(() => [
323
+ createBaseVNode("span", {
324
+ title: aliasHint(group) || void 0
325
+ }, toDisplayString(group.id), 9, _hoisted_7)
326
+ ]),
327
+ _: 2
328
+ }, 1032, ["value", "label"])) : createCommentVNode("", true)
329
+ ], 64);
294
330
  }), 128))
295
331
  ]),
296
332
  _: 1
@@ -469,7 +505,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
469
505
  };
470
506
  }
471
507
  });
472
- const MatrixView = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-6af3c04d"]]);
508
+ const MatrixView = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-22444ff1"]]);
473
509
  export {
474
510
  MatrixView as default
475
511
  };
@@ -102,7 +102,7 @@
102
102
  }
103
103
  }
104
104
 
105
- .matrix-view[data-v-6af3c04d] {
105
+ .matrix-view[data-v-22444ff1] {
106
106
  display: flex;
107
107
  flex-direction: column;
108
108
  min-height: 0;
@@ -111,7 +111,7 @@
111
111
  /* The matrix row: the project multi-select and the time range. Both scope the
112
112
  whole board, six status columns (泳道) at once; there is no third control in
113
113
  the normal state. */
114
- .boardbar[data-v-6af3c04d] {
114
+ .boardbar[data-v-22444ff1] {
115
115
  flex: none;
116
116
  display: flex;
117
117
  align-items: center;
@@ -121,21 +121,21 @@
121
121
  font: 12px/1 var(--sans);
122
122
  color: var(--ink-3);
123
123
  }
124
- .boardbar .fld[data-v-6af3c04d] {
124
+ .boardbar .fld[data-v-22444ff1] {
125
125
  display: inline-flex;
126
126
  align-items: center;
127
127
  gap: 7px;
128
128
  }
129
- .boardbar .sel[data-v-6af3c04d] {
129
+ .boardbar .sel[data-v-22444ff1] {
130
130
  width: 128px;
131
131
  }
132
- .boardbar .sel-projects[data-v-6af3c04d] {
132
+ .boardbar .sel-projects[data-v-22444ff1] {
133
133
  width: 240px;
134
134
  }
135
135
  /* The right-hand cluster: the hidden-column undo, then the capped warning.
136
136
  Both are notes, not filters, so they ride at the far end of the row rather
137
137
  than sitting inline with the two scoping controls. */
138
- .boardbar .rest[data-v-6af3c04d] {
138
+ .boardbar .rest[data-v-22444ff1] {
139
139
  display: inline-flex;
140
140
  align-items: center;
141
141
  gap: 14px;
@@ -143,7 +143,7 @@
143
143
  }
144
144
  /* The undo for hidden columns: not a filter, an escape hatch. It reads as a
145
145
  button because clicking it brings every hidden column back. */
146
- .boardbar .hidden-lanes[data-v-6af3c04d] {
146
+ .boardbar .hidden-lanes[data-v-22444ff1] {
147
147
  display: inline-flex;
148
148
  align-items: center;
149
149
  padding: 4px 10px;
@@ -154,21 +154,21 @@
154
154
  font: 11.5px/1 var(--sans);
155
155
  cursor: pointer;
156
156
  }
157
- .boardbar .hidden-lanes[data-v-6af3c04d]:hover {
157
+ .boardbar .hidden-lanes[data-v-22444ff1]:hover {
158
158
  background: var(--raise);
159
159
  }
160
160
  /* The capped warning is a note, not an alarm: the amber of "incomplete", not
161
161
  the red of "failed". While the budget can still rise it carries its own
162
162
  "继续取回" so the reader can pull the older window; once the cap is reached
163
163
  that button would be a dead click, so the note states the limit instead. */
164
- .boardbar .cap[data-v-6af3c04d] {
164
+ .boardbar .cap[data-v-22444ff1] {
165
165
  display: inline-flex;
166
166
  align-items: center;
167
167
  gap: 10px;
168
168
  font: 11.5px/1.2 var(--sans);
169
169
  color: var(--c-timeout);
170
170
  }
171
- .boardbar .cap .grow[data-v-6af3c04d] {
171
+ .boardbar .cap .grow[data-v-22444ff1] {
172
172
  flex: none;
173
173
  padding: 4px 10px;
174
174
  border: 1px solid var(--rule);
@@ -178,10 +178,10 @@
178
178
  font: 11.5px/1 var(--sans);
179
179
  cursor: pointer;
180
180
  }
181
- .boardbar .cap .grow[data-v-6af3c04d]:hover {
181
+ .boardbar .cap .grow[data-v-22444ff1]:hover {
182
182
  background: var(--raise);
183
183
  }
184
- .matrix[data-v-6af3c04d] {
184
+ .matrix[data-v-22444ff1] {
185
185
  flex: 1;
186
186
  overflow: auto;
187
187
  min-width: 0;
@@ -196,13 +196,13 @@
196
196
  show/hide switches. This must never be re-pinned to a literal: a track count
197
197
  that disagrees with the header/cell loop pushes each project's lane into the
198
198
  next column and the rows interleave, silently. 列数 = 可见列数. */
199
- .grid[data-v-6af3c04d] {
199
+ .grid[data-v-22444ff1] {
200
200
  display: grid;
201
201
  align-content: start;
202
202
  min-height: 100%;
203
203
  padding: 0 10px;
204
204
  }
205
- .hd[data-v-6af3c04d] {
205
+ .hd[data-v-22444ff1] {
206
206
  position: sticky;
207
207
  top: 0;
208
208
  z-index: 3;
@@ -225,7 +225,7 @@
225
225
  -- every pixel of the seam answers `.hd` (or the `.fold` it carries) rather
226
226
  than a card. `background: inherit` keeps the zebra columns' tint, and the
227
227
  band's bottom rule moves here so the seam reads as part of the header. */
228
- .hd[data-v-6af3c04d]::after {
228
+ .hd[data-v-22444ff1]::after {
229
229
  content: '';
230
230
  position: absolute;
231
231
  left: 0;
@@ -235,12 +235,12 @@
235
235
  background: inherit;
236
236
  border-bottom: 1px solid var(--rule-2);
237
237
  }
238
- .hd .lb[data-v-6af3c04d] {
238
+ .hd .lb[data-v-22444ff1] {
239
239
  display: inline-flex;
240
240
  align-items: center;
241
241
  gap: 7px;
242
242
  }
243
- .hd .rt[data-v-6af3c04d] {
243
+ .hd .rt[data-v-22444ff1] {
244
244
  display: inline-flex;
245
245
  align-items: center;
246
246
  gap: 6px;
@@ -248,19 +248,19 @@
248
248
  /* The band must answer as the header itself: the label and tally are
249
249
  decoration, so they do not intercept a hit -- only the hide switch does. The
250
250
  chip is a real control in `.hdctl`, not part of this decoration layer. */
251
- .hd .lb[data-v-6af3c04d],
252
- .hd .rt[data-v-6af3c04d] {
251
+ .hd .lb[data-v-22444ff1],
252
+ .hd .rt[data-v-22444ff1] {
253
253
  pointer-events: none;
254
254
  }
255
- .hd .rt .lane-hide[data-v-6af3c04d] {
255
+ .hd .rt .lane-hide[data-v-22444ff1] {
256
256
  pointer-events: auto;
257
257
  }
258
- .hd .rt .lane-hide[data-v-6af3c04d] * {
258
+ .hd .rt .lane-hide[data-v-22444ff1] * {
259
259
  pointer-events: none;
260
260
  }
261
261
  /* The per-column hide switch. Same shape in every header, so the row reads as
262
262
  one control repeated, not a menu. It is the header's own column it hides. */
263
- .hd .lane-hide[data-v-6af3c04d] {
263
+ .hd .lane-hide[data-v-22444ff1] {
264
264
  flex: none;
265
265
  display: inline-flex;
266
266
  align-items: center;
@@ -274,7 +274,7 @@
274
274
  color: var(--ink-4);
275
275
  cursor: pointer;
276
276
  }
277
- .hd .lane-hide[data-v-6af3c04d]:hover {
277
+ .hd .lane-hide[data-v-22444ff1]:hover {
278
278
  border-color: var(--rule);
279
279
  background: var(--panel);
280
280
  color: var(--ink-2);
@@ -285,7 +285,7 @@
285
285
  header's 3 and the lane's 2 -- and carry its own opaque background, so
286
286
  neither the first lane cell nor the first status column can show through
287
287
  the intersection. The background is the prototype's corner colour (--bg). */
288
- .hd.corner[data-v-6af3c04d] {
288
+ .hd.corner[data-v-22444ff1] {
289
289
  position: sticky;
290
290
  top: 0;
291
291
  left: 0;
@@ -299,10 +299,10 @@
299
299
  /* Column zebra: every other status column carries a faint tint, on both the
300
300
  header and the cells, so the band runs the full height and neighbouring
301
301
  columns cannot be read into each other. */
302
- .zcol[data-v-6af3c04d] {
302
+ .zcol[data-v-22444ff1] {
303
303
  background-color: var(--zebra);
304
304
  }
305
- .lane[data-v-6af3c04d] {
305
+ .lane[data-v-22444ff1] {
306
306
  position: sticky;
307
307
  left: 0;
308
308
  z-index: 2;
@@ -311,17 +311,17 @@
311
311
  border-right: 1px solid var(--rule-2);
312
312
  border-bottom: 1px solid var(--rule);
313
313
  }
314
- .lane .name[data-v-6af3c04d] {
314
+ .lane .name[data-v-22444ff1] {
315
315
  font: 600 12.5px/1 var(--mono);
316
316
  color: var(--ink);
317
317
  }
318
- .lane .pth[data-v-6af3c04d] {
318
+ .lane .pth[data-v-22444ff1] {
319
319
  margin-top: 5px;
320
320
  font: 10.5px/1.35 var(--mono);
321
321
  color: var(--ink-4);
322
322
  overflow-wrap: anywhere;
323
323
  }
324
- .lane .tally[data-v-6af3c04d] {
324
+ .lane .tally[data-v-22444ff1] {
325
325
  display: flex;
326
326
  flex-wrap: wrap;
327
327
  gap: 8px;
@@ -329,18 +329,18 @@
329
329
  font: 10.5px/1 var(--mono);
330
330
  color: var(--ink-3);
331
331
  }
332
- .lane .tally .bad[data-v-6af3c04d] {
332
+ .lane .tally .bad[data-v-22444ff1] {
333
333
  color: var(--c-failed);
334
334
  font-weight: 600;
335
335
  }
336
336
  /* Row separator: the lane and the cells each draw their own bottom border, and
337
337
  because they share a grid row the two lines meet into one. */
338
- .mcell[data-v-6af3c04d] {
338
+ .mcell[data-v-22444ff1] {
339
339
  min-height: 26px;
340
340
  padding: 10px 6px;
341
341
  border-bottom: 1px solid var(--rule);
342
342
  }
343
- .mcell .dash[data-v-6af3c04d] {
343
+ .mcell .dash[data-v-22444ff1] {
344
344
  padding-top: 2px;
345
345
  font: 11px/1 var(--mono);
346
346
  color: var(--ink-4);
@@ -348,7 +348,7 @@
348
348
  }
349
349
  /* The per-column control band: the chip is the only thing on this full-width
350
350
  line under the label row, so the header keeps one self-describing number. */
351
- .hdctl[data-v-6af3c04d] {
351
+ .hdctl[data-v-22444ff1] {
352
352
  flex: 1 0 100%;
353
353
  display: flex;
354
354
  align-items: center;
@@ -357,14 +357,14 @@
357
357
  /* Do not style Element Plus's internal `.el-tooltip__trigger` to lay out this
358
358
  control: that class also lands on .cap-chip, and its extra class selector
359
359
  outranks .cap-chip's own display rule. Own the full-width layout here. */
360
- .cap-dd[data-v-6af3c04d] {
360
+ .cap-dd[data-v-22444ff1] {
361
361
  display: block;
362
362
  width: 100%;
363
363
  min-width: 0;
364
364
  }
365
365
  /* Every column's chip. Its own click stops, but the Element Plus trigger still
366
366
  sees the same click and opens the menu. */
367
- .cap-chip[data-v-6af3c04d] {
367
+ .cap-chip[data-v-22444ff1] {
368
368
  display: inline-flex;
369
369
  align-items: center;
370
370
  justify-content: space-between;
@@ -380,20 +380,20 @@
380
380
  text-align: left;
381
381
  cursor: pointer;
382
382
  }
383
- .cap-chip[data-v-6af3c04d]:hover,
384
- .cap-chip[data-v-6af3c04d]:focus-visible {
383
+ .cap-chip[data-v-22444ff1]:hover,
384
+ .cap-chip[data-v-22444ff1]:focus-visible {
385
385
  border-color: var(--rule-2);
386
386
  background: var(--raise);
387
387
  color: var(--ink);
388
388
  }
389
- .cap-chip-label[data-v-6af3c04d] {
389
+ .cap-chip-label[data-v-22444ff1] {
390
390
  flex: 1 1 auto;
391
391
  min-width: 0;
392
392
  overflow: hidden;
393
393
  text-overflow: ellipsis;
394
394
  white-space: nowrap;
395
395
  }
396
- .cap-caret[data-v-6af3c04d] {
396
+ .cap-caret[data-v-22444ff1] {
397
397
  flex: none;
398
398
  color: var(--ink-4);
399
399
  display: inline-flex;
@@ -1,5 +1,5 @@
1
- import { d as defineComponent, i as useBoardStore, u as useI18n, c as createElementBlock, b as createBaseVNode, t as toDisplayString, f as unref, e as createVNode, l as withCtx, h as computed, U as ref, p as resolveComponent, n as normalizeClass, o as openBlock, _ as _export_sfc } from "./index-Cd1EoUu-.js";
2
- import { T as TaskDrawer } from "./TaskDrawer-COqi93G5.js";
1
+ import { d as defineComponent, i as useBoardStore, u as useI18n, c as createElementBlock, b as createBaseVNode, t as toDisplayString, f as unref, e as createVNode, l as withCtx, h as computed, W as ref, p as resolveComponent, n as normalizeClass, o as openBlock, _ as _export_sfc } from "./index-DV5k90pQ.js";
2
+ import { T as TaskDrawer } from "./TaskDrawer-CUtASIW0.js";
3
3
  function probeOf(value) {
4
4
  return value === "passed" || value === "failed" || value === "none" ? value : null;
5
5
  }
@@ -1,4 +1,4 @@
1
- import { d as defineComponent, i as useBoardStore, j as useSettingsStore, u as useI18n, k as watch, a8 as onMounted, c as createElementBlock, b as createBaseVNode, t as toDisplayString, f as unref, g as createCommentVNode, e as createVNode, l as withCtx, a9 as openAbout, F as Fragment, r as renderList, aa as STATUS_IDS, ab as VERIFY_KINDS, ac as hasDesktopHost, h as computed, U as ref, p as resolveComponent, y as createTextVNode, n as normalizeClass, o as openBlock, _ as _export_sfc } from "./index-Cd1EoUu-.js";
1
+ import { d as defineComponent, i as useBoardStore, j as useSettingsStore, u as useI18n, k as watch, aa as onMounted, c as createElementBlock, b as createBaseVNode, t as toDisplayString, f as unref, g as createCommentVNode, e as createVNode, l as withCtx, ab as openAbout, F as Fragment, r as renderList, ac as STATUS_IDS, ad as VERIFY_KINDS, ae as hasDesktopHost, h as computed, W as ref, p as resolveComponent, y as createTextVNode, n as normalizeClass, o as openBlock, _ as _export_sfc } from "./index-DV5k90pQ.js";
2
2
  const _hoisted_1 = { class: "settings-view" };
3
3
  const _hoisted_2 = { class: "panes grouped" };
4
4
  const _hoisted_3 = { class: "setwrap" };
@@ -1,4 +1,4 @@
1
- import { d as defineComponent, c as createElementBlock, F as Fragment, y as createTextVNode, t as toDisplayString, h as computed, o as openBlock, V as metaFor, _ as _export_sfc, i as useBoardStore, u as useI18n, k as watch, W as onBeforeUnmount, x as createBlock, l as withCtx, f as unref, U as ref, p as resolveComponent, b as createBaseVNode, e as createVNode, w as withKeys, a as withModifiers, n as normalizeClass, X as withDirectives, Y as vShow, r as renderList, g as createCommentVNode, Z as formatBytes, $ as byteLength, a0 as LOG_MAX_LINES, a1 as highlightSegments, a2 as shouldStickBottom, a3 as nextTick, s as useRoute, v as useRouter, a4 as ABNORMAL, a5 as countMatches, a6 as matchLineIndexes, a7 as stripAnsi } from "./index-Cd1EoUu-.js";
1
+ import { d as defineComponent, c as createElementBlock, F as Fragment, y as createTextVNode, t as toDisplayString, h as computed, o as openBlock, X as metaFor, _ as _export_sfc, i as useBoardStore, u as useI18n, k as watch, Y as onBeforeUnmount, x as createBlock, l as withCtx, f as unref, W as ref, p as resolveComponent, b as createBaseVNode, e as createVNode, w as withKeys, a as withModifiers, n as normalizeClass, Z as withDirectives, $ as vShow, r as renderList, g as createCommentVNode, a0 as formatBytes, a1 as byteLength, a2 as LOG_MAX_LINES, a3 as highlightSegments, a4 as shouldStickBottom, a5 as nextTick, s as useRoute, v as useRouter, a6 as ABNORMAL, a7 as countMatches, a8 as matchLineIndexes, a9 as stripAnsi } from "./index-DV5k90pQ.js";
2
2
  const _hoisted_1$1 = ["data-status", "data-shape"];
3
3
  const _hoisted_2$1 = {
4
4
  key: 0,
@@ -1,5 +1,5 @@
1
- import { d as defineComponent, i as useBoardStore, u as useI18n, c as createElementBlock, b as createBaseVNode, t as toDisplayString, f as unref, g as createCommentVNode, e as createVNode, l as withCtx, h as computed, p as resolveComponent, v as useRouter, s as useRoute, o as openBlock, _ as _export_sfc } from "./index-Cd1EoUu-.js";
2
- import { T as TaskDrawer, d as duration } from "./TaskDrawer-COqi93G5.js";
1
+ import { d as defineComponent, i as useBoardStore, u as useI18n, c as createElementBlock, b as createBaseVNode, t as toDisplayString, f as unref, g as createCommentVNode, e as createVNode, l as withCtx, h as computed, p as resolveComponent, v as useRouter, s as useRoute, o as openBlock, _ as _export_sfc } from "./index-DV5k90pQ.js";
2
+ import { T as TaskDrawer, d as duration } from "./TaskDrawer-CUtASIW0.js";
3
3
  const _hoisted_1 = { class: "tasks-view" };
4
4
  const _hoisted_2 = { class: "panes" };
5
5
  const _hoisted_3 = { class: "sub" };