Skip to content

One door: promptforge-api as the single public promptforge crate - #37

Closed
vinniefalco wants to merge 20 commits into
cppalliance:masterfrom
vinniefalco:one-door-promptforge-api
Closed

One door: promptforge-api as the single public promptforge crate#37
vinniefalco wants to merge 20 commits into
cppalliance:masterfrom
vinniefalco:one-door-promptforge-api

Conversation

@vinniefalco

Copy link
Copy Markdown
Member

Summary

Outside consumers previously needed seven promptforge-* crates to embed the executor. This PR establishes exactly two doors and enforces them in the build:

  • promptforge-api (renamed from promptforge-core) is the only promptforge-* crate outside products may depend on. run() is now run(&Prompt, &str, ResolutionContext, RunConfig): the store handle moved into RunConfig with a promptforge_vfs::empty() default, and the ResolutionContext tool picker is optional, so capability-free agents pass None. Only the parser and client re-export modules survive.
  • shared-promptforge-api (renamed from promptforge-core-support) carries the cross-product vocabulary: the Tool contract and ToolCatalog (the dissolved promptforge-tools crate), the host-facing model vocabulary (ModelId, ModelCatalog, ModelDescriptor, ThinkingMode), StreamDelta, events/metrics, Observer, and CancelHandle. Zero product-crate dependencies.
  • The .lua agent program path is gone: discovery lists .md stems under agents.path, chat.md shadows the embedded built-in, and the promptforge-agent crate, the promptforge facade, UserInputTool, and the dead product-integration-tests crate are all deleted. Guides rewritten to match.
  • Workshop consumers migrated: workshop-sessions depends on exactly the two doors; workshop-gateway and workshop-protocol on shared-promptforge-api alone. The gateway progress subscription was reimplemented over the workshop's own GatewayClient (dropping the promptforge-model-client edge), and agent model-client construction moved into workshop-sessions.
  • Enforcement: xtask (renamed build-xtask) gains a product_boundary_violations tidy check codifying the full product-boundary matrix across all dependency kinds, run by cargo test -p build-xtask on every run, with injected-violation tests proving it fails when it should.

Notable fixes along the way

  • Dropped runs leaked pending user_input waits (the supervisor's close detached leaf tasks); Drop for Scheduler now aborts in-flight leaf I/O, with a regression test.
  • The dead subscribe_progress transport in promptforge-model-client was deleted after its replacement landed (debt-collected post-run), and workshop-gateway's shared-progress edge now declares the serde feature it was silently inheriting.

Verification

  • Full suite: 3028 passed + workshop pair 199 passed, 0 failures
  • cargo clippy (both halves, -D warnings), cargo fmt --all --check, doctests: clean
  • cargo metadata --locked: no outside-product edge to any promptforge-* crate except promptforge-api
  • Boundary harness: 18/18 including injected-violation coverage

Every agent session now runs a Markdown prompt on the unified runtime; the standalone Lua program path is retired. Discovery lists Markdown file stems, a same-named directory file still shadows the embedded built-in chat, and a leftover Lua program is ignored rather than served. Launch, input recording, and run-error handling no longer branch on program kind, and the model-catalog builder and tool wiring that only the retired path consumed are gone.

- `AgentSource` keeps a single `Markdown` variant: every session, directory or built-in, is a Markdown prompt on the unified runtime.
- `AgentRunError` replaces the retired runtime's error type session-locally: cancellation maps to `Interrupted`, every other failure to an operator-facing message.
- `discover_agents` lists `.md` stems only; a `.lua` file is never an agent.
- `agent_source` lets a directory `chat.md` shadow the built-in while a directory `chat.lua` shadows nothing.
- `accept_input` always records consumer-side; the producer-side branch for relaunched Lua history is gone.
- `build_model_catalog` and `FALLBACK_CONTEXT` are deleted; the session no longer parses gateway catalog JSON into model descriptors.
- `launch_lua` is deleted, and the supervisor no longer builds a `UserInputTool` catalog for the run.

Design: removes dispatch-on-tag @ crates/workshop-sessions/src/agents/session.rs::AgentSource
Design: removes stringly-typed @ crates/workshop-sessions/src/agents/session.rs::build_model_catalog deps: Option<Vec<serde_json::Value>> boundary: wire
Design: removes speculative-abstraction @ crates/workshop-sessions/src/agents/supervisor/effects.rs::RunFactory
Plan: vibe/2026-09-12-5-one-door-promptforge-api.md
The session carried two constructs for one job, suspending an agent program until its operator answers: a host-primitive tool that served only the retired standalone script path, and the input broker behind the script-side input call. This change deletes the tool along with its constructor, its trait implementation, and its unit tests, and removes its re-exports from both crate roots. The documentation now presents the broker as the single input path. The wait registry, the drop guard, and the broker itself are unchanged.

- `crates/workshop-sessions/src/input/tool.rs::UserInputTool` - Deletes the struct, its constructor, and its Tool trait implementation; the session's input broker is now the single construct that opens a wait, announces it, and suspends until the operator answers.
- `crates/workshop-sessions/src/input/tests.rs` - Removes the six unit tests that exercised the deleted tool's contract, including byte-exact text resumption and cancel framing; the registry-level tests such as reconnect resend remain.
- `crates/workshop-sessions/src/lib.rs` - Drops the deleted tool from the crate-root re-exports, and the server crate root does the same, so the type leaves the public API of both crates.

Design: removes parallel-abstraction @ crates/workshop-sessions/src/input/tool.rs::UserInputTool boundary: pub
Plan: vibe/2026-09-12-5-one-door-promptforge-api.md
The standalone Lua agent-program executor is removed so a single runtime remains for both document prompts and agent loops. The integrator facade drops its second entry point and now exposes only the document-prompt pipeline. The server's socket integration tests drive their fixture agents as Markdown prompts on the unified runtime instead of Lua programs on the deleted executor. A new drop guard on the run scheduler aborts in-flight leaf tasks when a host tears a run down mid-suspension, so closing a session no longer strands a pending input wait.

- `crates/promptforge-agent`: the entire crate is deleted - `run_agent`, `run_agent_with_client`, `AgentConfig`, `AgentError`, and their tests - ending the sibling executor over the shared substrate; agents now run as Markdown prompts.
- `crates/promptforge/src/lib.rs`: the `agent` re-export module is removed, leaving `pipeline` as the facade's only entry point; the crate's manifest and README drop the second dependency and entry point to match.
- `crates/workshop-server/tests/it/chat_gate.rs::AgentError`: a test-local error enum mirrors the supervisor's run-outcome type, replacing the import from the deleted crate; its `Program` variant carries only the rendered message, dropping the boxed source.
- `impl Drop for Scheduler<'_>`: dropping the driver future aborts every handle in `io_tasks`, applying the cancellation path's abort on the drop path; a detached task would otherwise strand a broker wait or gateway round and never emit `input_cancelled`.
- `crates/workshop-server/tests/it/agents.rs::ECHO_MD`: the echo fixture is rewritten from a Lua program to a Markdown prompt whose loop calls `user_input()` directly and runs each chat round through `models.loop`.
- `crates/workshop-server/tests/it/agents/turns.rs`: a turn's durable record is now input, thinking, reply; the direct `user_input` call is not a tool call, so no `tool_call_update` event exists and the log indices shift down by one.
- `crates/promptforge/tests/paths.rs::pipeline_paths_resolve`: the compile-level path proof no longer covers an agent entry point, because none remains.

Design: removes parallel-abstraction @ crates/promptforge-agent
Design: removes facade @ crates/promptforge/src/lib.rs::agent
  boundary: pub
Design: new parallel-abstraction @ crates/workshop-server/tests/it/chat_gate.rs::AgentError
Plan: vibe/2026-09-12-5-one-door-promptforge-api.md
The agent documentation now teaches an agent as an ordinary Markdown prompt document discovered from a directory, replacing the standalone Lua program model. The built-in chat is presented as an embedded prompt that a same-named directory file shadows, and the full-loop walkthrough keeps the conversation in a retained message list instead of rebuilding it from the event log on every turn. A new crate README states the discovery, launch, and session contract in the same terms.

- `crates/workshop-sessions/README.md` is new and defines the subsystem contract: discovery lists `.md` file stems under `agents.path`, the embedded `chat` prompt guarantees a working agent with no directory at all, and launch goes through `Prompt::parse` and `promptforge_core::run`.
- `guide/src/agent/01-agent-programs.md` redefines the agent as a prompt document whose only extras are the session-installed `user_input()` and `ui()`; the smallest example is now frontmatter, one section, and one Lua block.
- `guide/src/agent/10-the-full-loop.md` rewrites the full program around a retained `messages.new()` history: `history:user(text)` appends operator input, `models.loop(models.get(selected), history)` runs each turn under `pcall`, and the model is re-read from `ui().selected_model` every turn.
- `guide/promptforge-agent-guide.md` and `guide/promptforge-workshop-guide.md` carry the same rewrites into the single-file guide mirrors.
- `guide/src/introduction.md`, `guide/src/workshop/01-application.md`, and `guide/src/workshop/06-chat.md` swap the remaining `.lua` references for `.md` in the agent-set pointer, the `agents.path` config description, and the chat chapter.
- `call`, `fanout`, and `jump` absence claims are dropped along with the Lua-coroutine execution description; the rewritten chapters no longer enumerate host calls that do not exist.

Plan: vibe/2026-09-12-5-one-door-promptforge-api.md
Renames the shared host-support crate to its final shared-vocabulary name, ahead of later work that sinks model and tool vocabulary into it. Every dependent manifest, import path, doc comment, and lockfile entry moves to the new name while the crate's own sources move unchanged. No runtime behavior changes.

- `crates/shared-promptforge-api/Cargo.toml`: the package takes the new name with version, edition, and license still workspace-inherited; its dependency set is unchanged.
- `Cargo.toml`: the workspace dependency entry now points at the renamed crate path, and all eight dependent manifests follow it.
- `crates/promptforge-core/src/lib.rs`: the public re-export of `CancelHandle` now sources from the renamed crate, so existing consumer paths keep working unchanged.
- `crates/shared-promptforge-api/src/lib.rs`: moved with 100% similarity; no item was added, removed, or re-scoped in the rename.

Plan: vibe/2026-09-12-5-one-door-promptforge-api.md
The model identity, catalog, descriptor, and thinking-mode vocabulary moves out of the model client into the shared API crate, joined by the streaming delta type hosts name in delta callbacks, so every crate and host can name these types without depending on transport machinery. The model client keeps its transport, binding, and completion types and re-exports the moved symbols through their historical paths, so existing imports keep resolving. Because the catalog now lives in another crate, its constraint-filtering helper becomes an extension trait in the model client, where the bind-options type still lives. The validation tests move with the types.

- `crates/shared-promptforge-api/src/models.rs` becomes the canonical home for the identity, catalog, descriptor, and thinking-mode types, moved with their validating constructors and unit tests.
- `crates/shared-promptforge-api/src/wire.rs` holds the streaming delta enum, the one wire type a host names in its delta callback.
- `crates/promptforge-model-client/src/model.rs::ModelCatalogFiltered` is a new doc-hidden extension trait carrying the catalog filtering helper, since the catalog is now foreign while the bind options stay in the model client.
- `crates/promptforge-model-client/src/model.rs` and `crates/promptforge-model-client/src/client.rs` re-export the sunk symbols so the historical import paths keep resolving.
- `crates/promptforge-model-client/src/model/ids.rs` is deleted; its types and tests now live in the shared crate.

Design: replaces encapsulated-invariant @ crates/shared-promptforge-api/src/models.rs::ModelCatalog was: crates/promptforge-model-client/src/model.rs::ModelCatalog
Design: replaces encapsulated-invariant @ crates/shared-promptforge-api/src/models.rs::ModelId was: crates/promptforge-model-client/src/model/ids.rs::ModelId
Design: replaces value-object @ crates/shared-promptforge-api/src/models.rs::ModelDescriptor was: crates/promptforge-model-client/src/model/options.rs::ModelDescriptor
Design: new speculative-abstraction @ crates/promptforge-model-client/src/model.rs::ModelCatalogFiltered
Design: extends facade @ crates/promptforge-model-client/src/model.rs
Design: extends facade @ crates/promptforge-model-client/src/client.rs
Plan: vibe/2026-09-12-5-one-door-promptforge-api.md
The tool contract vocabulary moves out of its standalone crate and into the shared API crate as a public module, leaving a single vocabulary home that every other crate in the workspace may depend on. Each former dependent now imports the contract types from that module, and the existing compatibility re-export keeps established use paths working unchanged. The deprecated free-function alias for guard wrapping is removed, so the method form is the only spelling. The retired crate's manifest, documentation, and workspace entry are deleted.

- `crates/shared-promptforge-api/src/tools.rs` - The full contract vocabulary (trait, catalog, identity, output, and error types with their kinds) becomes a public module of the shared crate; the content is the retired crate's source with documentation paths rewritten, and the crate manifest gains the async-trait edge the trait needs.
- `crates/promptforge-core/src/tools.rs` - The compatibility re-export is kept but now sources the vocabulary from the shared crate's module, so existing core paths resolve to the identical trait and types.
- `crates/promptforge-core/src/tools/tests.rs` - The re-export identity tests now pin against the shared crate's path; a lookalike re-export would fail to compile rather than pass silently.
- `crates/promptforge-tools/Cargo.toml` - The standalone crate is deleted with its manifest, docs, and workspace dependency entry; every former dependent now depends on the shared crate instead.
- `crates/shared-promptforge-api/src/untrusted.rs` - The deprecated `wrap` alias is removed; `GuardNonce::wrap` remains the only spelling.

Design: replaces encapsulated-invariant @ crates/shared-promptforge-api/src/tools/registry.rs::ToolCatalog was: crates/promptforge-tools/src/registry.rs::ToolCatalog
Plan: vibe/2026-09-12-5-one-door-promptforge-api.md
The runtime crate takes the api name and becomes the one library door for outside consumers, absorbing the integrator-facing package metadata from the retired facade, which is deleted outright with its path-resolution test. Every reference across dependents, tests, benches, and guides follows the rename, including the Lua shim chunk name whose verbatim path renders in tracebacks. No runtime behavior changes; the executor test suite moves with the crate.

- `crates/promptforge/src/lib.rs` deletes the re-export-only facade crate outright, with its manifest, docs, and compile-level path test; no alias or shim is left behind.
- `Cargo.toml` collapses the promptforge and promptforge-core workspace entries into one promptforge-api entry, and the lockfile drops the facade package.
- `crates/promptforge-api/Cargo.toml` absorbs the retiring facade's integrator-facing keywords and categories and retitles the description as the PromptForge API.
- `crates/promptforge-lua/src/coro.rs` points SHIM_CHUNK_NAME at the promptforge-api path so shim frames in tracebacks keep rendering as clickable file:line references, with the coroutine tests asserting the new spelling.

Design: removes facade @ crates/promptforge
Plan: vibe/2026-09-12-5-one-door-promptforge-api.md
Running a prompt no longer requires a tool picker or a store handle: capability-free agents pass no picker, and the store handle rides on the run configuration with a stock in-memory default. A capability bind attempted without a picker fails as a binding error naming the missing picker. The crate's public surface narrows to the parser and gateway client modules; hosts name the model, observe, tools, and store vocabulary through the shared crate, with the completion error types re-exported through the client module.

- `ResolutionContext` now holds an optional picker, so capability-free agents pass `None` instead of building an empty one.
- `RunConfig` gains the store handle as a field defaulting to the stock handle, set through a new `vfs` builder; `run` drops its separate store parameter.
- `NoPicker` is the decision source behind a picker-less run: every tool capability decision fails as an unbound bind and the near-duplicate scan is vacuous.
- `crates/promptforge-api/src/lib.rs` narrows the public re-exports to `parser` and `client`; the model, observe, store, and tools modules go crate-internal and the root cancel-handle re-export is dropped.
- `run` still overlays a defensive memory store when the config's handle lacks the mount, so a run never fails for want of the mount.
- `RuntimeResolution` fails a described-model bind without a picker as a binding error whose detail names the missing picker, rather than resolving through an empty catalog.

Design: extends parameter-object @ crates/promptforge-api/src/execute/config.rs::RunConfig boundary: pub
Design: new strategy @ crates/promptforge-api/src/resolve.rs::RuntimeResolution
Design: new surface-growth @ crates/promptforge-api/src/execute/gateway.rs::ResolutionContext boundary: pub
Plan: vibe/2026-09-12-5-one-door-promptforge-api.md
The progress subscription now runs over the workshop's own gateway client instead of a helper imported from another crate, so the event stream is authenticated and decoded through one door. Decoding keeps the strict posture the subscriber always had: only blank-line-terminated blocks dispatch, heartbeat comments are skipped, and a block that grows past a hard size bound is refused rather than buffered without limit. A non-success answer such as a rejected token surfaces as a bounded, control-escaped status error rather than a relayed response, and an undecodable event degrades to a single error item without ending the stream. Observable behavior is unchanged.

- `subscribe_progress` subscribes to the gateway progress endpoint through the client's own base URL and bearer. Only the wait for the response headers is bounded; the long-lived stream itself carries no deadline, and resubscription is the caller's decision.
- `GatewayError::Status` and `GatewayError::Malformed` carry a bounded, control-escaped error body and per-event decode failures, so a hostile body cannot forge log lines or smuggle terminal control sequences into a diagnostic.
- `decode` yields an undecodable block as one error item and continues; a mid-stream read failure or a block oversized past the one-megabyte bound yields one error item and ends the stream, and an incomplete trailing block is discarded.
- `gateway_progress.rs` drops the `promptforge_model_client::model::subscribe_progress` import; the progress task subscribes through the snapshot's client.

Design: new surface-growth @ crates/workshop-gateway/src/gateway.rs::GatewayClient::subscribe_progress boundary: pub instead-of: layer-violation: promptforge_model_client::model::subscribe_progress across the forbidden promptforge edge
Design: new surface-growth @ crates/workshop-gateway/src/gateway.rs::GatewayError::Status boundary: pub
Design: new surface-growth @ crates/workshop-gateway/src/gateway.rs::GatewayError::Malformed boundary: pub
Design: new surface-growth @ crates/workshop-gateway/src/gateway/progress.rs::ProgressEventStream boundary: pub
Design: new pure-function @ crates/workshop-gateway/src/gateway/progress.rs::block_end deps: &[u8]
Design: new pure-function @ crates/workshop-gateway/src/gateway/progress.rs::parse_event_block deps: &[u8]
Plan: vibe/2026-09-12-5-one-door-promptforge-api.md
The gateway snapshot no longer carries a prebuilt agent completion client. Each consumer now builds its own client from the snapshot's base URL and bearer at the moment it needs one, through the public API's client re-exports. This drops the gateway crate's model-client edge, and the launch and relaunch paths still refuse with the same unusable-gateway error when the key or URL cannot build a client.

- `agent_client` builds the completion client from one snapshot's base URL and bearer, returning None when the key or URL cannot build a client. Construction moves out of the gateway crate into the sessions crate that consumes it.
- `LaunchRefusal::GatewayUnusable` still fires at launch and at supervisor relaunch when the client cannot be built, now computed from the snapshot's URL and key rather than a stored client.
- `GatewaySnapshot` drops the `model_client` field and its accessor; a snapshot now carries only the HTTP client, base URL, bearer, generation, and identity.
- `promptforge-model-client` leaves the workshop-gateway manifest and lockfile, leaving shared-promptforge-api as that crate's only promptforge edge.

Design: replaces pure-function @ crates/workshop-sessions/src/agents.rs::agent_client deps: &str,&str was: crates/workshop-gateway/src/gateway_binding.rs::model_client
Plan: vibe/2026-09-12-5-one-door-promptforge-api.md
The session and server crates now reach the runtime through the two surviving library crates alone. The hand-built picker, tool catalog, and store plumbing they used to assemble is deleted because the runtime now supplies stock defaults for each, and the manifests drop the retired dependency edges.

- `crates/workshop-sessions/Cargo.toml` drops the model-client, tool-picker, and vfs edges, leaving `promptforge-api` and `shared-promptforge-api` as the crate's only promptforge dependencies; `Cargo.lock` shrinks to match.
- `crates/workshop-server/Cargo.toml` makes the same collapse for the shell's test-only dependencies.
- `RunFactory` no longer stores a picker or a store handle; the removed field documentation admitted the picker never bound tools, so relaunches now rely on the runtime's stock defaults.
- `run_markdown_agent` builds the catalog with `ToolCatalog::default()` and calls `ResolutionContext::new(None, &models, &tools)`, so capability-free agents run with no picker and the default store handle.
- `shared_promptforge_api::wire::StreamDelta` and `shared_promptforge_api::models::ModelCatalog` replace the retired model-client imports across the session, supervisor, and test code.
- `spawn_restored_chat` and `run_builtin_chat` exercise the new defaults, keeping the server integration gate and the session suite green in the same commit.
- `MarkdownRunParts` loses its `vfs` and `picker` fields; the supervisor no longer constructs an empty picker or store at any of its relaunch sites.

Design: removes speculative-abstraction @ crates/workshop-sessions/src/agents/supervisor/effects.rs::RunFactory
Plan: vibe/2026-09-12-5-one-door-promptforge-api.md
Remove the boundary-neutral end-to-end test crate that bridged the gateway and the model client. The crate was dead weight: its live-inference scenario was ignored unless explicitly opted in, and the one-door product boundary leaves no place for a test package that depends on both products at once. The lockfile entry goes with it.

- `crates/product-integration-tests/Cargo.toml` - Deleted with the entire crate; it declared a publish-forbidden, dev-dependency-only test package reaching across the product boundary into both `gateway` and `promptforge-model-client`.
- `crates/product-integration-tests/tests/gateway_client.rs` - Deletes the 227-line suite: the TestServer harness with graceful shutdown, the fake SSE backend, and the completion helper.
- `real_model_client_completes_through_gateway` - Ran unignored and asserted a pong reply through an in-process gateway; it was the crate's only test that ran without an opt-in.
- `real_model_client_completes_through_local_gateway` - Was ignored behind `PROMPTFORGE_LIVE_LOCAL` and downloaded llama-server plus a Qwen3 model, so its removal costs no routine coverage.
- `Cargo.lock` - Drops the product-integration-tests 0.3.0 package entry with its six declared dependencies.
- `product-integration-tests` - Leaves no successor behind: the diff adds no replacement for the deleted wire-contract coverage, and no root manifest edit was needed because the crate never appeared in the workspace dependency list.

Plan: vibe/2026-09-12-5-one-door-promptforge-api.md
Rename the workspace automation crate so it carries the same build prefix as the sibling tooling crate. The command alias keeps its existing spelling and now points at the renamed package, so the tidy report and the architecture test suite run exactly as before. Documentation, comments, and the lockfile are updated to match the new name.

- `.cargo/config.toml` retargets the `xtask` alias to `run -p build-xtask --`, keeping the command spelling stable while the package name changes.
- `crates/build-xtask/Cargo.toml` renames the package to `build-xtask`; the directory move carries `new_crate.rs` across unchanged and `main.rs` and `tidy.rs` with doc-only edits.
- `crates/build-xtask/src/tidy.rs` changes only doc text and one test failure message; every architecture check is byte-for-byte intact.
- `Cargo.lock` swaps the `xtask` entry for `build-xtask` with an identical dependency set.

Design: new shotgun-surgery @ crates/build-xtask
Plan: vibe/2026-09-12-5-one-door-promptforge-api.md
Adds a workspace lint that classifies every crate into a product family by package name and rejects dependency edges the product matrix forbids, including any reach past the single public entry crate into the internal substrate crates. The check covers normal, dev, build, and target-specific dependency tables, resolves renamed packages before classification, and reports unreadable or unparseable manifests as violations rather than skipping them. It runs as part of the existing lint harness in the build tooling, and the workspace documentation now states the rule the harness enforces.

- `crates/build-xtask/src/product.rs` holds the new check as its own module, keeping `tidy.rs` under the 500-line ceiling.
- `boundary_breach` encodes the matrix as a match over family pairs, with the one-door rule applied after the per-family rules.
- `product_boundary_violations` binds only workspace members; a crates.io package that happens to carry a product prefix is not checked.
- `manifest_dependencies` resolves `package` renames before classification so an aliased dependency cannot evade the matrix.
- `workspace_crates` turns unreadable directories, unreadable manifests, unparseable TOML, and missing package names into violations instead of passing them silently.
- Nine tests cover the live workspace, injected violations in temporary workspaces, dev, build, and target tables, package renames, and family classification.

Design: new value-object @ crates/build-xtask/src/product.rs::Family
Design: new pure-function @ crates/build-xtask/src/product.rs::family deps: str
Design: new pure-function @ crates/build-xtask/src/product.rs::boundary_breach deps: Family,str
Design: new pure-function @ crates/build-xtask/src/product.rs::manifest_dependencies deps: toml::Value
Plan: vibe/2026-09-12-5-one-door-promptforge-api.md
Records that the closing verification pass has finished. The full test suite, lint and format checks, dependency metadata inspection, and stale reference sweeps all ran clean, so the work is marked done.

Plan: vibe/2026-09-12-5-one-door-promptforge-api.md
Plan: vibe/2026-09-12-5-one-door-promptforge-api.md
The progress subscription moved to the workshop's own gateway client, leaving this copy without a single caller. Delete the function, its SSE decoder helpers, its eight tests, and the README mention so one progress decoder remains.

- \crates/workshop-gateway/Cargo.toml\: the \shared-progress\ edge gains the \serde\ feature its progress decoder needs; the feature previously arrived through unification with the deleted code's crate edge.
- \utures-util\ and \shared-progress\ leave \promptforge-model-client\ with the deleted code; neither has a remaining use in the crate.
The comment described .lua discovery and no agents on a missing directory; discovery lists .md stems and always offers the embedded chat built-in. Rewrite it to the shipped contract, including the unreadable-chat.md error and the chat.md shadowing rule.
The public doc comment on \ProgressEventStream\ linked to the crate-private \MAX_EVENT_BLOCK\ constant, which rustdoc rejects under -D warnings. Render both mentions as plain code spans instead; the constant stays private.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant