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.
- workbench_dashboard-0.1.3/.dockerignore +22 -0
- workbench_dashboard-0.1.3/.git-blame-ignore-revs +5 -0
- workbench_dashboard-0.1.3/.github/workflows/ci.yml +133 -0
- workbench_dashboard-0.1.3/.github/workflows/release.yml +270 -0
- workbench_dashboard-0.1.3/.gitignore +59 -0
- workbench_dashboard-0.1.3/.python-version +1 -0
- workbench_dashboard-0.1.3/CHANGELOG.md +64 -0
- workbench_dashboard-0.1.3/CONTRIBUTING.md +166 -0
- workbench_dashboard-0.1.3/LICENSE +21 -0
- workbench_dashboard-0.1.3/Makefile +44 -0
- workbench_dashboard-0.1.3/PKG-INFO +322 -0
- workbench_dashboard-0.1.3/README.md +289 -0
- workbench_dashboard-0.1.3/SECURITY.md +74 -0
- workbench_dashboard-0.1.3/desktop/package-lock.json +247 -0
- workbench_dashboard-0.1.3/desktop/package.json +13 -0
- workbench_dashboard-0.1.3/desktop/src-tauri/Cargo.lock +5526 -0
- workbench_dashboard-0.1.3/desktop/src-tauri/Cargo.toml +29 -0
- workbench_dashboard-0.1.3/desktop/src-tauri/Info.plist +9 -0
- workbench_dashboard-0.1.3/desktop/src-tauri/build.rs +3 -0
- workbench_dashboard-0.1.3/desktop/src-tauri/icons/128x128.png +0 -0
- workbench_dashboard-0.1.3/desktop/src-tauri/icons/128x128@2x.png +0 -0
- workbench_dashboard-0.1.3/desktop/src-tauri/icons/32x32.png +0 -0
- workbench_dashboard-0.1.3/desktop/src-tauri/icons/icon-source.png +0 -0
- workbench_dashboard-0.1.3/desktop/src-tauri/icons/icon.icns +0 -0
- workbench_dashboard-0.1.3/desktop/src-tauri/icons/icon.ico +0 -0
- workbench_dashboard-0.1.3/desktop/src-tauri/icons/icon.png +0 -0
- workbench_dashboard-0.1.3/desktop/src-tauri/icons/tray.png +0 -0
- workbench_dashboard-0.1.3/desktop/src-tauri/src/cli_link.rs +49 -0
- workbench_dashboard-0.1.3/desktop/src-tauri/src/environment.rs +53 -0
- workbench_dashboard-0.1.3/desktop/src-tauri/src/main.rs +253 -0
- workbench_dashboard-0.1.3/desktop/src-tauri/src/server.rs +301 -0
- workbench_dashboard-0.1.3/desktop/src-tauri/src/updater.rs +223 -0
- workbench_dashboard-0.1.3/desktop/src-tauri/tauri.conf.json +45 -0
- workbench_dashboard-0.1.3/desktop/src-tauri/tauri.updater.conf.json +5 -0
- workbench_dashboard-0.1.3/desktop/ui/index.html +3 -0
- workbench_dashboard-0.1.3/docker-compose.yml +32 -0
- workbench_dashboard-0.1.3/docs/architecture.md +187 -0
- workbench_dashboard-0.1.3/docs/desktop.md +134 -0
- workbench_dashboard-0.1.3/docs/reference.md +268 -0
- workbench_dashboard-0.1.3/docs/releasing.md +129 -0
- workbench_dashboard-0.1.3/docs/setup.md +301 -0
- workbench_dashboard-0.1.3/packaging/docker/Dockerfile +36 -0
- workbench_dashboard-0.1.3/packaging/docker/github_known_hosts +6 -0
- workbench_dashboard-0.1.3/packaging/docker/update.sh +65 -0
- workbench_dashboard-0.1.3/packaging/docker/workbench-update.service +11 -0
- workbench_dashboard-0.1.3/packaging/docker/workbench-update.timer +12 -0
- workbench_dashboard-0.1.3/packaging/hatch_build.py +29 -0
- workbench_dashboard-0.1.3/packaging/homebrew/workbench-dashboard.rb +48 -0
- workbench_dashboard-0.1.3/packaging/pyinstaller/entry.py +6 -0
- workbench_dashboard-0.1.3/packaging/pyinstaller/workbench.spec +37 -0
- workbench_dashboard-0.1.3/pyproject.toml +100 -0
- workbench_dashboard-0.1.3/schema/learning.schema.json +227 -0
- workbench_dashboard-0.1.3/schema/project.schema.json +416 -0
- workbench_dashboard-0.1.3/scripts/run_demo.py +59 -0
- workbench_dashboard-0.1.3/scripts/screenshots.py +169 -0
- workbench_dashboard-0.1.3/scripts/version.py +193 -0
- workbench_dashboard-0.1.3/src/workbench/__init__.py +3 -0
- workbench_dashboard-0.1.3/src/workbench/__main__.py +3 -0
- workbench_dashboard-0.1.3/src/workbench/agents/__init__.py +1 -0
- workbench_dashboard-0.1.3/src/workbench/agents/assets/chat/LEARNING_PROMPT.md +67 -0
- workbench_dashboard-0.1.3/src/workbench/agents/assets/chat/PROMPT.md +107 -0
- workbench_dashboard-0.1.3/src/workbench/agents/assets/claude/workbench-review/SKILL.md +130 -0
- workbench_dashboard-0.1.3/src/workbench/agents/assets/claude/workbench-update/SKILL.md +87 -0
- workbench_dashboard-0.1.3/src/workbench/agents/assets/gemini/GEMINI.md +96 -0
- workbench_dashboard-0.1.3/src/workbench/agents/assets/gemini/commands/workbench-review.toml +8 -0
- workbench_dashboard-0.1.3/src/workbench/agents/assets/gemini/commands/workbench-update.toml +9 -0
- workbench_dashboard-0.1.3/src/workbench/agents/hooks.py +388 -0
- workbench_dashboard-0.1.3/src/workbench/agents/install.py +242 -0
- workbench_dashboard-0.1.3/src/workbench/agents/updater.py +499 -0
- workbench_dashboard-0.1.3/src/workbench/cli/__init__.py +48 -0
- workbench_dashboard-0.1.3/src/workbench/cli/__main__.py +3 -0
- workbench_dashboard-0.1.3/src/workbench/cli/_common.py +421 -0
- workbench_dashboard-0.1.3/src/workbench/cli/agents.py +236 -0
- workbench_dashboard-0.1.3/src/workbench/cli/demo.py +22 -0
- workbench_dashboard-0.1.3/src/workbench/cli/discover.py +30 -0
- workbench_dashboard-0.1.3/src/workbench/cli/hierarchy.py +275 -0
- workbench_dashboard-0.1.3/src/workbench/cli/history.py +124 -0
- workbench_dashboard-0.1.3/src/workbench/cli/items.py +170 -0
- workbench_dashboard-0.1.3/src/workbench/cli/learning.py +113 -0
- workbench_dashboard-0.1.3/src/workbench/cli/projects.py +522 -0
- workbench_dashboard-0.1.3/src/workbench/cli/server.py +72 -0
- workbench_dashboard-0.1.3/src/workbench/cli/setup.py +114 -0
- workbench_dashboard-0.1.3/src/workbench/commitmsg.py +104 -0
- workbench_dashboard-0.1.3/src/workbench/config.py +109 -0
- workbench_dashboard-0.1.3/src/workbench/demo/__init__.py +13 -0
- workbench_dashboard-0.1.3/src/workbench/demo/data/github_fixtures.yaml +58 -0
- workbench_dashboard-0.1.3/src/workbench/demo/data/repos.yaml +67 -0
- workbench_dashboard-0.1.3/src/workbench/demo/data/seed/learning/demo-control-theory/path.yaml +40 -0
- workbench_dashboard-0.1.3/src/workbench/demo/data/seed/learning/demo-linear-algebra/path.yaml +51 -0
- workbench_dashboard-0.1.3/src/workbench/demo/data/seed/learning/demo-robotics-kinematics/path.yaml +51 -0
- workbench_dashboard-0.1.3/src/workbench/demo/data/seed/learning/demo-robotics-kinematics/topics/rigid-motions.md +6 -0
- workbench_dashboard-0.1.3/src/workbench/demo/data/seed/learning/demo-signal-processing/path.yaml +77 -0
- workbench_dashboard-0.1.3/src/workbench/demo/data/seed/learning/demo-signal-processing/topics/aliasing.md +6 -0
- workbench_dashboard-0.1.3/src/workbench/demo/data/seed/learning/demo-signal-processing/topics/filters.md +6 -0
- workbench_dashboard-0.1.3/src/workbench/demo/data/seed/learning/demo-signal-processing/topics/sampling.md +9 -0
- workbench_dashboard-0.1.3/src/workbench/demo/data/seed/projects/demo-budget-cli/project.yaml +67 -0
- workbench_dashboard-0.1.3/src/workbench/demo/data/seed/projects/demo-esp32-audio-dsp/project.yaml +71 -0
- workbench_dashboard-0.1.3/src/workbench/demo/data/seed/projects/demo-fpga-logic-analyzer/project.yaml +62 -0
- workbench_dashboard-0.1.3/src/workbench/demo/data/seed/projects/demo-home-lab-cluster/project.yaml +115 -0
- workbench_dashboard-0.1.3/src/workbench/demo/data/seed/projects/demo-notes-sync/project.yaml +15 -0
- workbench_dashboard-0.1.3/src/workbench/demo/data/seed/projects/demo-old-game/project.yaml +28 -0
- workbench_dashboard-0.1.3/src/workbench/demo/data/seed/projects/demo-portfolio-site/project.yaml +55 -0
- workbench_dashboard-0.1.3/src/workbench/demo/data/seed/projects/demo-robot-arm/project.yaml +200 -0
- workbench_dashboard-0.1.3/src/workbench/demo/data/seed/projects/demo-weather-station/project.yaml +145 -0
- workbench_dashboard-0.1.3/src/workbench/demo/data/seed/workbench.yaml +1 -0
- workbench_dashboard-0.1.3/src/workbench/demo/environment.py +201 -0
- workbench_dashboard-0.1.3/src/workbench/demo/fake_github.py +62 -0
- workbench_dashboard-0.1.3/src/workbench/discovery/__init__.py +1 -0
- workbench_dashboard-0.1.3/src/workbench/discovery/github.py +201 -0
- workbench_dashboard-0.1.3/src/workbench/discovery/local.py +143 -0
- workbench_dashboard-0.1.3/src/workbench/discovery/register.py +195 -0
- workbench_dashboard-0.1.3/src/workbench/edits.py +498 -0
- workbench_dashboard-0.1.3/src/workbench/gitops.py +276 -0
- workbench_dashboard-0.1.3/src/workbench/identity.py +95 -0
- workbench_dashboard-0.1.3/src/workbench/learning_md.py +171 -0
- workbench_dashboard-0.1.3/src/workbench/models.py +292 -0
- workbench_dashboard-0.1.3/src/workbench/privacy.py +310 -0
- workbench_dashboard-0.1.3/src/workbench/semantic.py +193 -0
- workbench_dashboard-0.1.3/src/workbench/server/__init__.py +1 -0
- workbench_dashboard-0.1.3/src/workbench/server/app.py +351 -0
- workbench_dashboard-0.1.3/src/workbench/server/sync.py +267 -0
- workbench_dashboard-0.1.3/src/workbench/server/writes/__init__.py +52 -0
- workbench_dashboard-0.1.3/src/workbench/server/writes/_transaction.py +196 -0
- workbench_dashboard-0.1.3/src/workbench/server/writes/fields.py +198 -0
- workbench_dashboard-0.1.3/src/workbench/server/writes/structure.py +299 -0
- workbench_dashboard-0.1.3/src/workbench/server/writes/suggestions.py +59 -0
- workbench_dashboard-0.1.3/src/workbench/validate.py +375 -0
- workbench_dashboard-0.1.3/src/workbench/yamlio.py +63 -0
- workbench_dashboard-0.1.3/uv.lock +864 -0
- workbench_dashboard-0.1.3/web/README.md +281 -0
- workbench_dashboard-0.1.3/web/biome.json +36 -0
- workbench_dashboard-0.1.3/web/docs/images/default-home.png +0 -0
- workbench_dashboard-0.1.3/web/docs/images/default-inline-editing.png +0 -0
- workbench_dashboard-0.1.3/web/docs/images/default-project-map.png +0 -0
- workbench_dashboard-0.1.3/web/docs/images/minimal-look.png +0 -0
- workbench_dashboard-0.1.3/web/examples/minimal-look/index.tsx +167 -0
- workbench_dashboard-0.1.3/web/examples/minimal-look/minimal.css +182 -0
- workbench_dashboard-0.1.3/web/index.html +15 -0
- workbench_dashboard-0.1.3/web/package-lock.json +4044 -0
- workbench_dashboard-0.1.3/web/package.json +33 -0
- workbench_dashboard-0.1.3/web/public/apple-touch-icon.png +0 -0
- workbench_dashboard-0.1.3/web/public/favicon-32.png +0 -0
- workbench_dashboard-0.1.3/web/public/favicon.svg +9 -0
- workbench_dashboard-0.1.3/web/src/core/api.ts +159 -0
- workbench_dashboard-0.1.3/web/src/core/derive.ts +670 -0
- workbench_dashboard-0.1.3/web/src/core/index.ts +89 -0
- workbench_dashboard-0.1.3/web/src/core/react.ts +59 -0
- workbench_dashboard-0.1.3/web/src/core/statuses.ts +23 -0
- workbench_dashboard-0.1.3/web/src/core/store.ts +1075 -0
- workbench_dashboard-0.1.3/web/src/main.tsx +13 -0
- workbench_dashboard-0.1.3/web/src/types/learning.d.ts +80 -0
- workbench_dashboard-0.1.3/web/src/types/project.d.ts +132 -0
- workbench_dashboard-0.1.3/web/src/ui/App.tsx +85 -0
- workbench_dashboard-0.1.3/web/src/ui/components/ChildProjects.tsx +155 -0
- workbench_dashboard-0.1.3/web/src/ui/components/ComponentCards.tsx +244 -0
- workbench_dashboard-0.1.3/web/src/ui/components/Editing.tsx +357 -0
- workbench_dashboard-0.1.3/web/src/ui/components/FooterBar.tsx +60 -0
- workbench_dashboard-0.1.3/web/src/ui/components/HomeCards.tsx +171 -0
- workbench_dashboard-0.1.3/web/src/ui/components/Inspector.tsx +329 -0
- workbench_dashboard-0.1.3/web/src/ui/components/ItemStatusMenu.tsx +52 -0
- workbench_dashboard-0.1.3/web/src/ui/components/LearningHeader.tsx +108 -0
- workbench_dashboard-0.1.3/web/src/ui/components/LearningNavPanel.tsx +133 -0
- workbench_dashboard-0.1.3/web/src/ui/components/LearningTopicList.tsx +110 -0
- workbench_dashboard-0.1.3/web/src/ui/components/LearningVisualPanel.tsx +184 -0
- workbench_dashboard-0.1.3/web/src/ui/components/PanelResizer.tsx +31 -0
- workbench_dashboard-0.1.3/web/src/ui/components/PhaseList.tsx +168 -0
- workbench_dashboard-0.1.3/web/src/ui/components/ProjectHeader.tsx +176 -0
- workbench_dashboard-0.1.3/web/src/ui/components/ProjectNavPanel.tsx +309 -0
- workbench_dashboard-0.1.3/web/src/ui/components/ProjectVisualPanel.tsx +173 -0
- workbench_dashboard-0.1.3/web/src/ui/components/SearchHeader.tsx +45 -0
- workbench_dashboard-0.1.3/web/src/ui/components/Sidebar.tsx +230 -0
- workbench_dashboard-0.1.3/web/src/ui/components/StatusMenu.tsx +153 -0
- workbench_dashboard-0.1.3/web/src/ui/components/StructureControls.tsx +369 -0
- workbench_dashboard-0.1.3/web/src/ui/components/SuggestionsInbox.tsx +83 -0
- workbench_dashboard-0.1.3/web/src/ui/components/VisualGraph.tsx +986 -0
- workbench_dashboard-0.1.3/web/src/ui/components/status.tsx +232 -0
- workbench_dashboard-0.1.3/web/src/ui/index.tsx +18 -0
- workbench_dashboard-0.1.3/web/src/ui/layoutPrefs.ts +83 -0
- workbench_dashboard-0.1.3/web/src/ui/lookState.tsx +224 -0
- workbench_dashboard-0.1.3/web/src/ui/pages/HomePage.tsx +94 -0
- workbench_dashboard-0.1.3/web/src/ui/pages/LearningPage.tsx +66 -0
- workbench_dashboard-0.1.3/web/src/ui/pages/ProjectPage.tsx +144 -0
- workbench_dashboard-0.1.3/web/src/ui/styles/base.css +119 -0
- workbench_dashboard-0.1.3/web/src/ui/styles/child-projects.css +167 -0
- workbench_dashboard-0.1.3/web/src/ui/styles/contents.css +186 -0
- workbench_dashboard-0.1.3/web/src/ui/styles/editing.css +371 -0
- workbench_dashboard-0.1.3/web/src/ui/styles/hierarchy.css +217 -0
- workbench_dashboard-0.1.3/web/src/ui/styles/home.css +190 -0
- workbench_dashboard-0.1.3/web/src/ui/styles/inbox.css +38 -0
- workbench_dashboard-0.1.3/web/src/ui/styles/layout.css +331 -0
- workbench_dashboard-0.1.3/web/src/ui/styles/map.css +146 -0
- workbench_dashboard-0.1.3/web/src/ui/styles/misc.css +78 -0
- workbench_dashboard-0.1.3/web/src/ui/styles/nav-tree.css +173 -0
- workbench_dashboard-0.1.3/web/src/ui/styles/related.css +117 -0
- workbench_dashboard-0.1.3/web/src/ui/styles/responsive.css +43 -0
- workbench_dashboard-0.1.3/web/src/ui/styles/status-menu.css +102 -0
- workbench_dashboard-0.1.3/web/src/ui/styles/status.css +57 -0
- workbench_dashboard-0.1.3/web/src/ui/styles/tokens.css +40 -0
- workbench_dashboard-0.1.3/web/src/ui/styles/workspace.css +148 -0
- workbench_dashboard-0.1.3/web/src/ui/styles.css +21 -0
- workbench_dashboard-0.1.3/web/tsconfig.json +34 -0
- workbench_dashboard-0.1.3/web/tsconfig.looks.json +8 -0
- 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,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
|