- Updated the `pickPluginFields` function to support legacy input aliases, improving compatibility with existing plugin structures.
- Added tests to ensure the new input handling works correctly with legacy inputs when resolving plugin snapshots.
- Enhanced CSS styles for subcategory elements in the plugin home section, improving visual clarity and user experience.
- Introduced new tests for subcategory filtering within the active workflow lane, ensuring accurate plugin categorization.
This update significantly improves the plugin management experience by enhancing input handling and refining the categorization system.
- Implemented `--schema` flag for `od ui show` to return only the JSON Schema of the surface.
- Enhanced the response of `GET /api/runs/:runId/genui/:surfaceId` to include the surface spec from the AppliedPluginSnapshot.
- Introduced new flags for daemon and library commands to improve command handling and parsing.
- Added tests for the new functionality, ensuring proper behavior of the enriched responses and flag handling.
This change supports headless interactions by allowing code agents to inspect surface contracts before responding.
Plan §8.
apps/daemon/tests/plugins-dod-e2e.test.ts anchors the four §8 e2es that
don't require Playwright UI flow or the Phase 1.5 headless flag:
e2e-2 pure apply across runs: two consecutive applies share digest
and produce no FS mutation. Snapshot count stays at 0 because
applyPlugin() itself never writes to applied_plugin_snapshots.
e2e-4 replay invariance: the snapshot's prompt block (rendered via
renderPluginBlock from @open-design/contracts) is byte-equal
before and after a same-id plugin upgrade, even though the
live applyPlugin against the upgraded plugin produces a
different manifestSourceDigest.
e2e-6 connector trust gate: a restricted plugin that declares
od.connectors.required=[{id:'slack'}] without connector:slack
capability fails resolvePluginSnapshot with HTTP 409 / exit 66
and capabilitiesRequiredError envelope shape. Independently the
token-issuance gate (checkConnectorAccess) refuses the same
call, so even a leaked tool token can't bypass §5.3.
e2e-8 apply purity regression: 100 applies leave the project cwd
byte size unchanged, write zero .mcp.json files, and grow the
snapshot count by exactly 100 only when the resolver path
explicitly persists.
Plus a guardrail on capabilitiesRequiredError() so the §12.4 / exit-66
data shape stays stable for code agents reading it.
Daemon tests: 1443 → 1448 (+5).
Co-authored-by: Tom Huang <1043269994@qq.com>