Skip to content

feat(documents): add code to a project as its own kind of document - #3004

Draft
camielvs wants to merge 1 commit into
cvs/editable-documentsfrom
cvs/code-documents
Draft

camielvs wants to merge 1 commit into
cvs/editable-documentsfrom
cvs/code-documents

Conversation

@camielvs

@camielvs camielvs commented Nov 5, 2026 •

Copy link
Copy Markdown
Collaborator

Stacked on #3003 (editable documents), which this branch is based on. Review only the top commit.

Intent

Let people keep code alongside a project's other documents: add it from the same Add menus, and read and edit it in the same editor, highlighted as code.

Current behavior

Everything added through Add a document is a document with a title. A .py file can be pasted in, but nothing marks the row as code, so it is listed and badged like prose.

What changes

A new Add code entry sits next to Add a document in the Add menu of Tangent's Resources window, and a Code entry next to Document in the project page's Add menu. Both open the same form (drop a file, browse, or type), but ask for a Filename (for example train.py) instead of a Title, and highlight the content by that filename's extension.

To the API the row is still a document (entity: "document"); it is marked metadata: { type: "code" } where a document has { type: "document" }, so there is no backend change. This is the same way local_pipeline and instructions rows are already told apart.

Once added, code:

languageFor now knows the common source-file extensions Monaco ships highlighters for (Ruby, Go, Rust, Java, C/C++, R, Julia, HTML/CSS, Dockerfile, .ipynb as JSON, and so on), which also improves highlighting of existing documents with those names.

Analytics: code reuses the existing projects.add_document_*, projects.save_document and projects.discard_document_edits events, which now carry kind: "document" or kind: "code".

How to test

  1. Open a project in Tangent. In the Resources window, open the Add menu (the chevron next to Add a pipeline). It should list Add a pipeline, Add pipeline run, Add a document and Add code.
  2. Choose Add code. The dialog should be titled Add code, with the first field labelled Filename and the placeholder train.py.
  3. Type train.py as the filename and a line of Python as the content. The content should highlight as Python. Click Add.
  4. The new row should appear in the Resources window with a code-file icon and the label Code. Click it: it should open as a tab in the right-hand panel, in the editor, highlighted as Python, with a code-file icon in the editor's header.
  5. Edit and press ⌘S / Ctrl+S. Unsaved changes should clear. Reload the page and reopen it: the new text should be there.
  6. Choose Add a document from the same menu. The dialog should still be titled Add a document with a Title field, and the new row should be labelled Document.
  7. On the project page (not Tangent), open Add under Resources. It should list Document, Code and Pipeline. Code should open a dialog titled Add Code with a Filename field. After adding, a Code added toast should show, the row should carry a Code badge, and selecting it should show it in the preview editor.
  8. Drop a .rb or .go file onto either dialog. The filename should fill in and the content should highlight in that language.

Automated: tests cover the form's two kinds, both Add menus, the Resources window opening code in a document tab, the kind on the editor's Save event, documentKindOf and documentResourceInput, and languageFor. The full vitest suite (488 files), tsc and knip pass, and eslint and prettier pass on the touched files. The UI steps have not been walked through in a browser.

Related Issue and Pull requests

Stacked on #3003, which is based on master now that #2978 is merged.

Follow-up, not in this PR: teach the agent tooling in tangent-shell / tangent-shell-shopify that a document with type: "code" is code, so agents find, read and update it through the project resources API in oasis-backend like any other document. The API itself needs no change, because a resource's data takes any JSON object.

Type of Change

  • New feature

Line Breakdown

Category Added Removed
Production code 176 39
Comments 2 2
Tests 217 8
Total 395 49

Checklist

  • I have tested this does not break current pipelines / runs functionality
  • I have tested the changes on staging

Additional Comments

  • code is a descriptor type, not a new API entity: a new ProjectResourceEntity member would mean a backend change and regenerated types, and nothing here needs one.
  • Code opens in the ordinary document tab rather than a tab type of its own, so the tab strip shows the document icon; the Resources window and the editor's header show the code icon.
  • Running code, or copying it into an agent's session, is out of scope.

@camielvs
camielvs requested a review from a team as a code owner November 5, 2026 19:03
@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

🎩 Preview

A preview build has been created at: cvs/code-documents/9bfed76

@camielvs
camielvs marked this pull request as draft November 5, 2026 23:38
@camielvs
camielvs force-pushed the cvs/editable-documents branch from 37f1855 to 2ea79b1 Compare November 6, 2026 00:11
@camielvs camielvs changed the title feat(documents): add code files to a project as their own kind of document feat(documents): add code to a project as its own kind of document Nov 6, 2026
Code is now added as its own kind of document: a document row with
`metadata: { type: "code" }`, so no API change. Both Add menus (Tangent's
Resources window and the project page) offer "Add code" next to "Add a
document"; the same form asks for a filename instead of a title, and the
editor highlights the code by that name.

Code is listed with a FileCode icon and a "Code" label, and opens in the
same document tab and editor a document uses. `languageFor` now knows the
common source-file extensions Monaco ships highlighters for.

The form, both dialogs and both menus share one `DocumentKind` from
resourceDescriptor, and `documentResourceInput` takes it in place of a
separate code builder. Analytics keep the existing `add_document_*`,
`save_document` and `discard_document_edits` events and tell the two
apart with a `kind` field.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@camielvs
camielvs force-pushed the cvs/editable-documents branch from 2ea79b1 to 17c99f6 Compare November 6, 2026 20:31

@camielvs camielvs left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🤖 This is an AI-generated code review comment.

2 findings, inline below (both Low). Across the stack: if the ⌘S analytics gap on #3003 gets a projects.save_document_completed event, that event should carry kind like the others in this PR.

namePlaceholder: "model-card.md",
contentPlaceholder: "What this document records",
},
code: {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🤖 This is an AI-generated code review comment.

In code mode, the drop hint and file error still talk about a title and a document. KIND_COPY changes the label to Filename. But the drop hint in DocumentFileDropZone.tsx:45 still says "Drop to fill in the title and content", and a non-text file is rejected with "Only text can be added as a document." (documentFile.ts:12). Consider adding a dropHint here, passed through to DocumentFileDropZone, and a read error that doesn't depend on the kind (e.g. "Only text files can be added.").

xml: "xml",
graphql: "graphql",
proto: "protobuf",
dockerfile: "dockerfile",

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🤖 This is an AI-generated code review comment.

Dockerfile only works because a name without a dot is treated as its own extension. When there is no dot, name.split(".").pop() returns the whole name. That is how Dockerfile resolves, and the new test locks it in. But with the new short keys, one-word document titles now get highlighted as code ("Go", "R", "C", "Swift"). Meanwhile the common Dockerfile.dev and Dockerfile.prod fall back to plain text. Suggestion: first look up the basename in a small filename table (dockerfile, dockerfile.*), and use the extension table only when the name contains a dot.

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant