dsh-env-manager-plugin 0.1.0 → 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.
Files changed (78) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +273 -250
  3. package/client.js +2581 -2581
  4. package/cordis.patch.yml +4 -4
  5. package/docs/00-project/current-state.md +32 -6
  6. package/docs/00-project/glossary.md +215 -215
  7. package/docs/00-project/project-brief.md +114 -114
  8. package/docs/00-project/roadmap.md +89 -89
  9. package/docs/01-architecture/DSH_Environment_Service_Memory_Skill_Brainstorm.md +493 -493
  10. package/docs/01-architecture/api-verification.md +416 -416
  11. package/docs/01-architecture/architecture-overview.md +222 -222
  12. package/docs/01-architecture/data-model.md +930 -930
  13. package/docs/01-architecture/decisions/ADR-0001-plugin-as-bundle.md +29 -29
  14. package/docs/01-architecture/decisions/ADR-0002-file-based-storage.md +25 -25
  15. package/docs/01-architecture/decisions/ADR-0003-skill-router-over-search.md +25 -25
  16. package/docs/01-architecture/decisions/ADR-0004-typescript-host-js-client.md +31 -31
  17. package/docs/01-architecture/decisions/ADR-0005-layered-rule-resolution.md +36 -36
  18. package/docs/01-architecture/decisions/ADR-0006-credentials-as-references.md +30 -30
  19. package/docs/01-architecture/decisions/ADR-0007-session-scoped-default-environment.md +28 -28
  20. package/docs/01-architecture/decisions/ADR-0008-memory-bridge-not-second-store.md +31 -31
  21. package/docs/01-architecture/decisions/ADR-0009-client-host-http-transport.md +87 -87
  22. package/docs/01-architecture/decisions/ADR-0010-environment-plane-model.md +87 -87
  23. package/docs/01-architecture/decisions/ADR-0011-k8s-node-execution-model.md +92 -92
  24. package/docs/01-architecture/design.md +666 -666
  25. package/docs/01-architecture/detailed-design.md +961 -961
  26. package/docs/01-architecture/implementation-plan.md +323 -323
  27. package/docs/01-architecture/module-boundaries.md +306 -306
  28. package/docs/01-architecture/security-model.md +227 -227
  29. package/docs/01-architecture/storage-contract.md +224 -224
  30. package/docs/01-architecture/tool-contract.md +438 -438
  31. package/docs/01-architecture/ui-design.md +587 -587
  32. package/docs/02-harness/agent-behavior.md +36 -36
  33. package/docs/02-harness/change-snapshot-policy.md +29 -29
  34. package/docs/02-harness/client-ui-integration.md +110 -110
  35. package/docs/02-harness/context-policy.md +43 -43
  36. package/docs/02-harness/harness-standard.md +91 -91
  37. package/docs/02-harness/task-execution-policy.md +26 -26
  38. package/docs/02-harness/verification-policy.md +97 -97
  39. package/docs/03-openspec/archive-rule.md +25 -25
  40. package/docs/03-openspec/bugfix-rule.md +30 -30
  41. package/docs/03-openspec/design-rule.md +33 -33
  42. package/docs/03-openspec/openspec-usage-guide.md +31 -31
  43. package/docs/03-openspec/proposal-rule.md +70 -70
  44. package/docs/03-openspec/spec-rule.md +33 -33
  45. package/docs/03-openspec/tasks-rule.md +31 -31
  46. package/docs/04-development/coding-style.md +67 -67
  47. package/docs/04-development/dependency-policy.md +43 -43
  48. package/docs/04-development/development-guide.md +85 -85
  49. package/docs/04-development/directory-convention.md +105 -105
  50. package/docs/04-development/local-run-guide.md +61 -55
  51. package/docs/04-development/testing-guide.md +102 -102
  52. package/docs/05-domain/deployment-template.md +76 -76
  53. package/docs/05-domain/environment-template.md +165 -165
  54. package/docs/05-domain/operation-binding-template.md +55 -55
  55. package/docs/05-domain/operation-record-template.md +55 -55
  56. package/docs/05-domain/prompt-template.md +90 -90
  57. package/docs/05-domain/rule-template.md +73 -73
  58. package/docs/05-domain/service-template.md +39 -39
  59. package/docs/06-operations/deployment-guide.md +54 -54
  60. package/docs/06-operations/release.md +198 -188
  61. package/docs/06-operations/security-policy.md +53 -53
  62. package/docs/06-operations/troubleshooting.md +141 -91
  63. package/docs/07-templates/adr-template.md +21 -21
  64. package/docs/07-templates/bugfix-template.md +11 -11
  65. package/docs/07-templates/case-template.md +15 -15
  66. package/docs/07-templates/design-template.md +29 -29
  67. package/docs/07-templates/proposal-template.md +19 -19
  68. package/docs/07-templates/spec-template.md +15 -15
  69. package/docs/07-templates/tasks-template.md +12 -12
  70. package/docs/99-archive/README.md +13 -13
  71. package/docs/README.md +142 -142
  72. package/icon.svg +4 -4
  73. package/index.js +31 -8
  74. package/lib/skill.js +37 -37
  75. package/locale/en.json +6 -6
  76. package/locale/zh.json +6 -6
  77. package/package.json +101 -99
  78. package/scripts/repair-profile.mjs +141 -0
@@ -1,224 +1,224 @@
1
- # Storage Contract
2
-
3
- Status: normative for V1.
4
-
5
- Durable registry data is a directory of YAML files. Nothing else is authoritative.
6
-
7
- Related: [data-model.md](./data-model.md), [design.md](./design.md) §5.
8
-
9
- ---
10
-
11
- ## 1. Location
12
-
13
- ```text
14
- <dataDir>/
15
- ├── environments/{environmentId}.yaml
16
- ├── services/{serviceId}.yaml
17
- ├── deployments/{deploymentId}.yaml
18
- ├── rules/{ruleProfileId}.yaml
19
- ├── operations/{bindingId}.yaml
20
- ├── sessions/{sessionId}.json
21
- └── .backups/
22
- ```
23
-
24
- ### 1.1 Resolving `dataDir`
25
-
26
- Precedence:
27
-
28
- 1. Plugin config `dataDir`, when set (absolute path or path relative to the profile directory).
29
- 2. `profileContext.dir` → `<dir>/data/dsh-env-manager`.
30
- 3. `$DSH_PROFILE_DIR/data/dsh-env-manager`.
31
- 4. `<working directory>/data/dsh-env-manager` as a last resort for development only.
32
-
33
- The chosen path is memoized, reported once at startup, and shown in the UI overview. It
34
- is never derived from model input. Resolution order and fallbacks are implemented in
35
- `src/storage/paths.ts` (detailed-design §4.1).
36
-
37
- ### 1.2 Creation
38
-
39
- - The directory tree is created on first use.
40
- - A missing directory is not an error; an unwritable directory is an error with `STORAGE_UNWRITABLE`.
41
-
42
- ---
43
-
44
- ## 2. File rules
45
-
46
- | Rule | Value |
47
- |---|---|
48
- | Encoding | UTF-8, no BOM |
49
- | Line endings | LF on write; CRLF tolerated on read |
50
- | Format | YAML 1.2 |
51
- | Extension | `.yaml` for records, `.json` for session state |
52
- | Name | `{id}.yaml`, where `id` matches `^[a-z0-9][a-z0-9-]{0,62}$` |
53
- | Extra files | Ignored unless they match the extension; ignored files are not deleted |
54
-
55
- A record file whose `id` differs from its filename is reported by `env_validate` and treated as invalid on load.
56
-
57
- ---
58
-
59
- ## 3. Record envelope
60
-
61
- Every record carries:
62
-
63
- ```yaml
64
- id: string
65
- schemaVersion: 1
66
- createdAt: 2026-11-01T03:00:00.000Z
67
- updatedAt: 2026-11-01T03:00:00.000Z
68
- ```
69
-
70
- - `createdAt` is set by storage on create.
71
- - `updatedAt` is set by storage on every successful write.
72
- - A write input may include both fields; storage overrides them. `createdAt` is
73
- preserved from the existing file on update, so a caller cannot rewrite history.
74
- - The stored record always contains both fields.
75
-
76
- ---
77
-
78
- ## 4. Atomic write protocol
79
-
80
- ```text
81
- 1. Serialize the record to YAML.
82
- 2. Validate the serialized document by parsing it back and running schema validation.
83
- 3. Open `.${id}.${pid}.${randomUUID()}.tmp` in the target directory.
84
- 4. Write UTF-8, fsync, close.
85
- 5. Copy the previous file into `.backups/<kind>/<id>/<timestamp>.yaml`, prune to 5.
86
- 6. Rename over the target (atomic on the same volume).
87
- 7. On a caught failure before rename, delete the temp file and leave the target intact.
88
- ```
89
-
90
- Constraints:
91
-
92
- - Never write directly to the target file.
93
- - Never leave a temp file behind on success or on a caught failure. A crash can leave
94
- one; startup removes `*.tmp` older than one hour.
95
- - A backup failure does not fail the write; it is reported as a warning.
96
- - Never delete a record file that failed to parse; surface a diagnostic instead.
97
- - Storage does not reload the registry; the application layer does after a successful
98
- write.
99
-
100
- ---
101
-
102
- ## 5. Read behavior
103
-
104
- ```text
105
- 1. Enumerate `*.yaml` in the directory.
106
- 2. Parse each file.
107
- 3. Schema-validate.
108
- 4. On parse error: record `RECORD_INVALID` diagnostic, skip the file.
109
- 5. On unknown schemaVersion: record `SCHEMA_UNSUPPORTED` warning, skip the file.
110
- 6. Build an in-memory map keyed by id.
111
- ```
112
-
113
- Reads never modify files. A failed file stays on disk for the user to fix.
114
-
115
- If a directory is unreadable, the loader returns an empty map plus an error diagnostic; tools still serve whatever other directories loaded.
116
-
117
- ---
118
-
119
- ## 6. Registry lifecycle
120
-
121
- - V1 loads the registry at the start of every application request.
122
- - Concurrent requests share one in-flight load.
123
- - A successful write triggers a reload before the request returns.
124
- - The registry is an in-memory snapshot; it is never persisted.
125
- - V1 has no index files and no watcher. A scan of a few hundred small YAML files is
126
- fast enough; an mtime-keyed cache is added only with measured need.
127
-
128
- ---
129
-
130
- ## 7. Session state
131
-
132
- ```text
133
- sessions/{sessionId}.json
134
- ```
135
-
136
- ```json
137
- {
138
- "schemaVersion": 1,
139
- "sessionId": "session-abc",
140
- "defaultEnvironmentId": "test-a",
141
- "updatedAt": "2026-11-01T03:00:00.000Z"
142
- }
143
- ```
144
-
145
- Rules:
146
-
147
- - Written atomically with the same protocol as records.
148
- - A missing file means "no default".
149
- - A corrupt file is treated as "no default" and reported as `persisted: false`; it is
150
- not deleted, so the user can inspect it.
151
- - A process-local cache mirrors the last value so a failed write still works until
152
- restart (detailed-design §9).
153
- - Session files are not registry records and are never scanned into the registry.
154
- - V1 uses this file store; a projection over the durable session log is a later
155
- refinement (detailed-design §9).
156
-
157
- ---
158
-
159
- ## 8. Referential integrity
160
-
161
- Storage itself does not enforce cross-record references; the registry does, on load and on write:
162
-
163
- - Broken references are reported by `env_validate`.
164
- - On load, an invalid reference produces a warning; the record stays usable for name lookups.
165
- - On write, an invalid reference is rejected (`RECORD_INVALID` with details).
166
-
167
- This split keeps a single bad file from making the whole registry unusable.
168
-
169
- ---
170
-
171
- ## 9. Backups
172
-
173
- V1 keeps one rolling backup per write:
174
-
175
- ```text
176
- .backups/{kind}/{id}/{timestamp}.yaml
177
- ```
178
-
179
- - At most 5 backups per record; older ones are pruned.
180
- - Backups are best-effort: a backup failure does not fail the write, but emits a warning.
181
- - Backups are not a history feature. They exist to recover from an accidental overwrite.
182
-
183
- ---
184
-
185
- ## 10. Migration
186
-
187
- - `schemaVersion` gates compatibility.
188
- - V1 accepts only `1`.
189
- - A future migration must:
190
- 1. read old files,
191
- 2. write new files atomically,
192
- 3. keep a backup,
193
- 4. report counts,
194
- 5. never delete the old file until the new one is verified.
195
-
196
- V1 implements no migration.
197
-
198
- ---
199
-
200
- ## 11. What must never be stored
201
-
202
- - Passwords, tokens, private keys, kubeconfigs.
203
- - Raw command output or logs.
204
- - Copy of credential values.
205
- - Session conversation content.
206
-
207
- A violation found in validation is reported as `RECORD_INVALID` with the field path but without echoing the value.
208
-
209
- ---
210
-
211
- ## 12. Concurrency
212
-
213
- - Writers are serialized in-process; the plugin is one Host process per profile.
214
- - Multi-process writers are last-write-wins; no file locks in V1.
215
- - Readers never block writers.
216
- - A write that fails validation leaves the previous file untouched.
217
-
218
- ---
219
-
220
- ## 13. Repository hygiene
221
-
222
- - `data/` is git-ignored.
223
- - The repository ships no registry data, only schemas, examples in docs, and tests fixtures.
224
- - Test fixtures live under `tests/fixtures/` and contain no real hostnames, IPs or URLs.
1
+ # Storage Contract
2
+
3
+ Status: normative for V1.
4
+
5
+ Durable registry data is a directory of YAML files. Nothing else is authoritative.
6
+
7
+ Related: [data-model.md](./data-model.md), [design.md](./design.md) §5.
8
+
9
+ ---
10
+
11
+ ## 1. Location
12
+
13
+ ```text
14
+ <dataDir>/
15
+ ├── environments/{environmentId}.yaml
16
+ ├── services/{serviceId}.yaml
17
+ ├── deployments/{deploymentId}.yaml
18
+ ├── rules/{ruleProfileId}.yaml
19
+ ├── operations/{bindingId}.yaml
20
+ ├── sessions/{sessionId}.json
21
+ └── .backups/
22
+ ```
23
+
24
+ ### 1.1 Resolving `dataDir`
25
+
26
+ Precedence:
27
+
28
+ 1. Plugin config `dataDir`, when set (absolute path or path relative to the profile directory).
29
+ 2. `profileContext.dir` → `<dir>/data/dsh-env-manager`.
30
+ 3. `$DSH_PROFILE_DIR/data/dsh-env-manager`.
31
+ 4. `<working directory>/data/dsh-env-manager` as a last resort for development only.
32
+
33
+ The chosen path is memoized, reported once at startup, and shown in the UI overview. It
34
+ is never derived from model input. Resolution order and fallbacks are implemented in
35
+ `src/storage/paths.ts` (detailed-design §4.1).
36
+
37
+ ### 1.2 Creation
38
+
39
+ - The directory tree is created on first use.
40
+ - A missing directory is not an error; an unwritable directory is an error with `STORAGE_UNWRITABLE`.
41
+
42
+ ---
43
+
44
+ ## 2. File rules
45
+
46
+ | Rule | Value |
47
+ |---|---|
48
+ | Encoding | UTF-8, no BOM |
49
+ | Line endings | LF on write; CRLF tolerated on read |
50
+ | Format | YAML 1.2 |
51
+ | Extension | `.yaml` for records, `.json` for session state |
52
+ | Name | `{id}.yaml`, where `id` matches `^[a-z0-9][a-z0-9-]{0,62}$` |
53
+ | Extra files | Ignored unless they match the extension; ignored files are not deleted |
54
+
55
+ A record file whose `id` differs from its filename is reported by `env_validate` and treated as invalid on load.
56
+
57
+ ---
58
+
59
+ ## 3. Record envelope
60
+
61
+ Every record carries:
62
+
63
+ ```yaml
64
+ id: string
65
+ schemaVersion: 1
66
+ createdAt: 2026-11-01T03:00:00.000Z
67
+ updatedAt: 2026-11-01T03:00:00.000Z
68
+ ```
69
+
70
+ - `createdAt` is set by storage on create.
71
+ - `updatedAt` is set by storage on every successful write.
72
+ - A write input may include both fields; storage overrides them. `createdAt` is
73
+ preserved from the existing file on update, so a caller cannot rewrite history.
74
+ - The stored record always contains both fields.
75
+
76
+ ---
77
+
78
+ ## 4. Atomic write protocol
79
+
80
+ ```text
81
+ 1. Serialize the record to YAML.
82
+ 2. Validate the serialized document by parsing it back and running schema validation.
83
+ 3. Open `.${id}.${pid}.${randomUUID()}.tmp` in the target directory.
84
+ 4. Write UTF-8, fsync, close.
85
+ 5. Copy the previous file into `.backups/<kind>/<id>/<timestamp>.yaml`, prune to 5.
86
+ 6. Rename over the target (atomic on the same volume).
87
+ 7. On a caught failure before rename, delete the temp file and leave the target intact.
88
+ ```
89
+
90
+ Constraints:
91
+
92
+ - Never write directly to the target file.
93
+ - Never leave a temp file behind on success or on a caught failure. A crash can leave
94
+ one; startup removes `*.tmp` older than one hour.
95
+ - A backup failure does not fail the write; it is reported as a warning.
96
+ - Never delete a record file that failed to parse; surface a diagnostic instead.
97
+ - Storage does not reload the registry; the application layer does after a successful
98
+ write.
99
+
100
+ ---
101
+
102
+ ## 5. Read behavior
103
+
104
+ ```text
105
+ 1. Enumerate `*.yaml` in the directory.
106
+ 2. Parse each file.
107
+ 3. Schema-validate.
108
+ 4. On parse error: record `RECORD_INVALID` diagnostic, skip the file.
109
+ 5. On unknown schemaVersion: record `SCHEMA_UNSUPPORTED` warning, skip the file.
110
+ 6. Build an in-memory map keyed by id.
111
+ ```
112
+
113
+ Reads never modify files. A failed file stays on disk for the user to fix.
114
+
115
+ If a directory is unreadable, the loader returns an empty map plus an error diagnostic; tools still serve whatever other directories loaded.
116
+
117
+ ---
118
+
119
+ ## 6. Registry lifecycle
120
+
121
+ - V1 loads the registry at the start of every application request.
122
+ - Concurrent requests share one in-flight load.
123
+ - A successful write triggers a reload before the request returns.
124
+ - The registry is an in-memory snapshot; it is never persisted.
125
+ - V1 has no index files and no watcher. A scan of a few hundred small YAML files is
126
+ fast enough; an mtime-keyed cache is added only with measured need.
127
+
128
+ ---
129
+
130
+ ## 7. Session state
131
+
132
+ ```text
133
+ sessions/{sessionId}.json
134
+ ```
135
+
136
+ ```json
137
+ {
138
+ "schemaVersion": 1,
139
+ "sessionId": "session-abc",
140
+ "defaultEnvironmentId": "test-a",
141
+ "updatedAt": "2026-11-01T03:00:00.000Z"
142
+ }
143
+ ```
144
+
145
+ Rules:
146
+
147
+ - Written atomically with the same protocol as records.
148
+ - A missing file means "no default".
149
+ - A corrupt file is treated as "no default" and reported as `persisted: false`; it is
150
+ not deleted, so the user can inspect it.
151
+ - A process-local cache mirrors the last value so a failed write still works until
152
+ restart (detailed-design §9).
153
+ - Session files are not registry records and are never scanned into the registry.
154
+ - V1 uses this file store; a projection over the durable session log is a later
155
+ refinement (detailed-design §9).
156
+
157
+ ---
158
+
159
+ ## 8. Referential integrity
160
+
161
+ Storage itself does not enforce cross-record references; the registry does, on load and on write:
162
+
163
+ - Broken references are reported by `env_validate`.
164
+ - On load, an invalid reference produces a warning; the record stays usable for name lookups.
165
+ - On write, an invalid reference is rejected (`RECORD_INVALID` with details).
166
+
167
+ This split keeps a single bad file from making the whole registry unusable.
168
+
169
+ ---
170
+
171
+ ## 9. Backups
172
+
173
+ V1 keeps one rolling backup per write:
174
+
175
+ ```text
176
+ .backups/{kind}/{id}/{timestamp}.yaml
177
+ ```
178
+
179
+ - At most 5 backups per record; older ones are pruned.
180
+ - Backups are best-effort: a backup failure does not fail the write, but emits a warning.
181
+ - Backups are not a history feature. They exist to recover from an accidental overwrite.
182
+
183
+ ---
184
+
185
+ ## 10. Migration
186
+
187
+ - `schemaVersion` gates compatibility.
188
+ - V1 accepts only `1`.
189
+ - A future migration must:
190
+ 1. read old files,
191
+ 2. write new files atomically,
192
+ 3. keep a backup,
193
+ 4. report counts,
194
+ 5. never delete the old file until the new one is verified.
195
+
196
+ V1 implements no migration.
197
+
198
+ ---
199
+
200
+ ## 11. What must never be stored
201
+
202
+ - Passwords, tokens, private keys, kubeconfigs.
203
+ - Raw command output or logs.
204
+ - Copy of credential values.
205
+ - Session conversation content.
206
+
207
+ A violation found in validation is reported as `RECORD_INVALID` with the field path but without echoing the value.
208
+
209
+ ---
210
+
211
+ ## 12. Concurrency
212
+
213
+ - Writers are serialized in-process; the plugin is one Host process per profile.
214
+ - Multi-process writers are last-write-wins; no file locks in V1.
215
+ - Readers never block writers.
216
+ - A write that fails validation leaves the previous file untouched.
217
+
218
+ ---
219
+
220
+ ## 13. Repository hygiene
221
+
222
+ - `data/` is git-ignored.
223
+ - The repository ships no registry data, only schemas, examples in docs, and tests fixtures.
224
+ - Test fixtures live under `tests/fixtures/` and contain no real hostnames, IPs or URLs.