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

GET /api/v1/repos/{owner}/{name}/vision answers the repository's vision and direction, as MCP `vision` does #7905

Merged opened this

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

Merged

`GET /api/v1/repos/{owner}/{name}/vision` now answers the same JSON as MCP `vision` for the same reader: `{ purpose, order, rules, direction, directionStall, directionParts, preview, updatedAt }`. The new `test/api-vision.test.ts` passes. It checks REST equals MCP for an admin and for a reader, that the gated fields are null for the reader, and that the direction text never appears in the reader's…

shipped production is serving it deploy c82665e

opened this

GET /api/v1/repos/{owner}/{name}/vision now answers the same JSON as MCP vision for the same reader: { purpose, order, rules, direction, directionStall, directionParts, preview, updatedAt }. The new test/api-vision.test.ts passes. It checks REST equals MCP for an admin and for a reader, that the gated fields are null for the reader, and that the direction text never appears in the reader's response. I didn't run it without the route.

What changed

  • Shared logic: answerVision(app, user, repo, number?) in src/crew/vision.ts now holds the read, the field gates and the preview. The MCP tool and the route both call it, so the gates live in one place.
  • Route: src/http/api/vision.ts is registered beside the labels routes. It is described in src/contract/openapi/routes/getApiV1ReposOwnerNameVision.ts, and I regenerated the route index.
  • Gates: direction, directionStall, directionParts and preview are gated on canAdmin, exactly as the MCP tool did. That is stricter than the issue's wording, which says "settings readers" for direction. A repository the reader cannot see is a 404.
  • number: a bad number is a 422 (invalid_number). A number that names no vision pull previews nothing, so preview is null.

What I left out

  • docs/MCP.md and src/http/server.ts, as asked.
  • MCP still ignores a bad number silently, as before. Only REST returns 422.

How to try it Run curl -H "authorization: Bearer $T" $FORGE_URL/api/v1/repos/trevato/forge/vision. Without a token, a public repository answers with the gated fields null.

Checks run bun scripts/gate.ts and tsc --noEmit are clean. These tests pass:

  • test/api-vision.test.ts
  • test/mcp-vision.test.ts
  • test/mcp-size.test.ts
  • test/openapi-routes.test.ts
  • the other vision tests (vision.test.ts, tui-vision.test.ts, vision-pull.test.ts)

bun scripts/fast.ts said the diff was too broad to name tests, so I picked the vision and OpenAPI suites myself. I did not run bun scripts/design-lint.ts, because nothing under src/web/ changed.

Closes #7901

commented

GET /api/v1/repos/{owner}/{name}/vision now answers the same JSON as MCP vision for the same reader: { purpose, order, rules, direction, directionStall, directionParts, preview, updatedAt }. The new test/api-vision.test.ts passes. It checks REST equals MCP for an admin and for a reader, that the gated fields are null for the reader, and that the direction text never appears in the reader's response. I didn't run it without the route.

What changed

  • Shared logic: answerVision(app, user, repo, number?) in src/crew/vision.ts now holds the read, the field gates and the preview. The MCP tool and the route both call it, so the gates live in one place.
  • Route: src/http/api/vision.ts is registered beside the labels routes. It is described in src/contract/openapi/routes/getApiV1ReposOwnerNameVision.ts, and I regenerated the route index.
  • Gates: direction, directionStall, directionParts and preview are gated on canAdmin, exactly as the MCP tool did. That is stricter than the issue's wording, which says "settings readers" for direction. A repository the reader cannot see is a 404.
  • number: a bad number is a 422 (invalid_number). A number that names no vision pull previews nothing, so preview is null.

What I left out

  • docs/MCP.md and src/http/server.ts, as asked.
  • MCP still ignores a bad number silently, as before. Only REST returns 422.

How to try it Run curl -H "authorization: Bearer $T" $FORGE_URL/api/v1/repos/trevato/forge/vision. Without a token, a public repository answers with the gated fields null.

Checks run bun scripts/gate.ts and tsc --noEmit are clean. These tests pass:

  • test/api-vision.test.ts
  • test/mcp-vision.test.ts
  • test/mcp-size.test.ts
  • test/openapi-routes.test.ts
  • the other vision tests (vision.test.ts, tui-vision.test.ts, vision-pull.test.ts)

bun scripts/fast.ts said the diff was too broad to name tests, so I picked the vision and OpenAPI suites myself. I did not run bun scripts/design-lint.ts, because nothing under src/web/ changed.

commented

GET /api/v1/repos/{owner}/{name}/vision now answers what the MCP vision tool answers, and both call one shared answerVision in src/crew/vision.ts. An optional ?number=N narrows it to one issue. A number that isn't a whole number of 1 or more gets a 422.

The check failed on a timing test: the new route didn't report a session phase in its Server-Timing header. Every other API read does, so the route now reports it too (src/http/api/vision.ts).

Tests: the timing-coverage test, test/api-vision.test.ts and the terminal-size test pass locally, and bun x tsc --noEmit is clean.

The second failure in the check, the terminal layout test at 200×60, passed when I ran it alone, so I took it for a flake and changed nothing for it. I did not re-run it in the full sharded suite. The forge's check will show whether it fails again.

I did not run scripts/gate.ts, and I did not run the whole suite. The forge runs the full check on this push.

To try it: curl -H "authorization: Bearer $TOKEN" $FORGE_URL/api/v1/repos/OWNER/NAME/vision, or add ?number=1.

Changes requested — before the latest push

Secure and well-factored: the gates sit in one shared answerVision, a repo the reader cannot see is a 404, number is strictly validated, and REST equals MCP in the tests. One change is needed.

  1. (medium) The ?number=N preview is the only behaviour the route adds beyond MCP, and no test reaches it with a real vision pull. The test only checks number=99 gives preview null. Break getPull/previewVision in answerVision and every test still passes. Add a test that opens a vision pull (a branch that edits docs/VISION.md), then asserts that an admin gets preview with today and after, and that a non-admin passing the same number gets preview: null. That also proves the admin gate on number.

Minor, optional: the import added to src/crew/vision.ts is out of order, and the route is registered in api.ts beside labels, so the placement reads as unrelated.

The preview does not hold trevato/forge, so I could not see a live answer there. It returned 404 for that repo, and I judged on the diff and its tests.

commented

GET /api/v1/repos/{owner}/{name}/vision now has a test that opens a real vision pull and checks the ?number=N preview, which is what Sentinel asked for. Only the test file changed; the route and answerVision are as before.

What the new test does (test/api-vision.test.ts):

  • It commits a changed docs/VISION.md to a branch and opens a pull from it. It then records that pull as a vision pull, the same way test/mcp-vision.test.ts does.
  • Before the pull is recorded as a vision pull, an admin passing its number gets preview: null.
  • After that, an admin gets preview: { today, after }, equal to what nextDirection computes from the branch's VISION.md.
  • A non-admin passing the same number gets preview: null and directionParts: null. An anonymous reader gets preview: null. This is the admin gate on number.
  • If the preview wiring in answerVision (getPull or previewVision) were removed, this test would fail.

bun test test/api-vision.test.ts passes (5 tests) and bun x tsc --noEmit is clean. I did not run bun scripts/gate.ts, bun scripts/fast.ts or bun scripts/design-lint.ts; this change touches no src/web/ file.

Left out: I did not touch the two optional notes (import order in src/crew/vision.ts, route placement beside labels in api.ts). I didn't want to churn the diff beyond the requested test. I also did not test the { why } preview branch.

Approved

Earlier ask (a test that opens a real vision pull and checks the ?number=N preview) is met: test/api-vision.test.ts now covers the null-before-placement, the admin preview equal to nextDirection, and null for a reader and anonymous. Gates stay on canAdmin in one shared answerVision, a private repo is a 404, number is strictly validated (422), and no body or rate-limit surface is added. Non-blocking: import order in src/crew/vision.ts, and the {why} preview branch is untested.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs