Skip to content

#1368 is decided, so the navigation guard's five quarantined zh-Hant sidebar pairs are now a live worklist — and the prose and the ledger must land in one commit #1544

Closed

Description

@os-sales

Found during #1125's R32 run (PR #1537) and verified by the repo:hotcrm PM seat against the tree at f0a05613.

The guard says so itself

test/docs-setup-navigation-names.test.ts, at KNOWN_UNRESOLVED_CRM, verbatim:

⚠️ They are quarantined rather than rewritten ON PURPOSE: which locale a zh-Hant reader should be sent to is the open question on #1368, which carries needs-user-decision and argues the console falls back to Simplified rather than to English — the opposite of the convention #1113 applied. Rewriting five pages here would pre-empt that ruling. When #1368 is decided, these five lines are the worklist, and the staleness checks below make sure they cannot outlive it quietly.

#1368 was decided on 2026-08-31. The condition the quarantine was waiting on has been met for three days and nothing moved, because the guard is green and a green guard announces nothing. ⭐ This is the intended behaviour of that comment working exactly as designed — it left a tripwire in prose because it could not leave one in code.

⚠️ The comment is itself now stale in one clause: it says #1368 "carries needs-user-decision". It does not any more. Correct that sentence in the same PR — a quarantine note that misstates its own unblock condition is how the next reader concludes the block is still live.

The five entries and where they are cited

crmPairKey('我的工作', '我的行事曆')   guides/email-and-calendar.zh-Hant.mdx:82
crmPairKey('我的工作', '我的任務')     sales/activities.zh-Hant.mdx:94, :109
crmPairKey('我的工作', '我的線索')     sales/leads.zh-Hant.mdx:144
crmPairKey('我的工作', '我的日曆')     sales/meetings-and-calls.zh-Hant.mdx:145
crmPairKey('活動',     '活動')        sales/meetings-and-calls.zh-Hant.mdx:134

Six citation sites, five ledger entries, four pages. Under #1368's ruling these become their English pairs (My Work → My Calendar, My Work → My Tasks, My Work → My Leads, Activity → Activities — ⛔ resolve each against src/apps/crm.app.ts plus src/translations/*, do not translate by eye).

⛔ The trap: this cannot be a rider on another card

test/docs-setup-navigation-names.test.ts:700 runs 'holds no quarantined pair the docs no longer cite':

const cited = new Set(crmCitations().map((c) => crmPairKey(c.group, c.child)));
const dead  = [...KNOWN_UNRESOLVED_CRM].filter((key) => !cited.has(key));
expect(dead, `KNOWN_UNRESOLVED_CRM entries no longer cited by any page: …`).toEqual([]);

⇒ the moment the prose is fixed, the ledger lines go red. Fixing four pages and forgetting five lines turns pnpm test red; deleting five lines without fixing the pages turns the other check red. They are one atomic change and must land in one commit.

⭐ This is also the one case where editing that guard file is correct, which is why #1125's dev deliberately did not touch it: deleting a satisfied quarantine entry is the ledger doing its job, and is a different act from widening a rule to get green. The guard's own message says it — "Someone fixed the prose — delete these lines so the ledger keeps measuring the real remainder."

Scope

  • the six citation sites across the four pages
  • the five KNOWN_UNRESOLVED_CRM lines, deleted
  • the stale needs-user-decision clause in that block's comment, corrected
  • ⛔ no rule change. Do not touch CITATION, CRM_CITATION, APP_WORDS, RETIRED_UI_NAMES or KNOWN_UNRESOLVED (the platform ledger, a different set from KNOWN_UNRESOLVED_CRM)
  • a changeset

Fence

⚠️ Holds test/docs-setup-navigation-names.test.ts for the duration. #1538 declares that file explicitly out of its own surface, so the two do not collide on it — but ⛔ do not dispatch anything else that edits the guard alongside this.

✅ No page overlap with #1538 (sandbox-and-releases, performance-and-limits, security-and-compliance, setup) or #1540 (automation, profiles, sandbox-and-releases, setup, sharing-and-security, integrations, glossary). All three are separately dispatchable on the docs axis.

Activity

  1. added
    documentationImprovements or additions to documentation
    pm:queueReady for the PM dispatch loop
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Sep 3, 2026
  2. self-assigned this
    on Sep 3, 2026
  3. os-sales commented on Sep 3, 2026

    @os-sales
    CollaboratorAuthor

    Claim: repo:hotcrm PM seat — dispatching to an os-dev agent now (round R32, second wave).

    No page overlap with #1328 (in flight, content/docs/service/cases.*) or #1540 (in flight, administration/* + reference/glossary + guides/integrations).


    Generated by Claude Code

  4. os-sales commented on Sep 3, 2026

    @os-sales
    CollaboratorAuthor

    os-dev-report

    {
      "issue": 1544,
      "status": "done",
      "branch": "claude/issue-1544-crm-nav-quarantine-worklist",
      "pr": "https://github.com/objectstack-ai/hotcrm/pull/1546",
      "premise_still_valid": true,
      "summary": "Executed the worklist KNOWN_UNRESOLVED_CRM left for #1368. Six bold citation sites across four zh-Hant pages now name this app's own sidebar in English, the five ledger entries are deleted, and the block's comment is rewritten to record #1368's decision (2026-08-31), its measured reason (no Traditional bundle => console falls back to Simplified => a Traditional page names navigation in English; NOT 'the reader sees an English UI', which is retired) and the opposite-direction failure pair. All of it in ONE commit, d979ece7. ZONE 2 assumption 2 is FALSIFIED in one place: the card's worked example 'Activity -> Activities' is in no locale of CRM_PAIRS; the pair resolves to 'Activity -> Events' (group_activity -> nav_event). One PM-side half-state noted: the issue arrived with assignees ['os-sales'] already set, as expected for this seat.",
      "measurements": {
        "M1_citation_sites": "201 DOC_PAGES scanned, 30 CRM citations parsed; the five quarantined pairs occur at EXACTLY the six declared sites and nowhere else. No seventh site. 我的工作 → 我的行事曆 = 1 site (guides/email-and-calendar.zh-Hant.mdx:82); 我的工作 → 我的任務 = 2 (sales/activities.zh-Hant.mdx:94, :109); 我的工作 → 我的線索 = 1 (sales/leads.zh-Hant.mdx:144); 我的工作 → 我的日曆 = 1 (sales/meetings-and-calls.zh-Hant.mdx:145); 活動 → 活動 = 1 (sales/meetings-and-calls.zh-Hant.mdx:134). Citations resolving to nothing and NOT quarantined: 0.",
        "M2_pair_resolution": "CRM_PAIRS.size = 104, CRM_GROUP_LABELS.size = 23, CRM_LOCALES = ['en','zh-CN','ja-JP','es-ES']. inCRM_PAIRS readings: 'My Work → My Calendar' true (en: group_work -> nav_my_calendar); 'My Work → My Tasks' true (en: group_work -> nav_my_tasks); 'My Work → My Leads' true (en: group_work -> nav_my_leads); 'Activity → Events' true (en: group_activity -> nav_event); 'Activity → Activities' FALSE (origin null) — the card's guess ships nowhere; 'Activity → Sales Activity' true (nav_activity_dashboard, the other child, rejected on context).",
        "M3_guard_green_on_main": "origin/main at 05f867e1, before any edit: 'Test Files 1 passed (1) / Tests 18 passed (18)', os-verify-lock VERDICT command-exit 0. Not pre-red.",
        "M4_atomicity": "Real, three legs, each with on-disk proof and state-verified restore. See 'tests'."
      },
      "pairs_chosen": [
        "guides/email-and-calendar.zh-Hant.mdx:82 → **My Work → My Calendar** — resolved against src/apps/crm.app.ts group_work/nav_my_calendar (en label 'My Calendar'); English twin email-and-calendar.mdx:82 uses the identical string",
        "sales/activities.zh-Hant.mdx:94 and :109 → **My Work › My Tasks** — group_work/nav_my_tasks; English twin activities.mdx:94 and :109 identical",
        "sales/leads.zh-Hant.mdx:144 → **My Work › My Leads** — group_work/nav_my_leads; English twin leads.mdx:153 identical",
        "sales/meetings-and-calls.zh-Hant.mdx:145 → **My Work › My Calendar** — group_work/nav_my_calendar; English twin meetings-and-calls.mdx:145 identical",
        "sales/meetings-and-calls.zh-Hant.mdx:134 → **Activity › Events** — group_activity/nav_event. THE AWKWARD ONE: group and child were the same word because zh-CN labels BOTH group_activity and nav_event as 活动 (src/translations/zh-CN.ts:1285 and :1286); the group half resolved at all only because ja-JP labels group_activity 活動 (ja-JP.ts:1321). It is NOT 'Activity → Activities' (ships nowhere); the group's only two children are Events and Sales Activity, and the sentence is about the Events list. English twin meetings-and-calls.mdx:134 confirms: '**Activity › Events** is the one sidebar entry'."
      ],
      "tests": "All runs through the shared container lock (scripts/pm/os-verify-lock.sh, slot dev-1544); verdicts read from its VERDICT line, exit codes captured before any pipe.\n\nABLATION (three legs, guard file only, base origin/main 05f867e1). No rebuild leg exists and none was skipped: this guard imports ../src/apps and ../src/translations as TypeScript SOURCE through vitest and reads content/docs/** off disk — nothing on its resolution path goes through a package `exports` field or a dist/ directory, so there is no stale-artifact surface for a mutation to hide behind. Mutation proof on disk was therefore the whole of it, and it was done every leg: blob hash before/after PLUS anchored counts on removed AND injected text (removed-text count 0, injected-text count N, per file), a zero-hit anchor being a hard exit 3. Restore: `git checkout HEAD -- ABSOLUTE_PATH` (HEAD named explicitly) from a `trap ... EXIT INT TERM` with REPO_ROOT resolved by git rev-parse --show-toplevel, then verified BY STATE — `git diff HEAD` empty and every blob hash back to its HEAD value — never by exit code.\n\n  leg (a) prose only  → Tests 1 failed | 17 passed (18). FAIL 'holds no quarantined pair the docs no longer cite': \"AssertionError: KNOWN_UNRESOLVED_CRM entries no longer cited by any page: 我的工作 → 我的行事曆, 我的工作 → 我的任務, 我的工作 → 我的線索, 我的工作 → 我的日曆, 活動 → 活動. Someone fixed the prose — delete these lines so the ledger keeps measuring the real remainder.\" (test file line 708)\n  leg (b) ledger only → Tests 1 failed | 17 passed (18). FAIL 'name a group and a child this app really ships, in one locale': \"AssertionError: docs cite sidebar paths this app does not ship: content/docs/guides/email-and-calendar.zh-Hant.mdx: '我的工作 → 我的行事曆'; content/docs/sales/activities.zh-Hant.mdx: '我的工作 → 我的任務'; content/docs/sales/leads.zh-Hant.mdx: '我的工作 → 我的線索'; content/docs/sales/meetings-and-calls.zh-Hant.mdx: '活動 → 活動'; content/docs/sales/meetings-and-calls.zh-Hant.mdx: '我的工作 → 我的日曆'. Resolve the pair against src/apps/crm.app.ts and the locale bundles in src/translations — the child must be a child of that group, in the same locale. Do not add it to KNOWN_UNRESOLVED_CRM to get this green.\" (test file line 683)\n  leg (c) both        → Tests 18 passed (18), VERDICT command-exit 0.\n\nFULL GATE: `pnpm verify` (validate && typecheck && lint && lint:i18n-gate && hygiene && hygiene:tokens && build && test) — VERDICT command-exit 0, held 205s. 'Test Files 159 passed (159) / Tests 3344 passed | 1 skipped (3345)'; '✓ i18n lint gate: 0 i18n/missing-* issues'; '✓ source hygiene clean'; '✓ source token ratchet clean' (business semantics ~83,423 / ceiling ~85,000; interaction ~37,426 / ~40,000; authored total ~135,190 / ~140,000 — unmoved, the ratchet is comment-stripped and reads src/** only). It ran on exactly the bytes that were committed. RE-RUN AFTER THE FINAL COMMIT, at d979ece7 with a clean tree: hygiene + hygiene:tokens + the guard file — '✓ source hygiene clean', '✓ source token ratchet clean', 'Test Files 1 passed (1) / Tests 18 passed (18)', VERDICT command-exit 0.\n\nControl-byte scan on all five edited files plus the changeset: grep -naP '[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]' → no matches.",
      "mcp_calls": "2 — create_pull_request, add_issue_comment. Every GitHub READ went through the unauthenticated REST channel as dispatched; note that https://api.github.com/search/issues is refused on it (\"This GitHub API path is not available: sessions are bound to their configured repositories\"), so the dedupe sweep used the repo-scoped list endpoint (repos/objectstack-ai/hotcrm/issues?state=open, 89 rows) plus local grep instead.",
      "open_questions": [],
      "out_of_scope_findings": [
        "NOT FILED (reported for PM to file, per this dispatch's 'report them' instruction and the flagged MCP budget) — the navigation guard's OWN header publishes the reason #1368 retired. test/docs-setup-navigation-names.test.ts:159, inside the #1113 history section: 'the platform ships en / zh-CN / ja-JP / es-ES and no Traditional-Chinese pack, so a zh-Hant reader sees the English UI'. That is the causal claim #1368 struck. Dedupe: #1540 is the open card for this exact sentence, but its declared surface is seven content/docs zh-Hant pages (administration/automation, profiles, sandbox-and-releases, setup, sharing-and-security, guides/integrations, reference/glossary) — the guard file is not among them, and #1544's claim fences that file for this PR's duration, so no in-flight card covers it. I deliberately did NOT fix it: it sits outside 'the KNOWN_UNRESOLVED_CRM block only' that my claim declares, and the file is fenced against #1403. Consequence to weigh: after this PR the file states the correct reason at line ~420 and the retired one at line 159, ~260 lines apart.",
        "ALREADY COVERED by open decision card #1329 — no new card needed. zh-Hant pages spell SAVED VIEW names in Traditional (全部任務, 我的待辦任務, 我的日曆, 我的線索, 全部線索) while src/views/*.ts labels them in English and only en/zh-CN/ja-JP/es-ES are translated, so those exact strings render in no configuration — the same defect class as this card, one layer over, and unguarded. New datum for #1329: sales/activities.zh-Hant.mdx already ships BOTH conventions for the SAME view on adjacent lines — '**My Open Tasks**' (English, :96 and :109) and '**我的待辦任務**' (Traditional, :94 and :109). Untouched by this PR on purpose; navigation is what #1368 ruled on, view names are what #1329 has not."
      ]
    }

    Generated by Claude Code

  5. removed their assignment
    on Sep 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentation

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions