workstate-bootstrap 0.5.2__tar.gz → 0.7.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.
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/CHANGELOG.md +60 -2
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/PKG-INFO +10 -9
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/README.md +7 -7
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/pyproject.toml +8 -2
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/src/workstate_bootstrap/__init__.py +1 -1
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/src/workstate_bootstrap/cli.py +51 -11
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/src/workstate_bootstrap/install.py +605 -126
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/src/workstate_bootstrap/mcp_sync.py +3 -0
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/src/workstate_bootstrap/subcommands.py +77 -44
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/tests/test_bootstrap_install_rehearsal.py +4 -4
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/tests/test_install.py +412 -54
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/tests/test_mcp_sync_cli.py +57 -0
- workstate_bootstrap-0.7.0/tests/test_package_source.py +196 -0
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/tests/test_render_seam.py +1 -1
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/tests/test_subcommands.py +142 -26
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/.gitignore +0 -0
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/src/workstate_bootstrap/__main__.py +0 -0
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/tests/__init__.py +0 -0
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/tests/test_cli_profile.py +0 -0
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/tests/test_doctor_repair_sync.py +0 -0
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/tests/test_ensure_hooks_path_make.py +0 -0
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/tests/test_install_manifest_walker.py +0 -0
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/tests/test_install_profile_all_lifecycle.py +0 -0
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/tests/test_install_profiles.py +0 -0
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/tests/test_manifest_build.py +0 -0
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/tests/test_mcp_sync_e2e.py +0 -0
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/tests/test_mcp_sync_malformed.py +0 -0
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/tests/test_mcp_sync_prune.py +0 -0
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/tests/test_mcp_sync_unit.py +0 -0
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/tests/test_package_metadata.py +0 -0
- {workstate_bootstrap-0.5.2 → workstate_bootstrap-0.7.0}/tests/test_root_visible_task_plans.py +0 -0
|
@@ -2,6 +2,64 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## [0.7.0] — 2026-06-01
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **Package-source overlay delivery (WS-PKG-DELIVERY-01).** `install` /
|
|
10
|
+
`update` can resolve the harness overlay from an installed
|
|
11
|
+
`workstate-system` distribution (`source_kind="package"`) instead of a git
|
|
12
|
+
clone, writing a `package`-kind `BootstrapManifest`. `update` / `repair`
|
|
13
|
+
reject a package-source manifest with a clear error rather than
|
|
14
|
+
dereferencing a `remote_url` that package manifests do not carry.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- **MCP launch decoupled from resolution (implementation note Theme A,
|
|
19
|
+
WS-MCP-LAUNCH-01).** Generated serve commands now use `uv run --no-sync`
|
|
20
|
+
and the server venvs are pre-built at install time
|
|
21
|
+
(`_presync_local_mcp_envs`), eliminating the cold-start re-sync race that
|
|
22
|
+
overran the harness's 30s MCP connection timeout and registered zero tools.
|
|
23
|
+
The `--no-sync` invariant is enforced at the shared render seam
|
|
24
|
+
(`_canonicalize_managed_servers`), so `install` / `update` / `repair` /
|
|
25
|
+
`mcp-sync` all rewrite an older launcher; the earlier preserve-path
|
|
26
|
+
`_normalize_local_mcp_server_specs` patch is retired.
|
|
27
|
+
|
|
28
|
+
### Removed
|
|
29
|
+
|
|
30
|
+
- **Runtime-path migration shim retired (implementation note Slice D cutover complete).**
|
|
31
|
+
The legacy-runtime-tree migration helpers (`migrate_runtime_paths()`,
|
|
32
|
+
`plan_runtime_path_migration()`) and the `legacy_runtime_path` `doctor` check
|
|
33
|
+
are removed. `.workstate/` / `docs/workstate/` are the sole runtime paths with
|
|
34
|
+
no backward compatibility — a consumer still carrying the pre-rebrand runtime
|
|
35
|
+
tree must reinstall cleanly.
|
|
36
|
+
|
|
37
|
+
## [0.6.0] — 2026-05-30
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
|
|
41
|
+
- **MCP server identity cutover (implementation note Slice B).** Default managed servers
|
|
42
|
+
register under the canonical `workstate-handoff-mcp` /
|
|
43
|
+
`workstate-orchestrator-mcp` names. `LEGACY_MCP_SERVER_RENAMES` +
|
|
44
|
+
`_legacy_prune_for()` dedup and forward-rewrite a stale `agent-*-mcp`
|
|
45
|
+
registration across all three config surfaces (`.mcp.json`,
|
|
46
|
+
`.vscode/mcp.json`, `.codex/config.toml`) so a re-install collapses the
|
|
47
|
+
duplicate to one canonical entry — fixing the "MCP servers not loading"
|
|
48
|
+
symptom caused by deep-merge preserving both old and new entries.
|
|
49
|
+
- **Default managed server pins bumped** to `mcp-workstate-handoff@0.12.0` and
|
|
50
|
+
`mcp-workstate-orchestrator@0.5.0`. `workstate-protocol` floor raised to
|
|
51
|
+
`>=0.1.6`.
|
|
52
|
+
|
|
53
|
+
### Added
|
|
54
|
+
|
|
55
|
+
- **Runtime path migration `.workstate/` → `.workstate/` and
|
|
56
|
+
`docs/workstate/` → `docs/workstate/` (implementation note Slice D).**
|
|
57
|
+
`migrate_runtime_paths()` / `plan_runtime_path_migration()` run on
|
|
58
|
+
`install`/`update`: idempotent, archive-backed (a both-present collision
|
|
59
|
+
moves the legacy tree aside rather than overwriting), dry-run-capable, and
|
|
60
|
+
routed through the shared `workstate_protocol.paths` constants. `doctor`
|
|
61
|
+
flags a surviving legacy tree as `legacy_runtime_path`.
|
|
62
|
+
|
|
5
63
|
## [0.5.2] — 2026-05-20
|
|
6
64
|
|
|
7
65
|
### Changed
|
|
@@ -19,7 +77,7 @@
|
|
|
19
77
|
When a consumer was installed pre-v0.2.0 (legacy root layout
|
|
20
78
|
`<clone>/<surface>`) and the layout subsequently moved into
|
|
21
79
|
`<clone>/packages/workstate-system/<surface>`, the target-side
|
|
22
|
-
`scripts/hooks -> ../.
|
|
80
|
+
`scripts/hooks -> ../.workstate/remote/scripts/hooks` symlink survived
|
|
23
81
|
every subsequent `workstate-bootstrap install` because the pre-fix
|
|
24
82
|
`points_into_clone` check still passed lexically for the broken
|
|
25
83
|
resolved path. `_materialize_surfaces` now classifies each existing
|
|
@@ -151,7 +209,7 @@
|
|
|
151
209
|
post-checkout / pre-commit / pre-push hooks `exec`) is materialized
|
|
152
210
|
alongside them. Without the helper, every branch-naming gate
|
|
153
211
|
silently no-ops. The shared surface itself is unchanged
|
|
154
|
-
(`scripts/hooks` is symlinked from `.
|
|
212
|
+
(`scripts/hooks` is symlinked from `.workstate/remote`); the new
|
|
155
213
|
assertion catches a future regression where the upstream package
|
|
156
214
|
drops the helper.
|
|
157
215
|
- **Manifest renamed: `.workstate-overlay.json` → `.workstate-bootstrap.json`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: workstate-bootstrap
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Bootstrap CLI that hoists the shared workstate-system surface into consumer repos.
|
|
5
5
|
Project-URL: Homepage, https://github.com/darce/workstate
|
|
6
6
|
Project-URL: Source, https://github.com/darce/workstate/tree/main/packages/workstate-bootstrap
|
|
@@ -11,7 +11,8 @@ License: Proprietary
|
|
|
11
11
|
Requires-Python: >=3.11
|
|
12
12
|
Requires-Dist: pyyaml>=6
|
|
13
13
|
Requires-Dist: tomlkit>=0.13
|
|
14
|
-
Requires-Dist: workstate-protocol<0.2.0,>=0.1.
|
|
14
|
+
Requires-Dist: workstate-protocol<0.2.0,>=0.1.7
|
|
15
|
+
Requires-Dist: workstate-system<0.2.0,>=0.1.0
|
|
15
16
|
Provides-Extra: dev
|
|
16
17
|
Requires-Dist: mcp-workstate-handoff; (python_version >= '3.12') and extra == 'dev'
|
|
17
18
|
Requires-Dist: pytest>=8; extra == 'dev'
|
|
@@ -117,20 +118,20 @@ installer implementation in
|
|
|
117
118
|
| ------------------------------------ | ---------- | ----------- |
|
|
118
119
|
| `scripts/hooks/` | shared | symlink |
|
|
119
120
|
| `.github/hooks/` | shared | symlink |
|
|
120
|
-
| `docs/
|
|
121
|
-
| `docs/
|
|
121
|
+
| `docs/workstate/contracts/` | shared | symlink |
|
|
122
|
+
| `docs/workstate/rules/` | shared | symlink |
|
|
122
123
|
| `Makefile.d/` non-excluded children | shared | carved dir |
|
|
123
124
|
| `scripts/workstate/` non-excluded children | shared | carved dir |
|
|
124
125
|
| `.github/prompts/` | generated | real dir |
|
|
125
|
-
| `.
|
|
126
|
-
| `.
|
|
126
|
+
| `.workstate/generated/plugins/workstate-system/base/` | generated | real dir |
|
|
127
|
+
| `.workstate/generated/plugins/workstate-system/effective/` | generated | real dir |
|
|
127
128
|
| `.mcp.json` | generated | real file |
|
|
128
129
|
| `.vscode/mcp.json` | generated | real file |
|
|
129
130
|
| `.codex/config.toml` | generated | real file |
|
|
130
131
|
| `core.hooksPath` git config | generated | git config |
|
|
131
132
|
| `.task-state/handoff.db` | runtime | sqlite |
|
|
132
133
|
| `.task-state/exports/` | runtime | dir |
|
|
133
|
-
| `.
|
|
134
|
+
| `.workstate/remote/` | bootstrap | git clone |
|
|
134
135
|
| `.workstate-bootstrap.json` | bootstrap | manifest |
|
|
135
136
|
|
|
136
137
|
`.task-state/` is provisioned by the handoff server's `init-state`
|
|
@@ -161,13 +162,13 @@ regenerates it through `workstate-bootstrap install`.
|
|
|
161
162
|
`install`, `update`, `doctor`, or `repair` for a non-default root;
|
|
162
163
|
bootstrap records that path so later update/doctor/repair runs reuse
|
|
163
164
|
it. Override-aware installs generate effective plugin trees under
|
|
164
|
-
`.
|
|
165
|
+
`.workstate/generated/plugins/workstate-system/effective/{claude,codex}`
|
|
165
166
|
and point marketplace pins at those generated trees.
|
|
166
167
|
- `install` and `update` preserve plugin override files by default.
|
|
167
168
|
`--reset-overrides` is the explicit destructive path; it removes only
|
|
168
169
|
the resolved override root, refuses dirty git worktrees unless
|
|
169
170
|
`--backup` is supplied, and archives backups under
|
|
170
|
-
`.
|
|
171
|
+
`.workstate/override-backups/<timestamp>/` before removal.
|
|
171
172
|
|
|
172
173
|
## Development
|
|
173
174
|
|
|
@@ -98,20 +98,20 @@ installer implementation in
|
|
|
98
98
|
| ------------------------------------ | ---------- | ----------- |
|
|
99
99
|
| `scripts/hooks/` | shared | symlink |
|
|
100
100
|
| `.github/hooks/` | shared | symlink |
|
|
101
|
-
| `docs/
|
|
102
|
-
| `docs/
|
|
101
|
+
| `docs/workstate/contracts/` | shared | symlink |
|
|
102
|
+
| `docs/workstate/rules/` | shared | symlink |
|
|
103
103
|
| `Makefile.d/` non-excluded children | shared | carved dir |
|
|
104
104
|
| `scripts/workstate/` non-excluded children | shared | carved dir |
|
|
105
105
|
| `.github/prompts/` | generated | real dir |
|
|
106
|
-
| `.
|
|
107
|
-
| `.
|
|
106
|
+
| `.workstate/generated/plugins/workstate-system/base/` | generated | real dir |
|
|
107
|
+
| `.workstate/generated/plugins/workstate-system/effective/` | generated | real dir |
|
|
108
108
|
| `.mcp.json` | generated | real file |
|
|
109
109
|
| `.vscode/mcp.json` | generated | real file |
|
|
110
110
|
| `.codex/config.toml` | generated | real file |
|
|
111
111
|
| `core.hooksPath` git config | generated | git config |
|
|
112
112
|
| `.task-state/handoff.db` | runtime | sqlite |
|
|
113
113
|
| `.task-state/exports/` | runtime | dir |
|
|
114
|
-
| `.
|
|
114
|
+
| `.workstate/remote/` | bootstrap | git clone |
|
|
115
115
|
| `.workstate-bootstrap.json` | bootstrap | manifest |
|
|
116
116
|
|
|
117
117
|
`.task-state/` is provisioned by the handoff server's `init-state`
|
|
@@ -142,13 +142,13 @@ regenerates it through `workstate-bootstrap install`.
|
|
|
142
142
|
`install`, `update`, `doctor`, or `repair` for a non-default root;
|
|
143
143
|
bootstrap records that path so later update/doctor/repair runs reuse
|
|
144
144
|
it. Override-aware installs generate effective plugin trees under
|
|
145
|
-
`.
|
|
145
|
+
`.workstate/generated/plugins/workstate-system/effective/{claude,codex}`
|
|
146
146
|
and point marketplace pins at those generated trees.
|
|
147
147
|
- `install` and `update` preserve plugin override files by default.
|
|
148
148
|
`--reset-overrides` is the explicit destructive path; it removes only
|
|
149
149
|
the resolved override root, refuses dirty git worktrees unless
|
|
150
150
|
`--backup` is supplied, and archives backups under
|
|
151
|
-
`.
|
|
151
|
+
`.workstate/override-backups/<timestamp>/` before removal.
|
|
152
152
|
|
|
153
153
|
## Development
|
|
154
154
|
|
|
@@ -4,13 +4,18 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "workstate-bootstrap"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.7.0"
|
|
8
8
|
description = "Bootstrap CLI that hoists the shared workstate-system surface into consumer repos."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
11
11
|
license = { text = "Proprietary" }
|
|
12
12
|
authors = [{ name = "darce" }]
|
|
13
|
-
dependencies = [
|
|
13
|
+
dependencies = [
|
|
14
|
+
"tomlkit>=0.13",
|
|
15
|
+
"pyyaml>=6",
|
|
16
|
+
"workstate-protocol>=0.1.7,<0.2.0",
|
|
17
|
+
"workstate-system>=0.1.0,<0.2.0",
|
|
18
|
+
]
|
|
14
19
|
|
|
15
20
|
[project.scripts]
|
|
16
21
|
workstate-bootstrap = "workstate_bootstrap.cli:main"
|
|
@@ -27,6 +32,7 @@ dev = ["pytest>=8", "mcp-workstate-handoff; python_version >= '3.12'"]
|
|
|
27
32
|
[tool.uv.sources]
|
|
28
33
|
mcp-workstate-handoff = { path = "../mcp-workstate-handoff", editable = true }
|
|
29
34
|
workstate-protocol = { path = "../workstate-protocol", editable = true }
|
|
35
|
+
workstate-system = { path = "../workstate-system", editable = true }
|
|
30
36
|
|
|
31
37
|
[tool.hatch.build.targets.wheel]
|
|
32
38
|
packages = ["src/workstate_bootstrap"]
|
|
@@ -13,6 +13,7 @@ from workstate_bootstrap.install import (
|
|
|
13
13
|
PROFILE_ALL,
|
|
14
14
|
PROFILE_LIFECYCLE,
|
|
15
15
|
PROFILE_MINIMAL,
|
|
16
|
+
_build_local_default_mcp_servers,
|
|
16
17
|
install,
|
|
17
18
|
)
|
|
18
19
|
from workstate_bootstrap.mcp_sync import (
|
|
@@ -64,8 +65,29 @@ def _resolve_mcp_servers(
|
|
|
64
65
|
return doc
|
|
65
66
|
|
|
66
67
|
|
|
68
|
+
def _resolve_managed_servers(
|
|
69
|
+
target: Path, raw: str | None
|
|
70
|
+
) -> Mapping[str, Mapping[str, Any]] | None:
|
|
71
|
+
"""Resolve ``--mcp-servers``, making ``default`` profile-aware.
|
|
72
|
+
|
|
73
|
+
On a ``git_overlay`` install with local MCP packages, ``default`` resolves
|
|
74
|
+
the LOCAL ``uv run --no-sync --project ...`` launchers (via
|
|
75
|
+
:func:`_build_local_default_mcp_servers`) instead of the uvx package map, so
|
|
76
|
+
``mcp-sync`` and ``repair`` converge on the same launchers as
|
|
77
|
+
``install``/``update`` and never silently downgrade a local install. Falls
|
|
78
|
+
back to the uvx map when no local packages are present. implementation note A1.
|
|
79
|
+
"""
|
|
80
|
+
servers = _resolve_mcp_servers(raw)
|
|
81
|
+
if raw == "default":
|
|
82
|
+
local = _build_local_default_mcp_servers(target)
|
|
83
|
+
if local is not None:
|
|
84
|
+
return local
|
|
85
|
+
return servers
|
|
86
|
+
|
|
87
|
+
|
|
67
88
|
DEFAULT_REMOTE_URL = "git@github.com:darce/workstate.git"
|
|
68
89
|
DEFAULT_REMOTE_REF = "main"
|
|
90
|
+
INSTALL_SOURCE_CHOICES: tuple[str, ...] = ("git_overlay", "package")
|
|
69
91
|
|
|
70
92
|
|
|
71
93
|
def _build_parser() -> argparse.ArgumentParser:
|
|
@@ -80,7 +102,7 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
80
102
|
|
|
81
103
|
p_install = sub.add_parser(
|
|
82
104
|
"install",
|
|
83
|
-
help="
|
|
105
|
+
help="Materialize the shared workstate-system overlay and write the manifest.",
|
|
84
106
|
)
|
|
85
107
|
p_install.add_argument(
|
|
86
108
|
"--target",
|
|
@@ -98,6 +120,16 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
98
120
|
default=DEFAULT_REMOTE_REF,
|
|
99
121
|
help=f"Tag or branch to check out (default: {DEFAULT_REMOTE_REF}).",
|
|
100
122
|
)
|
|
123
|
+
p_install.add_argument(
|
|
124
|
+
"--source",
|
|
125
|
+
choices=INSTALL_SOURCE_CHOICES,
|
|
126
|
+
default="git_overlay",
|
|
127
|
+
help=(
|
|
128
|
+
"Overlay source. 'git_overlay' keeps the existing clone-backed "
|
|
129
|
+
"default; 'package' resolves payload data from the installed "
|
|
130
|
+
"workstate-system distribution."
|
|
131
|
+
),
|
|
132
|
+
)
|
|
101
133
|
p_install.add_argument(
|
|
102
134
|
"--mcp-servers",
|
|
103
135
|
default=None,
|
|
@@ -151,7 +183,7 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
151
183
|
"--backup",
|
|
152
184
|
action="store_true",
|
|
153
185
|
help=(
|
|
154
|
-
"Archive plugin overrides under .
|
|
186
|
+
"Archive plugin overrides under .workstate/override-backups/<timestamp>/ "
|
|
155
187
|
"before a reset-overrides removal."
|
|
156
188
|
),
|
|
157
189
|
)
|
|
@@ -303,7 +335,7 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
303
335
|
"--backup",
|
|
304
336
|
action="store_true",
|
|
305
337
|
help=(
|
|
306
|
-
"Archive plugin overrides under .
|
|
338
|
+
"Archive plugin overrides under .workstate/override-backups/<timestamp>/ "
|
|
307
339
|
"before a reset-overrides removal."
|
|
308
340
|
),
|
|
309
341
|
)
|
|
@@ -439,6 +471,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
439
471
|
target=args.target,
|
|
440
472
|
remote_url=args.remote_url,
|
|
441
473
|
remote_ref=args.remote_ref,
|
|
474
|
+
source=args.source,
|
|
442
475
|
mcp_servers=_resolve_mcp_servers(
|
|
443
476
|
args.mcp_servers,
|
|
444
477
|
no_servers=args.no_mcp_servers,
|
|
@@ -454,11 +487,18 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
454
487
|
install_codex_stop_hook=args.install_codex_stop_hook,
|
|
455
488
|
install_vscode_stop_hook=args.install_vscode_stop_hook,
|
|
456
489
|
)
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
490
|
+
if manifest.get("source_kind") == "package":
|
|
491
|
+
print(
|
|
492
|
+
f"installed workstate-system overlay: "
|
|
493
|
+
f"workstate-system=={manifest['package_version']} -> {args.target}",
|
|
494
|
+
file=sys.stdout,
|
|
495
|
+
)
|
|
496
|
+
else:
|
|
497
|
+
print(
|
|
498
|
+
f"installed workstate-system overlay: "
|
|
499
|
+
f"{args.remote_url}@{manifest['remote_sha']} -> {args.target}",
|
|
500
|
+
file=sys.stdout,
|
|
501
|
+
)
|
|
462
502
|
if isinstance(manifest.get("override_backup_path"), str):
|
|
463
503
|
print(f"override backup: {manifest['override_backup_path']}", file=sys.stdout)
|
|
464
504
|
if isinstance(manifest.get("state_backup_path"), str):
|
|
@@ -503,7 +543,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
503
543
|
backup_overrides=args.backup,
|
|
504
544
|
enforce_required_surfaces=not args.no_enforce_required_surfaces,
|
|
505
545
|
)
|
|
506
|
-
except FileNotFoundError as exc:
|
|
546
|
+
except (FileNotFoundError, ValueError) as exc:
|
|
507
547
|
print(str(exc), file=sys.stderr)
|
|
508
548
|
return 1
|
|
509
549
|
print(
|
|
@@ -520,7 +560,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
520
560
|
report = repair(
|
|
521
561
|
target=args.target,
|
|
522
562
|
force_dirty=args.force_dirty,
|
|
523
|
-
mcp_servers=
|
|
563
|
+
mcp_servers=_resolve_managed_servers(args.target, args.mcp_servers),
|
|
524
564
|
plugin_overrides=args.plugin_overrides,
|
|
525
565
|
)
|
|
526
566
|
except FileNotFoundError as exc:
|
|
@@ -540,7 +580,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
540
580
|
|
|
541
581
|
if args.command == "mcp-sync":
|
|
542
582
|
try:
|
|
543
|
-
servers =
|
|
583
|
+
servers = _resolve_managed_servers(args.target, args.mcp_servers)
|
|
544
584
|
except (FileNotFoundError, json.JSONDecodeError) as exc:
|
|
545
585
|
print(f"mcp-sync: --mcp-servers: {exc}", file=sys.stderr)
|
|
546
586
|
return 2
|