toga-ai 1.0.704 → 1.0.706
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.
- package/knowledge/clients/compass-canada/profile.md +10 -1
- package/knowledge/clients/compass-usa/INDEX.md +1 -1
- package/knowledge/clients/compass-usa/features/mits-sales-order-transmission-alerting.md +89 -28
- package/knowledge/standalone/standards/communication-clarity.md +7 -0
- package/package.json +1 -1
- package/rules/common/communication.md +34 -0
|
@@ -16,7 +16,7 @@ project: _Underscore
|
|
|
16
16
|
client: compass-canada
|
|
17
17
|
type: profile
|
|
18
18
|
status: active
|
|
19
|
-
updated: 2026-08-
|
|
19
|
+
updated: 2026-08-31
|
|
20
20
|
owners: [jcardinal, bala, tcox, apeterson]
|
|
21
21
|
files: []
|
|
22
22
|
related:
|
|
@@ -28,6 +28,7 @@ related:
|
|
|
28
28
|
- ../compass-usa/features/stranded-approval-reassignment.md
|
|
29
29
|
- ../compass-usa/features/people-file-user-lifecycle.md
|
|
30
30
|
- ../compass-usa/features/isfulfillable-data-quality-and-type-rule.md
|
|
31
|
+
- ../compass-usa/features/mits-sales-order-transmission-alerting.md
|
|
31
32
|
- features/french-order-email-localization.md
|
|
32
33
|
- features/order-fulfillment-status-per-line.md
|
|
33
34
|
- features/item-fulfillment-tableviews.md
|
|
@@ -72,6 +73,14 @@ to but distinct from Compass USA. Like Compass USA it spans the **2.0** commerce
|
|
|
72
73
|
- Worker crons for the G&T flow live under `worker/crons/toga2/compasscanada/workflow/`
|
|
73
74
|
(`1_…` transmit SOs to MITS, `2_…` transmit POs to vendors, `3_…` status from G&T cXML,
|
|
74
75
|
`4_…` import G&T ASNs).
|
|
76
|
+
- **⚠ MITS transmit alerting has diverged from Compass USA.** Canada's `1_…transmit…to_mits`
|
|
77
|
+
cron still raises all **three** of its failure alerts as in-cron `App_Email_Agilant` emails
|
|
78
|
+
(No Items Found / more than 15 items / Invalid response from MITS API), so changing who is
|
|
79
|
+
notified here **is** a code edit — whereas USA's rejection path now routes through the Logs
|
|
80
|
+
Issue/Event pipeline and is configured against the issue instead. Canada's "Invalid response"
|
|
81
|
+
email also `print_r`s the full payload (ship-to PII) into the body and has no dedupe. Recipients
|
|
82
|
+
are currently `devteam@togatech.com` + `vburks@togatech.com`. See
|
|
83
|
+
[MITS Sales-Order Transmit Alerting](../compass-usa/features/mits-sales-order-transmission-alerting.md).
|
|
75
84
|
|
|
76
85
|
## Storefront notes (toga2-commerce)
|
|
77
86
|
- Runs the same `toga2-commerce` storefront (2.0, consumes api2), with English + French cart
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
| [Compass MITS PO → SO Item Linking](features/mits-po-to-so-item-linking.md) | 2.0 | MITS sends Compass inbound Purchase Orders (`POST /v2/purchase-orders`) against a Sales Order (`mitsSalesOrder`). | _underscore/Model/Compass/PurchaseOrder.php, worker/crons/toga2/compass/workflow/3a_import_office_depot_purchase_orders.php |
|
|
11
11
|
| [Compass MITS PO Transmission to Vendors](features/mits-po-transmission-to-vendors.md) | 2.0 | The 1.0 worker cron `2_transmit_mits_purchase_orders_to_vendors.php` transmits Compass PurchaseOrders to their vendors (Office Depot, Strategic Systems, Compass | worker/crons/toga2/compass/workflow/2_transmit_mits_purchase_orders_to_vendors.php, worker/crons/toga2/compasscanada/workflow/2_transmit_mits_purchase_orders_to_vendors.php, library/app/client/compass.php |
|
|
12
12
|
| [Compass MITS PO rejection — zero line items (400 + Issue + PM alert email)](features/mits-po-zero-line-item-rejection.md) | 2.0 | MITS transmits Compass purchase orders that carry **`"purchaseOrderItems": []`** (real example: PO `50309196-1`, `mitsSalesOrder` `MR244630`). | _underscore/Model/Compass/PurchaseOrder.php, _underscore/Model/Compass/Usa/PurchaseOrder.php, _underscore/Model/Compass/Canada/PurchaseOrder.php, worker2/Worker/Client/Compass/reports/PurchaseOrderRejectionEmail.php |
|
|
13
|
-
| [Compass MITS Sales-Order
|
|
13
|
+
| [Compass MITS Sales-Order Transmit Alerting (US Issue/Event vs Canada in-cron email)](features/mits-sales-order-transmission-alerting.md) | 2.0 | How a failure in the `1_transmit_..._sales_orders_to_mits.php` cron reaches a human — for **both** Compass tenants, because **they no longer work the same way** | worker/crons/toga2/compass/workflow/1_transmit_compass_sales_orders_to_mits.php, worker/crons/toga2/compasscanada/workflow/1_transmit_compassCanada_sales_orders_to_mits.php, worker2/Worker/Infrastructure/Errors.php, tools/mvc/errors/post.php, _underscore/Model/Core/Logs/Issue.php, _underscore/Model/Core/Logs/IssueEmailAddress.php, dbchanges2/Logs/2026-08-04a - MITS rejection business recipients.sql |
|
|
14
14
|
| [Compass MR/MA Order Auto-Approval & Status Gate](features/mr-ma-order-approval-and-status.md) | 2.0 | Compass **MR** and **MA** sales orders are system-generated from the MITS / Office Depot EDI pipeline (they do not originate as user-entered SA orders) and must | _underscore/Model/Compass/SalesOrder.php, _underscore/Model/Compass/PurchaseOrder.php, worker/crons/toga2/compass/workflow/3a_import_office_depot_purchase_orders.php |
|
|
15
15
|
| [Compass ODP EDI 850 Line-Item Resolution (VA part number to IN SKU fallback)](features/odp-edi-850-item-resolution.md) | 1.0 | How each **PO1 line** on an inbound Office Depot (ODP) **EDI 850** is resolved to a real `Client_Compass` catalog item before cron `3a_import_office_depot_purch | worker/crons/toga2/compass/workflow/3a_import_office_depot_purchase_orders.php, library/app/Edi.php |
|
|
16
16
|
| [Compass Office Depot EDI 855 Acknowledgement + Over-Quantity PO Guard](features/odp-edi-855-acknowledgement-and-overquantity-guard.md) | 1.0 | How Compass acknowledges Office Depot (ODP) inbound **EDI 850** purchase orders with an **X12 855**, and the **over-quantity guard** that rejects a duplicate PO | worker/crons/toga2/compass/workflow/3a_import_office_depot_purchase_orders.php, worker/crons/toga2/compass/workflow/4_transmit_office_depot_po_acknowledgements.php, library/app/edi.php |
|
|
@@ -1,59 +1,99 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: Compass MITS Sales-Order
|
|
2
|
+
title: Compass MITS Sales-Order Transmit Alerting (US Issue/Event vs Canada in-cron email)
|
|
3
3
|
framework: "2.0"
|
|
4
4
|
project: _Underscore
|
|
5
5
|
client: compass-usa
|
|
6
6
|
type: client-feature
|
|
7
7
|
status: active
|
|
8
|
-
updated: 2026-08-
|
|
9
|
-
owners: ["dfranks"]
|
|
8
|
+
updated: 2026-08-31
|
|
9
|
+
owners: ["dfranks", "bala"]
|
|
10
10
|
files:
|
|
11
11
|
- worker/crons/toga2/compass/workflow/1_transmit_compass_sales_orders_to_mits.php
|
|
12
|
+
- worker/crons/toga2/compasscanada/workflow/1_transmit_compassCanada_sales_orders_to_mits.php
|
|
12
13
|
- worker2/Worker/Infrastructure/Errors.php
|
|
14
|
+
- tools/mvc/errors/post.php
|
|
13
15
|
- _underscore/Model/Core/Logs/Issue.php
|
|
14
16
|
- _underscore/Model/Core/Logs/IssueEmailAddress.php
|
|
15
17
|
- dbchanges2/Logs/2026-08-04a - MITS rejection business recipients.sql
|
|
16
18
|
related:
|
|
17
19
|
- mits-po-transmission-to-vendors.md
|
|
20
|
+
- ../../compass-canada/profile.md
|
|
18
21
|
- ../../../2.0/apps/worker2/features/error-escalation-cron.md
|
|
19
22
|
- ../../../2.0/apps/_underscore/features/error-reporting-issue-event.md
|
|
20
23
|
- ../../../1.0/apps/library/features/error-capture-1-0.md
|
|
24
|
+
- ../../../1.0/apps/tools/features/errors-curation-console.md
|
|
21
25
|
---
|
|
22
26
|
|
|
23
27
|
## Summary
|
|
24
28
|
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
How a failure in the `1_transmit_..._sales_orders_to_mits.php` cron reaches a human — for
|
|
30
|
+
**both** Compass tenants, because **they no longer work the same way**.
|
|
31
|
+
|
|
32
|
+
When MITS **rejects** a Compass **USA** sales order, the alert is not an email built inside the
|
|
27
33
|
cron. It is a **business exception** raised into the shared Logs Issue/Event pipeline, and its
|
|
28
|
-
recipients are **rows in `Logs.IssueEmailAddress`**.
|
|
34
|
+
recipients are **rows in `Logs.IssueEmailAddress`**. The Compass **Canada** cron still sends a
|
|
35
|
+
direct `App_Email_Agilant` for the same rejection.
|
|
36
|
+
|
|
37
|
+
**Consequence for anyone handed a ticket like "add <person> to the MITS error emails": the
|
|
38
|
+
answer depends on the tenant and on which failure.** Check the table below before opening
|
|
39
|
+
either file — half of these alerts have no PHP to change, and the other half have no
|
|
40
|
+
configuration surface at all.
|
|
41
|
+
|
|
42
|
+
## Which alert goes where (check this first)
|
|
43
|
+
|
|
44
|
+
| Tenant / failure | Mechanism | To add a recipient |
|
|
45
|
+
|---|---|---|
|
|
46
|
+
| **USA** — MITS rejects the order (`responseCode != 200`) | `App_Exception_Business` → Logs Issue/Event | **Data/UI change.** Add a row to `Logs.IssueEmailAddress` against the issue — no code edit |
|
|
47
|
+
| **USA** — "MITS API Script Error: No Items Found" | in-cron `App_Email_Agilant` | edit `addTo()` in the cron |
|
|
48
|
+
| **Canada** — "No Items Found" | in-cron `App_Email_Agilant` | edit `addTo()` in the cron |
|
|
49
|
+
| **Canada** — "Sales Order Items are more than 15" | in-cron `App_Email_Agilant` | edit `addTo()` in the cron |
|
|
50
|
+
| **Canada** — "Invalid response from MITS API" (the rejection path) | in-cron `App_Email_Agilant` | edit `addTo()` in the cron |
|
|
29
51
|
|
|
30
|
-
|
|
31
|
-
|
|
52
|
+
So the USA cron is a **hybrid**: its rejection path is issue-routed, but it still holds one
|
|
53
|
+
hardcoded email for the no-items case. Only the rejection branch was migrated.
|
|
32
54
|
|
|
33
|
-
|
|
55
|
+
Both crons are live — `worker/schedules/cron.worker.sync.json` schedules
|
|
56
|
+
`toga2/compass/workflow/1_...` and `toga2/compasscanada/workflow/1_...`. (Per the
|
|
57
|
+
[ODP pipeline doc's](../workflows/odp-order-pipeline-to-netsuite.md) rule, a grep hit under
|
|
58
|
+
`crons/toga2/**` is not proof a script runs — these two were verified against the schedule.)
|
|
59
|
+
|
|
60
|
+
**Current recipients on every in-cron email above:** `devteam@togatech.com` +
|
|
61
|
+
`vburks@togatech.com` (business stakeholder, added 2026-08-31).
|
|
62
|
+
|
|
63
|
+
## How the USA rejection path works
|
|
34
64
|
|
|
35
65
|
- The cron raises
|
|
36
66
|
`throw new App_Exception_Business('COMPASS_SALES_ORDER_MITS_TRANSMIT_REJECTED', …, URGENCY_HIGH)`
|
|
37
67
|
on a MITS rejection. (Before 2026-08-03 this block was a hardcoded `new App_Email_Agilant()`
|
|
38
|
-
with `addTo('devteam@togatech.com')
|
|
39
|
-
- Capture creates/dedupes a `Logs.Issue` keyed on the `issueKey`,
|
|
40
|
-
|
|
41
|
-
|
|
68
|
+
with `addTo('devteam@togatech.com')` — i.e. exactly what Canada still does.)
|
|
69
|
+
- Capture creates/dedupes a `Logs.Issue` keyed on the `issueKey`, so repeated rejections are
|
|
70
|
+
**one issue with an occurrence count**, not one email per failure. It is visible to internal
|
|
71
|
+
staff in the Tools `/errors` console.
|
|
72
|
+
- The worker2 `Infrastructure/Errors/Escalate` cron does all outbound notification — business
|
|
73
|
+
email to the configured recipients **and**, independently, the dev-team ClickUp task. See
|
|
42
74
|
[error-escalation-cron](../../../2.0/apps/worker2/features/error-escalation-cron.md).
|
|
43
75
|
- Recipients live in `Logs.IssueEmailAddress` (FK `issueId` → `Logs.Issue`), scoped by
|
|
44
76
|
`clientId` (`0` = all clients).
|
|
45
77
|
|
|
46
|
-
### Adding a recipient
|
|
78
|
+
### Adding a recipient — two routes
|
|
79
|
+
|
|
80
|
+
**Route 1 (preferred): the Tools `/errors` console.** `tools/mvc/errors/post.php` exposes
|
|
81
|
+
`add-recipient` / `delete-recipient`, which write `IssueEmailAddress`
|
|
82
|
+
(`uuid, issueId, clientId, emailAddress, toCcBcc`) and set `Issue.isManaged = 1`. `clientId = 0`
|
|
83
|
+
requires an explicit second confirmation checkbox, because one mistyped `0` silently sends one
|
|
84
|
+
client's business users every other client's error content. See
|
|
85
|
+
[errors-curation-console](../../../1.0/apps/tools/features/errors-curation-console.md).
|
|
47
86
|
|
|
48
|
-
|
|
87
|
+
**Route 2: a `dbchanges2/Logs/YYYY-MM-DD<letter>` migration** — use this when the change must
|
|
88
|
+
ride a deploy across environments. It must:
|
|
49
89
|
|
|
50
|
-
1. **
|
|
90
|
+
1. **Look the issue up by `issueKey`**, never by its `id`. The id is assigned on the issue's
|
|
51
91
|
**first occurrence** and is therefore not stable across environments.
|
|
52
|
-
2.
|
|
92
|
+
2. Use **`clientId = 0`**. This `issueKey` is raised from a Compass-only code path, and an
|
|
53
93
|
occurrence recorded without client attribution resolves against scope `0` only — a row scoped
|
|
54
94
|
to the Compass `clientId` can deliver nothing. (Never use `0` for an `issueKey` raised from
|
|
55
95
|
shared code — that is a cross-tenant leak.)
|
|
56
|
-
3.
|
|
96
|
+
3. Be **idempotent** via `INSERT … WHERE NOT EXISTS`, mirroring the unique key
|
|
57
97
|
`uq_issue_client_address_type`.
|
|
58
98
|
|
|
59
99
|
Configuration is **never retroactive**: `shouldNotify()` fires on the first occurrence, on
|
|
@@ -62,28 +102,49 @@ zero events. The first email lands on the **next live rejection**, not on existi
|
|
|
62
102
|
|
|
63
103
|
## Gotchas / known issues
|
|
64
104
|
|
|
65
|
-
- **
|
|
105
|
+
- **Canada is the pre-2026-08-03 design, and it still carries the two problems that migration
|
|
106
|
+
fixed.** Its "Invalid response from MITS API" email `print_r`s the **whole transmission
|
|
107
|
+
payload** into the body — which includes ship-to addressee, attention line, street address and
|
|
108
|
+
phone number — and there is no issue dedupe, so a bad run emails once per order. Treat
|
|
109
|
+
bringing Canada onto `App_Exception_Business` as known outstanding work, not a new idea; the
|
|
110
|
+
USA block is the reference implementation.
|
|
111
|
+
- **Canada's alerts do not send where outbound email is disabled.** The USA no-items email sets
|
|
112
|
+
`sendEmailEvenIfOutboundEmailIsDisabled = true`; none of Canada's three do. On any environment
|
|
113
|
+
with outbound email off, Canada fails **silently**.
|
|
114
|
+
- **Do not "modernize" the USA rejection alert back into the cron.** Migrating it to
|
|
66
115
|
`_Model_Client_EmailTemplate::send` (or any in-cron email) reverts the move to the Issue/Event
|
|
67
116
|
pipeline and removes the recipient configuration surface entirely.
|
|
68
|
-
- **Never re-introduce the payload dump into the alert.** The
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
- **The MITS cron holds its API credentials inline in the file.** Treat that file as
|
|
117
|
+
- **Never re-introduce the payload dump into the USA alert.** The Issue message is stored in a
|
|
118
|
+
table **shared across every client**, displayed to internal staff in the Tools `/errors`
|
|
119
|
+
console, pushed to ClickUp, and emailed — so the payload was deliberately removed. Alerts here
|
|
120
|
+
name the order, not the person. (This is precisely what Canada still does wrong.)
|
|
121
|
+
- **The MITS crons hold their API credentials inline in the file.** Treat both files as
|
|
74
122
|
secret-bearing when copying snippets anywhere (tickets, PR bodies, knowledge docs).
|
|
75
123
|
- **Adding a recipient does not turn ClickUp ticketing off.** Routing is both-and, not
|
|
76
|
-
either-or
|
|
124
|
+
either-or: `_Worker_Infrastructure_Errors` runs `if ($recipients !== null)` and
|
|
125
|
+
`if ((bool) $issue->createsClickupTask)` as **two independent** branches.
|
|
126
|
+
**⚠ The comment above the insert in `tools/mvc/errors/post.php` still claims the opposite**
|
|
127
|
+
("it stops creating ClickUp tasks for the dev team and starts emailing these people
|
|
128
|
+
instead") — that describes the old `elseif` form and is **stale**. Trust `Errors.php`.
|
|
77
129
|
- As of 2026-08-04 prod `Logs.IssueEmailAddress` is empty, so this is the **first business-routed
|
|
78
130
|
issue on the platform**: `processBusinessIssue()` will execute in production for the first time
|
|
79
131
|
when this issue next fires. Watch that run rather than assuming it works.
|
|
80
132
|
|
|
81
133
|
## Change history
|
|
134
|
+
- 2026-08-31 — Added `vburks@togatech.com` alongside `devteam@togatech.com` on **every** in-cron
|
|
135
|
+
`App_Email_Agilant` alert in both MITS transmit crons (USA has one, Canada has three), so the
|
|
136
|
+
business stakeholder is alerted on transmission failures. Broadened this doc to cover **both**
|
|
137
|
+
tenants after finding they had diverged: the USA rejection path is Issue/Event-routed
|
|
138
|
+
(recipients configured against the issue, no `addTo()` to edit) while **Canada still uses the
|
|
139
|
+
old direct email** for the same branch — including the PII-bearing payload dump and with no
|
|
140
|
+
dedupe. Also recorded that the USA cron is a hybrid (its no-items alert is still an in-cron
|
|
141
|
+
email), that recipients can be managed from the Tools `/errors` console as well as a
|
|
142
|
+
`dbchanges2/Logs` migration, that Canada's alerts are suppressed wherever outbound email is
|
|
143
|
+
disabled, and that the stale `tools/mvc/errors/post.php` comment misstates ClickUp-vs-email
|
|
144
|
+
routing. (bala)
|
|
82
145
|
- 2026-08-04 — Documented that MITS rejection alerting moved (worker `5521854b`, 2026-08-03) from a
|
|
83
146
|
hardcoded in-cron `App_Email_Agilant` to `App_Exception_Business` +
|
|
84
147
|
`Logs.IssueEmailAddress` recipients, so adding an alert recipient is a data change, not a code
|
|
85
148
|
change. Recorded the deliberate removal of the PII-bearing payload dump from the alert, the
|
|
86
149
|
look-up-by-`issueKey` / `clientId = 0` / `NOT EXISTS` migration pattern, and that recipient
|
|
87
150
|
configuration only takes effect on the next live occurrence. (dfranks)
|
|
88
|
-
</content>
|
|
89
|
-
</invoke>
|
|
@@ -21,6 +21,10 @@ answers. This applies to **all** developers, **both** frameworks, and **every**
|
|
|
21
21
|
|
|
22
22
|
This is a team directive, not a style tip. Follow it by default.
|
|
23
23
|
|
|
24
|
+
> **Now enforced always-on.** The short, hard version lives in `rules/common/communication.md`,
|
|
25
|
+
> which loads in **every** session (not just kickoff). This doc is the fuller reference; the
|
|
26
|
+
> rule file is what binds. Keep the two in sync.
|
|
27
|
+
|
|
24
28
|
## The rules
|
|
25
29
|
|
|
26
30
|
1. **Be short.** Say the thing, then stop. Cut every sentence that does not help the reader
|
|
@@ -52,6 +56,9 @@ Long, wordy, jargon-heavy answers are hard and tiring to read, especially for no
|
|
|
52
56
|
English speakers. The team moves faster when Claude is brief and plain. Clear beats clever.
|
|
53
57
|
|
|
54
58
|
## Change history
|
|
59
|
+
- 2026-08-31 — Moved the hard, short version to always-on `rules/common/communication.md` so it
|
|
60
|
+
loads every session, not just some kickoffs. Team was still finding output too long and too
|
|
61
|
+
complex; the on-demand-only load was part of why. (jcardinal)
|
|
55
62
|
- 2026-08-05 — Standard recorded: keep all communication short, clear, and plain; avoid
|
|
56
63
|
obscure jargon (e.g. "sargability"); lead with the answer; stay technical but brief.
|
|
57
64
|
Team-wide, both frameworks. (jcardinal)
|
package/package.json
CHANGED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Communication Rules
|
|
2
|
+
|
|
3
|
+
You talk to the whole team. Many teammates read English as a second language, and long
|
|
4
|
+
answers tire them out or lose them. So keep every message short, plain, and clear — in your
|
|
5
|
+
thinking, your plans, and your final answers. This is a hard team rule, not a style tip.
|
|
6
|
+
|
|
7
|
+
**Clear with more words beats clever with fewer. But short and clear is the goal.**
|
|
8
|
+
|
|
9
|
+
## The rules
|
|
10
|
+
|
|
11
|
+
1. **Cut words.** Say the point, then stop. Delete any sentence that does not help the reader
|
|
12
|
+
do something or decide something. One line is better than three.
|
|
13
|
+
2. **Use common words.** Pick the everyday word over the fancy one. If a simpler word means
|
|
14
|
+
the same thing, use it.
|
|
15
|
+
3. **Drop the jargon.** Do not use rare technical words (like "idempotent", "cardinality",
|
|
16
|
+
"sargable", "orthogonal", "canonical"). Say what they mean in plain words instead.
|
|
17
|
+
- Bad: "make the query sargable"
|
|
18
|
+
- Good: "let the query use the index — don't wrap the indexed column in a function"
|
|
19
|
+
4. **Answer first.** Put the main point in the first line. Reasons come after, only if needed.
|
|
20
|
+
No long wind-up.
|
|
21
|
+
5. **Use lists.** More than two parts? Use a numbered or bulleted list, not a paragraph.
|
|
22
|
+
6. **Stay technical, stay exact.** Keep the real detail — file names, error text, exact steps.
|
|
23
|
+
Short does not mean vague. Be brief AND precise.
|
|
24
|
+
|
|
25
|
+
## Check before you send
|
|
26
|
+
|
|
27
|
+
- Can I cut half the words and keep the meaning? Cut them.
|
|
28
|
+
- Is there a rare word a non-native reader might miss? Swap it.
|
|
29
|
+
- Is my main point in the first line? If not, move it up.
|
|
30
|
+
|
|
31
|
+
## Why
|
|
32
|
+
|
|
33
|
+
Wordy, jargon-heavy output is hard and slow to read — worse for non-native English readers.
|
|
34
|
+
The team moves faster when you are brief and plain. Clear beats clever.
|