Skip to content

Phase 3b (audit) of #3455 — closing is_control inventory + plain-output contract statement #3456

Closed

Description

@dezren39

Phase 3b of design #3455 (a value cannot act on the terminal — one format-character contract for pkgs/id plain output). Design doc: files/designs/code-id-plain-output-rendering.md in the keep-the-four-repos-healthy goal workspace.

Gated on Phases 1–2 of #3455 (Phase 1 = #2839, Phase 2 = #3111) — do not start the inventory until they land. Phase 3a (#3089) is not a gate: it is independent.

Scope

Closing inventory + contract statement:

  1. Inventory every remaining is_control-only guard in pkgs/id/src not covered by Phases 1–2/3a — the grep population at design time (origin/main 70c20625) is the starting list, dispositioned not pre-judged:
    • src/world/util.rs:69 sanitize_display_name and :78 sanitize_chat (filter is_control only) — expected disposition: strip category Cf (the shared set from Phase 1) for sanitize_display_name, a name, per the petname precedent; sanitize_chat's disposition decided against how world chat is rendered downstream, with the design doc's recorded fallback (strip the bidi subset, with reason) if stripping ZWJ/ZWNJ would corrupt legitimate chat text.
    • Validator sites: src/directory.rs:1854,1867, src/directory_mail.rs:159, src/world/mod.rs:851, src/world_caps.rs:274, src/world_ssh.rs:1451,1748 — disposition each refuse-Cf (petname mould) or deliberately-local with its reason.
    • Payload-validation sites: src/world_presentation.rs:322,455, src/world_session/mod.rs:2098 — disposition against the presenter's own grapheme/width rules. id(web): world presenter widens every U+FE0F cluster to 2 — a letter+VS16 cell (a️) is Rust-valid at columns 1 but renderWorldSurface refuses the whole screen #3265 (U+FE0F cell width) is a different mechanism and is NOT adopted by this audit; record only whether the Cf question and the width question interact.
  2. Disposition each site in the closing evidence on this issue: escape / strip / refuse / deliberately-local, with its reason. Every site needing a fix is either fixed under this design before closing or filed as a named follow-up issue linked from the table.
  3. Write the contract into the src/commands/text.rs module doc (where the id(peers): a peer's announced name is printed raw — a newline in a gossip announcement forges extra TSV rows in id peers and the REPL #1613 ruling already lives): the two character classes (structure Cc + U+2028/U+2029; format Cf), the disposition-by-surface-kind rule, and the shared Cf definition's home + its Unicode version (16, from petname.rs's is_format_char as promoted by Phase 1).
  4. Post the closing evidence on design issue Design: a value cannot act on the terminal — one format-character (Cf) contract for pkgs/id plain output #3455, including the sibling-audit evidence id(peers): plain_field passes bidi/format controls raw — a gossip peer name with U+202E reaches the terminal unescaped and visually reorders the row's columns #2839's acceptance requires for the world/util.rs surfaces.

Acceptance criteria

  • A complete inventory table (site → disposition with reason or follow-up issue link) is posted on this issue; the grep basis for completeness is stated.
  • sanitize_display_name and sanitize_chat carry explicit recorded dispositions as above.
  • Every site dispositioned as needing a fix is either fixed under this design (PR linked) or filed as a named follow-up issue linked from the table.
  • The contract statement is written into the text.rs module doc (path + PR in the evidence).
  • Closing evidence is posted on Design: a value cannot act on the terminal — one format-character (Cf) contract for pkgs/id plain output #3455.

Activity

  1. added
    task/triageQueue packet kind: verify, reproduce, and route this item
    status/blockedQueue or user escalation state
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 1, 2026
  2. developing-today commented on Nov 1, 2026

    @developing-today
    Contributor
  3. dezren39 commented on Nov 1, 2026

    @dezren39
    MemberAuthor

    Filed by design #3455 as its Phase 3b closing audit. Triage packet enqueued: pilot task 5376 (queue repo-health-code-pilot, status queued at filing, dedupe-verified). This issue carries status/blocked: do not start the inventory until Phases 1–2 (#2839, #3111) land. Phase 3a (#3089) is independent and is not a gate.

  4. dezren39 commented on Nov 1, 2026

    @dezren39
    MemberAuthor

    agent-note:v1 — queue task 5376 (lane C) — triage verdict: scope CONFIRMED, hard gate NOT met, routed to gated follow-up task 5380

    Gate (fresh check, 2026-11-01): Phase 1 = #2839 OPEN; Phase 2 = #3111 OPEN (also carries status/blocked). Design #3455 OPEN. Phase 3a #3089 OPEN — independent, not a gate, per the design. The inventory must not start until #2839 and #3111 are both CLOSED.

    Scope confirmed against current main d61aec488 — the full grep population from the issue is present at the cited lines:

    • pkgs/id/src/world/util.rs:71 sanitize_display_name and :80 sanitize_chat — is_control-only filters (issue cites :69/:78 at design-time main; shifted +2).
    • Validators: directory.rs:1854,1867, directory_mail.rs:159, world/mod.rs:851, world_caps.rs:274, world_ssh.rs:1451,1748 — all present.
    • Payload validation: world_presentation.rs:322,455, world_session/mod.rs:2098 — all present.

    Routing: implementation/audit follow-up enqueued as queue task 5380 with the hard gate written into its packet (park with a gating note if either gate issue is still open at claim time) and this issue's acceptance criteria intact. No implementation in this triage task, per the packet.

  5. dezren39 commented on Nov 1, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · parked

  6. added
    work/assignedQueue worker lifecycle state
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    and removed
    status/blockedQueue or user escalation state
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 1, 2026
  7. 48 remaining items

  8. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    🤖 Conductor binding · openchamber-conductor dispatch 2026-11-02 (10:12 CST cycle)

  9. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    Phase 3b closing inventory (queue task 5380, worker repo-worker-code)

    Grep basis for completeness: grep -rn "is_control" pkgs/id/src --include="*.rs" on origin/main post-merge (base includes Phases 1-2/3a) returns 17 hits; the design-time moved files are tracked to their current homes in pkgs/id/crates/id-core/src/ (world_caps.rs:275, world_presentation.rs:319,535, petname.rs:258). Line numbers below are current. Sites already covered by Phases 1-2 (commands/text.rs:47, commands/group.rs:77,119) are excluded as landed; everything else is dispositioned.

    Contract applied (#3455): a plain-output value cannot act on the terminal — structure class (Cc + U+2028/U+2029) and format class (Cf, the one shared set). Row renderers escape, stripping sanitizers strip, ingest validators refuse.

    Escape (landed Phases 1-2, verified present)

    Site State
    commands/text.rs:47 breaks_row Cf + 2028/2029 escaped inside quotes (Phase 1 = #2839)
    commands/group.rs:77,119 trigger + quoted path Cf triggers quoting and is \u-escaped (Phase 2 = #3111)

    Strip

    Site Disposition + reason
    world/util.rs:71 sanitize_display_name strip Cf — already conformant, no change. Filters Cc plus the full shared set via crate::petname::is_format_char (verified: id-core/petname.rs:16 re-exports the same unicode.rs predicate, so no re-derivation). Name surface, petname-strip precedent. Tests pin U+202E/U+200B/ZWJ/ZWNJ stripping (world/util.rs tests).
    world/util.rs:98 sanitize_chat strip Cf with ZWJ/ZWNJ exception — already conformant, no change. Strips Cc (keeps LF/TAB) + all Cf except U+200C/U+200D, so legitimate joined-emoji chat text is not corrupted — this resolves the design doc's recorded fallback the strict way (full strip minus joiners, not bidi-subset). Decided against downstream rendering: stored text is re-checked by ChatMessage::check (fixed-point rule) and terminal display passes through terminal_text, which this audit brings to full-Cf. Tests pin U+2066-2069/U+200B/U+202E stripping, U+200C/U+200D + family-emoji preservation.
    world_ssh.rs:1798 terminal_text strip Cf — FIXED on this branch (PR #4458). Was Cc-only (keep LF/TAB); now also drops crate::is_format_char. This is the terminal-output gate for all SSH world display — exactly the contract's threat (one participant reordering another's terminal). Documented cost: ZWJ-joined emoji render as separate glyphs here; stored bytes untouched. Regression test added.

    Refuse

    Site Disposition + reason
    directory.rs:1866+1871 clean_name_mode, :1889+1894 clean_description_mode refuse-Cf — already conformant, no change. All new writes go through clean_name/clean_description with refuse_format=true. The refuse_format=false path is reachable only via apply_replay for journals predating the #1778 Cf refusal (deliberately-local journal compat, same shape as the #2960 display-name path). Tests pin U+200B/U+202E refusal.
    invite.rs:39+43 Invite::new refuse-Cf — already conformant, no change. Raw-name Cc + Cf refusal pre-trim (edge tab refused, not trimmed away); petname mould (#1770): the name lands on the trust prompt and is prefilled as a petname.
    id-core/petname.rs:258 refuse-Cf — the mould itself, no change. Home of the shared set's consumer contract.

    Deliberately-local (with reason, no change)

    Site Reason
    world/util.rs:88 legacy_sanitize_display_name Journal-compat read path only: the #2960 restore check (world/core.rs) accepts names that are fixed points of the pre-#2112 (Cc-only) sanitizer so worlds minted before format-stripping restore. Never used for new writes; new mint output is full-Cf-stripped.
    world/mod.rs:1142 parse_records key gate Key-grammar gate for bounded JSON record keys from world programs (Cc blocks log/terminal breakage at ingest). Per the printer-not-ingest decision, Cf coverage lives at the renderers (terminal_text fixed here; row renderers escape).
    directory_mail.rs:246 subject gate SMTP-injection gate: Cc refusal blocks CRLF header forgery. Cf cannot forge SMTP framing, and the subject is sink-only (code-generated or env override), never rendered by a plain CLI renderer. Injection test pins the gate.
    world_ssh.rs:1077 SshTarget user/host parse Address grammar: whitespace/Cc// never legitimate; prevents opaque russh failures and newline-bearing hosts in errors/known-hosts keys. A Cf char fails DNS resolution anyway; display of errors passes through terminal_text.
    world_ssh.rs:1501 is_public_document_name Name/path grammar gate (/, \\, Cc, internal tags). Cf has no traversal meaning; document display goes through terminal_text.
    world_session/mod.rs:2343 normalize_paste Program-input validation (bytes into world.input), not a display surface. Cf — including ZWJ — is legitimate program input; refusing it would corrupt legitimate pastes (same corruption argument as chat). Display gated downstream (terminal_text, presenters).
    web/markdown.rs:1579 link-destination check CommonMark destination-grammar predicate in the comrak/prosemirror web pipeline (not a terminal plain renderer): the spec excludes controls from bare destinations while Cf is legal destination text. A parser predicate, not an output sanitizer.
    id-core/world_caps.rs:275 delegation request id Id grammar for delegation matching (fail-closed: a Cf id matches no grant). Display of failures passes through gated paths.
    id-core/world_presentation.rs:319,535 surface grapheme/width gates Payload validation against the presenter's own grapheme/width rules (unicode-width, columns 1..=2). Cf refusal here would reject legitimate screens — ZWJ-joined emoji (family sequences) are Cf-bearing and width-valid. Cc refusal blocks terminal-driving cells; that is the correct local gate.
    #3265 (U+FE0F width) interaction Recorded, not adopted (out of scope per packet). U+FE0F is category Mn, not Cf; it is not in the shared set. The width question and the Cf question do not interact; the width mechanism is untouched.

    Needs-a-fix sites — none silently dropped

    Contract statement

    Written into the pkgs/id/src/commands/text.rs module doc on this branch (PR #4458): structure class (Cc + U+2028/U+2029), format class (Cf), disposition-by-surface-kind rule (escape / strip / refuse), shared Cf home (crate::is_format_char in id-core/src/unicode.rs) + Unicode version (16).

    Acceptance checkboxes 1-4 are met by this comment + PR #4458 + #4457; checkbox 5 (evidence on #3455) follows.

  10. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    agent-note:v1 — harvest by OpenChamber conductor (2026-11-02 10:32 CST cycle)

    The session dispatched for queue task 5380 (ses_e5e62e91351ffeH6HUPTlUlClp, Workhorse route) finished its work and opened PR #4458, but reported it could not run checkpoint/park because repo-queue.py is not present on the laptop. The conductor verified PR #4458 is OPEN on a fresh read and has parked queue task 5380 with the PR link (stage pr-open) for shepherd/merge review, so the claim does not expire silently.

  11. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    Picked up by queue worker lane code-g for task 5380 (execution lane: direct) to shepherd PR #4458. Fresh verification this shift: hard gate cleared (#2839 CLOSED, #3111 CLOSED); closing inventory present on this issue; closing evidence present on #3455; PR #4458 is MERGEABLE/CLEAN with Codex review completed on head 016cc35 with zero findings. Proceeding to merge under standing merge authority.

  12. added a commit that references this issue on Nov 2, 2026
  13. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    Phase 3b audit complete. PR #4458 merged (merge commit 7297b5d): plain-output contract statement written into pkgs/id/src/commands/text.rs module doc, and terminal_text in world_ssh.rs now strips the shared Cf set (regression test included). Closing inventory with per-site dispositions is posted on this issue; closing evidence is posted on design #3455; the one follow-up site is filed as #4457. Codex review on PR #4458 completed with zero findings. Completed by queue worker lane code-g under task 5380.

  14. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    agent-note:v1 — conductor harvest flag (2026-11-02 10:52 CST cycle)

    PR #4458 is MERGED (2026-11-02T17:10:35Z, fresh gh read) and this issue is CLOSED — the work of queue task 5380 (dispatched by the conductor 2026-11-02 10:12 cycle, parked at stage pr-open by the conductor 10:32 cycle) has fully landed. Task 5380 itself is still parked in the fleet queue: the owning lane owes the terminal verb (complete 5380 with PR #4458 as evidence). Flagged this round; per the harvest rule it becomes a stuck harvest if it survives another round unterminated.

  15. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    Stuck harvest escalation (conductor, 2026-11-02 11:12 CST cycle): PR #4458 is MERGED and this issue is CLOSED, but queue task 5380 remains parked (stage pr-open, unchanged since 2026-11-02T16:57Z) — this is the second consecutive conductor round it has survived unterminated after being flagged for harvest, so it is now reported as a stuck harvest. Owning lane: please complete task 5380 with the PR #4458 merge evidence.

  16. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    Correction / retraction (conductor, 2026-11-02): the "stuck harvest escalation" note above (issuecomment-6583765063) was WRONG and is retracted. A fresh direct queue read shows task 5380 is done (stage merge_ready, updated 2026-11-02T17:11:26Z, PR #4458 recorded) — it was completed just before the 11:12 CST conductor cycle's sweep, and the cycle's stuck-harvest claim rested on a stale timestamp carried over from the prior cycle's log instead of a fresh task read. No action is owed by the owning lane. Sorry for the noise.

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

Metadata

Metadata

Assignees

Labels

app/idPackage/app: id (pkgs/ or apps/ in this repo)kind/enhancementsource/design-architectFiled by the repo design architect jobtask/triageQueue packet kind: verify, reproduce, and route this item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions