@mnmal-ai/cortext-opencode 1.0.0-alpha.7 → 1.0.0-alpha.8
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
CHANGED
|
@@ -18,7 +18,7 @@ OpenCode 1.x compat).
|
|
|
18
18
|
"$schema": "https://opencode.ai/config.json",
|
|
19
19
|
"plugins": [
|
|
20
20
|
{
|
|
21
|
-
"package": "@mnmal-ai/cortext-opencode",
|
|
21
|
+
"package": "@mnmal-ai/cortext-opencode@next",
|
|
22
22
|
"options": {
|
|
23
23
|
"kid": "synoptic-opencode@YourHost",
|
|
24
24
|
"key": "/home/you/.config/substrate/keys/synoptic-opencode.key"
|
|
@@ -28,7 +28,7 @@ OpenCode 1.x compat).
|
|
|
28
28
|
}
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
The plain string form (`"plugins": ["@mnmal-ai/cortext-opencode"]`) also
|
|
31
|
+
The plain string form (`"plugins": ["@mnmal-ai/cortext-opencode@next"]`) also
|
|
32
32
|
works — identity then comes from the env pair. **Keep exactly one entry
|
|
33
33
|
per package**: as of opencode v2.0.24 the `plugins`
|
|
34
34
|
arrays concatenate across global + project config and loads dedupe only
|
|
@@ -40,7 +40,7 @@ OpenCode 1.x compat).
|
|
|
40
40
|
public on npmjs.com, as is the `@mnmal-ai/substrate` dep; no token needed.
|
|
41
41
|
|
|
42
42
|
2. MCP server — merge into the same `opencode.json` (see
|
|
43
|
-
`
|
|
43
|
+
`skills/substrate-setup/SKILL.md` Step 4 for the full procedure). **The MCP server
|
|
44
44
|
must sign as the same identity as the plugin**: the plugin shows
|
|
45
45
|
mail for its `options.kid`, and only that kid may ack it. With
|
|
46
46
|
`options.kid`/`options.key`, give the MCP `environment` the same kid and
|
|
@@ -53,7 +53,7 @@ OpenCode 1.x compat).
|
|
|
53
53
|
"servers": {
|
|
54
54
|
"substrate": {
|
|
55
55
|
"type": "local",
|
|
56
|
-
"command": ["npx", "-y", "@mnmal-ai/substrate", "mcp"],
|
|
56
|
+
"command": ["npx", "-y", "@mnmal-ai/substrate@next", "mcp"],
|
|
57
57
|
"codemode": false,
|
|
58
58
|
"environment": {
|
|
59
59
|
"SUBSTRATE_URL": "https://substrate.example.com:3100",
|
|
@@ -77,10 +77,18 @@ OpenCode 1.x compat).
|
|
|
77
77
|
version. An older hand-copied `.opencode/substrate-conventions.md` is named in
|
|
78
78
|
the session context as stale; delete it and its `"instructions"` entry.
|
|
79
79
|
|
|
80
|
-
4. Restart opencode (config loads once at startup)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
4. Restart opencode (config loads once at startup), then install the
|
|
81
|
+
skills. OpenCode loads no skills from a plugin package, so copy them to the
|
|
82
|
+
user skills directory, and again after each plugin update:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
PKG=$(ls -d ~/.cache/opencode/npm/@mnmal-ai/cortext-opencode@next/*/node_modules/@mnmal-ai/cortext-opencode | sort | tail -1)
|
|
86
|
+
mkdir -p ~/.config/opencode/skills && cp -R "$PKG/skills/." ~/.config/opencode/skills/
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The `substrate-setup` skill is the guided version of all of the above plus
|
|
90
|
+
capability probing, AgentRule seeding, identity provisioning, and the
|
|
91
|
+
first anchor.
|
|
84
92
|
|
|
85
93
|
## Environment
|
|
86
94
|
|
|
@@ -105,8 +113,9 @@ OpenCode 1.x compat).
|
|
|
105
113
|
| `Stop` inbox check (blocks once) | V2: a `session.execution.succeeded` event with unread mail queues one synthetic message carrying the same reason, with `resume: true`. Each message id nudges once. `SYNOPTIC_INBOX_STOP_CHECK=off` disables it |
|
|
106
114
|
| Mid-turn push (`inbox-bridge`) | V2: the watcher runs in-process; new mail is steered into every busy session, allowlisted urgent mail preempts the most recently prompted session, and idle wake is opt-in. While the watcher is live the per-prompt summary is skipped; the end-of-turn nudge stays |
|
|
107
115
|
| `skills/{council,todos}` | `skills/{council,todos}` — byte-identical pointer bodies (`test/skills-sync.test.ts` enforces) |
|
|
116
|
+
| `skills/substrate-run` | `skills/substrate-run` — shared steps 1–5, own binary/identity and permission steps (`test/skills-sync.test.ts` enforces) |
|
|
108
117
|
| `fragments/substrate-conventions.md` | `instructions/substrate-conventions.md` — shared body, own marker (`test/instructions-sync.test.ts` enforces) |
|
|
109
|
-
| `/substrate-setup` skill | `
|
|
118
|
+
| `/substrate-setup` skill | `skills/substrate-setup` — opencode paths + MCP dialect |
|
|
110
119
|
| SessionStart `compact` re-run | `compaction` session hook: drops the cache (next dispatch rebuilds) + leaves a pointer in the summary |
|
|
111
120
|
| Fragment-drift watchdog | **Deferred** — the check reads the `.claude/` install path; see `src/plugin.ts` header |
|
|
112
121
|
|
package/dist/plugin.js
CHANGED
|
@@ -69,14 +69,22 @@ function mint(kid, key, ns, capabilities, aud) {
|
|
|
69
69
|
exp
|
|
70
70
|
};
|
|
71
71
|
}
|
|
72
|
-
|
|
72
|
+
const LOOPBACK = /^(localhost|127\.\d{1,3}\.\d{1,3}\.\d{1,3}|\[::1\])$/;
|
|
73
|
+
/**
|
|
74
|
+
* The origin a token for `url` names as its `aud`. Throws rather than mint a
|
|
75
|
+
* token without one, or one bound for plain http to a non-loopback host, where
|
|
76
|
+
* the network can read it. Same rule as substrate-client's `tokenAudience`.
|
|
77
|
+
*/
|
|
73
78
|
function audienceOf(url) {
|
|
74
79
|
const raw = typeof url === "object" && url !== null && "url" in url ? url.url : url;
|
|
80
|
+
let parsed;
|
|
75
81
|
try {
|
|
76
|
-
|
|
82
|
+
parsed = new URL(String(raw));
|
|
77
83
|
} catch {
|
|
78
84
|
throw new Error(`cannot mint an agent token without an audience: '${raw}' is not a URL`);
|
|
79
85
|
}
|
|
86
|
+
if (parsed.protocol === "https:" || parsed.protocol === "http:" && LOOPBACK.test(parsed.hostname)) return parsed.origin;
|
|
87
|
+
throw new Error(`refusing to send an agent token to ${parsed.origin}: use https, or plain http only to a loopback host`);
|
|
80
88
|
}
|
|
81
89
|
function misconfigured(detail) {
|
|
82
90
|
return {
|
|
@@ -160,6 +168,7 @@ function makeSignedFetch(getAuthHeader, fetchImpl = fetch) {
|
|
|
160
168
|
if (header === null) return fetchImpl(url, init);
|
|
161
169
|
return fetchImpl(url, {
|
|
162
170
|
...init,
|
|
171
|
+
redirect: "error",
|
|
163
172
|
headers: {
|
|
164
173
|
...init.headers,
|
|
165
174
|
authorization: header
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- substrate-conventions vsynoptic-1.0.0-alpha.
|
|
1
|
+
<!-- substrate-conventions vsynoptic-1.0.0-alpha.8+9d0bf8e1 — opencode skin; plugin-owned, do not edit. Edit your own AGENTS.md instead. Body is shared with the Claude skin's fragment (test/instructions-sync.test.ts enforces it). -->
|
|
2
2
|
|
|
3
3
|
# Substrate interaction conventions
|
|
4
4
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mnmal-ai/cortext-opencode",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.8",
|
|
4
4
|
"description": "Cortext — the OpenCode skin: cold-start injection via experimental.chat.system.transform, bundling the @mnmal-ai/synoptic host into a committed dist artifact. Installed as an OpenCode plugin (\"plugin\": [\"@mnmal-ai/cortext-opencode\"]). Published to npm, not the Claude marketplace.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
"dist",
|
|
18
18
|
"skills",
|
|
19
19
|
"instructions",
|
|
20
|
-
"commands",
|
|
21
20
|
"README.md"
|
|
22
21
|
],
|
|
23
22
|
"publishConfig": {
|
|
@@ -25,7 +24,7 @@
|
|
|
25
24
|
"access": "public"
|
|
26
25
|
},
|
|
27
26
|
"devDependencies": {
|
|
28
|
-
"@mnmal-ai/synoptic": "1.0.0-alpha.
|
|
27
|
+
"@mnmal-ai/synoptic": "1.0.0-alpha.8",
|
|
29
28
|
"@opencode-ai/plugin": "^1.18.35",
|
|
30
29
|
"@opencode/plugin": "^2.0.24",
|
|
31
30
|
"@types/node": "^26.6.4",
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: substrate-run
|
|
3
|
+
description: "Run a short TypeScript script against Substrate with `substrate run`, so many reads and writes cost one tool call and return one small result. Use for multi-step store work: censuses and counts, joins across types, recall-then-hydrate, and batch writes driven by reads. Do NOT use for a single lookup or a single write; the substrate MCP tools are simpler there. Requires substrate >= 1.0.0-alpha.6."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
`substrate run` imports one `.mts` script, calls its default export with a signed
|
|
7
|
+
`ScriptContext`, and prints one JSON report. Many queries and mutations run in a
|
|
8
|
+
single tool call, and only the result the script returns reaches your context.
|
|
9
|
+
|
|
10
|
+
## 0. Find the binary and the identity
|
|
11
|
+
|
|
12
|
+
**Requires substrate >= 1.0.0-alpha.6.** Older binaries have no `run` subcommand.
|
|
13
|
+
|
|
14
|
+
Both come from the `substrate` server in `opencode.json` (`mcp.servers.substrate`,
|
|
15
|
+
project or user level):
|
|
16
|
+
|
|
17
|
+
- **The binary** is its `command` array minus the trailing `mcp`: either
|
|
18
|
+
`node /abs/path/to/substrate.js`, or `npx -y @mnmal-ai/substrate@next`.
|
|
19
|
+
- **The identity** is its `environment`: `SUBSTRATE_URL`,
|
|
20
|
+
`SUBSTRATE_AGENT_KEY_ID` and `SUBSTRATE_AGENT_KEY_PATH`. A `{env:VAR}` value
|
|
21
|
+
is already in your shell. A literal one is not, so set it on the command.
|
|
22
|
+
Use only the key's path; never read or print the key file.
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
node /abs/path/to/substrate.js --version
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Write every run as one literal command, values filled in, leaving out any
|
|
29
|
+
variable your shell already has:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
env SUBSTRATE_URL=https://substrate.example.com:3100 SUBSTRATE_AGENT_KEY_ID=repo-opencode@host SUBSTRATE_AGENT_KEY_PATH=/abs/path/to/repo-opencode.key node /abs/path/to/substrate.js run script.mts
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
If the version is below `1.0.0-alpha.6`, stop and use the MCP tools instead.
|
|
36
|
+
Say that the local substrate install is behind and that updating it unlocks
|
|
37
|
+
this skill.
|
|
38
|
+
|
|
39
|
+
**It refuses to run unsigned**, so a refusal names a missing identity rather
|
|
40
|
+
than a broken script.
|
|
41
|
+
|
|
42
|
+
## 1. When to use it, and when not to
|
|
43
|
+
|
|
44
|
+
| Use `substrate run` | Use the MCP tools |
|
|
45
|
+
|---|---|
|
|
46
|
+
| A count or census over many rows (`queryAll` pages to the end) | One lookup by id, shortId or name |
|
|
47
|
+
| A join: rows of one type, then the rows they reference | One write |
|
|
48
|
+
| Recall, then fetch the bodies of the few hits worth reading | Exploring the schema |
|
|
49
|
+
| A batch of writes chosen by what a read found | Anything you will read only once, row by row |
|
|
50
|
+
|
|
51
|
+
The test: if you would otherwise make three or more MCP calls and pass ids from
|
|
52
|
+
one call to the next, write a script.
|
|
53
|
+
|
|
54
|
+
## 2. Write the script outside the repo
|
|
55
|
+
|
|
56
|
+
Scripts are throwaway. Put them in the session scratchpad directory, or a temp
|
|
57
|
+
directory if the harness gives you none, never in the repo.
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import type { ScriptContext } from '@mnmal-ai/substrate/client';
|
|
61
|
+
|
|
62
|
+
// node /abs/path/to/substrate.js run open-by-project.mts --args '{"ns":"cortext"}'
|
|
63
|
+
export default async function (s: ScriptContext) {
|
|
64
|
+
const ns = String(s.args.ns ?? 'cortext');
|
|
65
|
+
const open = await s.queryAll(`${ns}/Todo`, {
|
|
66
|
+
params: { where: { status: { eq: 'open' }, archived: { eq: false } }, limit: 100 },
|
|
67
|
+
fields: { id: true, project: true }
|
|
68
|
+
});
|
|
69
|
+
const byProject: Record<string, number> = {};
|
|
70
|
+
for (const t of open) byProject[String(t.project ?? 'null')] = (byProject[String(t.project ?? 'null')] ?? 0) + 1;
|
|
71
|
+
return { total: open.length, byProject };
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The namespace is `cortext` unless `SUBSTRATE_NAMESPACE` says otherwise. Pass it
|
|
76
|
+
in through `--args` instead of hardcoding it. The `import type` line is erased
|
|
77
|
+
at load, so the script needs no `node_modules` beside it.
|
|
78
|
+
|
|
79
|
+
The context:
|
|
80
|
+
|
|
81
|
+
| Member | Does |
|
|
82
|
+
|---|---|
|
|
83
|
+
| `s.args` | The `--args` JSON object, frozen. `{}` when omitted |
|
|
84
|
+
| `s.query(frame)` | One query frame. **Throws if any key you asked for is missing from `data`**: a rejected frame fails the run with the server's `errors` instead of reading as empty. Adds a warning when a result is truncated (`hasMore`) |
|
|
85
|
+
| `s.queryAll(key, { params, fields })` | Every row of one key, paging until `hasMore` is false |
|
|
86
|
+
| `s.recall({ query, namespace, type?, k?, threshold?, where?, row? })` | Hits, best first. `row` holds `id` plus the handle fields; pass `row: { body: true }` (or `true`) only on the call whose hits you will read |
|
|
87
|
+
| `s.mutate(payload)` | One mutate payload. Throws by default, records without sending under `--dry-run`, sends under `--write`. Throws when the server refuses any frame |
|
|
88
|
+
| `s.log(...)` | stderr only. The report owns stdout |
|
|
89
|
+
| `s.kid`, `s.mode` | The signing kid and `read` / `dry-run` / `write` |
|
|
90
|
+
|
|
91
|
+
## 3. Reduce in the script
|
|
92
|
+
|
|
93
|
+
Return counts, ids, short handles, a verdict. Never return whole rows "to look
|
|
94
|
+
at". Filtering, grouping and joining belong in the script, because what it
|
|
95
|
+
returns lands in your context.
|
|
96
|
+
|
|
97
|
+
When the result is large, pass `--out <file>` (beside the script). The report
|
|
98
|
+
goes to the file and stdout gets one line. Then read only what you need from
|
|
99
|
+
the file.
|
|
100
|
+
|
|
101
|
+
## 4. Writes: dry run, read, then write
|
|
102
|
+
|
|
103
|
+
The default mode is read-only, and `s.mutate` throws in it.
|
|
104
|
+
|
|
105
|
+
1. Run with `--dry-run`. Each payload is recorded in `report.mutations` and
|
|
106
|
+
nothing is sent; `s.mutate` returns `null`, so do not let later logic depend
|
|
107
|
+
on its return value.
|
|
108
|
+
2. Read `report.mutations`. Check the count, the ids, and a sample of the
|
|
109
|
+
params against what you intended.
|
|
110
|
+
3. Re-run the same script with `--write`. It sends up to `--max-writes` frames
|
|
111
|
+
(default 50; an array under an op-key counts one per element). Raise it
|
|
112
|
+
deliberately, not by habit.
|
|
113
|
+
|
|
114
|
+
The script re-reads the store on the write run, so it acts on the current state
|
|
115
|
+
rather than on what the dry run saw.
|
|
116
|
+
|
|
117
|
+
Transactions are per call and per op-key. Within one `s.mutate` payload, each
|
|
118
|
+
array op-key is its own transaction and the single-frame op-keys share one, so
|
|
119
|
+
one op-key can be refused (for example `policy_denied`) while its siblings
|
|
120
|
+
land. Separate `s.mutate` calls are separate transactions. For writes that must
|
|
121
|
+
land together, put them in one array under one op-key.
|
|
122
|
+
|
|
123
|
+
## 5. Read the report
|
|
124
|
+
|
|
125
|
+
```json
|
|
126
|
+
{ "ok": true, "kid": "…", "mode": "write", "args": {}, "result": {}, "mutations": [{ "frame": {}, "applied": true }], "warnings": [], "stats": { "queries": 3, "writes": 1, "ms": 137 } }
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
- Check `ok` and the exit code (`0` ok, `1` the script failed, `2` usage or
|
|
130
|
+
configuration) before `result`. On failure `error` carries the server's
|
|
131
|
+
message.
|
|
132
|
+
- **`mutations` lists every payload with `applied`, including those sent before
|
|
133
|
+
a failure.** A failed `--write` run may have written part of its batch. Read
|
|
134
|
+
this list before retrying, and make a retry skip rows that already changed.
|
|
135
|
+
- `warnings` names truncated reads. A warning means the answer is incomplete;
|
|
136
|
+
switch that read to `queryAll`.
|
|
137
|
+
|
|
138
|
+
Never pipe the run into `tail` or `jq` when its exit code matters. Use
|
|
139
|
+
`--out`, or redirect to a file.
|
|
140
|
+
|
|
141
|
+
## 6. Cut the permission prompts
|
|
142
|
+
|
|
143
|
+
If OpenCode asks before each run, suggest the user allow the command in
|
|
144
|
+
`opencode.json`, using the prefix from step 0:
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{ "permission": { "bash": { "env SUBSTRATE_URL=* node /abs/path/to/substrate.js run *": "allow" } } }
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
This covers `--write` too, just as the MCP tools write without prompting. The
|
|
151
|
+
dry run in step 4 is the guard on writes, not the permission prompt.
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
+
name: substrate-setup
|
|
2
3
|
description: Onboard this repo as a Cortext consumer under OpenCode. Probes the target Substrate, wires the substrate MCP server in opencode.json (identity-ready), installs the conventions instructions, and seeds baseline AgentRules. Run once per repo.
|
|
3
4
|
---
|
|
4
5
|
|
|
5
|
-
#
|
|
6
|
+
# substrate-setup (OpenCode): onboard a cortext-opencode consumer
|
|
6
7
|
|
|
7
|
-
Run these steps in order. This
|
|
8
|
+
Run these steps in order. This skill is **idempotent** — re-running it never duplicates config entries or rules.
|
|
8
9
|
|
|
9
10
|
Steps 2, 5, 6, 8 are transport-agnostic and identical to the Claude skin's
|
|
10
11
|
`/substrate-setup`; only the file paths and the MCP dialect differ. Where this
|
|
@@ -51,7 +52,7 @@ following and report it as ✓/✗:
|
|
|
51
52
|
3. **Recall capability:** `GET <SUBSTRATE_URL>/substrate/v1/embed-stats` → `enabled`.
|
|
52
53
|
`true` = hybrid cold-start; `false` = structural-only (degrades cleanly).
|
|
53
54
|
4. **MCP package resolvable** (only if Step 4 uses the npx server form):
|
|
54
|
-
`npm view @mnmal-ai/substrate version`. It is public on npmjs.com, so a
|
|
55
|
+
`npm view @mnmal-ai/substrate@next version`. It is public on npmjs.com, so a
|
|
55
56
|
failure here is a network or registry-mirror problem, not missing auth.
|
|
56
57
|
|
|
57
58
|
Print a capability summary block.
|
|
@@ -67,7 +68,7 @@ Print a capability summary block.
|
|
|
67
68
|
"$schema": "https://opencode.ai/config.json",
|
|
68
69
|
"plugins": [
|
|
69
70
|
{
|
|
70
|
-
"package": "@mnmal-ai/cortext-opencode",
|
|
71
|
+
"package": "@mnmal-ai/cortext-opencode@next",
|
|
71
72
|
"options": {
|
|
72
73
|
"kid": "<the Step-1 kid>",
|
|
73
74
|
"key": "<the Step-1 key file>"
|
|
@@ -77,7 +78,7 @@ Print a capability summary block.
|
|
|
77
78
|
}
|
|
78
79
|
```
|
|
79
80
|
|
|
80
|
-
The plain string form (`"plugins": ["@mnmal-ai/cortext-opencode"]`) also
|
|
81
|
+
The plain string form (`"plugins": ["@mnmal-ai/cortext-opencode@next"]`) also
|
|
81
82
|
works — identity then comes from the env pair. **Keep exactly one entry
|
|
82
83
|
per package**: as of opencode v2.0.24 the `plugins`
|
|
83
84
|
arrays concatenate across global + project config and loads dedupe only
|
|
@@ -89,7 +90,19 @@ Print a capability summary block.
|
|
|
89
90
|
npm plugins install automatically via Bun at startup (cached under
|
|
90
91
|
`~/.cache/opencode/`). No registry auth is needed.
|
|
91
92
|
|
|
92
|
-
2.
|
|
93
|
+
2. Install the skills. OpenCode loads no skills from a plugin package, so
|
|
94
|
+
copy them to the user skills directory, where every repo sees them. Bun
|
|
95
|
+
installs the plugin at startup, so restart opencode after step 1 first.
|
|
96
|
+
Re-run this after each plugin update; the copy does not track the package.
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
PKG=$(ls -d ~/.cache/opencode/npm/@mnmal-ai/cortext-opencode@next/*/node_modules/@mnmal-ai/cortext-opencode | sort | tail -1)
|
|
100
|
+
mkdir -p ~/.config/opencode/skills && cp -R "$PKG/skills/." ~/.config/opencode/skills/
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
That installs `council`, `todos`, `substrate-run` and this skill.
|
|
104
|
+
|
|
105
|
+
3. Conventions need no step: the plugin injects them from its own package
|
|
93
106
|
on every dispatch, so they track the installed version. If the
|
|
94
107
|
repo has an older `.opencode/substrate-conventions.md` copy, delete it and its
|
|
95
108
|
`"instructions"` entry; the session context names it while it is stale.
|
|
@@ -115,7 +128,7 @@ leaves empty:
|
|
|
115
128
|
"servers": {
|
|
116
129
|
"substrate": {
|
|
117
130
|
"type": "local",
|
|
118
|
-
"command": ["npx", "-y", "@mnmal-ai/substrate", "mcp"],
|
|
131
|
+
"command": ["npx", "-y", "@mnmal-ai/substrate@next", "mcp"],
|
|
119
132
|
"codemode": false,
|
|
120
133
|
"environment": {
|
|
121
134
|
"SUBSTRATE_URL": "<the url>",
|
|
@@ -212,6 +225,6 @@ set):
|
|
|
212
225
|
```
|
|
213
226
|
|
|
214
227
|
Then summarise: SUBSTRATE_URL source, plugin entry, instructions copy, MCP
|
|
215
|
-
server form, rules created vs skipped, recall tier, identity (per-project
|
|
228
|
+
server form, skills installed, rules created vs skipped, recall tier, identity (per-project
|
|
216
229
|
kid vs fleet default). Tell the user to restart opencode — config loads once
|
|
217
230
|
at startup, and the cold-start injects on the first dispatch after that.
|