workstate-bootstrap 0.5.2__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.
- workstate_bootstrap-0.5.2/.gitignore +8 -0
- workstate_bootstrap-0.5.2/CHANGELOG.md +240 -0
- workstate_bootstrap-0.5.2/PKG-INFO +179 -0
- workstate_bootstrap-0.5.2/README.md +160 -0
- workstate_bootstrap-0.5.2/pyproject.toml +36 -0
- workstate_bootstrap-0.5.2/src/workstate_bootstrap/__init__.py +6 -0
- workstate_bootstrap-0.5.2/src/workstate_bootstrap/__main__.py +5 -0
- workstate_bootstrap-0.5.2/src/workstate_bootstrap/cli.py +610 -0
- workstate_bootstrap-0.5.2/src/workstate_bootstrap/install.py +2057 -0
- workstate_bootstrap-0.5.2/src/workstate_bootstrap/mcp_sync.py +293 -0
- workstate_bootstrap-0.5.2/src/workstate_bootstrap/subcommands.py +1358 -0
- workstate_bootstrap-0.5.2/tests/__init__.py +5 -0
- workstate_bootstrap-0.5.2/tests/test_bootstrap_install_rehearsal.py +479 -0
- workstate_bootstrap-0.5.2/tests/test_cli_profile.py +200 -0
- workstate_bootstrap-0.5.2/tests/test_doctor_repair_sync.py +235 -0
- workstate_bootstrap-0.5.2/tests/test_ensure_hooks_path_make.py +98 -0
- workstate_bootstrap-0.5.2/tests/test_install.py +2499 -0
- workstate_bootstrap-0.5.2/tests/test_install_manifest_walker.py +780 -0
- workstate_bootstrap-0.5.2/tests/test_install_profile_all_lifecycle.py +147 -0
- workstate_bootstrap-0.5.2/tests/test_install_profiles.py +275 -0
- workstate_bootstrap-0.5.2/tests/test_manifest_build.py +89 -0
- workstate_bootstrap-0.5.2/tests/test_mcp_sync_cli.py +258 -0
- workstate_bootstrap-0.5.2/tests/test_mcp_sync_e2e.py +212 -0
- workstate_bootstrap-0.5.2/tests/test_mcp_sync_malformed.py +185 -0
- workstate_bootstrap-0.5.2/tests/test_mcp_sync_prune.py +210 -0
- workstate_bootstrap-0.5.2/tests/test_mcp_sync_unit.py +181 -0
- workstate_bootstrap-0.5.2/tests/test_package_metadata.py +51 -0
- workstate_bootstrap-0.5.2/tests/test_render_seam.py +130 -0
- workstate_bootstrap-0.5.2/tests/test_root_visible_task_plans.py +164 -0
- workstate_bootstrap-0.5.2/tests/test_subcommands.py +1765 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# Changelog — workstate-bootstrap
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## [0.5.2] — 2026-05-20
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- **Bump the default managed handoff server pin** to
|
|
10
|
+
`mcp-workstate-handoff@0.11.5` so fresh `workstate-bootstrap install`
|
|
11
|
+
dogfood installs pick up the `ACTIVE TASK PLANS` task-plan-path fix by
|
|
12
|
+
default. `mcp-workstate-orchestrator` remains pinned at `0.4.7`.
|
|
13
|
+
|
|
14
|
+
## [0.5.1] — 2026-05-11
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- **WORKSTATE-REF-57 — stale shared-surface symlinks now repointed on rerun.**
|
|
19
|
+
When a consumer was installed pre-v0.2.0 (legacy root layout
|
|
20
|
+
`<clone>/<surface>`) and the layout subsequently moved into
|
|
21
|
+
`<clone>/packages/workstate-system/<surface>`, the target-side
|
|
22
|
+
`scripts/hooks -> ../.agentic/remote/scripts/hooks` symlink survived
|
|
23
|
+
every subsequent `workstate-bootstrap install` because the pre-fix
|
|
24
|
+
`points_into_clone` check still passed lexically for the broken
|
|
25
|
+
resolved path. `_materialize_surfaces` now classifies each existing
|
|
26
|
+
symlink into three buckets — resolves-to-expected (shared,
|
|
27
|
+
idempotent), lexically inside our remote subtree but stale-or-broken
|
|
28
|
+
(repointed to the canonical target, audited to stdout as
|
|
29
|
+
`repointed: <surface>`), and foreign (preserved as local override).
|
|
30
|
+
The lexical containment check uses `os.readlink` +
|
|
31
|
+
`os.path.normpath` so broken targets are classified without raising
|
|
32
|
+
during `Path.resolve(strict=True)`.
|
|
33
|
+
|
|
34
|
+
## [0.5.0] — 2026-05-10
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
|
|
38
|
+
- **WORKSTATE-REF-56 — cross-harness install manifest is now the single source of
|
|
39
|
+
truth for hook adapter wiring.** `config/agent-workflows/portable_commands.json`
|
|
40
|
+
schema v2 introduces a top-level `hooks[]` array; install dispatches
|
|
41
|
+
adapter rows through a manifest-driven walker (closed-set operation
|
|
42
|
+
table) instead of bespoke per-harness writers. New harnesses (Codex,
|
|
43
|
+
VS Code, …) are onboarded by appending adapter rows.
|
|
44
|
+
- **CLI default profile flips back to `all`** so a no-argument
|
|
45
|
+
`workstate-bootstrap install` materializes the full surface set out of
|
|
46
|
+
the box — per-agent generated surfaces (`.claude/skills`,
|
|
47
|
+
`.claude/commands`, `.github/prompts`, `.codex/skills`), shared
|
|
48
|
+
overlay symlinks (`scripts/hooks`, `Makefile.d`, `scripts/workstate`,
|
|
49
|
+
…), and the lifecycle hoist (`Makefile.d/lifecycle.mk` plus the
|
|
50
|
+
sentinel-bracketed `-include` block). `--profile minimal` and
|
|
51
|
+
`--profile lifecycle` remain opt-in for lean installs. The library
|
|
52
|
+
`install()` API has always defaulted to `"all"`; this realigns the
|
|
53
|
+
two layers.
|
|
54
|
+
- **The install manifest (`.workstate-bootstrap.json`) now records the
|
|
55
|
+
active profile** under `manifest["profile"]` so downstream tools
|
|
56
|
+
(`sync`, `doctor`, rehearsals) can reason about what the consumer
|
|
57
|
+
installed without re-inferring it from the surface set.
|
|
58
|
+
- **Stop-hook wiring is fully opt-in across every harness shipped by
|
|
59
|
+
the manifest.** The legacy `--harness-hook-scope` flag is replaced by
|
|
60
|
+
four boolean flags: `--install-claude-stop-hook` (shared, checked-in
|
|
61
|
+
`.claude/settings.json`), `--install-claude-stop-hook-local`
|
|
62
|
+
(user-owned, gitignored `.claude/settings.local.json`),
|
|
63
|
+
`--install-codex-stop-hook` (`.codex/hooks/stop.json`), and
|
|
64
|
+
`--install-vscode-stop-hook` (`.vscode/agentic-stop-hooks.json`).
|
|
65
|
+
All four default off — no file is touched unless the operator
|
|
66
|
+
explicitly opts in. The library `install()` API surfaces the same
|
|
67
|
+
switches as `install_claude_stop_hook` / `install_claude_stop_hook_local`
|
|
68
|
+
/ `install_codex_stop_hook` / `install_vscode_stop_hook`.
|
|
69
|
+
|
|
70
|
+
## [0.4.2] — 2026-05-10
|
|
71
|
+
|
|
72
|
+
### Changed
|
|
73
|
+
|
|
74
|
+
- **Bump default managed MCP server pins** to `mcp-workstate-handoff@0.11.1`
|
|
75
|
+
and `mcp-workstate-orchestrator@0.4.5` so consumer repos pick up the
|
|
76
|
+
WORKSTATE-REF-54 (multi-active CURRENT_TASK projection, import/export
|
|
77
|
+
malformed-payload rejection, target_branch/worktree_path/plan_path
|
|
78
|
+
preservation) and WORKSTATE-REF-55 (compaction env-var namespace
|
|
79
|
+
consolidation under `AGENT_HANDOFF_COMPACTION_*` with `WORKSTATE_*` kept
|
|
80
|
+
as a deprecated alias) fixes by default.
|
|
81
|
+
|
|
82
|
+
## [0.4.1] — 2026-05-09
|
|
83
|
+
|
|
84
|
+
### Fixed
|
|
85
|
+
|
|
86
|
+
- **`--profile all` now performs the lifecycle hoist** (WORKSTATE-REF-48). The
|
|
87
|
+
legacy default profile shipped lifecycle-referencing skills
|
|
88
|
+
(`branch-lifecycle`, `tdd`, `incremental-implementation`,
|
|
89
|
+
`branch-review`, `handoff-lifecycle`) but did not install the
|
|
90
|
+
matching `Makefile.d/lifecycle.mk` and
|
|
91
|
+
`scripts/workstate/lifecycle/` runner that those skills' `make
|
|
92
|
+
task-start` / `make slice-start` / `make context` /
|
|
93
|
+
`make review-ready` / `make handoff-close-check` /
|
|
94
|
+
`make format-all` references resolve through. Consumer repos
|
|
95
|
+
bootstrapped under `--profile all` now receive the runner and the
|
|
96
|
+
sentinel-bracketed `-include Makefile.d/*.mk` directive, so the
|
|
97
|
+
skill manifest and the make graph stay aligned.
|
|
98
|
+
|
|
99
|
+
### Changed
|
|
100
|
+
|
|
101
|
+
- **Default managed MCP servers are now version-pinned.** The built-in
|
|
102
|
+
`--mcp-servers default` map writes `uvx mcp-workstate-handoff@0.11.0` and
|
|
103
|
+
`uvx mcp-workstate-orchestrator@0.4.4` (rather than unpinned `uvx
|
|
104
|
+
mcp-workstate-handoff` / `uvx mcp-workstate-orchestrator`) so consumer repos
|
|
105
|
+
do not silently drift when PyPI advances independently of the overlay
|
|
106
|
+
tag they bootstrapped against. Operators wanting a different pin
|
|
107
|
+
continue to pass `--mcp-servers <path>`.
|
|
108
|
+
- **Raise `workstate-protocol` lower bound to `>=0.1.4,<0.2.0`** to match
|
|
109
|
+
the floor pinned by `mcp-workstate-handoff` 0.11.0 and
|
|
110
|
+
`mcp-workstate-orchestrator` 0.4.4 — the two packages bootstrap launches
|
|
111
|
+
via `uvx` — so the bootstrap venv cannot resolve a protocol release
|
|
112
|
+
older than what those servers import at startup.
|
|
113
|
+
|
|
114
|
+
## [0.4.0] — 2026-05-04
|
|
115
|
+
|
|
116
|
+
### Added
|
|
117
|
+
|
|
118
|
+
- **Install profile contract: `--profile {minimal,lifecycle,all}`**
|
|
119
|
+
(implementation note / WORKSTATE-REF-40 implementation note.5.a). The CLI now accepts an explicit
|
|
120
|
+
install profile flag and honors it across the manifest layers, so
|
|
121
|
+
consumer repos can pick a smaller hoist surface than the default.
|
|
122
|
+
- **Hoist `Makefile.d/plans.mk` + `git-plan-cat.sh` stub** (implementation note /
|
|
123
|
+
WORKSTATE-REF-38 implementation note). Consumer repos installed via `workstate-bootstrap`
|
|
124
|
+
pick up `make plan-show / plan-edit / plans-list / plan-register`
|
|
125
|
+
out of the box; the targets shell out to `uvx mcp-workstate-handoff`
|
|
126
|
+
under the hood.
|
|
127
|
+
|
|
128
|
+
### Changed
|
|
129
|
+
|
|
130
|
+
- Bootstrap installs and rehearsals are validated against
|
|
131
|
+
`mcp-workstate-handoff>=0.8.0` (the version that ships the
|
|
132
|
+
`plan_resolve` / `plan_cli` surface targeted by the new make
|
|
133
|
+
recipes).
|
|
134
|
+
|
|
135
|
+
## [0.3.1] — 2026-05-03
|
|
136
|
+
|
|
137
|
+
- **implementation note BR-01 — raise `workstate-protocol` lower bound to
|
|
138
|
+
`>=0.1.2,<0.2.0`.** Bootstrap's default install path invokes
|
|
139
|
+
`uvx mcp-workstate-handoff`, which imports `workstate_protocol.branch_naming`
|
|
140
|
+
at startup; the previous `>=0.1.0` floor let `uvx` resolve a protocol
|
|
141
|
+
release missing the module, crashing init-state on a fresh install. A
|
|
142
|
+
new packaging test (`tests/test_package_metadata.py`) pins the floor
|
|
143
|
+
so the declaration cannot silently drift back below the contract.
|
|
144
|
+
- **implementation note implementation note — install rehearsal pins six-hook surface +
|
|
145
|
+
helper materialization.** `SHARED_GIT_HOOK_NAMES` now includes
|
|
146
|
+
`pre-commit` (in addition to `post-checkout`, `post-commit`,
|
|
147
|
+
`post-merge`, `post-rewrite`, `pre-push`); the install rehearsal
|
|
148
|
+
test asserts that `core.hooksPath` resolves to the directory
|
|
149
|
+
carrying all six executable hook scripts AND that the Python helper
|
|
150
|
+
`scripts/hooks/check_branch_naming.py` (the delegate the
|
|
151
|
+
post-checkout / pre-commit / pre-push hooks `exec`) is materialized
|
|
152
|
+
alongside them. Without the helper, every branch-naming gate
|
|
153
|
+
silently no-ops. The shared surface itself is unchanged
|
|
154
|
+
(`scripts/hooks` is symlinked from `.agentic/remote`); the new
|
|
155
|
+
assertion catches a future regression where the upstream package
|
|
156
|
+
drops the helper.
|
|
157
|
+
- **Manifest renamed: `.workstate-overlay.json` → `.workstate-bootstrap.json`
|
|
158
|
+
(schema_version bumped to 2).** Resolves a name collision with consumer
|
|
159
|
+
repos that also use `.workstate-overlay.json` for unrelated config. On first
|
|
160
|
+
run, an existing `.workstate-overlay.json` carrying the bootstrap shape
|
|
161
|
+
(top-level dict with a list `surfaces` key) is renamed in-place via
|
|
162
|
+
`git mv` (or filesystem rename when the target is not a git worktree).
|
|
163
|
+
Consumer-owned files at the legacy name are left untouched. The Python
|
|
164
|
+
alias `OVERLAY_MANIFEST_NAME` is preserved (now pointing at the canonical
|
|
165
|
+
filename) for downstream import compatibility.
|
|
166
|
+
- **Managed MCP defaults now launch stdio servers.** The built-in
|
|
167
|
+
`--mcp-servers default` map writes `uvx mcp-workstate-handoff
|
|
168
|
+
--workspace-root . serve-stdio` and `uvx mcp-workstate-orchestrator
|
|
169
|
+
--workspace-root . serve-stdio` into `.mcp.json`,
|
|
170
|
+
`.vscode/mcp.json`, and `.codex/config.toml`, so external clients
|
|
171
|
+
start runnable MCP servers from a fresh install or update.
|
|
172
|
+
- **`regenerate-task-views` harness hook contract dropped (implementation note).**
|
|
173
|
+
Bootstrap no longer materializes any Claude / VS Code / Codex hook
|
|
174
|
+
wiring that invokes `regenerate-task-views`; `DASHBOARD.txt` is now
|
|
175
|
+
auto-regenerated server-side inside `mcp-workstate-handoff` on every
|
|
176
|
+
state-mutating MCP call. The shared `scripts/hooks/` surface is still
|
|
177
|
+
materialized; `regenerate-task-views.sh` remains there only as a
|
|
178
|
+
documented manual fallback for the auto-regen opt-out path
|
|
179
|
+
(`WORKSTATE_HANDOFF_DASHBOARD_AUTO_REGEN=0`). Operators upgrading from
|
|
180
|
+
0.3.0 do not need to touch any harness config — the next
|
|
181
|
+
`workstate-bootstrap update` removes the obsolete hook wiring.
|
|
182
|
+
|
|
183
|
+
## 0.3.0 — 2026-04-28
|
|
184
|
+
|
|
185
|
+
- **Install-time state provisioning (implementation note).** `install` now runs
|
|
186
|
+
the handoff server's `init-state` after surface/config materialization
|
|
187
|
+
but before `core.hooksPath` is set, so a fresh install ends with a
|
|
188
|
+
schema-current `.task-state/handoff.db` and `.task-state/exports/`
|
|
189
|
+
ready for the first MCP call. The init-state invocation is resolved
|
|
190
|
+
from the same `mcp_servers` map written into `.mcp.json` /
|
|
191
|
+
`.vscode/mcp.json` / `.codex/config.toml` (avoiding dogfood version
|
|
192
|
+
skew between PyPI and local-source schemas), and the bootstrap
|
|
193
|
+
manifest's `remote_url` is threaded through `--expected-remote-url`
|
|
194
|
+
so a stale adjacent overlay from a different remote is rejected.
|
|
195
|
+
Skipped under `--no-mcp-servers`.
|
|
196
|
+
- **Required-surfaces refusal runs before the generator and
|
|
197
|
+
init-state.** A failing required-surface check now leaves no
|
|
198
|
+
`.task-state/`, no generated artifacts, and no manifest behind on
|
|
199
|
+
disk, so refused installs no longer half-write the target.
|
|
200
|
+
- **`status` reports handoff state.** When the install registered MCP
|
|
201
|
+
servers, `status` invokes `init-state --check` and appends the
|
|
202
|
+
resolved `state_dir` / `db_path` / `exports_dir` / `schema_version` /
|
|
203
|
+
`initialized` to the summary. `--no-mcp-servers` installs suppress
|
|
204
|
+
the section.
|
|
205
|
+
- **`doctor` flags missing `.task-state/handoff.db` as `state_drift`,**
|
|
206
|
+
gated on `.mcp.json` being present in the manifest's `configs` array
|
|
207
|
+
so config-only installs (`--no-mcp-servers`) do not produce
|
|
208
|
+
false-positive drift.
|
|
209
|
+
- **`switch_task` cold-start fix.** implementation note implementation note (in
|
|
210
|
+
`mcp-workstate-handoff` 0.5.0+) drops `BranchMismatchError` from
|
|
211
|
+
`switch_task`; the cold-start cycle (register task → `switch_task`
|
|
212
|
+
→ first content write) now completes from any branch. Branch
|
|
213
|
+
enforcement on content writes (`record_event`, `close_slice`,
|
|
214
|
+
`set_handoff_state`, `record_review_finding`,
|
|
215
|
+
`record_verified_test`) is unchanged — bootstrap's docs reflect
|
|
216
|
+
this, but the behavior change lives in the handoff package.
|
|
217
|
+
|
|
218
|
+
## 0.2.1 — 2026-04-26
|
|
219
|
+
|
|
220
|
+
- Add `pyyaml>=6` to runtime dependencies. The agent-workflow generator
|
|
221
|
+
imports `yaml` to read `skill.yaml`; bootstrap invokes the generator
|
|
222
|
+
via its own `sys.executable`, so PyYAML must be present in bootstrap's
|
|
223
|
+
uvx-isolated venv. Without it, install fails with
|
|
224
|
+
`PyYAML is required to read skill.yaml` on a clean uvx run.
|
|
225
|
+
|
|
226
|
+
## 0.2.0 — 2026-04-26
|
|
227
|
+
|
|
228
|
+
- Resolve shared overlay surfaces and the agent-workflow generator under
|
|
229
|
+
`packages/workstate-system/` (the workstate monorepo layout) with
|
|
230
|
+
fallback to the clone root for legacy hoisted overlays. Fixes
|
|
231
|
+
`BootstrapManifestValidationError: required surface 'scripts/hooks' was
|
|
232
|
+
not materialized` against monorepo refs at or after implementation note step 1.
|
|
233
|
+
- Rehearsal fixture (`fake_remote_with_generator`) now mirrors the real
|
|
234
|
+
monorepo layout so this regression cannot return silently.
|
|
235
|
+
|
|
236
|
+
### Note on previously published refs
|
|
237
|
+
|
|
238
|
+
The monorepo `v0.1.0` tag pre-dates this fix. Consumers using
|
|
239
|
+
`uvx --from "...@v0.1.0..." workstate-bootstrap install ...` will hit the
|
|
240
|
+
required-surface error. Pin to `v0.1.1` or later.
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: workstate-bootstrap
|
|
3
|
+
Version: 0.5.2
|
|
4
|
+
Summary: Bootstrap CLI that hoists the shared workstate-system surface into consumer repos.
|
|
5
|
+
Project-URL: Homepage, https://github.com/darce/workstate
|
|
6
|
+
Project-URL: Source, https://github.com/darce/workstate/tree/main/packages/workstate-bootstrap
|
|
7
|
+
Project-URL: Documentation, https://github.com/darce/workstate/blob/main/docs/CONSUMER.md
|
|
8
|
+
Project-URL: Issues, https://github.com/darce/workstate/issues
|
|
9
|
+
Author: darce
|
|
10
|
+
License: Proprietary
|
|
11
|
+
Requires-Python: >=3.11
|
|
12
|
+
Requires-Dist: pyyaml>=6
|
|
13
|
+
Requires-Dist: tomlkit>=0.13
|
|
14
|
+
Requires-Dist: workstate-protocol<0.2.0,>=0.1.4
|
|
15
|
+
Provides-Extra: dev
|
|
16
|
+
Requires-Dist: mcp-workstate-handoff; (python_version >= '3.12') and extra == 'dev'
|
|
17
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# workstate-bootstrap
|
|
21
|
+
|
|
22
|
+
Pip-installable CLI that hoists the shared workstate-system surface
|
|
23
|
+
(typed protocol, two MCP servers, hooks, skills, generated agent
|
|
24
|
+
workflows) into consumer repositories. Lives inside
|
|
25
|
+
[`darce/workstate`](https://github.com/darce/workstate).
|
|
26
|
+
|
|
27
|
+
Consumers run `workstate-bootstrap install --target <path>` once; it
|
|
28
|
+
clones the monorepo, materializes the overlay, and registers both
|
|
29
|
+
managed MCP servers (`mcp-workstate-handoff`, `mcp-workstate-orchestrator`)
|
|
30
|
+
across `.mcp.json`, `.vscode/mcp.json`, and `.codex/config.toml`. No
|
|
31
|
+
hand-edits required.
|
|
32
|
+
|
|
33
|
+
## Install
|
|
34
|
+
|
|
35
|
+
### From PyPI (recommended)
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
uvx --from workstate-bootstrap workstate-bootstrap install --target /path/to/your/repo
|
|
39
|
+
# or, persistent:
|
|
40
|
+
uv tool install workstate-bootstrap
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### From the monorepo source tree (development)
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
cd packages/workstate-bootstrap
|
|
47
|
+
python -m pip install -e ".[dev]"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Direct from git (private-repo phase, before PyPI release)
|
|
51
|
+
|
|
52
|
+
One-shot (no install — fetches each invocation):
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
uvx --from "git+https://github.com/darce/workstate@workstate-bootstrap-v0.2.1#subdirectory=packages/workstate-bootstrap" \
|
|
56
|
+
workstate-bootstrap install \
|
|
57
|
+
--target /path/to/your/repo
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Persistent (recommended once you start running `status` / `doctor`
|
|
61
|
+
regularly — installs `workstate-bootstrap` onto `$PATH`):
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
uv tool install "git+https://github.com/darce/workstate@workstate-bootstrap-v0.2.1#subdirectory=packages/workstate-bootstrap"
|
|
65
|
+
# then:
|
|
66
|
+
workstate-bootstrap status --target /path/to/your/repo
|
|
67
|
+
workstate-bootstrap doctor --target /path/to/your/repo
|
|
68
|
+
# upgrade later:
|
|
69
|
+
uv tool upgrade workstate-bootstrap
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
> **Hardlink warning on first install?** If you see
|
|
73
|
+
> `Failed to hardlink files; falling back to full copy`, your `uv`
|
|
74
|
+
> cache and tool dir live on different filesystems. The install still
|
|
75
|
+
> succeeds; silence the warning with `export UV_LINK_MODE=copy` in
|
|
76
|
+
> your shell profile.
|
|
77
|
+
|
|
78
|
+
## Subcommands
|
|
79
|
+
|
|
80
|
+
```text
|
|
81
|
+
workstate-bootstrap install --target <path> [--remote-ref <tag>] [--mcp-servers <default|path>] [--no-mcp-servers]
|
|
82
|
+
workstate-bootstrap update --target <path> --remote-ref <tag>
|
|
83
|
+
workstate-bootstrap status --target <path>
|
|
84
|
+
workstate-bootstrap doctor --target <path> [--mcp-servers <default|path>]
|
|
85
|
+
workstate-bootstrap repair --target <path> [--force-dirty] [--mcp-servers <default|path>]
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
- `install`: Clone the monorepo, materialize SHARED + GENERATED
|
|
89
|
+
surfaces, write the three MCP-config files, run `init-state` to
|
|
90
|
+
provision `<target>/.task-state/handoff.db` (skipped under
|
|
91
|
+
`--no-mcp-servers`), set `core.hooksPath`, and write the overlay
|
|
92
|
+
manifest.
|
|
93
|
+
- `update`: Re-run install at a new `--remote-ref`; refresh GENERATED
|
|
94
|
+
surfaces and, optionally, configs.
|
|
95
|
+
- `status`: Print a summary of the installed overlay manifest. When
|
|
96
|
+
the install registered MCP servers, also reports the resolved
|
|
97
|
+
`state_dir` / `db_path` / `exports_dir` / `schema_version` via
|
|
98
|
+
`init-state --check`.
|
|
99
|
+
- `doctor`: Detect drift in SHARED, GENERATED, config, and
|
|
100
|
+
initialized-state surfaces. Flags missing `.task-state/handoff.db`
|
|
101
|
+
as `state_drift` only when the manifest recorded `.mcp.json`. Exit
|
|
102
|
+
`1` when drift exists.
|
|
103
|
+
- `repair`: Restore drifted surfaces flagged by `doctor`.
|
|
104
|
+
|
|
105
|
+
See [`docs/CONSUMER.md`](https://github.com/darce/workstate/blob/main/docs/CONSUMER.md)
|
|
106
|
+
for the consumer-facing walkthrough (upgrade, drift handling, skill
|
|
107
|
+
overrides, the `current_task_auto_regen` migration note).
|
|
108
|
+
|
|
109
|
+
## Surfaces written by `install`
|
|
110
|
+
|
|
111
|
+
The canonical source of truth for bootstrap-managed surfaces is the
|
|
112
|
+
installer implementation in
|
|
113
|
+
`src/workstate_bootstrap/install.py` (`SHARED_SURFACES` and
|
|
114
|
+
`GENERATED_SURFACES`). Keep this table aligned with those constants.
|
|
115
|
+
|
|
116
|
+
| Surface | Source | Layer |
|
|
117
|
+
| ------------------------------------ | ---------- | ----------- |
|
|
118
|
+
| `scripts/hooks/` | shared | symlink |
|
|
119
|
+
| `.github/hooks/` | shared | symlink |
|
|
120
|
+
| `docs/agentic/contracts/` | shared | symlink |
|
|
121
|
+
| `docs/agentic/rules/` | shared | symlink |
|
|
122
|
+
| `Makefile.d/` non-excluded children | shared | carved dir |
|
|
123
|
+
| `scripts/workstate/` non-excluded children | shared | carved dir |
|
|
124
|
+
| `.github/prompts/` | generated | real dir |
|
|
125
|
+
| `.agentic/generated/plugins/workstate-system/base/` | generated | real dir |
|
|
126
|
+
| `.agentic/generated/plugins/workstate-system/effective/` | generated | real dir |
|
|
127
|
+
| `.mcp.json` | generated | real file |
|
|
128
|
+
| `.vscode/mcp.json` | generated | real file |
|
|
129
|
+
| `.codex/config.toml` | generated | real file |
|
|
130
|
+
| `core.hooksPath` git config | generated | git config |
|
|
131
|
+
| `.task-state/handoff.db` | runtime | sqlite |
|
|
132
|
+
| `.task-state/exports/` | runtime | dir |
|
|
133
|
+
| `.agentic/remote/` | bootstrap | git clone |
|
|
134
|
+
| `.workstate-bootstrap.json` | bootstrap | manifest |
|
|
135
|
+
|
|
136
|
+
`.task-state/` is provisioned by the handoff server's `init-state`
|
|
137
|
+
subcommand at install time and is gitignored — each fresh checkout
|
|
138
|
+
regenerates it through `workstate-bootstrap install`.
|
|
139
|
+
|
|
140
|
+
## Defaults
|
|
141
|
+
|
|
142
|
+
- `--profile` defaults to `all`, which materializes the full surface
|
|
143
|
+
set: generated Copilot prompts, Claude/Codex plugin trees, shared
|
|
144
|
+
overlay surfaces, and the lifecycle hoist
|
|
145
|
+
(`Makefile.d/lifecycle.mk` plus the sentinel-bracketed `-include`
|
|
146
|
+
block in the consumer `Makefile`). Pass `--profile minimal` for a
|
|
147
|
+
clone-only install with no surfaces, or `--profile lifecycle` for
|
|
148
|
+
just the lifecycle runner and Makefile fragment. The active profile
|
|
149
|
+
is recorded in `.workstate-bootstrap.json` under `"profile"`.
|
|
150
|
+
- `--remote-url` defaults to `git@github.com:darce/workstate.git`.
|
|
151
|
+
- `--remote-ref` defaults to `main` (override with a release tag like `v0.1.0`).
|
|
152
|
+
- `--mcp-servers` defaults to the built-in managed map registering
|
|
153
|
+
`mcp-workstate-handoff` and `mcp-workstate-orchestrator` via `uvx` with
|
|
154
|
+
`--workspace-root . serve-stdio`, so Codex, VS Code, and Claude
|
|
155
|
+
clients start real MCP stdio servers from the generated config.
|
|
156
|
+
Pass a JSON file path to override; pass `--no-mcp-servers` to skip
|
|
157
|
+
the three config writers entirely.
|
|
158
|
+
- Plugin overrides are auto-discovered at
|
|
159
|
+
`workstate-overrides/workstate-system/` when that root contains an
|
|
160
|
+
`overrides.yaml` manifest. Use `--plugin-overrides <path>` on
|
|
161
|
+
`install`, `update`, `doctor`, or `repair` for a non-default root;
|
|
162
|
+
bootstrap records that path so later update/doctor/repair runs reuse
|
|
163
|
+
it. Override-aware installs generate effective plugin trees under
|
|
164
|
+
`.agentic/generated/plugins/workstate-system/effective/{claude,codex}`
|
|
165
|
+
and point marketplace pins at those generated trees.
|
|
166
|
+
- `install` and `update` preserve plugin override files by default.
|
|
167
|
+
`--reset-overrides` is the explicit destructive path; it removes only
|
|
168
|
+
the resolved override root, refuses dirty git worktrees unless
|
|
169
|
+
`--backup` is supplied, and archives backups under
|
|
170
|
+
`.agentic/override-backups/<timestamp>/` before removal.
|
|
171
|
+
|
|
172
|
+
## Development
|
|
173
|
+
|
|
174
|
+
Tests live under `tests/`. From the monorepo root:
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
cd packages/workstate-bootstrap
|
|
178
|
+
PYTHONPATH=.:src:../workstate-protocol/src pytest tests -q
|
|
179
|
+
```
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# workstate-bootstrap
|
|
2
|
+
|
|
3
|
+
Pip-installable CLI that hoists the shared workstate-system surface
|
|
4
|
+
(typed protocol, two MCP servers, hooks, skills, generated agent
|
|
5
|
+
workflows) into consumer repositories. Lives inside
|
|
6
|
+
[`darce/workstate`](https://github.com/darce/workstate).
|
|
7
|
+
|
|
8
|
+
Consumers run `workstate-bootstrap install --target <path>` once; it
|
|
9
|
+
clones the monorepo, materializes the overlay, and registers both
|
|
10
|
+
managed MCP servers (`mcp-workstate-handoff`, `mcp-workstate-orchestrator`)
|
|
11
|
+
across `.mcp.json`, `.vscode/mcp.json`, and `.codex/config.toml`. No
|
|
12
|
+
hand-edits required.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
### From PyPI (recommended)
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
uvx --from workstate-bootstrap workstate-bootstrap install --target /path/to/your/repo
|
|
20
|
+
# or, persistent:
|
|
21
|
+
uv tool install workstate-bootstrap
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### From the monorepo source tree (development)
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
cd packages/workstate-bootstrap
|
|
28
|
+
python -m pip install -e ".[dev]"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Direct from git (private-repo phase, before PyPI release)
|
|
32
|
+
|
|
33
|
+
One-shot (no install — fetches each invocation):
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
uvx --from "git+https://github.com/darce/workstate@workstate-bootstrap-v0.2.1#subdirectory=packages/workstate-bootstrap" \
|
|
37
|
+
workstate-bootstrap install \
|
|
38
|
+
--target /path/to/your/repo
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Persistent (recommended once you start running `status` / `doctor`
|
|
42
|
+
regularly — installs `workstate-bootstrap` onto `$PATH`):
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
uv tool install "git+https://github.com/darce/workstate@workstate-bootstrap-v0.2.1#subdirectory=packages/workstate-bootstrap"
|
|
46
|
+
# then:
|
|
47
|
+
workstate-bootstrap status --target /path/to/your/repo
|
|
48
|
+
workstate-bootstrap doctor --target /path/to/your/repo
|
|
49
|
+
# upgrade later:
|
|
50
|
+
uv tool upgrade workstate-bootstrap
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
> **Hardlink warning on first install?** If you see
|
|
54
|
+
> `Failed to hardlink files; falling back to full copy`, your `uv`
|
|
55
|
+
> cache and tool dir live on different filesystems. The install still
|
|
56
|
+
> succeeds; silence the warning with `export UV_LINK_MODE=copy` in
|
|
57
|
+
> your shell profile.
|
|
58
|
+
|
|
59
|
+
## Subcommands
|
|
60
|
+
|
|
61
|
+
```text
|
|
62
|
+
workstate-bootstrap install --target <path> [--remote-ref <tag>] [--mcp-servers <default|path>] [--no-mcp-servers]
|
|
63
|
+
workstate-bootstrap update --target <path> --remote-ref <tag>
|
|
64
|
+
workstate-bootstrap status --target <path>
|
|
65
|
+
workstate-bootstrap doctor --target <path> [--mcp-servers <default|path>]
|
|
66
|
+
workstate-bootstrap repair --target <path> [--force-dirty] [--mcp-servers <default|path>]
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
- `install`: Clone the monorepo, materialize SHARED + GENERATED
|
|
70
|
+
surfaces, write the three MCP-config files, run `init-state` to
|
|
71
|
+
provision `<target>/.task-state/handoff.db` (skipped under
|
|
72
|
+
`--no-mcp-servers`), set `core.hooksPath`, and write the overlay
|
|
73
|
+
manifest.
|
|
74
|
+
- `update`: Re-run install at a new `--remote-ref`; refresh GENERATED
|
|
75
|
+
surfaces and, optionally, configs.
|
|
76
|
+
- `status`: Print a summary of the installed overlay manifest. When
|
|
77
|
+
the install registered MCP servers, also reports the resolved
|
|
78
|
+
`state_dir` / `db_path` / `exports_dir` / `schema_version` via
|
|
79
|
+
`init-state --check`.
|
|
80
|
+
- `doctor`: Detect drift in SHARED, GENERATED, config, and
|
|
81
|
+
initialized-state surfaces. Flags missing `.task-state/handoff.db`
|
|
82
|
+
as `state_drift` only when the manifest recorded `.mcp.json`. Exit
|
|
83
|
+
`1` when drift exists.
|
|
84
|
+
- `repair`: Restore drifted surfaces flagged by `doctor`.
|
|
85
|
+
|
|
86
|
+
See [`docs/CONSUMER.md`](https://github.com/darce/workstate/blob/main/docs/CONSUMER.md)
|
|
87
|
+
for the consumer-facing walkthrough (upgrade, drift handling, skill
|
|
88
|
+
overrides, the `current_task_auto_regen` migration note).
|
|
89
|
+
|
|
90
|
+
## Surfaces written by `install`
|
|
91
|
+
|
|
92
|
+
The canonical source of truth for bootstrap-managed surfaces is the
|
|
93
|
+
installer implementation in
|
|
94
|
+
`src/workstate_bootstrap/install.py` (`SHARED_SURFACES` and
|
|
95
|
+
`GENERATED_SURFACES`). Keep this table aligned with those constants.
|
|
96
|
+
|
|
97
|
+
| Surface | Source | Layer |
|
|
98
|
+
| ------------------------------------ | ---------- | ----------- |
|
|
99
|
+
| `scripts/hooks/` | shared | symlink |
|
|
100
|
+
| `.github/hooks/` | shared | symlink |
|
|
101
|
+
| `docs/agentic/contracts/` | shared | symlink |
|
|
102
|
+
| `docs/agentic/rules/` | shared | symlink |
|
|
103
|
+
| `Makefile.d/` non-excluded children | shared | carved dir |
|
|
104
|
+
| `scripts/workstate/` non-excluded children | shared | carved dir |
|
|
105
|
+
| `.github/prompts/` | generated | real dir |
|
|
106
|
+
| `.agentic/generated/plugins/workstate-system/base/` | generated | real dir |
|
|
107
|
+
| `.agentic/generated/plugins/workstate-system/effective/` | generated | real dir |
|
|
108
|
+
| `.mcp.json` | generated | real file |
|
|
109
|
+
| `.vscode/mcp.json` | generated | real file |
|
|
110
|
+
| `.codex/config.toml` | generated | real file |
|
|
111
|
+
| `core.hooksPath` git config | generated | git config |
|
|
112
|
+
| `.task-state/handoff.db` | runtime | sqlite |
|
|
113
|
+
| `.task-state/exports/` | runtime | dir |
|
|
114
|
+
| `.agentic/remote/` | bootstrap | git clone |
|
|
115
|
+
| `.workstate-bootstrap.json` | bootstrap | manifest |
|
|
116
|
+
|
|
117
|
+
`.task-state/` is provisioned by the handoff server's `init-state`
|
|
118
|
+
subcommand at install time and is gitignored — each fresh checkout
|
|
119
|
+
regenerates it through `workstate-bootstrap install`.
|
|
120
|
+
|
|
121
|
+
## Defaults
|
|
122
|
+
|
|
123
|
+
- `--profile` defaults to `all`, which materializes the full surface
|
|
124
|
+
set: generated Copilot prompts, Claude/Codex plugin trees, shared
|
|
125
|
+
overlay surfaces, and the lifecycle hoist
|
|
126
|
+
(`Makefile.d/lifecycle.mk` plus the sentinel-bracketed `-include`
|
|
127
|
+
block in the consumer `Makefile`). Pass `--profile minimal` for a
|
|
128
|
+
clone-only install with no surfaces, or `--profile lifecycle` for
|
|
129
|
+
just the lifecycle runner and Makefile fragment. The active profile
|
|
130
|
+
is recorded in `.workstate-bootstrap.json` under `"profile"`.
|
|
131
|
+
- `--remote-url` defaults to `git@github.com:darce/workstate.git`.
|
|
132
|
+
- `--remote-ref` defaults to `main` (override with a release tag like `v0.1.0`).
|
|
133
|
+
- `--mcp-servers` defaults to the built-in managed map registering
|
|
134
|
+
`mcp-workstate-handoff` and `mcp-workstate-orchestrator` via `uvx` with
|
|
135
|
+
`--workspace-root . serve-stdio`, so Codex, VS Code, and Claude
|
|
136
|
+
clients start real MCP stdio servers from the generated config.
|
|
137
|
+
Pass a JSON file path to override; pass `--no-mcp-servers` to skip
|
|
138
|
+
the three config writers entirely.
|
|
139
|
+
- Plugin overrides are auto-discovered at
|
|
140
|
+
`workstate-overrides/workstate-system/` when that root contains an
|
|
141
|
+
`overrides.yaml` manifest. Use `--plugin-overrides <path>` on
|
|
142
|
+
`install`, `update`, `doctor`, or `repair` for a non-default root;
|
|
143
|
+
bootstrap records that path so later update/doctor/repair runs reuse
|
|
144
|
+
it. Override-aware installs generate effective plugin trees under
|
|
145
|
+
`.agentic/generated/plugins/workstate-system/effective/{claude,codex}`
|
|
146
|
+
and point marketplace pins at those generated trees.
|
|
147
|
+
- `install` and `update` preserve plugin override files by default.
|
|
148
|
+
`--reset-overrides` is the explicit destructive path; it removes only
|
|
149
|
+
the resolved override root, refuses dirty git worktrees unless
|
|
150
|
+
`--backup` is supplied, and archives backups under
|
|
151
|
+
`.agentic/override-backups/<timestamp>/` before removal.
|
|
152
|
+
|
|
153
|
+
## Development
|
|
154
|
+
|
|
155
|
+
Tests live under `tests/`. From the monorepo root:
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
cd packages/workstate-bootstrap
|
|
159
|
+
PYTHONPATH=.:src:../workstate-protocol/src pytest tests -q
|
|
160
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling>=1.21"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "workstate-bootstrap"
|
|
7
|
+
version = "0.5.2"
|
|
8
|
+
description = "Bootstrap CLI that hoists the shared workstate-system surface into consumer repos."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = { text = "Proprietary" }
|
|
12
|
+
authors = [{ name = "darce" }]
|
|
13
|
+
dependencies = ["tomlkit>=0.13", "pyyaml>=6", "workstate-protocol>=0.1.4,<0.2.0"]
|
|
14
|
+
|
|
15
|
+
[project.scripts]
|
|
16
|
+
workstate-bootstrap = "workstate_bootstrap.cli:main"
|
|
17
|
+
|
|
18
|
+
[project.urls]
|
|
19
|
+
Homepage = "https://github.com/darce/workstate"
|
|
20
|
+
Source = "https://github.com/darce/workstate/tree/main/packages/workstate-bootstrap"
|
|
21
|
+
Documentation = "https://github.com/darce/workstate/blob/main/docs/CONSUMER.md"
|
|
22
|
+
Issues = "https://github.com/darce/workstate/issues"
|
|
23
|
+
|
|
24
|
+
[project.optional-dependencies]
|
|
25
|
+
dev = ["pytest>=8", "mcp-workstate-handoff; python_version >= '3.12'"]
|
|
26
|
+
|
|
27
|
+
[tool.uv.sources]
|
|
28
|
+
mcp-workstate-handoff = { path = "../mcp-workstate-handoff", editable = true }
|
|
29
|
+
workstate-protocol = { path = "../workstate-protocol", editable = true }
|
|
30
|
+
|
|
31
|
+
[tool.hatch.build.targets.wheel]
|
|
32
|
+
packages = ["src/workstate_bootstrap"]
|
|
33
|
+
|
|
34
|
+
[tool.pytest.ini_options]
|
|
35
|
+
testpaths = ["tests"]
|
|
36
|
+
addopts = "-ra"
|