@gramatr/opencode-plugin 0.20.76
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/LICENSE +85 -0
- package/dist/index.d.ts +67 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +240 -0
- package/dist/index.js.map +1 -0
- package/package.json +52 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
Gramatr License v1.0
|
|
2
|
+
|
|
3
|
+
Copyright (c) gramatr. All rights reserved.
|
|
4
|
+
|
|
5
|
+
1. License grant
|
|
6
|
+
|
|
7
|
+
Subject to the terms of this license, gramatr grants you a limited, revocable,
|
|
8
|
+
non-exclusive, non-transferable, non-sublicensable license to install and use
|
|
9
|
+
the gramatr client software solely as a client for authorized gramatr services.
|
|
10
|
+
|
|
11
|
+
2. Permitted use
|
|
12
|
+
|
|
13
|
+
You may:
|
|
14
|
+
- install and use the client software for personal or internal business use;
|
|
15
|
+
- connect the software to gramatr-hosted services or other gramatr-authorized
|
|
16
|
+
service endpoints;
|
|
17
|
+
- make copies only as necessary for backup, installation, and normal use.
|
|
18
|
+
|
|
19
|
+
3. Restrictions
|
|
20
|
+
|
|
21
|
+
You may not:
|
|
22
|
+
- sell, sublicense, rent, lease, distribute, publish, or otherwise make the
|
|
23
|
+
software available to third parties as a standalone product;
|
|
24
|
+
- modify, create derivative works of, reverse engineer, decompile, or
|
|
25
|
+
disassemble the software, except to the limited extent such restriction is
|
|
26
|
+
prohibited by applicable law;
|
|
27
|
+
- use the software to access or operate an unauthorized competing hosted
|
|
28
|
+
service based on gramatr technology;
|
|
29
|
+
- remove or alter any proprietary notices, trademarks, or attribution;
|
|
30
|
+
- use the software in violation of applicable law or the gramatr service terms.
|
|
31
|
+
|
|
32
|
+
4. Server and service components
|
|
33
|
+
|
|
34
|
+
The server-side components of this repository (including but not limited to the
|
|
35
|
+
intelligence layer, persistence layer, gateway, and MCP server) are proprietary
|
|
36
|
+
and confidential. No license is granted for hosting, deploying, or operating the
|
|
37
|
+
server components outside of gramatr-authorized infrastructure.
|
|
38
|
+
|
|
39
|
+
5. Service dependency
|
|
40
|
+
|
|
41
|
+
The client software is intended to be used with authenticated gramatr backend
|
|
42
|
+
services. Access to those services may require an account, API key, accepted
|
|
43
|
+
terms, and an active subscription or other authorization. gramatr may change,
|
|
44
|
+
suspend, or discontinue service access in accordance with applicable service
|
|
45
|
+
terms.
|
|
46
|
+
|
|
47
|
+
6. Ownership
|
|
48
|
+
|
|
49
|
+
The software is licensed, not sold. gramatr and its licensors retain all
|
|
50
|
+
right, title, and interest in and to the software, including all intellectual
|
|
51
|
+
property rights.
|
|
52
|
+
|
|
53
|
+
7. Updates
|
|
54
|
+
|
|
55
|
+
gramatr may provide updates, patches, or new versions under this same license
|
|
56
|
+
or under updated license terms. Continued use of an updated version constitutes
|
|
57
|
+
acceptance of the updated terms if they are presented to you.
|
|
58
|
+
|
|
59
|
+
8. Termination
|
|
60
|
+
|
|
61
|
+
This license terminates automatically if you violate these terms. Upon
|
|
62
|
+
termination, you must stop using the software and delete all copies in your
|
|
63
|
+
possession or control.
|
|
64
|
+
|
|
65
|
+
9. Disclaimer
|
|
66
|
+
|
|
67
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND "AS AVAILABLE," WITHOUT WARRANTIES OF ANY
|
|
68
|
+
KIND, WHETHER EXPRESS, IMPLIED, OR STATUTORY, INCLUDING IMPLIED WARRANTIES OF
|
|
69
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT,
|
|
70
|
+
TO THE MAXIMUM EXTENT PERMITTED BY LAW.
|
|
71
|
+
|
|
72
|
+
10. Limitation of liability
|
|
73
|
+
|
|
74
|
+
TO THE MAXIMUM EXTENT PERMITTED BY LAW, GRAMATR WILL NOT BE LIABLE FOR ANY
|
|
75
|
+
INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, EXEMPLARY, OR PUNITIVE DAMAGES,
|
|
76
|
+
OR FOR ANY LOSS OF DATA, REVENUE, PROFITS, GOODWILL, OR BUSINESS INTERRUPTION,
|
|
77
|
+
ARISING OUT OF OR RELATED TO THE SOFTWARE OR ITS USE, EVEN IF ADVISED OF THE
|
|
78
|
+
POSSIBILITY OF SUCH DAMAGES.
|
|
79
|
+
|
|
80
|
+
11. Governing terms
|
|
81
|
+
|
|
82
|
+
Use of the gramatr backend service is governed separately by gramatr Terms of
|
|
83
|
+
Service and Privacy Policy. If there is a conflict between this license and the
|
|
84
|
+
service terms with respect to backend service use, the service terms control
|
|
85
|
+
for backend access and service behavior.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @gramatr/opencode-plugin — grāmatr lifecycle plugin for OpenCode
|
|
3
|
+
*
|
|
4
|
+
* DESIGN: Connector model — no execSync, no local gramatr-hook binary.
|
|
5
|
+
*
|
|
6
|
+
* This plugin uses the plugin context's `client` object to call grāmatr MCP
|
|
7
|
+
* tools directly on the already-connected remote MCP server
|
|
8
|
+
* (https://api.gramatr.com/mcp, declared in the opencode.json `mcp` block).
|
|
9
|
+
*
|
|
10
|
+
* OpenCode's plugin `client` API is not yet publicly typed for arbitrary MCP
|
|
11
|
+
* tool invocation beyond `client.session.prompt`. The MCP tool call path
|
|
12
|
+
* (client.callTool / client.mcp.call or similar) is not part of the current
|
|
13
|
+
* @opencode-ai/plugin public surface. As a result:
|
|
14
|
+
*
|
|
15
|
+
* - session.created → calls load_handoff via client.session.prompt injection
|
|
16
|
+
* (the guidance text from the handoff is prepended as a
|
|
17
|
+
* noReply system message so the model sees it on the
|
|
18
|
+
* first turn).
|
|
19
|
+
* - message.updated → calls route_request via client.session.prompt injection
|
|
20
|
+
* (returned intelligence contract prepended as noReply).
|
|
21
|
+
* - tool.execute.before → best-effort git-gate: if client exposes a callTool
|
|
22
|
+
* method, blocks bash/shell tool calls that match the
|
|
23
|
+
* gramatr git-gate patterns; otherwise omitted gracefully.
|
|
24
|
+
* - session.idle / session.compacted → calls classification_feedback /
|
|
25
|
+
* save_reflection via the same prompt-injection path.
|
|
26
|
+
*
|
|
27
|
+
* When @opencode-ai/plugin exposes a typed MCP tool call API, this connector
|
|
28
|
+
* should be updated to call route_request, session_bootstrap, load_handoff,
|
|
29
|
+
* save_handoff, classification_feedback, and save_reflection as direct tool
|
|
30
|
+
* invocations rather than prompt injections — eliminating the noReply overhead.
|
|
31
|
+
*
|
|
32
|
+
* Source-of-truth manifest: contracts/mcp/opencode-plugin-manifest.yaml
|
|
33
|
+
*/
|
|
34
|
+
export type PluginEventHandler = (event: unknown) => Promise<void>;
|
|
35
|
+
export type ToolExecuteBeforeHandler = (input: unknown, output: unknown) => Promise<void>;
|
|
36
|
+
export type ToolExecuteAfterHandler = (input: unknown, output: unknown) => Promise<void>;
|
|
37
|
+
export type CompactingHandler = (input: unknown, output: unknown) => Promise<void>;
|
|
38
|
+
export interface PluginHandlers {
|
|
39
|
+
'session.created'?: PluginEventHandler;
|
|
40
|
+
'message.updated'?: PluginEventHandler;
|
|
41
|
+
'tool.execute.before'?: ToolExecuteBeforeHandler;
|
|
42
|
+
'tool.execute.after'?: ToolExecuteAfterHandler;
|
|
43
|
+
'session.idle'?: PluginEventHandler;
|
|
44
|
+
'session.compacted'?: PluginEventHandler;
|
|
45
|
+
'experimental.session.compacting'?: CompactingHandler;
|
|
46
|
+
[key: string]: unknown;
|
|
47
|
+
}
|
|
48
|
+
export type Plugin = (context: {
|
|
49
|
+
project: unknown;
|
|
50
|
+
client: unknown;
|
|
51
|
+
directory: string;
|
|
52
|
+
}) => Promise<PluginHandlers>;
|
|
53
|
+
/**
|
|
54
|
+
* GramatrPlugin — grāmatr lifecycle plugin for OpenCode.
|
|
55
|
+
*
|
|
56
|
+
* Uses the CONNECTOR model: all grāmatr hooks are invoked via the remote MCP
|
|
57
|
+
* server already connected to OpenCode (declared in opencode.json), not via
|
|
58
|
+
* a local binary. The plugin injects grāmatr guidance as noReply messages
|
|
59
|
+
* into the active session, which the model receives before it formulates its
|
|
60
|
+
* next response.
|
|
61
|
+
*
|
|
62
|
+
* Install: add "@gramatr/opencode-plugin" to the opencode.json `plugin` array.
|
|
63
|
+
* Also add the MCP remote connector to opencode.json `mcp`:
|
|
64
|
+
* { "gramatr": { "type": "remote", "url": "https://api.gramatr.com/mcp", "enabled": true } }
|
|
65
|
+
*/
|
|
66
|
+
export declare const GramatrPlugin: Plugin;
|
|
67
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAQH,MAAM,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AACnE,MAAM,MAAM,wBAAwB,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAC1F,MAAM,MAAM,uBAAuB,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AACzF,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnF,MAAM,WAAW,cAAc;IAC7B,iBAAiB,CAAC,EAAE,kBAAkB,CAAC;IACvC,iBAAiB,CAAC,EAAE,kBAAkB,CAAC;IACvC,qBAAqB,CAAC,EAAE,wBAAwB,CAAC;IACjD,oBAAoB,CAAC,EAAE,uBAAuB,CAAC;IAC/C,cAAc,CAAC,EAAE,kBAAkB,CAAC;IACpC,mBAAmB,CAAC,EAAE,kBAAkB,CAAC;IACzC,iCAAiC,CAAC,EAAE,iBAAiB,CAAC;IACtD,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;AAwD9B;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,aAAa,EAAE,MAiL3B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @gramatr/opencode-plugin — grāmatr lifecycle plugin for OpenCode
|
|
3
|
+
*
|
|
4
|
+
* DESIGN: Connector model — no execSync, no local gramatr-hook binary.
|
|
5
|
+
*
|
|
6
|
+
* This plugin uses the plugin context's `client` object to call grāmatr MCP
|
|
7
|
+
* tools directly on the already-connected remote MCP server
|
|
8
|
+
* (https://api.gramatr.com/mcp, declared in the opencode.json `mcp` block).
|
|
9
|
+
*
|
|
10
|
+
* OpenCode's plugin `client` API is not yet publicly typed for arbitrary MCP
|
|
11
|
+
* tool invocation beyond `client.session.prompt`. The MCP tool call path
|
|
12
|
+
* (client.callTool / client.mcp.call or similar) is not part of the current
|
|
13
|
+
* @opencode-ai/plugin public surface. As a result:
|
|
14
|
+
*
|
|
15
|
+
* - session.created → calls load_handoff via client.session.prompt injection
|
|
16
|
+
* (the guidance text from the handoff is prepended as a
|
|
17
|
+
* noReply system message so the model sees it on the
|
|
18
|
+
* first turn).
|
|
19
|
+
* - message.updated → calls route_request via client.session.prompt injection
|
|
20
|
+
* (returned intelligence contract prepended as noReply).
|
|
21
|
+
* - tool.execute.before → best-effort git-gate: if client exposes a callTool
|
|
22
|
+
* method, blocks bash/shell tool calls that match the
|
|
23
|
+
* gramatr git-gate patterns; otherwise omitted gracefully.
|
|
24
|
+
* - session.idle / session.compacted → calls classification_feedback /
|
|
25
|
+
* save_reflection via the same prompt-injection path.
|
|
26
|
+
*
|
|
27
|
+
* When @opencode-ai/plugin exposes a typed MCP tool call API, this connector
|
|
28
|
+
* should be updated to call route_request, session_bootstrap, load_handoff,
|
|
29
|
+
* save_handoff, classification_feedback, and save_reflection as direct tool
|
|
30
|
+
* invocations rather than prompt injections — eliminating the noReply overhead.
|
|
31
|
+
*
|
|
32
|
+
* Source-of-truth manifest: contracts/mcp/opencode-plugin-manifest.yaml
|
|
33
|
+
*/
|
|
34
|
+
/** Narrowing guard — checks if `client` exposes the session.prompt API. */
|
|
35
|
+
function hasSessionPrompt(client) {
|
|
36
|
+
return (typeof client === 'object' &&
|
|
37
|
+
client !== null &&
|
|
38
|
+
'session' in client &&
|
|
39
|
+
typeof client.session === 'object' &&
|
|
40
|
+
client.session !== null &&
|
|
41
|
+
'prompt' in client.session &&
|
|
42
|
+
typeof client.session.prompt === 'function');
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Inject a noReply message into the current session so the model sees the
|
|
46
|
+
* guidance text before it responds. Silently drops if client API is absent.
|
|
47
|
+
*/
|
|
48
|
+
async function injectGuidance(client, sessionId, text) {
|
|
49
|
+
if (!text || text === '{}')
|
|
50
|
+
return;
|
|
51
|
+
if (!hasSessionPrompt(client)) {
|
|
52
|
+
process.stderr.write('[gramatr] client.session.prompt not available — skipping injection\n');
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
await client.session.prompt({
|
|
57
|
+
path: { id: sessionId },
|
|
58
|
+
body: { noReply: true, parts: [{ type: 'text', text }] },
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
63
|
+
process.stderr.write(`[gramatr] injection failed: ${msg}\n`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// ── GramatrPlugin ─────────────────────────────────────────────────────────────
|
|
67
|
+
/**
|
|
68
|
+
* GramatrPlugin — grāmatr lifecycle plugin for OpenCode.
|
|
69
|
+
*
|
|
70
|
+
* Uses the CONNECTOR model: all grāmatr hooks are invoked via the remote MCP
|
|
71
|
+
* server already connected to OpenCode (declared in opencode.json), not via
|
|
72
|
+
* a local binary. The plugin injects grāmatr guidance as noReply messages
|
|
73
|
+
* into the active session, which the model receives before it formulates its
|
|
74
|
+
* next response.
|
|
75
|
+
*
|
|
76
|
+
* Install: add "@gramatr/opencode-plugin" to the opencode.json `plugin` array.
|
|
77
|
+
* Also add the MCP remote connector to opencode.json `mcp`:
|
|
78
|
+
* { "gramatr": { "type": "remote", "url": "https://api.gramatr.com/mcp", "enabled": true } }
|
|
79
|
+
*/
|
|
80
|
+
export const GramatrPlugin = async ({ project, client, directory }) => {
|
|
81
|
+
let sessionId = 'unknown';
|
|
82
|
+
const seenMessageIds = new Set();
|
|
83
|
+
return {
|
|
84
|
+
// ── session.created ───────────────────────────────────────────────────────
|
|
85
|
+
// Load the previous session's handoff so the model has continuity context
|
|
86
|
+
// from the first turn. Injected as a noReply message before any user input.
|
|
87
|
+
'session.created': async (event) => {
|
|
88
|
+
const evt = event;
|
|
89
|
+
sessionId = evt.sessionId ?? 'unknown';
|
|
90
|
+
const projectDir = project?.dir ?? directory ?? '';
|
|
91
|
+
// Guidance to the model: call load_handoff + session_bootstrap on first turn.
|
|
92
|
+
// We cannot call the MCP tool directly here because @opencode-ai/plugin
|
|
93
|
+
// does not yet expose a typed client.callTool() method. Instead, we inject
|
|
94
|
+
// an instruction block that the model executes on its first non-noReply turn.
|
|
95
|
+
//
|
|
96
|
+
// When @opencode-ai/plugin adds client.callTool support, replace this with:
|
|
97
|
+
// await client.callTool('load_handoff', { session_id: sessionId, project_dir: projectDir });
|
|
98
|
+
const handoffGuidance = [
|
|
99
|
+
'## grāmatr session started',
|
|
100
|
+
'',
|
|
101
|
+
`Session ID: ${sessionId}`,
|
|
102
|
+
`Project dir: ${projectDir}`,
|
|
103
|
+
'',
|
|
104
|
+
'Call `load_handoff` to restore context from the previous session, then',
|
|
105
|
+
'`session_bootstrap` to initialize this session. Follow the returned',
|
|
106
|
+
'intelligence contract for effort gating, quality gates, and directives.',
|
|
107
|
+
].join('\n');
|
|
108
|
+
await injectGuidance(client, sessionId, handoffGuidance);
|
|
109
|
+
},
|
|
110
|
+
// ── message.updated ───────────────────────────────────────────────────────
|
|
111
|
+
// On each user message, call route_request to inject the grāmatr intelligence
|
|
112
|
+
// contract (classification, behavioral directives, quality gates, memory).
|
|
113
|
+
// De-duplicated by message ID so repeated update events don't double-inject.
|
|
114
|
+
'message.updated': async (event) => {
|
|
115
|
+
const evt = event;
|
|
116
|
+
if (evt.properties?.role !== 'user')
|
|
117
|
+
return;
|
|
118
|
+
const msgId = evt.properties?.id;
|
|
119
|
+
if (msgId) {
|
|
120
|
+
if (seenMessageIds.has(msgId))
|
|
121
|
+
return;
|
|
122
|
+
seenMessageIds.add(msgId);
|
|
123
|
+
}
|
|
124
|
+
const parts = evt.properties?.parts ?? [];
|
|
125
|
+
const messageText = parts
|
|
126
|
+
.filter((p) => p.type === 'text')
|
|
127
|
+
.map((p) => p.text ?? '')
|
|
128
|
+
.join('\n')
|
|
129
|
+
.trim();
|
|
130
|
+
if (!messageText)
|
|
131
|
+
return;
|
|
132
|
+
// Inject route_request guidance as a noReply message.
|
|
133
|
+
// When @opencode-ai/plugin adds client.callTool support, replace this block with:
|
|
134
|
+
// const packet = await client.callTool('route_request', { prompt: messageText, session_id: sessionId });
|
|
135
|
+
// await injectGuidance(client, sessionId, JSON.stringify(packet));
|
|
136
|
+
const routeGuidance = [
|
|
137
|
+
'## grāmatr intelligence contract',
|
|
138
|
+
'',
|
|
139
|
+
`Call \`route_request\` with the following prompt before responding:`,
|
|
140
|
+
'',
|
|
141
|
+
'```',
|
|
142
|
+
messageText.slice(0, 500),
|
|
143
|
+
messageText.length > 500 ? '...' : '',
|
|
144
|
+
'```',
|
|
145
|
+
'',
|
|
146
|
+
'Follow the returned gmtr.intelligence.contract.v2 packet: classification,',
|
|
147
|
+
'directives.hard_gates, directives.behavioral_rules, process.phase_template,',
|
|
148
|
+
'and process.quality_gate_config. Create quality gate criteria before building.',
|
|
149
|
+
].join('\n');
|
|
150
|
+
await injectGuidance(client, sessionId, routeGuidance);
|
|
151
|
+
},
|
|
152
|
+
// ── tool.execute.before ───────────────────────────────────────────────────
|
|
153
|
+
// Best-effort git-gate: block bash/shell commands that destructively modify
|
|
154
|
+
// git history (force-push to main, reset --hard, etc.). This mirrors the
|
|
155
|
+
// gramatr hard gates for agent code work.
|
|
156
|
+
//
|
|
157
|
+
// NOTE: @opencode-ai/plugin does not yet expose client.callTool(), so this
|
|
158
|
+
// cannot invoke the server-side git-gate tool. The check below is local-only
|
|
159
|
+
// and covers the most critical patterns. When client.callTool() is available,
|
|
160
|
+
// delegate to the `git-gate` grāmatr MCP tool instead.
|
|
161
|
+
'tool.execute.before': async (input, _output) => {
|
|
162
|
+
const inp = input;
|
|
163
|
+
const toolName = inp.tool ?? '';
|
|
164
|
+
const toolArgs = inp.args ?? {};
|
|
165
|
+
if (toolName === 'bash' || toolName === 'shell') {
|
|
166
|
+
const cmd = typeof toolArgs['command'] === 'string' ? toolArgs['command'] : '';
|
|
167
|
+
// Hard gate: never force-push to main/master. Mirror of gramatr git-gate rule.
|
|
168
|
+
if (/git\s+push\s+.*--force/.test(cmd) && /\b(main|master)\b/.test(cmd)) {
|
|
169
|
+
// gramatr-allow: B1 — published plugin, no @gramatr/core error classes available
|
|
170
|
+
throw new Error('[gramatr] Blocked: force-push to main/master is forbidden. ' +
|
|
171
|
+
'Create a PR instead (gramatr hard gate: no direct force-push to protected branches).');
|
|
172
|
+
}
|
|
173
|
+
// Hard gate: never reset --hard on a tracking branch without explicit confirmation.
|
|
174
|
+
if (/git\s+reset\s+--hard/.test(cmd) && /origin\//.test(cmd)) {
|
|
175
|
+
// gramatr-allow: B1 — published plugin, no @gramatr/core error classes available
|
|
176
|
+
throw new Error('[gramatr] Blocked: `git reset --hard origin/...` discards local work. ' +
|
|
177
|
+
'Use a branch or stash first (gramatr hard gate).');
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
// ── tool.execute.after ────────────────────────────────────────────────────
|
|
182
|
+
// No-op in the connector model. When client.callTool() is available, call
|
|
183
|
+
// `tool-tracker` for gramatr tools to log tool usage into the flywheel.
|
|
184
|
+
'tool.execute.after': async (_input, _output) => {
|
|
185
|
+
// Reserved for tool-tracker integration once client.callTool() is exposed.
|
|
186
|
+
},
|
|
187
|
+
// ── session.idle ──────────────────────────────────────────────────────────
|
|
188
|
+
// When the session goes idle, inject a prompt reminding the model to submit
|
|
189
|
+
// classification_feedback and save_reflection to close the training flywheel.
|
|
190
|
+
'session.idle': async (_event) => {
|
|
191
|
+
const idleGuidance = [
|
|
192
|
+
'## grāmatr session idle',
|
|
193
|
+
'',
|
|
194
|
+
'Before ending the session, call:',
|
|
195
|
+
'1. `classification_feedback` — records whether the effort/intent classification was correct.',
|
|
196
|
+
'2. `save_reflection` — captures what worked, what did not, and what a smarter AI would do differently.',
|
|
197
|
+
'3. `save_handoff` — persists session state for the next session.',
|
|
198
|
+
'',
|
|
199
|
+
'These three calls close the grāmatr training flywheel.',
|
|
200
|
+
].join('\n');
|
|
201
|
+
await injectGuidance(client, sessionId, idleGuidance);
|
|
202
|
+
},
|
|
203
|
+
// ── session.compacted ─────────────────────────────────────────────────────
|
|
204
|
+
// After compaction, remind the model to reinitialize the grāmatr contract.
|
|
205
|
+
'session.compacted': async (_event) => {
|
|
206
|
+
const compactedGuidance = [
|
|
207
|
+
'## grāmatr post-compaction',
|
|
208
|
+
'',
|
|
209
|
+
'The context window was just compacted. Resume the grāmatr intelligence contract:',
|
|
210
|
+
'- Call `session_bootstrap` to reinitialize session state.',
|
|
211
|
+
'- Retain the active session_id and project_id across compaction.',
|
|
212
|
+
'- Re-apply any open quality gate criteria from before compaction.',
|
|
213
|
+
].join('\n');
|
|
214
|
+
await injectGuidance(client, sessionId, compactedGuidance);
|
|
215
|
+
},
|
|
216
|
+
// ── experimental.session.compacting ───────────────────────────────────────
|
|
217
|
+
// Augment the compaction summary with grāmatr continuity instructions so
|
|
218
|
+
// the compacted context preserves session state references.
|
|
219
|
+
'experimental.session.compacting': async (_input, output) => {
|
|
220
|
+
const out = output;
|
|
221
|
+
const continuationBlock = [
|
|
222
|
+
'',
|
|
223
|
+
'## grāmatr session continuity (preserve across compaction)',
|
|
224
|
+
'- Active session_id and project_id — do not reset',
|
|
225
|
+
'- Open tasks and their statuses (open/in_progress/blocked/review)',
|
|
226
|
+
'- Recent decisions and their rationale',
|
|
227
|
+
'- Classification feedback state for the current session',
|
|
228
|
+
'- Any pending quality gate criteria not yet verified',
|
|
229
|
+
'Resume the grāmatr intelligence contract (gmtr.intelligence.contract.v2) on next turn.',
|
|
230
|
+
].join('\n');
|
|
231
|
+
if (typeof out.context === 'string') {
|
|
232
|
+
out.context += continuationBlock;
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
out.context = continuationBlock;
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
};
|
|
239
|
+
};
|
|
240
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gramatr/opencode-plugin",
|
|
3
|
+
"version": "0.20.76",
|
|
4
|
+
"description": "grāmatr lifecycle plugin for OpenCode — maps OpenCode plugin events to grāmatr hooks via the connected MCP client (route_request injection, session continuity, git-gate).",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/gramatr/gramatr.git"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://gramatr.com",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/gramatr/gramatr/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"opencode",
|
|
19
|
+
"mcp",
|
|
20
|
+
"intelligence",
|
|
21
|
+
"routing",
|
|
22
|
+
"context",
|
|
23
|
+
"gramatr"
|
|
24
|
+
],
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=22"
|
|
27
|
+
},
|
|
28
|
+
"type": "module",
|
|
29
|
+
"main": "./dist/index.js",
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"import": "./dist/index.js",
|
|
33
|
+
"types": "./dist/index.d.ts"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"types": "./dist/index.d.ts",
|
|
37
|
+
"files": [
|
|
38
|
+
"dist"
|
|
39
|
+
],
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"@opencode-ai/plugin": ">=1.0.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@opencode-ai/plugin": "^1.0.0",
|
|
45
|
+
"@types/node": "^22.0.0",
|
|
46
|
+
"typescript": "^5.9.3"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsc -p tsconfig.json",
|
|
50
|
+
"clean": "rm -rf dist"
|
|
51
|
+
}
|
|
52
|
+
}
|