workbench-dashboard 0.1.3__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 (203) hide show
  1. workbench_dashboard-0.1.3/.dockerignore +22 -0
  2. workbench_dashboard-0.1.3/.git-blame-ignore-revs +5 -0
  3. workbench_dashboard-0.1.3/.github/workflows/ci.yml +133 -0
  4. workbench_dashboard-0.1.3/.github/workflows/release.yml +270 -0
  5. workbench_dashboard-0.1.3/.gitignore +59 -0
  6. workbench_dashboard-0.1.3/.python-version +1 -0
  7. workbench_dashboard-0.1.3/CHANGELOG.md +64 -0
  8. workbench_dashboard-0.1.3/CONTRIBUTING.md +166 -0
  9. workbench_dashboard-0.1.3/LICENSE +21 -0
  10. workbench_dashboard-0.1.3/Makefile +44 -0
  11. workbench_dashboard-0.1.3/PKG-INFO +322 -0
  12. workbench_dashboard-0.1.3/README.md +289 -0
  13. workbench_dashboard-0.1.3/SECURITY.md +74 -0
  14. workbench_dashboard-0.1.3/desktop/package-lock.json +247 -0
  15. workbench_dashboard-0.1.3/desktop/package.json +13 -0
  16. workbench_dashboard-0.1.3/desktop/src-tauri/Cargo.lock +5526 -0
  17. workbench_dashboard-0.1.3/desktop/src-tauri/Cargo.toml +29 -0
  18. workbench_dashboard-0.1.3/desktop/src-tauri/Info.plist +9 -0
  19. workbench_dashboard-0.1.3/desktop/src-tauri/build.rs +3 -0
  20. workbench_dashboard-0.1.3/desktop/src-tauri/icons/128x128.png +0 -0
  21. workbench_dashboard-0.1.3/desktop/src-tauri/icons/128x128@2x.png +0 -0
  22. workbench_dashboard-0.1.3/desktop/src-tauri/icons/32x32.png +0 -0
  23. workbench_dashboard-0.1.3/desktop/src-tauri/icons/icon-source.png +0 -0
  24. workbench_dashboard-0.1.3/desktop/src-tauri/icons/icon.icns +0 -0
  25. workbench_dashboard-0.1.3/desktop/src-tauri/icons/icon.ico +0 -0
  26. workbench_dashboard-0.1.3/desktop/src-tauri/icons/icon.png +0 -0
  27. workbench_dashboard-0.1.3/desktop/src-tauri/icons/tray.png +0 -0
  28. workbench_dashboard-0.1.3/desktop/src-tauri/src/cli_link.rs +49 -0
  29. workbench_dashboard-0.1.3/desktop/src-tauri/src/environment.rs +53 -0
  30. workbench_dashboard-0.1.3/desktop/src-tauri/src/main.rs +253 -0
  31. workbench_dashboard-0.1.3/desktop/src-tauri/src/server.rs +301 -0
  32. workbench_dashboard-0.1.3/desktop/src-tauri/src/updater.rs +223 -0
  33. workbench_dashboard-0.1.3/desktop/src-tauri/tauri.conf.json +45 -0
  34. workbench_dashboard-0.1.3/desktop/src-tauri/tauri.updater.conf.json +5 -0
  35. workbench_dashboard-0.1.3/desktop/ui/index.html +3 -0
  36. workbench_dashboard-0.1.3/docker-compose.yml +32 -0
  37. workbench_dashboard-0.1.3/docs/architecture.md +187 -0
  38. workbench_dashboard-0.1.3/docs/desktop.md +134 -0
  39. workbench_dashboard-0.1.3/docs/reference.md +268 -0
  40. workbench_dashboard-0.1.3/docs/releasing.md +129 -0
  41. workbench_dashboard-0.1.3/docs/setup.md +301 -0
  42. workbench_dashboard-0.1.3/packaging/docker/Dockerfile +36 -0
  43. workbench_dashboard-0.1.3/packaging/docker/github_known_hosts +6 -0
  44. workbench_dashboard-0.1.3/packaging/docker/update.sh +65 -0
  45. workbench_dashboard-0.1.3/packaging/docker/workbench-update.service +11 -0
  46. workbench_dashboard-0.1.3/packaging/docker/workbench-update.timer +12 -0
  47. workbench_dashboard-0.1.3/packaging/hatch_build.py +29 -0
  48. workbench_dashboard-0.1.3/packaging/homebrew/workbench-dashboard.rb +48 -0
  49. workbench_dashboard-0.1.3/packaging/pyinstaller/entry.py +6 -0
  50. workbench_dashboard-0.1.3/packaging/pyinstaller/workbench.spec +37 -0
  51. workbench_dashboard-0.1.3/pyproject.toml +100 -0
  52. workbench_dashboard-0.1.3/schema/learning.schema.json +227 -0
  53. workbench_dashboard-0.1.3/schema/project.schema.json +416 -0
  54. workbench_dashboard-0.1.3/scripts/run_demo.py +59 -0
  55. workbench_dashboard-0.1.3/scripts/screenshots.py +169 -0
  56. workbench_dashboard-0.1.3/scripts/version.py +193 -0
  57. workbench_dashboard-0.1.3/src/workbench/__init__.py +3 -0
  58. workbench_dashboard-0.1.3/src/workbench/__main__.py +3 -0
  59. workbench_dashboard-0.1.3/src/workbench/agents/__init__.py +1 -0
  60. workbench_dashboard-0.1.3/src/workbench/agents/assets/chat/LEARNING_PROMPT.md +67 -0
  61. workbench_dashboard-0.1.3/src/workbench/agents/assets/chat/PROMPT.md +107 -0
  62. workbench_dashboard-0.1.3/src/workbench/agents/assets/claude/workbench-review/SKILL.md +130 -0
  63. workbench_dashboard-0.1.3/src/workbench/agents/assets/claude/workbench-update/SKILL.md +87 -0
  64. workbench_dashboard-0.1.3/src/workbench/agents/assets/gemini/GEMINI.md +96 -0
  65. workbench_dashboard-0.1.3/src/workbench/agents/assets/gemini/commands/workbench-review.toml +8 -0
  66. workbench_dashboard-0.1.3/src/workbench/agents/assets/gemini/commands/workbench-update.toml +9 -0
  67. workbench_dashboard-0.1.3/src/workbench/agents/hooks.py +388 -0
  68. workbench_dashboard-0.1.3/src/workbench/agents/install.py +242 -0
  69. workbench_dashboard-0.1.3/src/workbench/agents/updater.py +499 -0
  70. workbench_dashboard-0.1.3/src/workbench/cli/__init__.py +48 -0
  71. workbench_dashboard-0.1.3/src/workbench/cli/__main__.py +3 -0
  72. workbench_dashboard-0.1.3/src/workbench/cli/_common.py +421 -0
  73. workbench_dashboard-0.1.3/src/workbench/cli/agents.py +236 -0
  74. workbench_dashboard-0.1.3/src/workbench/cli/demo.py +22 -0
  75. workbench_dashboard-0.1.3/src/workbench/cli/discover.py +30 -0
  76. workbench_dashboard-0.1.3/src/workbench/cli/hierarchy.py +275 -0
  77. workbench_dashboard-0.1.3/src/workbench/cli/history.py +124 -0
  78. workbench_dashboard-0.1.3/src/workbench/cli/items.py +170 -0
  79. workbench_dashboard-0.1.3/src/workbench/cli/learning.py +113 -0
  80. workbench_dashboard-0.1.3/src/workbench/cli/projects.py +522 -0
  81. workbench_dashboard-0.1.3/src/workbench/cli/server.py +72 -0
  82. workbench_dashboard-0.1.3/src/workbench/cli/setup.py +114 -0
  83. workbench_dashboard-0.1.3/src/workbench/commitmsg.py +104 -0
  84. workbench_dashboard-0.1.3/src/workbench/config.py +109 -0
  85. workbench_dashboard-0.1.3/src/workbench/demo/__init__.py +13 -0
  86. workbench_dashboard-0.1.3/src/workbench/demo/data/github_fixtures.yaml +58 -0
  87. workbench_dashboard-0.1.3/src/workbench/demo/data/repos.yaml +67 -0
  88. workbench_dashboard-0.1.3/src/workbench/demo/data/seed/learning/demo-control-theory/path.yaml +40 -0
  89. workbench_dashboard-0.1.3/src/workbench/demo/data/seed/learning/demo-linear-algebra/path.yaml +51 -0
  90. workbench_dashboard-0.1.3/src/workbench/demo/data/seed/learning/demo-robotics-kinematics/path.yaml +51 -0
  91. workbench_dashboard-0.1.3/src/workbench/demo/data/seed/learning/demo-robotics-kinematics/topics/rigid-motions.md +6 -0
  92. workbench_dashboard-0.1.3/src/workbench/demo/data/seed/learning/demo-signal-processing/path.yaml +77 -0
  93. workbench_dashboard-0.1.3/src/workbench/demo/data/seed/learning/demo-signal-processing/topics/aliasing.md +6 -0
  94. workbench_dashboard-0.1.3/src/workbench/demo/data/seed/learning/demo-signal-processing/topics/filters.md +6 -0
  95. workbench_dashboard-0.1.3/src/workbench/demo/data/seed/learning/demo-signal-processing/topics/sampling.md +9 -0
  96. workbench_dashboard-0.1.3/src/workbench/demo/data/seed/projects/demo-budget-cli/project.yaml +67 -0
  97. workbench_dashboard-0.1.3/src/workbench/demo/data/seed/projects/demo-esp32-audio-dsp/project.yaml +71 -0
  98. workbench_dashboard-0.1.3/src/workbench/demo/data/seed/projects/demo-fpga-logic-analyzer/project.yaml +62 -0
  99. workbench_dashboard-0.1.3/src/workbench/demo/data/seed/projects/demo-home-lab-cluster/project.yaml +115 -0
  100. workbench_dashboard-0.1.3/src/workbench/demo/data/seed/projects/demo-notes-sync/project.yaml +15 -0
  101. workbench_dashboard-0.1.3/src/workbench/demo/data/seed/projects/demo-old-game/project.yaml +28 -0
  102. workbench_dashboard-0.1.3/src/workbench/demo/data/seed/projects/demo-portfolio-site/project.yaml +55 -0
  103. workbench_dashboard-0.1.3/src/workbench/demo/data/seed/projects/demo-robot-arm/project.yaml +200 -0
  104. workbench_dashboard-0.1.3/src/workbench/demo/data/seed/projects/demo-weather-station/project.yaml +145 -0
  105. workbench_dashboard-0.1.3/src/workbench/demo/data/seed/workbench.yaml +1 -0
  106. workbench_dashboard-0.1.3/src/workbench/demo/environment.py +201 -0
  107. workbench_dashboard-0.1.3/src/workbench/demo/fake_github.py +62 -0
  108. workbench_dashboard-0.1.3/src/workbench/discovery/__init__.py +1 -0
  109. workbench_dashboard-0.1.3/src/workbench/discovery/github.py +201 -0
  110. workbench_dashboard-0.1.3/src/workbench/discovery/local.py +143 -0
  111. workbench_dashboard-0.1.3/src/workbench/discovery/register.py +195 -0
  112. workbench_dashboard-0.1.3/src/workbench/edits.py +498 -0
  113. workbench_dashboard-0.1.3/src/workbench/gitops.py +276 -0
  114. workbench_dashboard-0.1.3/src/workbench/identity.py +95 -0
  115. workbench_dashboard-0.1.3/src/workbench/learning_md.py +171 -0
  116. workbench_dashboard-0.1.3/src/workbench/models.py +292 -0
  117. workbench_dashboard-0.1.3/src/workbench/privacy.py +310 -0
  118. workbench_dashboard-0.1.3/src/workbench/semantic.py +193 -0
  119. workbench_dashboard-0.1.3/src/workbench/server/__init__.py +1 -0
  120. workbench_dashboard-0.1.3/src/workbench/server/app.py +351 -0
  121. workbench_dashboard-0.1.3/src/workbench/server/sync.py +267 -0
  122. workbench_dashboard-0.1.3/src/workbench/server/writes/__init__.py +52 -0
  123. workbench_dashboard-0.1.3/src/workbench/server/writes/_transaction.py +196 -0
  124. workbench_dashboard-0.1.3/src/workbench/server/writes/fields.py +198 -0
  125. workbench_dashboard-0.1.3/src/workbench/server/writes/structure.py +299 -0
  126. workbench_dashboard-0.1.3/src/workbench/server/writes/suggestions.py +59 -0
  127. workbench_dashboard-0.1.3/src/workbench/validate.py +375 -0
  128. workbench_dashboard-0.1.3/src/workbench/yamlio.py +63 -0
  129. workbench_dashboard-0.1.3/uv.lock +864 -0
  130. workbench_dashboard-0.1.3/web/README.md +281 -0
  131. workbench_dashboard-0.1.3/web/biome.json +36 -0
  132. workbench_dashboard-0.1.3/web/docs/images/default-home.png +0 -0
  133. workbench_dashboard-0.1.3/web/docs/images/default-inline-editing.png +0 -0
  134. workbench_dashboard-0.1.3/web/docs/images/default-project-map.png +0 -0
  135. workbench_dashboard-0.1.3/web/docs/images/minimal-look.png +0 -0
  136. workbench_dashboard-0.1.3/web/examples/minimal-look/index.tsx +167 -0
  137. workbench_dashboard-0.1.3/web/examples/minimal-look/minimal.css +182 -0
  138. workbench_dashboard-0.1.3/web/index.html +15 -0
  139. workbench_dashboard-0.1.3/web/package-lock.json +4044 -0
  140. workbench_dashboard-0.1.3/web/package.json +33 -0
  141. workbench_dashboard-0.1.3/web/public/apple-touch-icon.png +0 -0
  142. workbench_dashboard-0.1.3/web/public/favicon-32.png +0 -0
  143. workbench_dashboard-0.1.3/web/public/favicon.svg +9 -0
  144. workbench_dashboard-0.1.3/web/src/core/api.ts +159 -0
  145. workbench_dashboard-0.1.3/web/src/core/derive.ts +670 -0
  146. workbench_dashboard-0.1.3/web/src/core/index.ts +89 -0
  147. workbench_dashboard-0.1.3/web/src/core/react.ts +59 -0
  148. workbench_dashboard-0.1.3/web/src/core/statuses.ts +23 -0
  149. workbench_dashboard-0.1.3/web/src/core/store.ts +1075 -0
  150. workbench_dashboard-0.1.3/web/src/main.tsx +13 -0
  151. workbench_dashboard-0.1.3/web/src/types/learning.d.ts +80 -0
  152. workbench_dashboard-0.1.3/web/src/types/project.d.ts +132 -0
  153. workbench_dashboard-0.1.3/web/src/ui/App.tsx +85 -0
  154. workbench_dashboard-0.1.3/web/src/ui/components/ChildProjects.tsx +155 -0
  155. workbench_dashboard-0.1.3/web/src/ui/components/ComponentCards.tsx +244 -0
  156. workbench_dashboard-0.1.3/web/src/ui/components/Editing.tsx +357 -0
  157. workbench_dashboard-0.1.3/web/src/ui/components/FooterBar.tsx +60 -0
  158. workbench_dashboard-0.1.3/web/src/ui/components/HomeCards.tsx +171 -0
  159. workbench_dashboard-0.1.3/web/src/ui/components/Inspector.tsx +329 -0
  160. workbench_dashboard-0.1.3/web/src/ui/components/ItemStatusMenu.tsx +52 -0
  161. workbench_dashboard-0.1.3/web/src/ui/components/LearningHeader.tsx +108 -0
  162. workbench_dashboard-0.1.3/web/src/ui/components/LearningNavPanel.tsx +133 -0
  163. workbench_dashboard-0.1.3/web/src/ui/components/LearningTopicList.tsx +110 -0
  164. workbench_dashboard-0.1.3/web/src/ui/components/LearningVisualPanel.tsx +184 -0
  165. workbench_dashboard-0.1.3/web/src/ui/components/PanelResizer.tsx +31 -0
  166. workbench_dashboard-0.1.3/web/src/ui/components/PhaseList.tsx +168 -0
  167. workbench_dashboard-0.1.3/web/src/ui/components/ProjectHeader.tsx +176 -0
  168. workbench_dashboard-0.1.3/web/src/ui/components/ProjectNavPanel.tsx +309 -0
  169. workbench_dashboard-0.1.3/web/src/ui/components/ProjectVisualPanel.tsx +173 -0
  170. workbench_dashboard-0.1.3/web/src/ui/components/SearchHeader.tsx +45 -0
  171. workbench_dashboard-0.1.3/web/src/ui/components/Sidebar.tsx +230 -0
  172. workbench_dashboard-0.1.3/web/src/ui/components/StatusMenu.tsx +153 -0
  173. workbench_dashboard-0.1.3/web/src/ui/components/StructureControls.tsx +369 -0
  174. workbench_dashboard-0.1.3/web/src/ui/components/SuggestionsInbox.tsx +83 -0
  175. workbench_dashboard-0.1.3/web/src/ui/components/VisualGraph.tsx +986 -0
  176. workbench_dashboard-0.1.3/web/src/ui/components/status.tsx +232 -0
  177. workbench_dashboard-0.1.3/web/src/ui/index.tsx +18 -0
  178. workbench_dashboard-0.1.3/web/src/ui/layoutPrefs.ts +83 -0
  179. workbench_dashboard-0.1.3/web/src/ui/lookState.tsx +224 -0
  180. workbench_dashboard-0.1.3/web/src/ui/pages/HomePage.tsx +94 -0
  181. workbench_dashboard-0.1.3/web/src/ui/pages/LearningPage.tsx +66 -0
  182. workbench_dashboard-0.1.3/web/src/ui/pages/ProjectPage.tsx +144 -0
  183. workbench_dashboard-0.1.3/web/src/ui/styles/base.css +119 -0
  184. workbench_dashboard-0.1.3/web/src/ui/styles/child-projects.css +167 -0
  185. workbench_dashboard-0.1.3/web/src/ui/styles/contents.css +186 -0
  186. workbench_dashboard-0.1.3/web/src/ui/styles/editing.css +371 -0
  187. workbench_dashboard-0.1.3/web/src/ui/styles/hierarchy.css +217 -0
  188. workbench_dashboard-0.1.3/web/src/ui/styles/home.css +190 -0
  189. workbench_dashboard-0.1.3/web/src/ui/styles/inbox.css +38 -0
  190. workbench_dashboard-0.1.3/web/src/ui/styles/layout.css +331 -0
  191. workbench_dashboard-0.1.3/web/src/ui/styles/map.css +146 -0
  192. workbench_dashboard-0.1.3/web/src/ui/styles/misc.css +78 -0
  193. workbench_dashboard-0.1.3/web/src/ui/styles/nav-tree.css +173 -0
  194. workbench_dashboard-0.1.3/web/src/ui/styles/related.css +117 -0
  195. workbench_dashboard-0.1.3/web/src/ui/styles/responsive.css +43 -0
  196. workbench_dashboard-0.1.3/web/src/ui/styles/status-menu.css +102 -0
  197. workbench_dashboard-0.1.3/web/src/ui/styles/status.css +57 -0
  198. workbench_dashboard-0.1.3/web/src/ui/styles/tokens.css +40 -0
  199. workbench_dashboard-0.1.3/web/src/ui/styles/workspace.css +148 -0
  200. workbench_dashboard-0.1.3/web/src/ui/styles.css +21 -0
  201. workbench_dashboard-0.1.3/web/tsconfig.json +34 -0
  202. workbench_dashboard-0.1.3/web/tsconfig.looks.json +8 -0
  203. workbench_dashboard-0.1.3/web/vite.config.ts +34 -0
@@ -0,0 +1,22 @@
1
+ # Keep the build context small and free of host-specific or secret files.
2
+ # node_modules from a Mac checkout would overwrite the Linux build's own install.
3
+ .git
4
+ .env
5
+ .env.*
6
+ secrets/
7
+ .claude/
8
+ .venv/
9
+ **/__pycache__/
10
+ .pytest_cache/
11
+ graphify-out/
12
+ test-results/
13
+ playwright-report/
14
+ web/node_modules/
15
+ web/dist/
16
+ web/docs/
17
+ web/*.tsbuildinfo
18
+ # Tests are not needed to build the image
19
+ tests/
20
+ web/src/core/__tests__/
21
+ # The desktop app is built on the laptop, not in the server image (its Rust output is over 1 GB)
22
+ desktop/
@@ -0,0 +1,5 @@
1
+ # Commits that only reformatted code; `git blame` skips them.
2
+ # Enable locally with: git config blame.ignoreRevsFile .git-blame-ignore-revs
3
+
4
+ # build(workbench): add Ruff, Biome and CI; apply lint fixes and format the code
5
+ e78414a665db3c065d2c94d74e709296990c3d43
@@ -0,0 +1,133 @@
1
+ # Checks every push and pull request. The test suites are kept out of the repository, so CI
2
+ # lints, type-checks, builds, and smoke-tests the installed package on each OS instead.
3
+ name: CI
4
+
5
+ on:
6
+ push:
7
+ branches: [main]
8
+ pull_request:
9
+
10
+ permissions:
11
+ contents: read
12
+
13
+ concurrency:
14
+ group: ci-${{ github.ref }}
15
+ cancel-in-progress: true
16
+
17
+ jobs:
18
+ lint:
19
+ name: Lint and format
20
+ runs-on: ubuntu-latest
21
+ steps:
22
+ - uses: actions/checkout@v7
23
+ - uses: astral-sh/setup-uv@v10.3.3
24
+ - uses: actions/setup-node@v7
25
+ with:
26
+ node-version: 22
27
+ cache: npm
28
+ cache-dependency-path: web/package-lock.json
29
+ - run: uv sync --locked
30
+ # Every copy of the version agrees and CHANGELOG.md keeps an Unreleased section
31
+ - run: python3 scripts/version.py check
32
+ - run: uv run ruff check .
33
+ - run: uv run ruff format --check .
34
+ - run: npm ci
35
+ working-directory: web
36
+ - run: npm run lint
37
+ working-directory: web
38
+
39
+ web:
40
+ name: Web UI and generated files
41
+ runs-on: ubuntu-latest
42
+ steps:
43
+ - uses: actions/checkout@v7
44
+ - uses: astral-sh/setup-uv@v10.3.3
45
+ - uses: actions/setup-node@v7
46
+ with:
47
+ node-version: 22
48
+ cache: npm
49
+ cache-dependency-path: web/package-lock.json
50
+ - run: uv sync --locked
51
+ - run: npm ci
52
+ working-directory: web
53
+ # schema/ and web/src/types/ are generated from models.py and must be committed up to date
54
+ - run: make schema
55
+ - run: git diff --exit-code -- schema web/src/types
56
+ - run: npx tsc --noEmit -p .
57
+ working-directory: web
58
+ - run: npm run typecheck:look
59
+ working-directory: web
60
+ - run: npm run build
61
+ working-directory: web
62
+
63
+ package:
64
+ name: Package on ${{ matrix.os }}
65
+ runs-on: ${{ matrix.os }}
66
+ strategy:
67
+ fail-fast: false
68
+ matrix:
69
+ os: [ubuntu-latest, macos-latest, windows-latest]
70
+ defaults:
71
+ run:
72
+ shell: bash
73
+ steps:
74
+ - uses: actions/checkout@v7
75
+ - uses: astral-sh/setup-uv@v10.3.3
76
+ - uses: actions/setup-node@v7
77
+ with:
78
+ node-version: 22
79
+ cache: npm
80
+ cache-dependency-path: web/package-lock.json
81
+ - name: Build the UI and the wheel
82
+ run: |
83
+ (cd web && npm ci && npm run build)
84
+ uv build --wheel -o dist
85
+ - name: The wheel ships the UI and the agent files
86
+ run: |
87
+ uv run --no-project python - <<'EOF'
88
+ import glob, zipfile
89
+ names = zipfile.ZipFile(glob.glob("dist/*.whl")[0]).namelist()
90
+ for required in ("workbench/web_dist/index.html",
91
+ "workbench/agents/assets/claude/workbench-update/SKILL.md",
92
+ "workbench/agents/assets/gemini/GEMINI.md"):
93
+ assert required in names, f"missing from wheel: {required}"
94
+ print(f"wheel ok ({len(names)} files)")
95
+ EOF
96
+ - name: Install the wheel in a clean environment
97
+ run: |
98
+ uv venv --python 3.13 ../clean
99
+ VIRTUAL_ENV=../clean uv pip install dist/*.whl
100
+ echo "WB=$(cd ../clean && pwd)/$([ "$RUNNER_OS" = Windows ] && echo Scripts/workbench.exe || echo bin/workbench)" >> "$GITHUB_ENV"
101
+ - name: Smoke-test the installed CLI
102
+ run: |
103
+ home="$RUNNER_TEMP/wb-home"
104
+ mkdir -p "$home"
105
+ "$WB" --help > /dev/null
106
+ "$WB" install --home "$home" --claude --gemini
107
+ test -f "$home/.claude/skills/workbench-update/SKILL.md"
108
+ test -f "$home/.gemini/GEMINI.md"
109
+ - name: Smoke-test the dashboard server
110
+ if: runner.os == 'Linux'
111
+ run: |
112
+ demo="$RUNNER_TEMP/wb-demo"
113
+ "$WB" demo init "$demo"
114
+ # The demo's fake laptop has a config.toml pointing at the demo's local data repo
115
+ HOME="$demo/laptop" "$WB" serve --port 8499 > "$RUNNER_TEMP/serve.log" 2>&1 &
116
+ server=$!
117
+ for _ in $(seq 1 30); do curl -sf http://127.0.0.1:8499/api/status > /dev/null && break; sleep 1; done
118
+ curl -sf http://127.0.0.1:8499/api/status | grep -q '"last_error":null' || { cat "$RUNNER_TEMP/serve.log"; exit 1; }
119
+ curl -sf http://127.0.0.1:8499/ | grep -q "<title>Workbench</title>"
120
+ kill "$server"
121
+
122
+ docker:
123
+ name: Docker image
124
+ runs-on: ubuntu-latest
125
+ steps:
126
+ - uses: actions/checkout@v7
127
+ - uses: docker/setup-buildx-action@v4
128
+ - uses: docker/build-push-action@v7
129
+ with:
130
+ context: .
131
+ file: packaging/docker/Dockerfile
132
+ push: false
133
+ tags: workbench:ci
@@ -0,0 +1,270 @@
1
+ # Builds and publishes a release when a version tag (v1.2.3) is pushed:
2
+ # - Workbench_<version>_aarch64.dmg macOS desktop app (unsigned, Apple silicon)
3
+ # - Workbench_<version>_aarch64.app.tar.gz (+ .sig) and latest.json: what installed apps update from
4
+ # - workbench_dashboard-<version>-py3-none-any.whl and .tar.gz, also published to PyPI
5
+ # - ghcr.io/<owner>/workbench:<version> (and :<major>.<minor>, :latest) for linux/amd64 + arm64
6
+ # The release notes are the version's section of CHANGELOG.md. See docs/releasing.md.
7
+ name: Release
8
+
9
+ on:
10
+ push:
11
+ tags: ["v*.*.*"]
12
+
13
+ permissions:
14
+ contents: read
15
+
16
+ concurrency:
17
+ group: release-${{ github.ref }}
18
+ cancel-in-progress: false
19
+
20
+ jobs:
21
+ check:
22
+ name: Version and changelog
23
+ runs-on: ubuntu-latest
24
+ outputs:
25
+ version: ${{ steps.version.outputs.version }}
26
+ steps:
27
+ - uses: actions/checkout@v7
28
+ # Every version copy matches the tag and CHANGELOG.md has a non-empty section for it
29
+ - run: python3 scripts/version.py check --tag "$GITHUB_REF_NAME"
30
+ - id: version
31
+ run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
32
+
33
+ python:
34
+ name: Wheel and sdist
35
+ needs: check
36
+ runs-on: ubuntu-latest
37
+ steps:
38
+ - uses: actions/checkout@v7
39
+ - uses: astral-sh/setup-uv@v10.3.3
40
+ - uses: actions/setup-node@v7
41
+ with:
42
+ node-version: 22
43
+ cache: npm
44
+ cache-dependency-path: web/package-lock.json
45
+ # The wheel is built from the checkout, not from the sdist (plain `uv build` does that), because
46
+ # the sdist leaves out the gitignored web/dist and a wheel built from it would have no UI
47
+ - name: Build the UI, then the wheel (which ships it) and the sdist
48
+ run: |
49
+ (cd web && npm ci && npm run build)
50
+ uv build --wheel -o dist
51
+ uv build --sdist -o dist
52
+ - name: The installed wheel reports the release version and serves the UI files
53
+ run: |
54
+ uv venv --python 3.13 ../clean
55
+ VIRTUAL_ENV=../clean uv pip install dist/*.whl
56
+ test "$(../clean/bin/workbench --version)" = "workbench ${{ needs.check.outputs.version }}"
57
+ ../clean/bin/python -c "import pathlib, workbench; assert (pathlib.Path(workbench.__file__).parent / 'web_dist/index.html').is_file()"
58
+ - uses: actions/upload-artifact@v7
59
+ with:
60
+ name: python
61
+ path: dist/*
62
+ if-no-files-found: error
63
+
64
+ macos:
65
+ name: macOS app
66
+ needs: check
67
+ runs-on: macos-latest
68
+ steps:
69
+ - uses: actions/checkout@v7
70
+ - uses: astral-sh/setup-uv@v10.3.3
71
+ - uses: actions/setup-node@v7
72
+ with:
73
+ node-version: 22
74
+ cache: npm
75
+ cache-dependency-path: |
76
+ web/package-lock.json
77
+ desktop/package-lock.json
78
+ - name: Build the app (UI, frozen workbench binary, Tauri bundle, signed update archive)
79
+ env:
80
+ # Signs the update archive; installed apps reject updates without a valid signature
81
+ TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
82
+ TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
83
+ run: |
84
+ if [ -z "$TAURI_SIGNING_PRIVATE_KEY" ]; then
85
+ echo "::error::The TAURI_SIGNING_PRIVATE_KEY secret is not set (see docs/releasing.md)"
86
+ exit 1
87
+ fi
88
+ (cd web && npm ci)
89
+ make desktop-release
90
+ - name: The bundled binary reports the release version
91
+ run: |
92
+ app=desktop/src-tauri/target/release/bundle/macos/Workbench.app
93
+ test "$("$app/Contents/Resources/workbench/workbench" --version)" = "workbench ${{ needs.check.outputs.version }}"
94
+ # latest.json is what installed apps read (releases/latest/download/latest.json) to find and
95
+ # verify the new version
96
+ - name: Name the update archive by version and write latest.json
97
+ env:
98
+ VERSION: ${{ needs.check.outputs.version }}
99
+ BASE_URL: https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}
100
+ run: |
101
+ bundle=desktop/src-tauri/target/release/bundle
102
+ mkdir -p out
103
+ cp "$bundle"/dmg/*.dmg out/
104
+ cp "$bundle/macos/Workbench.app.tar.gz" "out/Workbench_${VERSION}_aarch64.app.tar.gz"
105
+ cp "$bundle/macos/Workbench.app.tar.gz.sig" "out/Workbench_${VERSION}_aarch64.app.tar.gz.sig"
106
+ python3 - <<'EOF'
107
+ import json, os, pathlib, datetime
108
+ version = os.environ["VERSION"]
109
+ archive = f"Workbench_{version}_aarch64.app.tar.gz"
110
+ manifest = {
111
+ "version": version,
112
+ "notes": f"Workbench {version}: see CHANGELOG.md",
113
+ "pub_date": datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
114
+ "platforms": {
115
+ "darwin-aarch64": {
116
+ "signature": pathlib.Path(f"out/{archive}.sig").read_text().strip(),
117
+ "url": f"{os.environ['BASE_URL']}/{archive}",
118
+ }
119
+ },
120
+ }
121
+ pathlib.Path("out/latest.json").write_text(json.dumps(manifest, indent=2) + "\n")
122
+ EOF
123
+ - uses: actions/upload-artifact@v7
124
+ with:
125
+ name: macos
126
+ path: out/*
127
+ if-no-files-found: error
128
+
129
+ docker:
130
+ name: Docker image
131
+ needs: check
132
+ runs-on: ubuntu-latest
133
+ permissions:
134
+ contents: read
135
+ packages: write
136
+ steps:
137
+ - uses: actions/checkout@v7
138
+ - uses: docker/setup-qemu-action@v4
139
+ - uses: docker/setup-buildx-action@v4
140
+ - uses: docker/login-action@v4
141
+ with:
142
+ registry: ghcr.io
143
+ username: ${{ github.actor }}
144
+ password: ${{ secrets.GITHUB_TOKEN }}
145
+ - id: meta
146
+ uses: docker/metadata-action@v6
147
+ with:
148
+ images: ghcr.io/${{ github.repository }}
149
+ # 1.2.3 and 1.2 always; latest only for releases without a -suffix
150
+ tags: |
151
+ type=semver,pattern={{version}}
152
+ type=semver,pattern={{major}}.{{minor}}
153
+ - uses: docker/build-push-action@v7
154
+ env:
155
+ # Otherwise the action uploads a .dockerbuild record as a workflow artifact, and the
156
+ # release job (which downloads every artifact) attaches it to the GitHub Release
157
+ DOCKER_BUILD_RECORD_UPLOAD: false
158
+ with:
159
+ context: .
160
+ file: packaging/docker/Dockerfile
161
+ platforms: linux/amd64,linux/arm64
162
+ push: true
163
+ tags: ${{ steps.meta.outputs.tags }}
164
+ labels: ${{ steps.meta.outputs.labels }}
165
+
166
+ release:
167
+ name: GitHub Release
168
+ needs: [check, python, macos, docker]
169
+ runs-on: ubuntu-latest
170
+ permissions:
171
+ contents: write
172
+ steps:
173
+ - uses: actions/checkout@v7
174
+ - uses: actions/download-artifact@v8
175
+ with:
176
+ path: dist
177
+ merge-multiple: true
178
+ - name: Checksums and notes
179
+ run: |
180
+ (cd dist && sha256sum * > SHA256SUMS)
181
+ python3 scripts/version.py notes "$GITHUB_REF_NAME" > notes.md
182
+ cat >> notes.md <<EOF
183
+
184
+ ---
185
+ **Docker:** \`docker pull ghcr.io/${{ github.repository }}:${{ needs.check.outputs.version }}\`
186
+
187
+ **macOS app:** not signed by Apple yet, so macOS calls the download "damaged". After dragging it to Applications, run \`xattr -dr com.apple.quarantine /Applications/Workbench.app\` once, then open it. Installed apps from 0.1.2 on update themselves. See [docs/desktop.md](https://github.com/${{ github.repository }}/blob/$GITHUB_REF_NAME/docs/desktop.md).
188
+ EOF
189
+ - name: Create the release
190
+ env:
191
+ GH_TOKEN: ${{ github.token }}
192
+ run: |
193
+ version="${{ needs.check.outputs.version }}"
194
+ prerelease=""
195
+ case "$version" in *-*) prerelease="--prerelease" ;; esac
196
+ gh release create "$GITHUB_REF_NAME" dist/* --verify-tag $prerelease \
197
+ --title "Workbench $version" --notes-file notes.md
198
+
199
+ # Publishes the wheel and sdist as workbench-dashboard on PyPI with trusted publishing: PyPI
200
+ # trusts this workflow's OIDC token (no API token is stored), once the project's trusted
201
+ # publisher names this repository, release.yml and the environment `pypi` (docs/releasing.md).
202
+ # Runs after the GitHub Release, since a version uploaded to PyPI can never be replaced.
203
+ pypi:
204
+ name: PyPI
205
+ needs: [check, release]
206
+ runs-on: ubuntu-latest
207
+ environment:
208
+ name: pypi
209
+ url: https://pypi.org/project/workbench-dashboard/
210
+ permissions:
211
+ id-token: write
212
+ steps:
213
+ - uses: actions/download-artifact@v8
214
+ with:
215
+ name: python
216
+ path: dist
217
+ - uses: pypa/gh-action-pypi-publish@release/v1
218
+
219
+ # Points the Homebrew cask (tap user7217/homebrew-workbench) at the new dmg. Needs the
220
+ # HOMEBREW_TAP_TOKEN secret: a fine-grained token with Contents read/write on the tap repo only.
221
+ # Pre-releases are skipped, like the app's own updates.
222
+ homebrew:
223
+ name: Homebrew cask
224
+ needs: [check, release]
225
+ if: ${{ !contains(needs.check.outputs.version, '-') }}
226
+ runs-on: ubuntu-latest
227
+ env:
228
+ VERSION: ${{ needs.check.outputs.version }}
229
+ TAP: ${{ github.repository_owner }}/homebrew-workbench
230
+ steps:
231
+ - id: token
232
+ env:
233
+ HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
234
+ run: |
235
+ if [ -z "$HOMEBREW_TAP_TOKEN" ]; then
236
+ echo "::warning::HOMEBREW_TAP_TOKEN is not set, so the Homebrew cask was not updated (see docs/releasing.md)"
237
+ echo "set=false" >> "$GITHUB_OUTPUT"
238
+ else
239
+ echo "set=true" >> "$GITHUB_OUTPUT"
240
+ fi
241
+ - if: steps.token.outputs.set == 'true'
242
+ uses: actions/checkout@v7
243
+ - if: steps.token.outputs.set == 'true'
244
+ uses: actions/checkout@v7
245
+ with:
246
+ repository: ${{ env.TAP }}
247
+ token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
248
+ path: tap
249
+ - if: steps.token.outputs.set == 'true'
250
+ uses: actions/download-artifact@v8
251
+ with:
252
+ name: macos
253
+ path: dist
254
+ - name: Write the cask for this version and push it to the tap
255
+ if: steps.token.outputs.set == 'true'
256
+ run: |
257
+ sha=$(sha256sum "dist/Workbench_${VERSION}_aarch64.dmg" | cut -d' ' -f1)
258
+ mkdir -p tap/Casks
259
+ sed -e "s/@VERSION@/${VERSION}/" -e "s/@SHA256@/${sha}/" \
260
+ packaging/homebrew/workbench-dashboard.rb > tap/Casks/workbench-dashboard.rb
261
+ cd tap
262
+ git config user.name "github-actions[bot]"
263
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
264
+ git add Casks/workbench-dashboard.rb
265
+ if git diff --cached --quiet; then
266
+ echo "The cask is already at ${VERSION}"
267
+ exit 0
268
+ fi
269
+ git commit -m "workbench-dashboard ${VERSION}"
270
+ git push
@@ -0,0 +1,59 @@
1
+ # --- Secrets and local configuration (never publish) ---
2
+ .env
3
+ .env.*
4
+ !.env.example
5
+ *.pem
6
+ *.key
7
+ id_ed25519*
8
+ workbench_deploy_key*
9
+ # Server deploy key and other server-only files (see docs/setup.md)
10
+ secrets/
11
+ docker-compose.override.yml
12
+
13
+ # Local editor / Claude Code settings (contain machine-specific paths)
14
+ .claude/
15
+
16
+ # Personal notes and data kept next to the code, not part of the app
17
+ ros2-learn.md
18
+
19
+ # --- Python ---
20
+ .venv/
21
+ __pycache__/
22
+ *.py[cod]
23
+ *.egg-info/
24
+ .pytest_cache/
25
+ .ruff_cache/
26
+ .mypy_cache/
27
+ .coverage
28
+ htmlcov/
29
+ build/
30
+ dist/
31
+ tests/
32
+
33
+ # --- Web UI ---
34
+ web/node_modules/
35
+ web/dist/
36
+ web/src/core/__tests__/
37
+ web/*.tsbuildinfo
38
+
39
+ # Playwright output
40
+ test-results/
41
+ playwright-report/
42
+
43
+ # --- Tooling output ---
44
+ # Local knowledge-graph build (graphify); regenerate with `graphify update .`
45
+ graphify-out/
46
+ ros2-learn.md
47
+
48
+ # --- OS / editors ---
49
+ .DS_Store
50
+ .idea/
51
+ .vscode/
52
+ *.swp
53
+ DECISIONS.md
54
+
55
+ # Desktop app build output (frozen server binary, Rust target, Tauri CLI)
56
+ desktop/build/
57
+ desktop/node_modules/
58
+ desktop/src-tauri/target/
59
+ desktop/src-tauri/gen/
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,64 @@
1
+ # Changelog
2
+
3
+ Notable changes to Workbench. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Before 1.0, a minor version (0.x.0) may change the data format or the CLI; such changes are listed under **Changed** with what to do about them.
4
+
5
+ Each release on [GitHub Releases](https://github.com/user7217/workbench/releases) uses its section below as release notes. Changes waiting for the next release go under **Unreleased**; [docs/releasing.md](docs/releasing.md) describes how a release is cut.
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.1.3] - 2026-11-10
10
+
11
+ ### Added
12
+
13
+ - **Homebrew:** `brew install --cask user7217/workbench/workbench-dashboard` installs the macOS app and links the `workbench` command. Each release updates the cask.
14
+ - **PyPI:** the CLI and server are published as `workbench-dashboard`: `uv tool install workbench-dashboard` or `pipx install workbench-dashboard`. The command is still `workbench`.
15
+
16
+ ### Changed
17
+
18
+ - The Python package is now named `workbench-dashboard` (wheels are `workbench_dashboard-<version>-…`); the import package and the `workbench` command are unchanged. A CLI installed earlier with `uv tool install .` is registered as the tool `workbench`: run `uv tool uninstall workbench` once, then install `workbench-dashboard`. In a development checkout, run `uv sync --reinstall-package workbench-dashboard` once if `uv run workbench` stops finding the command.
19
+
20
+ ## [0.1.2] - 2026-11-07
21
+
22
+ ### Added
23
+
24
+ - **The macOS app updates itself:** it checks GitHub Releases at launch and every 6 hours, installs a signed new version in place, and offers **Restart to Update** in the menu. **Check for Updates…** checks on demand. Apps before this version need one manual update to get it.
25
+
26
+ ### Fixed
27
+
28
+ - `packaging/docker/update.sh` no longer fails, without a message, when the server's clone holds an outdated copy of a release tag; it takes GitHub's copy and logs any fetch error.
29
+
30
+ ## [0.1.1] - 2026-11-07
31
+
32
+ ### Added
33
+
34
+ - **Automatic server updates:** `packaging/docker/update.sh` and an hourly systemd timer move a Docker server to each new release (releases only, never unreleased commits). To switch an existing server from building on the server to released images, see "Automatic Updates from Releases" in docs/setup.md.
35
+ - **Browser tab icon:** the dashboard shows the app's icon in the browser tab and as the iOS home-screen icon.
36
+ - **Desktop docs:** a first-run guide for setting up a new laptop from the app alone.
37
+
38
+ ### Fixed
39
+
40
+ - Release pages no longer list a stray `.dockerbuild` file among the downloads.
41
+ - The error for a file the data repository does not allow now names the allowed paths correctly.
42
+ - SECURITY.md matches the code: network binding for each run mode, what the headless updater can change, release checksums, and supported versions.
43
+
44
+ ## [0.1.0] - 2026-11-07
45
+
46
+ The first release. Everything below is new.
47
+
48
+ ### Added
49
+
50
+ - **Data model and validation:** projects with phases or topics, components nested to any depth with dependencies, child projects, learning paths with topics and subtopics, all in a private `workbench-data` Git repository. Every change is checked against JSON Schemas, a semantic diff (no lost ids, no mass deletions, no status regressions) and a privacy scanner for secrets, local paths and private addresses, with an optional LLM privacy review (off by default).
51
+ - **CLI:** `workbench show`, `set`, `add`, `focus`, `new`, `attach`, `detach`, `archive-empty`, `push`, `history`, `revert`, learning-path import and update, local and GitHub repository discovery, `setup`, `install`, `serve`, and `workbench --version`. Repositories are identified by their root commit, so renames and moves keep their history.
52
+ - **Dashboard server:** FastAPI server that syncs `workbench-data`, validates each fetched commit in a staging worktree and serves the last good snapshot. Edits made in the dashboard are validated and committed back. Daily GitHub discovery with an optional read-only token (private repositories included).
53
+ - **Web UI:** home view of projects and learning paths, three-panel project and learning workspaces, an interactive dependency map with a divider that moves across the whole column, inline editing of text and structure, and a suggestions inbox (Keep or Dismiss). The UI is split into a fixed state layer and a replaceable look, with a minimal example look.
54
+ - **Coding-agent integration:** Claude Code and Gemini CLI hooks with `workbench-update` and `workbench-review` skills, and a headless updater that records each agent turn in the background through a tool-less model call.
55
+ - **Server mode:** Docker image and Compose file for an always-on machine reached over Tailscale, with a deploy key for the data repository. Also published as `ghcr.io/user7217/workbench`.
56
+ - **Desktop mode (macOS):** a menu-bar app that runs the server on the laptop from login, restarts it if it crashes, opens the dashboard in the browser and can put the `workbench` command on the PATH. Distributed as an unsigned `.dmg` for Apple silicon.
57
+ - **Security:** write endpoints require `X-Workbench: 1` and JSON; a server listening on localhost rejects other `Host` names, blocking DNS rebinding.
58
+ - **Releases:** one version number for the Python package, web UI and desktop app (`scripts/version.py`), this changelog, and a release workflow that builds the `.dmg`, the wheel and sdist, and the Docker image for each `v*` tag.
59
+
60
+ [Unreleased]: https://github.com/user7217/workbench/compare/v0.1.3...HEAD
61
+ [0.1.3]: https://github.com/user7217/workbench/compare/v0.1.2...v0.1.3
62
+ [0.1.2]: https://github.com/user7217/workbench/compare/v0.1.1...v0.1.2
63
+ [0.1.1]: https://github.com/user7217/workbench/compare/v0.1.0...v0.1.1
64
+ [0.1.0]: https://github.com/user7217/workbench/releases/tag/v0.1.0