94 lines
4.4 KiB
Markdown
94 lines
4.4 KiB
Markdown
# Task 10 — Workspace Registry Manager Publish UX
|
|
|
|
## Delivered
|
|
|
|
- Added a typed `WorkspacePublishDialog` with an explicit two-stage flow: validate the
|
|
canonical draft, then confirm publication. The dialog displays the action and pinned base
|
|
revision before a request can be sent.
|
|
- Connected the workspace editor's Publish action and staged deletion action to that dialog;
|
|
local browser drafts remain local until the explicit confirmation.
|
|
- Added registry pull, workspace bundle import, and Blob-URL export controls. Imports are saved
|
|
as browser-only drafts and never publish automatically; export URLs are revoked after download.
|
|
- Added field-level 409 conflict presentation with base, local, and registry values. The only
|
|
recovery actions are Pull latest registry and Reload workspace; no automatic merge, overwrite,
|
|
or re-publication occurs.
|
|
- Kept diagnostics user-initiated and restricted UI/API draft data to canonical workspace fields.
|
|
Conflict payloads now pass through the canonical draft sanitizer and reject unknown/secret
|
|
fields before rendering.
|
|
|
|
## Review round 1
|
|
|
|
- Replaced the pull/reload-only conflict recovery with an explicit choice of the local draft or
|
|
registry value for every changed field. A revised draft can be saved only after every field has
|
|
a choice; it is rebased to the conflict's `actual.commit` and `actual.blob` and is never
|
|
published automatically.
|
|
- Kept normal validation and the explicit publish confirmation as mandatory steps after saving a
|
|
resolution. Nothing silently discards the local draft or merges it into the registry.
|
|
- Added typed expected/actual conflict revisions, displayed the active registry `status.head`
|
|
commit, and whitelisted every canonical `diagnostics.*` leaf path structurally.
|
|
|
|
## TDD evidence
|
|
|
|
- Wrote the publish-dialog and manager import/export tests before the implementation and observed
|
|
the expected RED failures (missing dialog/import control).
|
|
- Added a regression test for conflict payloads containing a secret field and observed it fail
|
|
before wiring the conflict parser through the canonical sanitizer.
|
|
- Added a regression test for a failed pull during conflict recovery and observed the original
|
|
unhandled rejection before adding the redacted in-dialog error state.
|
|
- Added review-round tests first for per-field local/registry selection, rebased draft saving
|
|
without a second publish, active-commit rendering, and every canonical diagnostics conflict
|
|
path; these initially failed against the pull/reload-only UI and narrow path parser.
|
|
|
|
## Review round 2
|
|
|
|
- Fixed recursive registry diffs so add/remove changes to optional nested diagnostics branches
|
|
report their actual canonical paths instead of the fallback `workspace.id`. The regression cases
|
|
cover both add and remove for `diagnostics.dwh_rest` and
|
|
`diagnostics.vector_rest.reversible_probe`.
|
|
- Extended the conflict-path allowlist to accept the optional `diagnostics` root and every
|
|
optional diagnostics branch. The existing structural rebase now saves an explicitly selected
|
|
branch (including an added or removed branch) in the revised browser draft, still pinned to the
|
|
registry's actual revision and requiring normal validation and confirmation before publishing.
|
|
- Wrote the backend/frontend cases first and observed the expected RED failures: backend conflict
|
|
fields were `workspace.id`, while the frontend rejected the safe conflict payload before the
|
|
resolution UI could render.
|
|
|
|
## Verification
|
|
|
|
Run in `frontend/` after the final changes:
|
|
|
|
```text
|
|
npx vitest run src/shell/WorkspacePublishDialog.test.tsx src/api/workspaces.test.ts src/shell/WorkspaceManager.test.tsx src/workspaces/drafts.test.ts
|
|
# 4 files passed, 47 tests passed
|
|
|
|
npx tsc -b
|
|
# exit 0
|
|
```
|
|
|
|
```text
|
|
npx vitest run
|
|
# 51 files passed, 398 tests passed
|
|
```
|
|
|
|
Round-2 focused verification:
|
|
|
|
```text
|
|
backend: npx vitest run test/workspace-registry.test.ts
|
|
# 1 file passed, 23 tests passed
|
|
|
|
backend: npx tsc --noEmit -p .
|
|
# exit 0
|
|
|
|
frontend: npx vitest run
|
|
# 51 files passed, 398 tests passed
|
|
|
|
frontend: npx tsc -b
|
|
# exit 0
|
|
```
|
|
|
|
The full backend `npx vitest run` was also attempted after allowing its local SSE test socket.
|
|
The Task 10 registry tests passed, but seven unchanged SSE/session tests fail because their
|
|
default, unbootstrapped registry makes session authorization return the intentional
|
|
`session storage is unavailable` response. This failure is outside the Task 10 diff; it persists
|
|
without any changed Task 10 route or test-harness code.
|