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.
- package/LICENSE +21 -21
- package/README.md +273 -250
- package/client.js +2581 -2581
- package/cordis.patch.yml +4 -4
- package/docs/00-project/current-state.md +32 -6
- package/docs/00-project/glossary.md +215 -215
- package/docs/00-project/project-brief.md +114 -114
- package/docs/00-project/roadmap.md +89 -89
- package/docs/01-architecture/DSH_Environment_Service_Memory_Skill_Brainstorm.md +493 -493
- package/docs/01-architecture/api-verification.md +416 -416
- package/docs/01-architecture/architecture-overview.md +222 -222
- package/docs/01-architecture/data-model.md +930 -930
- package/docs/01-architecture/decisions/ADR-0001-plugin-as-bundle.md +29 -29
- package/docs/01-architecture/decisions/ADR-0002-file-based-storage.md +25 -25
- package/docs/01-architecture/decisions/ADR-0003-skill-router-over-search.md +25 -25
- package/docs/01-architecture/decisions/ADR-0004-typescript-host-js-client.md +31 -31
- package/docs/01-architecture/decisions/ADR-0005-layered-rule-resolution.md +36 -36
- package/docs/01-architecture/decisions/ADR-0006-credentials-as-references.md +30 -30
- package/docs/01-architecture/decisions/ADR-0007-session-scoped-default-environment.md +28 -28
- package/docs/01-architecture/decisions/ADR-0008-memory-bridge-not-second-store.md +31 -31
- package/docs/01-architecture/decisions/ADR-0009-client-host-http-transport.md +87 -87
- package/docs/01-architecture/decisions/ADR-0010-environment-plane-model.md +87 -87
- package/docs/01-architecture/decisions/ADR-0011-k8s-node-execution-model.md +92 -92
- package/docs/01-architecture/design.md +666 -666
- package/docs/01-architecture/detailed-design.md +961 -961
- package/docs/01-architecture/implementation-plan.md +323 -323
- package/docs/01-architecture/module-boundaries.md +306 -306
- package/docs/01-architecture/security-model.md +227 -227
- package/docs/01-architecture/storage-contract.md +224 -224
- package/docs/01-architecture/tool-contract.md +438 -438
- package/docs/01-architecture/ui-design.md +587 -587
- package/docs/02-harness/agent-behavior.md +36 -36
- package/docs/02-harness/change-snapshot-policy.md +29 -29
- package/docs/02-harness/client-ui-integration.md +110 -110
- package/docs/02-harness/context-policy.md +43 -43
- package/docs/02-harness/harness-standard.md +91 -91
- package/docs/02-harness/task-execution-policy.md +26 -26
- package/docs/02-harness/verification-policy.md +97 -97
- package/docs/03-openspec/archive-rule.md +25 -25
- package/docs/03-openspec/bugfix-rule.md +30 -30
- package/docs/03-openspec/design-rule.md +33 -33
- package/docs/03-openspec/openspec-usage-guide.md +31 -31
- package/docs/03-openspec/proposal-rule.md +70 -70
- package/docs/03-openspec/spec-rule.md +33 -33
- package/docs/03-openspec/tasks-rule.md +31 -31
- package/docs/04-development/coding-style.md +67 -67
- package/docs/04-development/dependency-policy.md +43 -43
- package/docs/04-development/development-guide.md +85 -85
- package/docs/04-development/directory-convention.md +105 -105
- package/docs/04-development/local-run-guide.md +61 -55
- package/docs/04-development/testing-guide.md +102 -102
- package/docs/05-domain/deployment-template.md +76 -76
- package/docs/05-domain/environment-template.md +165 -165
- package/docs/05-domain/operation-binding-template.md +55 -55
- package/docs/05-domain/operation-record-template.md +55 -55
- package/docs/05-domain/prompt-template.md +90 -90
- package/docs/05-domain/rule-template.md +73 -73
- package/docs/05-domain/service-template.md +39 -39
- package/docs/06-operations/deployment-guide.md +54 -54
- package/docs/06-operations/release.md +198 -188
- package/docs/06-operations/security-policy.md +53 -53
- package/docs/06-operations/troubleshooting.md +141 -91
- package/docs/07-templates/adr-template.md +21 -21
- package/docs/07-templates/bugfix-template.md +11 -11
- package/docs/07-templates/case-template.md +15 -15
- package/docs/07-templates/design-template.md +29 -29
- package/docs/07-templates/proposal-template.md +19 -19
- package/docs/07-templates/spec-template.md +15 -15
- package/docs/07-templates/tasks-template.md +12 -12
- package/docs/99-archive/README.md +13 -13
- package/docs/README.md +142 -142
- package/icon.svg +4 -4
- package/index.js +31 -8
- package/lib/skill.js +37 -37
- package/locale/en.json +6 -6
- package/locale/zh.json +6 -6
- package/package.json +101 -99
- package/scripts/repair-profile.mjs +141 -0
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
# ADR-0001: Distribute as a DSH Bundle
|
|
2
|
-
|
|
3
|
-
## Status
|
|
4
|
-
|
|
5
|
-
Accepted
|
|
6
|
-
|
|
7
|
-
## Context
|
|
8
|
-
|
|
9
|
-
The Environment Manager must be installable into DSH and share state across sessions in the same profile. We considered several distribution models:
|
|
10
|
-
|
|
11
|
-
1. Standalone Node.js service
|
|
12
|
-
2. DSH plugin bundle
|
|
13
|
-
3. External CLI tool
|
|
14
|
-
|
|
15
|
-
## Decision
|
|
16
|
-
|
|
17
|
-
We will distribute Environment Manager as a DSH bundle with both Host and Client entries.
|
|
18
|
-
|
|
19
|
-
## Consequences
|
|
20
|
-
|
|
21
|
-
- Users install the bundle through DSH's `plugin_manager`.
|
|
22
|
-
- Host-side code runs in the DSH host process and can register tools and services.
|
|
23
|
-
- Client-side code runs in the Web/Desktop UI and can provide configuration panels.
|
|
24
|
-
- State is scoped to a DSH profile; all sessions in the profile share the registry.
|
|
25
|
-
|
|
26
|
-
## Alternatives Considered
|
|
27
|
-
|
|
28
|
-
- **Standalone service**: Adds operational overhead and is not idiomatic for DSH.
|
|
29
|
-
- **External CLI tool**: Loses integration with DSH session context and UI.
|
|
1
|
+
# ADR-0001: Distribute as a DSH Bundle
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
The Environment Manager must be installable into DSH and share state across sessions in the same profile. We considered several distribution models:
|
|
10
|
+
|
|
11
|
+
1. Standalone Node.js service
|
|
12
|
+
2. DSH plugin bundle
|
|
13
|
+
3. External CLI tool
|
|
14
|
+
|
|
15
|
+
## Decision
|
|
16
|
+
|
|
17
|
+
We will distribute Environment Manager as a DSH bundle with both Host and Client entries.
|
|
18
|
+
|
|
19
|
+
## Consequences
|
|
20
|
+
|
|
21
|
+
- Users install the bundle through DSH's `plugin_manager`.
|
|
22
|
+
- Host-side code runs in the DSH host process and can register tools and services.
|
|
23
|
+
- Client-side code runs in the Web/Desktop UI and can provide configuration panels.
|
|
24
|
+
- State is scoped to a DSH profile; all sessions in the profile share the registry.
|
|
25
|
+
|
|
26
|
+
## Alternatives Considered
|
|
27
|
+
|
|
28
|
+
- **Standalone service**: Adds operational overhead and is not idiomatic for DSH.
|
|
29
|
+
- **External CLI tool**: Loses integration with DSH session context and UI.
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
# ADR-0002: File-based Storage as Source of Truth
|
|
2
|
-
|
|
3
|
-
## Status
|
|
4
|
-
|
|
5
|
-
Accepted
|
|
6
|
-
|
|
7
|
-
## Context
|
|
8
|
-
|
|
9
|
-
We need durable storage for registry records. Options include a local JSON/YAML file tree, SQLite, or a database.
|
|
10
|
-
|
|
11
|
-
## Decision
|
|
12
|
-
|
|
13
|
-
Registry data is stored as YAML files in a directory tree under the plugin workspace.
|
|
14
|
-
|
|
15
|
-
## Consequences
|
|
16
|
-
|
|
17
|
-
- Human-readable and version-control friendly.
|
|
18
|
-
- Easy to inspect and edit.
|
|
19
|
-
- No external database dependency.
|
|
20
|
-
- Concurrent writes are last-write-wins; higher-level locking may be added later.
|
|
21
|
-
|
|
22
|
-
## Alternatives Considered
|
|
23
|
-
|
|
24
|
-
- **SQLite**: Adds complexity and a binary artifact; not necessary for V1 scale.
|
|
25
|
-
- **DSH memory plugin**: Memory plugin is for historical knowledge, not authoritative configuration.
|
|
1
|
+
# ADR-0002: File-based Storage as Source of Truth
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
We need durable storage for registry records. Options include a local JSON/YAML file tree, SQLite, or a database.
|
|
10
|
+
|
|
11
|
+
## Decision
|
|
12
|
+
|
|
13
|
+
Registry data is stored as YAML files in a directory tree under the plugin workspace.
|
|
14
|
+
|
|
15
|
+
## Consequences
|
|
16
|
+
|
|
17
|
+
- Human-readable and version-control friendly.
|
|
18
|
+
- Easy to inspect and edit.
|
|
19
|
+
- No external database dependency.
|
|
20
|
+
- Concurrent writes are last-write-wins; higher-level locking may be added later.
|
|
21
|
+
|
|
22
|
+
## Alternatives Considered
|
|
23
|
+
|
|
24
|
+
- **SQLite**: Adds complexity and a binary artifact; not necessary for V1 scale.
|
|
25
|
+
- **DSH memory plugin**: Memory plugin is for historical knowledge, not authoritative configuration.
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
# ADR-0003: Explicit Operation-to-Skill Binding over Search
|
|
2
|
-
|
|
3
|
-
## Status
|
|
4
|
-
|
|
5
|
-
Accepted
|
|
6
|
-
|
|
7
|
-
## Context
|
|
8
|
-
|
|
9
|
-
When an Agent asks to perform an operation (e.g. redeploy a service), the system could either search for a relevant Skill or use an explicit binding.
|
|
10
|
-
|
|
11
|
-
## Decision
|
|
12
|
-
|
|
13
|
-
We will use explicit Operation Bindings with deterministic scope-based matching.
|
|
14
|
-
|
|
15
|
-
## Consequences
|
|
16
|
-
|
|
17
|
-
- Predictable routing: the same context always resolves to the same Skill.
|
|
18
|
-
- Conflicts are explicit and fail safely.
|
|
19
|
-
- Parameters are mapped declaratively.
|
|
20
|
-
- Approval policies are attached to bindings.
|
|
21
|
-
|
|
22
|
-
## Alternatives Considered
|
|
23
|
-
|
|
24
|
-
- **Semantic search over skill descriptions**: Non-deterministic and hard to audit for production operations.
|
|
25
|
-
- **Convention-based naming**: Brittle and does not support fine-grained policy.
|
|
1
|
+
# ADR-0003: Explicit Operation-to-Skill Binding over Search
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
When an Agent asks to perform an operation (e.g. redeploy a service), the system could either search for a relevant Skill or use an explicit binding.
|
|
10
|
+
|
|
11
|
+
## Decision
|
|
12
|
+
|
|
13
|
+
We will use explicit Operation Bindings with deterministic scope-based matching.
|
|
14
|
+
|
|
15
|
+
## Consequences
|
|
16
|
+
|
|
17
|
+
- Predictable routing: the same context always resolves to the same Skill.
|
|
18
|
+
- Conflicts are explicit and fail safely.
|
|
19
|
+
- Parameters are mapped declaratively.
|
|
20
|
+
- Approval policies are attached to bindings.
|
|
21
|
+
|
|
22
|
+
## Alternatives Considered
|
|
23
|
+
|
|
24
|
+
- **Semantic search over skill descriptions**: Non-deterministic and hard to audit for production operations.
|
|
25
|
+
- **Convention-based naming**: Brittle and does not support fine-grained policy.
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
# ADR-0004: TypeScript Host, Plain-JavaScript Client
|
|
2
|
-
|
|
3
|
-
## Status
|
|
4
|
-
|
|
5
|
-
Accepted
|
|
6
|
-
|
|
7
|
-
## Context
|
|
8
|
-
|
|
9
|
-
The Host half contains the domain logic: schemas, layered rule resolution, provenance, conflict detection and policy evaluation. These benefit from static types and exhaustive checks.
|
|
10
|
-
|
|
11
|
-
The Client half is a DSH module-loader artifact. It has no build step today and uses `React.createElement` rather than JSX.
|
|
12
|
-
|
|
13
|
-
The alternative was TypeScript everywhere with a client bundler, or plain JavaScript everywhere.
|
|
14
|
-
|
|
15
|
-
## Decision
|
|
16
|
-
|
|
17
|
-
- Host: TypeScript compiled to ESM (`src/` → `lib/`).
|
|
18
|
-
- Client: plain JavaScript module at the repository root (`client.js`), no bundler.
|
|
19
|
-
- The current JavaScript host skeleton is replaced during V1 implementation; the bundle entry becomes a thin shim over `lib/index.js`.
|
|
20
|
-
|
|
21
|
-
## Consequences
|
|
22
|
-
|
|
23
|
-
- Domain invariants are checked at compile time.
|
|
24
|
-
- No client build pipeline in V1; UI code is more verbose.
|
|
25
|
-
- Two languages in one repository; the boundary is explicit: `src/` is Host-only.
|
|
26
|
-
- If the UI later needs TypeScript or JSX, that change gets its own ADR and a bundling step.
|
|
27
|
-
|
|
28
|
-
## Alternatives Considered
|
|
29
|
-
|
|
30
|
-
- **TypeScript everywhere now**: a bundler and a module-loader wrapper are needed immediately; delays the core value.
|
|
31
|
-
- **JavaScript everywhere**: loses compile-time guarantees exactly where the domain is most intricate.
|
|
1
|
+
# ADR-0004: TypeScript Host, Plain-JavaScript Client
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
The Host half contains the domain logic: schemas, layered rule resolution, provenance, conflict detection and policy evaluation. These benefit from static types and exhaustive checks.
|
|
10
|
+
|
|
11
|
+
The Client half is a DSH module-loader artifact. It has no build step today and uses `React.createElement` rather than JSX.
|
|
12
|
+
|
|
13
|
+
The alternative was TypeScript everywhere with a client bundler, or plain JavaScript everywhere.
|
|
14
|
+
|
|
15
|
+
## Decision
|
|
16
|
+
|
|
17
|
+
- Host: TypeScript compiled to ESM (`src/` → `lib/`).
|
|
18
|
+
- Client: plain JavaScript module at the repository root (`client.js`), no bundler.
|
|
19
|
+
- The current JavaScript host skeleton is replaced during V1 implementation; the bundle entry becomes a thin shim over `lib/index.js`.
|
|
20
|
+
|
|
21
|
+
## Consequences
|
|
22
|
+
|
|
23
|
+
- Domain invariants are checked at compile time.
|
|
24
|
+
- No client build pipeline in V1; UI code is more verbose.
|
|
25
|
+
- Two languages in one repository; the boundary is explicit: `src/` is Host-only.
|
|
26
|
+
- If the UI later needs TypeScript or JSX, that change gets its own ADR and a bundling step.
|
|
27
|
+
|
|
28
|
+
## Alternatives Considered
|
|
29
|
+
|
|
30
|
+
- **TypeScript everywhere now**: a bundler and a module-loader wrapper are needed immediately; delays the core value.
|
|
31
|
+
- **JavaScript everywhere**: loses compile-time guarantees exactly where the domain is most intricate.
|
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
# ADR-0005: Layered Rule Resolution with Provenance
|
|
2
|
-
|
|
3
|
-
## Status
|
|
4
|
-
|
|
5
|
-
Accepted
|
|
6
|
-
|
|
7
|
-
## Context
|
|
8
|
-
|
|
9
|
-
Rule profiles define paths, log sources and class locations that differ by service and by environment. Users need to override one field without copying an entire profile, and they need to understand why a resolved value is what it is.
|
|
10
|
-
|
|
11
|
-
Alternatives: a single flat profile per deployment, whole-object replacement, or embedding script hooks.
|
|
12
|
-
|
|
13
|
-
## Decision
|
|
14
|
-
|
|
15
|
-
Resolve rules in four ordered layers:
|
|
16
|
-
|
|
17
|
-
1. global defaults
|
|
18
|
-
2. service `ruleProfileRefs`, in list order
|
|
19
|
-
3. environment `ruleOverrides`
|
|
20
|
-
4. deployment `variables` and `ruleOverrides`
|
|
21
|
-
|
|
22
|
-
Merging is field-level. Every returned field carries provenance: the winning layer, the referenced inputs with their own sources, and the shadowed definitions.
|
|
23
|
-
|
|
24
|
-
Templates support `${...}` interpolation only. No functions, operators or code.
|
|
25
|
-
|
|
26
|
-
## Consequences
|
|
27
|
-
|
|
28
|
-
- An environment can override `paths.logDir` without touching `paths.jar`.
|
|
29
|
-
- A field defined at the service layer can still change because an input was overridden; provenance makes that visible.
|
|
30
|
-
- Validation must detect cycles and undefined references before returning anything.
|
|
31
|
-
- Users see derived values as derived; they are not implied to exist.
|
|
32
|
-
|
|
33
|
-
## Alternatives Considered
|
|
34
|
-
|
|
35
|
-
- **Whole-object replacement**: simple but forces duplication and hides intent.
|
|
36
|
-
- **Script hooks**: powerful but unreviewable in production and outside the safety model.
|
|
1
|
+
# ADR-0005: Layered Rule Resolution with Provenance
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
Rule profiles define paths, log sources and class locations that differ by service and by environment. Users need to override one field without copying an entire profile, and they need to understand why a resolved value is what it is.
|
|
10
|
+
|
|
11
|
+
Alternatives: a single flat profile per deployment, whole-object replacement, or embedding script hooks.
|
|
12
|
+
|
|
13
|
+
## Decision
|
|
14
|
+
|
|
15
|
+
Resolve rules in four ordered layers:
|
|
16
|
+
|
|
17
|
+
1. global defaults
|
|
18
|
+
2. service `ruleProfileRefs`, in list order
|
|
19
|
+
3. environment `ruleOverrides`
|
|
20
|
+
4. deployment `variables` and `ruleOverrides`
|
|
21
|
+
|
|
22
|
+
Merging is field-level. Every returned field carries provenance: the winning layer, the referenced inputs with their own sources, and the shadowed definitions.
|
|
23
|
+
|
|
24
|
+
Templates support `${...}` interpolation only. No functions, operators or code.
|
|
25
|
+
|
|
26
|
+
## Consequences
|
|
27
|
+
|
|
28
|
+
- An environment can override `paths.logDir` without touching `paths.jar`.
|
|
29
|
+
- A field defined at the service layer can still change because an input was overridden; provenance makes that visible.
|
|
30
|
+
- Validation must detect cycles and undefined references before returning anything.
|
|
31
|
+
- Users see derived values as derived; they are not implied to exist.
|
|
32
|
+
|
|
33
|
+
## Alternatives Considered
|
|
34
|
+
|
|
35
|
+
- **Whole-object replacement**: simple but forces duplication and hides intent.
|
|
36
|
+
- **Script hooks**: powerful but unreviewable in production and outside the safety model.
|
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
# ADR-0006: Credentials Are References
|
|
2
|
-
|
|
3
|
-
## Status
|
|
4
|
-
|
|
5
|
-
Accepted
|
|
6
|
-
|
|
7
|
-
## Context
|
|
8
|
-
|
|
9
|
-
The registry describes production hosts, clusters and services. Operators will want the Agent to "log in" or "use the credential for test-a".
|
|
10
|
-
|
|
11
|
-
Storing values in the registry would make the YAML files a secret store, would leak through tool output and Git history, and would duplicate the DSH credential service.
|
|
12
|
-
|
|
13
|
-
## Decision
|
|
14
|
-
|
|
15
|
-
1. Registry records store only `credentialRef` strings.
|
|
16
|
-
2. Credential status is obtained with `ctx.credentials.describe(ref)` and reduced to
|
|
17
|
-
`{ configured, source? }`.
|
|
18
|
-
3. The plugin never calls `ctx.credentials.resolve(ref)` and never forwards a credential value.
|
|
19
|
-
4. Tool and HTTP output expose `{ ref, configured, source? }` only.
|
|
20
|
-
|
|
21
|
-
## Consequences
|
|
22
|
-
|
|
23
|
-
- Secrets stay in the DSH credential service or an external vault.
|
|
24
|
-
- The plugin cannot authenticate anything itself; execution adapters (future) must obtain credentials through the proper service.
|
|
25
|
-
- A wrong reference cannot be detected beyond `configured: true/false`; operational review remains necessary.
|
|
26
|
-
|
|
27
|
-
## Alternatives Considered
|
|
28
|
-
|
|
29
|
-
- **Store values in YAML**: unacceptable for Git history and tool output.
|
|
30
|
-
- **Skip references entirely**: loses the link between a host and its credential, which users need.
|
|
1
|
+
# ADR-0006: Credentials Are References
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
The registry describes production hosts, clusters and services. Operators will want the Agent to "log in" or "use the credential for test-a".
|
|
10
|
+
|
|
11
|
+
Storing values in the registry would make the YAML files a secret store, would leak through tool output and Git history, and would duplicate the DSH credential service.
|
|
12
|
+
|
|
13
|
+
## Decision
|
|
14
|
+
|
|
15
|
+
1. Registry records store only `credentialRef` strings.
|
|
16
|
+
2. Credential status is obtained with `ctx.credentials.describe(ref)` and reduced to
|
|
17
|
+
`{ configured, source? }`.
|
|
18
|
+
3. The plugin never calls `ctx.credentials.resolve(ref)` and never forwards a credential value.
|
|
19
|
+
4. Tool and HTTP output expose `{ ref, configured, source? }` only.
|
|
20
|
+
|
|
21
|
+
## Consequences
|
|
22
|
+
|
|
23
|
+
- Secrets stay in the DSH credential service or an external vault.
|
|
24
|
+
- The plugin cannot authenticate anything itself; execution adapters (future) must obtain credentials through the proper service.
|
|
25
|
+
- A wrong reference cannot be detected beyond `configured: true/false`; operational review remains necessary.
|
|
26
|
+
|
|
27
|
+
## Alternatives Considered
|
|
28
|
+
|
|
29
|
+
- **Store values in YAML**: unacceptable for Git history and tool output.
|
|
30
|
+
- **Skip references entirely**: loses the link between a host and its credential, which users need.
|
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
# ADR-0007: Session-Scoped Default Environment
|
|
2
|
-
|
|
3
|
-
## Status
|
|
4
|
-
|
|
5
|
-
Accepted
|
|
6
|
-
|
|
7
|
-
## Context
|
|
8
|
-
|
|
9
|
-
Users work in one environment at a time and do not want to repeat "test-a" in every request. A shared global default would let one session silently change another session's target, which is unsafe.
|
|
10
|
-
|
|
11
|
-
## Decision
|
|
12
|
-
|
|
13
|
-
- The default environment is stored per session.
|
|
14
|
-
- `env_set_context` writes only the current session's value.
|
|
15
|
-
- Tools accept an explicit `environmentId` first; the session default is a fallback.
|
|
16
|
-
- The default is advisory: it never mutates registry records and never changes routing policy.
|
|
17
|
-
|
|
18
|
-
## Consequences
|
|
19
|
-
|
|
20
|
-
- Two sessions can target different environments concurrently (AC-07).
|
|
21
|
-
- Storage is a small JSON file per session under `<dataDir>/sessions/`; the DSH
|
|
22
|
-
projection store is not usable from a standalone bundle (`api-verification.md` F11).
|
|
23
|
-
- A session without a default must pass `environmentId` explicitly; the error names both options.
|
|
24
|
-
|
|
25
|
-
## Alternatives Considered
|
|
26
|
-
|
|
27
|
-
- **Profile-global default**: convenient but violates session isolation.
|
|
28
|
-
- **No default at all**: safe but adds friction to every call.
|
|
1
|
+
# ADR-0007: Session-Scoped Default Environment
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
Users work in one environment at a time and do not want to repeat "test-a" in every request. A shared global default would let one session silently change another session's target, which is unsafe.
|
|
10
|
+
|
|
11
|
+
## Decision
|
|
12
|
+
|
|
13
|
+
- The default environment is stored per session.
|
|
14
|
+
- `env_set_context` writes only the current session's value.
|
|
15
|
+
- Tools accept an explicit `environmentId` first; the session default is a fallback.
|
|
16
|
+
- The default is advisory: it never mutates registry records and never changes routing policy.
|
|
17
|
+
|
|
18
|
+
## Consequences
|
|
19
|
+
|
|
20
|
+
- Two sessions can target different environments concurrently (AC-07).
|
|
21
|
+
- Storage is a small JSON file per session under `<dataDir>/sessions/`; the DSH
|
|
22
|
+
projection store is not usable from a standalone bundle (`api-verification.md` F11).
|
|
23
|
+
- A session without a default must pass `environmentId` explicitly; the error names both options.
|
|
24
|
+
|
|
25
|
+
## Alternatives Considered
|
|
26
|
+
|
|
27
|
+
- **Profile-global default**: convenient but violates session isolation.
|
|
28
|
+
- **No default at all**: safe but adds friction to every call.
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
# ADR-0008: Memory Bridge Instead of a Second Memory Store
|
|
2
|
-
|
|
3
|
-
## Status
|
|
4
|
-
|
|
5
|
-
Accepted
|
|
6
|
-
|
|
7
|
-
## Context
|
|
8
|
-
|
|
9
|
-
The brainstorm originally considered a standalone memory plugin with structured categories. The project already depends on a memory plugin for durable knowledge, decisions, playbooks and open questions.
|
|
10
|
-
|
|
11
|
-
Building a second store would duplicate environment facts and split the place where lessons live.
|
|
12
|
-
|
|
13
|
-
## Decision
|
|
14
|
-
|
|
15
|
-
- DSH Environment Manager owns environment facts, service catalog, deployment bindings, rules and operation bindings.
|
|
16
|
-
- The memory plugin owns durable knowledge: observations, playbooks, decisions and proposals.
|
|
17
|
-
- The bridge exchanges scoped references, never copies of registry data.
|
|
18
|
-
- V1 ships the contract and a null adapter; P1 implements the adapter.
|
|
19
|
-
- Nothing in the bridge auto-applies a change.
|
|
20
|
-
|
|
21
|
-
## Consequences
|
|
22
|
-
|
|
23
|
-
- One place for facts, one place for knowledge.
|
|
24
|
-
- Memory entries must carry `environmentId`/`serviceId`/`deploymentId` scope.
|
|
25
|
-
- A single-environment conclusion cannot silently become a global rule.
|
|
26
|
-
- The bridge contract must be versioned when the memory plugin changes.
|
|
27
|
-
|
|
28
|
-
## Alternatives Considered
|
|
29
|
-
|
|
30
|
-
- **Own memory store**: duplicates scope, evidence and review logic.
|
|
31
|
-
- **No integration**: the improvement loop from the brainstorm cannot close.
|
|
1
|
+
# ADR-0008: Memory Bridge Instead of a Second Memory Store
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
The brainstorm originally considered a standalone memory plugin with structured categories. The project already depends on a memory plugin for durable knowledge, decisions, playbooks and open questions.
|
|
10
|
+
|
|
11
|
+
Building a second store would duplicate environment facts and split the place where lessons live.
|
|
12
|
+
|
|
13
|
+
## Decision
|
|
14
|
+
|
|
15
|
+
- DSH Environment Manager owns environment facts, service catalog, deployment bindings, rules and operation bindings.
|
|
16
|
+
- The memory plugin owns durable knowledge: observations, playbooks, decisions and proposals.
|
|
17
|
+
- The bridge exchanges scoped references, never copies of registry data.
|
|
18
|
+
- V1 ships the contract and a null adapter; P1 implements the adapter.
|
|
19
|
+
- Nothing in the bridge auto-applies a change.
|
|
20
|
+
|
|
21
|
+
## Consequences
|
|
22
|
+
|
|
23
|
+
- One place for facts, one place for knowledge.
|
|
24
|
+
- Memory entries must carry `environmentId`/`serviceId`/`deploymentId` scope.
|
|
25
|
+
- A single-environment conclusion cannot silently become a global rule.
|
|
26
|
+
- The bridge contract must be versioned when the memory plugin changes.
|
|
27
|
+
|
|
28
|
+
## Alternatives Considered
|
|
29
|
+
|
|
30
|
+
- **Own memory store**: duplicates scope, evidence and review logic.
|
|
31
|
+
- **No integration**: the improvement loop from the brainstorm cannot close.
|
|
@@ -1,87 +1,87 @@
|
|
|
1
|
-
# ADR-0009: Client–Host transport via a plugin-owned HTTP route
|
|
2
|
-
|
|
3
|
-
- Status: accepted
|
|
4
|
-
- Date: 2026-11-01
|
|
5
|
-
- Supersedes: none
|
|
6
|
-
- Related: ADR-0004 (TypeScript Host, plain-JS Client), `api-verification.md` F9–F14
|
|
7
|
-
|
|
8
|
-
## Context
|
|
9
|
-
|
|
10
|
-
The V1 panel must list, edit and validate registry records. The data lives in the Host
|
|
11
|
-
process; the Client half runs in the browser page. A transport is therefore required.
|
|
12
|
-
|
|
13
|
-
DSH's native mechanism is the Typert Remote system:
|
|
14
|
-
|
|
15
|
-
- the Host defines a service extending `TypertRemoteService` and marks methods with
|
|
16
|
-
`@Remote` / `@RemoteScope`;
|
|
17
|
-
- a build-time Typert loader emits an `InvocationDescriptor` and a `/remote` artifact;
|
|
18
|
-
- the Client imports that artifact, mounts it through `ctx.remote.$mount()`, and calls
|
|
19
|
-
generated methods;
|
|
20
|
-
- the Gateway rejects Client-supplied fields that lack a strict generated codec.
|
|
21
|
-
|
|
22
|
-
That pipeline assumes the DSH monorepo build toolchain and a matching DSH release.
|
|
23
|
-
This repository is a standalone bundle compiled with plain `tsc`, and the runtime
|
|
24
|
-
provides no API for registering a Remote namespace from plain JavaScript.
|
|
25
|
-
|
|
26
|
-
## Decision
|
|
27
|
-
|
|
28
|
-
The plugin registers one same-origin HTTP route and the Client calls it:
|
|
29
|
-
|
|
30
|
-
```text
|
|
31
|
-
POST /env-manager/api
|
|
32
|
-
headers: content-type: application/json
|
|
33
|
-
x-env-manager-request: 1
|
|
34
|
-
body: { "op": "...", "payload": { ... } }
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
- The route is registered with `ctx.webServer.register({ kind: 'prefix', ... })` and
|
|
38
|
-
disposed with the plugin fiber.
|
|
39
|
-
- The route handler is a thin adapter over the same application service the tools use;
|
|
40
|
-
there is no second business path.
|
|
41
|
-
- Authentication is a required custom header plus an `Origin` equality check against
|
|
42
|
-
`ctx.webServer.getOrigin()`. No cookie or credential is read. No CORS headers are
|
|
43
|
-
sent, so a cross-origin page cannot preflight the custom header.
|
|
44
|
-
- Every request is validated server-side; the Client's TypeScript-free code is never
|
|
45
|
-
trusted for shape.
|
|
46
|
-
- Writes from this route run with actor `'ui'` and are subject to
|
|
47
|
-
`writePolicy.allowUiProductionWrites`; deletes require an explicit `confirm: true`.
|
|
48
|
-
|
|
49
|
-
## Consequences
|
|
50
|
-
|
|
51
|
-
Positive:
|
|
52
|
-
|
|
53
|
-
- No dependency on the Typert codegen toolchain or on a matching DSH release.
|
|
54
|
-
- One transport for tools and UI, so behavior cannot drift.
|
|
55
|
-
- Simple to test with Node's `http` mocks and `curl`.
|
|
56
|
-
- No streaming requirement in V1, so request/response is sufficient.
|
|
57
|
-
|
|
58
|
-
Negative:
|
|
59
|
-
|
|
60
|
-
- The Client has no generated type contract; shared shapes are maintained by hand and
|
|
61
|
-
checked by tests.
|
|
62
|
-
- A new local HTTP surface exists. It is header-gated, origin-checked, read-only for
|
|
63
|
-
credentials, and cannot be reached cross-origin without a preflight the server
|
|
64
|
-
refuses.
|
|
65
|
-
- No streaming or subscriptions; the UI refreshes explicitly.
|
|
66
|
-
- Session-scoped operations are not exposed to the UI in V1, because the UI has no
|
|
67
|
-
trustworthy session identity.
|
|
68
|
-
|
|
69
|
-
## Alternatives
|
|
70
|
-
|
|
71
|
-
| Alternative | Why rejected |
|
|
72
|
-
|---|---|
|
|
73
|
-
| Typert Remote namespace | Requires build-time descriptors and DSH monorepo tooling; impossible from plain JS |
|
|
74
|
-
| Client reads registry files directly | The browser has no filesystem access, and it would bypass Host validation |
|
|
75
|
-
| Agent-mediated UI (buttons insert prompts) | Poor UX; every inspection would consume a turn |
|
|
76
|
-
| WebSocket / streaming | V1 has no live-update requirement |
|
|
77
|
-
| `window.__DSH_BOOT__` global injection of data | One-shot snapshot, no writes, stale immediately |
|
|
78
|
-
|
|
79
|
-
## Review trigger
|
|
80
|
-
|
|
81
|
-
Revisit when either becomes true:
|
|
82
|
-
|
|
83
|
-
1. DSH exposes a runtime API to register an `InvocationDescriptor` from a bundle, or
|
|
84
|
-
2. this repository adopts the DSH build toolchain and can emit `/remote` artifacts.
|
|
85
|
-
|
|
86
|
-
At that point the HTTP adapter can be replaced without changing the application service
|
|
87
|
-
or the tools.
|
|
1
|
+
# ADR-0009: Client–Host transport via a plugin-owned HTTP route
|
|
2
|
+
|
|
3
|
+
- Status: accepted
|
|
4
|
+
- Date: 2026-11-01
|
|
5
|
+
- Supersedes: none
|
|
6
|
+
- Related: ADR-0004 (TypeScript Host, plain-JS Client), `api-verification.md` F9–F14
|
|
7
|
+
|
|
8
|
+
## Context
|
|
9
|
+
|
|
10
|
+
The V1 panel must list, edit and validate registry records. The data lives in the Host
|
|
11
|
+
process; the Client half runs in the browser page. A transport is therefore required.
|
|
12
|
+
|
|
13
|
+
DSH's native mechanism is the Typert Remote system:
|
|
14
|
+
|
|
15
|
+
- the Host defines a service extending `TypertRemoteService` and marks methods with
|
|
16
|
+
`@Remote` / `@RemoteScope`;
|
|
17
|
+
- a build-time Typert loader emits an `InvocationDescriptor` and a `/remote` artifact;
|
|
18
|
+
- the Client imports that artifact, mounts it through `ctx.remote.$mount()`, and calls
|
|
19
|
+
generated methods;
|
|
20
|
+
- the Gateway rejects Client-supplied fields that lack a strict generated codec.
|
|
21
|
+
|
|
22
|
+
That pipeline assumes the DSH monorepo build toolchain and a matching DSH release.
|
|
23
|
+
This repository is a standalone bundle compiled with plain `tsc`, and the runtime
|
|
24
|
+
provides no API for registering a Remote namespace from plain JavaScript.
|
|
25
|
+
|
|
26
|
+
## Decision
|
|
27
|
+
|
|
28
|
+
The plugin registers one same-origin HTTP route and the Client calls it:
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
POST /env-manager/api
|
|
32
|
+
headers: content-type: application/json
|
|
33
|
+
x-env-manager-request: 1
|
|
34
|
+
body: { "op": "...", "payload": { ... } }
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
- The route is registered with `ctx.webServer.register({ kind: 'prefix', ... })` and
|
|
38
|
+
disposed with the plugin fiber.
|
|
39
|
+
- The route handler is a thin adapter over the same application service the tools use;
|
|
40
|
+
there is no second business path.
|
|
41
|
+
- Authentication is a required custom header plus an `Origin` equality check against
|
|
42
|
+
`ctx.webServer.getOrigin()`. No cookie or credential is read. No CORS headers are
|
|
43
|
+
sent, so a cross-origin page cannot preflight the custom header.
|
|
44
|
+
- Every request is validated server-side; the Client's TypeScript-free code is never
|
|
45
|
+
trusted for shape.
|
|
46
|
+
- Writes from this route run with actor `'ui'` and are subject to
|
|
47
|
+
`writePolicy.allowUiProductionWrites`; deletes require an explicit `confirm: true`.
|
|
48
|
+
|
|
49
|
+
## Consequences
|
|
50
|
+
|
|
51
|
+
Positive:
|
|
52
|
+
|
|
53
|
+
- No dependency on the Typert codegen toolchain or on a matching DSH release.
|
|
54
|
+
- One transport for tools and UI, so behavior cannot drift.
|
|
55
|
+
- Simple to test with Node's `http` mocks and `curl`.
|
|
56
|
+
- No streaming requirement in V1, so request/response is sufficient.
|
|
57
|
+
|
|
58
|
+
Negative:
|
|
59
|
+
|
|
60
|
+
- The Client has no generated type contract; shared shapes are maintained by hand and
|
|
61
|
+
checked by tests.
|
|
62
|
+
- A new local HTTP surface exists. It is header-gated, origin-checked, read-only for
|
|
63
|
+
credentials, and cannot be reached cross-origin without a preflight the server
|
|
64
|
+
refuses.
|
|
65
|
+
- No streaming or subscriptions; the UI refreshes explicitly.
|
|
66
|
+
- Session-scoped operations are not exposed to the UI in V1, because the UI has no
|
|
67
|
+
trustworthy session identity.
|
|
68
|
+
|
|
69
|
+
## Alternatives
|
|
70
|
+
|
|
71
|
+
| Alternative | Why rejected |
|
|
72
|
+
|---|---|
|
|
73
|
+
| Typert Remote namespace | Requires build-time descriptors and DSH monorepo tooling; impossible from plain JS |
|
|
74
|
+
| Client reads registry files directly | The browser has no filesystem access, and it would bypass Host validation |
|
|
75
|
+
| Agent-mediated UI (buttons insert prompts) | Poor UX; every inspection would consume a turn |
|
|
76
|
+
| WebSocket / streaming | V1 has no live-update requirement |
|
|
77
|
+
| `window.__DSH_BOOT__` global injection of data | One-shot snapshot, no writes, stale immediately |
|
|
78
|
+
|
|
79
|
+
## Review trigger
|
|
80
|
+
|
|
81
|
+
Revisit when either becomes true:
|
|
82
|
+
|
|
83
|
+
1. DSH exposes a runtime API to register an `InvocationDescriptor` from a bundle, or
|
|
84
|
+
2. this repository adopts the DSH build toolchain and can emit `/remote` artifacts.
|
|
85
|
+
|
|
86
|
+
At that point the HTTP adapter can be replaced without changing the application service
|
|
87
|
+
or the tools.
|