✨ Describe terminal grids as executable document structure (#729) - #733

Open
taras wants to merge 2 commits into
architect/717-terminal-grid-contractfrom
agent/issue-729-terminal-grid
Open

✨ Describe terminal grids as executable document structure (#729)#733
taras wants to merge 2 commits into
architect/717-terminal-grid-contractfrom
agent/issue-729-terminal-grid

Conversation

@taras

@tarastaras commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Closes#729. First implementation Story under Quest #717.

Why

An author cannot yet write a terminal grid, and nothing can tell them whether
the one they wrote is well formed. #717's later Stories build the terminal
authority, the concurrent pane lifecycle and the tmux provider on top of an
authored structure that has to exist and be checkable first — on every runtime,
including the ones that will never install a provider.

This Story owns that structure and nothing else.

What changes

<Terminal.Grid> and <Terminal> become reserved core structural syntax.

Before: both names were ordinary component names. <Terminal title="A" />
resolved a repository file or a registration, or failed as an unresolved
component; nothing knew what a grid was.

After: both are the language's own syntax. A registration cannot claim either
name and a repository file named after one never stands in for it. The grammar,
the placement rules and the derived row-major layout are decided from source,
shared by expansion and document validation, and reported by xmd syntax:

<Terminal.Grid columns={2}>
<Terminaltitle="Agent">…</Terminal>
<Terminaltitle="Shell" />
</Terminal.Grid>

The grid's closed props hold one required positive-integer columns; a pane's
hold one required non-empty title. Titles are display labels and may repeat —
a pane's structural identity is its ordinal among the grid's direct children.
Rows are derived in authored row-major order and the last row is left short.

Executing a valid grid refuses, because no terminal provider exists yet, and it
refuses before any pane body expands or a default shell starts.

How it works

scanner → terminalGridStructure (source rules) → columns and titles resolved
→ terminalGridLayout (row-major placement) → provider refusal

structural-rules.ts gains terminalGridStructure() beside the rules for every
other construct, so expansion and validation cannot disagree about what a grid's
source says: which panes it holds, which form each was written in, and what is
wrong with the way it was written. Only whitespace and direct <Terminal> panes
may appear in a grid; a control structure that would produce panes as it ran
cannot be one, because which panes exist is what the grid must know before it
opens anything.

terminal-grid.ts is where the source facts and the computed columns meet.
It places the panes and reports the rows they fill — provider-neutral data
naming no terminal, socket, process or window.

expandTerminalGrid() runs that order and then refuses. The refusal carries the
derived layout as its structured cause, the way <Session.Launch> carries its
failure class, so a test asserts on the grid that was derived rather than on the
wording of a sentence.

Review guide

Start with:packages/core/tests/terminal-grid-structure.test.ts

Then review:

  1. packages/core/src/structural.ts — the two declarations, which is what makes
    the names reserved and what xmd syntax prints.
  2. packages/core/src/structural-rules.tsterminalGridStructure() and the
    pane, column and title rules it reads from source.
  3. packages/core/src/terminal-grid.ts — the derived layout.
  4. packages/core/src/expand.tsexpandTerminalGrid(), the order it decides
    in, and the stray-<Terminal> branch.
  5. packages/core/src/document-validation.ts — the same rules, reported as
    diagnostics.

Look carefully at:

  • The order in expandTerminalGrid(). Source structure is decided first, then
    columns, then every pane's title, and only a complete grid reaches the
    refusal. Anything that moved provider contact earlier would let a partial grid
    escape.
  • misplacedTerminalViolations(). A <Terminal> deeper than a direct child, and
    a <Terminal.Grid> below another one, are found by walking rather than by a
    lexical flag, so a pane hidden inside an <If> inside a grid is still refused.

What must stay true

  • One rule catalog — enforced by expansion and validation both calling
    terminalGridStructure(), and checked by the grammar rows in
    terminal-grid-structure.test.ts and the matching invalid-form table in
    document-validation.test.ts.
  • Reserved means unshadowable — enforced by RESERVED_STRUCTURAL, and checked by
    the TG3 row in syntax-catalog.test.ts that puts components/Terminal.md and
    components/Terminal/Grid.md on disk and still finds both names structural,
    and refuses a registration of either.
  • Describing the language probes no terminal — enforced by the catalog reading
    declarations rather than a host, and checked by the TG3 row in
    syntax-cli.test.ts that traps API.Process.exec while building the catalog.
  • Nothing beneath a grid runs before a provider does — enforced by the order
    above, and checked by rows that trap component resolution, expression
    evaluation and code-block execution and assert all three stayed empty.

How to verify it

deno task test packages/core/tests/terminal-grid-structure.test.ts
deno task test packages/core/tests/syntax-catalog.test.ts
deno task test packages/core/tests/document-validation.test.ts
deno task test packages/cli/tests/syntax-cli.test.ts
  • TG1 proves the grammar accepts exactly a paired grid with a positive
    integer columns and one or more panes, and both pane forms with a non-empty
    title; it fails if an unknown prop, as, a self-closing grid, a
    non-integer or non-positive columns, or an absent or empty title were
    admitted — as a literal or as a computed value.
  • TG2 proves an empty grid, direct text, a non-pane element, a pane produced
    by control flow, a nested grid and a pane outside a grid are all refused, and
    that whitespace between panes is inert; it fails if any of them expanded, or
    if a refusal reported the wrong construct.
  • TG4 proves one through five panes under two and three columns produce the
    exact row-major positions, that duplicate titles stay valid, and that the
    ordinal rather than the title is identity; it fails if the layout balanced or
    padded the last row, or if two panes sharing a title collapsed.
  • The provider-non-observation assertion is not vacuous: the same recorders fire
    on a body that does expand — a <Boom /> to resolve, a seen() call to
    evaluate and a ```bash exec block to run were confirmed recorded outside a
    grid before the rows relying on their silence were trusted.
  • TG3 proves xmd syntax reports both entries with their exact forms and
    contracts, and that document validation returns the same diagnostics without
    reaching exec, fetch, a write or eval compilation; it fails if either name
    moved out of the structural category, or if any refused boundary fired.

Run under all three runtimes:

npx tsx --tsconfig tsconfig.node.json --test --test-concurrency=1 packages/core/tests/terminal-grid-structure.test.ts
bun test --timeout=60000 packages/core/tests/terminal-grid-structure.test.ts
npx tsx --tsconfig tsconfig.node.json --test --test-concurrency=1 packages/cli/tests/syntax-cli.test.ts
bun test --timeout=60000 packages/cli/tests/syntax-cli.test.ts

Scope

Included

  • The two reserved structural declarations and their catalog entries.
  • The grammar, placement rules and derived row-major layout.
  • Expansion's refusal on a host with no terminal-grid provider.
  • Document validation's diagnostics for every invalid authored form.

Intentionally unchanged

  • No terminal authority, provider API, pane claim or readiness latch.
  • No concurrent pane execution, pane scope isolation, or default-shell start.
  • No native Agent integration inside a pane, and no tmux anything.
  • No durability, retained layout record or replay admission.
  • architecture.md and specs/executable-mdx-spec.md describe the whole of
    Quest: Add interactive terminal grids to executable documents #717 and are unchanged here; §6.21 and Tier TG were settled by the
    architecture commit this branch starts from.

New abstractions

  • TerminalPane and TerminalGridStructure in structural-rules.ts exist
    because the grid's panes are read once and used by two consumers — expansion
    and document validation — exactly as SwitchCase/SwitchStructure are.

  • terminal-grid.ts (TerminalGridLayout, TerminalGridCell, PlacedPane,
    terminalGridLayout()) exists because placement needs both the source facts
    and the computed columns, which is a different question from what the source
    says. It is the value Quest: Add interactive terminal grids to executable documents #717's execution Story hands a provider.

  • resolveStructuralProp() in expand.ts exists because both columns and
    title are read the same way — literal or computed, with absence meaning
    absence — and duplicating that would let the two drift.

  • Each new abstraction has multiple concrete uses or a clear justification.

  • No speculative functionality is included.

Risks and limitations

  • Stack base: This PR is based on architecture PR 🏗️ Define interactive terminal grid architecture (#717) #734 at 736b909d.
    Its focused diff begins at 01bb083f, with the approved description
    refinement in 97be0632. The remaining Quest: Add interactive terminal grids to executable documents #717 Stories stack above this PR,
    and the complete feature is verified at the final stack head before any layer
    merges.
  • The new test file has no recorded weight, so the shard partition charges it the
    heaviest weight the current corpus records until Measure test weights runs
    on a runner. That is the documented behavior for a new file, not a defect.
  • A document that executes a valid grid fails today. That is this Story's
    contract — the execution Story replaces the refusal — but it does mean the
    syntax is writable and inspectable before it is runnable.

Scope confirmation

  • Every changed file supports the purpose described above.
  • Unrelated cleanup and formatting changes are excluded.
  • Generated or mechanical changes are clearly identified.
  • The description matches the final diff and test results.

`<Terminal.Grid>` and `<Terminal>` become reserved core structural syntax.
This Story owns the authored structure alone: the grammar, the placement
rules, and the row-major layout a grid derives. No terminal authority,
provider, pane execution, shell, durability or replay is built here.
The grid's closed props hold one required positive-integer `columns`; a
pane's hold one required non-empty `title`. Titles are display labels and
identify nothing — a pane's structural identity is its ordinal among the
grid's direct children, and rows are derived in authored row-major order
with the last row left short.
`structural-rules.ts` decides what the source says, so expansion and
document validation cannot disagree about it: only whitespace and direct
`<Terminal>` panes may appear in a grid, and an empty grid, direct text, a
non-pane element, a control structure that would produce panes, a nested
grid, and a pane written anywhere else are refused. `terminal-grid.ts`
places the panes once `columns` and each `title` are known.
A grid the grammar accepts runs until a terminal provider would be asked
for one. This build installs none, so it refuses there, before any pane
body expands or a default shell starts, and carries the layout it derived
beside the refusal.
Evidence rows TG1-TG4: the new structural suite owns TG1, TG2 and TG4; the
catalog, validation and `xmd syntax` suites own TG3.
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown

PR #733: ✨ Describe terminal grids as executable document structure (#729)

12 files, +2070 / -36

Scope

🔴 PR has 2106 lines changed. Split into focused PRs.

🟡 2106 lines changed. PRs under 400 receive more thorough review.

Structural

Oxlint structural signals:

  • no-unused-vars ×7: packages/core/src/expand.ts
  • no-unnecessary-type-assertion ×1: packages/core/src/expand.ts

Slop

  • packages/core/src/document-validation.ts:1094// below the grid that the grid does not lay out.
  • packages/core/src/document-validation.ts:1099// is left is a pane with no grid above it at all.

Oxlint slop signals:

  • no-inferrable-types ×2: packages/core/src/expand.ts

Static Analysis

Oxlint: 25 diagnostics across 2 files (11 rules)
Density: 0.012 violations/added-line

no-unused-vars (7): packages/core/src/expand.ts
no-base-to-string (4): packages/core/src/expand.ts
no-unsafe-type-assertion (3): packages/core/src/expand.ts
no-array-sort (2): packages/core/src/document-validation.ts
no-inferrable-types (2): packages/core/src/expand.ts
unbound-method (2): packages/core/src/expand.ts
no-shadow (1): packages/core/src/expand.ts
restrict-template-expressions (1): packages/core/src/expand.ts
consistent-return (1): packages/core/src/document-validation.ts
no-unnecessary-type-assertion (1): packages/core/src/expand.ts
no-implied-eval (1): packages/core/src/expand.ts

Correctness

FILE: packages/core/src/expand.ts, PATTERN: no-unused-vars, CONCERN: Unused variable insideTerminalGrid in context, QUESTION: Is insideTerminalGrid necessary or can it be removed?
FILE: packages/core/src/expand.ts, PATTERN: no-unused-vars, CONCERN: Unused variable strayTerminalMessage in error handling, QUESTION: Is strayTerminalMessage referenced elsewhere or can it be eliminated?
FILE: packages/core/src/expand.ts, PATTERN: no-unsafe-type-assertion, CONCERN: Type assertion in terminalGridLayout may hide missing props, QUESTION: Are type assertions justified or can they be replaced with safer checks?
FILE: packages/core/src/expand.ts, PATTERN: no-array-sort, CONCERN: misplacedTerminalViolations uses sort on a list of violations, QUESTION: Is sorting necessary, or does it introduce unintended side effects?
FILE: packages/core/src/expand.ts, PATTERN: signal cluster, CONCERN: Multiple Oxlint violations (no-unused-vars, no-unsafe-type-assertion, no-array-sort) in same file, QUESTION: Are these issues clustered due to unreviewed code or design debt?
FILE: packages/core/src/document-validation.ts, PATTERN: signal cluster, CONCERN: no-array-sort and consistent-return violations in same file, QUESTION: Are these violations isolated or indicative of broader issues?

Both descriptions lead with what the author can do and show the invocation
to copy. The placement rule, the row-major detail and the title's display
role are the catalog's structured fields and §6.21's to state, not a second
reference entry beside the forms.
The frozen catalog entries in `syntax-catalog.test.ts` mirror the two
declarations, so they move with them.

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found 2 redundant comments. Inline suggestions to remove them below.

case "Terminal.Grid":
// The whole layout is decided from source, so every pane's own mistake
// is reported where it was written — and so is a construct written
// below the grid that the grid does not lay out.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// below the grid that the grid does not lay out.

case "Terminal":
// A well-placed `<Terminal>` is its grid's, and one placed wrongly
// under a grid is already reported by that grid's own structure. What
// is left is a pane with no grid above it at all.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// is left is a pane with no grid above it at all.

Sign up for freeto 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.

Describe terminal grids as executable document structure

1 participant

@taras
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

✨ Describe terminal grids as executable document structure (#729) - #733

Open
taras wants to merge 2 commits into
architect/717-terminal-grid-contractfrom
agent/issue-729-terminal-grid
Open

✨ Describe terminal grids as executable document structure (#729)#733
taras wants to merge 2 commits into
architect/717-terminal-grid-contractfrom
agent/issue-729-terminal-grid

Conversation

@taras

@tarastaras commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Closes#729. First implementation Story under Quest #717.

Why

An author cannot yet write a terminal grid, and nothing can tell them whether
the one they wrote is well formed. #717's later Stories build the terminal
authority, the concurrent pane lifecycle and the tmux provider on top of an
authored structure that has to exist and be checkable first — on every runtime,
including the ones that will never install a provider.

This Story owns that structure and nothing else.

What changes

<Terminal.Grid> and <Terminal> become reserved core structural syntax.

Before: both names were ordinary component names. <Terminal title="A" />
resolved a repository file or a registration, or failed as an unresolved
component; nothing knew what a grid was.

After: both are the language's own syntax. A registration cannot claim either
name and a repository file named after one never stands in for it. The grammar,
the placement rules and the derived row-major layout are decided from source,
shared by expansion and document validation, and reported by xmd syntax:

<Terminal.Grid columns={2}>
<Terminaltitle="Agent">…</Terminal>
<Terminaltitle="Shell" />
</Terminal.Grid>

The grid's closed props hold one required positive-integer columns; a pane's
hold one required non-empty title. Titles are display labels and may repeat —
a pane's structural identity is its ordinal among the grid's direct children.
Rows are derived in authored row-major order and the last row is left short.

Executing a valid grid refuses, because no terminal provider exists yet, and it
refuses before any pane body expands or a default shell starts.

How it works

scanner → terminalGridStructure (source rules) → columns and titles resolved
→ terminalGridLayout (row-major placement) → provider refusal

structural-rules.ts gains terminalGridStructure() beside the rules for every
other construct, so expansion and validation cannot disagree about what a grid's
source says: which panes it holds, which form each was written in, and what is
wrong with the way it was written. Only whitespace and direct <Terminal> panes
may appear in a grid; a control structure that would produce panes as it ran
cannot be one, because which panes exist is what the grid must know before it
opens anything.

terminal-grid.ts is where the source facts and the computed columns meet.
It places the panes and reports the rows they fill — provider-neutral data
naming no terminal, socket, process or window.

expandTerminalGrid() runs that order and then refuses. The refusal carries the
derived layout as its structured cause, the way <Session.Launch> carries its
failure class, so a test asserts on the grid that was derived rather than on the
wording of a sentence.

Review guide

Start with:packages/core/tests/terminal-grid-structure.test.ts

Then review:

  1. packages/core/src/structural.ts — the two declarations, which is what makes
    the names reserved and what xmd syntax prints.
  2. packages/core/src/structural-rules.tsterminalGridStructure() and the
    pane, column and title rules it reads from source.
  3. packages/core/src/terminal-grid.ts — the derived layout.
  4. packages/core/src/expand.tsexpandTerminalGrid(), the order it decides
    in, and the stray-<Terminal> branch.
  5. packages/core/src/document-validation.ts — the same rules, reported as
    diagnostics.

Look carefully at:

  • The order in expandTerminalGrid(). Source structure is decided first, then
    columns, then every pane's title, and only a complete grid reaches the
    refusal. Anything that moved provider contact earlier would let a partial grid
    escape.
  • misplacedTerminalViolations(). A <Terminal> deeper than a direct child, and
    a <Terminal.Grid> below another one, are found by walking rather than by a
    lexical flag, so a pane hidden inside an <If> inside a grid is still refused.

What must stay true

  • One rule catalog — enforced by expansion and validation both calling
    terminalGridStructure(), and checked by the grammar rows in
    terminal-grid-structure.test.ts and the matching invalid-form table in
    document-validation.test.ts.
  • Reserved means unshadowable — enforced by RESERVED_STRUCTURAL, and checked by
    the TG3 row in syntax-catalog.test.ts that puts components/Terminal.md and
    components/Terminal/Grid.md on disk and still finds both names structural,
    and refuses a registration of either.
  • Describing the language probes no terminal — enforced by the catalog reading
    declarations rather than a host, and checked by the TG3 row in
    syntax-cli.test.ts that traps API.Process.exec while building the catalog.
  • Nothing beneath a grid runs before a provider does — enforced by the order
    above, and checked by rows that trap component resolution, expression
    evaluation and code-block execution and assert all three stayed empty.

How to verify it

deno task test packages/core/tests/terminal-grid-structure.test.ts
deno task test packages/core/tests/syntax-catalog.test.ts
deno task test packages/core/tests/document-validation.test.ts
deno task test packages/cli/tests/syntax-cli.test.ts
  • TG1 proves the grammar accepts exactly a paired grid with a positive
    integer columns and one or more panes, and both pane forms with a non-empty
    title; it fails if an unknown prop, as, a self-closing grid, a
    non-integer or non-positive columns, or an absent or empty title were
    admitted — as a literal or as a computed value.
  • TG2 proves an empty grid, direct text, a non-pane element, a pane produced
    by control flow, a nested grid and a pane outside a grid are all refused, and
    that whitespace between panes is inert; it fails if any of them expanded, or
    if a refusal reported the wrong construct.
  • TG4 proves one through five panes under two and three columns produce the
    exact row-major positions, that duplicate titles stay valid, and that the
    ordinal rather than the title is identity; it fails if the layout balanced or
    padded the last row, or if two panes sharing a title collapsed.
  • The provider-non-observation assertion is not vacuous: the same recorders fire
    on a body that does expand — a <Boom /> to resolve, a seen() call to
    evaluate and a ```bash exec block to run were confirmed recorded outside a
    grid before the rows relying on their silence were trusted.
  • TG3 proves xmd syntax reports both entries with their exact forms and
    contracts, and that document validation returns the same diagnostics without
    reaching exec, fetch, a write or eval compilation; it fails if either name
    moved out of the structural category, or if any refused boundary fired.

Run under all three runtimes:

npx tsx --tsconfig tsconfig.node.json --test --test-concurrency=1 packages/core/tests/terminal-grid-structure.test.ts
bun test --timeout=60000 packages/core/tests/terminal-grid-structure.test.ts
npx tsx --tsconfig tsconfig.node.json --test --test-concurrency=1 packages/cli/tests/syntax-cli.test.ts
bun test --timeout=60000 packages/cli/tests/syntax-cli.test.ts

Scope

Included

  • The two reserved structural declarations and their catalog entries.
  • The grammar, placement rules and derived row-major layout.
  • Expansion's refusal on a host with no terminal-grid provider.
  • Document validation's diagnostics for every invalid authored form.

Intentionally unchanged

  • No terminal authority, provider API, pane claim or readiness latch.
  • No concurrent pane execution, pane scope isolation, or default-shell start.
  • No native Agent integration inside a pane, and no tmux anything.
  • No durability, retained layout record or replay admission.
  • architecture.md and specs/executable-mdx-spec.md describe the whole of
    Quest: Add interactive terminal grids to executable documents #717 and are unchanged here; §6.21 and Tier TG were settled by the
    architecture commit this branch starts from.

New abstractions

  • TerminalPane and TerminalGridStructure in structural-rules.ts exist
    because the grid's panes are read once and used by two consumers — expansion
    and document validation — exactly as SwitchCase/SwitchStructure are.

  • terminal-grid.ts (TerminalGridLayout, TerminalGridCell, PlacedPane,
    terminalGridLayout()) exists because placement needs both the source facts
    and the computed columns, which is a different question from what the source
    says. It is the value Quest: Add interactive terminal grids to executable documents #717's execution Story hands a provider.

  • resolveStructuralProp() in expand.ts exists because both columns and
    title are read the same way — literal or computed, with absence meaning
    absence — and duplicating that would let the two drift.

  • Each new abstraction has multiple concrete uses or a clear justification.

  • No speculative functionality is included.

Risks and limitations

  • Stack base: This PR is based on architecture PR 🏗️ Define interactive terminal grid architecture (#717) #734 at 736b909d.
    Its focused diff begins at 01bb083f, with the approved description
    refinement in 97be0632. The remaining Quest: Add interactive terminal grids to executable documents #717 Stories stack above this PR,
    and the complete feature is verified at the final stack head before any layer
    merges.
  • The new test file has no recorded weight, so the shard partition charges it the
    heaviest weight the current corpus records until Measure test weights runs
    on a runner. That is the documented behavior for a new file, not a defect.
  • A document that executes a valid grid fails today. That is this Story's
    contract — the execution Story replaces the refusal — but it does mean the
    syntax is writable and inspectable before it is runnable.

Scope confirmation

  • Every changed file supports the purpose described above.
  • Unrelated cleanup and formatting changes are excluded.
  • Generated or mechanical changes are clearly identified.
  • The description matches the final diff and test results.

`<Terminal.Grid>` and `<Terminal>` become reserved core structural syntax.
This Story owns the authored structure alone: the grammar, the placement
rules, and the row-major layout a grid derives. No terminal authority,
provider, pane execution, shell, durability or replay is built here.
The grid's closed props hold one required positive-integer `columns`; a
pane's hold one required non-empty `title`. Titles are display labels and
identify nothing — a pane's structural identity is its ordinal among the
grid's direct children, and rows are derived in authored row-major order
with the last row left short.
`structural-rules.ts` decides what the source says, so expansion and
document validation cannot disagree about it: only whitespace and direct
`<Terminal>` panes may appear in a grid, and an empty grid, direct text, a
non-pane element, a control structure that would produce panes, a nested
grid, and a pane written anywhere else are refused. `terminal-grid.ts`
places the panes once `columns` and each `title` are known.
A grid the grammar accepts runs until a terminal provider would be asked
for one. This build installs none, so it refuses there, before any pane
body expands or a default shell starts, and carries the layout it derived
beside the refusal.
Evidence rows TG1-TG4: the new structural suite owns TG1, TG2 and TG4; the
catalog, validation and `xmd syntax` suites own TG3.
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown

PR #733: ✨ Describe terminal grids as executable document structure (#729)

12 files, +2070 / -36

Scope

🔴 PR has 2106 lines changed. Split into focused PRs.

🟡 2106 lines changed. PRs under 400 receive more thorough review.

Structural

Oxlint structural signals:

  • no-unused-vars ×7: packages/core/src/expand.ts
  • no-unnecessary-type-assertion ×1: packages/core/src/expand.ts

Slop

  • packages/core/src/document-validation.ts:1094// below the grid that the grid does not lay out.
  • packages/core/src/document-validation.ts:1099// is left is a pane with no grid above it at all.

Oxlint slop signals:

  • no-inferrable-types ×2: packages/core/src/expand.ts

Static Analysis

Oxlint: 25 diagnostics across 2 files (11 rules)
Density: 0.012 violations/added-line

no-unused-vars (7): packages/core/src/expand.ts
no-base-to-string (4): packages/core/src/expand.ts
no-unsafe-type-assertion (3): packages/core/src/expand.ts
no-array-sort (2): packages/core/src/document-validation.ts
no-inferrable-types (2): packages/core/src/expand.ts
unbound-method (2): packages/core/src/expand.ts
no-shadow (1): packages/core/src/expand.ts
restrict-template-expressions (1): packages/core/src/expand.ts
consistent-return (1): packages/core/src/document-validation.ts
no-unnecessary-type-assertion (1): packages/core/src/expand.ts
no-implied-eval (1): packages/core/src/expand.ts

Correctness

FILE: packages/core/src/expand.ts, PATTERN: no-unused-vars, CONCERN: Unused variable insideTerminalGrid in context, QUESTION: Is insideTerminalGrid necessary or can it be removed?
FILE: packages/core/src/expand.ts, PATTERN: no-unused-vars, CONCERN: Unused variable strayTerminalMessage in error handling, QUESTION: Is strayTerminalMessage referenced elsewhere or can it be eliminated?
FILE: packages/core/src/expand.ts, PATTERN: no-unsafe-type-assertion, CONCERN: Type assertion in terminalGridLayout may hide missing props, QUESTION: Are type assertions justified or can they be replaced with safer checks?
FILE: packages/core/src/expand.ts, PATTERN: no-array-sort, CONCERN: misplacedTerminalViolations uses sort on a list of violations, QUESTION: Is sorting necessary, or does it introduce unintended side effects?
FILE: packages/core/src/expand.ts, PATTERN: signal cluster, CONCERN: Multiple Oxlint violations (no-unused-vars, no-unsafe-type-assertion, no-array-sort) in same file, QUESTION: Are these issues clustered due to unreviewed code or design debt?
FILE: packages/core/src/document-validation.ts, PATTERN: signal cluster, CONCERN: no-array-sort and consistent-return violations in same file, QUESTION: Are these violations isolated or indicative of broader issues?

Both descriptions lead with what the author can do and show the invocation
to copy. The placement rule, the row-major detail and the title's display
role are the catalog's structured fields and §6.21's to state, not a second
reference entry beside the forms.
The frozen catalog entries in `syntax-catalog.test.ts` mirror the two
declarations, so they move with them.

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found 2 redundant comments. Inline suggestions to remove them below.

case "Terminal.Grid":
// The whole layout is decided from source, so every pane's own mistake
// is reported where it was written — and so is a construct written
// below the grid that the grid does not lay out.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// below the grid that the grid does not lay out.

case "Terminal":
// A well-placed `<Terminal>` is its grid's, and one placed wrongly
// under a grid is already reported by that grid's own structure. What
// is left is a pane with no grid above it at all.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// is left is a pane with no grid above it at all.

Sign up for freeto 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.

Describe terminal grids as executable document structure

1 participant

@taras
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

✨ Describe terminal grids as executable document structure (#729) - #733

Open
taras wants to merge 2 commits into
architect/717-terminal-grid-contractfrom
agent/issue-729-terminal-grid
Open

✨ Describe terminal grids as executable document structure (#729)#733
taras wants to merge 2 commits into
architect/717-terminal-grid-contractfrom
agent/issue-729-terminal-grid

Conversation

@taras

@tarastaras commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Closes#729. First implementation Story under Quest #717.

Why

An author cannot yet write a terminal grid, and nothing can tell them whether
the one they wrote is well formed. #717's later Stories build the terminal
authority, the concurrent pane lifecycle and the tmux provider on top of an
authored structure that has to exist and be checkable first — on every runtime,
including the ones that will never install a provider.

This Story owns that structure and nothing else.

What changes

<Terminal.Grid> and <Terminal> become reserved core structural syntax.

Before: both names were ordinary component names. <Terminal title="A" />
resolved a repository file or a registration, or failed as an unresolved
component; nothing knew what a grid was.

After: both are the language's own syntax. A registration cannot claim either
name and a repository file named after one never stands in for it. The grammar,
the placement rules and the derived row-major layout are decided from source,
shared by expansion and document validation, and reported by xmd syntax:

<Terminal.Grid columns={2}>
<Terminaltitle="Agent">…</Terminal>
<Terminaltitle="Shell" />
</Terminal.Grid>

The grid's closed props hold one required positive-integer columns; a pane's
hold one required non-empty title. Titles are display labels and may repeat —
a pane's structural identity is its ordinal among the grid's direct children.
Rows are derived in authored row-major order and the last row is left short.

Executing a valid grid refuses, because no terminal provider exists yet, and it
refuses before any pane body expands or a default shell starts.

How it works

scanner → terminalGridStructure (source rules) → columns and titles resolved
→ terminalGridLayout (row-major placement) → provider refusal

structural-rules.ts gains terminalGridStructure() beside the rules for every
other construct, so expansion and validation cannot disagree about what a grid's
source says: which panes it holds, which form each was written in, and what is
wrong with the way it was written. Only whitespace and direct <Terminal> panes
may appear in a grid; a control structure that would produce panes as it ran
cannot be one, because which panes exist is what the grid must know before it
opens anything.

terminal-grid.ts is where the source facts and the computed columns meet.
It places the panes and reports the rows they fill — provider-neutral data
naming no terminal, socket, process or window.

expandTerminalGrid() runs that order and then refuses. The refusal carries the
derived layout as its structured cause, the way <Session.Launch> carries its
failure class, so a test asserts on the grid that was derived rather than on the
wording of a sentence.

Review guide

Start with:packages/core/tests/terminal-grid-structure.test.ts

Then review:

  1. packages/core/src/structural.ts — the two declarations, which is what makes
    the names reserved and what xmd syntax prints.
  2. packages/core/src/structural-rules.tsterminalGridStructure() and the
    pane, column and title rules it reads from source.
  3. packages/core/src/terminal-grid.ts — the derived layout.
  4. packages/core/src/expand.tsexpandTerminalGrid(), the order it decides
    in, and the stray-<Terminal> branch.
  5. packages/core/src/document-validation.ts — the same rules, reported as
    diagnostics.

Look carefully at:

  • The order in expandTerminalGrid(). Source structure is decided first, then
    columns, then every pane's title, and only a complete grid reaches the
    refusal. Anything that moved provider contact earlier would let a partial grid
    escape.
  • misplacedTerminalViolations(). A <Terminal> deeper than a direct child, and
    a <Terminal.Grid> below another one, are found by walking rather than by a
    lexical flag, so a pane hidden inside an <If> inside a grid is still refused.

What must stay true

  • One rule catalog — enforced by expansion and validation both calling
    terminalGridStructure(), and checked by the grammar rows in
    terminal-grid-structure.test.ts and the matching invalid-form table in
    document-validation.test.ts.
  • Reserved means unshadowable — enforced by RESERVED_STRUCTURAL, and checked by
    the TG3 row in syntax-catalog.test.ts that puts components/Terminal.md and
    components/Terminal/Grid.md on disk and still finds both names structural,
    and refuses a registration of either.
  • Describing the language probes no terminal — enforced by the catalog reading
    declarations rather than a host, and checked by the TG3 row in
    syntax-cli.test.ts that traps API.Process.exec while building the catalog.
  • Nothing beneath a grid runs before a provider does — enforced by the order
    above, and checked by rows that trap component resolution, expression
    evaluation and code-block execution and assert all three stayed empty.

How to verify it

deno task test packages/core/tests/terminal-grid-structure.test.ts
deno task test packages/core/tests/syntax-catalog.test.ts
deno task test packages/core/tests/document-validation.test.ts
deno task test packages/cli/tests/syntax-cli.test.ts
  • TG1 proves the grammar accepts exactly a paired grid with a positive
    integer columns and one or more panes, and both pane forms with a non-empty
    title; it fails if an unknown prop, as, a self-closing grid, a
    non-integer or non-positive columns, or an absent or empty title were
    admitted — as a literal or as a computed value.
  • TG2 proves an empty grid, direct text, a non-pane element, a pane produced
    by control flow, a nested grid and a pane outside a grid are all refused, and
    that whitespace between panes is inert; it fails if any of them expanded, or
    if a refusal reported the wrong construct.
  • TG4 proves one through five panes under two and three columns produce the
    exact row-major positions, that duplicate titles stay valid, and that the
    ordinal rather than the title is identity; it fails if the layout balanced or
    padded the last row, or if two panes sharing a title collapsed.
  • The provider-non-observation assertion is not vacuous: the same recorders fire
    on a body that does expand — a <Boom /> to resolve, a seen() call to
    evaluate and a ```bash exec block to run were confirmed recorded outside a
    grid before the rows relying on their silence were trusted.
  • TG3 proves xmd syntax reports both entries with their exact forms and
    contracts, and that document validation returns the same diagnostics without
    reaching exec, fetch, a write or eval compilation; it fails if either name
    moved out of the structural category, or if any refused boundary fired.

Run under all three runtimes:

npx tsx --tsconfig tsconfig.node.json --test --test-concurrency=1 packages/core/tests/terminal-grid-structure.test.ts
bun test --timeout=60000 packages/core/tests/terminal-grid-structure.test.ts
npx tsx --tsconfig tsconfig.node.json --test --test-concurrency=1 packages/cli/tests/syntax-cli.test.ts
bun test --timeout=60000 packages/cli/tests/syntax-cli.test.ts

Scope

Included

  • The two reserved structural declarations and their catalog entries.
  • The grammar, placement rules and derived row-major layout.
  • Expansion's refusal on a host with no terminal-grid provider.
  • Document validation's diagnostics for every invalid authored form.

Intentionally unchanged

  • No terminal authority, provider API, pane claim or readiness latch.
  • No concurrent pane execution, pane scope isolation, or default-shell start.
  • No native Agent integration inside a pane, and no tmux anything.
  • No durability, retained layout record or replay admission.
  • architecture.md and specs/executable-mdx-spec.md describe the whole of
    Quest: Add interactive terminal grids to executable documents #717 and are unchanged here; §6.21 and Tier TG were settled by the
    architecture commit this branch starts from.

New abstractions

  • TerminalPane and TerminalGridStructure in structural-rules.ts exist
    because the grid's panes are read once and used by two consumers — expansion
    and document validation — exactly as SwitchCase/SwitchStructure are.

  • terminal-grid.ts (TerminalGridLayout, TerminalGridCell, PlacedPane,
    terminalGridLayout()) exists because placement needs both the source facts
    and the computed columns, which is a different question from what the source
    says. It is the value Quest: Add interactive terminal grids to executable documents #717's execution Story hands a provider.

  • resolveStructuralProp() in expand.ts exists because both columns and
    title are read the same way — literal or computed, with absence meaning
    absence — and duplicating that would let the two drift.

  • Each new abstraction has multiple concrete uses or a clear justification.

  • No speculative functionality is included.

Risks and limitations

  • Stack base: This PR is based on architecture PR 🏗️ Define interactive terminal grid architecture (#717) #734 at 736b909d.
    Its focused diff begins at 01bb083f, with the approved description
    refinement in 97be0632. The remaining Quest: Add interactive terminal grids to executable documents #717 Stories stack above this PR,
    and the complete feature is verified at the final stack head before any layer
    merges.
  • The new test file has no recorded weight, so the shard partition charges it the
    heaviest weight the current corpus records until Measure test weights runs
    on a runner. That is the documented behavior for a new file, not a defect.
  • A document that executes a valid grid fails today. That is this Story's
    contract — the execution Story replaces the refusal — but it does mean the
    syntax is writable and inspectable before it is runnable.

Scope confirmation

  • Every changed file supports the purpose described above.
  • Unrelated cleanup and formatting changes are excluded.
  • Generated or mechanical changes are clearly identified.
  • The description matches the final diff and test results.

`<Terminal.Grid>` and `<Terminal>` become reserved core structural syntax.
This Story owns the authored structure alone: the grammar, the placement
rules, and the row-major layout a grid derives. No terminal authority,
provider, pane execution, shell, durability or replay is built here.
The grid's closed props hold one required positive-integer `columns`; a
pane's hold one required non-empty `title`. Titles are display labels and
identify nothing — a pane's structural identity is its ordinal among the
grid's direct children, and rows are derived in authored row-major order
with the last row left short.
`structural-rules.ts` decides what the source says, so expansion and
document validation cannot disagree about it: only whitespace and direct
`<Terminal>` panes may appear in a grid, and an empty grid, direct text, a
non-pane element, a control structure that would produce panes, a nested
grid, and a pane written anywhere else are refused. `terminal-grid.ts`
places the panes once `columns` and each `title` are known.
A grid the grammar accepts runs until a terminal provider would be asked
for one. This build installs none, so it refuses there, before any pane
body expands or a default shell starts, and carries the layout it derived
beside the refusal.
Evidence rows TG1-TG4: the new structural suite owns TG1, TG2 and TG4; the
catalog, validation and `xmd syntax` suites own TG3.
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown

PR #733: ✨ Describe terminal grids as executable document structure (#729)

12 files, +2070 / -36

Scope

🔴 PR has 2106 lines changed. Split into focused PRs.

🟡 2106 lines changed. PRs under 400 receive more thorough review.

Structural

Oxlint structural signals:

  • no-unused-vars ×7: packages/core/src/expand.ts
  • no-unnecessary-type-assertion ×1: packages/core/src/expand.ts

Slop

  • packages/core/src/document-validation.ts:1094// below the grid that the grid does not lay out.
  • packages/core/src/document-validation.ts:1099// is left is a pane with no grid above it at all.

Oxlint slop signals:

  • no-inferrable-types ×2: packages/core/src/expand.ts

Static Analysis

Oxlint: 25 diagnostics across 2 files (11 rules)
Density: 0.012 violations/added-line

no-unused-vars (7): packages/core/src/expand.ts
no-base-to-string (4): packages/core/src/expand.ts
no-unsafe-type-assertion (3): packages/core/src/expand.ts
no-array-sort (2): packages/core/src/document-validation.ts
no-inferrable-types (2): packages/core/src/expand.ts
unbound-method (2): packages/core/src/expand.ts
no-shadow (1): packages/core/src/expand.ts
restrict-template-expressions (1): packages/core/src/expand.ts
consistent-return (1): packages/core/src/document-validation.ts
no-unnecessary-type-assertion (1): packages/core/src/expand.ts
no-implied-eval (1): packages/core/src/expand.ts

Correctness

FILE: packages/core/src/expand.ts, PATTERN: no-unused-vars, CONCERN: Unused variable insideTerminalGrid in context, QUESTION: Is insideTerminalGrid necessary or can it be removed?
FILE: packages/core/src/expand.ts, PATTERN: no-unused-vars, CONCERN: Unused variable strayTerminalMessage in error handling, QUESTION: Is strayTerminalMessage referenced elsewhere or can it be eliminated?
FILE: packages/core/src/expand.ts, PATTERN: no-unsafe-type-assertion, CONCERN: Type assertion in terminalGridLayout may hide missing props, QUESTION: Are type assertions justified or can they be replaced with safer checks?
FILE: packages/core/src/expand.ts, PATTERN: no-array-sort, CONCERN: misplacedTerminalViolations uses sort on a list of violations, QUESTION: Is sorting necessary, or does it introduce unintended side effects?
FILE: packages/core/src/expand.ts, PATTERN: signal cluster, CONCERN: Multiple Oxlint violations (no-unused-vars, no-unsafe-type-assertion, no-array-sort) in same file, QUESTION: Are these issues clustered due to unreviewed code or design debt?
FILE: packages/core/src/document-validation.ts, PATTERN: signal cluster, CONCERN: no-array-sort and consistent-return violations in same file, QUESTION: Are these violations isolated or indicative of broader issues?

Both descriptions lead with what the author can do and show the invocation
to copy. The placement rule, the row-major detail and the title's display
role are the catalog's structured fields and §6.21's to state, not a second
reference entry beside the forms.
The frozen catalog entries in `syntax-catalog.test.ts` mirror the two
declarations, so they move with them.

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found 2 redundant comments. Inline suggestions to remove them below.

case "Terminal.Grid":
// The whole layout is decided from source, so every pane's own mistake
// is reported where it was written — and so is a construct written
// below the grid that the grid does not lay out.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// below the grid that the grid does not lay out.

case "Terminal":
// A well-placed `<Terminal>` is its grid's, and one placed wrongly
// under a grid is already reported by that grid's own structure. What
// is left is a pane with no grid above it at all.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// is left is a pane with no grid above it at all.

Sign up for freeto 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.

Describe terminal grids as executable document structure

1 participant

@taras
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

✨ Describe terminal grids as executable document structure (#729) - #733

Open
taras wants to merge 2 commits into
architect/717-terminal-grid-contractfrom
agent/issue-729-terminal-grid
Open

✨ Describe terminal grids as executable document structure (#729)#733
taras wants to merge 2 commits into
architect/717-terminal-grid-contractfrom
agent/issue-729-terminal-grid

Conversation

@taras

@tarastaras commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Closes#729. First implementation Story under Quest #717.

Why

An author cannot yet write a terminal grid, and nothing can tell them whether
the one they wrote is well formed. #717's later Stories build the terminal
authority, the concurrent pane lifecycle and the tmux provider on top of an
authored structure that has to exist and be checkable first — on every runtime,
including the ones that will never install a provider.

This Story owns that structure and nothing else.

What changes

<Terminal.Grid> and <Terminal> become reserved core structural syntax.

Before: both names were ordinary component names. <Terminal title="A" />
resolved a repository file or a registration, or failed as an unresolved
component; nothing knew what a grid was.

After: both are the language's own syntax. A registration cannot claim either
name and a repository file named after one never stands in for it. The grammar,
the placement rules and the derived row-major layout are decided from source,
shared by expansion and document validation, and reported by xmd syntax:

<Terminal.Grid columns={2}>
<Terminaltitle="Agent">…</Terminal>
<Terminaltitle="Shell" />
</Terminal.Grid>

The grid's closed props hold one required positive-integer columns; a pane's
hold one required non-empty title. Titles are display labels and may repeat —
a pane's structural identity is its ordinal among the grid's direct children.
Rows are derived in authored row-major order and the last row is left short.

Executing a valid grid refuses, because no terminal provider exists yet, and it
refuses before any pane body expands or a default shell starts.

How it works

scanner → terminalGridStructure (source rules) → columns and titles resolved
→ terminalGridLayout (row-major placement) → provider refusal

structural-rules.ts gains terminalGridStructure() beside the rules for every
other construct, so expansion and validation cannot disagree about what a grid's
source says: which panes it holds, which form each was written in, and what is
wrong with the way it was written. Only whitespace and direct <Terminal> panes
may appear in a grid; a control structure that would produce panes as it ran
cannot be one, because which panes exist is what the grid must know before it
opens anything.

terminal-grid.ts is where the source facts and the computed columns meet.
It places the panes and reports the rows they fill — provider-neutral data
naming no terminal, socket, process or window.

expandTerminalGrid() runs that order and then refuses. The refusal carries the
derived layout as its structured cause, the way <Session.Launch> carries its
failure class, so a test asserts on the grid that was derived rather than on the
wording of a sentence.

Review guide

Start with:packages/core/tests/terminal-grid-structure.test.ts

Then review:

  1. packages/core/src/structural.ts — the two declarations, which is what makes
    the names reserved and what xmd syntax prints.
  2. packages/core/src/structural-rules.tsterminalGridStructure() and the
    pane, column and title rules it reads from source.
  3. packages/core/src/terminal-grid.ts — the derived layout.
  4. packages/core/src/expand.tsexpandTerminalGrid(), the order it decides
    in, and the stray-<Terminal> branch.
  5. packages/core/src/document-validation.ts — the same rules, reported as
    diagnostics.

Look carefully at:

  • The order in expandTerminalGrid(). Source structure is decided first, then
    columns, then every pane's title, and only a complete grid reaches the
    refusal. Anything that moved provider contact earlier would let a partial grid
    escape.
  • misplacedTerminalViolations(). A <Terminal> deeper than a direct child, and
    a <Terminal.Grid> below another one, are found by walking rather than by a
    lexical flag, so a pane hidden inside an <If> inside a grid is still refused.

What must stay true

  • One rule catalog — enforced by expansion and validation both calling
    terminalGridStructure(), and checked by the grammar rows in
    terminal-grid-structure.test.ts and the matching invalid-form table in
    document-validation.test.ts.
  • Reserved means unshadowable — enforced by RESERVED_STRUCTURAL, and checked by
    the TG3 row in syntax-catalog.test.ts that puts components/Terminal.md and
    components/Terminal/Grid.md on disk and still finds both names structural,
    and refuses a registration of either.
  • Describing the language probes no terminal — enforced by the catalog reading
    declarations rather than a host, and checked by the TG3 row in
    syntax-cli.test.ts that traps API.Process.exec while building the catalog.
  • Nothing beneath a grid runs before a provider does — enforced by the order
    above, and checked by rows that trap component resolution, expression
    evaluation and code-block execution and assert all three stayed empty.

How to verify it

deno task test packages/core/tests/terminal-grid-structure.test.ts
deno task test packages/core/tests/syntax-catalog.test.ts
deno task test packages/core/tests/document-validation.test.ts
deno task test packages/cli/tests/syntax-cli.test.ts
  • TG1 proves the grammar accepts exactly a paired grid with a positive
    integer columns and one or more panes, and both pane forms with a non-empty
    title; it fails if an unknown prop, as, a self-closing grid, a
    non-integer or non-positive columns, or an absent or empty title were
    admitted — as a literal or as a computed value.
  • TG2 proves an empty grid, direct text, a non-pane element, a pane produced
    by control flow, a nested grid and a pane outside a grid are all refused, and
    that whitespace between panes is inert; it fails if any of them expanded, or
    if a refusal reported the wrong construct.
  • TG4 proves one through five panes under two and three columns produce the
    exact row-major positions, that duplicate titles stay valid, and that the
    ordinal rather than the title is identity; it fails if the layout balanced or
    padded the last row, or if two panes sharing a title collapsed.
  • The provider-non-observation assertion is not vacuous: the same recorders fire
    on a body that does expand — a <Boom /> to resolve, a seen() call to
    evaluate and a ```bash exec block to run were confirmed recorded outside a
    grid before the rows relying on their silence were trusted.
  • TG3 proves xmd syntax reports both entries with their exact forms and
    contracts, and that document validation returns the same diagnostics without
    reaching exec, fetch, a write or eval compilation; it fails if either name
    moved out of the structural category, or if any refused boundary fired.

Run under all three runtimes:

npx tsx --tsconfig tsconfig.node.json --test --test-concurrency=1 packages/core/tests/terminal-grid-structure.test.ts
bun test --timeout=60000 packages/core/tests/terminal-grid-structure.test.ts
npx tsx --tsconfig tsconfig.node.json --test --test-concurrency=1 packages/cli/tests/syntax-cli.test.ts
bun test --timeout=60000 packages/cli/tests/syntax-cli.test.ts

Scope

Included

  • The two reserved structural declarations and their catalog entries.
  • The grammar, placement rules and derived row-major layout.
  • Expansion's refusal on a host with no terminal-grid provider.
  • Document validation's diagnostics for every invalid authored form.

Intentionally unchanged

  • No terminal authority, provider API, pane claim or readiness latch.
  • No concurrent pane execution, pane scope isolation, or default-shell start.
  • No native Agent integration inside a pane, and no tmux anything.
  • No durability, retained layout record or replay admission.
  • architecture.md and specs/executable-mdx-spec.md describe the whole of
    Quest: Add interactive terminal grids to executable documents #717 and are unchanged here; §6.21 and Tier TG were settled by the
    architecture commit this branch starts from.

New abstractions

  • TerminalPane and TerminalGridStructure in structural-rules.ts exist
    because the grid's panes are read once and used by two consumers — expansion
    and document validation — exactly as SwitchCase/SwitchStructure are.

  • terminal-grid.ts (TerminalGridLayout, TerminalGridCell, PlacedPane,
    terminalGridLayout()) exists because placement needs both the source facts
    and the computed columns, which is a different question from what the source
    says. It is the value Quest: Add interactive terminal grids to executable documents #717's execution Story hands a provider.

  • resolveStructuralProp() in expand.ts exists because both columns and
    title are read the same way — literal or computed, with absence meaning
    absence — and duplicating that would let the two drift.

  • Each new abstraction has multiple concrete uses or a clear justification.

  • No speculative functionality is included.

Risks and limitations

  • Stack base: This PR is based on architecture PR 🏗️ Define interactive terminal grid architecture (#717) #734 at 736b909d.
    Its focused diff begins at 01bb083f, with the approved description
    refinement in 97be0632. The remaining Quest: Add interactive terminal grids to executable documents #717 Stories stack above this PR,
    and the complete feature is verified at the final stack head before any layer
    merges.
  • The new test file has no recorded weight, so the shard partition charges it the
    heaviest weight the current corpus records until Measure test weights runs
    on a runner. That is the documented behavior for a new file, not a defect.
  • A document that executes a valid grid fails today. That is this Story's
    contract — the execution Story replaces the refusal — but it does mean the
    syntax is writable and inspectable before it is runnable.

Scope confirmation

  • Every changed file supports the purpose described above.
  • Unrelated cleanup and formatting changes are excluded.
  • Generated or mechanical changes are clearly identified.
  • The description matches the final diff and test results.

`<Terminal.Grid>` and `<Terminal>` become reserved core structural syntax.
This Story owns the authored structure alone: the grammar, the placement
rules, and the row-major layout a grid derives. No terminal authority,
provider, pane execution, shell, durability or replay is built here.
The grid's closed props hold one required positive-integer `columns`; a
pane's hold one required non-empty `title`. Titles are display labels and
identify nothing — a pane's structural identity is its ordinal among the
grid's direct children, and rows are derived in authored row-major order
with the last row left short.
`structural-rules.ts` decides what the source says, so expansion and
document validation cannot disagree about it: only whitespace and direct
`<Terminal>` panes may appear in a grid, and an empty grid, direct text, a
non-pane element, a control structure that would produce panes, a nested
grid, and a pane written anywhere else are refused. `terminal-grid.ts`
places the panes once `columns` and each `title` are known.
A grid the grammar accepts runs until a terminal provider would be asked
for one. This build installs none, so it refuses there, before any pane
body expands or a default shell starts, and carries the layout it derived
beside the refusal.
Evidence rows TG1-TG4: the new structural suite owns TG1, TG2 and TG4; the
catalog, validation and `xmd syntax` suites own TG3.
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown

PR #733: ✨ Describe terminal grids as executable document structure (#729)

12 files, +2070 / -36

Scope

🔴 PR has 2106 lines changed. Split into focused PRs.

🟡 2106 lines changed. PRs under 400 receive more thorough review.

Structural

Oxlint structural signals:

  • no-unused-vars ×7: packages/core/src/expand.ts
  • no-unnecessary-type-assertion ×1: packages/core/src/expand.ts

Slop

  • packages/core/src/document-validation.ts:1094// below the grid that the grid does not lay out.
  • packages/core/src/document-validation.ts:1099// is left is a pane with no grid above it at all.

Oxlint slop signals:

  • no-inferrable-types ×2: packages/core/src/expand.ts

Static Analysis

Oxlint: 25 diagnostics across 2 files (11 rules)
Density: 0.012 violations/added-line

no-unused-vars (7): packages/core/src/expand.ts
no-base-to-string (4): packages/core/src/expand.ts
no-unsafe-type-assertion (3): packages/core/src/expand.ts
no-array-sort (2): packages/core/src/document-validation.ts
no-inferrable-types (2): packages/core/src/expand.ts
unbound-method (2): packages/core/src/expand.ts
no-shadow (1): packages/core/src/expand.ts
restrict-template-expressions (1): packages/core/src/expand.ts
consistent-return (1): packages/core/src/document-validation.ts
no-unnecessary-type-assertion (1): packages/core/src/expand.ts
no-implied-eval (1): packages/core/src/expand.ts

Correctness

FILE: packages/core/src/expand.ts, PATTERN: no-unused-vars, CONCERN: Unused variable insideTerminalGrid in context, QUESTION: Is insideTerminalGrid necessary or can it be removed?
FILE: packages/core/src/expand.ts, PATTERN: no-unused-vars, CONCERN: Unused variable strayTerminalMessage in error handling, QUESTION: Is strayTerminalMessage referenced elsewhere or can it be eliminated?
FILE: packages/core/src/expand.ts, PATTERN: no-unsafe-type-assertion, CONCERN: Type assertion in terminalGridLayout may hide missing props, QUESTION: Are type assertions justified or can they be replaced with safer checks?
FILE: packages/core/src/expand.ts, PATTERN: no-array-sort, CONCERN: misplacedTerminalViolations uses sort on a list of violations, QUESTION: Is sorting necessary, or does it introduce unintended side effects?
FILE: packages/core/src/expand.ts, PATTERN: signal cluster, CONCERN: Multiple Oxlint violations (no-unused-vars, no-unsafe-type-assertion, no-array-sort) in same file, QUESTION: Are these issues clustered due to unreviewed code or design debt?
FILE: packages/core/src/document-validation.ts, PATTERN: signal cluster, CONCERN: no-array-sort and consistent-return violations in same file, QUESTION: Are these violations isolated or indicative of broader issues?

Both descriptions lead with what the author can do and show the invocation
to copy. The placement rule, the row-major detail and the title's display
role are the catalog's structured fields and §6.21's to state, not a second
reference entry beside the forms.
The frozen catalog entries in `syntax-catalog.test.ts` mirror the two
declarations, so they move with them.

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found 2 redundant comments. Inline suggestions to remove them below.

case "Terminal.Grid":
// The whole layout is decided from source, so every pane's own mistake
// is reported where it was written — and so is a construct written
// below the grid that the grid does not lay out.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// below the grid that the grid does not lay out.

case "Terminal":
// A well-placed `<Terminal>` is its grid's, and one placed wrongly
// under a grid is already reported by that grid's own structure. What
// is left is a pane with no grid above it at all.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// is left is a pane with no grid above it at all.

Sign up for freeto 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.

Describe terminal grids as executable document structure

1 participant

@taras
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

✨ Describe terminal grids as executable document structure (#729) - #733

Open
taras wants to merge 2 commits into
architect/717-terminal-grid-contractfrom
agent/issue-729-terminal-grid
Open

✨ Describe terminal grids as executable document structure (#729)#733
taras wants to merge 2 commits into
architect/717-terminal-grid-contractfrom
agent/issue-729-terminal-grid

Conversation

@taras

@tarastaras commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Closes#729. First implementation Story under Quest #717.

Why

An author cannot yet write a terminal grid, and nothing can tell them whether
the one they wrote is well formed. #717's later Stories build the terminal
authority, the concurrent pane lifecycle and the tmux provider on top of an
authored structure that has to exist and be checkable first — on every runtime,
including the ones that will never install a provider.

This Story owns that structure and nothing else.

What changes

<Terminal.Grid> and <Terminal> become reserved core structural syntax.

Before: both names were ordinary component names. <Terminal title="A" />
resolved a repository file or a registration, or failed as an unresolved
component; nothing knew what a grid was.

After: both are the language's own syntax. A registration cannot claim either
name and a repository file named after one never stands in for it. The grammar,
the placement rules and the derived row-major layout are decided from source,
shared by expansion and document validation, and reported by xmd syntax:

<Terminal.Grid columns={2}>
<Terminaltitle="Agent">…</Terminal>
<Terminaltitle="Shell" />
</Terminal.Grid>

The grid's closed props hold one required positive-integer columns; a pane's
hold one required non-empty title. Titles are display labels and may repeat —
a pane's structural identity is its ordinal among the grid's direct children.
Rows are derived in authored row-major order and the last row is left short.

Executing a valid grid refuses, because no terminal provider exists yet, and it
refuses before any pane body expands or a default shell starts.

How it works

scanner → terminalGridStructure (source rules) → columns and titles resolved
→ terminalGridLayout (row-major placement) → provider refusal

structural-rules.ts gains terminalGridStructure() beside the rules for every
other construct, so expansion and validation cannot disagree about what a grid's
source says: which panes it holds, which form each was written in, and what is
wrong with the way it was written. Only whitespace and direct <Terminal> panes
may appear in a grid; a control structure that would produce panes as it ran
cannot be one, because which panes exist is what the grid must know before it
opens anything.

terminal-grid.ts is where the source facts and the computed columns meet.
It places the panes and reports the rows they fill — provider-neutral data
naming no terminal, socket, process or window.

expandTerminalGrid() runs that order and then refuses. The refusal carries the
derived layout as its structured cause, the way <Session.Launch> carries its
failure class, so a test asserts on the grid that was derived rather than on the
wording of a sentence.

Review guide

Start with:packages/core/tests/terminal-grid-structure.test.ts

Then review:

  1. packages/core/src/structural.ts — the two declarations, which is what makes
    the names reserved and what xmd syntax prints.
  2. packages/core/src/structural-rules.tsterminalGridStructure() and the
    pane, column and title rules it reads from source.
  3. packages/core/src/terminal-grid.ts — the derived layout.
  4. packages/core/src/expand.tsexpandTerminalGrid(), the order it decides
    in, and the stray-<Terminal> branch.
  5. packages/core/src/document-validation.ts — the same rules, reported as
    diagnostics.

Look carefully at:

  • The order in expandTerminalGrid(). Source structure is decided first, then
    columns, then every pane's title, and only a complete grid reaches the
    refusal. Anything that moved provider contact earlier would let a partial grid
    escape.
  • misplacedTerminalViolations(). A <Terminal> deeper than a direct child, and
    a <Terminal.Grid> below another one, are found by walking rather than by a
    lexical flag, so a pane hidden inside an <If> inside a grid is still refused.

What must stay true

  • One rule catalog — enforced by expansion and validation both calling
    terminalGridStructure(), and checked by the grammar rows in
    terminal-grid-structure.test.ts and the matching invalid-form table in
    document-validation.test.ts.
  • Reserved means unshadowable — enforced by RESERVED_STRUCTURAL, and checked by
    the TG3 row in syntax-catalog.test.ts that puts components/Terminal.md and
    components/Terminal/Grid.md on disk and still finds both names structural,
    and refuses a registration of either.
  • Describing the language probes no terminal — enforced by the catalog reading
    declarations rather than a host, and checked by the TG3 row in
    syntax-cli.test.ts that traps API.Process.exec while building the catalog.
  • Nothing beneath a grid runs before a provider does — enforced by the order
    above, and checked by rows that trap component resolution, expression
    evaluation and code-block execution and assert all three stayed empty.

How to verify it

deno task test packages/core/tests/terminal-grid-structure.test.ts
deno task test packages/core/tests/syntax-catalog.test.ts
deno task test packages/core/tests/document-validation.test.ts
deno task test packages/cli/tests/syntax-cli.test.ts
  • TG1 proves the grammar accepts exactly a paired grid with a positive
    integer columns and one or more panes, and both pane forms with a non-empty
    title; it fails if an unknown prop, as, a self-closing grid, a
    non-integer or non-positive columns, or an absent or empty title were
    admitted — as a literal or as a computed value.
  • TG2 proves an empty grid, direct text, a non-pane element, a pane produced
    by control flow, a nested grid and a pane outside a grid are all refused, and
    that whitespace between panes is inert; it fails if any of them expanded, or
    if a refusal reported the wrong construct.
  • TG4 proves one through five panes under two and three columns produce the
    exact row-major positions, that duplicate titles stay valid, and that the
    ordinal rather than the title is identity; it fails if the layout balanced or
    padded the last row, or if two panes sharing a title collapsed.
  • The provider-non-observation assertion is not vacuous: the same recorders fire
    on a body that does expand — a <Boom /> to resolve, a seen() call to
    evaluate and a ```bash exec block to run were confirmed recorded outside a
    grid before the rows relying on their silence were trusted.
  • TG3 proves xmd syntax reports both entries with their exact forms and
    contracts, and that document validation returns the same diagnostics without
    reaching exec, fetch, a write or eval compilation; it fails if either name
    moved out of the structural category, or if any refused boundary fired.

Run under all three runtimes:

npx tsx --tsconfig tsconfig.node.json --test --test-concurrency=1 packages/core/tests/terminal-grid-structure.test.ts
bun test --timeout=60000 packages/core/tests/terminal-grid-structure.test.ts
npx tsx --tsconfig tsconfig.node.json --test --test-concurrency=1 packages/cli/tests/syntax-cli.test.ts
bun test --timeout=60000 packages/cli/tests/syntax-cli.test.ts

Scope

Included

  • The two reserved structural declarations and their catalog entries.
  • The grammar, placement rules and derived row-major layout.
  • Expansion's refusal on a host with no terminal-grid provider.
  • Document validation's diagnostics for every invalid authored form.

Intentionally unchanged

  • No terminal authority, provider API, pane claim or readiness latch.
  • No concurrent pane execution, pane scope isolation, or default-shell start.
  • No native Agent integration inside a pane, and no tmux anything.
  • No durability, retained layout record or replay admission.
  • architecture.md and specs/executable-mdx-spec.md describe the whole of
    Quest: Add interactive terminal grids to executable documents #717 and are unchanged here; §6.21 and Tier TG were settled by the
    architecture commit this branch starts from.

New abstractions

  • TerminalPane and TerminalGridStructure in structural-rules.ts exist
    because the grid's panes are read once and used by two consumers — expansion
    and document validation — exactly as SwitchCase/SwitchStructure are.

  • terminal-grid.ts (TerminalGridLayout, TerminalGridCell, PlacedPane,
    terminalGridLayout()) exists because placement needs both the source facts
    and the computed columns, which is a different question from what the source
    says. It is the value Quest: Add interactive terminal grids to executable documents #717's execution Story hands a provider.

  • resolveStructuralProp() in expand.ts exists because both columns and
    title are read the same way — literal or computed, with absence meaning
    absence — and duplicating that would let the two drift.

  • Each new abstraction has multiple concrete uses or a clear justification.

  • No speculative functionality is included.

Risks and limitations

  • Stack base: This PR is based on architecture PR 🏗️ Define interactive terminal grid architecture (#717) #734 at 736b909d.
    Its focused diff begins at 01bb083f, with the approved description
    refinement in 97be0632. The remaining Quest: Add interactive terminal grids to executable documents #717 Stories stack above this PR,
    and the complete feature is verified at the final stack head before any layer
    merges.
  • The new test file has no recorded weight, so the shard partition charges it the
    heaviest weight the current corpus records until Measure test weights runs
    on a runner. That is the documented behavior for a new file, not a defect.
  • A document that executes a valid grid fails today. That is this Story's
    contract — the execution Story replaces the refusal — but it does mean the
    syntax is writable and inspectable before it is runnable.

Scope confirmation

  • Every changed file supports the purpose described above.
  • Unrelated cleanup and formatting changes are excluded.
  • Generated or mechanical changes are clearly identified.
  • The description matches the final diff and test results.

`<Terminal.Grid>` and `<Terminal>` become reserved core structural syntax.
This Story owns the authored structure alone: the grammar, the placement
rules, and the row-major layout a grid derives. No terminal authority,
provider, pane execution, shell, durability or replay is built here.
The grid's closed props hold one required positive-integer `columns`; a
pane's hold one required non-empty `title`. Titles are display labels and
identify nothing — a pane's structural identity is its ordinal among the
grid's direct children, and rows are derived in authored row-major order
with the last row left short.
`structural-rules.ts` decides what the source says, so expansion and
document validation cannot disagree about it: only whitespace and direct
`<Terminal>` panes may appear in a grid, and an empty grid, direct text, a
non-pane element, a control structure that would produce panes, a nested
grid, and a pane written anywhere else are refused. `terminal-grid.ts`
places the panes once `columns` and each `title` are known.
A grid the grammar accepts runs until a terminal provider would be asked
for one. This build installs none, so it refuses there, before any pane
body expands or a default shell starts, and carries the layout it derived
beside the refusal.
Evidence rows TG1-TG4: the new structural suite owns TG1, TG2 and TG4; the
catalog, validation and `xmd syntax` suites own TG3.
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown

PR #733: ✨ Describe terminal grids as executable document structure (#729)

12 files, +2070 / -36

Scope

🔴 PR has 2106 lines changed. Split into focused PRs.

🟡 2106 lines changed. PRs under 400 receive more thorough review.

Structural

Oxlint structural signals:

  • no-unused-vars ×7: packages/core/src/expand.ts
  • no-unnecessary-type-assertion ×1: packages/core/src/expand.ts

Slop

  • packages/core/src/document-validation.ts:1094// below the grid that the grid does not lay out.
  • packages/core/src/document-validation.ts:1099// is left is a pane with no grid above it at all.

Oxlint slop signals:

  • no-inferrable-types ×2: packages/core/src/expand.ts

Static Analysis

Oxlint: 25 diagnostics across 2 files (11 rules)
Density: 0.012 violations/added-line

no-unused-vars (7): packages/core/src/expand.ts
no-base-to-string (4): packages/core/src/expand.ts
no-unsafe-type-assertion (3): packages/core/src/expand.ts
no-array-sort (2): packages/core/src/document-validation.ts
no-inferrable-types (2): packages/core/src/expand.ts
unbound-method (2): packages/core/src/expand.ts
no-shadow (1): packages/core/src/expand.ts
restrict-template-expressions (1): packages/core/src/expand.ts
consistent-return (1): packages/core/src/document-validation.ts
no-unnecessary-type-assertion (1): packages/core/src/expand.ts
no-implied-eval (1): packages/core/src/expand.ts

Correctness

FILE: packages/core/src/expand.ts, PATTERN: no-unused-vars, CONCERN: Unused variable insideTerminalGrid in context, QUESTION: Is insideTerminalGrid necessary or can it be removed?
FILE: packages/core/src/expand.ts, PATTERN: no-unused-vars, CONCERN: Unused variable strayTerminalMessage in error handling, QUESTION: Is strayTerminalMessage referenced elsewhere or can it be eliminated?
FILE: packages/core/src/expand.ts, PATTERN: no-unsafe-type-assertion, CONCERN: Type assertion in terminalGridLayout may hide missing props, QUESTION: Are type assertions justified or can they be replaced with safer checks?
FILE: packages/core/src/expand.ts, PATTERN: no-array-sort, CONCERN: misplacedTerminalViolations uses sort on a list of violations, QUESTION: Is sorting necessary, or does it introduce unintended side effects?
FILE: packages/core/src/expand.ts, PATTERN: signal cluster, CONCERN: Multiple Oxlint violations (no-unused-vars, no-unsafe-type-assertion, no-array-sort) in same file, QUESTION: Are these issues clustered due to unreviewed code or design debt?
FILE: packages/core/src/document-validation.ts, PATTERN: signal cluster, CONCERN: no-array-sort and consistent-return violations in same file, QUESTION: Are these violations isolated or indicative of broader issues?

Both descriptions lead with what the author can do and show the invocation
to copy. The placement rule, the row-major detail and the title's display
role are the catalog's structured fields and §6.21's to state, not a second
reference entry beside the forms.
The frozen catalog entries in `syntax-catalog.test.ts` mirror the two
declarations, so they move with them.

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found 2 redundant comments. Inline suggestions to remove them below.

case "Terminal.Grid":
// The whole layout is decided from source, so every pane's own mistake
// is reported where it was written — and so is a construct written
// below the grid that the grid does not lay out.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// below the grid that the grid does not lay out.

case "Terminal":
// A well-placed `<Terminal>` is its grid's, and one placed wrongly
// under a grid is already reported by that grid's own structure. What
// is left is a pane with no grid above it at all.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// is left is a pane with no grid above it at all.

Sign up for freeto 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.

Describe terminal grids as executable document structure

1 participant

@taras
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

✨ Describe terminal grids as executable document structure (#729) - #733

Open
taras wants to merge 2 commits into
architect/717-terminal-grid-contractfrom
agent/issue-729-terminal-grid
Open

✨ Describe terminal grids as executable document structure (#729)#733
taras wants to merge 2 commits into
architect/717-terminal-grid-contractfrom
agent/issue-729-terminal-grid

Conversation

@taras

@tarastaras commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Closes#729. First implementation Story under Quest #717.

Why

An author cannot yet write a terminal grid, and nothing can tell them whether
the one they wrote is well formed. #717's later Stories build the terminal
authority, the concurrent pane lifecycle and the tmux provider on top of an
authored structure that has to exist and be checkable first — on every runtime,
including the ones that will never install a provider.

This Story owns that structure and nothing else.

What changes

<Terminal.Grid> and <Terminal> become reserved core structural syntax.

Before: both names were ordinary component names. <Terminal title="A" />
resolved a repository file or a registration, or failed as an unresolved
component; nothing knew what a grid was.

After: both are the language's own syntax. A registration cannot claim either
name and a repository file named after one never stands in for it. The grammar,
the placement rules and the derived row-major layout are decided from source,
shared by expansion and document validation, and reported by xmd syntax:

<Terminal.Grid columns={2}>
<Terminaltitle="Agent">…</Terminal>
<Terminaltitle="Shell" />
</Terminal.Grid>

The grid's closed props hold one required positive-integer columns; a pane's
hold one required non-empty title. Titles are display labels and may repeat —
a pane's structural identity is its ordinal among the grid's direct children.
Rows are derived in authored row-major order and the last row is left short.

Executing a valid grid refuses, because no terminal provider exists yet, and it
refuses before any pane body expands or a default shell starts.

How it works

scanner → terminalGridStructure (source rules) → columns and titles resolved
→ terminalGridLayout (row-major placement) → provider refusal

structural-rules.ts gains terminalGridStructure() beside the rules for every
other construct, so expansion and validation cannot disagree about what a grid's
source says: which panes it holds, which form each was written in, and what is
wrong with the way it was written. Only whitespace and direct <Terminal> panes
may appear in a grid; a control structure that would produce panes as it ran
cannot be one, because which panes exist is what the grid must know before it
opens anything.

terminal-grid.ts is where the source facts and the computed columns meet.
It places the panes and reports the rows they fill — provider-neutral data
naming no terminal, socket, process or window.

expandTerminalGrid() runs that order and then refuses. The refusal carries the
derived layout as its structured cause, the way <Session.Launch> carries its
failure class, so a test asserts on the grid that was derived rather than on the
wording of a sentence.

Review guide

Start with:packages/core/tests/terminal-grid-structure.test.ts

Then review:

  1. packages/core/src/structural.ts — the two declarations, which is what makes
    the names reserved and what xmd syntax prints.
  2. packages/core/src/structural-rules.tsterminalGridStructure() and the
    pane, column and title rules it reads from source.
  3. packages/core/src/terminal-grid.ts — the derived layout.
  4. packages/core/src/expand.tsexpandTerminalGrid(), the order it decides
    in, and the stray-<Terminal> branch.
  5. packages/core/src/document-validation.ts — the same rules, reported as
    diagnostics.

Look carefully at:

  • The order in expandTerminalGrid(). Source structure is decided first, then
    columns, then every pane's title, and only a complete grid reaches the
    refusal. Anything that moved provider contact earlier would let a partial grid
    escape.
  • misplacedTerminalViolations(). A <Terminal> deeper than a direct child, and
    a <Terminal.Grid> below another one, are found by walking rather than by a
    lexical flag, so a pane hidden inside an <If> inside a grid is still refused.

What must stay true

  • One rule catalog — enforced by expansion and validation both calling
    terminalGridStructure(), and checked by the grammar rows in
    terminal-grid-structure.test.ts and the matching invalid-form table in
    document-validation.test.ts.
  • Reserved means unshadowable — enforced by RESERVED_STRUCTURAL, and checked by
    the TG3 row in syntax-catalog.test.ts that puts components/Terminal.md and
    components/Terminal/Grid.md on disk and still finds both names structural,
    and refuses a registration of either.
  • Describing the language probes no terminal — enforced by the catalog reading
    declarations rather than a host, and checked by the TG3 row in
    syntax-cli.test.ts that traps API.Process.exec while building the catalog.
  • Nothing beneath a grid runs before a provider does — enforced by the order
    above, and checked by rows that trap component resolution, expression
    evaluation and code-block execution and assert all three stayed empty.

How to verify it

deno task test packages/core/tests/terminal-grid-structure.test.ts
deno task test packages/core/tests/syntax-catalog.test.ts
deno task test packages/core/tests/document-validation.test.ts
deno task test packages/cli/tests/syntax-cli.test.ts
  • TG1 proves the grammar accepts exactly a paired grid with a positive
    integer columns and one or more panes, and both pane forms with a non-empty
    title; it fails if an unknown prop, as, a self-closing grid, a
    non-integer or non-positive columns, or an absent or empty title were
    admitted — as a literal or as a computed value.
  • TG2 proves an empty grid, direct text, a non-pane element, a pane produced
    by control flow, a nested grid and a pane outside a grid are all refused, and
    that whitespace between panes is inert; it fails if any of them expanded, or
    if a refusal reported the wrong construct.
  • TG4 proves one through five panes under two and three columns produce the
    exact row-major positions, that duplicate titles stay valid, and that the
    ordinal rather than the title is identity; it fails if the layout balanced or
    padded the last row, or if two panes sharing a title collapsed.
  • The provider-non-observation assertion is not vacuous: the same recorders fire
    on a body that does expand — a <Boom /> to resolve, a seen() call to
    evaluate and a ```bash exec block to run were confirmed recorded outside a
    grid before the rows relying on their silence were trusted.
  • TG3 proves xmd syntax reports both entries with their exact forms and
    contracts, and that document validation returns the same diagnostics without
    reaching exec, fetch, a write or eval compilation; it fails if either name
    moved out of the structural category, or if any refused boundary fired.

Run under all three runtimes:

npx tsx --tsconfig tsconfig.node.json --test --test-concurrency=1 packages/core/tests/terminal-grid-structure.test.ts
bun test --timeout=60000 packages/core/tests/terminal-grid-structure.test.ts
npx tsx --tsconfig tsconfig.node.json --test --test-concurrency=1 packages/cli/tests/syntax-cli.test.ts
bun test --timeout=60000 packages/cli/tests/syntax-cli.test.ts

Scope

Included

  • The two reserved structural declarations and their catalog entries.
  • The grammar, placement rules and derived row-major layout.
  • Expansion's refusal on a host with no terminal-grid provider.
  • Document validation's diagnostics for every invalid authored form.

Intentionally unchanged

  • No terminal authority, provider API, pane claim or readiness latch.
  • No concurrent pane execution, pane scope isolation, or default-shell start.
  • No native Agent integration inside a pane, and no tmux anything.
  • No durability, retained layout record or replay admission.
  • architecture.md and specs/executable-mdx-spec.md describe the whole of
    Quest: Add interactive terminal grids to executable documents #717 and are unchanged here; §6.21 and Tier TG were settled by the
    architecture commit this branch starts from.

New abstractions

  • TerminalPane and TerminalGridStructure in structural-rules.ts exist
    because the grid's panes are read once and used by two consumers — expansion
    and document validation — exactly as SwitchCase/SwitchStructure are.

  • terminal-grid.ts (TerminalGridLayout, TerminalGridCell, PlacedPane,
    terminalGridLayout()) exists because placement needs both the source facts
    and the computed columns, which is a different question from what the source
    says. It is the value Quest: Add interactive terminal grids to executable documents #717's execution Story hands a provider.

  • resolveStructuralProp() in expand.ts exists because both columns and
    title are read the same way — literal or computed, with absence meaning
    absence — and duplicating that would let the two drift.

  • Each new abstraction has multiple concrete uses or a clear justification.

  • No speculative functionality is included.

Risks and limitations

  • Stack base: This PR is based on architecture PR 🏗️ Define interactive terminal grid architecture (#717) #734 at 736b909d.
    Its focused diff begins at 01bb083f, with the approved description
    refinement in 97be0632. The remaining Quest: Add interactive terminal grids to executable documents #717 Stories stack above this PR,
    and the complete feature is verified at the final stack head before any layer
    merges.
  • The new test file has no recorded weight, so the shard partition charges it the
    heaviest weight the current corpus records until Measure test weights runs
    on a runner. That is the documented behavior for a new file, not a defect.
  • A document that executes a valid grid fails today. That is this Story's
    contract — the execution Story replaces the refusal — but it does mean the
    syntax is writable and inspectable before it is runnable.

Scope confirmation

  • Every changed file supports the purpose described above.
  • Unrelated cleanup and formatting changes are excluded.
  • Generated or mechanical changes are clearly identified.
  • The description matches the final diff and test results.

`<Terminal.Grid>` and `<Terminal>` become reserved core structural syntax.
This Story owns the authored structure alone: the grammar, the placement
rules, and the row-major layout a grid derives. No terminal authority,
provider, pane execution, shell, durability or replay is built here.
The grid's closed props hold one required positive-integer `columns`; a
pane's hold one required non-empty `title`. Titles are display labels and
identify nothing — a pane's structural identity is its ordinal among the
grid's direct children, and rows are derived in authored row-major order
with the last row left short.
`structural-rules.ts` decides what the source says, so expansion and
document validation cannot disagree about it: only whitespace and direct
`<Terminal>` panes may appear in a grid, and an empty grid, direct text, a
non-pane element, a control structure that would produce panes, a nested
grid, and a pane written anywhere else are refused. `terminal-grid.ts`
places the panes once `columns` and each `title` are known.
A grid the grammar accepts runs until a terminal provider would be asked
for one. This build installs none, so it refuses there, before any pane
body expands or a default shell starts, and carries the layout it derived
beside the refusal.
Evidence rows TG1-TG4: the new structural suite owns TG1, TG2 and TG4; the
catalog, validation and `xmd syntax` suites own TG3.
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown

PR #733: ✨ Describe terminal grids as executable document structure (#729)

12 files, +2070 / -36

Scope

🔴 PR has 2106 lines changed. Split into focused PRs.

🟡 2106 lines changed. PRs under 400 receive more thorough review.

Structural

Oxlint structural signals:

  • no-unused-vars ×7: packages/core/src/expand.ts
  • no-unnecessary-type-assertion ×1: packages/core/src/expand.ts

Slop

  • packages/core/src/document-validation.ts:1094// below the grid that the grid does not lay out.
  • packages/core/src/document-validation.ts:1099// is left is a pane with no grid above it at all.

Oxlint slop signals:

  • no-inferrable-types ×2: packages/core/src/expand.ts

Static Analysis

Oxlint: 25 diagnostics across 2 files (11 rules)
Density: 0.012 violations/added-line

no-unused-vars (7): packages/core/src/expand.ts
no-base-to-string (4): packages/core/src/expand.ts
no-unsafe-type-assertion (3): packages/core/src/expand.ts
no-array-sort (2): packages/core/src/document-validation.ts
no-inferrable-types (2): packages/core/src/expand.ts
unbound-method (2): packages/core/src/expand.ts
no-shadow (1): packages/core/src/expand.ts
restrict-template-expressions (1): packages/core/src/expand.ts
consistent-return (1): packages/core/src/document-validation.ts
no-unnecessary-type-assertion (1): packages/core/src/expand.ts
no-implied-eval (1): packages/core/src/expand.ts

Correctness

FILE: packages/core/src/expand.ts, PATTERN: no-unused-vars, CONCERN: Unused variable insideTerminalGrid in context, QUESTION: Is insideTerminalGrid necessary or can it be removed?
FILE: packages/core/src/expand.ts, PATTERN: no-unused-vars, CONCERN: Unused variable strayTerminalMessage in error handling, QUESTION: Is strayTerminalMessage referenced elsewhere or can it be eliminated?
FILE: packages/core/src/expand.ts, PATTERN: no-unsafe-type-assertion, CONCERN: Type assertion in terminalGridLayout may hide missing props, QUESTION: Are type assertions justified or can they be replaced with safer checks?
FILE: packages/core/src/expand.ts, PATTERN: no-array-sort, CONCERN: misplacedTerminalViolations uses sort on a list of violations, QUESTION: Is sorting necessary, or does it introduce unintended side effects?
FILE: packages/core/src/expand.ts, PATTERN: signal cluster, CONCERN: Multiple Oxlint violations (no-unused-vars, no-unsafe-type-assertion, no-array-sort) in same file, QUESTION: Are these issues clustered due to unreviewed code or design debt?
FILE: packages/core/src/document-validation.ts, PATTERN: signal cluster, CONCERN: no-array-sort and consistent-return violations in same file, QUESTION: Are these violations isolated or indicative of broader issues?

Both descriptions lead with what the author can do and show the invocation
to copy. The placement rule, the row-major detail and the title's display
role are the catalog's structured fields and §6.21's to state, not a second
reference entry beside the forms.
The frozen catalog entries in `syntax-catalog.test.ts` mirror the two
declarations, so they move with them.

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found 2 redundant comments. Inline suggestions to remove them below.

case "Terminal.Grid":
// The whole layout is decided from source, so every pane's own mistake
// is reported where it was written — and so is a construct written
// below the grid that the grid does not lay out.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// below the grid that the grid does not lay out.

case "Terminal":
// A well-placed `<Terminal>` is its grid's, and one placed wrongly
// under a grid is already reported by that grid's own structure. What
// is left is a pane with no grid above it at all.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// is left is a pane with no grid above it at all.

Sign up for freeto 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.

Describe terminal grids as executable document structure

1 participant

@taras
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

✨ Describe terminal grids as executable document structure (#729) - #733

Open
taras wants to merge 2 commits into
architect/717-terminal-grid-contractfrom
agent/issue-729-terminal-grid
Open

✨ Describe terminal grids as executable document structure (#729)#733
taras wants to merge 2 commits into
architect/717-terminal-grid-contractfrom
agent/issue-729-terminal-grid

Conversation

@taras

@tarastaras commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Closes#729. First implementation Story under Quest #717.

Why

An author cannot yet write a terminal grid, and nothing can tell them whether
the one they wrote is well formed. #717's later Stories build the terminal
authority, the concurrent pane lifecycle and the tmux provider on top of an
authored structure that has to exist and be checkable first — on every runtime,
including the ones that will never install a provider.

This Story owns that structure and nothing else.

What changes

<Terminal.Grid> and <Terminal> become reserved core structural syntax.

Before: both names were ordinary component names. <Terminal title="A" />
resolved a repository file or a registration, or failed as an unresolved
component; nothing knew what a grid was.

After: both are the language's own syntax. A registration cannot claim either
name and a repository file named after one never stands in for it. The grammar,
the placement rules and the derived row-major layout are decided from source,
shared by expansion and document validation, and reported by xmd syntax:

<Terminal.Grid columns={2}>
<Terminaltitle="Agent">…</Terminal>
<Terminaltitle="Shell" />
</Terminal.Grid>

The grid's closed props hold one required positive-integer columns; a pane's
hold one required non-empty title. Titles are display labels and may repeat —
a pane's structural identity is its ordinal among the grid's direct children.
Rows are derived in authored row-major order and the last row is left short.

Executing a valid grid refuses, because no terminal provider exists yet, and it
refuses before any pane body expands or a default shell starts.

How it works

scanner → terminalGridStructure (source rules) → columns and titles resolved
→ terminalGridLayout (row-major placement) → provider refusal

structural-rules.ts gains terminalGridStructure() beside the rules for every
other construct, so expansion and validation cannot disagree about what a grid's
source says: which panes it holds, which form each was written in, and what is
wrong with the way it was written. Only whitespace and direct <Terminal> panes
may appear in a grid; a control structure that would produce panes as it ran
cannot be one, because which panes exist is what the grid must know before it
opens anything.

terminal-grid.ts is where the source facts and the computed columns meet.
It places the panes and reports the rows they fill — provider-neutral data
naming no terminal, socket, process or window.

expandTerminalGrid() runs that order and then refuses. The refusal carries the
derived layout as its structured cause, the way <Session.Launch> carries its
failure class, so a test asserts on the grid that was derived rather than on the
wording of a sentence.

Review guide

Start with:packages/core/tests/terminal-grid-structure.test.ts

Then review:

  1. packages/core/src/structural.ts — the two declarations, which is what makes
    the names reserved and what xmd syntax prints.
  2. packages/core/src/structural-rules.tsterminalGridStructure() and the
    pane, column and title rules it reads from source.
  3. packages/core/src/terminal-grid.ts — the derived layout.
  4. packages/core/src/expand.tsexpandTerminalGrid(), the order it decides
    in, and the stray-<Terminal> branch.
  5. packages/core/src/document-validation.ts — the same rules, reported as
    diagnostics.

Look carefully at:

  • The order in expandTerminalGrid(). Source structure is decided first, then
    columns, then every pane's title, and only a complete grid reaches the
    refusal. Anything that moved provider contact earlier would let a partial grid
    escape.
  • misplacedTerminalViolations(). A <Terminal> deeper than a direct child, and
    a <Terminal.Grid> below another one, are found by walking rather than by a
    lexical flag, so a pane hidden inside an <If> inside a grid is still refused.

What must stay true

  • One rule catalog — enforced by expansion and validation both calling
    terminalGridStructure(), and checked by the grammar rows in
    terminal-grid-structure.test.ts and the matching invalid-form table in
    document-validation.test.ts.
  • Reserved means unshadowable — enforced by RESERVED_STRUCTURAL, and checked by
    the TG3 row in syntax-catalog.test.ts that puts components/Terminal.md and
    components/Terminal/Grid.md on disk and still finds both names structural,
    and refuses a registration of either.
  • Describing the language probes no terminal — enforced by the catalog reading
    declarations rather than a host, and checked by the TG3 row in
    syntax-cli.test.ts that traps API.Process.exec while building the catalog.
  • Nothing beneath a grid runs before a provider does — enforced by the order
    above, and checked by rows that trap component resolution, expression
    evaluation and code-block execution and assert all three stayed empty.

How to verify it

deno task test packages/core/tests/terminal-grid-structure.test.ts
deno task test packages/core/tests/syntax-catalog.test.ts
deno task test packages/core/tests/document-validation.test.ts
deno task test packages/cli/tests/syntax-cli.test.ts
  • TG1 proves the grammar accepts exactly a paired grid with a positive
    integer columns and one or more panes, and both pane forms with a non-empty
    title; it fails if an unknown prop, as, a self-closing grid, a
    non-integer or non-positive columns, or an absent or empty title were
    admitted — as a literal or as a computed value.
  • TG2 proves an empty grid, direct text, a non-pane element, a pane produced
    by control flow, a nested grid and a pane outside a grid are all refused, and
    that whitespace between panes is inert; it fails if any of them expanded, or
    if a refusal reported the wrong construct.
  • TG4 proves one through five panes under two and three columns produce the
    exact row-major positions, that duplicate titles stay valid, and that the
    ordinal rather than the title is identity; it fails if the layout balanced or
    padded the last row, or if two panes sharing a title collapsed.
  • The provider-non-observation assertion is not vacuous: the same recorders fire
    on a body that does expand — a <Boom /> to resolve, a seen() call to
    evaluate and a ```bash exec block to run were confirmed recorded outside a
    grid before the rows relying on their silence were trusted.
  • TG3 proves xmd syntax reports both entries with their exact forms and
    contracts, and that document validation returns the same diagnostics without
    reaching exec, fetch, a write or eval compilation; it fails if either name
    moved out of the structural category, or if any refused boundary fired.

Run under all three runtimes:

npx tsx --tsconfig tsconfig.node.json --test --test-concurrency=1 packages/core/tests/terminal-grid-structure.test.ts
bun test --timeout=60000 packages/core/tests/terminal-grid-structure.test.ts
npx tsx --tsconfig tsconfig.node.json --test --test-concurrency=1 packages/cli/tests/syntax-cli.test.ts
bun test --timeout=60000 packages/cli/tests/syntax-cli.test.ts

Scope

Included

  • The two reserved structural declarations and their catalog entries.
  • The grammar, placement rules and derived row-major layout.
  • Expansion's refusal on a host with no terminal-grid provider.
  • Document validation's diagnostics for every invalid authored form.

Intentionally unchanged

  • No terminal authority, provider API, pane claim or readiness latch.
  • No concurrent pane execution, pane scope isolation, or default-shell start.
  • No native Agent integration inside a pane, and no tmux anything.
  • No durability, retained layout record or replay admission.
  • architecture.md and specs/executable-mdx-spec.md describe the whole of
    Quest: Add interactive terminal grids to executable documents #717 and are unchanged here; §6.21 and Tier TG were settled by the
    architecture commit this branch starts from.

New abstractions

  • TerminalPane and TerminalGridStructure in structural-rules.ts exist
    because the grid's panes are read once and used by two consumers — expansion
    and document validation — exactly as SwitchCase/SwitchStructure are.

  • terminal-grid.ts (TerminalGridLayout, TerminalGridCell, PlacedPane,
    terminalGridLayout()) exists because placement needs both the source facts
    and the computed columns, which is a different question from what the source
    says. It is the value Quest: Add interactive terminal grids to executable documents #717's execution Story hands a provider.

  • resolveStructuralProp() in expand.ts exists because both columns and
    title are read the same way — literal or computed, with absence meaning
    absence — and duplicating that would let the two drift.

  • Each new abstraction has multiple concrete uses or a clear justification.

  • No speculative functionality is included.

Risks and limitations

  • Stack base: This PR is based on architecture PR 🏗️ Define interactive terminal grid architecture (#717) #734 at 736b909d.
    Its focused diff begins at 01bb083f, with the approved description
    refinement in 97be0632. The remaining Quest: Add interactive terminal grids to executable documents #717 Stories stack above this PR,
    and the complete feature is verified at the final stack head before any layer
    merges.
  • The new test file has no recorded weight, so the shard partition charges it the
    heaviest weight the current corpus records until Measure test weights runs
    on a runner. That is the documented behavior for a new file, not a defect.
  • A document that executes a valid grid fails today. That is this Story's
    contract — the execution Story replaces the refusal — but it does mean the
    syntax is writable and inspectable before it is runnable.

Scope confirmation

  • Every changed file supports the purpose described above.
  • Unrelated cleanup and formatting changes are excluded.
  • Generated or mechanical changes are clearly identified.
  • The description matches the final diff and test results.

`<Terminal.Grid>` and `<Terminal>` become reserved core structural syntax.
This Story owns the authored structure alone: the grammar, the placement
rules, and the row-major layout a grid derives. No terminal authority,
provider, pane execution, shell, durability or replay is built here.
The grid's closed props hold one required positive-integer `columns`; a
pane's hold one required non-empty `title`. Titles are display labels and
identify nothing — a pane's structural identity is its ordinal among the
grid's direct children, and rows are derived in authored row-major order
with the last row left short.
`structural-rules.ts` decides what the source says, so expansion and
document validation cannot disagree about it: only whitespace and direct
`<Terminal>` panes may appear in a grid, and an empty grid, direct text, a
non-pane element, a control structure that would produce panes, a nested
grid, and a pane written anywhere else are refused. `terminal-grid.ts`
places the panes once `columns` and each `title` are known.
A grid the grammar accepts runs until a terminal provider would be asked
for one. This build installs none, so it refuses there, before any pane
body expands or a default shell starts, and carries the layout it derived
beside the refusal.
Evidence rows TG1-TG4: the new structural suite owns TG1, TG2 and TG4; the
catalog, validation and `xmd syntax` suites own TG3.
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown

PR #733: ✨ Describe terminal grids as executable document structure (#729)

12 files, +2070 / -36

Scope

🔴 PR has 2106 lines changed. Split into focused PRs.

🟡 2106 lines changed. PRs under 400 receive more thorough review.

Structural

Oxlint structural signals:

  • no-unused-vars ×7: packages/core/src/expand.ts
  • no-unnecessary-type-assertion ×1: packages/core/src/expand.ts

Slop

  • packages/core/src/document-validation.ts:1094// below the grid that the grid does not lay out.
  • packages/core/src/document-validation.ts:1099// is left is a pane with no grid above it at all.

Oxlint slop signals:

  • no-inferrable-types ×2: packages/core/src/expand.ts

Static Analysis

Oxlint: 25 diagnostics across 2 files (11 rules)
Density: 0.012 violations/added-line

no-unused-vars (7): packages/core/src/expand.ts
no-base-to-string (4): packages/core/src/expand.ts
no-unsafe-type-assertion (3): packages/core/src/expand.ts
no-array-sort (2): packages/core/src/document-validation.ts
no-inferrable-types (2): packages/core/src/expand.ts
unbound-method (2): packages/core/src/expand.ts
no-shadow (1): packages/core/src/expand.ts
restrict-template-expressions (1): packages/core/src/expand.ts
consistent-return (1): packages/core/src/document-validation.ts
no-unnecessary-type-assertion (1): packages/core/src/expand.ts
no-implied-eval (1): packages/core/src/expand.ts

Correctness

FILE: packages/core/src/expand.ts, PATTERN: no-unused-vars, CONCERN: Unused variable insideTerminalGrid in context, QUESTION: Is insideTerminalGrid necessary or can it be removed?
FILE: packages/core/src/expand.ts, PATTERN: no-unused-vars, CONCERN: Unused variable strayTerminalMessage in error handling, QUESTION: Is strayTerminalMessage referenced elsewhere or can it be eliminated?
FILE: packages/core/src/expand.ts, PATTERN: no-unsafe-type-assertion, CONCERN: Type assertion in terminalGridLayout may hide missing props, QUESTION: Are type assertions justified or can they be replaced with safer checks?
FILE: packages/core/src/expand.ts, PATTERN: no-array-sort, CONCERN: misplacedTerminalViolations uses sort on a list of violations, QUESTION: Is sorting necessary, or does it introduce unintended side effects?
FILE: packages/core/src/expand.ts, PATTERN: signal cluster, CONCERN: Multiple Oxlint violations (no-unused-vars, no-unsafe-type-assertion, no-array-sort) in same file, QUESTION: Are these issues clustered due to unreviewed code or design debt?
FILE: packages/core/src/document-validation.ts, PATTERN: signal cluster, CONCERN: no-array-sort and consistent-return violations in same file, QUESTION: Are these violations isolated or indicative of broader issues?

Both descriptions lead with what the author can do and show the invocation
to copy. The placement rule, the row-major detail and the title's display
role are the catalog's structured fields and §6.21's to state, not a second
reference entry beside the forms.
The frozen catalog entries in `syntax-catalog.test.ts` mirror the two
declarations, so they move with them.

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found 2 redundant comments. Inline suggestions to remove them below.

case "Terminal.Grid":
// The whole layout is decided from source, so every pane's own mistake
// is reported where it was written — and so is a construct written
// below the grid that the grid does not lay out.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// below the grid that the grid does not lay out.

case "Terminal":
// A well-placed `<Terminal>` is its grid's, and one placed wrongly
// under a grid is already reported by that grid's own structure. What
// is left is a pane with no grid above it at all.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// is left is a pane with no grid above it at all.

Sign up for freeto 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.

Describe terminal grids as executable document structure

1 participant

@taras
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

✨ Describe terminal grids as executable document structure (#729) - #733

Open
taras wants to merge 2 commits into
architect/717-terminal-grid-contractfrom
agent/issue-729-terminal-grid
Open

✨ Describe terminal grids as executable document structure (#729)#733
taras wants to merge 2 commits into
architect/717-terminal-grid-contractfrom
agent/issue-729-terminal-grid

Conversation

@taras

@tarastaras commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Closes#729. First implementation Story under Quest #717.

Why

An author cannot yet write a terminal grid, and nothing can tell them whether
the one they wrote is well formed. #717's later Stories build the terminal
authority, the concurrent pane lifecycle and the tmux provider on top of an
authored structure that has to exist and be checkable first — on every runtime,
including the ones that will never install a provider.

This Story owns that structure and nothing else.

What changes

<Terminal.Grid> and <Terminal> become reserved core structural syntax.

Before: both names were ordinary component names. <Terminal title="A" />
resolved a repository file or a registration, or failed as an unresolved
component; nothing knew what a grid was.

After: both are the language's own syntax. A registration cannot claim either
name and a repository file named after one never stands in for it. The grammar,
the placement rules and the derived row-major layout are decided from source,
shared by expansion and document validation, and reported by xmd syntax:

<Terminal.Grid columns={2}>
<Terminaltitle="Agent">…</Terminal>
<Terminaltitle="Shell" />
</Terminal.Grid>

The grid's closed props hold one required positive-integer columns; a pane's
hold one required non-empty title. Titles are display labels and may repeat —
a pane's structural identity is its ordinal among the grid's direct children.
Rows are derived in authored row-major order and the last row is left short.

Executing a valid grid refuses, because no terminal provider exists yet, and it
refuses before any pane body expands or a default shell starts.

How it works

scanner → terminalGridStructure (source rules) → columns and titles resolved
→ terminalGridLayout (row-major placement) → provider refusal

structural-rules.ts gains terminalGridStructure() beside the rules for every
other construct, so expansion and validation cannot disagree about what a grid's
source says: which panes it holds, which form each was written in, and what is
wrong with the way it was written. Only whitespace and direct <Terminal> panes
may appear in a grid; a control structure that would produce panes as it ran
cannot be one, because which panes exist is what the grid must know before it
opens anything.

terminal-grid.ts is where the source facts and the computed columns meet.
It places the panes and reports the rows they fill — provider-neutral data
naming no terminal, socket, process or window.

expandTerminalGrid() runs that order and then refuses. The refusal carries the
derived layout as its structured cause, the way <Session.Launch> carries its
failure class, so a test asserts on the grid that was derived rather than on the
wording of a sentence.

Review guide

Start with:packages/core/tests/terminal-grid-structure.test.ts

Then review:

  1. packages/core/src/structural.ts — the two declarations, which is what makes
    the names reserved and what xmd syntax prints.
  2. packages/core/src/structural-rules.tsterminalGridStructure() and the
    pane, column and title rules it reads from source.
  3. packages/core/src/terminal-grid.ts — the derived layout.
  4. packages/core/src/expand.tsexpandTerminalGrid(), the order it decides
    in, and the stray-<Terminal> branch.
  5. packages/core/src/document-validation.ts — the same rules, reported as
    diagnostics.

Look carefully at:

  • The order in expandTerminalGrid(). Source structure is decided first, then
    columns, then every pane's title, and only a complete grid reaches the
    refusal. Anything that moved provider contact earlier would let a partial grid
    escape.
  • misplacedTerminalViolations(). A <Terminal> deeper than a direct child, and
    a <Terminal.Grid> below another one, are found by walking rather than by a
    lexical flag, so a pane hidden inside an <If> inside a grid is still refused.

What must stay true

  • One rule catalog — enforced by expansion and validation both calling
    terminalGridStructure(), and checked by the grammar rows in
    terminal-grid-structure.test.ts and the matching invalid-form table in
    document-validation.test.ts.
  • Reserved means unshadowable — enforced by RESERVED_STRUCTURAL, and checked by
    the TG3 row in syntax-catalog.test.ts that puts components/Terminal.md and
    components/Terminal/Grid.md on disk and still finds both names structural,
    and refuses a registration of either.
  • Describing the language probes no terminal — enforced by the catalog reading
    declarations rather than a host, and checked by the TG3 row in
    syntax-cli.test.ts that traps API.Process.exec while building the catalog.
  • Nothing beneath a grid runs before a provider does — enforced by the order
    above, and checked by rows that trap component resolution, expression
    evaluation and code-block execution and assert all three stayed empty.

How to verify it

deno task test packages/core/tests/terminal-grid-structure.test.ts
deno task test packages/core/tests/syntax-catalog.test.ts
deno task test packages/core/tests/document-validation.test.ts
deno task test packages/cli/tests/syntax-cli.test.ts
  • TG1 proves the grammar accepts exactly a paired grid with a positive
    integer columns and one or more panes, and both pane forms with a non-empty
    title; it fails if an unknown prop, as, a self-closing grid, a
    non-integer or non-positive columns, or an absent or empty title were
    admitted — as a literal or as a computed value.
  • TG2 proves an empty grid, direct text, a non-pane element, a pane produced
    by control flow, a nested grid and a pane outside a grid are all refused, and
    that whitespace between panes is inert; it fails if any of them expanded, or
    if a refusal reported the wrong construct.
  • TG4 proves one through five panes under two and three columns produce the
    exact row-major positions, that duplicate titles stay valid, and that the
    ordinal rather than the title is identity; it fails if the layout balanced or
    padded the last row, or if two panes sharing a title collapsed.
  • The provider-non-observation assertion is not vacuous: the same recorders fire
    on a body that does expand — a <Boom /> to resolve, a seen() call to
    evaluate and a ```bash exec block to run were confirmed recorded outside a
    grid before the rows relying on their silence were trusted.
  • TG3 proves xmd syntax reports both entries with their exact forms and
    contracts, and that document validation returns the same diagnostics without
    reaching exec, fetch, a write or eval compilation; it fails if either name
    moved out of the structural category, or if any refused boundary fired.

Run under all three runtimes:

npx tsx --tsconfig tsconfig.node.json --test --test-concurrency=1 packages/core/tests/terminal-grid-structure.test.ts
bun test --timeout=60000 packages/core/tests/terminal-grid-structure.test.ts
npx tsx --tsconfig tsconfig.node.json --test --test-concurrency=1 packages/cli/tests/syntax-cli.test.ts
bun test --timeout=60000 packages/cli/tests/syntax-cli.test.ts

Scope

Included

  • The two reserved structural declarations and their catalog entries.
  • The grammar, placement rules and derived row-major layout.
  • Expansion's refusal on a host with no terminal-grid provider.
  • Document validation's diagnostics for every invalid authored form.

Intentionally unchanged

  • No terminal authority, provider API, pane claim or readiness latch.
  • No concurrent pane execution, pane scope isolation, or default-shell start.
  • No native Agent integration inside a pane, and no tmux anything.
  • No durability, retained layout record or replay admission.
  • architecture.md and specs/executable-mdx-spec.md describe the whole of
    Quest: Add interactive terminal grids to executable documents #717 and are unchanged here; §6.21 and Tier TG were settled by the
    architecture commit this branch starts from.

New abstractions

  • TerminalPane and TerminalGridStructure in structural-rules.ts exist
    because the grid's panes are read once and used by two consumers — expansion
    and document validation — exactly as SwitchCase/SwitchStructure are.

  • terminal-grid.ts (TerminalGridLayout, TerminalGridCell, PlacedPane,
    terminalGridLayout()) exists because placement needs both the source facts
    and the computed columns, which is a different question from what the source
    says. It is the value Quest: Add interactive terminal grids to executable documents #717's execution Story hands a provider.

  • resolveStructuralProp() in expand.ts exists because both columns and
    title are read the same way — literal or computed, with absence meaning
    absence — and duplicating that would let the two drift.

  • Each new abstraction has multiple concrete uses or a clear justification.

  • No speculative functionality is included.

Risks and limitations

  • Stack base: This PR is based on architecture PR 🏗️ Define interactive terminal grid architecture (#717) #734 at 736b909d.
    Its focused diff begins at 01bb083f, with the approved description
    refinement in 97be0632. The remaining Quest: Add interactive terminal grids to executable documents #717 Stories stack above this PR,
    and the complete feature is verified at the final stack head before any layer
    merges.
  • The new test file has no recorded weight, so the shard partition charges it the
    heaviest weight the current corpus records until Measure test weights runs
    on a runner. That is the documented behavior for a new file, not a defect.
  • A document that executes a valid grid fails today. That is this Story's
    contract — the execution Story replaces the refusal — but it does mean the
    syntax is writable and inspectable before it is runnable.

Scope confirmation

  • Every changed file supports the purpose described above.
  • Unrelated cleanup and formatting changes are excluded.
  • Generated or mechanical changes are clearly identified.
  • The description matches the final diff and test results.

`<Terminal.Grid>` and `<Terminal>` become reserved core structural syntax.
This Story owns the authored structure alone: the grammar, the placement
rules, and the row-major layout a grid derives. No terminal authority,
provider, pane execution, shell, durability or replay is built here.
The grid's closed props hold one required positive-integer `columns`; a
pane's hold one required non-empty `title`. Titles are display labels and
identify nothing — a pane's structural identity is its ordinal among the
grid's direct children, and rows are derived in authored row-major order
with the last row left short.
`structural-rules.ts` decides what the source says, so expansion and
document validation cannot disagree about it: only whitespace and direct
`<Terminal>` panes may appear in a grid, and an empty grid, direct text, a
non-pane element, a control structure that would produce panes, a nested
grid, and a pane written anywhere else are refused. `terminal-grid.ts`
places the panes once `columns` and each `title` are known.
A grid the grammar accepts runs until a terminal provider would be asked
for one. This build installs none, so it refuses there, before any pane
body expands or a default shell starts, and carries the layout it derived
beside the refusal.
Evidence rows TG1-TG4: the new structural suite owns TG1, TG2 and TG4; the
catalog, validation and `xmd syntax` suites own TG3.
@github-actions

github-actionsBot commented Sep 2, 2026

Copy link
Copy Markdown

PR #733: ✨ Describe terminal grids as executable document structure (#729)

12 files, +2070 / -36

Scope

🔴 PR has 2106 lines changed. Split into focused PRs.

🟡 2106 lines changed. PRs under 400 receive more thorough review.

Structural

Oxlint structural signals:

  • no-unused-vars ×7: packages/core/src/expand.ts
  • no-unnecessary-type-assertion ×1: packages/core/src/expand.ts

Slop

  • packages/core/src/document-validation.ts:1094// below the grid that the grid does not lay out.
  • packages/core/src/document-validation.ts:1099// is left is a pane with no grid above it at all.

Oxlint slop signals:

  • no-inferrable-types ×2: packages/core/src/expand.ts

Static Analysis

Oxlint: 25 diagnostics across 2 files (11 rules)
Density: 0.012 violations/added-line

no-unused-vars (7): packages/core/src/expand.ts
no-base-to-string (4): packages/core/src/expand.ts
no-unsafe-type-assertion (3): packages/core/src/expand.ts
no-array-sort (2): packages/core/src/document-validation.ts
no-inferrable-types (2): packages/core/src/expand.ts
unbound-method (2): packages/core/src/expand.ts
no-shadow (1): packages/core/src/expand.ts
restrict-template-expressions (1): packages/core/src/expand.ts
consistent-return (1): packages/core/src/document-validation.ts
no-unnecessary-type-assertion (1): packages/core/src/expand.ts
no-implied-eval (1): packages/core/src/expand.ts

Correctness

FILE: packages/core/src/expand.ts, PATTERN: no-unused-vars, CONCERN: Unused variable insideTerminalGrid in context, QUESTION: Is insideTerminalGrid necessary or can it be removed?
FILE: packages/core/src/expand.ts, PATTERN: no-unused-vars, CONCERN: Unused variable strayTerminalMessage in error handling, QUESTION: Is strayTerminalMessage referenced elsewhere or can it be eliminated?
FILE: packages/core/src/expand.ts, PATTERN: no-unsafe-type-assertion, CONCERN: Type assertion in terminalGridLayout may hide missing props, QUESTION: Are type assertions justified or can they be replaced with safer checks?
FILE: packages/core/src/expand.ts, PATTERN: no-array-sort, CONCERN: misplacedTerminalViolations uses sort on a list of violations, QUESTION: Is sorting necessary, or does it introduce unintended side effects?
FILE: packages/core/src/expand.ts, PATTERN: signal cluster, CONCERN: Multiple Oxlint violations (no-unused-vars, no-unsafe-type-assertion, no-array-sort) in same file, QUESTION: Are these issues clustered due to unreviewed code or design debt?
FILE: packages/core/src/document-validation.ts, PATTERN: signal cluster, CONCERN: no-array-sort and consistent-return violations in same file, QUESTION: Are these violations isolated or indicative of broader issues?

Both descriptions lead with what the author can do and show the invocation
to copy. The placement rule, the row-major detail and the title's display
role are the catalog's structured fields and §6.21's to state, not a second
reference entry beside the forms.
The frozen catalog entries in `syntax-catalog.test.ts` mirror the two
declarations, so they move with them.

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found 2 redundant comments. Inline suggestions to remove them below.

case "Terminal.Grid":
// The whole layout is decided from source, so every pane's own mistake
// is reported where it was written — and so is a construct written
// below the grid that the grid does not lay out.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// below the grid that the grid does not lay out.

case "Terminal":
// A well-placed `<Terminal>` is its grid's, and one placed wrongly
// under a grid is already reported by that grid's own structure. What
// is left is a pane with no grid above it at all.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant comment — restates what the code does.

Suggested change
// is left is a pane with no grid above it at all.

Sign up for freeto 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.

Describe terminal grids as executable document structure

1 participant

@taras