toga-ai 1.0.388 → 1.0.389

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,70 @@
1
+ ---
2
+ type: session
3
+ slug: surface-approve-steptwo
4
+ title: Surface-drive the Approve step-two-assigned enable gate for Compass/Compass Canada
5
+ author: apeterson
6
+ repos: [toga25-supply, dbchanges2, _underscore, api2]
7
+ framework: "2.0"
8
+ client: shared
9
+ status: active
10
+ created: 2026-07-21
11
+ updated: 2026-07-21
12
+ ---
13
+
14
+ # Session: surface-approve-steptwo
15
+ **Date:** 2026-07-21
16
+ **Project/Repo:** toga25-supply + dbchanges2 (2.0)
17
+ **Task:** Move the Approve-button "step-two assigned" enable gate off the legacy per-client FE JSON and into the Surface layer (role-scoped SurfaceOverride ENABLED_RULE), for Compass/Compass Canada admins, on the record-actions bar (surface 8) and listing row-actions (surface 3).
18
+
19
+ ---
20
+
21
+ ## What WORKED
22
+ <!-- Include specific file paths and evidence -->
23
+ - **Record-actions (modal) data merge — DONE & verified.** In `toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/viewModel/useSalesOrderRecordModalLayoutModel.tsx`, merged `currentStage: approvalCurrentStage ?? null` and `stages: approvalStages ?? []` onto the returned `orderWithPo` object (lines ~148-149), and added `approvalCurrentStage, approvalStages` to the useMemo deps (line ~172). Purely additive — parallel to the existing `purchaseOrderDetails` merge. `approvalCurrentStage/approvalStages` were already fetched in that hook via `useFetchApprovalStages` (lines ~105-113). Verified present with grep post-edit.
24
+ - **DB — row-actions default-visibility correction (Core).** Created `dbchanges2/Core/2026-07-20e - Update - RestoreApproveDenyRowActions.sql` — narrows the earlier over-broad `2026-07-20d` hide: re-enables Approve (el 29) + Deny (el 30) `isVisible=1` on surface `sales-order-listing-row-actions` (id 3), leaving only View (el 5) and Approval Workflow (el 31) hidden by default. Scoped by surface slug + `e.id IN (29,30)`, idempotent.
25
+ - **DB — Approval Workflow row-item ADMIN opt-in (Compass + Compass Canada).** Created `dbchanges2/Client_Compass/2026-07-20e - RowActionsApprovalWorkflowAdminEnable.sql` and the mirrored `dbchanges2/Client_CompassCanada/2026-07-20e - RowActionsApprovalWorkflowAdminEnable.sql`. Each opts the `Admin` role (resolved id-agnostically by `Roles.name='Admin'`) into element 31 with two override rows — `IS_VISIBLE='1'` and `VISIBILITY_RULE` (`{"all":[{"field":"order._status","op":"in","value":["pendingApproval","pendingInitialApproval"]}]}`) — element resolved by surface slug + `Core.Actions.slug='salesOrder.approvalWorkflow'`. NOT EXISTS-guarded. Mirrors the 2026-07-17a `SalesOrderApprovalActionsOverride` precedent. NOTE: these are for the Approval WORKFLOW item's *visibility* (el 31), NOT the Approve-button ENABLED_RULE work (still TODO — see below).
26
+ - **DB — RUN ORDER updated.** `dbchanges2/Core/2026-07-17 - README - RUN ORDER.md` lists the three new `2026-07-20e` files.
27
+ - **Knowledge captured.** `/capture` updated 4 docs (surface-resolver, surface-meta-option, surface-frontend, surface-layer-schema) and pushed to `_main`.
28
+
29
+ ## What did NOT work — DO NOT RETRY THESE
30
+ <!-- Exact failure reasons — do not vague-ify -->
31
+ - **DO NOT "move `config.tier2` from Core into a SurfaceOverride" to control the disabled state.** `config.tier2 = "stepTwoAssigned"` on Core element 17 is a NON-FUNCTIONAL marker. Nothing reads it: the backend Tier-2 gate (`_underscore/Model/Core/Surface.php::resolveRecordState` → `_resolveTier2State`, ~line 280) dispatches by ACTION SLUG to a model method `resolveSurfaceActionState()` (const `TIER2_CAPABILITY_METHOD`), never by `config.tier2`; and the FE (`toga25-supply/src/surface/resolveElementState.ts`) never reads `config.tier2`. Moving/overriding it changes zero behavior.
32
+ - **DO NOT rely on the backend Tier-2 path to gate this today.** No model implements `resolveSurfaceActionState` (only `Surface.php` references it), and `stepTwoAssigned` does not exist anywhere in the backend. So `_resolveTier2State` always returns null; `meta.surface` carries only Tier-1 results.
33
+ - **DO NOT put `{"type":"stepTwoAssigned"}` into a rule and expect `evaluateSurfaceRule` to run it as-is.** `toga25-supply/src/surface/evaluateSurfaceRule.ts` has a DELIBERATELY FROZEN grammar (all/any/none + leaf field ops eq/ne/in/nin/gt/gte/lt/lte) and THROWS `"[surface] Unknown rule node"` on any `{type:...}` node. It needs named-check support added first (piece #3 below).
34
+ - **DO NOT bake the Approve rule into Core's element `enabledRule`.** Per developer decision, the rule lives ONLY in the per-client SurfaceOverride `c_longValue` column (attribute `ENABLED_RULE`, `value` NULL). Core stays client-neutral.
35
+ - **DO NOT edit an already-run migration file in place.** Developer instruction: create a NEW forward migration instead. (An in-place edit to `2026-07-20d` was made then reverted for this reason; the `2026-07-20e` Core file is the forward fix.)
36
+
37
+ ## Not tried yet (candidates for next session)
38
+ - **[Piece 2 — row-actions data merge]** Add a `useFetchApprovalStages(enabled ? uuid : null, userUuid, {})` call to `toga25-supply/src/pages/SalesOrders/hooks/useSalesOrderRowRecordState.ts` (gated on `enabled`, like the order fetch) and merge `currentStage`/`stages` into its `order` object (currently `{ order: {...cleanedOrder, purchaseOrderDetails} }`). This is the heaviest piece — adds a per-row approval-stages fetch when a dropdown opens.
39
+ - **[Piece 3 — evaluator]** Teach `toga25-supply/src/surface/evaluateSurfaceRule.ts` the `{"type":"stepTwoAssigned"}` named check, reusing the existing logic from `toga25-supply/src/pages/SalesOrders/helpers/evaluateEnableRule.ts` (`NAMED_RULES.stepTwoAssigned`). Surface record is shaped `{ order }`, so the surface predicate must read `order.currentStage` / `order.stages` (NOT top-level `ctx.currentStage` like the legacy engine). Add a code comment noting this intentionally deviates from the "frozen grammar / escalate to Tier-2" note.
40
+ - **[Piece 4 — DB ENABLED_RULE overrides]** Write per-client SurfaceOverride rows (attribute `ENABLED_RULE`, `value` NULL, rule JSON in `c_longValue`, scoped to `@adminRoleId` via `Roles.name='Admin'`) on the Approve element for surface 8 el 17 (`sales-order-record-actions`) AND surface 3 el 29 (`sales-order-listing-row-actions`), for Compass + Compass Canada. Rule = `{"any":[{"all":[{"field":"order._status","op":"in","value":["pendingInitialApproval"]},{"type":"stepTwoAssigned"}]},{"field":"order._status","op":"in","value":["pendingApproval"]}]}`. Works because `_castOverride` (Surface.php ~line 871) reads `value` then falls back to `c_longValue`. Resolve element id-agnostically by surface slug + `Core.Actions.slug='salesOrder.approve'`. NOT EXISTS-guard; add to RUN ORDER.
41
+ - **Verify keying caveat:** backend keys `meta.surface.state` by element UUID, but `resolveElementState` looks up `recordSurfaceState` by `element.action.key`. Confirm these line up (or Tier-2 state silently never matches). Not blocking the Tier-1 ENABLED_RULE plan, but relevant if backend Tier-2 is ever wired.
42
+
43
+ ## Current file state
44
+ | File | Status | Notes |
45
+ |------|--------|-------|
46
+ | toga25-supply/src/pages/SalesOrders/view/SalesOrderRecordModalLayout/viewModel/useSalesOrderRecordModalLayoutModel.tsx | Modified (DONE) | `currentStage`/`stages` merged onto `orderWithPo` + deps updated. Additive. |
47
+ | toga25-supply/src/pages/SalesOrders/hooks/useSalesOrderRowRecordState.ts | Unchanged (TODO piece 2) | Still fetches order + PO only; no approval-stages fetch/merge. |
48
+ | toga25-supply/src/surface/evaluateSurfaceRule.ts | Unchanged (TODO piece 3) | Frozen grammar; throws on `{type}`. Needs `stepTwoAssigned` named check. |
49
+ | dbchanges2/Core/2026-07-20e - Update - RestoreApproveDenyRowActions.sql | Created | Re-enables Approve(29)+Deny(30) on surface 3; narrows 2026-07-20d. |
50
+ | dbchanges2/Core/2026-07-20d - Update - HideSalesOrderRowActionsByDefault.sql | Unchanged (in-place edit reverted) | Original all-elements hide preserved. |
51
+ | dbchanges2/Client_Compass/2026-07-20e - RowActionsApprovalWorkflowAdminEnable.sql | Created | Admin opt-in for Approval Workflow item (el 31): IS_VISIBLE + VISIBILITY_RULE. NOT the Approve ENABLED_RULE. |
52
+ | dbchanges2/Client_CompassCanada/2026-07-20e - RowActionsApprovalWorkflowAdminEnable.sql | Created | Mirror of Compass. |
53
+ | dbchanges2/Core/2026-07-17 - README - RUN ORDER.md | Modified | Lists the three new 2026-07-20e files. |
54
+ | (TODO) dbchanges2 Client_Compass/Client_CompassCanada Approve ENABLED_RULE override files | Not created | Piece 4 — Approve el 17 + el 29 ENABLED_RULE in c_longValue. |
55
+
56
+ ## Decisions made
57
+ - **Approve step-two gate lives in the Surface layer, evaluated on the FE (Option B), not backend Tier-2 (Option C) and not legacy-only (Option A).** Rationale: the value changes live in-modal (user assigns a step-two approver right there), so instant FE evaluation beats a server snapshot that only refreshes on refetch; and the team is already creating separate Approve elements per surface. Rejected: A (legacy JSON only — can't reach the surface bar/row); C (backend `resolveSurfaceActionState` — snapshot-only, won't re-enable live after assignment).
58
+ - **The rule JSON goes in the SurfaceOverride `c_longValue` column, attribute `ENABLED_RULE`, `value` NULL — NOT in Core.** Rationale: keep Core client-neutral; client/role gating stays in overrides; `_castOverride` falls back to `c_longValue`. (Note: the earlier 2026-07-17a files put shorter rule JSON in `value`; this longer OR-rule uses `c_longValue` per developer instruction.)
59
+ - **Corrected Approve rule:** `(pendingInitialApproval AND stepTwoAssigned) OR (pendingApproval)` — only for the Approve button (not Deny / Approval Workflow).
60
+ - **Scope for now:** only `sales-order-record-actions` (surface 8, el 17) and `sales-order-listing-row-actions` (surface 3, el 29). The approval-workflow-modal Approve element does NOT exist as a surface yet — deferred.
61
+ - **Admin role resolved by `Roles.name='Admin'`** (id-agnostic; client role ids are not environment-stable), matching the 2026-07-17a precedent.
62
+
63
+ ## Blockers
64
+ - None hard. Piece 2 (row-actions) requires an extra per-row approval-stages fetch — a performance consideration (fires on dropdown open only), not a blocker. Piece 3 intentionally deviates from the frozen-grammar design intent of `evaluateSurfaceRule` — acceptable per the Option B decision but worth a comment.
65
+
66
+ ## Exact next step
67
+ > In `toga25-supply/src/surface/evaluateSurfaceRule.ts`, add support for a `{"type":"stepTwoAssigned"}` leaf node (a small named-predicate branch reusing the `stepTwoAssigned` logic from `src/pages/SalesOrders/helpers/evaluateEnableRule.ts`), reading `order.currentStage` / `order.stages` off the `{ order }`-shaped surface record. This is the smallest independent piece and unblocks testing the already-merged modal stage data (piece 1).
68
+
69
+ ---
70
+ _Saved by /session-save on 2026-07-21_
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toga-ai",
3
- "version": "1.0.388",
3
+ "version": "1.0.389",
4
4
  "description": "TOGA Technology Team Claude Knowledge System — shared AI coding harness with skills, knowledge base CLI, and project installer for Claude Code.",
5
5
  "keywords": [
6
6
  "claude",