Publishing was reachable only by walking the whole chain blind. The editor
offered one link — "저장본 검증" — and the word "게시" appeared nowhere until
three screens later, so an author with a finished draft could not tell how to
publish it. The working-copy list already named the next step, but the name was
plain text with nowhere to go.
The editor now shows the whole path: 검증 → 미리보기 → 게시, each a link. The
list's next step is a link to that step. Neither weakens the gates — an
unvalidated document is still refused at preview, an unpreviewed one at
publish. What changes is that the order stops being a secret.
What is blocking publication now appears where it gets fixed. The validation
report lived on its own screen, so an author read the list, navigated back, and
had to remember which field each item meant. The editor shows the same issues
above the fields, in red, and says plainly when they describe an older saved
version rather than the current one.
The clock is read during render, not captured as an effect dependency. It is a
new function on every render of the provider, so depending on it refetched the
document endlessly — the editor never settled, and a tab click did not even
register. A value you are asking about now does not belong in a dependency
array.
Publishing needs a topic and nothing could create one. The backend now owns
that surface; this is its consumer — the management contract vendored, a
gateway over its nine operations, and one Studio screen that lists, creates,
and deletes topics and projects.
The screen adds no CSS. It reuses the classes the working-copy list already
uses, so it inherits Studio's spacing, type, and colour rather than growing a
second visual vocabulary beside them. Scope stops at list/create/delete:
renaming, phase changes, and visibility are implemented in the backend and
declared in the contract, but their screens are a separate design.
Two real defects surfaced while making the public port async, and both would
have shipped:
The search page and the header search dialog shared a query key. With an empty
query, `["tech-log","search",""]` was identical for both, so react-query
handed one surface the other's cache — different shapes — and the page died
reading a field that was not there. Keys now name the surface.
The explore filter's selects are uncontrolled and read `defaultValue`, which
React applies once. Their options arrive later now, so the first render had
nothing to match and the value stayed empty: a topic in the URL no longer
showed as selected. The form key includes whether the catalog has arrived, so
it remounts with the options present. Controlled inputs would be the other
answer, but this form submits to build a URL — the URL owns the value.
The route brought its own bookkeeping: a build chunk, a manual accessibility
evidence file, and the CI artifact baseline that counts them. The gate pins a
digest of its own shape precisely so a new route cannot slip in without that
count being reviewed.
Test harnesses that render public screens now assemble the query providers and
await the settled paint, because the screens they render became async.
Adds an Asset Picker and upload dialog to the CASE editor so authors can
insert `:::evidence` directives that reference backend assets, and opens
projectWorkingCopy's two evidence gates so Instant Preview accepts a key
backed by a freshly loaded READY asset instead of only the one hardcoded
legacy key. The editor screen now owns the loaded Asset list so the
Picker, the upload dialog, and Instant Preview all read the same array,
and a freshly uploaded asset appears in the preview without a refetch.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Adds TECH_LOG_STUDIO_SOURCE (MOCK | HTTP, default MOCK) to the V2 runtime
config schema so a build can switch createTechLogFeatureInstalledInput
between the mock and HTTP Studio gateways without a rebuild. V1 documents
predate the key and always normalize to MOCK. The HTTP gateway is
constructed with only { operations } per Task 4's actual signature -
no CSRF provider is wired here; that lands with attachCredentials at a
later composition-root task.
Updates every existing Studio test call site to the new required
createTechLogFeatureInstalledInput(context) signature via a shared
tests/helpers/studio-install-context.ts MOCK fixture, so the whole
existing Studio suite keeps exercising the mock adapter unchanged.