dsh-env-manager-plugin 0.0.0-stage → 0.1.1
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 +21 -0
- package/README.md +273 -3
- package/client.js +2581 -0
- package/cordis.patch.yml +4 -0
- package/docs/00-project/current-state.md +272 -0
- package/docs/00-project/glossary.md +215 -0
- package/docs/00-project/project-brief.md +114 -0
- package/docs/00-project/roadmap.md +89 -0
- package/docs/01-architecture/DSH_Environment_Service_Memory_Skill_Brainstorm.md +493 -0
- package/docs/01-architecture/api-verification.md +416 -0
- package/docs/01-architecture/architecture-overview.md +222 -0
- package/docs/01-architecture/data-model.md +930 -0
- package/docs/01-architecture/decisions/ADR-0001-plugin-as-bundle.md +29 -0
- package/docs/01-architecture/decisions/ADR-0002-file-based-storage.md +25 -0
- package/docs/01-architecture/decisions/ADR-0003-skill-router-over-search.md +25 -0
- package/docs/01-architecture/decisions/ADR-0004-typescript-host-js-client.md +31 -0
- package/docs/01-architecture/decisions/ADR-0005-layered-rule-resolution.md +36 -0
- package/docs/01-architecture/decisions/ADR-0006-credentials-as-references.md +30 -0
- package/docs/01-architecture/decisions/ADR-0007-session-scoped-default-environment.md +28 -0
- package/docs/01-architecture/decisions/ADR-0008-memory-bridge-not-second-store.md +31 -0
- package/docs/01-architecture/decisions/ADR-0009-client-host-http-transport.md +87 -0
- package/docs/01-architecture/decisions/ADR-0010-environment-plane-model.md +87 -0
- package/docs/01-architecture/decisions/ADR-0011-k8s-node-execution-model.md +92 -0
- package/docs/01-architecture/design.md +666 -0
- package/docs/01-architecture/detailed-design.md +961 -0
- package/docs/01-architecture/implementation-plan.md +323 -0
- package/docs/01-architecture/module-boundaries.md +306 -0
- package/docs/01-architecture/security-model.md +227 -0
- package/docs/01-architecture/storage-contract.md +224 -0
- package/docs/01-architecture/tool-contract.md +438 -0
- package/docs/01-architecture/ui-design.md +587 -0
- package/docs/02-harness/agent-behavior.md +36 -0
- package/docs/02-harness/change-snapshot-policy.md +29 -0
- package/docs/02-harness/client-ui-integration.md +110 -0
- package/docs/02-harness/context-policy.md +43 -0
- package/docs/02-harness/harness-standard.md +91 -0
- package/docs/02-harness/task-execution-policy.md +26 -0
- package/docs/02-harness/verification-policy.md +97 -0
- package/docs/03-openspec/archive-rule.md +25 -0
- package/docs/03-openspec/bugfix-rule.md +30 -0
- package/docs/03-openspec/design-rule.md +33 -0
- package/docs/03-openspec/openspec-usage-guide.md +31 -0
- package/docs/03-openspec/proposal-rule.md +70 -0
- package/docs/03-openspec/spec-rule.md +33 -0
- package/docs/03-openspec/tasks-rule.md +31 -0
- package/docs/04-development/coding-style.md +67 -0
- package/docs/04-development/dependency-policy.md +43 -0
- package/docs/04-development/development-guide.md +85 -0
- package/docs/04-development/directory-convention.md +105 -0
- package/docs/04-development/local-run-guide.md +61 -0
- package/docs/04-development/testing-guide.md +102 -0
- package/docs/05-domain/deployment-template.md +76 -0
- package/docs/05-domain/environment-template.md +165 -0
- package/docs/05-domain/operation-binding-template.md +55 -0
- package/docs/05-domain/operation-record-template.md +55 -0
- package/docs/05-domain/prompt-template.md +90 -0
- package/docs/05-domain/rule-template.md +73 -0
- package/docs/05-domain/service-template.md +39 -0
- package/docs/06-operations/deployment-guide.md +54 -0
- package/docs/06-operations/release.md +198 -0
- package/docs/06-operations/security-policy.md +53 -0
- package/docs/06-operations/troubleshooting.md +141 -0
- package/docs/07-templates/adr-template.md +21 -0
- package/docs/07-templates/bugfix-template.md +11 -0
- package/docs/07-templates/case-template.md +15 -0
- package/docs/07-templates/design-template.md +29 -0
- package/docs/07-templates/proposal-template.md +19 -0
- package/docs/07-templates/spec-template.md +15 -0
- package/docs/07-templates/tasks-template.md +12 -0
- package/docs/99-archive/README.md +13 -0
- package/docs/README.md +142 -0
- package/icon.svg +4 -0
- package/index.js +31 -0
- package/lib/app/app.d.ts +67 -0
- package/lib/app/app.js +494 -0
- package/lib/app/app.js.map +1 -0
- package/lib/config.d.ts +55 -0
- package/lib/config.js +42 -0
- package/lib/config.js.map +1 -0
- package/lib/domain/constants.d.ts +21 -0
- package/lib/domain/constants.js +59 -0
- package/lib/domain/constants.js.map +1 -0
- package/lib/domain/errors.d.ts +20 -0
- package/lib/domain/errors.js +22 -0
- package/lib/domain/errors.js.map +1 -0
- package/lib/domain/schemas.d.ts +28 -0
- package/lib/domain/schemas.js +445 -0
- package/lib/domain/schemas.js.map +1 -0
- package/lib/domain/types.d.ts +412 -0
- package/lib/domain/types.js +2 -0
- package/lib/domain/types.js.map +1 -0
- package/lib/index.d.ts +18 -0
- package/lib/index.js +89 -0
- package/lib/index.js.map +1 -0
- package/lib/logger.d.ts +8 -0
- package/lib/logger.js +13 -0
- package/lib/logger.js.map +1 -0
- package/lib/memory/bridge.d.ts +18 -0
- package/lib/memory/bridge.js +13 -0
- package/lib/memory/bridge.js.map +1 -0
- package/lib/registry/integrity.d.ts +10 -0
- package/lib/registry/integrity.js +204 -0
- package/lib/registry/integrity.js.map +1 -0
- package/lib/registry/registry.d.ts +14 -0
- package/lib/registry/registry.js +182 -0
- package/lib/registry/registry.js.map +1 -0
- package/lib/resolver/merge.d.ts +23 -0
- package/lib/resolver/merge.js +90 -0
- package/lib/resolver/merge.js.map +1 -0
- package/lib/resolver/resolve.d.ts +18 -0
- package/lib/resolver/resolve.js +288 -0
- package/lib/resolver/resolve.js.map +1 -0
- package/lib/resolver/template.d.ts +10 -0
- package/lib/resolver/template.js +42 -0
- package/lib/resolver/template.js.map +1 -0
- package/lib/router/params.d.ts +3 -0
- package/lib/router/params.js +83 -0
- package/lib/router/params.js.map +1 -0
- package/lib/router/router.d.ts +11 -0
- package/lib/router/router.js +204 -0
- package/lib/router/router.js.map +1 -0
- package/lib/session/session.d.ts +16 -0
- package/lib/session/session.js +64 -0
- package/lib/session/session.js.map +1 -0
- package/lib/skill.d.ts +17 -0
- package/lib/skill.js +56 -0
- package/lib/skill.js.map +1 -0
- package/lib/storage/atomic.d.ts +10 -0
- package/lib/storage/atomic.js +107 -0
- package/lib/storage/atomic.js.map +1 -0
- package/lib/storage/paths.d.ts +10 -0
- package/lib/storage/paths.js +50 -0
- package/lib/storage/paths.js.map +1 -0
- package/lib/storage/records.d.ts +16 -0
- package/lib/storage/records.js +112 -0
- package/lib/storage/records.js.map +1 -0
- package/lib/storage/sessions.d.ts +17 -0
- package/lib/storage/sessions.js +65 -0
- package/lib/storage/sessions.js.map +1 -0
- package/lib/tools/tools.d.ts +14 -0
- package/lib/tools/tools.js +472 -0
- package/lib/tools/tools.js.map +1 -0
- package/lib/transport/http.d.ts +3 -0
- package/lib/transport/http.js +217 -0
- package/lib/transport/http.js.map +1 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +101 -6
- package/scripts/repair-profile.mjs +141 -0
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
# Tool Contract (V1)
|
|
2
|
+
|
|
3
|
+
> Status: normative model-facing contract. Registration mechanics are in
|
|
4
|
+
> [`api-verification.md`](api-verification.md) F2–F5; implementation in
|
|
5
|
+
> [`detailed-design.md`](detailed-design.md) §11.
|
|
6
|
+
> An implementation whose tool schema differs from this document is a bug in one of
|
|
7
|
+
> them; update both in the same change.
|
|
8
|
+
|
|
9
|
+
## 1. Conventions
|
|
10
|
+
|
|
11
|
+
### 1.1 Registration
|
|
12
|
+
|
|
13
|
+
Every tool is a `defineTool` definition registered on `ctx.tools` during `apply`:
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
ctx.tools.register(defineTool({
|
|
17
|
+
name, description, parameters,
|
|
18
|
+
output: { schema, render },
|
|
19
|
+
async execute(args, exec) { /* returns the declared JSON value */ },
|
|
20
|
+
}))
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
- The tool name is stable and matches `^env_[a-z_]+$`.
|
|
24
|
+
- `parameters` uses DSH's value-schema DSL, not raw JSON Schema. Property-level
|
|
25
|
+
`required: true` marks required arguments. `additionalProperties` must be explicit.
|
|
26
|
+
- `output.schema` is the enforced JSON Schema subset: `type`, `oneOf`, `properties`,
|
|
27
|
+
`required`, `additionalProperties`, `items`, `enum`, `const` plus annotations.
|
|
28
|
+
- `render(args, value)` returns `ContentBlock[]`. V1 emits exactly one text block: a
|
|
29
|
+
one-line summary plus the ids a human needs. The canonical JSON value is what the
|
|
30
|
+
model receives.
|
|
31
|
+
- Descriptions start with the decision rule ("Use when …"), not with a restatement of
|
|
32
|
+
the name.
|
|
33
|
+
|
|
34
|
+
### 1.2 Errors
|
|
35
|
+
|
|
36
|
+
Success returns the declared value. Every expected failure throws:
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
class EnvManagerError extends HarnessError {
|
|
40
|
+
constructor(code: ErrorCode, message: string, details?: JsonValue)
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`HarnessError` is imported from `@deepseek-ai/dsh-llm` and constructed as
|
|
45
|
+
`super(message, code)`. DSH records `{ name, code }` beside the message, so the model
|
|
46
|
+
and the UI can branch on `code` without parsing text.
|
|
47
|
+
|
|
48
|
+
Rules:
|
|
49
|
+
|
|
50
|
+
- No tool returns `{ ok: false }`.
|
|
51
|
+
- No tool throws a bare string.
|
|
52
|
+
- Messages never contain a credential value, a file body, or a stack trace.
|
|
53
|
+
- Unexpected exceptions are wrapped as `INTERNAL_ERROR` with a redacted message.
|
|
54
|
+
- A cancelled call surfaces DSH's own abort error; do not translate it.
|
|
55
|
+
|
|
56
|
+
Codes are defined in [`data-model.md`](data-model.md) §11.
|
|
57
|
+
|
|
58
|
+
### 1.3 Approval
|
|
59
|
+
|
|
60
|
+
| Tool | Approval |
|
|
61
|
+
|---|---|
|
|
62
|
+
| `env_delete` | always, when `confirm: true` and `writePolicy.requireApprovalForDelete` |
|
|
63
|
+
| `env_save` | when the record is a production environment, or a deployment whose environment is production, and `writePolicy.requireApprovalForProductionSave` |
|
|
64
|
+
| everything else | no |
|
|
65
|
+
|
|
66
|
+
Approval uses `ctx.approval.request` with the executing agent, the tool name, the call
|
|
67
|
+
id, an English `reason`, and a localized `displayReason`. Only `'allowed-once'` grants;
|
|
68
|
+
`'rejected'`, `'cancelled'` and `'unavailable'` all become `POLICY_DENIED`.
|
|
69
|
+
|
|
70
|
+
A session-scoped tool invoked without `exec.agent` fails with
|
|
71
|
+
`SESSION_CONTEXT_UNAVAILABLE`; it never guesses a session.
|
|
72
|
+
|
|
73
|
+
### 1.4 Session default
|
|
74
|
+
|
|
75
|
+
`env_resolve`, `env_resolve_operation` and `env_set_context` operate on the calling
|
|
76
|
+
agent's session. When `environmentId` is omitted, the order is:
|
|
77
|
+
|
|
78
|
+
1. the explicit argument;
|
|
79
|
+
2. the session default (`sessions/<sessionId>.json`);
|
|
80
|
+
3. `config.defaults.environmentId`;
|
|
81
|
+
4. `INVALID_ARGUMENT` naming both ways to supply an environment.
|
|
82
|
+
|
|
83
|
+
### 1.5 Shared value shapes
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
interface Diagnostic {
|
|
87
|
+
severity: 'info' | 'warning' | 'error'
|
|
88
|
+
code: string
|
|
89
|
+
message: string
|
|
90
|
+
file?: string
|
|
91
|
+
path?: string
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
interface RecordSummary {
|
|
95
|
+
kind: RecordKind
|
|
96
|
+
id: string
|
|
97
|
+
name: string
|
|
98
|
+
summary?: string // kind-specific one-liner
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
interface WarningList { warnings: Diagnostic[] }
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`RecordKind = 'environment' | 'service' | 'deployment' | 'ruleProfile' | 'operationBinding'`.
|
|
105
|
+
|
|
106
|
+
## 2. Read tools
|
|
107
|
+
|
|
108
|
+
### 2.1 `env_list`
|
|
109
|
+
|
|
110
|
+
Use when the caller needs an inventory or wants to discover ids before a specific call.
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
parameters: {
|
|
114
|
+
kind: {
|
|
115
|
+
type: 'string',
|
|
116
|
+
required: false,
|
|
117
|
+
enum: ['environment', 'service', 'deployment', 'ruleProfile', 'operationBinding'],
|
|
118
|
+
description: 'Restrict to one record kind.',
|
|
119
|
+
},
|
|
120
|
+
query: {
|
|
121
|
+
type: 'string',
|
|
122
|
+
required: false,
|
|
123
|
+
description: 'Case-insensitive match over id, name and alias.',
|
|
124
|
+
},
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
|
|
130
|
+
```json
|
|
131
|
+
{ "items": [ { "kind": "environment", "id": "test-a", "name": "Test A", "summary": "test · 2 hosts" } ],
|
|
132
|
+
"warnings": [] }
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
- Sorted by kind, then id.
|
|
136
|
+
- An empty registry is `{ "items": [], "warnings": [] }`, not an error.
|
|
137
|
+
- Registry diagnostics are summarized in `warnings` (at most 20, with a count of the
|
|
138
|
+
rest).
|
|
139
|
+
|
|
140
|
+
Errors: `INVALID_ARGUMENT` for an unknown `kind`.
|
|
141
|
+
|
|
142
|
+
Render: `"5 environments, 2 services (2 warnings)."`
|
|
143
|
+
|
|
144
|
+
### 2.2 `env_get`
|
|
145
|
+
|
|
146
|
+
Use when the caller already has an id and needs the full record.
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
parameters: {
|
|
150
|
+
kind: { type: 'string', required: true, enum: [/* five kinds */] },
|
|
151
|
+
id: { type: 'string', required: true, description: 'Record id, e.g. test-a.' },
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
|
|
157
|
+
```json
|
|
158
|
+
{ "record": { "id": "test-a", "schemaVersion": 1, "...": "..." },
|
|
159
|
+
"yaml": "id: test-a\n..." }
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
- `record` is the parsed document; `yaml` is the on-disk text (helpful for edits).
|
|
163
|
+
- Unknown fields in the file are preserved in both.
|
|
164
|
+
|
|
165
|
+
Errors: `ENV_NOT_FOUND`, `SERVICE_NOT_FOUND`, `DEPLOYMENT_NOT_FOUND`,
|
|
166
|
+
`RULE_PROFILE_NOT_FOUND`, `BINDING_NOT_FOUND` depending on `kind`; `INVALID_ARGUMENT`
|
|
167
|
+
for a malformed id (fails before any I/O).
|
|
168
|
+
|
|
169
|
+
Render: `"environment test-a (Test A), updated 2026-11-01."`
|
|
170
|
+
|
|
171
|
+
### 2.3 `env_find`
|
|
172
|
+
|
|
173
|
+
Use when the caller has a name or fragment and wants candidate ids. Prefer this over
|
|
174
|
+
guessing an id.
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
parameters: {
|
|
178
|
+
query: {
|
|
179
|
+
type: 'string',
|
|
180
|
+
required: true,
|
|
181
|
+
description: 'Fragment of an id, name, alias or category (min 2 characters).',
|
|
182
|
+
},
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
|
|
188
|
+
```json
|
|
189
|
+
{ "hits": [ { "kind": "service", "id": "aicoservice", "name": "Aico Service", "field": "alias" } ] }
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
- Matching is case-insensitive over `id`, `name`, `aliases`, `category`.
|
|
193
|
+
- Ranked: exact id, prefix id, name, alias, category. At most 25 hits.
|
|
194
|
+
- No hit is not an error.
|
|
195
|
+
|
|
196
|
+
Errors: `INVALID_ARGUMENT` when `query` is shorter than 2 characters.
|
|
197
|
+
|
|
198
|
+
Render: `"3 matches for \"aico\"."`
|
|
199
|
+
|
|
200
|
+
### 2.4 `env_resolve`
|
|
201
|
+
|
|
202
|
+
Use when the caller needs concrete paths, log sources, class locations or variables
|
|
203
|
+
for a service in an environment. This is the authoritative answer; do not reconstruct
|
|
204
|
+
paths from templates.
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
parameters: {
|
|
208
|
+
environmentId: { type: 'string', required: false, description: 'Defaults to the session environment.' },
|
|
209
|
+
serviceId: { type: 'string', required: true },
|
|
210
|
+
deploymentId: {
|
|
211
|
+
type: 'string',
|
|
212
|
+
required: false,
|
|
213
|
+
description: 'Required when the service has more than one binding in the environment; a single binding is selected automatically.',
|
|
214
|
+
},
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Returns the Service Context from `data-model.md` §8.2, including `provenance` and
|
|
219
|
+
`warnings`.
|
|
220
|
+
|
|
221
|
+
Errors: `ENV_NOT_FOUND`, `SERVICE_NOT_FOUND`, `DEPLOYMENT_NOT_FOUND`,
|
|
222
|
+
`DEPLOYMENT_AMBIGUOUS` (lists candidates), `RULE_*`, `PARAMETER_RESOLUTION_FAILED`.
|
|
223
|
+
|
|
224
|
+
Render: `"Resolved aicoservice in test-a (kubernetes): 7 paths, 2 variables, 1 warning."`
|
|
225
|
+
|
|
226
|
+
### 2.5 `env_resolve_operation`
|
|
227
|
+
|
|
228
|
+
Use before acting: ask which Skill handles an operation for this context and what
|
|
229
|
+
parameters it expects. This tool **does not execute** the Skill.
|
|
230
|
+
|
|
231
|
+
```ts
|
|
232
|
+
parameters: {
|
|
233
|
+
operation: {
|
|
234
|
+
type: 'string',
|
|
235
|
+
required: true,
|
|
236
|
+
description: 'deploy | redeploy | restart | rollback | collect-logs | health-check | … (standard id or a bound custom id).',
|
|
237
|
+
},
|
|
238
|
+
environmentId: { type: 'string', required: false },
|
|
239
|
+
serviceId: { type: 'string', required: false },
|
|
240
|
+
deploymentId: { type: 'string', required: false },
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
- At least one of `serviceId` / `deploymentId` is required; `environmentId` falls back
|
|
245
|
+
to the session default.
|
|
246
|
+
|
|
247
|
+
Returns `OperationResolution` from `data-model.md` §8.3:
|
|
248
|
+
|
|
249
|
+
```json
|
|
250
|
+
{
|
|
251
|
+
"ok": true,
|
|
252
|
+
"operation": "redeploy",
|
|
253
|
+
"requested": { "environmentId": "test-a", "serviceId": "aicoservice", "deploymentId": "deploy-001" },
|
|
254
|
+
"matchedBindingId": "binding-001",
|
|
255
|
+
"matchLevel": "environment-service",
|
|
256
|
+
"skill": { "name": "redeploy-k8s-service", "available": true, "source": "project-dsh", "provider": "dsh-skills" },
|
|
257
|
+
"parameters": { "namespace": "dv-sop", "workload": "aicoservice", "cluster": "k8s-01" },
|
|
258
|
+
"policy": { "requiresApproval": true, "allowProduction": false },
|
|
259
|
+
"diagnostics": []
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Errors: `ENV_NOT_FOUND`, `SERVICE_NOT_FOUND`, `DEPLOYMENT_NOT_FOUND`,
|
|
264
|
+
`DEPLOYMENT_AMBIGUOUS`, `BINDING_NOT_FOUND`, `BINDING_CONFLICT` (lists every candidate),
|
|
265
|
+
`SKILL_UNAVAILABLE`, `POLICY_DENIED`, `OPERATION_UNKNOWN`, `PARAMETER_RESOLUTION_FAILED`.
|
|
266
|
+
|
|
267
|
+
Incomplete Skill catalog: `skill.available: "unknown"` plus a
|
|
268
|
+
`SKILL_REGISTRY_UNAVAILABLE` warning; the call still succeeds.
|
|
269
|
+
|
|
270
|
+
Render: `"redeploy aicoservice/test-a → redeploy-k8s-service (approval required)."`
|
|
271
|
+
|
|
272
|
+
### 2.6 `env_get_context`
|
|
273
|
+
|
|
274
|
+
Use to check what environment the current session defaults to.
|
|
275
|
+
|
|
276
|
+
```ts
|
|
277
|
+
parameters: {}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Returns:
|
|
281
|
+
|
|
282
|
+
```json
|
|
283
|
+
{ "sessionId": "01J…", "defaultEnvironmentId": "test-a", "persisted": true }
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Errors: `SESSION_CONTEXT_UNAVAILABLE` when there is no owning agent.
|
|
287
|
+
|
|
288
|
+
Render: `"Session default: test-a."`
|
|
289
|
+
|
|
290
|
+
### 2.7 `env_set_context`
|
|
291
|
+
|
|
292
|
+
Use when the user says "work on test-a" and later calls should omit `environmentId`.
|
|
293
|
+
|
|
294
|
+
```ts
|
|
295
|
+
parameters: {
|
|
296
|
+
environmentId: {
|
|
297
|
+
oneOf: [{ type: 'string' }, { type: 'null' }],
|
|
298
|
+
required: true,
|
|
299
|
+
description: 'Environment id, or null to clear the session default.',
|
|
300
|
+
},
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Returns the same shape as `env_get_context`. Writing an unknown environment fails with
|
|
305
|
+
`ENV_NOT_FOUND`.
|
|
306
|
+
|
|
307
|
+
A file write failure returns `persisted: false` plus a `SESSION_CONTEXT_UNPERSISTED`
|
|
308
|
+
warning; it does not throw, because the process-local cache still honors the choice for
|
|
309
|
+
this process.
|
|
310
|
+
|
|
311
|
+
Render: `"Session default set to test-a."` / `"Session default cleared."`
|
|
312
|
+
|
|
313
|
+
## 3. Management tools
|
|
314
|
+
|
|
315
|
+
### 3.1 `env_save`
|
|
316
|
+
|
|
317
|
+
Use to create or replace a record. Prefer `env_get` first, edit the YAML, then save the
|
|
318
|
+
whole record; do not send a partial patch.
|
|
319
|
+
|
|
320
|
+
```ts
|
|
321
|
+
parameters: {
|
|
322
|
+
kind: { type: 'string', required: true, enum: [/* five kinds */] },
|
|
323
|
+
record: {
|
|
324
|
+
type: 'json',
|
|
325
|
+
required: true,
|
|
326
|
+
description: 'Complete record; id and schemaVersion are required. Host timestamps are set by the plugin and ignored if supplied.',
|
|
327
|
+
},
|
|
328
|
+
dryRun: {
|
|
329
|
+
type: 'boolean',
|
|
330
|
+
required: false,
|
|
331
|
+
description: 'Validate and report without writing.',
|
|
332
|
+
},
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
Returns:
|
|
337
|
+
|
|
338
|
+
```json
|
|
339
|
+
{ "id": "test-a", "kind": "environment", "created": false, "dryRun": false,
|
|
340
|
+
"warnings": [ { "severity": "warning", "code": "CREDENTIAL_MISSING", "message": "…" } ] }
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
Behavior:
|
|
344
|
+
|
|
345
|
+
- Zod validation, id/filename equality, record cap, then atomic write, then reload.
|
|
346
|
+
- `created` is `true` only when no file existed before.
|
|
347
|
+
- Broken references after the write are returned as warnings; the write is not rolled
|
|
348
|
+
back because the record itself is valid.
|
|
349
|
+
- Production records require approval unless the config disables it.
|
|
350
|
+
|
|
351
|
+
Errors: `RECORD_INVALID` (with `details.issues`), `RECORD_LIMIT_EXCEEDED`,
|
|
352
|
+
`RECORD_TOO_LARGE`, `STORAGE_UNWRITABLE`, `POLICY_DENIED`.
|
|
353
|
+
|
|
354
|
+
Render: `"Saved environment test-a (updated, 1 warning)."`
|
|
355
|
+
|
|
356
|
+
### 3.2 `env_delete`
|
|
357
|
+
|
|
358
|
+
Use only when the user explicitly asks to remove a record.
|
|
359
|
+
|
|
360
|
+
```ts
|
|
361
|
+
parameters: {
|
|
362
|
+
kind: { type: 'string', required: true, enum: [/* five kinds */] },
|
|
363
|
+
id: { type: 'string', required: true },
|
|
364
|
+
confirm: {
|
|
365
|
+
type: 'boolean',
|
|
366
|
+
required: true,
|
|
367
|
+
description: 'false checks references only; true deletes after approval.',
|
|
368
|
+
},
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Returns:
|
|
373
|
+
|
|
374
|
+
```json
|
|
375
|
+
{ "id": "test-a", "kind": "environment", "deleted": true, "blockers": [] }
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
Behavior:
|
|
379
|
+
|
|
380
|
+
- `confirm: false` never deletes; it returns `blockers` describing references.
|
|
381
|
+
- `confirm: true` asks for approval, then refuses with `RECORD_IN_USE` when referenced.
|
|
382
|
+
- A backup copy is written before the unlink.
|
|
383
|
+
|
|
384
|
+
Errors: not found by kind, `RECORD_IN_USE`, `POLICY_DENIED`, `STORAGE_UNWRITABLE`.
|
|
385
|
+
|
|
386
|
+
Render: `"Deleted environment test-a (backup kept)."`
|
|
387
|
+
|
|
388
|
+
### 3.3 `env_validate`
|
|
389
|
+
|
|
390
|
+
Use after hand-editing YAML or before trusting a resolve result.
|
|
391
|
+
|
|
392
|
+
```ts
|
|
393
|
+
parameters: {}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
Returns:
|
|
397
|
+
|
|
398
|
+
```json
|
|
399
|
+
{
|
|
400
|
+
"ok": false,
|
|
401
|
+
"counts": {
|
|
402
|
+
"environment": 2, "service": 1, "deployment": 1,
|
|
403
|
+
"ruleProfile": 1, "operationBinding": 2
|
|
404
|
+
},
|
|
405
|
+
"diagnostics": [
|
|
406
|
+
{ "severity": "error", "code": "RULE_PROFILE_NOT_FOUND",
|
|
407
|
+
"message": "service aicoservice references unknown rule profile java-commn",
|
|
408
|
+
"file": "services/aicoservice.yaml", "path": "ruleProfileRefs[0]" }
|
|
409
|
+
]
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
- Always succeeds at the tool level; `ok: false` is a report, not a failure.
|
|
414
|
+
- Read-only: no write, no reload side effect beyond the normal request load.
|
|
415
|
+
|
|
416
|
+
Render: `"Registry invalid: 2 errors, 1 warning."`
|
|
417
|
+
|
|
418
|
+
## 4. Cross-tool rules
|
|
419
|
+
|
|
420
|
+
1. **Ids are data, not paths.** A tool never accepts a filesystem path.
|
|
421
|
+
2. **No credentials.** `credentialRef` status is reported as
|
|
422
|
+
`{ ref, configured, source }`; values are never resolved.
|
|
423
|
+
3. **No execution.** No tool runs a Skill, a shell command, or a network request.
|
|
424
|
+
4. **Determinism.** Same registry and inputs produce the same result; no random ids,
|
|
425
|
+
no wall-clock ordering.
|
|
426
|
+
5. **Read-only means read-only.** `env_validate`, `env_get_context`, `env_list`,
|
|
427
|
+
`env_get`, `env_find`, `env_resolve`, `env_resolve_operation` never write a file.
|
|
428
|
+
6. **Fail closed.** A conflict, missing Skill, broken reference or production denial is
|
|
429
|
+
an error, never a fallback.
|
|
430
|
+
|
|
431
|
+
## 5. Non-goals for V1 tools
|
|
432
|
+
|
|
433
|
+
- Executing an operation or invoking a Skill.
|
|
434
|
+
- Writing operation records to memory.
|
|
435
|
+
- Bulk import/export.
|
|
436
|
+
- Editing plugin configuration.
|
|
437
|
+
- Reading or writing session context for a session other than the caller's.
|
|
438
|
+
- Any network or shell access.
|