Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
const { defineConfig } = require("@vscode/test-cli");

module.exports = defineConfig({
files: "out/test/**/*.test.js",
files: "out/test/**/*.test.cjs",
version: "1.121.0",
workspaceFolder: "./src/test/fixtures",
mocha: {
timeout: 10000,
},
timeout: 10000
}
});
5 changes: 4 additions & 1 deletion integrations/vscode/.vscodeignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@ tsconfig.json
*.map
node_modules/
tsup.config.ts
*.patch
*.patch
.vscode-test.cjs
tsconfig.test.json
tsdown.config.ts
27 changes: 27 additions & 0 deletions integrations/vscode/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,33 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

---

## [1.0.25]

### Added

- **`.tenure.json` configuration format** (`tenureConfig.ts`): Introduced a new JSON-based project configuration file supporting `projectId`, `ignore`, and `noiseIgnores` fields alongside the legacy plain-text `.tenure` file. The JSON format is preferred when both files exist, with automatic fallback to `.tenure`.
- **`generateDefaultTenureConfig()`** (`tenureConfig.ts`): Added a utility function that produces a pretty-printed `.tenure.json` template with empty `ignore` and `noiseIgnores` arrays, used when prompting users to create a new config file.
- **File policy module** (`filePolicy.ts`): Added `getTenureFilePolicy()` and `getTenureFilePolicyForPath()` to support per-file metadata and content suppression rules, preventing sensitive files from leaking active file paths, language IDs, edit events, or content to the Tenure proxy.
- **`.tenure.json` file watcher** (`extension.ts`): Added a dedicated filesystem watcher for `.tenure.json` changes that invalidates the sync cache and triggers a re-sync, alongside the existing `.tenure` watcher.

### Changed

- **Version and display name** (`package.json`, `package-lock.json`): Bumped extension version to `1.0.25`, updated the display name to "Tenure", added `language-models` to keywords, set `"type": "module"`, and added `bugs` and `homepage` fields.
- **Build configuration** (`package.json`, `tsdown.config.ts`): Replaced the separate `build:test` npm script with a unified tsdown config that handles both extension and test builds. The test command now references `.vscode-test.cjs` instead of the removed `.vscode-test.js`.
- **Onboarding prompt wording** (`workspaceSync.ts`): Updated the missing config file prompt to reference `.tenure.json` instead of `.tenure`, now creating a JSON document with `generateDefaultTenureConfig()` rather than a plain-text file.
- **File metadata suppression in workspace sync** (`workspaceSync.ts`): Integrated file policy checks into `buildWorkspaceState()` and `sendActiveFileUpdate()` so that files matching suppression rules omit their path and language from workspace state payloads.
- **File metadata suppression in beliefs provider** (`beliefsViewProvider.ts`): Added file policy checks to `sendFileMeta()`, `sendFileEdited()`, and the belief record submission flow, suppressing metadata and content for files covered by suppression rules.
- **Active editor change handling** (`extension.ts`): Updated the `onDidChangeActiveTextEditor` handler to respect file policy suppression, skipping active file propagation for suppressed files.
- **README update** (`README.md`): Revised the project description, feature descriptions, and drift explanation to emphasize Tenure as a governed context layer rather than just persistent memory.

### Removed

- **`.vscode-test.js`** (`integrations/vscode/.vscode-test.js`): Deleted the legacy test runner configuration file, replaced by `.vscode-test.cjs`.
- **Unused `@emnapi/core` and `@emnapi/runtime` packages** (`package-lock.json`): Removed these optional dependencies from the lockfile.
- **Redundant platform metadata** (`package-lock.json`): Stripped `libc` annotations from optional native dependency entries (`@emnapi/wasi-threads` platform variants).

---

## [1.0.24]

### Added
Expand Down
10 changes: 5 additions & 5 deletions integrations/vscode/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Tenure

> Persistent, governable state for AI systems. Fully local, fully private, fully automatic. Bring your own key and use Tenure directly inside VS Code's native chat interface. No Copilot subscription required.
> The governed context layer for AI coding agents. Tenure preserves project decisions, constraints, and team conventions across tools, sessions, and interfaces, locally, privately, and automatically.

## BYOK. Your models. Your memory.
## BYOK. Your models. Governed project context.

Tenure registers as a native language model provider in VS Code. Connect your own API key during setup, pick from any model your provider offers, and those models appear directly in the Copilot Chat picker. No subscription to GitHub Copilot. No third-party billing. Just your key, your models, and your context.

Expand All @@ -12,7 +12,7 @@ Supported providers include OpenAI, Anthropic, AWS Bedrock, local models, and an

You spend an hour in OpenWebUI thinking through an architecture problem. You explore options, rule some out, and land on a direction. Then you open VS Code to start building.

Tenure is already there. It knows what you decided, what you rejected, and why. You do not re-explain anything. You just build.
Tenure is already there. It carries forward the decision state: what you chose, what you rejected, why it mattered, and which project it belongs to. You do not re-explain anything. You just build.

This works because Tenure runs as a local proxy outside any single tool. OpenWebUI, LibreChat, Cline, Continue, Windsurf, and any OpenAI-compatible client connect through `localhost:5757`. The VS Code extension brings your IDE into the same memory layer, and because it registers as a native language model provider, Tenure appears directly in Copilot Chat with no manual configuration.

Expand All @@ -35,13 +35,13 @@ If Docker Desktop is not running, the extension will prompt you to start it. If
- **Pushes workspace context** on every file switch so the proxy resolves the right project scope before your first message.
- **Auto-configures other extensions** when possible (for example, Continue) and shows copy-paste instructions for the rest.

## How it solves drift
## Why governed context beats copied instructions

Beyond cross-interface continuity, Tenure fixes the way AI coding sessions break through drift. A script gets renamed in `package.json`. A config file moves. A rule you wrote for Cline never makes it into the equivalent for Windsurf. The agent works from whatever it was last told, and what it was last told is increasingly wrong.

The deeper issue is duplication. Anything that copies information already in your code or config will go stale. Anything that points to that information tends to stay correct. Most `AGENTS.md` files are full of copies.

Tenure does not duplicate. It learns.
Tenure does not treat project context as another file to copy. It keeps decision state in the proxy layer and resolves the right scope before the model responds.

## Which clients work with Tenure?

Expand Down
55 changes: 9 additions & 46 deletions integrations/vscode/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 10 additions & 5 deletions integrations/vscode/package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "tenure-vscode",
"displayName": "Tenure for VSCode",
"displayName": "Tenure",
"description": "Persistent AI memory that follows you across every tool, session, and interface. Fully local.",
"version": "1.0.24",
"version": "1.0.25",
"publisher": "tenureai",
"license": "MIT",
"icon": "resources/tenure-logo-icon.png",
Expand Down Expand Up @@ -39,8 +39,13 @@
"world model",
"local ai",
"openai",
"byok"
"byok",
"language-models"
],
"bugs": {
"url": "https://github.com/tenurehq/tenure/issues"
},
"homepage": "https://tenureai.dev",
"activationEvents": [
"onStartupFinished"
],
Expand Down Expand Up @@ -157,11 +162,11 @@
],
"scripts": {
"build": "tsdown",
"build:test": "tsdown 'src/test/**/*.ts' --out-dir out/test --format cjs --out-extension .js --no-splitting --deps.neverBundle vscode",
"build:test": "tsdown --config tsdown.config.ts",
"watch": "tsc -watch -p tsconfig.json",
"package": "npm run build && vsce package",
"publish": "vsce publish",
"test": "npm run build && npm run build:test && vscode-test"
"test": "npm run build && vscode-test --config .vscode-test.cjs"
},
"devDependencies": {
"@types/jest": "^30.0.0",
Expand Down
23 changes: 20 additions & 3 deletions integrations/vscode/src/beliefsViewProvider.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as vscode from "vscode";
import type { TokenStore } from "./tokenStore.js";
import WebSocket from "ws";
import { getTenureFilePolicyForPath } from "./filePolicy.js";

interface BeliefSummary {
id: string;
Expand Down Expand Up @@ -255,11 +256,23 @@ export class TenureBeliefsViewProvider implements vscode.WebviewViewProvider {
.slice(0, 5)
.join("_");

const activeFile =
const rawActiveFile =
activeFileOverride !== undefined
? activeFileOverride
: this.currentActiveFile;

let safeActiveFile: string | null = rawActiveFile ?? null;
let safeActiveLanguage: string | null =
this.pendingWorkspaceState?.active_language ?? null;

if (rawActiveFile) {
const policy = getTenureFilePolicyForPath(rawActiveFile);
if (policy.suppressMetadata) {
safeActiveFile = null;
safeActiveLanguage = null;
}
}

this.ensureConnected()
.then(() => {
this.send({
Expand All @@ -269,8 +282,8 @@ export class TenureBeliefsViewProvider implements vscode.WebviewViewProvider {
why_it_matters: whyItMatters,
scope,
canonical_name: canonicalName,
active_file: activeFile,
active_language: this.pendingWorkspaceState?.active_language ?? null,
active_file: safeActiveFile,
active_language: safeActiveLanguage,
project_scope: this.currentScope
});
})
Expand All @@ -297,10 +310,14 @@ export class TenureBeliefsViewProvider implements vscode.WebviewViewProvider {
}

sendFileMeta(path: string, sizeBytes: number): void {
const policy = getTenureFilePolicyForPath(path);
if (policy.suppressContent) return;
this.send({ type: "file_meta", path, size_bytes: sizeBytes });
}

sendFileEdited(path: string, projectScope: string): void {
const policy = getTenureFilePolicyForPath(path);
if (policy.suppressContent) return;
this.send({ type: "file_edited", path, project_scope: projectScope });
}

Expand Down
Loading