Nick's decision, 2026-08-20: 'email bodies provide links back to the system.
we can talk about customers we just cant exposed their confidential
documents.' The T7.6-era rule (no customer IP at all, so number + link only)
is refined: context IN, content OUT.
- wp_titled() and wp_where() compose 'number - title' and the CR-004
location (structured paths first, legacy free text second); the where-line
is dropped entirely when unset rather than mailing 'Where: '.
- assign, qa-ready, qa-reject and hold bodies gain title + location. The
scope summary the original CR asked for stays OUT - scope text is document
content; the link is its summary. Rejection comments stay on the package.
- hold_body gains the house footer it alone lacked.
- kitting and material-request bodies adopt wp_titled for the same identity
line (their delivery-location rule is unchanged).
- notify.py's docstring states the new rule where the transport documents it.
Pins flipped WITH the rule, reasons in code: qa_gate_check's location canary
is now asserted PRESENT in QA bodies; a new DESC_CANARY (document content) is
asserted absent from every message (40 -> 41 checks). The sink also gains a
decoded-body view: the em-dash switches smtplib to quoted-printable, whose
column-76 soft breaks made raw-payload substring pins pass or fail on luck of
line position - content pins now read the decoded body, header pins still
read the wire payload.
Battery: qa_gate_check 41/41, kitting_notify_check 17/17, mreq_check 19/19.
Items: CR-014 (rule per decisions-2026-08-20.md), CR-011 pins.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The OneNote comparison from the meeting was "word vomit"; the structure that
replaces it, built at the lightweight scope EXACTLY as approved Aug 14:
- Line items (qty, unit, description) added, edited, removed. Descriptions
offer the D6 project list through a datalist - which is also precisely what
keeps free text working when no list is loaded, the state every project is
in today. Picking a listed material fills its unit; nothing locks.
- Needed-by date, requestor (the signed-in account), delivery location (T8.4's
fields on this package, composed), and an explicit status set
(Requested / Filled / Declined). The request rides on the package record
(data.materialRequests) - server-persisted through the same upsert as
everything else, never localStorage.
- Submitting notifies the warehouse owner named on the package (CR-010) - the
routing that replaces the funnel through one person - through the T7.6 gate,
with the count, the needed-by, the delivery location and the deep link, in
the house convention. material_requested lands in the audit history.
- The dashboard grows a Material requests queue, filterable by status and by
delivery location.
- The block lives inside #material-card, so the CR-006 materials toggle
governs it with no special casing. The whole flow is driven at 390px -
requests originate in the field.
- NO parts catalog, no inventory count, no warehouse integration - the probe
greps the block for them.
One infrastructure bug fixed in passing detection (not silently): T8.5's
dashboard-panel insert matched the substring inside "async function
dashIssue", splitting the async keyword from its function - the creator
failed to parse and every boot died. Caught by the probe's first run;
anchored fixes now restore both halves.
Verification (each probe run alone): NEW tests/mreq_check.py 19/19 (request
end-to-end at 390px against the SMTP sink, dashboard filters, fences).
Regressions: frame_check 39/39, sections_check 95/95, kitting_check 26/26.
Items: CR-013, D6
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>