vouchington-tooling 0.24.1 → 0.26.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 +43 -0
- package/dist/agent-blackboard/client.d.mts +5 -0
- package/dist/agent-blackboard/client.mjs +1 -1
- package/dist/agent-blackboard/feedback-audit-source.d.mts +13 -0
- package/dist/agent-blackboard/feedback-audit-source.mjs +30 -0
- package/dist/agent-blackboard/feedback-compose.d.mts +5 -1
- package/dist/agent-blackboard/feedback-compose.mjs +8 -18
- package/dist/agent-blackboard/feedback-journal-audit.d.mts +20 -0
- package/dist/agent-blackboard/feedback-journal-audit.mjs +29 -0
- package/dist/agent-blackboard/feedback-journal-sandbox.d.mts +5 -0
- package/dist/agent-blackboard/feedback-journal-sandbox.mjs +40 -0
- package/dist/agent-blackboard/index.d.mts +9 -8
- package/dist/agent-blackboard/index.mjs +7 -34
- package/dist/agent-blackboard/journal.d.mts +21 -0
- package/dist/agent-blackboard/journal.mjs +45 -0
- package/dist/agent-blackboard/session-tools.d.mts +36 -0
- package/dist/agent-blackboard/session-tools.mjs +41 -0
- package/dist/cli/commands/mcp.d.mts +5 -0
- package/dist/cli/commands/mcp.mjs +18 -0
- package/dist/cli/index.mjs +5 -5
- package/dist/cli/installed-version.d.mts +1 -0
- package/dist/cli/installed-version.mjs +5 -0
- package/dist/cli/parse-forwarded-commands.d.mts +3 -0
- package/dist/cli/parse-forwarded-commands.mjs +2 -0
- package/dist/cli/parse.d.mts +3 -0
- package/dist/cli/usage.d.mts +1 -1
- package/dist/cli/usage.mjs +6 -0
- package/dist/mcp-server/args.d.mts +9 -0
- package/dist/mcp-server/args.mjs +48 -0
- package/dist/mcp-server/context.d.mts +19 -0
- package/dist/mcp-server/context.mjs +23 -0
- package/dist/mcp-server/dispatch.d.mts +18 -0
- package/dist/mcp-server/dispatch.mjs +62 -0
- package/dist/mcp-server/fake-blackboard.test-helpers.d.mts +39 -0
- package/dist/mcp-server/fake-blackboard.test-helpers.mjs +75 -0
- package/dist/mcp-server/git-fixture.test-helpers.d.mts +16 -0
- package/dist/mcp-server/git-fixture.test-helpers.mjs +35 -0
- package/dist/mcp-server/handlers-journal.d.mts +6 -0
- package/dist/mcp-server/handlers-journal.mjs +98 -0
- package/dist/mcp-server/handlers-session.d.mts +4 -0
- package/dist/mcp-server/handlers-session.mjs +47 -0
- package/dist/mcp-server/harness.test-helpers.d.mts +33 -0
- package/dist/mcp-server/harness.test-helpers.mjs +48 -0
- package/dist/mcp-server/run.d.mts +20 -0
- package/dist/mcp-server/run.mjs +21 -0
- package/dist/mcp-server/sdk.d.mts +17 -0
- package/dist/mcp-server/sdk.mjs +33 -0
- package/dist/mcp-server/server.d.mts +9 -0
- package/dist/mcp-server/server.mjs +17 -0
- package/dist/mcp-server/tools.d.mts +19 -0
- package/dist/mcp-server/tools.mjs +120 -0
- package/dist/mcp-server/worktree.d.mts +18 -0
- package/dist/mcp-server/worktree.mjs +58 -0
- package/dist/session-friction/audit-block.d.mts +4 -0
- package/dist/session-friction/audit-block.mjs +45 -0
- package/dist/session-friction/ci-failures.d.mts +2 -1
- package/dist/session-friction/ci-failures.mjs +10 -46
- package/dist/session-friction/journal.d.mts +14 -0
- package/dist/session-friction/journal.mjs +66 -0
- package/dist/session-friction/report.mjs +10 -74
- package/docs/mcp-server.md +134 -0
- package/package.json +7 -2
- package/skills/blackboard/SKILL.md +59 -22
- package/skills/manifest.json +19 -19
- package/skills/retrospective-distill/SKILL.md +37 -13
|
@@ -1,61 +1,8 @@
|
|
|
1
1
|
import { eventLimit, readFrictionLog, requireDirectory } from './log.mjs';
|
|
2
|
-
import { buildCiFailuresSection, getConformingGroups } from './ci-failures.mjs';
|
|
2
|
+
import { buildCiFailuresSection, getConformingGroups, incompleteCiSection } from './ci-failures.mjs';
|
|
3
|
+
import { errorMessage, scanJournal } from './journal.mjs';
|
|
3
4
|
import { buildSandboxSection } from './sandbox.mjs';
|
|
4
5
|
import { validateSessionId } from './session-id.mjs';
|
|
5
|
-
const JOURNAL_ENTRY_MAX_COUNT = 500;
|
|
6
|
-
const JOURNAL_MARKDOWN_MAX_BYTES = 10_000;
|
|
7
|
-
const JOURNAL_TOTAL_MAX_BYTES = 1_000_000;
|
|
8
|
-
function journalData(entry) {
|
|
9
|
-
try {
|
|
10
|
-
const data = entry?.data;
|
|
11
|
-
return data ? { type: data.type, markdown: data.markdown } : undefined;
|
|
12
|
-
}
|
|
13
|
-
catch {
|
|
14
|
-
return 'unreadable';
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
async function collectEntries(entries) {
|
|
18
|
-
const result = [];
|
|
19
|
-
let consumed = 0;
|
|
20
|
-
let inspectedBytes = 0;
|
|
21
|
-
let retainedBytes = 0;
|
|
22
|
-
let truncated = false;
|
|
23
|
-
for await (const entry of entries) {
|
|
24
|
-
consumed++;
|
|
25
|
-
const scanned = journalData(entry);
|
|
26
|
-
if (scanned === 'unreadable')
|
|
27
|
-
truncated = true;
|
|
28
|
-
const data = scanned === 'unreadable' ? undefined : scanned;
|
|
29
|
-
const markdown = data?.markdown;
|
|
30
|
-
if (data?.type === 'journal' && typeof markdown !== 'string')
|
|
31
|
-
truncated = true;
|
|
32
|
-
if (data?.type === 'journal' && typeof markdown === 'string') {
|
|
33
|
-
const bytes = Buffer.byteLength(markdown);
|
|
34
|
-
inspectedBytes += bytes;
|
|
35
|
-
if (bytes > JOURNAL_MARKDOWN_MAX_BYTES)
|
|
36
|
-
truncated = true;
|
|
37
|
-
if (bytes <= JOURNAL_MARKDOWN_MAX_BYTES && retainedBytes + bytes <= JOURNAL_TOTAL_MAX_BYTES) {
|
|
38
|
-
result.push({ data: { type: 'journal', markdown } });
|
|
39
|
-
retainedBytes += bytes;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
if (consumed >= JOURNAL_ENTRY_MAX_COUNT ||
|
|
43
|
-
inspectedBytes >= JOURNAL_TOTAL_MAX_BYTES ||
|
|
44
|
-
retainedBytes >= JOURNAL_TOTAL_MAX_BYTES) {
|
|
45
|
-
truncated = true;
|
|
46
|
-
break;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
return { entries: result, truncated };
|
|
50
|
-
}
|
|
51
|
-
function errorMessage(error) {
|
|
52
|
-
try {
|
|
53
|
-
return error instanceof Error ? error.message : String(error);
|
|
54
|
-
}
|
|
55
|
-
catch {
|
|
56
|
-
return '[unprintable error]';
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
6
|
function sandboxMarkdown(friction) {
|
|
60
7
|
if (friction.status === 'events')
|
|
61
8
|
return `${friction.truncated ? `## Capture Coverage\nStatus: partial\nDropped records: ${friction.droppedCount}\n\n` : ''}${buildSandboxSection(friction.events)}`;
|
|
@@ -64,9 +11,6 @@ function sandboxMarkdown(friction) {
|
|
|
64
11
|
const status = friction.status === 'empty' ? 'none observed' : 'unavailable (no friction log)';
|
|
65
12
|
return `## Sandbox & Permission Audit\nStatus: ${status}`;
|
|
66
13
|
}
|
|
67
|
-
function incompleteCiSection(markdownBlocks) {
|
|
68
|
-
return ['## CI Failures\nStatus: unavailable (journal scan incomplete)', ...markdownBlocks].join('\n\n');
|
|
69
|
-
}
|
|
70
14
|
function reportFromLog(sessionId, logOptions, journal) {
|
|
71
15
|
try {
|
|
72
16
|
const friction = readFrictionLog(sessionId, logOptions);
|
|
@@ -113,24 +57,16 @@ export async function buildSessionFrictionReport(sessionId, options) {
|
|
|
113
57
|
validateSessionId(sessionId);
|
|
114
58
|
requireDirectory(options.directory);
|
|
115
59
|
eventLimit(options.maxEvents);
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
const collected = await collectEntries(loaded.entries);
|
|
123
|
-
journal = {
|
|
60
|
+
const scanned = await scanJournal(sessionId, options.journalLoader);
|
|
61
|
+
const journal = scanned.status === 'unreachable'
|
|
62
|
+
? scanned
|
|
63
|
+
: scanned.status === 'not-found'
|
|
64
|
+
? { status: 'ok', markdownBlocks: [], truncated: false }
|
|
65
|
+
: {
|
|
124
66
|
status: 'ok',
|
|
125
|
-
markdownBlocks: getConformingGroups(
|
|
126
|
-
truncated:
|
|
67
|
+
markdownBlocks: getConformingGroups(scanned.entries),
|
|
68
|
+
truncated: scanned.truncated,
|
|
127
69
|
};
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
catch (error) {
|
|
131
|
-
const diagnostic = errorMessage(error);
|
|
132
|
-
journal = { status: 'unreachable', diagnostic };
|
|
133
|
-
}
|
|
134
70
|
const report = reportFromLog(sessionId, options, journal);
|
|
135
71
|
if (journal.status === 'unreachable') {
|
|
136
72
|
const diagnostic = report.diagnostic
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# MCP server
|
|
2
|
+
|
|
3
|
+
`vouchington mcp` serves the [agent-blackboard](../README.md#validated-feedback-and-delivery)
|
|
4
|
+
journal operations to an agent over stdio (Model Context Protocol). An agent passes the markdown as
|
|
5
|
+
a tool argument; there is no temp file, `--file`, or replay command. The server builds on the
|
|
6
|
+
existing `vouchington-tooling/agent-blackboard` exports and adds no provider protocol.
|
|
7
|
+
|
|
8
|
+
Phase 1 of [vouchington-tooling#324](https://github.com/vouchington/vouchington-tooling/issues/324)
|
|
9
|
+
covers the journal, outbox, session, and snapshot tools below. Retrospective and pull request tools
|
|
10
|
+
are later phases.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
The server needs three packages next to `vouchington-tooling`. The last two are optional peer
|
|
15
|
+
dependencies, so nothing else in the CLI requires them:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm add -D vouchington-tooling agent-blackboard@^0.6.0
|
|
19
|
+
pnpm add -D @modelcontextprotocol/sdk zod
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`zod` is required by the SDK. When the SDK is missing, `vouchington mcp` writes a message naming the
|
|
23
|
+
package to stderr and exits with status 1. `agent-blackboard` is resolved from the validated
|
|
24
|
+
worktree at call time (`createRequire` on `<worktree>/package.json`), never from this package.
|
|
25
|
+
|
|
26
|
+
The connection comes from `AGENT_BLACKBOARD_URL` and `AGENT_BLACKBOARD_TOKEN` in the server's
|
|
27
|
+
environment. The server never searches for, prints, or mints them.
|
|
28
|
+
|
|
29
|
+
## Launch
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
vouchington mcp
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The command takes no arguments. Start it inside the repository's git worktree: that repository
|
|
36
|
+
defines which worktrees the tools accept. stdout carries only protocol frames, and diagnostics go
|
|
37
|
+
to stderr.
|
|
38
|
+
|
|
39
|
+
## Tools
|
|
40
|
+
|
|
41
|
+
Every tool takes an explicit `sessionId` (`^[A-Za-z0-9._:-]+$`, at most 256 characters) that the
|
|
42
|
+
server never infers, and an optional `worktree`. Unknown arguments are rejected. Failures come back
|
|
43
|
+
as MCP tool errors (`isError: true`) with an actionable message rather than crashing the server.
|
|
44
|
+
|
|
45
|
+
| Tool | Arguments besides `sessionId` and `worktree` | Returns |
|
|
46
|
+
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
|
|
47
|
+
| `journal_append` | `parentSessionId`, `agent`, `version`, `mode` (`interactive` or `autonomous`), `markdown`, `sourceEventId`, `workOutcome`, `repositories`, `feedbackCoverage`, optional `timestamp`, `category` | `sessionId`, `timestamp`, delivery `status` (`delivered` with a verified receipt, or `pending`) |
|
|
48
|
+
| `journal_entries` | none | `sessionId` and `entries`, every entry oldest first |
|
|
49
|
+
| `outbox_status` | none | `sessionId`, `status`, `pendingCount` |
|
|
50
|
+
| `outbox_flush` | none | `sessionId`, `status`, `pendingCount`, `deliveredCount` |
|
|
51
|
+
| `session_ensure` | `parentSessionId`, `agent`, `version` | `sessionId`, `status` (`created` or `exists`), `archived` |
|
|
52
|
+
| `snapshot_export` | optional `agent`, `version`, `parentSessionId`, `data`, `dataArrayContains`, `inactiveForHours` | `sessionId`, `path`, `counts`, `checksum`, `manifest`, `cleanupToken` |
|
|
53
|
+
| `session_archive` | none | `sessionId`, `archived: true` |
|
|
54
|
+
|
|
55
|
+
`journal_append` validates the whole feedback envelope with `validateFeedbackEnvelope` before
|
|
56
|
+
anything is written, so a missing required field writes nothing. It returns the verified read-back
|
|
57
|
+
result of `writeFeedback`. Delivery is at least once. The envelope includes its timestamp, so when
|
|
58
|
+
retrying the same `sourceEventId`, resend the same content and the `timestamp` the first call
|
|
59
|
+
returned; the server fixes a default timestamp and returns it for that reason. Markdown is limited
|
|
60
|
+
to 12000 bytes.
|
|
61
|
+
|
|
62
|
+
`journal_entries` returns `{ sessionId, entries }`. Each entry is exactly what the `agent-blackboard`
|
|
63
|
+
client returns (`sessionId`, `createdAt`, `data`), so `data` keeps its envelope fields such as
|
|
64
|
+
`repositories`, `sourceEventId`, `workOutcome`, and `feedbackCoverage`. Entries of every type come
|
|
65
|
+
back, including `retrospective` and legacy entries without an envelope. The client documents no
|
|
66
|
+
order, so they are sorted stably by `createdAt`, oldest first. An empty session returns
|
|
67
|
+
`entries: []`. `vouchington agent-blackboard journal entries` still prints journal markdown only.
|
|
68
|
+
|
|
69
|
+
`sessionId` on `outbox_status`, `outbox_flush`, and `snapshot_export` only identifies the caller.
|
|
70
|
+
The outbox is per worktree and the status and flush cover every record in it. Flushing an empty
|
|
71
|
+
outbox does not create the directory. `snapshot_export` never accepts a destination: the
|
|
72
|
+
`agent-blackboard` client chooses a private file and returns its path. `session_archive` is the one
|
|
73
|
+
destructive tool; archived metadata is immutable, while entries stay appendable.
|
|
74
|
+
|
|
75
|
+
The outbox lives at `<worktree>/.local/blackboard-outbox` and is used only in interactive mode.
|
|
76
|
+
Autonomous mode forbids a filesystem outbox, so a failed delivery is an error.
|
|
77
|
+
|
|
78
|
+
## Worktree validation
|
|
79
|
+
|
|
80
|
+
`worktree` must be an absolute path that, after resolving symlinks, exactly matches an entry of
|
|
81
|
+
`git worktree list --porcelain` for the repository the server was launched from. The list is read on
|
|
82
|
+
every call, so worktrees created after launch are accepted and removed ones are refused. Anything
|
|
83
|
+
else is rejected: a subdirectory of a worktree, a relative or nonexistent path, and a separate
|
|
84
|
+
repository, including one made with `git init` elsewhere. It defaults to the launch worktree's root.
|
|
85
|
+
Git runs without `GIT_*` variables, so `GIT_DIR` cannot redirect the check.
|
|
86
|
+
|
|
87
|
+
## Registering the server
|
|
88
|
+
|
|
89
|
+
The commands below run `vouchington` from the repository's own `node_modules`, so a fresh worktree
|
|
90
|
+
uses the version its lockfile pins. Set the blackboard credentials in the environment the harness
|
|
91
|
+
gives the server.
|
|
92
|
+
|
|
93
|
+
Claude Code, `.mcp.json`:
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"mcpServers": {
|
|
98
|
+
"vouchington-tooling": {
|
|
99
|
+
"command": "bash",
|
|
100
|
+
"args": ["-c", "exec \"$(git rev-parse --show-toplevel)/node_modules/.bin/vouchington\" mcp"]
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Codex, `.codex/config.toml`:
|
|
107
|
+
|
|
108
|
+
```toml
|
|
109
|
+
[mcp_servers.vouchington-tooling]
|
|
110
|
+
command = "bash"
|
|
111
|
+
args = ["-c", "exec \"$(git rev-parse --show-toplevel)/node_modules/.bin/vouchington\" mcp"]
|
|
112
|
+
default_tools_approval_mode = "approve"
|
|
113
|
+
required = false
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Approving every tool of the server at once:
|
|
117
|
+
|
|
118
|
+
- Claude Code permission rule: `mcp__vouchington-tooling__*`
|
|
119
|
+
- Cursor permission rule: `Mcp(vouchington-tooling:*)`
|
|
120
|
+
- Codex: `default_tools_approval_mode = "approve"` above
|
|
121
|
+
|
|
122
|
+
## What is verified
|
|
123
|
+
|
|
124
|
+
Covered by this package's tests: the tool list and schemas, every tool's success and rejection
|
|
125
|
+
paths against a faked blackboard client, the worktree gate against real temporary git repositories,
|
|
126
|
+
an in-process client and server round trip through the SDK's in-memory transport, and a spawned
|
|
127
|
+
`vouchington mcp` process driven over real stdio.
|
|
128
|
+
|
|
129
|
+
Not verified, and tracked as the unchecked Phase 0 checklist in
|
|
130
|
+
[#324](https://github.com/vouchington/vouchington-tooling/issues/324): each harness's approval
|
|
131
|
+
syntax and whether the rules above take effect, the working directory after entering a worktree,
|
|
132
|
+
environment interpolation and credential passing, `gh` authentication, behavior in a freshly
|
|
133
|
+
created worktree, and connectivity from automation. Treat the registration snippets and permission
|
|
134
|
+
rules as untested per harness until that checklist is complete.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vouchington-tooling",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
4
4
|
"description": "Vouchington CLI and extractable tooling libraries.",
|
|
5
5
|
"homepage": "https://github.com/vouchington/vouchington-tooling/tree/main/packages/vouchington-tooling#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -352,21 +352,26 @@
|
|
|
352
352
|
"picomatch": "4.0.7",
|
|
353
353
|
"remark": "15.0.1",
|
|
354
354
|
"remark-gfm": "4.0.1",
|
|
355
|
-
"smol-toml": "1.
|
|
355
|
+
"smol-toml": "1.9.0",
|
|
356
356
|
"spdx-expression-parse": "5.0.0",
|
|
357
357
|
"yaml": "2.9.1"
|
|
358
358
|
},
|
|
359
359
|
"devDependencies": {
|
|
360
360
|
"@ast-grep/cli": "0.45.3",
|
|
361
|
+
"@modelcontextprotocol/sdk": "1.31.0",
|
|
361
362
|
"@types/picomatch": "^4.0.3",
|
|
362
363
|
"@types/spdx-expression-parse": "4.0.0",
|
|
363
364
|
"agent-blackboard": "^0.6.0"
|
|
364
365
|
},
|
|
365
366
|
"peerDependencies": {
|
|
367
|
+
"@modelcontextprotocol/sdk": "^1.31.0",
|
|
366
368
|
"typescript": ">=5",
|
|
367
369
|
"vitest": ">=5"
|
|
368
370
|
},
|
|
369
371
|
"peerDependenciesMeta": {
|
|
372
|
+
"@modelcontextprotocol/sdk": {
|
|
373
|
+
"optional": true
|
|
374
|
+
},
|
|
370
375
|
"typescript": {
|
|
371
376
|
"optional": true
|
|
372
377
|
},
|
|
@@ -13,38 +13,75 @@ Use when the current repository provides a journal, blackboard, or equivalent du
|
|
|
13
13
|
record. Read local `AGENTS.md` for the provider, credential, retention, and
|
|
14
14
|
subagent-identity rules.
|
|
15
15
|
|
|
16
|
+
Journal operations are tools of the `vouchington-tooling` MCP server (`vouchington mcp`):
|
|
17
|
+
`journal_append`, `journal_entries`, `outbox_status`, `outbox_flush`, `session_ensure`,
|
|
18
|
+
`snapshot_export`, and `session_archive`. A harness may prefix the tool names with the server name.
|
|
19
|
+
Every call takes an exact `sessionId`, never inferred, whose meaning depends on the tool:
|
|
20
|
+
|
|
21
|
+
- `journal_append` and `session_ensure`: the session written or ensured, which is the caller's own
|
|
22
|
+
session unless a runner ensures a child identity.
|
|
23
|
+
- `journal_entries` and `session_archive`: the session read or archived, which during distillation
|
|
24
|
+
belongs to another agent.
|
|
25
|
+
- `snapshot_export`, `outbox_status`, and `outbox_flush`: only the caller. The outbox tools cover
|
|
26
|
+
every record in the worktree outbox, not only that session's.
|
|
27
|
+
|
|
28
|
+
Every call may take `worktree`, the absolute path of a worktree of the current repository (the
|
|
29
|
+
launch worktree by default). Writing or retrying an entry needs no provider skill, temporary file,
|
|
30
|
+
`--file` flag, or replay command.
|
|
31
|
+
If these tools are not available because the server is not registered or not connected, stop and
|
|
32
|
+
report that the journal server is unavailable. Do not fall back to a CLI command.
|
|
33
|
+
|
|
16
34
|
1. Capture consequential observations before filing an issue: failed or recovered checks, denied or
|
|
17
35
|
approved permissions, repeated fixes, scope changes, first-party tool behavior, and architectural
|
|
18
36
|
findings. Record useful resolved outcomes as well as unresolved gaps. Include bounded evidence,
|
|
19
37
|
affected areas, an explicit disposition, and an existing tracking reference when present.
|
|
20
38
|
Journal meaningful skips or bypasses of applicable configured workflows before completion, with
|
|
21
39
|
the owning workflow or command-catalog entrypoint, reason, and observed result/action.
|
|
22
|
-
2.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
40
|
+
2. Record each observation with one `journal_append` call and pass the note as its `markdown`
|
|
41
|
+
argument (at most 12000 bytes). Required arguments are `sessionId`, `parentSessionId` (null for a
|
|
42
|
+
root session), `agent`, `version`, `mode`, `markdown`, a stable `sourceEventId`, `workOutcome`,
|
|
43
|
+
canonical exact `repositories`, and explicit `feedbackCoverage`. Also pass an ISO 8601
|
|
44
|
+
`timestamp` fixed before the first attempt: the server otherwise generates one, and a failed or
|
|
45
|
+
timed-out call returns no result to learn it from. Nothing is written unless the
|
|
46
|
+
whole envelope validates. The tool writes journal entries; `category` is optional context and
|
|
47
|
+
never changes storage type or distillation eligibility. Generate routine facts and metadata
|
|
48
|
+
through the approved composer and pass its output as `markdown` instead of hand-authoring
|
|
49
|
+
factual markers. `journal_append` stores only journal entries: save a composed retrospective
|
|
50
|
+
through the retrospective skill's writer, never through `journal_append`.
|
|
26
51
|
3. Preserve exact provider session and parent identities. Each agent writes only its own session.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
52
|
+
`journal_append` ensures that session and merges the entry's `repositories` into the session's
|
|
53
|
+
cumulative repository union, so list every repository the entry concerns. Never infer another
|
|
54
|
+
repository from prose or create a child identity from a model guess. Call `session_ensure` with
|
|
55
|
+
the exact identity only when a runner must confirm the session before work starts.
|
|
56
|
+
4. Select the repository's trusted `mode` (`interactive` or `autonomous`) explicitly. In interactive
|
|
57
|
+
mode an outage may retain the validated, sanitized record in the bounded durable outbox, and
|
|
58
|
+
`journal_append` reports it as pending. Report the pending count from `outbox_status`, deliver
|
|
59
|
+
with `outbox_flush` once the provider is reachable, and continue primary work only after
|
|
60
|
+
persistence succeeds. A full, unsafe, or unwritable outbox blocks capture; never evict or
|
|
61
|
+
silently discard an unsent record.
|
|
62
|
+
5. Autonomous runners require online `session_ensure`, a fresh admission `journal_append`, and
|
|
63
|
+
readback before launching an attempt. Give each attempt's admission entry a `sourceEventId`
|
|
64
|
+
unique to that attempt: reusing an earlier one returns the earlier receipt, which does not
|
|
65
|
+
prove a fresh write. Autonomous mode has no filesystem outbox, so a failed delivery is an error.
|
|
66
|
+
Terminal reporting preserves work outcome separately from feedback coverage and delivery. A
|
|
67
|
+
filesystem outbox never grants admission or acknowledged completion.
|
|
68
|
+
6. Use at-least-once delivery with consumer deduplication by exact session/source identity. To
|
|
69
|
+
retry a pending or failed append, call `journal_append` again with the same `sourceEventId`,
|
|
70
|
+
content, and `timestamp` from the first attempt: the whole envelope must match, and conflicting
|
|
71
|
+
source reuse is rejected. A transport timeout can leave a late
|
|
72
|
+
durable write; pending or blocked is never an acknowledged receipt.
|
|
73
|
+
7. Read the session's entries oldest-first with `journal_entries` for retrospectives. It returns
|
|
74
|
+
every entry with its envelope, including its type and repository tags, so a retrospective can
|
|
75
|
+
find an existing retrospective and keep entry-level tags. Record explicit
|
|
76
|
+
none-observed with inspected scope, or not-assessed/unavailable with reason, when evidence does
|
|
77
|
+
not establish a finding. A permission request is not proof of approval or denial; localhost
|
|
78
|
+
refusal is not proof of sandbox enforcement. Mark partial capture and dropped counts instead of
|
|
79
|
+
reporting clean evidence.
|
|
43
80
|
|
|
44
81
|
Never search for, print, invent, or mint credentials. Durable entries and outbox records contain only
|
|
45
82
|
bounded structured facts or sanitized summaries, never raw command output, transcript content,
|
|
46
83
|
environment dumps, provider payloads, or secrets. Known-secret redaction supplements the author's
|
|
47
84
|
minimization responsibility; it cannot prove arbitrary prose contains no undisclosed secret.
|
|
48
85
|
|
|
49
|
-
Consumer wrappers own service configuration,
|
|
50
|
-
issue routing, and archival authorization.
|
|
86
|
+
Consumer wrappers own service configuration, server registration and approval rules, trusted mode
|
|
87
|
+
selection, issue routing, and archival authorization. The server fixes the outbox location.
|
package/skills/manifest.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
{
|
|
5
5
|
"name": "agent-workflow",
|
|
6
6
|
"plugin": "vouchington-workflow",
|
|
7
|
-
"pluginVersion": "0.
|
|
7
|
+
"pluginVersion": "0.10.0",
|
|
8
8
|
"path": "agent-workflow/SKILL.md",
|
|
9
9
|
"prerequisites": ["github-issue", "pr-description", "review-ci-logs"]
|
|
10
10
|
},
|
|
@@ -18,13 +18,13 @@
|
|
|
18
18
|
{
|
|
19
19
|
"name": "blackboard",
|
|
20
20
|
"plugin": "vouchington-workflow",
|
|
21
|
-
"pluginVersion": "0.
|
|
21
|
+
"pluginVersion": "0.10.0",
|
|
22
22
|
"path": "blackboard/SKILL.md"
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
25
|
"name": "dependabot",
|
|
26
26
|
"plugin": "vouchington-workflow",
|
|
27
|
-
"pluginVersion": "0.
|
|
27
|
+
"pluginVersion": "0.10.0",
|
|
28
28
|
"path": "dependabot/SKILL.md",
|
|
29
29
|
"prerequisites": ["github-actions-checklist"]
|
|
30
30
|
},
|
|
@@ -38,26 +38,26 @@
|
|
|
38
38
|
{
|
|
39
39
|
"name": "git-commit-checklist",
|
|
40
40
|
"plugin": "vouchington-workflow",
|
|
41
|
-
"pluginVersion": "0.
|
|
41
|
+
"pluginVersion": "0.10.0",
|
|
42
42
|
"path": "git-commit-checklist/SKILL.md"
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
45
|
"name": "github-actions-authoring",
|
|
46
46
|
"plugin": "vouchington-workflow",
|
|
47
|
-
"pluginVersion": "0.
|
|
47
|
+
"pluginVersion": "0.10.0",
|
|
48
48
|
"path": "github-actions-authoring/SKILL.md",
|
|
49
49
|
"prerequisites": ["github-actions-checklist"]
|
|
50
50
|
},
|
|
51
51
|
{
|
|
52
52
|
"name": "github-actions-checklist",
|
|
53
53
|
"plugin": "vouchington-workflow",
|
|
54
|
-
"pluginVersion": "0.
|
|
54
|
+
"pluginVersion": "0.10.0",
|
|
55
55
|
"path": "github-actions-checklist/SKILL.md"
|
|
56
56
|
},
|
|
57
57
|
{
|
|
58
58
|
"name": "github-issue",
|
|
59
59
|
"plugin": "vouchington-workflow",
|
|
60
|
-
"pluginVersion": "0.
|
|
60
|
+
"pluginVersion": "0.10.0",
|
|
61
61
|
"path": "github-issue/SKILL.md"
|
|
62
62
|
},
|
|
63
63
|
{
|
|
@@ -70,26 +70,26 @@
|
|
|
70
70
|
{
|
|
71
71
|
"name": "npm-publishing",
|
|
72
72
|
"plugin": "vouchington-workflow",
|
|
73
|
-
"pluginVersion": "0.
|
|
73
|
+
"pluginVersion": "0.10.0",
|
|
74
74
|
"path": "npm-publishing/SKILL.md"
|
|
75
75
|
},
|
|
76
76
|
{
|
|
77
77
|
"name": "organize-github-issues",
|
|
78
78
|
"plugin": "vouchington-workflow",
|
|
79
|
-
"pluginVersion": "0.
|
|
79
|
+
"pluginVersion": "0.10.0",
|
|
80
80
|
"path": "organize-github-issues/SKILL.md",
|
|
81
81
|
"prerequisites": ["github-issue"]
|
|
82
82
|
},
|
|
83
83
|
{
|
|
84
84
|
"name": "package-json-checklist",
|
|
85
85
|
"plugin": "vouchington-workflow",
|
|
86
|
-
"pluginVersion": "0.
|
|
86
|
+
"pluginVersion": "0.10.0",
|
|
87
87
|
"path": "package-json-checklist/SKILL.md"
|
|
88
88
|
},
|
|
89
89
|
{
|
|
90
90
|
"name": "planning",
|
|
91
91
|
"plugin": "vouchington-workflow",
|
|
92
|
-
"pluginVersion": "0.
|
|
92
|
+
"pluginVersion": "0.10.0",
|
|
93
93
|
"path": "planning/SKILL.md",
|
|
94
94
|
"prerequisites": ["github-issue"]
|
|
95
95
|
},
|
|
@@ -115,53 +115,53 @@
|
|
|
115
115
|
{
|
|
116
116
|
"name": "pr-description",
|
|
117
117
|
"plugin": "vouchington-workflow",
|
|
118
|
-
"pluginVersion": "0.
|
|
118
|
+
"pluginVersion": "0.10.0",
|
|
119
119
|
"path": "pr-description/SKILL.md"
|
|
120
120
|
},
|
|
121
121
|
{
|
|
122
122
|
"name": "retrospective",
|
|
123
123
|
"plugin": "vouchington-workflow",
|
|
124
|
-
"pluginVersion": "0.
|
|
124
|
+
"pluginVersion": "0.10.0",
|
|
125
125
|
"path": "retrospective/SKILL.md"
|
|
126
126
|
},
|
|
127
127
|
{
|
|
128
128
|
"name": "retrospective-distill",
|
|
129
129
|
"plugin": "vouchington-workflow",
|
|
130
|
-
"pluginVersion": "0.
|
|
130
|
+
"pluginVersion": "0.10.0",
|
|
131
131
|
"path": "retrospective-distill/SKILL.md",
|
|
132
132
|
"prerequisites": ["github-issue"]
|
|
133
133
|
},
|
|
134
134
|
{
|
|
135
135
|
"name": "review-ci-logs",
|
|
136
136
|
"plugin": "vouchington-workflow",
|
|
137
|
-
"pluginVersion": "0.
|
|
137
|
+
"pluginVersion": "0.10.0",
|
|
138
138
|
"path": "review-ci-logs/SKILL.md",
|
|
139
139
|
"prerequisites": ["github-actions-checklist", "pr-description"]
|
|
140
140
|
},
|
|
141
141
|
{
|
|
142
142
|
"name": "review-github-issue-taxonomy",
|
|
143
143
|
"plugin": "vouchington-workflow",
|
|
144
|
-
"pluginVersion": "0.
|
|
144
|
+
"pluginVersion": "0.10.0",
|
|
145
145
|
"path": "review-github-issue-taxonomy/SKILL.md",
|
|
146
146
|
"prerequisites": ["github-issue"]
|
|
147
147
|
},
|
|
148
148
|
{
|
|
149
149
|
"name": "revisit-followups",
|
|
150
150
|
"plugin": "vouchington-workflow",
|
|
151
|
-
"pluginVersion": "0.
|
|
151
|
+
"pluginVersion": "0.10.0",
|
|
152
152
|
"path": "revisit-followups/SKILL.md",
|
|
153
153
|
"prerequisites": ["github-issue"]
|
|
154
154
|
},
|
|
155
155
|
{
|
|
156
156
|
"name": "stacked-prs",
|
|
157
157
|
"plugin": "vouchington-workflow",
|
|
158
|
-
"pluginVersion": "0.
|
|
158
|
+
"pluginVersion": "0.10.0",
|
|
159
159
|
"path": "stacked-prs/SKILL.md"
|
|
160
160
|
},
|
|
161
161
|
{
|
|
162
162
|
"name": "static-analysis-checklist",
|
|
163
163
|
"plugin": "vouchington-workflow",
|
|
164
|
-
"pluginVersion": "0.
|
|
164
|
+
"pluginVersion": "0.10.0",
|
|
165
165
|
"path": "static-analysis-checklist/SKILL.md",
|
|
166
166
|
"prerequisites": ["github-actions-checklist"]
|
|
167
167
|
},
|
|
@@ -12,26 +12,48 @@ Local policy overrides these defaults; do not reload an already-read adapter or
|
|
|
12
12
|
Use when completed retrospectives or journals should become durable follow-up work. Read local
|
|
13
13
|
`AGENTS.md`, issue policy, and journal retention rules before any mutation.
|
|
14
14
|
|
|
15
|
-
1. Enumerate only completed, eligible session records
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
1. Enumerate only completed, eligible session records with the `snapshot_export` tool of the
|
|
16
|
+
`vouchington-tooling` MCP server, narrowing by `agent`, `version`, `parentSessionId`, exact
|
|
17
|
+
`data` fields, `dataArrayContains`, and `inactiveForHours`. It exports non-archived sessions to a
|
|
18
|
+
private local file and returns the path, counts, checksum, and manifest, never the records.
|
|
19
|
+
Before exporting, call `outbox_flush` and then `outbox_status` for every worktree that
|
|
20
|
+
`git worktree list` reports, passing each path as `worktree`, and stop if any still reports
|
|
21
|
+
pending records: an archived session refuses later delivery, so a retained record would never
|
|
22
|
+
be distilled. Outboxes in removed worktrees or on other machines cannot be drained this way, so
|
|
23
|
+
select with `inactiveForHours` to give them time to deliver. Leave in-progress sessions intact.
|
|
24
|
+
If the server is not connected, stop and report it; do not fall back to a CLI command.
|
|
25
|
+
2. Before using any record, verify the file against the returned checksum, counts, and terminal
|
|
26
|
+
manifest with the consumer's approved snapshot reader, and stop on a mismatch rather than
|
|
27
|
+
treating missing records as absent. Read full records, with their storage type, repository
|
|
28
|
+
tags, source identity, coverage, and outcomes, from that file. Do not distill from
|
|
29
|
+
`journal_entries`: it reads one session at a time and has no checksum or manifest to show that
|
|
30
|
+
the read is complete. For repository-scoped work, filter sessions by
|
|
31
|
+
repository membership (`dataArrayContains` with `repositories` and the exact `owner/name`) and
|
|
32
|
+
use only entries attributed to that repository. Leave untagged legacy records unclassified. Do
|
|
33
|
+
not infer their repository.
|
|
34
|
+
3. Validate storage type and the shared envelope independently of optional category. Never repair
|
|
19
35
|
unknown legacy types or repository provenance by inference. Quarantine malformed sessions with
|
|
20
36
|
an explicit reason while processing valid unrelated sessions. Deduplicate at-least-once records
|
|
21
37
|
by exact session/source identity and reject conflicting duplicate content. Retain coverage,
|
|
22
38
|
dropped counts, requested versus observed outcomes, and useful resolved findings.
|
|
23
|
-
|
|
39
|
+
4. Cluster findings by root cause. Prefer a few broad actionable themes over many narrow issues.
|
|
24
40
|
Treat a finding already linked to an open tracker as context, not a duplicate.
|
|
25
|
-
|
|
41
|
+
5. Verify each candidate against the current base. Search existing issues and open changes before
|
|
26
42
|
drafting. Skip work that is complete, explicitly rejected, or already covered. A first-party version
|
|
27
43
|
bump is not proof of resolution: verify the adopted change against the original finding before
|
|
28
44
|
deferring. Capture a new observation in the journal before filing it.
|
|
29
|
-
|
|
45
|
+
6. Draft self-contained issues with the problem, concrete proposed work, relevant areas, and
|
|
30
46
|
validation. Route every authorized creation through
|
|
31
47
|
[github-issue](../github-issue/SKILL.md), including its repository gate, label approval, and
|
|
32
48
|
denied-external tracking behavior.
|
|
33
|
-
|
|
34
|
-
|
|
49
|
+
7. Archive only verified records fully processed across every represented repository, and never
|
|
50
|
+
while any worktree's `outbox_status` reports pending records, under the repository's retention
|
|
51
|
+
rules. Make one `session_archive` call per session, whose `sessionId` is the archived session,
|
|
52
|
+
not the caller. Immediately before each call, read that session with `journal_entries` and
|
|
53
|
+
archive only if its entries match the verified snapshot's by source identity; otherwise leave it
|
|
54
|
+
for the next pass, because an entry added after the export would never be distilled.
|
|
55
|
+
Archiving makes the session's metadata immutable, so it needs the archival authorization that
|
|
56
|
+
local policy requires. A one-repository pass leaves a multi-repository session active until the other
|
|
35
57
|
repositories are reviewed. Report reviewed, fixed, duplicate, deferred, quarantined, and
|
|
36
58
|
actionable dispositions with reasons. Keep the top five themes in human prose without dropping
|
|
37
59
|
underlying findings or unresolved records.
|
|
@@ -40,8 +62,10 @@ Use source records only for local verification and leave them in the repository'
|
|
|
40
62
|
or retention system. Public issue bodies contain only the minimum bounded facts or redacted
|
|
41
63
|
summaries needed to establish the problem, proposed work, relevant areas, and validation. Never
|
|
42
64
|
embed unredacted logs, command output, environment details, provider payloads, or transcript
|
|
43
|
-
content.
|
|
65
|
+
content. A snapshot file is a private local copy of source records: never commit or attach it, or
|
|
66
|
+
copy its contents into an issue.
|
|
44
67
|
|
|
45
|
-
This skill supplies no
|
|
46
|
-
|
|
47
|
-
|
|
68
|
+
This skill supplies no issue repository, labels, milestones, projects, or approval model; it reads
|
|
69
|
+
sessions only from the snapshot file that `snapshot_export` writes, and archives them only with
|
|
70
|
+
`session_archive`. Consumer wrappers cannot weaken this export
|
|
71
|
+
boundary; they provide only those local details.
|