Journey Stage 1a's core: `pmacs .` opens the directory instead of
exiting 1, and local startup stops being a second implementation of
path resolution.
`EditorState::open` now calls `EditorCore::resolve_target_buffer` --
the primitive whose own doc comment says it exists "so two
path-normalization, dedup, and hook transactions cannot drift apart",
and which local startup had never been a caller of.
`resolve_target_buffer` returns a typed `ResolvedTarget` rather than
`(BufferId, HookKind)`, with a `Directory` arm checked ahead of the
load. Without it the load runs and fails: `File::open` succeeds on a
directory and `read_to_end` returns EISDIR, which is not `NotFound`, so
the `[new file]` arm never fired.
A directory creates no buffer. It dispatches a resolver chain: the
short-circuit `path.open-directory` hook, which no builtin subscribes
to, and then `pmacs.path.directory_handler`, which dired defaults. The
split is forced rather than chosen -- hook callbacks only append and
builtins load before init.lua, so a subscribing builtin would always
claim before any user listener could run. A raising listener stops the
chain and suppresses the fallback.
The listing is async and the daemon bootstrap is not, so the whole
post-await commit runs inside a new `pmacs.window.commit_to`: it
validates the destination -- frontend live, window live, buffer
unchanged, window replaceable -- BEFORE invoking its callback, then
scopes the acting frontend for its extent. Validating at display time
would be four dired mutations too late.
That scope is deliberately not `InteractiveCommandOrigin`, which does
not reach the core-ambient APIs and is authenticated user-command
authority a background continuation must not acquire.
The dedication rule is extracted into one `window_accepts_buffer`
shared by exact display, the display probe, and the new preflight, with
`incoming: Option<BufferId>` -- `None` means "the replacement does not
exist yet" and refuses a dedicated window.
`display_file` keeps its directory-is-an-error contract and does not
enter the chain; find-file's accept arm depends on it.
Framing: docs/journey-stage1a-framing.md rev 5 (Q#JR1-JR15).