hypernote 0.2.0__tar.gz → 0.4.0__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.
- hypernote-0.4.0/.github/workflows/release.yml +236 -0
- {hypernote-0.2.0 → hypernote-0.4.0}/AGENTS.md +12 -14
- {hypernote-0.2.0 → hypernote-0.4.0}/CHANGELOG.md +40 -0
- hypernote-0.4.0/CONTEXT.md +53 -0
- {hypernote-0.2.0 → hypernote-0.4.0}/PKG-INFO +16 -37
- {hypernote-0.2.0 → hypernote-0.4.0}/README.md +12 -32
- {hypernote-0.2.0 → hypernote-0.4.0}/SKILL.md +13 -9
- {hypernote-0.2.0 → hypernote-0.4.0}/dev/README.md +5 -7
- {hypernote-0.2.0 → hypernote-0.4.0}/dev/current-architecture.md +7 -2
- hypernote-0.4.0/dev/module-map.md +29 -0
- hypernote-0.4.0/dev/release.md +157 -0
- {hypernote-0.2.0 → hypernote-0.4.0}/dev/testing-and-verification.md +1 -3
- {hypernote-0.2.0 → hypernote-0.4.0}/docs/README.md +0 -1
- {hypernote-0.2.0 → hypernote-0.4.0}/docs/browser-regression-spec.md +5 -5
- {hypernote-0.2.0 → hypernote-0.4.0}/docs/cli.md +6 -4
- {hypernote-0.2.0 → hypernote-0.4.0}/docs/getting-started.md +17 -9
- {hypernote-0.2.0 → hypernote-0.4.0}/docs/runtime-model.md +13 -0
- {hypernote-0.2.0 → hypernote-0.4.0}/docs/sdk.md +9 -0
- {hypernote-0.2.0 → hypernote-0.4.0}/pyproject.toml +4 -6
- {hypernote-0.2.0 → hypernote-0.4.0}/src/hypernote/cli/main.py +152 -13
- {hypernote-0.2.0 → hypernote-0.4.0}/src/hypernote/execution_orchestrator.py +9 -78
- {hypernote-0.2.0 → hypernote-0.4.0}/src/hypernote/sdk.py +17 -1
- {hypernote-0.2.0 → hypernote-0.4.0}/src/hypernote/server/extension.py +38 -9
- {hypernote-0.2.0 → hypernote-0.4.0}/src/hypernote/server/handlers.py +10 -0
- {hypernote-0.2.0 → hypernote-0.4.0}/tests/conftest.py +4 -5
- {hypernote-0.2.0 → hypernote-0.4.0}/tests/test_cli.py +174 -3
- {hypernote-0.2.0 → hypernote-0.4.0}/tests/test_live_server.py +15 -0
- hypernote-0.4.0/tests/test_package_metadata.py +27 -0
- hypernote-0.4.0/tests/test_server_extension.py +83 -0
- hypernote-0.4.0/tests/test_shared_notebook_accessor.py +47 -0
- {hypernote-0.2.0 → hypernote-0.4.0}/uv.lock +8 -10
- hypernote-0.2.0/.github/workflows/release.yml +0 -161
- hypernote-0.2.0/dev/module-map.md +0 -32
- {hypernote-0.2.0 → hypernote-0.4.0}/.gitignore +0 -0
- {hypernote-0.2.0 → hypernote-0.4.0}/CLAUDE.md +0 -0
- {hypernote-0.2.0 → hypernote-0.4.0}/dev/cli-agent-ergonomics-rollout.md +0 -0
- {hypernote-0.2.0 → hypernote-0.4.0}/src/hypernote/__init__.py +0 -0
- {hypernote-0.2.0 → hypernote-0.4.0}/src/hypernote/actor_ledger.py +0 -0
- {hypernote-0.2.0 → hypernote-0.4.0}/src/hypernote/cli/__init__.py +0 -0
- {hypernote-0.2.0 → hypernote-0.4.0}/src/hypernote/errors.py +0 -0
- {hypernote-0.2.0 → hypernote-0.4.0}/src/hypernote/runtime_manager.py +0 -0
- {hypernote-0.2.0 → hypernote-0.4.0}/src/hypernote/server/__init__.py +0 -0
- {hypernote-0.2.0 → hypernote-0.4.0}/src/hypernote/server/subshell.py +0 -0
- {hypernote-0.2.0 → hypernote-0.4.0}/tests/__init__.py +0 -0
- {hypernote-0.2.0 → hypernote-0.4.0}/tests/helpers.py +0 -0
- {hypernote-0.2.0 → hypernote-0.4.0}/tests/test_actor_ledger.py +0 -0
- {hypernote-0.2.0 → hypernote-0.4.0}/tests/test_browser_regression.py +0 -0
- {hypernote-0.2.0 → hypernote-0.4.0}/tests/test_runtime_manager.py +0 -0
- {hypernote-0.2.0 → hypernote-0.4.0}/tests/test_sdk.py +0 -0
- {hypernote-0.2.0 → hypernote-0.4.0}/tests/test_subshell.py +0 -0
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
version:
|
|
7
|
+
description: "Version to release (e.g., 0.3.0)"
|
|
8
|
+
required: true
|
|
9
|
+
type: string
|
|
10
|
+
publish_to_pypi:
|
|
11
|
+
description: "Publish to PyPI"
|
|
12
|
+
required: true
|
|
13
|
+
default: true
|
|
14
|
+
type: boolean
|
|
15
|
+
create_draft:
|
|
16
|
+
description: "Create as draft release"
|
|
17
|
+
required: false
|
|
18
|
+
default: false
|
|
19
|
+
type: boolean
|
|
20
|
+
push:
|
|
21
|
+
branches:
|
|
22
|
+
- master
|
|
23
|
+
paths:
|
|
24
|
+
- "CHANGELOG.md"
|
|
25
|
+
- "pyproject.toml"
|
|
26
|
+
- "uv.lock"
|
|
27
|
+
- ".github/workflows/release.yml"
|
|
28
|
+
|
|
29
|
+
permissions:
|
|
30
|
+
contents: write
|
|
31
|
+
|
|
32
|
+
jobs:
|
|
33
|
+
resolve-version:
|
|
34
|
+
if: ${{ github.event_name != 'push' || github.actor != 'github-actions[bot]' }}
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
outputs:
|
|
37
|
+
version: ${{ steps.resolve.outputs.version }}
|
|
38
|
+
publish_to_pypi: ${{ steps.resolve.outputs.publish_to_pypi }}
|
|
39
|
+
create_draft: ${{ steps.resolve.outputs.create_draft }}
|
|
40
|
+
should_release: ${{ steps.resolve.outputs.should_release }}
|
|
41
|
+
steps:
|
|
42
|
+
- uses: actions/checkout@v6
|
|
43
|
+
with:
|
|
44
|
+
fetch-depth: 0
|
|
45
|
+
|
|
46
|
+
- name: Resolve release version
|
|
47
|
+
id: resolve
|
|
48
|
+
env:
|
|
49
|
+
INPUT_VERSION: ${{ inputs.version }}
|
|
50
|
+
INPUT_PUBLISH_TO_PYPI: ${{ inputs.publish_to_pypi }}
|
|
51
|
+
INPUT_CREATE_DRAFT: ${{ inputs.create_draft }}
|
|
52
|
+
run: |
|
|
53
|
+
VERSION="$INPUT_VERSION"
|
|
54
|
+
if [ -z "$VERSION" ]; then
|
|
55
|
+
VERSION="$(python - <<'PY'
|
|
56
|
+
import tomllib
|
|
57
|
+
from pathlib import Path
|
|
58
|
+
|
|
59
|
+
print(tomllib.loads(Path("pyproject.toml").read_text())["project"]["version"])
|
|
60
|
+
PY
|
|
61
|
+
)"
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+(\.[a-zA-Z0-9]+)*)?$ ]]; then
|
|
65
|
+
echo "❌ Invalid version format: $VERSION"
|
|
66
|
+
echo "Expected semantic version (e.g., 0.3.0, 0.3.0-alpha.1)"
|
|
67
|
+
exit 1
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
git fetch --tags --force
|
|
71
|
+
TAG="v$VERSION"
|
|
72
|
+
if git rev-parse -q --verify "refs/tags/$TAG" >/dev/null; then
|
|
73
|
+
if [ "$GITHUB_EVENT_NAME" = "push" ] && [ "${GITHUB_RUN_ATTEMPT:-1}" = "1" ]; then
|
|
74
|
+
echo "ℹ️ $TAG already exists; nothing to release."
|
|
75
|
+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
|
76
|
+
echo "publish_to_pypi=false" >> "$GITHUB_OUTPUT"
|
|
77
|
+
echo "create_draft=false" >> "$GITHUB_OUTPUT"
|
|
78
|
+
echo "should_release=false" >> "$GITHUB_OUTPUT"
|
|
79
|
+
exit 0
|
|
80
|
+
fi
|
|
81
|
+
echo "ℹ️ $TAG already exists; continuing because this is a rerun/recovery attempt."
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
echo "✅ Version format is valid: $VERSION"
|
|
85
|
+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
|
86
|
+
echo "publish_to_pypi=${INPUT_PUBLISH_TO_PYPI:-true}" >> "$GITHUB_OUTPUT"
|
|
87
|
+
echo "create_draft=${INPUT_CREATE_DRAFT:-false}" >> "$GITHUB_OUTPUT"
|
|
88
|
+
echo "should_release=true" >> "$GITHUB_OUTPUT"
|
|
89
|
+
|
|
90
|
+
release:
|
|
91
|
+
needs: resolve-version
|
|
92
|
+
if: ${{ needs.resolve-version.outputs.should_release == 'true' }}
|
|
93
|
+
runs-on: ubuntu-latest
|
|
94
|
+
outputs:
|
|
95
|
+
version: ${{ needs.resolve-version.outputs.version }}
|
|
96
|
+
steps:
|
|
97
|
+
- uses: actions/checkout@v6
|
|
98
|
+
with:
|
|
99
|
+
fetch-depth: 0
|
|
100
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
101
|
+
|
|
102
|
+
- uses: astral-sh/setup-uv@v7
|
|
103
|
+
with:
|
|
104
|
+
enable-cache: true
|
|
105
|
+
|
|
106
|
+
- name: Ensure release version is checked in
|
|
107
|
+
env:
|
|
108
|
+
VERSION: ${{ needs.resolve-version.outputs.version }}
|
|
109
|
+
run: |
|
|
110
|
+
CURRENT_VERSION="$(python - <<'PY'
|
|
111
|
+
import tomllib
|
|
112
|
+
from pathlib import Path
|
|
113
|
+
|
|
114
|
+
print(tomllib.loads(Path("pyproject.toml").read_text())["project"]["version"])
|
|
115
|
+
PY
|
|
116
|
+
)"
|
|
117
|
+
|
|
118
|
+
if [ "$CURRENT_VERSION" = "$VERSION" ]; then
|
|
119
|
+
echo "✅ pyproject.toml already declares $VERSION"
|
|
120
|
+
exit 0
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
if [ "$GITHUB_EVENT_NAME" != "workflow_dispatch" ]; then
|
|
124
|
+
echo "❌ pyproject.toml declares $CURRENT_VERSION, expected $VERSION"
|
|
125
|
+
exit 1
|
|
126
|
+
fi
|
|
127
|
+
|
|
128
|
+
sed -i -E "0,/^version = \".*\"/s//version = \"$VERSION\"/" pyproject.toml
|
|
129
|
+
|
|
130
|
+
if ! grep -q "version = \"$VERSION\"" pyproject.toml; then
|
|
131
|
+
echo "❌ Failed to update version in pyproject.toml"
|
|
132
|
+
exit 1
|
|
133
|
+
fi
|
|
134
|
+
|
|
135
|
+
git config user.name "github-actions[bot]"
|
|
136
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
137
|
+
uv lock
|
|
138
|
+
git add pyproject.toml uv.lock
|
|
139
|
+
git commit -m "chore: bump version to v$VERSION"
|
|
140
|
+
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
|
141
|
+
git push origin "$CURRENT_BRANCH"
|
|
142
|
+
echo "✅ Version commit pushed"
|
|
143
|
+
|
|
144
|
+
- name: Build package
|
|
145
|
+
run: |
|
|
146
|
+
rm -rf dist/ build/ *.egg-info/
|
|
147
|
+
uv build
|
|
148
|
+
if [ ! -f dist/*.whl ] || [ ! -f dist/*.tar.gz ]; then
|
|
149
|
+
echo "❌ Build artifacts not found"
|
|
150
|
+
exit 1
|
|
151
|
+
fi
|
|
152
|
+
echo "✅ Package built"
|
|
153
|
+
ls -la dist/
|
|
154
|
+
|
|
155
|
+
- name: Verify package
|
|
156
|
+
run: |
|
|
157
|
+
uv run --isolated --no-project --with dist/*.whl python -c "import hypernote; print('ok')"
|
|
158
|
+
echo "✅ Package verified"
|
|
159
|
+
|
|
160
|
+
- uses: actions/upload-artifact@v6
|
|
161
|
+
with:
|
|
162
|
+
name: dist-${{ needs.resolve-version.outputs.version }}
|
|
163
|
+
path: dist/*
|
|
164
|
+
if-no-files-found: error
|
|
165
|
+
|
|
166
|
+
- name: Run tests
|
|
167
|
+
run: |
|
|
168
|
+
uv run --extra dev playwright install --with-deps chromium
|
|
169
|
+
uv run --extra dev python -m pytest -q
|
|
170
|
+
|
|
171
|
+
- name: Create and push tag
|
|
172
|
+
env:
|
|
173
|
+
VERSION: ${{ needs.resolve-version.outputs.version }}
|
|
174
|
+
run: |
|
|
175
|
+
TAG="v$VERSION"
|
|
176
|
+
git config user.name "github-actions[bot]"
|
|
177
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
178
|
+
git fetch --tags --force
|
|
179
|
+
if git rev-parse -q --verify "refs/tags/$TAG" >/dev/null; then
|
|
180
|
+
TAG_TARGET="$(git rev-list -n 1 "$TAG")"
|
|
181
|
+
HEAD_SHA="$(git rev-parse HEAD)"
|
|
182
|
+
if [ "$TAG_TARGET" = "$HEAD_SHA" ]; then
|
|
183
|
+
echo "✅ $TAG already points at $HEAD_SHA; continuing."
|
|
184
|
+
exit 0
|
|
185
|
+
fi
|
|
186
|
+
echo "❌ $TAG points at $TAG_TARGET, not current HEAD $HEAD_SHA. Refusing to retag."
|
|
187
|
+
exit 1
|
|
188
|
+
fi
|
|
189
|
+
git tag -a "$TAG" -m "Release $TAG"
|
|
190
|
+
git push origin "$TAG"
|
|
191
|
+
echo "✅ Created and pushed tag $TAG"
|
|
192
|
+
|
|
193
|
+
- name: Create GitHub Release
|
|
194
|
+
env:
|
|
195
|
+
GH_TOKEN: ${{ github.token }}
|
|
196
|
+
CREATE_DRAFT: ${{ needs.resolve-version.outputs.create_draft }}
|
|
197
|
+
run: |
|
|
198
|
+
TAG="v${{ needs.resolve-version.outputs.version }}"
|
|
199
|
+
DRAFT_FLAG=""
|
|
200
|
+
if [ "$CREATE_DRAFT" = "true" ]; then
|
|
201
|
+
DRAFT_FLAG="--draft"
|
|
202
|
+
fi
|
|
203
|
+
if gh release view "$TAG" >/dev/null 2>&1; then
|
|
204
|
+
gh release upload "$TAG" dist/* --clobber
|
|
205
|
+
else
|
|
206
|
+
gh release create "$TAG" dist/* \
|
|
207
|
+
--generate-notes \
|
|
208
|
+
--verify-tag \
|
|
209
|
+
$DRAFT_FLAG
|
|
210
|
+
fi
|
|
211
|
+
|
|
212
|
+
- name: Summary
|
|
213
|
+
run: |
|
|
214
|
+
echo "## Release Summary" >> "$GITHUB_STEP_SUMMARY"
|
|
215
|
+
echo "- **Version:** v${{ needs.resolve-version.outputs.version }}" >> "$GITHUB_STEP_SUMMARY"
|
|
216
|
+
echo "- **PyPI:** ${{ needs.resolve-version.outputs.publish_to_pypi }}" >> "$GITHUB_STEP_SUMMARY"
|
|
217
|
+
echo "- **Draft:** ${{ needs.resolve-version.outputs.create_draft }}" >> "$GITHUB_STEP_SUMMARY"
|
|
218
|
+
|
|
219
|
+
publish-pypi:
|
|
220
|
+
needs:
|
|
221
|
+
- resolve-version
|
|
222
|
+
- release
|
|
223
|
+
if: ${{ needs.resolve-version.outputs.publish_to_pypi == 'true' }}
|
|
224
|
+
runs-on: ubuntu-latest
|
|
225
|
+
steps:
|
|
226
|
+
- uses: actions/download-artifact@v5
|
|
227
|
+
with:
|
|
228
|
+
name: dist-${{ needs.resolve-version.outputs.version }}
|
|
229
|
+
path: dist/
|
|
230
|
+
|
|
231
|
+
- uses: astral-sh/setup-uv@v7
|
|
232
|
+
|
|
233
|
+
- name: Publish to PyPI
|
|
234
|
+
env:
|
|
235
|
+
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
|
|
236
|
+
run: uv publish
|
|
@@ -37,11 +37,10 @@ Hypernote owns a thin control plane:
|
|
|
37
37
|
- Jupyter extension wiring in [src/hypernote/server/extension.py](src/hypernote/server/extension.py)
|
|
38
38
|
- ephemeral job and attribution ledger in [src/hypernote/actor_ledger.py](src/hypernote/actor_ledger.py)
|
|
39
39
|
- subshell-aware execute/interrupt/restart in [src/hypernote/server/subshell.py](src/hypernote/server/subshell.py)
|
|
40
|
-
- optional VS Code embedding surface in [vscode-extension/src/extension.ts](vscode-extension/src/extension.ts)
|
|
41
40
|
|
|
42
41
|
Core rule: notebook edits and execution must operate on one logical document truth whether JupyterLab is closed, already open, or opened mid-run.
|
|
43
42
|
|
|
44
|
-
Lifecycle rule: notebook contents and outputs persist through Jupyter's `.ipynb` model, but Hypernote's runtime state, job records,
|
|
43
|
+
Lifecycle rule: notebook contents and outputs persist through Jupyter's `.ipynb` model, but Hypernote's runtime state, job records, cell attribution, and `setup serve` collaboration journal are intentionally ephemeral and notebook- or server-scoped.
|
|
45
44
|
|
|
46
45
|
Concurrent-actor rule: JupyterLab and Hypernote share one notebook session and one kernel. Hypernote-driven cells run in an ipykernel subshell so the kernel's main shell stays responsive to native Lab actions. Hypernote's extension overrides `/api/kernels/{id}/interrupt` and `/api/kernels/{id}/restart` so Lab's Stop and Restart toolbar buttons reach the subshell-routed cell or perform the right cleanup. See [dev/current-architecture.md](dev/current-architecture.md) for the full mechanism.
|
|
47
46
|
|
|
@@ -80,7 +79,7 @@ Default CLI contract:
|
|
|
80
79
|
- non-TTY: one compact final JSON result
|
|
81
80
|
- explicit streaming only through `--watch` or `--stream-json`
|
|
82
81
|
- summary-first read payloads should come from SDK-backed observation helpers, not CLI-only formatting rules
|
|
83
|
-
- `setup serve` is the default local bootstrap path for a Hypernote-enabled
|
|
82
|
+
- `setup serve` is the default local bootstrap path for a Hypernote-enabled JupyterLab server
|
|
84
83
|
- `setup doctor --path PATH` is the preferred first diagnostic when server reachability,
|
|
85
84
|
kernelspec selection, or runtime mismatch is unclear
|
|
86
85
|
|
|
@@ -100,23 +99,17 @@ Default CLI contract:
|
|
|
100
99
|
- Normalize boundary inputs early. If upstream payloads can arrive in more than one valid shape, accept and normalize them at the adapter boundary rather than assuming a single representation.
|
|
101
100
|
- Prefer unique notebook paths in tests and demos. Browser tests must also use unique JupyterLab workspace URLs.
|
|
102
101
|
- Keep `tmp/` disposable. Durable notes belong in `docs/` or `dev/`, not `tmp/`.
|
|
102
|
+
- Release every version through a PR (CHANGELOG move + version bump + lockfile refresh on a `release/vX.Y.Z` branch), never via direct push to master. The full process is in [dev/release.md](dev/release.md).
|
|
103
103
|
|
|
104
104
|
## Read These First
|
|
105
105
|
|
|
106
106
|
- [SKILL.md](SKILL.md)
|
|
107
107
|
- [docs/README.md](docs/README.md)
|
|
108
108
|
- [dev/README.md](dev/README.md)
|
|
109
|
+
- [dev/release.md](dev/release.md)
|
|
109
110
|
|
|
110
111
|
## If You Are Editing...
|
|
111
112
|
|
|
112
|
-
### `vscode-extension/*`
|
|
113
|
-
|
|
114
|
-
- keep the extension decoupled from Hypernote-specific notebook semantics
|
|
115
|
-
- prefer embedding JupyterLab over recreating notebook behavior in VS Code
|
|
116
|
-
- if the extension launches Jupyter itself, keep that process local, explicit, and easy to inspect
|
|
117
|
-
- update [docs/vscode-extension.md](docs/vscode-extension.md)
|
|
118
|
-
- update [dev/vscode-extension.md](dev/vscode-extension.md)
|
|
119
|
-
|
|
120
113
|
### `src/hypernote/sdk.py` or `src/hypernote/errors.py`
|
|
121
114
|
|
|
122
115
|
- preserve the notebook-first public object model
|
|
@@ -155,14 +148,19 @@ Default CLI contract:
|
|
|
155
148
|
- alternate valid input shapes from upstream payloads
|
|
156
149
|
- parity between real helpers and any fake/test-double implementations
|
|
157
150
|
|
|
151
|
+
### `pyproject.toml` version, `CHANGELOG.md`, or `.github/workflows/release.yml`
|
|
152
|
+
|
|
153
|
+
- always use the PR-based release process in [dev/release.md](dev/release.md)
|
|
154
|
+
- do not push release-prep commits directly to master, even for a one-line version bump
|
|
155
|
+
- before opening the release PR, confirm `git ls-tree origin/master` shows every file mentioned in the new CHANGELOG section — local-only work must not be claimed in the changelog
|
|
156
|
+
- if you change the release workflow shape (steps, secrets, version source), update [dev/release.md](dev/release.md) in the same PR so the doc stays accurate
|
|
157
|
+
|
|
158
158
|
## Verification
|
|
159
159
|
|
|
160
160
|
Install guidance:
|
|
161
161
|
|
|
162
162
|
- `uv sync`
|
|
163
|
-
-
|
|
164
|
-
- `uv sync --extra lab`
|
|
165
|
-
- adds the collaborative JupyterLab bundle
|
|
163
|
+
- Hypernote's default JupyterLab integration stack
|
|
166
164
|
- `uv sync --extra dev`
|
|
167
165
|
- adds local development, lint, test, and browser-validation tooling
|
|
168
166
|
|
|
@@ -4,6 +4,46 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 0.4.0 - 2026-05-10
|
|
8
|
+
|
|
9
|
+
Hypernote now treats Jupyter's real-time collaboration journal as temporary
|
|
10
|
+
server-local state for `setup serve`, keeping the `.ipynb` notebook file as the
|
|
11
|
+
only durable project artifact.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- `hypernote setup serve` now configures Jupyter RTC to use temporary
|
|
16
|
+
collaboration journal storage instead of Jupyter's default project-root
|
|
17
|
+
`.jupyter_ystore.db` SQLite database.
|
|
18
|
+
- Live-server and browser regression fixtures now launch with the same
|
|
19
|
+
temporary journal policy as `setup serve`, including coverage that notebook
|
|
20
|
+
execution does not create `.jupyter_ystore.db` in the server root.
|
|
21
|
+
- Project guidance now distinguishes the durable **Notebook File** from the
|
|
22
|
+
temporary **Collaboration Journal**, and documents the crash-recovery tradeoff
|
|
23
|
+
for unsaved live shared-document changes.
|
|
24
|
+
|
|
25
|
+
## 0.3.0 - 2026-05-10
|
|
26
|
+
|
|
27
|
+
Hypernote is now a JupyterLab-first integration: the default install carries the
|
|
28
|
+
collaboration/docprovider stack, `setup serve` opens Lab by default, and
|
|
29
|
+
`setup doctor` can distinguish API reachability from shared-document and Lab
|
|
30
|
+
frontend health.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- Hypernote is now packaged and documented as a JupyterLab-first integration:
|
|
35
|
+
the default install includes JupyterLab collaboration support, `setup serve`
|
|
36
|
+
opens Lab by default, `setup doctor` reports the shared-document stack and
|
|
37
|
+
duplicate local servers, and cell-state operations require the shared
|
|
38
|
+
document path instead of falling back to contents-manager edits.
|
|
39
|
+
|
|
40
|
+
### Notes
|
|
41
|
+
|
|
42
|
+
- correction: the 0.2.0 headline mentions "an experimental VS Code extension" but the
|
|
43
|
+
`vscode-extension/` work was never committed and did not ship in the 0.2.0 artifact.
|
|
44
|
+
Documentation referring to the VS Code extension has been removed from `README.md`,
|
|
45
|
+
`AGENTS.md`, `SKILL.md`, `docs/README.md`, `dev/README.md`, and `dev/module-map.md`.
|
|
46
|
+
|
|
7
47
|
## 0.2.0 - 2026-05-07
|
|
8
48
|
|
|
9
49
|
Native JupyterLab as a first-class concurrent actor: open a notebook
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Hypernote
|
|
2
|
+
|
|
3
|
+
Hypernote coordinates notebook execution through a Hypernote-enabled JupyterLab
|
|
4
|
+
server so agents and humans can work against one notebook truth.
|
|
5
|
+
|
|
6
|
+
## Language
|
|
7
|
+
|
|
8
|
+
**Shared Document**:
|
|
9
|
+
The server-side notebook document that all Hypernote operations use as the live notebook truth.
|
|
10
|
+
_Avoid_: file-only notebook truth
|
|
11
|
+
|
|
12
|
+
**Notebook File**:
|
|
13
|
+
The `.ipynb` artifact that persists notebook contents and outputs after the Shared Document is saved.
|
|
14
|
+
_Avoid_: Hypernote database, collaboration store, job history
|
|
15
|
+
|
|
16
|
+
**Collaboration Journal**:
|
|
17
|
+
The Jupyter real-time collaboration update store used as recoverability cache for live Shared Document state.
|
|
18
|
+
_Avoid_: notebook primary storage, Hypernote job history, attribution store
|
|
19
|
+
|
|
20
|
+
**Hypernote JupyterLab Server**:
|
|
21
|
+
A JupyterLab server launched or verified with Hypernote's required server and collaboration extensions.
|
|
22
|
+
_Avoid_: plain Jupyter server, separate agent server
|
|
23
|
+
|
|
24
|
+
**Open Lab Tab**:
|
|
25
|
+
A browser tab viewing a notebook through the Hypernote JupyterLab Server.
|
|
26
|
+
_Avoid_: separate Lab server, plain Lab tab
|
|
27
|
+
|
|
28
|
+
**Agent Automation**:
|
|
29
|
+
CLI or SDK notebook work performed through the Hypernote JupyterLab Server, whether an Open Lab Tab currently exists.
|
|
30
|
+
_Avoid_: separate runtime mode
|
|
31
|
+
|
|
32
|
+
## Relationships
|
|
33
|
+
|
|
34
|
+
- A **Hypernote JupyterLab Server** owns the **Shared Document**.
|
|
35
|
+
- A **Shared Document** saves durable notebook contents and outputs into one **Notebook File**.
|
|
36
|
+
- A **Collaboration Journal** is temporary server-local state; Hypernote does not make it a durable project artifact or product choice.
|
|
37
|
+
- An **Open Lab Tab** and **Agent Automation** must attach to the same **Hypernote JupyterLab Server**.
|
|
38
|
+
- **Agent Automation** does not require an **Open Lab Tab**, but it still requires the **Hypernote JupyterLab Server**.
|
|
39
|
+
|
|
40
|
+
## Example Dialogue
|
|
41
|
+
|
|
42
|
+
> **Dev:** "Can agents run notebooks without JupyterLab?"
|
|
43
|
+
> **Domain expert:** "No separate mode: agents use the **Hypernote JupyterLab Server** even if nobody has an **Open Lab Tab**."
|
|
44
|
+
>
|
|
45
|
+
> **Dev:** "Is the collaboration database part of Hypernote's durable state?"
|
|
46
|
+
> **Domain expert:** "No — durability means the **Shared Document** has saved back to the **Notebook File**."
|
|
47
|
+
|
|
48
|
+
## Flagged Ambiguities
|
|
49
|
+
|
|
50
|
+
- Agent work without an **Open Lab Tab** was previously described as a separate product mode; resolved: Hypernote only distinguishes whether an **Open Lab Tab** exists.
|
|
51
|
+
- "Jupyter server" was used broadly; resolved: the supported product server is a **Hypernote JupyterLab Server**.
|
|
52
|
+
- Jupyter's real-time collaboration store was treated as possible Hypernote state; resolved: it is a **Collaboration Journal**, not primary notebook storage or Hypernote job history.
|
|
53
|
+
- Persistent collaboration-store configuration was considered as a user-facing choice; resolved: Hypernote treats the **Collaboration Journal** as temporary server-local state only.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hypernote
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Thin control plane for Jupyter notebook execution with jobs, attribution, and runtime lifecycle
|
|
5
5
|
Project-URL: Homepage, https://github.com/gilad-rubin/hypernote
|
|
6
6
|
Project-URL: Repository, https://github.com/gilad-rubin/hypernote
|
|
@@ -8,37 +8,37 @@ Project-URL: Issues, https://github.com/gilad-rubin/hypernote/issues
|
|
|
8
8
|
Requires-Python: >=3.11
|
|
9
9
|
Requires-Dist: click>=8.0
|
|
10
10
|
Requires-Dist: httpx>=0.27
|
|
11
|
+
Requires-Dist: jupyter-collaboration>=3.0
|
|
12
|
+
Requires-Dist: jupyter-docprovider>=2.0
|
|
11
13
|
Requires-Dist: jupyter-server-nbmodel>=0.1
|
|
12
14
|
Requires-Dist: jupyter-server-ydoc>=1.0
|
|
13
15
|
Requires-Dist: jupyter-server>=2.0
|
|
16
|
+
Requires-Dist: jupyterlab>=4.0
|
|
14
17
|
Requires-Dist: pycrdt>=0.12
|
|
15
18
|
Provides-Extra: dev
|
|
16
|
-
Requires-Dist: jupyter-collaboration>=3.0; extra == 'dev'
|
|
17
|
-
Requires-Dist: jupyterlab>=4.0; extra == 'dev'
|
|
18
19
|
Requires-Dist: playwright>=1.40; extra == 'dev'
|
|
19
20
|
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
|
|
20
21
|
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
|
|
21
22
|
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
22
23
|
Requires-Dist: ruff>=0.8; extra == 'dev'
|
|
23
|
-
Provides-Extra: lab
|
|
24
|
-
Requires-Dist: jupyter-collaboration>=3.0; extra == 'lab'
|
|
25
24
|
Description-Content-Type: text/markdown
|
|
26
25
|
|
|
27
26
|
# Hypernote
|
|
28
27
|
|
|
29
|
-
- **
|
|
28
|
+
- **JupyterLab-first** - Hypernote is a thin execution control plane for a Hypernote-enabled JupyterLab server.
|
|
30
29
|
- **One notebook truth** - notebook edits, execution, and late-open JupyterLab views all operate on the same logical document.
|
|
31
30
|
- **Agent-first surface** - the Python SDK is primary, and the CLI is a thin shell over it.
|
|
32
31
|
- **Ephemeral control plane** - Jupyter owns durable `.ipynb` contents and outputs; Hypernote owns in-memory runtimes, jobs, and attribution.
|
|
32
|
+
- **Temporary collaboration journal** - `setup serve` keeps Jupyter RTC updates in server-local temp storage, not repo-root databases.
|
|
33
33
|
|
|
34
34
|
## What it ships
|
|
35
35
|
|
|
36
36
|
- notebook-first SDK in `src/hypernote/sdk.py`
|
|
37
37
|
- agent-first CLI in `src/hypernote/cli/main.py`
|
|
38
38
|
- Jupyter server extension for execution and runtime control
|
|
39
|
-
-
|
|
39
|
+
- subshell-routed execute, interrupt, and restart so JupyterLab stays usable while Hypernote is running cells
|
|
40
40
|
- notebook-scoped runtime lifecycle with attach, detach, recovery, and stop
|
|
41
|
-
- job polling and `input()` round-trips for
|
|
41
|
+
- job polling and `input()` round-trips for agent automation without requiring an open Lab tab
|
|
42
42
|
- live-server and browser regression coverage for shared-document behavior
|
|
43
43
|
|
|
44
44
|
## Quick start
|
|
@@ -56,23 +56,18 @@ uv run hypernote status tmp/demo.ipynb --full
|
|
|
56
56
|
For another repo's environment, install Hypernote there (`uv add hypernote --dev`) and run
|
|
57
57
|
the same bootstrap command from that repo.
|
|
58
58
|
|
|
59
|
-
## Install
|
|
59
|
+
## Install
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
- use this when you want the full collaborative JupyterLab experience
|
|
67
|
-
- `hypernote[dev]`
|
|
68
|
-
- adds test, lint, browser, and local dev tooling
|
|
69
|
-
- use this for local development and CI
|
|
61
|
+
The default install includes the JupyterLab integration stack Hypernote needs:
|
|
62
|
+
JupyterLab, shared-document support, server-side notebook execution, and the
|
|
63
|
+
collaboration/docprovider frontend packages.
|
|
64
|
+
|
|
65
|
+
Use `hypernote[dev]` only for local development and CI tooling.
|
|
70
66
|
|
|
71
67
|
Examples:
|
|
72
68
|
|
|
73
69
|
```bash
|
|
74
70
|
uv sync
|
|
75
|
-
uv sync --extra lab
|
|
76
71
|
uv sync --extra dev
|
|
77
72
|
```
|
|
78
73
|
|
|
@@ -82,6 +77,7 @@ Jupyter owns:
|
|
|
82
77
|
|
|
83
78
|
- notebook persistence
|
|
84
79
|
- shared YDoc document state
|
|
80
|
+
- temporary collaboration journal state for live RTC updates
|
|
85
81
|
- kernel and session primitives
|
|
86
82
|
- notebook rendering in JupyterLab
|
|
87
83
|
|
|
@@ -105,16 +101,7 @@ Hypernote owns:
|
|
|
105
101
|
- [CLI Reference](docs/cli.md)
|
|
106
102
|
- [SDK Reference](docs/sdk.md)
|
|
107
103
|
- [Runtime Model](docs/runtime-model.md)
|
|
108
|
-
- [
|
|
109
|
-
|
|
110
|
-
## VS Code
|
|
111
|
-
|
|
112
|
-
The repository now includes a minimal VS Code extension under `vscode-extension/`.
|
|
113
|
-
|
|
114
|
-
- It embeds JupyterLab inside a VS Code custom editor or panel.
|
|
115
|
-
- It can reuse an existing Jupyter server via settings.
|
|
116
|
-
- If no server is reachable, it can start a managed local `jupyter lab` process.
|
|
117
|
-
- It stays decoupled from Hypernote-specific UI so Hypernote can connect to the same server separately.
|
|
104
|
+
- [Browser Regression Spec](docs/browser-regression-spec.md)
|
|
118
105
|
|
|
119
106
|
## Verification
|
|
120
107
|
|
|
@@ -128,11 +115,3 @@ uv sync --extra dev
|
|
|
128
115
|
uv run ruff check src/hypernote tests
|
|
129
116
|
uv run python -m pytest -q
|
|
130
117
|
```
|
|
131
|
-
|
|
132
|
-
Extension build:
|
|
133
|
-
|
|
134
|
-
```bash
|
|
135
|
-
cd vscode-extension
|
|
136
|
-
npm install
|
|
137
|
-
npm run compile
|
|
138
|
-
```
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
# Hypernote
|
|
2
2
|
|
|
3
|
-
- **
|
|
3
|
+
- **JupyterLab-first** - Hypernote is a thin execution control plane for a Hypernote-enabled JupyterLab server.
|
|
4
4
|
- **One notebook truth** - notebook edits, execution, and late-open JupyterLab views all operate on the same logical document.
|
|
5
5
|
- **Agent-first surface** - the Python SDK is primary, and the CLI is a thin shell over it.
|
|
6
6
|
- **Ephemeral control plane** - Jupyter owns durable `.ipynb` contents and outputs; Hypernote owns in-memory runtimes, jobs, and attribution.
|
|
7
|
+
- **Temporary collaboration journal** - `setup serve` keeps Jupyter RTC updates in server-local temp storage, not repo-root databases.
|
|
7
8
|
|
|
8
9
|
## What it ships
|
|
9
10
|
|
|
10
11
|
- notebook-first SDK in `src/hypernote/sdk.py`
|
|
11
12
|
- agent-first CLI in `src/hypernote/cli/main.py`
|
|
12
13
|
- Jupyter server extension for execution and runtime control
|
|
13
|
-
-
|
|
14
|
+
- subshell-routed execute, interrupt, and restart so JupyterLab stays usable while Hypernote is running cells
|
|
14
15
|
- notebook-scoped runtime lifecycle with attach, detach, recovery, and stop
|
|
15
|
-
- job polling and `input()` round-trips for
|
|
16
|
+
- job polling and `input()` round-trips for agent automation without requiring an open Lab tab
|
|
16
17
|
- live-server and browser regression coverage for shared-document behavior
|
|
17
18
|
|
|
18
19
|
## Quick start
|
|
@@ -30,23 +31,18 @@ uv run hypernote status tmp/demo.ipynb --full
|
|
|
30
31
|
For another repo's environment, install Hypernote there (`uv add hypernote --dev`) and run
|
|
31
32
|
the same bootstrap command from that repo.
|
|
32
33
|
|
|
33
|
-
## Install
|
|
34
|
+
## Install
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
- use this when you want the full collaborative JupyterLab experience
|
|
41
|
-
- `hypernote[dev]`
|
|
42
|
-
- adds test, lint, browser, and local dev tooling
|
|
43
|
-
- use this for local development and CI
|
|
36
|
+
The default install includes the JupyterLab integration stack Hypernote needs:
|
|
37
|
+
JupyterLab, shared-document support, server-side notebook execution, and the
|
|
38
|
+
collaboration/docprovider frontend packages.
|
|
39
|
+
|
|
40
|
+
Use `hypernote[dev]` only for local development and CI tooling.
|
|
44
41
|
|
|
45
42
|
Examples:
|
|
46
43
|
|
|
47
44
|
```bash
|
|
48
45
|
uv sync
|
|
49
|
-
uv sync --extra lab
|
|
50
46
|
uv sync --extra dev
|
|
51
47
|
```
|
|
52
48
|
|
|
@@ -56,6 +52,7 @@ Jupyter owns:
|
|
|
56
52
|
|
|
57
53
|
- notebook persistence
|
|
58
54
|
- shared YDoc document state
|
|
55
|
+
- temporary collaboration journal state for live RTC updates
|
|
59
56
|
- kernel and session primitives
|
|
60
57
|
- notebook rendering in JupyterLab
|
|
61
58
|
|
|
@@ -79,16 +76,7 @@ Hypernote owns:
|
|
|
79
76
|
- [CLI Reference](docs/cli.md)
|
|
80
77
|
- [SDK Reference](docs/sdk.md)
|
|
81
78
|
- [Runtime Model](docs/runtime-model.md)
|
|
82
|
-
- [
|
|
83
|
-
|
|
84
|
-
## VS Code
|
|
85
|
-
|
|
86
|
-
The repository now includes a minimal VS Code extension under `vscode-extension/`.
|
|
87
|
-
|
|
88
|
-
- It embeds JupyterLab inside a VS Code custom editor or panel.
|
|
89
|
-
- It can reuse an existing Jupyter server via settings.
|
|
90
|
-
- If no server is reachable, it can start a managed local `jupyter lab` process.
|
|
91
|
-
- It stays decoupled from Hypernote-specific UI so Hypernote can connect to the same server separately.
|
|
79
|
+
- [Browser Regression Spec](docs/browser-regression-spec.md)
|
|
92
80
|
|
|
93
81
|
## Verification
|
|
94
82
|
|
|
@@ -102,11 +90,3 @@ uv sync --extra dev
|
|
|
102
90
|
uv run ruff check src/hypernote tests
|
|
103
91
|
uv run python -m pytest -q
|
|
104
92
|
```
|
|
105
|
-
|
|
106
|
-
Extension build:
|
|
107
|
-
|
|
108
|
-
```bash
|
|
109
|
-
cd vscode-extension
|
|
110
|
-
npm install
|
|
111
|
-
npm run compile
|
|
112
|
-
```
|