hosystem Engagements

ho-06.5 — The Workshop: right-side action panel and flat grounds

created 2026-07-11
status complete
type ho-document
project sharibako
ho 06.5
kamae 5
shape ha
splits-from ho-06
agent-tasks

    Give the Workshop the chrome it should have had. ho-06.2's ratified bet — native top-toolbar plus an overflow » menu — failed its signed-install gate ("NOT an acceptable UI"): the toolbar could not carry the action set legibly, and the overflow buried Add Shared Secret, Preview .env, and Jump to Directory behind a nested menu. The rail-revisit criterion Decision 1 named was met the same day it was written. This is the response: a collapsible right-side action panel hosting the Workshop's verbs, the toolbar emptied to a toggle, and the whole window moved from translucent system materials onto the flat pālana grounds ho-06.4 defined for exactly this moment.

    This is a new ho, not a reopening of 06.2. 06.2's document stands as the record of what was believed then; this document responds to what the gate proved. It spends what 06.4 deliberately left unconsumed: ground, groundDeep, and panelGround are defined and tested but nothing renders them — they exist for this ho.

    Chrome only. No new vault behavior. Every verb the panel hosts already exists and keeps its exact intent, wiring, confirmation dialogs, and Touch ID posture from 06.1/06.2.

    Out of scope:


    Phase 1 —

    Four decisions, ratified 2026-07-11. All four were framed in K4's 06.5 entry; two of them (idiom, grounds) were explicitly handed here by earlier hos.

    Decision 1 — Idiom: a custom collapsible right panel, not .inspector, not a fixed rail

    The panel is a -built trailing column beside the NavigationSplitView, filled with panelGround, holding the Workshop's actions as always-titled buttons in labeled groups, with a toolbar toggle to collapse and restore it. The collapse state persists across relaunch (@AppStorage).

    Why not the alternatives:

    The toolbar empties to the panel toggle. Every action it carried — Add Scope, Add Secret, Materialize, Check Drift, Materialize All Stale, Sync, Rescan, and the three the overflow buried (Add Shared Secret, Preview .env, Jump to Directory) — moves into the panel. Nothing is reachable only through a nested menu. Disabled logic travels with each verb unchanged (selectedScopeID, model.activity, the preview/jump disabled reasons).

    Decision 2 — Appearance control lives at the panel's base; Settings keeps the durable copy

    A quiet System/Light/Dark control sits at the bottom of the panel, reading and writing the same @AppStorage(AppAppearance.storageKey) the Settings scene uses — one stored value, two surfaces, no divergence possible. Settings (⌘,) stays as-is; the panel makes the control reachable without knowing it exists. This resolves the 06.2 's reconsideration ("a panel changes the calculus") in the panel's favor; the floated top-bar toggle is declined — it would re-add chrome to the toolbar this ho empties.

    Decision 3 — Flat pālana grounds across the whole window

    The holistic call 06.4 deferred here, made: the translucent system materials (.bar, .quaternary) are replaced by flat token fills across the window. This is the notebook-over-Mac move — the window becomes warm paper the way pālana's own surfaces are, and Sharibako and pālana read as siblings rather than a native-vibrant app wearing pālana's accent.

    The mapping:

    Fallback, named now: the sidebar's native translucency (desktop showing through) is the most Mac-native thing this decision flattens. If the flat sidebar reads wrong at the visual gate, the fallback is flat-except-sidebar — everything else stays on tokens. That is a gate call, not a reopening.

    Decision 4 — Destructive-verb rust folds in

    Delete/remove affordances get Color.drift per pālana, closing the gap 06.4 flagged (its migration left destructive affordances neutral). Small, and the work already touches these views. The system's role: .destructive red (the drift-overwrite and all-stale confirmation buttons, any delete controls) is brought onto the rust voice so success/alarm hues stay pālana's throughout.

    Discovery (deferred to execution)


    Phase 2 — Execute

    Branch panel-chrome off main. No agent tasks — the work is one bounded surface (chrome + grounds across a handful of view files) with no natural seams; splitting it would force coordination where none is needed. This document frames the session directly.

    The work, in order:

    1. Sources/Sharibako/Views/ActionPanel.swift — the panel view: grouped, always-titled action buttons; collapse handled by the parent; appearance control at the base. Any branching logic (which verbs are disabled and why) stays in WorkshopModel's tested surface — the view stays declarative.
    2. WorkshopWindow.swift — embed the panel trailing the NavigationSplitView; strip the toolbar to the panel toggle; migrate the status surface to groundDeep.
    3. Grounds migration — replace .bar/.quaternary sites across ScopeSidebar, SecretList, SecretDetail, the Add sheets, and Settings with the token fills per Decision 3.
    4. Rust wiring — the destructive-affordance census, then Color.drift on each (Decision 4).
    5. ci.yml — new View file(s) join the named-EXCLUDED regex with justification comments, the established convention.

    Testing and iteration approach

    Per change, the rhythm: swift package clean && swift test directly (never clean→build→test — the SwiftPM incremental-link bug after SharibakoCore changes) → swift build -Xswiftc -warnings-as-errorsswift-format lint --strict --recursive Sources Testsswiftlint lint --strict → coverage ≥90%. Logic that branches (panel-verb enablement, if any of it moves) lives tested in WorkshopModel; declarative View bodies are CI-excluded by name with justification. Tests never touch live user state — injected home / roots / temp vaults only.

    Done means

    Verification and the gate

    1. The rhythm above, green, on the panel-chrome branch.

    2. Signed-install gate — the committed Xcode project is the only real build path for the Workshop (the 06.4 lesson: not swift run, not scripts/install.sh):

      xcodebuild -project xcode/Sharibako.xcodeproj -scheme Sharibako \
        -configuration Release -derivedDataPath .build/xcode build
      

      Replace /Applications/Sharibako.app with the product and launch from /Applications explicitly (Spotlight resurfaces stale DerivedData builds). Against the real vault and Keychain:

      • Every verb fires from the panel: Materialize, Check Drift (one Touch ID), Materialize All Stale, Sync, Rescan, the three Adds, Preview .env, Jump to Directory.
      • Collapse the panel, quit, relaunch — still collapsed; restore it — the full set is back, nothing buried.
      • Flip appearance from the panel base; confirm Settings agrees; quit and relaunch — the override holds.
      • Drift loop unregressed: hand-edit an owned line, Check Drift, see per-key drift, reconcile, watch it clear.
      • The visual light/dark gate is the operator's eyeball on this build — flat grounds in both appearances, panel legibility, rust on destructive verbs, calm overall. Not called passed until Andrew confirms on the themed build. The sidebar fallback (Decision 3) is decided here if needed.

    Phase 3 — Reflect

    Recorded during the gate (2026-07-11) — scope deletion does not exist

    The operator asked "how do I delete a scope?" and the answer is: nowhere. No GUI affordance, no CLI verb, and — the real finding — no SharibakoCore operation. The says deletion is "always an explicit user action against the Vault Core," but the Vault Core verb was never in ho-01's nine operations. The only path today is hand-deleting the scope directory inside the vault and committing. Owed: a delete-scope ho across all three surfaces (Core verb + CLI verb + GUI affordance with confirmation) — new vault behavior, outside this chrome-only ho, flagged for the K4 overview pass. That ho is also destructive-rust's first real in-window consumer.

    Recorded during the gate — dialogs take no tint; rust cannot reach them

    Decision 4's dialog wiring failed empirically, twice. With role: .destructive plus a rust .tint, the system paints its destructive red label over the rust fill ("icky red"). With the role dropped, the tint is ignored outright and the button renders system-blue — confirmation dialogs render out of the view hierarchy and inherit no tint at all, not even the moss accent. Resolution: dialogs stay fully system-rendered (role: .destructive, no tint) and speak the system's alarm voice; pālana rust applies to in-window destructive affordances only — of which none exist yet. The first real consumer is the owed delete-scope ho.

    Recorded during the gate — Edit Notes now authenticates on demand

    The editor opened blank over an undecrypted note (silently clearing it on save) and, after the first fix, prefilled only when already revealed. The operator's call: editing a note should ask for authentication. Edit Notes now routes through the same synchronous reveal intent when the payload isn't decrypted — Touch ID prompts, the editor opens prefilled; on auth denial the editor does not open and the status surface announces the error.

    Filled at close (2026-07-11, after the signed-install gate)

    The flat-grounds bet held in full. Both appearances passed the operator's eyeball on the signed /Applications build; the sidebar fallback never fired — the flattened sidebar reads fine without its translucency. The window sits on palana paper and the operator's summary was "everything works."

    The panel earns its width. Every verb fired from the panel at the gate; nothing is buried, the emptied toolbar reads calm, collapse persisted across relaunch, and the panel-base appearance control stayed in agreement with Settings. The drift loop (hand-edit → Check Drift → per-key drift → reconcile → clear) ran unregressed.

    Decision review. Decisions 1–3 (custom panel, panel-base appearance, flat grounds) held as ratified. Decision 4 half-failed: the destructive-verb census found no in-window destructive affordances anywhere — rust's intended consumers don't exist yet — and the only destructive controls (the two confirmation-dialog buttons) proved untintable, twice (the two gate sections above). Dialogs stay system-rendered; the operator accepted this without enthusiasm ("not thrilled, but OK") — if it keeps rankling, the escape hatch is a custom in-window confirmation surface, noted and not scheduled. Rust remains defined and waiting for the delete-scope ho.

    What the tests didn't catch — view-layer, by (the gate's job): the dialog tint behavior (dialogs render out of hierarchy; no unit test sees that), the notes editor opening blank over an undecrypted note, and the two rounds of dialog-color tuning. One behavior change landed from a gate question: Edit Notes now authenticates on demand through the synchronous reveal intent (the section above).

    Answered at the gate: ScopeType (Project — dev, Service, …) is confirmed tag-only — it drives sidebar sectioning and the ingest default suggestion; no behavior keys off it.

    Followups (for the K4 overview pass):

    Closing this ho

    Closing = fill this Reflect + flip status: complete + write the state-summary block to the project's K6 (/kamae-6-sharibako-state-memory.md, refreshing the block at the top, verbatim labels and order) + append a build-record entry to K4 (ho-process/kamae-4-sharibako-ho-overview.md, , append-only). The block:

    STATE-SUMMARY


    Authored 2026-07-11 (Think ratified same day, four decisions; the forward-only response to ho-06.2's gate finding). Executed and closed 2026-07-11: panel + flat grounds + two gate-fix rounds (dialog rendering, notes auth-on-demand), signed-install gate passed; the missing delete-scope verb recorded as the gate's owed ho.

    Rendered from the corpus, verbatim · source on GitHub →

    ingested: sharibako @ 75a79d08a2b3 · ho-system @ 0f93b7fa32f7 · the glossary · the colophon