frontier-mcp 0.5.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +66 -15
- package/dist/domain.d.ts +69 -25
- package/dist/domain.d.ts.map +1 -1
- package/dist/domain.js +9 -0
- package/dist/domain.js.map +1 -1
- package/dist/frontier.d.ts +8 -0
- package/dist/frontier.d.ts.map +1 -1
- package/dist/frontier.js +33 -4
- package/dist/frontier.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +26 -9
- package/dist/server.js.map +1 -1
- package/dist/storage/driver.d.ts +61 -6
- package/dist/storage/driver.d.ts.map +1 -1
- package/dist/storage/driver.js +67 -5
- package/dist/storage/driver.js.map +1 -1
- package/dist/storage/markdown/create.d.ts +2 -3
- package/dist/storage/markdown/create.d.ts.map +1 -1
- package/dist/storage/markdown/create.js +2 -11
- package/dist/storage/markdown/create.js.map +1 -1
- package/dist/storage/markdown/driver.d.ts.map +1 -1
- package/dist/storage/markdown/driver.js +155 -36
- package/dist/storage/markdown/driver.js.map +1 -1
- package/dist/storage/markdown/frontmatter.js +1 -1
- package/dist/storage/markdown/header-doc.d.ts.map +1 -1
- package/dist/storage/markdown/header-doc.js +13 -11
- package/dist/storage/markdown/header-doc.js.map +1 -1
- package/dist/storage/markdown/legacy.d.ts +8 -4
- package/dist/storage/markdown/legacy.d.ts.map +1 -1
- package/dist/storage/markdown/legacy.js +20 -15
- package/dist/storage/markdown/legacy.js.map +1 -1
- package/dist/storage/markdown/migrate.d.ts +13 -3
- package/dist/storage/markdown/migrate.d.ts.map +1 -1
- package/dist/storage/markdown/migrate.js +69 -79
- package/dist/storage/markdown/migrate.js.map +1 -1
- package/dist/storage/markdown/schema.d.ts +9 -0
- package/dist/storage/markdown/schema.d.ts.map +1 -0
- package/dist/storage/markdown/schema.js +21 -0
- package/dist/storage/markdown/schema.js.map +1 -0
- package/dist/storage/markdown/serialize.d.ts +1 -1
- package/dist/storage/markdown/serialize.d.ts.map +1 -1
- package/dist/storage/markdown/serialize.js +110 -24
- package/dist/storage/markdown/serialize.js.map +1 -1
- package/dist/storage/markdown/ticket.d.ts +29 -4
- package/dist/storage/markdown/ticket.d.ts.map +1 -1
- package/dist/storage/markdown/ticket.js +102 -30
- package/dist/storage/markdown/ticket.js.map +1 -1
- package/dist/storage/markdown/watcher.d.ts +1 -1
- package/dist/storage/markdown/watcher.d.ts.map +1 -1
- package/dist/storage/markdown/watcher.js +91 -11
- package/dist/storage/markdown/watcher.js.map +1 -1
- package/dist/tools/create-tickets.d.ts +12 -1
- package/dist/tools/create-tickets.d.ts.map +1 -1
- package/dist/tools/create-tickets.js +23 -6
- package/dist/tools/create-tickets.js.map +1 -1
- package/dist/tools/edit-map.d.ts.map +1 -1
- package/dist/tools/edit-map.js +6 -2
- package/dist/tools/edit-map.js.map +1 -1
- package/dist/tools/get-board.d.ts.map +1 -1
- package/dist/tools/get-board.js +34 -7
- package/dist/tools/get-board.js.map +1 -1
- package/dist/tools/get-tickets.d.ts.map +1 -1
- package/dist/tools/get-tickets.js +42 -11
- package/dist/tools/get-tickets.js.map +1 -1
- package/dist/tools/list-efforts.d.ts +7 -0
- package/dist/tools/list-efforts.d.ts.map +1 -1
- package/dist/tools/list-efforts.js +15 -0
- package/dist/tools/list-efforts.js.map +1 -1
- package/dist/tools/migrate-effort.d.ts +6 -1
- package/dist/tools/migrate-effort.d.ts.map +1 -1
- package/dist/tools/migrate-effort.js +62 -20
- package/dist/tools/migrate-effort.js.map +1 -1
- package/dist/tools/update-ticket.d.ts +2 -0
- package/dist/tools/update-ticket.d.ts.map +1 -1
- package/dist/tools/update-ticket.js +14 -7
- package/dist/tools/update-ticket.js.map +1 -1
- package/dist/tools/workspace-line.d.ts +2 -2
- package/dist/tools/workspace-line.js +2 -2
- package/dist/workspace.d.ts +11 -0
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +17 -5
- package/dist/workspace.js.map +1 -1
- package/docs/agents/issue-tracker.md +60 -27
- package/package.json +11 -11
- package/scripts/frontier-setup.cjs +451 -18
package/dist/workspace.js
CHANGED
|
@@ -41,15 +41,26 @@ const ROOT_MARKERS = [
|
|
|
41
41
|
* A workspace with no `.scratch/` is not — that is a fresh project.
|
|
42
42
|
*/
|
|
43
43
|
export function resolveWorkspace(root, context) {
|
|
44
|
+
return locateWorkspace(root, context).root;
|
|
45
|
+
}
|
|
46
|
+
/** {@link resolveWorkspace}, saying which source won. */
|
|
47
|
+
export function locateWorkspace(root, context) {
|
|
44
48
|
const argument = given(root);
|
|
45
49
|
if (argument !== undefined) {
|
|
46
|
-
return
|
|
50
|
+
return {
|
|
51
|
+
root: requireDirectory(resolve(context.cwd, argument), 'root argument'),
|
|
52
|
+
resolvedBy: 'root argument',
|
|
53
|
+
};
|
|
47
54
|
}
|
|
48
55
|
const fromEnv = given(context.env[WORKSPACE_ENV_VAR]);
|
|
49
56
|
if (fromEnv !== undefined) {
|
|
50
|
-
return
|
|
57
|
+
return {
|
|
58
|
+
root: requireDirectory(resolve(context.cwd, fromEnv), WORKSPACE_ENV_VAR),
|
|
59
|
+
resolvedBy: `$${WORKSPACE_ENV_VAR}`,
|
|
60
|
+
};
|
|
51
61
|
}
|
|
52
|
-
|
|
62
|
+
const cwd = resolve(context.cwd);
|
|
63
|
+
return (findRootMarker(cwd) ?? { root: cwd, resolvedBy: 'working directory, no root marker found' });
|
|
53
64
|
}
|
|
54
65
|
/**
|
|
55
66
|
* An empty override was not supplied. Falling through to the next source is the
|
|
@@ -67,8 +78,9 @@ function given(value) {
|
|
|
67
78
|
function findRootMarker(from) {
|
|
68
79
|
let dir = from;
|
|
69
80
|
for (;;) {
|
|
70
|
-
|
|
71
|
-
|
|
81
|
+
const marker = ROOT_MARKERS.find(candidate => candidate.matches(join(dir, candidate.name)));
|
|
82
|
+
if (marker !== undefined)
|
|
83
|
+
return { root: dir, resolvedBy: marker.name };
|
|
72
84
|
const parent = dirname(dir);
|
|
73
85
|
if (parent === dir)
|
|
74
86
|
return undefined;
|
package/dist/workspace.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace.js","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEnD,iFAAiF;AACjF,MAAM,CAAC,MAAM,iBAAiB,GAAG,eAAe,CAAC;AAEjD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,YAAY,GAAG;IACnB,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE;IAC1C,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE;CAClC,CAAC;AAQF;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAwB,EAAE,OAAyB;IAClF,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,gBAAgB,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,eAAe,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"workspace.js","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
# Issue tracker — FrontierMCP and file fallback
|
|
2
2
|
|
|
3
|
+
Tracker doc revision 7. To check a vendored copy, compare this number with the one in the
|
|
4
|
+
`frontier://tracker-doc` resource of the server you run; a lower number, or no revision line, is
|
|
5
|
+
stale.
|
|
6
|
+
|
|
3
7
|
Use **FrontierMCP** as the issue tracker. Its canonical storage is markdown under `.scratch/`.
|
|
4
8
|
Vocabulary is defined in the project's `CONTEXT.md` when present — Effort, Board, Header doc, Map,
|
|
5
|
-
Spec, Ticket, Edge, Frontier.
|
|
9
|
+
Spec, Ticket, Edge, Frontier, Handle, Temporary key.
|
|
6
10
|
|
|
7
11
|
When **FrontierMCP** (server name `frontier`) is loaded in your session, use the tools below. They
|
|
8
12
|
own the schema, compute the graph, and answer orientation questions for a fraction of the token cost
|
|
@@ -30,7 +34,7 @@ session.** Moving to another worktree mid-session does not retarget it: pass `ro
|
|
|
30
34
|
reports no Efforts — that is the worktree being served correctly, not the tracker going missing.
|
|
31
35
|
|
|
32
36
|
**Every call that writes opens with `root: <path>`**, naming the repository it just changed. Read it
|
|
33
|
-
— a Ticket id is not
|
|
37
|
+
— a Ticket id is unique within a repository, not across them, so `T10 updated` looks the same whichever repository answered, and
|
|
34
38
|
this line is the only part of the result that tells you. Reads do not carry it, and neither do the
|
|
35
39
|
read paths of write-capable tools: `edit_map` with no section fields, `spec` with no `content`, and
|
|
36
40
|
`migrate_effort` with `preview`.
|
|
@@ -44,14 +48,14 @@ Eight tools permanently. Optional arguments extend an existing tool; there is no
|
|
|
44
48
|
|
|
45
49
|
| Tool | Use when |
|
|
46
50
|
| --- | --- |
|
|
47
|
-
| `list_efforts` | Orient — list Efforts with Ticket counts, header doc kinds, and Frontier size. |
|
|
51
|
+
| `list_efforts` | Orient — list Efforts with Ticket counts, header doc kinds, and Frontier size. A repository with no `.scratch/` at all gets `no tracker here`, the marker that located the root, and a `start one` line to copy; an empty `.scratch/` still reads `(no efforts)`. |
|
|
48
52
|
| `get_board` | See the whole Effort cheaply — Destination, one summary line per Ticket, Frontier marked. Never returns bodies. |
|
|
49
53
|
| `get_tickets` | Fetch full bodies for specific ids after the Board tells you which Tickets matter. |
|
|
50
54
|
| `create_tickets` | Publish a breakdown in one call. Declare Edges with temporary keys; the server assigns ids and numbers. |
|
|
51
|
-
| `update_ticket` | Claim, resolve, drop, reopen, release, set title/kind/type, set triage, replace Edges, comment,
|
|
55
|
+
| `update_ticket` | Claim, resolve, drop, reopen, release, set title/kind/type, set triage, replace Edges, comment, tick acceptance criteria, or `drop_keys` to delete Unimported frontmatter keys. One Ticket per call. |
|
|
52
56
|
| `edit_map` | Edit Map sections — Destination, Notes, fog, Out of scope. Decisions-so-far regenerates from resolved Tickets. |
|
|
53
57
|
| `spec` | Read or write a Spec as a whole document. |
|
|
54
|
-
| `migrate_effort` | Normalize
|
|
58
|
+
| `migrate_effort` | Normalize Foreign Tickets — those whose file does not conform to the schema — in an Effort. Filenames never change. Preview writes nothing and names a Ticket it would mint by its handle (`<effort>#<order>`), not a predicted id. |
|
|
55
59
|
|
|
56
60
|
### Typical agent flow
|
|
57
61
|
|
|
@@ -76,7 +80,21 @@ Eight tools permanently. Optional arguments extend an existing tool; there is no
|
|
|
76
80
|
| release a stale claim | `update_ticket` with `{ release: true }` |
|
|
77
81
|
| edit the Map | `edit_map` |
|
|
78
82
|
| write or read the Spec | `spec` |
|
|
79
|
-
| normalize
|
|
83
|
+
| normalize foreign files | `migrate_effort` |
|
|
84
|
+
|
|
85
|
+
Two Ticket files carrying one id are listed in each Board's warnings, with claimant files for the
|
|
86
|
+
first few, and every write addressed to that id is refused. Fix it by hand, giving all but one a new id; the server never
|
|
87
|
+
renumbers. Under a pattern whose only variable token is `<N>`, every `create_tickets` result carries
|
|
88
|
+
a standing warning that the pattern collides across branches — it describes the configuration, not
|
|
89
|
+
that call; the remedy is a mixed pattern such as `T<N>-<b36{4}>`. When a Ticket's frontmatter carries
|
|
90
|
+
keys outside the schema, `get_tickets` appends them as a fenced `yaml` block under `## Unimported
|
|
91
|
+
frontmatter` — the whole fence for a Ticket with no `id`, only the unimported entries otherwise. The
|
|
92
|
+
read leaves the file unchanged, and no ordinary write removes them: pass `update_ticket` `drop_keys`
|
|
93
|
+
with the names to delete. A schema key or a key the fence does not carry fails the call and writes
|
|
94
|
+
nothing; the rest of the fence stays byte-identical. Dropping the last one from a Ticket with no `id`
|
|
95
|
+
leaves it no longer Foreign, still listed under the Board's `no id` warning. A Board counts `resolved` Tickets
|
|
96
|
+
with no `answer_gist`, `dropped` with no `dropped_reason` and `claimed` with no `claimed_by` or `claimed_at` in its
|
|
97
|
+
warnings, so set the field with the Status.
|
|
80
98
|
|
|
81
99
|
Claims are compare-and-set — a parallel session that already holds the Ticket wins. Writes carry the
|
|
82
100
|
`revision` from the last read; a mismatch is refused, never retried over the caller's edit.
|
|
@@ -87,41 +105,56 @@ These conventions are canonical whether FrontierMCP is loaded or not. FrontierMC
|
|
|
87
105
|
the same files; a session without the server still produces valid Tickets by following this section.
|
|
88
106
|
|
|
89
107
|
**Canonical is not licence to allocate ids by hand.** When FrontierMCP is loaded, ids come from
|
|
90
|
-
`create_tickets
|
|
91
|
-
repo
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
distinct ids, and duplicates are silent. A *guessed* id passed to `create_tickets` costs nothing;
|
|
96
|
-
the server allocates and discards the guess. Only the hand-written file breaks.
|
|
108
|
+
`create_tickets`, and you never scan for one: the server mints every id it is present for. It knows
|
|
109
|
+
the repo's id pattern, and under a pattern containing `<N>` it counts under a guard
|
|
110
|
+
(`.scratch/.frontier-id-N-<n>.guard`, keyed on the counter value) that a file written straight to
|
|
111
|
+
disk cannot take — ADR 0006 in the frontier-mcp repository. Hand-writing while the server is loaded
|
|
112
|
+
bypasses the mint whatever the pattern.
|
|
97
113
|
|
|
98
114
|
### Layout
|
|
99
115
|
|
|
100
|
-
- One Effort per directory: `.scratch/<effort-slug
|
|
116
|
+
- One Effort per directory: `.scratch/<effort-slug>/`.
|
|
117
|
+
- `.scratch/frontier.yml`, beside the Effort directories, is the one other file FrontierMCP reads.
|
|
118
|
+
Its one key, `id_pattern`, shapes Ticket ids. The server reads it once at start; restart a running
|
|
119
|
+
server after editing it.
|
|
101
120
|
- The header doc is `spec.md` (from `/to-spec`) or `map.md` (from `/wayfinder`). An Effort charted as a
|
|
102
121
|
Map may later gain a Spec — that is wayfinder's handoff, not a mistake.
|
|
103
122
|
- Tickets are one file per Ticket under `.scratch/<effort-slug>/issues/` — never a single combined
|
|
104
123
|
tickets file.
|
|
105
|
-
- Ticket filenames are `<NN
|
|
106
|
-
the identity and never changes.
|
|
107
|
-
- **Ticket ids are
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
124
|
+
- Ticket filenames are `<NN>-<id>-<slug>.md`. `NN` is sort order only and may be rewritten. The id
|
|
125
|
+
is the identity and never changes.
|
|
126
|
+
- **Ticket ids are unique across the whole repo**, so a bare id resolves anywhere in it, including
|
|
127
|
+
in commit messages. With FrontierMCP loaded, `create_tickets` assigns them. Only when the server is
|
|
128
|
+
absent, mint one by hand:
|
|
129
|
+
1. Read `id_pattern` from `.scratch/frontier.yml`. No file or no key means `T<b36{6}>`.
|
|
130
|
+
2. Check the pattern is legal: it begins with a literal letter or underscore; literals are only
|
|
131
|
+
`A-Z a-z 0-9 . _ -`; the tokens are `<N>`, `<b36{n}>` and `<b16{n}>` with n from 1 to 64, and
|
|
132
|
+
`<effort>` is refused; at most one `<N>`; at least one `<N>` or random token; a minted id is at
|
|
133
|
+
most 64 characters, counting `<N>` as one. If the file is not valid YAML, is not a mapping,
|
|
134
|
+
`id_pattern` is not a string, or the pattern breaks a rule, **do not mint** — fix the file first.
|
|
135
|
+
Never fall back to the default: an id minted in a format nobody asked for is permanent.
|
|
136
|
+
3. Render it. Every `<b36{n}>` is exactly n characters from `0-9a-z`, every `<b16{n}>` exactly n
|
|
137
|
+
from `0-9a-f`, lowercase always. `<N>` is decimal with no leading zeros. Anything outside `<>`
|
|
138
|
+
is literal.
|
|
139
|
+
4. **No `<N>` in the pattern:** draw the random tokens. Do not scan for a highest id.
|
|
140
|
+
5. **`<N>` in the pattern:** scan every `.scratch/*/issues/` for the highest `<N>` among ids that
|
|
141
|
+
match the whole pattern and add one; under a mixed pattern, count first, then draw the random
|
|
142
|
+
part. A hand-writer cannot take the server's guard, so if any session might be minting at the
|
|
143
|
+
same time you can both reach the same number unseen.
|
|
144
|
+
6. Check the id is not already in use anywhere in `.scratch/`.
|
|
112
145
|
- Formal metadata goes in YAML frontmatter. Prose stays prose.
|
|
113
146
|
|
|
114
147
|
### Ticket frontmatter
|
|
115
148
|
|
|
116
149
|
```yaml
|
|
117
150
|
---
|
|
118
|
-
id: T12 #
|
|
119
|
-
title: Parse
|
|
151
|
+
id: T12 # shaped by id_pattern; repo-unique, never reused or changed
|
|
152
|
+
title: Parse tickets without frontmatter
|
|
120
153
|
kind: build # build | decision
|
|
121
154
|
type: research # decision only: research | prototype | grilling | task
|
|
122
155
|
status: open # open | claimed | resolved | dropped
|
|
123
156
|
triage: ready-for-agent # see triage-labels.md
|
|
124
|
-
blocked_by: [
|
|
157
|
+
blocked_by: [T9, T11] # plain ids, resolved repo-wide
|
|
125
158
|
claimed_by: # required when status: claimed
|
|
126
159
|
claimed_at: # timestamp, set with claimed_by
|
|
127
160
|
answer_gist: # required when status: resolved — one line, every kind
|
|
@@ -164,8 +197,8 @@ When FrontierMCP is loaded, prefer the MCP calls in the table above over hand-ed
|
|
|
164
197
|
|
|
165
198
|
**Everything below holds only while FrontierMCP is absent from the session.** With the server
|
|
166
199
|
loaded, `create_tickets` publishes the breakdown and is the only thing that may allocate an id;
|
|
167
|
-
hand-writing the file bypasses the
|
|
200
|
+
hand-writing the file bypasses the mint, per the File conventions preamble.
|
|
168
201
|
|
|
169
202
|
When a skill says "publish to the issue tracker" and FrontierMCP is not loaded, create
|
|
170
|
-
`.scratch/<effort-slug>/issues/<NN
|
|
171
|
-
|
|
203
|
+
`.scratch/<effort-slug>/issues/<NN>-<id>-<slug>.md` (creating directories as needed), mint the id
|
|
204
|
+
as the Layout steps above describe, and write frontmatter matching the template above.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "frontier-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "An MCP server exposing the markdown issue tracker under a repo's .scratch/ as a queryable graph",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -25,19 +25,19 @@
|
|
|
25
25
|
}
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@modelcontextprotocol/server": "^2.
|
|
29
|
-
"yaml": "^2.9.
|
|
30
|
-
"zod": "^4.
|
|
28
|
+
"@modelcontextprotocol/server": "^2.4.0",
|
|
29
|
+
"yaml": "^2.9.1",
|
|
30
|
+
"zod": "^4.6.7"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@modelcontextprotocol/client": "^2.
|
|
34
|
-
"@release-it/conventional-changelog": "^12.0.
|
|
35
|
-
"@types/node": "^24.
|
|
36
|
-
"oxfmt": "^0.
|
|
37
|
-
"oxlint": "^1.
|
|
38
|
-
"release-it": "^21.
|
|
33
|
+
"@modelcontextprotocol/client": "^2.4.0",
|
|
34
|
+
"@release-it/conventional-changelog": "^12.0.2",
|
|
35
|
+
"@types/node": "^24.19.2",
|
|
36
|
+
"oxfmt": "^0.78.0",
|
|
37
|
+
"oxlint": "^1.93.0",
|
|
38
|
+
"release-it": "^21.1.2",
|
|
39
39
|
"typescript": "^7.0.2",
|
|
40
|
-
"vitest": "^
|
|
40
|
+
"vitest": "^5.1.0"
|
|
41
41
|
},
|
|
42
42
|
"engines": {
|
|
43
43
|
"node": "^20.20.2 || ^22.17.1 || ^24.15.0"
|