Skip to content

Commit 57c7ccc

Browse files
committed
release: v0.9.0 — undo, forward links, obsidian path-traversal fix, broader MCP clients
- undo: ats undo / undo_write reverse a recorded write from a ledger before-image (restore an update, delete a create); compensating action.reverted entry, no double-undo - forward links: add_task_link --allow-missing records a dangling link that back-resolves on target creation; resolve_task_links refreshes the placeholder title - security: constrain Obsidian adapter fs access to the vault root (../, /, ..%2f in ids/projectIds could read/overwrite external files) - docs: verified stdio config for Cursor, Windsurf, OpenCode + compat table - test: live add->find e2e smoke incl. graceful degradation with no embedder - bump all packages 0.9.0; internal @reneza deps -> ^0.9.0; server.json 0.9.0
1 parent 45291c8 commit 57c7ccc

32 files changed

Lines changed: 698 additions & 57 deletions

File tree

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11

22
# Changelog
33

4+
## 0.9.0 - Undo, forward links, path-traversal hardening, broader MCP clients
5+
6+
Released 2026-07-03.
7+
8+
- **Reversible writes.** `ats undo [ACTION_ID]` and the `undo_write` MCP tool reverse a recorded write from a before-image the ledger now captures on every update: an updated task is restored to its prior title/body/tags/due, and a created task is deleted. Omit the id to undo the most recent undoable write. Each undo appends a compensating `action.reverted` entry, so it is itself audited and cannot be applied twice. Before-images are only stored for writes that need them, keeping the ledger lean for reads and creates.
9+
- **Forward (dangling) links.** `add_task_link` and `ats link add` gain `--allow-missing`, which records a typed link to a task that does not exist yet. Because ATS resolves a link's target from corpus presence at read time, the link auto-resolves the moment the target is created (the graph node flips from `missing: true` to the real title). `resolve_task_links` / `ats link resolve` persists that heal by refreshing the placeholder title to the real one. Default `add_task_link` stays strict (unknown target still errors).
10+
- **Path-traversal hardening (Obsidian adapter).** Task ids and project ids flowed into filesystem paths unconstrained, so a crafted `../`, leading `/`, or decoded `..%2f` could read or overwrite files outside the vault. Every fs access derived from user input is now constrained to the vault root via a single guard; a title alone was already safe (separators are stripped).
11+
- **Broader MCP client coverage.** Verified stdio configuration for Cursor, Windsurf, and OpenCode alongside Claude Code and Claude Desktop, with a compatibility table and copy-paste config blocks.
12+
- Added a live end-to-end retrieval smoke test that locks in the add→find round-trip and graceful degradation to keyword/RRF retrieval when no embedder is present (or the embedder throws).
13+
414
## 0.8.1 - Minimal frontmatter
515

616
Released 2026-06-17.

README.md

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,24 +126,50 @@ ats bench run|score|progress|analyze-usage
126126
npm run prove:intent|prove:taskmaster|prove:beads|prove:progress
127127
```
128128

129-
## Use it from Claude Code, Claude Desktop, Cursor (MCP)
129+
## Use it from any MCP client (Claude Code, Claude Desktop, Cursor, Windsurf, OpenCode)
130130

131-
[`@reneza/ats-mcp`](packages/mcp) exposes the active adapter as a tool set spanning retrieval, CRUD, and execution context (`find`, `get_task`, `create_task`, `set_task_intent`, `add_task_link`, `context_for_task`, `record_action`, `poll_task_events`, and more). For Claude Code this is persistent memory between sessions with no new database — the agent recalls runbooks, decisions, and project state from the task app you already keep current.
131+
[`@reneza/ats-mcp`](packages/mcp) exposes the active adapter as a tool set spanning retrieval, CRUD, and execution context (`find`, `get_task`, `create_task`, `set_task_intent`, `add_task_link`, `resolve_task_links`, `context_for_task`, `record_action`, `undo_write`, `poll_task_events`, and more). For Claude Code this is persistent memory between sessions with no new database: the agent recalls runbooks, decisions, and project state from the task app you already keep current.
132+
133+
ATS speaks MCP over **stdio**, so any client that can launch a stdio MCP server works. Only the config file and the wrapper key differ; the binary (`ats-mcp`) and its `ATS_ADAPTER` env are the same everywhere.
134+
135+
| Client | Where the config lives | Wrapper key |
136+
| --- | --- | --- |
137+
| Claude Code | `claude mcp add` (below) | n/a |
138+
| Claude Desktop | `claude_desktop_config.json` | `mcpServers` |
139+
| Cursor | `~/.cursor/mcp.json` | `mcpServers` |
140+
| Windsurf | `~/.codeium/windsurf/mcp_config.json` | `mcpServers` |
141+
| OpenCode | `opencode.json` | `mcp` (shape differs, below) |
132142

133143
```bash
134144
# Claude Code
135145
claude mcp add ats -e ATS_ADAPTER=@reneza/ats-adapter-ticktick -- ats-mcp
136146
```
137147

138148
```jsonc
139-
// Claude Desktop / Cursor
149+
// Claude Desktop / Cursor / Windsurf — identical `mcpServers` shape
140150
{
141151
"mcpServers": {
142152
"ats": { "command": "ats-mcp", "env": { "ATS_ADAPTER": "@reneza/ats-adapter-ticktick" } }
143153
}
144154
}
145155
```
146156

157+
```jsonc
158+
// OpenCode (opencode.json) — local stdio server, note `command` is an array
159+
{
160+
"mcp": {
161+
"ats": {
162+
"type": "local",
163+
"command": ["ats-mcp"],
164+
"environment": { "ATS_ADAPTER": "@reneza/ats-adapter-ticktick" },
165+
"enabled": true
166+
}
167+
}
168+
}
169+
```
170+
171+
Install the binary on `PATH` first (`npm i -g @reneza/ats-cli`), or use an absolute path to `ats-mcp` if your client does not inherit your shell `PATH`.
172+
147173
## Conventions
148174

149175
- **Wiki project.** A designated project (default `Permanent Notes`) holds durable knowledge; others hold ephemeral tasks.
@@ -166,6 +192,6 @@ so it stops re-reading the whole tree each session.
166192

167193
## Versioning & license
168194

169-
`v0.6`portable intent, exploration promotion, goal hierarchy + conflict evaluation, bounded task events, workflow-progress evaluation, Taskmaster and Beads adapters. See [`CHANGELOG.md`](CHANGELOG.md). MIT.
195+
`v0.9`: reversible writes (`ats undo` / `undo_write` from a ledger before-image), forward/dangling links that back-resolve on target creation (`add_task_link --allow-missing`, `resolve_task_links`), Obsidian path-traversal hardening, and verified stdio config for Cursor, Windsurf, and OpenCode. Built on v0.6-v0.8: portable intent, exploration promotion, goal hierarchy and conflict evaluation, bounded task events, and the Taskmaster/Beads adapters. See [`CHANGELOG.md`](CHANGELOG.md). MIT.
170196

171197
If ATS is useful, consider a ⭐ — it helps others find it.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "agentic-task-system",
3-
"version": "0.8.1",
3+
"version": "0.9.0",
44
"private": true,
55
"type": "module",
66
"description": "Your task manager is the best agent memory you're not using. Agent-native context layer over your existing task app, with hybrid retrieval (RRF) and pluggable storage adapters.",

packages/adapter-airtable/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@reneza/ats-adapter-airtable",
3-
"version": "0.8.1",
3+
"version": "0.9.0",
44
"description": "Airtable adapter for Agentic Task System. Expose any Airtable base as agent-queryable records through ATS retrieval, RRF fusion, and MCP — a table is a project, a record is a task. Adapter, not migration.",
55
"type": "module",
66
"main": "index.js",
@@ -12,7 +12,7 @@
1212
"test": "node --test"
1313
},
1414
"peerDependencies": {
15-
"@reneza/ats-core": "^0.8.1"
15+
"@reneza/ats-core": "^0.9.0"
1616
},
1717
"dependencies": {},
1818
"repository": {

packages/adapter-beads/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@reneza/ats-adapter-beads",
3-
"version": "0.8.1",
3+
"version": "0.9.0",
44
"description": "Beads adapter for Agentic Task System using the official bd JSON CLI over repository-local Dolt state.",
55
"type": "module",
66
"main": "index.js",
@@ -13,7 +13,7 @@
1313
"prepublishOnly": "node ../../scripts/check-no-pii.mjs --self"
1414
},
1515
"peerDependencies": {
16-
"@reneza/ats-core": "^0.8.1"
16+
"@reneza/ats-core": "^0.9.0"
1717
},
1818
"repository": {
1919
"type": "git",

packages/adapter-composite/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@reneza/ats-adapter-composite",
3-
"version": "0.8.1",
3+
"version": "0.9.0",
44
"description": "Cross-source adapter for the Agentic Task System. Query GitHub + Notion + TickTick + any ATS backends as ONE fused corpus: a single `ats find` returns one RRF-ranked list across all of them, each result tagged with its backend. The thing a single-vendor MCP server can't do.",
55
"type": "module",
66
"main": "index.js",
@@ -12,7 +12,7 @@
1212
"test": "node --test"
1313
},
1414
"peerDependencies": {
15-
"@reneza/ats-core": "^0.8.1"
15+
"@reneza/ats-core": "^0.9.0"
1616
},
1717
"dependencies": {},
1818
"repository": {

packages/adapter-github/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@reneza/ats-adapter-github",
3-
"version": "0.8.1",
3+
"version": "0.9.0",
44
"description": "GitHub Issues adapter for Agentic Task System. Expose any repository's issues as agent-queryable tasks through ATS retrieval, RRF fusion, and MCP — a repo is a project, an issue is a task. Adapter, not migration.",
55
"type": "module",
66
"main": "index.js",
@@ -12,7 +12,7 @@
1212
"test": "node --test"
1313
},
1414
"peerDependencies": {
15-
"@reneza/ats-core": "^0.8.1"
15+
"@reneza/ats-core": "^0.9.0"
1616
},
1717
"dependencies": {},
1818
"repository": {

packages/adapter-google/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@reneza/ats-adapter-google",
3-
"version": "0.8.1",
3+
"version": "0.9.0",
44
"description": "Google Workspace adapter for Agentic Task System. Pull Google Sheets, Docs, and Slides into ATS retrieval and MCP as a read-only corpus, authed as a dedicated share-scoped user. Adapter, not migration.",
55
"type": "module",
66
"main": "index.js",
@@ -12,7 +12,7 @@
1212
"test": "node --test"
1313
},
1414
"peerDependencies": {
15-
"@reneza/ats-core": "^0.8.1"
15+
"@reneza/ats-core": "^0.9.0"
1616
},
1717
"dependencies": {},
1818
"repository": {

packages/adapter-notion/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@reneza/ats-adapter-notion",
3-
"version": "0.8.1",
3+
"version": "0.9.0",
44
"description": "Notion adapter for Agentic Task System. Expose any Notion database as agent-queryable pages through ATS retrieval, RRF fusion, and MCP — a database is a project, a page is a task. Adapter, not migration.",
55
"type": "module",
66
"main": "index.js",
@@ -12,7 +12,7 @@
1212
"test": "node --test"
1313
},
1414
"peerDependencies": {
15-
"@reneza/ats-core": "^0.8.1"
15+
"@reneza/ats-core": "^0.9.0"
1616
},
1717
"dependencies": {},
1818
"repository": {

packages/adapter-obsidian/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@reneza/ats-adapter-obsidian",
3-
"version": "0.8.1",
3+
"version": "0.9.0",
44
"description": "Obsidian vault adapter for Agentic Task System. Hybrid + RRF retrieval, the wiki layer, and the MCP server over the folder of markdown you already keep in Obsidian — adapter, not migration.",
55
"type": "module",
66
"main": "index.js",
@@ -12,7 +12,7 @@
1212
"prepublishOnly": "node ../../scripts/check-no-pii.mjs --self"
1313
},
1414
"peerDependencies": {
15-
"@reneza/ats-core": "^0.8.1"
15+
"@reneza/ats-core": "^0.9.0"
1616
},
1717
"dependencies": {},
1818
"repository": {

0 commit comments

Comments
 (0)