Replace the hand-rolled byte scanner in strip_css_comments with a
str::find loop over "/*" and "*/".
Drop the quote and backslash tracking. The stylesheet language has no
string literals: parse_declarations ends a value at the first ';' or
'}' with no quote awareness, and values flow into AttrValue::String
verbatim, so a quoted model name is just an unknown model. Tracking
quotes here also created a failure mode the simple scan does not have.
An unpaired apostrophe, as in `model: don't`, disabled comment
stripping for the rest of the input and then blamed a well-formed
comment for the parse error.
Also drop the Cow and its copied_through watermark. They avoided one
allocation on a graph attribute of a few hundred bytes, parsed once per
workflow load, in a function whose caller already clones the attribute
and whose parser allocates a String per property and per value.
Extract excerpt() for the error snippets. The two existing call sites
sliced raw bytes at index 20, which panics when a multi-byte character
straddles the cutoff; model_stylesheet is arbitrary user text, so that
was reachable.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Node classes were built in two places. The parser split the `class`
attribute on commas and whitespace, but the import transform re-split the
raw attribute on commas only. A space-separated class on an import
placeholder became a single class name, so stylesheet rules did not match.
That included the `class="fast shared"` example in the imports docs.
- add `Node::add_class`, replacing the duplicate append helpers in
`SemanticState` and `ImportTransform`
- read `node.classes` in `placeholder_config` instead of re-parsing the raw
attribute, so class splitting happens in exactly one place
- name the separator rule `split_class_attr`, splitting on commas and then
whitespace so empty entries need no trimming
- drop the unused `Node::class` accessor that invited the re-parse
- keep the comma-compatibility note in the DOT attribute reference only
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
## Summary
Implemented ACP support as a first-class Fabro backend alongside `api`
and `cli`. This adds a new `fabro-acp` crate using the official ACP Rust
crates, routes `backend=\"acp\"` for agent and prompt nodes, adds
sandbox stdio support for local/Docker/test-support paths, emits ACP
workflow events/projections, updates server steerability handling,
validation, documentation, and black-box CLI coverage.
## Test Plan
Passed strict non-live verification:
- `ulimit -n 4096 && cargo nextest run -p fabro-workflow --run-ignored
all --no-fail-fast` — 1162 passed, 0 skipped.
- `ulimit -n 4096 && cargo nextest run -p fabro-acp -p fabro-sandbox -p
fabro-workflow -p fabro-validate -p fabro-store -p fabro-server -p
fabro-cli --run-ignored all --no-fail-fast -E 'not
test(daytona_streaming_live_smoke)'` — 3125 passed.
- `cargo build --workspace` — passed.
- `ulimit -n 4096 && cargo nextest run --workspace --run-ignored all
--no-fail-fast -E 'not test(daytona_streaming_live_smoke)'` — 5666
passed.
- `cargo +nightly-2026-04-14 fmt --check --all` — passed.
- `cargo +nightly-2026-04-14 clippy --workspace --all-targets -- -D
warnings` — passed.
Live-environment tests skipped/excluded under explicit user override:
- `daytona_streaming_live_smoke` was excluded from final nextest runs
because it requires live Daytona infrastructure and `DAYTONA_API_KEY`.
- Confirmed with `env -u DAYTONA_API_KEY cargo test -p fabro-sandbox
--features daytona --test daytona_streaming_live
daytona_streaming_live::daytona_streaming_live_smoke -- --ignored
--exact --nocapture`: failed fast with `DAYTONA_API_KEY must be set to
run this live smoke test`.
Invert the docs convention so the Mintlify-published site lives under
docs/public/ and internal artifacts (strategy docs, brainstorms, plans,
etc.) sit at docs/ root or docs/internal/. Tools that default to writing
into docs/ now land in the catch-all instead of leaking into the
published tree.
- Move Mintlify content (administration/, agents/, api-reference/,
changelog/, core-concepts/, examples/, execution/, getting-started/,
human-tools/, integrations/, languages/, reference/, tutorials/,
workflows/, images/, logo/, docs.json, favicon.svg, dot-highlight.js)
into docs/public/.
- Collapse docs-internal/ into docs/internal/.
- Update Rust path references (fabro-api/build.rs, fabro-server,
fabro-dev), TypeScript generator arg, CI path filters, clippy.toml
reasons, AGENTS.md/CLAUDE.md, and README.md image refs.
Mintlify dashboard project root must be updated to docs/public/ in a
follow-up. .mintignore move/trim and .claude/skills/ updates land in a
separate commit.
2026-04-27 07:21:13 -07:00
Renamed from docs/workflows/stylesheets.mdx (Browse further)