Files
ThothII/task-10-report.md
T

4.4 KiB

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:

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
npx vitest run
# 51 files passed, 398 tests passed

Round-2 focused verification:

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.