Skip to content

feat(website): system documentation #/docs from specs/docs + Queen PROJECT tab (key p) — Round 2 item D - #980

Merged
gHashTag merged 3 commits into
mainfrom
feat/queen-docs-project
Sep 9, 2026
Merged

gHashTag merged 3 commits into
mainfrom
feat/queen-docs-project

Conversation

@gHashTag

@gHashTag gHashTag commented Sep 9, 2026

Copy link
Copy Markdown
Owner

Round 2 — item D: system documentation #/docs from specs/docs + Queen GAME TAB «ПРОЕКТ» (key p)

Stacked on #978 (feat/queen-tools-layer5). Merge order: #976 → #978 → this PR. Pairs with t27 #3551 (specs/docs/system.t27 + chapters + specs/i18n/docs-ru.t27, closes t27 #3550) and ghpages PR #20 (hides the old t27.ai/docs/ page; merge only after this PR is published, so #/docs exists before the redirect).

D2 — documentation generated from specs (trinity side)

  • scripts/docs-from-specs.mjs — compiles the vendored specs/docs/**.t27 with the pinned t27_compiler.wasm (sha256 4d9c0447b5ca2887…), joins EN prose from docs/system/*.md and RU from the specs/i18n/docs-ru.t27 bundle (i18n/docs.ru.json), and writes public/docs/system-docs.json. Wired into prebuild. No regex parsing of .t27; no hand-written lists.
  • QA qa/docs-spec-contract.mjs (npm run check:docs): every chapter has a body (EN + RU), every SOURCES path exists in the vendored tree or the checkout, every generated table is non-empty, no forbidden superlatives in EN/RU prose, routes /docs + /docs/:chapter present, figures file with <figcaption>, print CSS, PROJECT jumps, DOCS_URL = '#/docs' and no https://t27.ai/docs/ left in Navigation/Footer/ProductionDashboard.
  • scripts/docs-from-specs.test.mjs — 8 tests (npm run test:docs-specs).
  • UI src/pages/SystemDocs.tsx — routes #/docs, #/docs/<chapter>, ?embed=1. Left TOC (chapters/sections; collapsible bar under 980px), right content: prose + generated tables + six data-driven inline SVG figures (src/components/SystemDocsFigures.tsx): five-layer ladder with live counts, 27-letter agent ring, 6+1 phase cycle, law hierarchy, skills↔crons↔agents graph, tools family map. Every figure has a caption and a "Data source / Источник данных" line. Print-friendly CSS (@media print). EN/RU via the site i18n toggle.
  • Navigation.tsx / Footer.tsx / ProductionDashboard.tsx: DOCS_URL → #/docs (internal, no target=_blank).
  • Vendored byte-identical copies from t27@2518951 (head of t27 #3551): specs/docs/**, docs/system/*.md, specs/i18n/docs-ru.t27, SOUL.md, AGENTS.md, CLAUDE.md, docs/T27-CONSTITUTION.md, docs/agents/AGENTS_ALPHABET.md, docs/coordination/TASK_PROTOCOL.md, README-ZENODO.md, docs/reports/TNF-ARTICLE-*.md. Catalog pins moved from f726e2e to 2518951.

D3 — Queen GAME TAB «ПРОЕКТ» / PROJECT

  • New module project (src/lib/queenModules.ts, queenHud.ts): key p (digits 1–0 are exhausted), glyph §; the key is documented in the rail hint ("(key p)" / "(клавиша p)") and in qa/agents-spec-contract.mjs (keys 1234567890p).
  • QueenAgents.tsx kind project: embeds SystemDocs in embed mode with quick jumps «Проект», «Правила игры», «Система», «Алфавит», «Инструменты», «Свидетели» (PROJECT_JUMPS, EN/RU). Counts panel: chapters, RU chapters, sources, typecheck ok.
  • Rail with 11 items (Queen.css): rows follow the item count, the rail is a declared scroller, «Свернуть» / Collapse is sticky and always last; below 760px the rail switches to two-column tiles.
  • ModulesBlock.tsx counts read MODULES.length (was hand-written "EIGHT"/"ten").

Witnesses (local, apps/website)

Check Command Result
Docs contract npm run check:docs PASS — 7 chapters, 32 sections; tables 7, figures 6; laws 7, phases 7; sources 31 (vendored 29, checkout 2); ru 7/7; typecheck ok 8/8; pinned at 2518951; PROJECT on key p
Agents contract npm run check:agents PASS — Queen views 11, modules 11, keys 1234567890p; skills 26/26, crons 33/33, agents 27/27
Catalogs npm run check:tools / check:spec-catalog / check:skills-catalog / check:crons-catalog PASS (62 / 760 / 26 / 33)
Languages npm run check:explorer-languages / check:queen-languages PASS (7 pages / 277/277)
Unit tests node --test scripts/*.test.mjs 92/92
Types npm run typecheck:ratchet 179 errors / 26 files = baseline, no file gained errors
Lint npx eslint . 180 problems = baseline
Build npx vite build OK
Viewport CHROME_PATH=… npm run check:queen-viewport FAIL (pre-existing): undeclared scrollers .queen27-hud-viewport, .queen27-hud-intel, alerts slot; the rail (.queen27-hud-command) is now declared and no longer reported; rows that pass show cmd=11

Chromium screenshots (local, not committed): #/queen?tab=project at 1280×600/700/900 — rail probe: 12 buttons (11 modules + Collapse), Collapse below all tiles, no rail overflow, rail bottom = viewport − 20px, 0 console errors; #/docs/layers EN 1280×900, #/docs/alphabet RU 1280×900 and 390×844, #/docs/queen EN 1280×900.

Boundaries

  • The wiring reads what the sources say. Recorded discrepancies stay in the prose and are not resolved here: AGENTS.md "L1-L8" vs constitution L1–L7; alphabet 6+1 phases vs CLAUDE.md AEL; tri git has no clap variant.
  • 6 of 7 chapter bodies have no lead paragraph before the first ## (accepted; the contract checks for a non-empty body).
  • .tool_artifacts/ untouched; public/*/manifest.json not hand-edited; generatedAt timestamps in the regenerated catalogs are the pre-existing prebuild pattern.
  • Known infra reds on trinity PRs: claude-review, pr-opened, Brain Health.
  • Not merged — review requested.

@gHashTag
gHashTag force-pushed the feat/queen-tools-layer5 branch from 7b8d160 to 4dd56a0 Compare September 9, 2026 17:10
@gHashTag
gHashTag force-pushed the feat/queen-docs-project branch from 01814c0 to 4bdd0d2 Compare September 9, 2026 17:19
…PROJECT tab (key p)

Round 2 - item D (D2 trinity side + D3).

D2 - documentation generated from t27 specs/docs
- scripts/docs-from-specs.mjs: compiles vendored specs/docs/**.t27 with the
  pinned t27_compiler.wasm, joins docs/system/*.md prose (EN) and the RU
  bundle from specs/i18n/docs-ru.t27 (via i18n/docs.ru.json), and writes
  public/docs/system-docs.json (7 chapters, 32 sections, 7 tables, 6 figures,
  laws 7, phases 7, 31 SOURCES). Wired into prebuild.
- qa/docs-spec-contract.mjs (npm run check:docs): every chapter has a body,
  every SOURCES path exists in the vendored tree or the checkout, every
  generated table is non-empty, no forbidden superlatives in EN/RU prose,
  routes/figures/print CSS/jumps present, DOCS_URL points at #/docs.
- scripts/docs-from-specs.test.mjs (8 tests).
- src/pages/SystemDocs.tsx (#/docs, #/docs/:chapter, ?embed=1): left TOC,
  prose + generated tables, six data-driven inline SVG figures in
  src/components/SystemDocsFigures.tsx (five-layer ladder with live counts,
  27-letter agent ring, 6+1 phase cycle, law hierarchy, skills-crons-agents
  graph, tools family map), each with caption and data-source line;
  print-friendly CSS; EN/RU toggle via site i18n.
- Navigation/Footer/ProductionDashboard: DOCS_URL -> #/docs (was t27.ai/docs).
- Vendored byte-identical copies from t27@2518951 (specs/docs/**, docs/system,
  specs/i18n/docs-ru.t27, SOUL.md, AGENTS.md, CLAUDE.md, constitution,
  alphabet, TASK_PROTOCOL, README-ZENODO, TNF-ARTICLE reports).

D3 - Queen GAME TAB "project"
- New module project (PROJECT / ПРОЕКТ), key p (digits exhausted), glyph §,
  documented in the rail hint and in qa/agents-spec-contract.mjs (keys
  1234567890p). Embeds SystemDocs in embed mode with quick jumps: Project /
  Rules of the game / System / Alphabet / Tooling / Witnesses.
- Rail with 11 items: rows follow the item count, rail scrolls when needed,
  "Collapse" is sticky and always last; below 760px the rail switches to
  two-column tiles. Chromium screenshots 1280x600/700/900 captured locally
  (collapse below all tiles, no overflow, 0 console errors).
- ModulesBlock counts read MODULES.length instead of hand-written words.

Checks (local): check:docs, check:agents, check:tools, check:spec-catalog,
check:skills-catalog, check:crons-catalog, check:explorer-languages,
check:queen-languages PASS; node --test scripts/*.test.mjs 92/92;
typecheck:ratchet 179/26 = baseline; eslint 180 = baseline; vite build OK.
check:queen-viewport still FAIL on the pre-existing undeclared scrollers
(hud-viewport, hud-intel, alerts slot); the rail is now a declared scroller.
…) and mirror the rewrite in the RU bundle

t27's check_documented_commands_exist gate read five new dead tri mentions
in docs/system/queen.md and layers.md (`tri git`, line-initial "tri card").
t27 feat/specs-docs@64fe6204 states the discrepancy in prose instead of
quoting a command; the vendored copies are byte-identical to that commit,
i18n/docs.ru.json carries the same rewrite, and the catalogs are pinned
at 64fe620. check:docs, check:agents, catalogs, languages PASS; 92/92 tests.
…ols-layer5 (twelve modules, keys 1234567890tp)

Rebased onto the tools branch as it stands after #979 landed on main:
FUNCTIONS holds key 0, TOOLS key t, and PROJECT is the twelfth module on
key p. HUD_KEYS ends ...0,t,p; the agents, viewport and docs contracts hold
twelve views and the key string 1234567890tp; ModulesBlock reads its count
from MODULES.length. QueenAgents carries six kinds (skills, crons, agents,
functions, tools, project).

Vendored specs/docs and specs/i18n/docs-ru.t27 are byte-identical to
gHashTag/t27 feat/specs-docs 93727f73 (PR #3551, issue #3550); the
catalogs and public/docs/system-docs.json are regenerated at that pin.
Screenshots of #/queen?tab=project at 1280x600/700/900 show the rail of
twelve with COLLAPSE still in view.

check:docs 7 chapters, 32 sections, ru 7/7, typecheck ok 8/8; check:agents
Queen views 12, modules 12; tests 100/100; typecheck ratchet 179/26 and
eslint 180 unchanged; vite build ok.

Closes #3550
@gHashTag
gHashTag changed the base branch from feat/queen-tools-layer5 to main September 9, 2026 17:32
@gHashTag
gHashTag force-pushed the feat/queen-docs-project branch from 4bdd0d2 to 07b0c46 Compare September 9, 2026 17:32
@gHashTag
gHashTag merged commit c881e7f into main Sep 9, 2026
22 of 27 checks passed
@gHashTag
gHashTag deleted the feat/queen-docs-project branch September 9, 2026 17:44
github-actions Bot added a commit that referenced this pull request Sep 9, 2026
feat(website): system documentation #/docs from specs/docs + Queen PROJECT tab (key p) — Round 2 item D (#980)

* feat(website): system documentation #/docs from specs/docs and Queen PROJECT tab (key p)

Round 2 - item D (D2 trinity side + D3).

D2 - documentation generated from t27 specs/docs
- scripts/docs-from-specs.mjs: compiles vendored specs/docs/**.t27 with the
  pinned t27_compiler.wasm, joins docs/system/*.md prose (EN) and the RU
  bundle from specs/i18n/docs-ru.t27 (via i18n/docs.ru.json), and writes
  public/docs/system-docs.json (7 chapters, 32 sections, 7 tables, 6 figures,
  laws 7, phases 7, 31 SOURCES). Wired into prebuild.
- qa/docs-spec-contract.mjs (npm run check:docs): every chapter has a body,
  every SOURCES path exists in the vendored tree or the checkout, every
  generated table is non-empty, no forbidden superlatives in EN/RU prose,
  routes/figures/print CSS/jumps present, DOCS_URL points at #/docs.
- scripts/docs-from-specs.test.mjs (8 tests).
- src/pages/SystemDocs.tsx (#/docs, #/docs/:chapter, ?embed=1): left TOC,
  prose + generated tables, six data-driven inline SVG figures in
  src/components/SystemDocsFigures.tsx (five-layer ladder with live counts,
  27-letter agent ring, 6+1 phase cycle, law hierarchy, skills-crons-agents
  graph, tools family map), each with caption and data-source line;
  print-friendly CSS; EN/RU toggle via site i18n.
- Navigation/Footer/ProductionDashboard: DOCS_URL -> #/docs (was t27.ai/docs).
- Vendored byte-identical copies from t27@2518951 (specs/docs/**, docs/system,
  specs/i18n/docs-ru.t27, SOUL.md, AGENTS.md, CLAUDE.md, constitution,
  alphabet, TASK_PROTOCOL, README-ZENODO, TNF-ARTICLE reports).

D3 - Queen GAME TAB "project"
- New module project (PROJECT / ПРОЕКТ), key p (digits exhausted), glyph §,
  documented in the rail hint and in qa/agents-spec-contract.mjs (keys
  1234567890p). Embeds SystemDocs in embed mode with quick jumps: Project /
  Rules of the game / System / Alphabet / Tooling / Witnesses.
- Rail with 11 items: rows follow the item count, rail scrolls when needed,
  "Collapse" is sticky and always last; below 760px the rail switches to
  two-column tiles. Chromium screenshots 1280x600/700/900 captured locally
  (collapse below all tiles, no overflow, 0 console errors).
- ModulesBlock counts read MODULES.length instead of hand-written words.

Checks (local): check:docs, check:agents, check:tools, check:spec-catalog,
check:skills-catalog, check:crons-catalog, check:explorer-languages,
check:queen-languages PASS; node --test scripts/*.test.mjs 92/92;
typecheck:ratchet 179/26 = baseline; eslint 180 = baseline; vite build OK.
check:queen-viewport still FAIL on the pre-existing undeclared scrollers
(hud-viewport, hud-intel, alerts slot); the rail is now a declared scroller.

* docs: re-vendor docs/system from t27@64fe620 (no dead tri invocations) and mirror the rewrite in the RU bundle

t27's check_documented_commands_exist gate read five new dead tri mentions
in docs/system/queen.md and layers.md (`tri git`, line-initial "tri card").
t27 feat/specs-docs@64fe6204 states the discrepancy in prose instead of
quoting a command; the vendored copies are byte-identical to that commit,
i18n/docs.ru.json carries the same rewrite, and the catalogs are pinned
at 64fe620. check:docs, check:agents, catalogs, languages PASS; 92/92 tests.

* docs: pin catalogs at t27@93727f7 after the rebase onto feat/queen-tools-layer5 (twelve modules, keys 1234567890tp)

Rebased onto the tools branch as it stands after #979 landed on main:
FUNCTIONS holds key 0, TOOLS key t, and PROJECT is the twelfth module on
key p. HUD_KEYS ends ...0,t,p; the agents, viewport and docs contracts hold
twelve views and the key string 1234567890tp; ModulesBlock reads its count
from MODULES.length. QueenAgents carries six kinds (skills, crons, agents,
functions, tools, project).

Vendored specs/docs and specs/i18n/docs-ru.t27 are byte-identical to
gHashTag/t27 feat/specs-docs 93727f73 (PR #3551, issue #3550); the
catalogs and public/docs/system-docs.json are regenerated at that pin.
Screenshots of #/queen?tab=project at 1280x600/700/900 show the rail of
twelve with COLLAPSE still in view.

check:docs 7 chapters, 32 sections, ru 7/7, typecheck ok 8/8; check:agents
Queen views 12, modules 12; tests 100/100; typecheck ratchet 179/26 and
eslint 180 unchanged; vite build ok.

Closes #3550

---------

Co-authored-by: gHashTag <gHashTag@users.noreply.github.com>
gHashTag added a commit that referenced this pull request Sep 14, 2026
* test(website): derive the Queen viewport gate's command count from HUD_VIEWS

The gate pinned commands !== 11 while the rail already had 12 views (#980 added
PROJECT and left the pin). On the base commit 429499e it reports
"COUNT commands=12" at every size, next to other long-standing failures
(undeclared scrollers, the alerts slot, views=0 on the comb) that this commit
does not touch. The count is now read from src/components/queenHud.ts HUD_VIEWS,
so a new view cannot leave it stale again.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(website): TRI, the app at app.t27.ai inside the Queen, one screen per address

A thirteenth Queen tab, TRI (key r; the digits are spent, t is TOOLS, p is
PROJECT). A row of the app's screens - Feed, Agent, AI, Profile, CRM - over one
frame of the real app page, https://app.t27.ai/<route>?embed=1&lang=<lang>.

Every screen has its own address: #/queen?tab=tri&screen=chat, and path= for
one CRM client (/crm/<id>, /crm/<id>/chat) or one profile (/<username>). A click
writes it, a reload reads it, an address changed from outside (Back, a link, a
script) moves the screen and the frame. Stages the app switches inside the frame
come back as {type:'t27-app', kind:'route', path} and are written to the address
without reloading the frame. The frame URL is always APP_ORIGIN plus a route
from src/lib/triScreens.ts or a deep path checked against it.

- Both address writers (the shell's tab, TRI's screen) build from the live hash:
  React Router 7.13 hands the setSearchParams updater the params of the hook's
  last render, and its navigations wait in a transition, so two quick writes
  built that way erased each other. Leaving TRI drops screen= and path=.
- An address that lags the live hash is TRI's own pending write, not an outside
  change, so it never moves the screen back or reloads the frame.
- The frame is keyed per screen: a fresh browsing context adds no history entry,
  so Back leaves TRI instead of walking the frame. name="t27-embed" marks it.
- Load is not success (a frame refused by frame-ancestors still loads Chrome's
  error page): without the app's own message 8 s after load, a strip says the
  app did not answer and links out to the same screen.
- Only plain-object messages from app.t27.ai and from TRI's own frame are heard;
  nothing is ever posted into the frame.
- Inside the app (its Hive frames this game) TRI frames nothing and says so.
- The phone rail scrolls its active button into view (13 items, about 6 fit).
- The landing renders no TRI preview: it would load the whole app for every
  visitor inside a sandbox where its link out cannot open.

Checks: qa/tri-screens-contract.mjs (pure, added to website-checks.yml as
check:tri) and qa/queen-tri-contract.mjs (browser, app frames answered by a CDP
Fetch stub; fails at check 1 on 429499e; a combined mutant - route message
reloading the frame, tabAddress keeping screen=, no rail scroll - fails checks
4, 8 and 11). agents-spec-contract pins keys 1234567890tpr and TRI on r.

Production app.t27.ai still refuses the frame (frame-ancestors has no t27.ai)
until the player's CSP and embed bridge ship; TRI then shows its strip.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(website): TRI keeps Back usable and customer ids out of the address

Review findings on the TRI tab.

- Back after the app navigates inside the frame. The app's router pushes a
  history entry for every in-app page (AiPipelineNav, CRM links). A fresh
  iframe element per screen stranded those entries, so after two in-frame
  pages and a screen click Back did nothing twice (measured on the previous
  build). TRI now keeps one frame element for the life of the view and moves
  it with contentWindow.location.replace: a screen click still adds no entry,
  and Back walks the app's own pages with screen= following the app's route
  message. The src attribute stays the first URL (changing it would push);
  data-src names where TRI sent the frame. The full fix is on the app's side:
  in embed mode it should replace instead of push, and then one Back leaves
  TRI (check 13 pins that as a control). Entries pushed in the frame before
  leaving TRI for another tab still stay dead until the app replaces.
- path= no longer carries a CRM client. /crm/<id> ids are customers'
  Telegram ids and would sit in the t27.ai address bar, history and copied
  links. The CRM is addressed at its list; path= is kept for one profile.
- A trailing slash no longer drops the profile path (/alice/ -> /alice).
- The iframe's name="t27-embed" is gone: the app never read it (it decides
  embed from ?embed=1 and its parent and keeps its own marker in window.name).
- An embedded Queen (a landing preview, embed=1) reached TRI by the r key and
  framed the whole app inside the preview's sandbox. TRI there frames nothing
  and says so (new COPY key triPreview, en and ru).

Checks: qa/tri-screens-contract.mjs pins no CRM path, the slash, JSON
strings never parsed, and lang encoded as one query value; it fails on the
previous triScreens.ts, and 12 of 12 independent mutants fail it.
qa/queen-tri-contract.mjs: check 5 now covers the CRM id and a profile path,
new checks 12 (in-frame pushes, a screen click, Back walks them), 13 (control:
an app that replaces leaves TRI on one Back) and 14 (embedded Queen plus r
asks app.t27.ai for nothing); 5, 12 and 14 fail on the previous build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
github-actions Bot added a commit that referenced this pull request Sep 14, 2026
feat(website): TRI tab, the app at app.t27.ai inside the Queen (#1011)

* test(website): derive the Queen viewport gate's command count from HUD_VIEWS

The gate pinned commands !== 11 while the rail already had 12 views (#980 added
PROJECT and left the pin). On the base commit 429499e it reports
"COUNT commands=12" at every size, next to other long-standing failures
(undeclared scrollers, the alerts slot, views=0 on the comb) that this commit
does not touch. The count is now read from src/components/queenHud.ts HUD_VIEWS,
so a new view cannot leave it stale again.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(website): TRI, the app at app.t27.ai inside the Queen, one screen per address

A thirteenth Queen tab, TRI (key r; the digits are spent, t is TOOLS, p is
PROJECT). A row of the app's screens - Feed, Agent, AI, Profile, CRM - over one
frame of the real app page, https://app.t27.ai/<route>?embed=1&lang=<lang>.

Every screen has its own address: #/queen?tab=tri&screen=chat, and path= for
one CRM client (/crm/<id>, /crm/<id>/chat) or one profile (/<username>). A click
writes it, a reload reads it, an address changed from outside (Back, a link, a
script) moves the screen and the frame. Stages the app switches inside the frame
come back as {type:'t27-app', kind:'route', path} and are written to the address
without reloading the frame. The frame URL is always APP_ORIGIN plus a route
from src/lib/triScreens.ts or a deep path checked against it.

- Both address writers (the shell's tab, TRI's screen) build from the live hash:
  React Router 7.13 hands the setSearchParams updater the params of the hook's
  last render, and its navigations wait in a transition, so two quick writes
  built that way erased each other. Leaving TRI drops screen= and path=.
- An address that lags the live hash is TRI's own pending write, not an outside
  change, so it never moves the screen back or reloads the frame.
- The frame is keyed per screen: a fresh browsing context adds no history entry,
  so Back leaves TRI instead of walking the frame. name="t27-embed" marks it.
- Load is not success (a frame refused by frame-ancestors still loads Chrome's
  error page): without the app's own message 8 s after load, a strip says the
  app did not answer and links out to the same screen.
- Only plain-object messages from app.t27.ai and from TRI's own frame are heard;
  nothing is ever posted into the frame.
- Inside the app (its Hive frames this game) TRI frames nothing and says so.
- The phone rail scrolls its active button into view (13 items, about 6 fit).
- The landing renders no TRI preview: it would load the whole app for every
  visitor inside a sandbox where its link out cannot open.

Checks: qa/tri-screens-contract.mjs (pure, added to website-checks.yml as
check:tri) and qa/queen-tri-contract.mjs (browser, app frames answered by a CDP
Fetch stub; fails at check 1 on 429499e; a combined mutant - route message
reloading the frame, tabAddress keeping screen=, no rail scroll - fails checks
4, 8 and 11). agents-spec-contract pins keys 1234567890tpr and TRI on r.

Production app.t27.ai still refuses the frame (frame-ancestors has no t27.ai)
until the player's CSP and embed bridge ship; TRI then shows its strip.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(website): TRI keeps Back usable and customer ids out of the address

Review findings on the TRI tab.

- Back after the app navigates inside the frame. The app's router pushes a
  history entry for every in-app page (AiPipelineNav, CRM links). A fresh
  iframe element per screen stranded those entries, so after two in-frame
  pages and a screen click Back did nothing twice (measured on the previous
  build). TRI now keeps one frame element for the life of the view and moves
  it with contentWindow.location.replace: a screen click still adds no entry,
  and Back walks the app's own pages with screen= following the app's route
  message. The src attribute stays the first URL (changing it would push);
  data-src names where TRI sent the frame. The full fix is on the app's side:
  in embed mode it should replace instead of push, and then one Back leaves
  TRI (check 13 pins that as a control). Entries pushed in the frame before
  leaving TRI for another tab still stay dead until the app replaces.
- path= no longer carries a CRM client. /crm/<id> ids are customers'
  Telegram ids and would sit in the t27.ai address bar, history and copied
  links. The CRM is addressed at its list; path= is kept for one profile.
- A trailing slash no longer drops the profile path (/alice/ -> /alice).
- The iframe's name="t27-embed" is gone: the app never read it (it decides
  embed from ?embed=1 and its parent and keeps its own marker in window.name).
- An embedded Queen (a landing preview, embed=1) reached TRI by the r key and
  framed the whole app inside the preview's sandbox. TRI there frames nothing
  and says so (new COPY key triPreview, en and ru).

Checks: qa/tri-screens-contract.mjs pins no CRM path, the slash, JSON
strings never parsed, and lang encoded as one query value; it fails on the
previous triScreens.ts, and 12 of 12 independent mutants fail it.
qa/queen-tri-contract.mjs: check 5 now covers the CRM id and a profile path,
new checks 12 (in-frame pushes, a screen click, Back walks them), 13 (control:
an app that replaces leaves TRI on one Back) and 14 (embedded Queen plus r
asks app.t27.ai for nothing); 5, 12 and 14 fail on the previous build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant