Skip to content

fix(service): carry the case SLA wall-clock unit in identifiers and one test, collapse the prose warnings to one - #1987

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-1974-case-sla-calendar-hours
Oct 2, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-1974-case-sla-calendar-hours

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #1974

The case SLA matrix is counted in calendar (wall-clock) hours. Until now the app said so in four dev-prose copies, and a test pinned two of them by regex. This PR says it once, carries the unit in names, pins it with a fixed clock, and tells the operator. It is the app half of objectstack-ai/objectstack#13801 (mechanism B). It makes no spec change and renames no published metadata key.

What changed

  • One dev-prose site. The src/service/objects/_case-sla.ts module header keeps the warning and now also names where the unit lives. Four copies are deleted:
    • the case.hook.ts module-header bullet;
    • the case.hook.ts comment above the matrix literal;
    • the case.object.ts comment above sla_due_date;
    • a fifth copy the card did not count: the celCaseSlaDue doc comment in src/service/data/service.seed.ts.
  • The unit rides in module-private names.
    • CASE_SLA_HOURS → CASE_SLA_CALENDAR_HOURS and caseSlaHours → caseSlaCalendarHours, both in _case-sla.ts.
    • The hook-body literal slaHours → slaCalendarHours.
    • The import sites follow: src/service/data/service.seed.ts, test/case-sla-matrix.test.ts and test/seed-consistency.test.ts.
  • The test pins the clock, not the prose. In test/case-sla-matrix.test.ts the two-file prose regex is gone. In its place:
    • A fixed-clock block. vi.setSystemTime sets the clock to Friday 2026-10-02 17:00Z. The hook runs through its shipped body: runHookBody executes the lowered body.source in QuickJS, which is where production computes the deadline. A Critical case (4 h) is due Friday 21:00. A Medium case (48 h, smb column) is due Sunday 17:00. A Low case (168 h) is due the next Friday at 17:00.
    • An identifier check. The lowered body declares const slaCalendarHours. The body comes from extractSandboxBody, which wraps the CLI's own extractHookBody.
    • The elapsed-ms magnitude assertion, kept unchanged.
  • Operator text. sla_due_date gets description: 'Set from the case priority and the account’s Customer Tier, in calendar hours: nights, weekends and holidays count.'. The same text is mirrored as help in the four locale packs.

Premises measured

The card's line numbers predate the src/PKG/ move, so each premise was re-measured on the tree.

  1. Prose sites.

    • On base cf422b83 the acceptance grep returned 7 lines in 3 files: _case-sla.ts 4/20/23, case.hook.ts 16/216/219 and case.object.ts 231.
    • Reading the files case-insensitively found one more copy, the seed's (service.seed.ts:50-52). It spells the unit CALENDAR hours, so the case-sensitive grep misses it.
    • Two hits stay: test/case-guest-branch-leftovers.test.ts:140 and test/seed-consistency.test.ts:468. Each is a one-line unit note on a test's own value, not a copy of the no-business-hours warning.
  2. Where the operator text lives. Measured offline in the installed @objectstack/console 17.6.0:

    • The object form renders a field's help from n.help||n.description (the plugin-form chunk).
    • The action-param dialog reads e.helpText??s.help??s.description.
    • Only the flow-screen form and the designer read inlineHelpText.
    • On the server, translateObject (@objectstack/spec/system) copies a pack's help onto the served field as help.

    So in each locale the operator sees the pack's help, with the inline description as the fallback. That is the repo's existing convention, and test/i18n-references.test.ts requires every inline description to have a help in all four packs.

  3. The handler clock. case_sla_defaults stamps new Date(Date.now() + hours * 3_600_000). The seed's celCaseSlaDue is a seed-time CEL expression (daysAgo(n) + duration('Nh')), not the runtime clock. The fixed-clock test therefore drives the hook's shipped body.

Acceptance

  • Prose grep. grep -rn "CALENDAR HOURS\|business-hours calendar" src/ returns 3 lines, all in the _case-sla.ts header: one site. The user-doc paragraph still exists at src/docs/crm_service.md:32-35. Its wording ("calendar hours, not business hours … no working-day calendar") does not match the grep.

  • Build output. A deep JSON diff of dist/objectstack.json, base cf422b83 against head, finds exactly 6 changed leaf paths:

    • objects[crm_case].fields.sla_due_date.description (new);
    • translations[0].{en,zh-CN,ja-JP,es-ES}.objects.crm_case.fields.sla_due_date.help (new, four paths);
    • hooks[case_sla_defaults].body.source.

    The body.source change is the identifier rename that work item 2 asks for. A probe replaced slaCalendarHours with slaHours in the head source and compared it with the base source: byte-identical (true). Comments never reach body.source.

Verification (HEAD 1e00b183)

  • pnpm verify under the shared lock: os-verify-lock: VERDICT command-exit 0.
    • validate: ✓ Validation passed
    • typecheck: clean
    • lint: 1 warning(s), 16 suggestion(s), none on crm_case
    • i18n gate: ✓ i18n lint gate: 0 i18n/missing-* issues
    • hygiene: ✓ source hygiene clean
    • token ratchet: ✓ source token ratchet clean
    • build: ✓ Build complete
    • test: Test Files 174 passed (174), Tests 3731 passed | 1 skipped (3732)
  • Token ratchet, before → after:
    • src/service business semantics: ~12,601 → ~12,646 (ceiling 14,000).
    • src/service authored total: ~20,691 → ~20,736 (ceiling 22,000).
    • src/service interaction layer: unchanged at ~5,784.
    • src/sales: unchanged at 54,323 / 28,003 / 97,805, because the packs are outside the ratchet.
    • src/revenue and src/marketing: untouched.
  • Ablations. Both are one-off runs on committed HEAD b85218e5 through ablation-replace.mjs. The anchor must hit, and the restore is proven by a blob hash equal to HEAD and an empty git diff HEAD.
    • A1: slaCalendarHours → slaHours in case.hook.ts (2 hits) gave Tests 1 failed | 34 passed (35). Only the identifier check went red.
    • A2: making the stamp drift by 1 ms gave Tests 3 failed | 32 passed (35). Only the three fixed-clock rows went red. The ±1 min matrix cells and the ±60 s elapsed-ms assertion stayed green, so the fixed-clock rows are the stricter check.
    • The green run also shows that the Date-only fake clock reaches inside QuickJS. The real clock at run time was 22:04Z, which could not produce a Friday 21:00Z deadline.

Acceptance notes (seen in passing, not fixed here)

  • Stale paths in comments. Pre-src/PKG/ paths remain in comments this PR does not otherwise rewrite:

    • _case-sla.ts:18 (src/views/account.view.ts) and :65 (src/data/service.seed.ts);
    • case.object.ts:203 and :397;
    • case.hook.ts:120;
    • test/seed-consistency.test.ts:471.

    The path in the case.object.ts comment above sla_due_date sits in lines this PR rewrites, and it now reads ./_case-sla.ts. This is comment drift only, and no one has taken it on.

  • Token ceiling. pnpm hygiene:tokens suggests re-anchoring the src/sales interaction-layer ceiling (headroom ~2,997). This PR does not touch that layer.


Generated by Claude Code

claude added 3 commits October 2, 2026 22:03
…ot four prose copies

The case SLA matrix is wall-clock (calendar) hours. Say it once, in the
_case-sla.ts header; carry the unit in CASE_SLA_CALENDAR_HOURS,
caseSlaCalendarHours and the hook-body slaCalendarHours literal; pin it with a
fixed Friday 17:00 clock run through the shipped body; and tell the operator in
the sla_due_date field description (and its four pack help strings).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ER8ntXZhYebyQ66aXWdjfT
@vercel

vercel Bot commented Oct 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
hotcrm Ignored Ignored Oct 2, 2026 10:11pm UTC

Request Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend Server-side behaviour — hooks, flows, actions ci/cd CI plumbing and the verification pipeline metadata Declarative metadata — schema, security posture, UI surfaces

Projects

None yet

2 participants