Part of #13801 — the reference-app half of the mechanism ruled on that card (comment: the in-seat ruling by the domain:spec seat, session session_01GDA48PuRFrHyRfdkBz8m21). Filed here with repo:hotcrm because objectstack-ai/hotcrm is not writable from this seat (REST 403); the measurement below was taken from a read-only clone at hotcrm a6be39a3.
Reader: the repo:hotcrm execution seat, at its next selection pass (plain pm:queue candidate for that seat; no domain:* — single-lane repo).
Ruling of record
Maintainer 2026-08-31 (director summon #7, decision batch #18, verbatim 「其他同意」): "this number is wall-clock hours" must be part of the declaration, not ambient prose — the A-half of #13655; ⛔ the business-hours capability stays frozen (the B-half). Mechanism B was ruled on #13801 after measurement: the four hotcrm sites are code (a hook-body literal objectstack build lowers to body.source, a module constant, two comments), unreachable by any spec schema, so the app carries the clock in its own identifiers and its own test.
Measured on hotcrm a6be39a3
- The SLA matrix is a plain TS object literal inside the Hook handler (
case.hook.ts:179-184), mirrored by a module constant (_case-sla.ts:89-95) imported only by seeds and tests; the field site is a comment on Field.datetime (case.object.ts:228-237); the hook module header repeats the warning. Four dev-prose warnings, plus one legitimate user-doc paragraph. test/case-sla-matrix.test.ts:271-288pins the prose in two of them by regex (CALENDAR HOURS and business-hours calendar in _case-sla.ts AND case.hook.ts) — i.e. the test currently enforces at least two prose copies, the opposite of the collapse-to-one acceptance. :263-269 asserts the elapsed-ms magnitude (168 h within ±60 s), not the clock over a weekend.
Work
- Collapse the four prose sites to one — the
_case-sla.ts module header — and delete the other three copies. - Carry the clock in identifiers, module-private, no published metadata renamed: e.g.
CASE_SLA_CALENDAR_HOURS (the constant), caseSlaCalendarHours / inline slaCalendarHours (the hook-body literal and its use); one seed import and one test import follow the rename. - Rewrite
test/case-sla-matrix.test.ts:262-288: replace the two-file prose regex with (a) a fixed-clock assertion (vi.setSystemTime on a Friday 17:00; the handler reads Date.now()) proving a 4 h deadline lands Friday 21:00 and a 168 h deadline spans the weekend — wall-clock, not business hours — and (b) the identifier check. - Put "calendar hours" into the user-visible
sla_due_date field description (the tooltip/help text on the Field.datetime), the one operator-facing surface.
Acceptance (executable)
grep -rn "CALENDAR HOURS\|business-hours calendar" src/ in hotcrm returns exactly one dev-prose site (the _case-sla.ts header) plus the user-doc paragraph.test/case-sla-matrix.test.ts passes with the fixed-clock Friday assertions and no prose regex; the elapsed-ms magnitude assertion is kept.- No published app metadata key renamed;
objectstack build output unchanged except the field description.
Out of scope
Refs: #13801 (ruling + phase-1 measurement, comment 5506949302) · #13655 (the decision record) · objectstack-ai/hotcrm#1184 (where the prose warnings live).
Generated by Claude Code
Part of #13801 — the reference-app half of the mechanism ruled on that card (comment: the in-seat ruling by the
domain:specseat, sessionsession_01GDA48PuRFrHyRfdkBz8m21). Filed here withrepo:hotcrmbecause objectstack-ai/hotcrm is not writable from this seat (REST 403); the measurement below was taken from a read-only clone at hotcrma6be39a3.Reader: the
repo:hotcrmexecution seat, at its next selection pass (plainpm:queuecandidate for that seat; nodomain:*— single-lane repo).Ruling of record
Maintainer 2026-08-31 (director summon #7, decision batch #18, verbatim 「其他同意」): "this number is wall-clock hours" must be part of the declaration, not ambient prose — the A-half of #13655; ⛔ the business-hours capability stays frozen (the B-half). Mechanism B was ruled on #13801 after measurement: the four hotcrm sites are code (a hook-body literal
objectstack buildlowers tobody.source, a module constant, two comments), unreachable by any spec schema, so the app carries the clock in its own identifiers and its own test.Measured on hotcrm
a6be39a3case.hook.ts:179-184), mirrored by a module constant (_case-sla.ts:89-95) imported only by seeds and tests; the field site is a comment onField.datetime(case.object.ts:228-237); the hook module header repeats the warning. Four dev-prose warnings, plus one legitimate user-doc paragraph.test/case-sla-matrix.test.ts:271-288pins the prose in two of them by regex (CALENDAR HOURSandbusiness-hours calendarin_case-sla.tsANDcase.hook.ts) — i.e. the test currently enforces at least two prose copies, the opposite of the collapse-to-one acceptance.:263-269asserts the elapsed-ms magnitude (168 h within ±60 s), not the clock over a weekend.Work
_case-sla.tsmodule header — and delete the other three copies.CASE_SLA_CALENDAR_HOURS(the constant),caseSlaCalendarHours/ inlineslaCalendarHours(the hook-body literal and its use); one seed import and one test import follow the rename.test/case-sla-matrix.test.ts:262-288: replace the two-file prose regex with (a) a fixed-clock assertion (vi.setSystemTimeon a Friday 17:00; the handler readsDate.now()) proving a 4 h deadline lands Friday 21:00 and a 168 h deadline spans the weekend — wall-clock, not business hours — and (b) the identifier check.sla_due_datefield description (the tooltip/help text on theField.datetime), the one operator-facing surface.Acceptance (executable)
grep -rn "CALENDAR HOURS\|business-hours calendar" src/in hotcrm returns exactly one dev-prose site (the_case-sla.tsheader) plus the user-doc paragraph.test/case-sla-matrix.test.tspasses with the fixed-clock Friday assertions and no prose regex; the elapsed-ms magnitude assertion is kept.objectstack buildoutput unchanged except the field description.Out of scope
Refs: #13801 (ruling + phase-1 measurement, comment 5506949302) · #13655 (the decision record) · objectstack-ai/hotcrm#1184 (where the prose warnings live).
Generated by Claude Code