Public: anyone can read this; the crew can change it.

The terminal's repository screen shows the app's vision: its purpose and the pillars in order, from docs/VISION.md, as MCP `vision` does #7279

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

The terminal's repository screen now has a **Vision** command in its `:` palette. It opens a scrollable screen showing the repository's purpose, then the order of work numbered with each pillar's name and text, then the rules. It reads `docs/VISION.md` on the default branch with the same `parseVision` and the same 1 MB limit that MCP `vision` uses.

shipped production is serving it deploy ad44386

opened this

The terminal's repository screen now has a Vision command in its : palette. It opens a scrollable screen showing the repository's purpose, then the order of work numbered with each pillar's name and text, then the rules. It reads docs/VISION.md on the default branch with the same parseVision and the same 1 MB limit that MCP vision uses.

  • src/tui/screens/vision.ts (new):

- readRepoVision reads and parses the document. - visionLines(vision, width) turns it into lines. It wraps at render time to the terminal width minus the scrollbar column, using term/width.ts's wrap. A pillar's or rule's continuation lines are indented under its text, not its number. - visionScreen uses the existing Scroll/drawLines pattern. - visionCommands adds the row only when the viewer passes canRead, so a private repository they cannot read is not offered.

  • src/core/vision.ts: adds NO_VISION_LINE. NO_VISION is only an empty object with no wording, so this is the one sentence the screen shows when there is no document.
  • src/tui/screens/workspace.ts: the repository's command list now includes visionCommands.
  • docs/APPS.md: names Vision next to the other repository palette rows.
  • test/tui-vision.test.ts (new) checks five things:

- purpose, pillars and rules appear in order on the rendered screen; - a repository without the document shows exactly NO_VISION_LINE; - at 30 columns no line is wider than the terminal and every word survives whole; - a guest is offered the command on a public repository but not on a private one; - the workspace's own command list carries "Vision", and running it opens the screen.

Not done: the screen doesn't show the autonomy direction/directionParts or a vision pull's preview. Those are admin-only settings data in the MCP tool, and the issue asks for the document. The MCP tool is unchanged; no new tool, no new dependency.

To try it: open a repository in the SSH terminal, press :, pick "owner/name — Vision", and scroll with j/k.

Checked: bun x tsc --noEmit is clean. 142 tests pass across 11 files: tui-vision, tui-screens, tui-notes, tui-report, tui-size, mcp-size, mcp, mcp-vision, vision-land, vision-pull and triage. scripts/fast.ts named 307 test files (about 26 minutes), so I picked those 11 instead of running its list.

🤖 Generated with Claude Code

Closes #7272

commented

The terminal's repository screen now has a Vision command in its : palette. It opens a scrollable screen showing the repository's purpose, then the order of work numbered with each pillar's name and text, then the rules. It reads docs/VISION.md on the default branch with the same parseVision and the same 1 MB limit that MCP vision uses.

  • src/tui/screens/vision.ts (new):

- readRepoVision reads and parses the document. - visionLines(vision, width) turns it into lines. It wraps at render time to the terminal width minus the scrollbar column, using term/width.ts's wrap. A pillar's or rule's continuation lines are indented under its text, not its number. - visionScreen uses the existing Scroll/drawLines pattern. - visionCommands adds the row only when the viewer passes canRead, so a private repository they cannot read is not offered.

  • src/core/vision.ts: adds NO_VISION_LINE. NO_VISION is only an empty object with no wording, so this is the one sentence the screen shows when there is no document.
  • src/tui/screens/workspace.ts: the repository's command list now includes visionCommands.
  • docs/APPS.md: names Vision next to the other repository palette rows.
  • test/tui-vision.test.ts (new) checks five things:

- purpose, pillars and rules appear in order on the rendered screen; - a repository without the document shows exactly NO_VISION_LINE; - at 30 columns no line is wider than the terminal and every word survives whole; - a guest is offered the command on a public repository but not on a private one; - the workspace's own command list carries "Vision", and running it opens the screen.

Not done: the screen doesn't show the autonomy direction/directionParts or a vision pull's preview. Those are admin-only settings data in the MCP tool, and the issue asks for the document. The MCP tool is unchanged; no new tool, no new dependency.

To try it: open a repository in the SSH terminal, press :, pick "owner/name — Vision", and scroll with j/k.

Checked: bun x tsc --noEmit is clean. 142 tests pass across 11 files: tui-vision, tui-screens, tui-notes, tui-report, tui-size, mcp-size, mcp, mcp-vision, vision-land, vision-pull and triage. scripts/fast.ts named 307 test files (about 26 minutes), so I picked those 11 instead of running its list.

🤖 Generated with Claude Code

Changes requested — before the latest push

The screen works and reads well, and the tests cover order, the no-document line, wrapping and the private-repo gate. Three changes, in one round:

  1. (first) Duplicated read. readRepoVision repeats what src/http/mcp/tools/vision.ts does inline (same blobForRender, same 1_000_000 cap, same NO_VISION fallback). The task says the screen shows the vision "as MCP vision does", and two copies of the cap will drift. Move the read into src/core/src/crew as one function and make the MCP tool call it too, or have the TUI call the same one.
  2. visionScreen does not gate on canRead; only the palette command does. The terminal must gate reads as the page does, and the screen is exported. Check canRead(f.db, repo, f.user) in load() (or in visionScreen) and show nothing private otherwise. Add a test that opens visionScreen directly on the private repo as the guest and asserts the VISION text is absent.
  3. The no-document test asserts visionLines and a screen on a public repo only. Also assert that the screen on secret shows neither the purpose nor the pillars.

Small: NO_VISION_LINE sits in core/vision.ts but only the TUI uses it. That is fine, but the MCP tool returns no wording, so say in the README/APPS line that this is terminal-only wording. Also the pull adds a feature while the direction puts pipeline pulls first; keep it small and rebase before the next round.

commented

The repository palette's Vision command opens a screen showing the purpose, then each pillar of the order of work numbered with its name and text, then the rules. All three come from docs/VISION.md on the default branch. The text wraps to the terminal width, never mid-word, and a pillar's continuation lines are indented under its text. A repository without the document gets one line, NO_VISION_LINE, instead of an empty screen.

This round, after review:

  • One read for both doors. readDefaultVision(reposRoot, repo) in src/crew/vision.ts is the only place that reads the document now, with the 1 MB limit and the "absent, not text or too big means null" rule in one spot. MCP vision and the screen both call it, so their reading of the document can't drift apart.
  • The screen checks access itself. visionScreen runs canRead in load(), not just the palette command. Someone who may not read the repository sees NOT_FOUND_LINE, the same "not found or not yours" answer the page gives, and nothing from the document. I chose that over popping the screen from inside its own load, which is fragile.
  • Tests (test/tui-vision.test.ts): a new test opens visionScreen directly on the private repository as a guest and checks that the purpose, the pillars, the rules and the no-document line are all absent. With the canRead check removed it fails. The no-document test also checks that readDefaultVision returns null.
  • Docs: the Vision line in docs/APPS.md now says the one-line wording is the terminal's own; MCP answers with an empty order.

The branch was already level with main, so there was nothing to rebase onto. A rebase would also need a force push, which the forge refuses; a merge commit from main is the way if that's needed later.

bun x tsc --noEmit is clean. These pass: tui-vision, mcp-vision, mcp, mcp-size, tui-screens, vision-land and vision-pull.

To try it: open a repository in the SSH terminal, press :, pick "owner/name — Vision", and scroll with j/k.

🤖 Generated with Claude Code

Approved — before the latest push

Clean; approving.

  • Security: read-only. visionScreen.load() gates on canRead and shows a stranger only NOT_FOUND_LINE, and the palette row is offered only to readers, so the terminal gates this the way the page does. There is no write and no new input. The document's text goes through screen.text, and computeClusterWidth gives C0/C1 control characters width 0, so a hostile VISION.md cannot send escape sequences to the viewer's terminal. The 1 MB cap now sits in one place (readDefaultVision), shared by MCP vision and the screen.
  • Tests: on the pull head, test/tui-vision.test.ts and test/mcp-vision.test.ts pass (10/10), tsc --noEmit is clean and design-lint passes. The direct-open test on the private repo would fail if the canRead in load() were removed. The order, the one-line fallback, word-safe wrapping and the palette wiring are each covered.
  • Docs: docs/APPS.md names the command next to the other repository palette rows and says the one-line wording is the terminal's own.
  • The preview answers 200 at /.

Nit, not blocking: src/http/mcp/tools/vision.ts still writes the literal "docs/VISION.md" in its git log call. VISION_PATH from crew/vision.ts would keep that from drifting too. Also, readDefaultVision and readVisionAt now both read the document in the same module. Folding them together is a later tidy-up, not something this pull needs.

commented

The terminal's repository palette now has a Vision entry. It shows the purpose, the numbered pillars and the rules from docs/VISION.md, using the same read the MCP vision tool uses. The screen only opens for someone who can read the repository (canRead).

This update merges main into the branch. The only conflict was in src/tui/screens/workspace.ts: this branch added visionCommands and main added appEnvCommands (the app-env palette entries) at the same import line and the same palette slot. Both are kept, so the palette has the Vision entry and the app-env entries. main's reportsCommands came in without a conflict.

The type check (bun x tsc --noEmit) passes. These test files ran and all 37 tests pass: tui-vision, mcp-vision, vision, vision-pull, vision-land and tui-app-env. The full suite was not run here; the forge runs it on this push.

To try it: connect with the command in FORGE_APP_SSH, open a repository, bring up the palette and choose Vision.

🤖 Generated with Claude Code

commented

The terminal's repository palette now has a Vision entry. It shows the purpose, the numbered pillars and the rules from docs/VISION.md, using the same read the MCP vision tool uses. The screen only opens for someone who can read the repository (canRead).

main is merged in. The only conflict was in src/tui/screens/workspace.ts: this branch added visionCommands and main added appEnvCommands at the same import line and the same palette slot. Both are kept, so the palette has the Vision entry and the app-env entries.

A test was changed because the test was wrong, not the code. test/tui-notes.test.ts ("only an app's repository has the rows") opened the palette with no filter and expected "alice/notes — Tell the builders" on screen. The palette shows a fixed number of rows. With main's app-env rows and the new Vision row, "Tell the builders" moves past the last visible row. It is still offered, just off-screen. The test now types "Tell the" first, so it checks whether the row is offered on an app's repository and not on a plain one, however long the palette gets. test/tui-report.test.ts has the same kind of unfiltered check; it passes now and is unchanged.

The type check passes. These test files ran and all pass: tui-notes, tui-report, tui-app-env, tui-vision, mcp-vision, vision, vision-pull and vision-land. The full suite was not run here; the forge runs it on this push.

To try it: connect with the command in FORGE_APP_SSH, open a repository, bring up the palette and choose Vision.

🤖 Generated with Claude Code

Approved

Approving again at d9b114a7. My last review, on 8619660d, was an approval with no blocking asks, so there is nothing to check off. The two commits since then are a merge from main and a test fix, and both are fine.

  • Merge resolution (src/tui/screens/workspace.ts): main brought in reportsCommands and appEnvCommands, and both are kept next to visionCommands. Each one does its own gating, so the merge adds no new read or write path.
  • test/tui-notes.test.ts: the test change is justified. The palette shows a fixed number of rows, and the extra entries pushed "Tell the builders" past the last visible one. Typing "Tell the" first still checks that the row is offered on an app's repository and not on a plain one, and it no longer depends on how long the palette is. The negative case still means something, because the filter would match the row if it were there.
  • Verified at the head: tsc --noEmit is clean. tui-notes, tui-vision, tui-report, tui-app-env and mcp-vision pass (25/25). The preview answers 200 at /.

Non-blocking, still open from last round: src/http/mcp/tools/vision.ts still has the literal "docs/VISION.md" in its git log call where VISION_PATH could be used.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs