@ran-sh/dsh-crew 0.3.5 → 0.3.7

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/.claude-plugin/plugin.json +8 -8
  2. package/.mcp.json +8 -8
  3. package/LICENSE +21 -21
  4. package/README.de.md +359 -359
  5. package/README.es.md +359 -359
  6. package/README.fr.md +359 -359
  7. package/README.hi.md +359 -359
  8. package/README.id.md +359 -359
  9. package/README.ja.md +359 -359
  10. package/README.ko.md +359 -359
  11. package/README.md +125 -180
  12. package/README.pt.md +359 -359
  13. package/README.ru.md +359 -359
  14. package/README.th.md +359 -359
  15. package/README.tr.md +359 -359
  16. package/README.vi.md +359 -359
  17. package/README.zh-TW.md +359 -359
  18. package/README.zh.md +125 -180
  19. package/agents/ds-flash.md +26 -26
  20. package/agents/ds-pro.md +32 -32
  21. package/agents/ds-reviewer.md +23 -23
  22. package/agents/ds-worker.md +22 -22
  23. package/codex/agents/ds-flash.toml +30 -30
  24. package/codex/agents/ds-pro.toml +31 -31
  25. package/codex/agents/ds-reviewer.toml +28 -28
  26. package/codex/agents/ds-worker.toml +28 -28
  27. package/codex/prompts/dsh-config.md +3 -3
  28. package/codex/prompts/dsh-status.md +1 -1
  29. package/commands/config.md +11 -11
  30. package/commands/off.md +5 -5
  31. package/commands/on.md +5 -5
  32. package/commands/status.md +5 -5
  33. package/cordis.patch.yml +4 -4
  34. package/lib/client.js +3446 -2765
  35. package/package.json +131 -131
  36. package/scripts/build-client.mjs +28 -28
  37. package/scripts/live-crew-smoke.mjs +39 -39
  38. package/scripts/live-policy-matrix.mjs +177 -177
  39. package/scripts/policy-probe.mjs +101 -101
  40. package/scripts/setup.mjs +284 -284
  41. package/scripts/smoke-real.mjs +110 -110
  42. package/scripts/smoke.mjs +78 -78
  43. package/scripts/verify-installer-fix.mjs +26 -26
  44. package/src/adaptive-routing.mjs +260 -260
  45. package/src/client/activation-summary.tsx +64 -64
  46. package/src/client/collapsible-sections.mjs +55 -0
  47. package/src/client/entry.tsx +236 -236
  48. package/src/client/index.tsx +1213 -1120
  49. package/src/config-readiness.mjs +59 -59
  50. package/src/delivery.mjs +205 -205
  51. package/src/dsh-cli-runtime.mjs +239 -239
  52. package/src/failure-classification.mjs +172 -172
  53. package/src/hub/entry.mjs +98 -98
  54. package/src/hub-client.mjs +132 -132
  55. package/src/hub-compatibility.mjs +49 -49
  56. package/src/i18n.mjs +19 -19
  57. package/src/install/cli.mjs +28 -28
  58. package/src/install/install-legacy.mjs +462 -462
  59. package/src/install/install.mjs +451 -451
  60. package/src/install/npx-lifecycle.mjs +1055 -1019
  61. package/src/mcp-runtime.mjs +257 -257
  62. package/src/model-catalog.mjs +173 -173
  63. package/src/model-routing.mjs +391 -391
  64. package/src/policy.mjs +197 -197
  65. package/src/readiness-matrix.mjs +169 -169
  66. package/src/runtime-controls.mjs +90 -90
  67. package/src/runtime-identity.mjs +108 -108
  68. package/src/server.mjs +477 -477
  69. package/src/status-shard.mjs +52 -52
  70. package/src/structured-error-code.mjs +38 -38
  71. package/src/vision-route.mjs +138 -138
  72. package/src/workflow-runtime.mjs +573 -573
  73. package/src/workflow.mjs +160 -160
  74. package/src/workspace-audit.mjs +231 -231
  75. package/src/workspace-isolation.mjs +365 -365
  76. package/statusline/statusline.sh +14 -14
  77. package/statusline/worker-segment.sh +35 -35
  78. package/worker.cordis.yml +77 -77
@@ -1,169 +1,169 @@
1
- // Conservative release/environment readiness matrix.
2
- //
3
- // A row is PASS only when the caller supplies direct evidence for that row.
4
- // Missing evidence is NOT_RUN, not an inferred success. Runtime observations
5
- // (Hub handshake / catalog read) are intentionally separate from execution
6
- // verification (real worker, reviewer, cancellation, timeout, etc.).
7
-
8
- export const READINESS_STATUSES = Object.freeze(['PASS', 'FAIL', 'BLOCKED', 'SKIP', 'NOT_RUN']);
9
-
10
- export const READINESS_REASON_CODES = Object.freeze({
11
- LIVE_CHECK_PASSED: 'LIVE_CHECK_PASSED',
12
- HUB_UNREACHABLE: 'HUB_UNREACHABLE',
13
- HUB_INCOMPATIBLE: 'HUB_INCOMPATIBLE',
14
- PROVIDER_CATALOG_RESOLVED: 'PROVIDER_CATALOG_RESOLVED',
15
- PROVIDER_CATALOG_UNAVAILABLE: 'PROVIDER_CATALOG_UNAVAILABLE',
16
- PROVIDER_CATALOG_HEALTH_WARNING: 'PROVIDER_CATALOG_HEALTH_WARNING',
17
- PROVIDER_CATALOG_NOT_REQUIRED: 'PROVIDER_CATALOG_NOT_REQUIRED',
18
- PROVIDER_MODE_UNKNOWN: 'PROVIDER_MODE_UNKNOWN',
19
- NO_CI_EVIDENCE: 'NO_CI_EVIDENCE',
20
- NO_EXECUTION_EVIDENCE: 'NO_EXECUTION_EVIDENCE',
21
- CREDENTIAL_STATUS_NOT_PROBED: 'CREDENTIAL_STATUS_NOT_PROBED',
22
- EVIDENCE_REPORTED: 'EVIDENCE_REPORTED',
23
- });
24
-
25
- const TARGET_ROWS = Object.freeze([
26
- ['linux_deterministic', 'ci'],
27
- ['windows_regressions', 'ci'],
28
- ['macos_smoke', 'ci'],
29
- ['hub_compatibility', 'live-runtime'],
30
- ['provider_catalog', 'live-runtime'],
31
- ['deepseek_flash', 'real-execution'],
32
- ['deepseek_pro', 'real-execution'],
33
- ['opencode_go_mimo_qwen', 'real-execution'],
34
- ['reviewer_pipeline', 'real-execution'],
35
- ['cancellation_timeout_escalation', 'real-execution'],
36
- ['standalone_official', 'real-execution'],
37
- ]);
38
-
39
- function baseRow(id, category, status, reasonCode, evidenceSource = 'none', extra = {}) {
40
- return {
41
- id,
42
- category,
43
- status,
44
- reason_code: reasonCode,
45
- evidence_source: evidenceSource,
46
- ...extra,
47
- };
48
- }
49
-
50
- function normalizeEvidence(row, evidence) {
51
- if (!evidence || typeof evidence !== 'object') return row;
52
- if (!READINESS_STATUSES.includes(evidence.status)) return row;
53
- const reason = typeof evidence.reason_code === 'string' && evidence.reason_code.trim()
54
- ? evidence.reason_code.trim()
55
- : READINESS_REASON_CODES.EVIDENCE_REPORTED;
56
- const source = typeof evidence.evidence_source === 'string' && evidence.evidence_source.trim()
57
- ? evidence.evidence_source.trim()
58
- : 'reported-evidence';
59
- return {
60
- ...row,
61
- status: evidence.status,
62
- reason_code: reason,
63
- evidence_source: source,
64
- ...(typeof evidence.evidence_ref === 'string' && evidence.evidence_ref.trim()
65
- ? { evidence_ref: evidence.evidence_ref.trim() }
66
- : {}),
67
- };
68
- }
69
-
70
- function defaultRows() {
71
- return Object.fromEntries(TARGET_ROWS.map(([id, category]) => {
72
- const reason = category === 'ci'
73
- ? READINESS_REASON_CODES.NO_CI_EVIDENCE
74
- : id === 'standalone_official'
75
- ? READINESS_REASON_CODES.CREDENTIAL_STATUS_NOT_PROBED
76
- : READINESS_REASON_CODES.NO_EXECUTION_EVIDENCE;
77
- return [id, baseRow(id, category, 'NOT_RUN', reason)];
78
- }));
79
- }
80
-
81
- /**
82
- * Build a secret-free readiness matrix from direct runtime observations plus
83
- * optional trusted evidence supplied by a higher layer.
84
- *
85
- * `evidence` is deliberately inert metadata: this module never reads files,
86
- * credentials, GitHub, provider config, or the network on its own.
87
- */
88
- export function buildReadinessMatrix({
89
- platform = process.platform,
90
- hubCompatibility = null,
91
- workerProviderMode = null,
92
- providerCatalogChecked = false,
93
- providerCatalogOk = false,
94
- evidence = {},
95
- } = {}) {
96
- const rows = defaultRows();
97
-
98
- if (hubCompatibility?.compatible === true) {
99
- rows.hub_compatibility = baseRow(
100
- 'hub_compatibility', 'live-runtime', 'PASS',
101
- READINESS_REASON_CODES.LIVE_CHECK_PASSED, 'hub-handshake',
102
- {
103
- runtime_version: hubCompatibility.runtime_version ?? null,
104
- protocol_version: hubCompatibility.protocol_version ?? null,
105
- },
106
- );
107
- } else if (hubCompatibility?.reachable === true) {
108
- rows.hub_compatibility = baseRow(
109
- 'hub_compatibility', 'live-runtime', 'FAIL',
110
- READINESS_REASON_CODES.HUB_INCOMPATIBLE, 'hub-handshake',
111
- { detail_code: hubCompatibility.code ?? null },
112
- );
113
- } else {
114
- rows.hub_compatibility = baseRow(
115
- 'hub_compatibility', 'live-runtime', 'BLOCKED',
116
- READINESS_REASON_CODES.HUB_UNREACHABLE, 'hub-handshake',
117
- { detail_code: hubCompatibility?.code ?? null },
118
- );
119
- }
120
-
121
- if (workerProviderMode == null) {
122
- rows.provider_catalog = baseRow(
123
- 'provider_catalog', 'live-runtime', 'NOT_RUN',
124
- READINESS_REASON_CODES.PROVIDER_MODE_UNKNOWN, 'none',
125
- );
126
- } else if (workerProviderMode === 'deepseek-official') {
127
- rows.provider_catalog = baseRow(
128
- 'provider_catalog', 'live-runtime', 'SKIP',
129
- READINESS_REASON_CODES.PROVIDER_CATALOG_NOT_REQUIRED, 'runtime-policy',
130
- );
131
- } else if (!hubCompatibility?.compatible) {
132
- rows.provider_catalog = baseRow(
133
- 'provider_catalog', 'live-runtime', 'BLOCKED',
134
- hubCompatibility?.reachable
135
- ? READINESS_REASON_CODES.HUB_INCOMPATIBLE
136
- : READINESS_REASON_CODES.HUB_UNREACHABLE,
137
- 'hub-handshake',
138
- { detail_code: hubCompatibility?.code ?? null },
139
- );
140
- } else if (providerCatalogChecked && providerCatalogOk) {
141
- rows.provider_catalog = baseRow(
142
- 'provider_catalog', 'live-runtime', 'PASS',
143
- READINESS_REASON_CODES.PROVIDER_CATALOG_RESOLVED, 'harness-catalog',
144
- );
145
- } else if (providerCatalogChecked) {
146
- rows.provider_catalog = baseRow(
147
- 'provider_catalog', 'live-runtime', 'FAIL',
148
- READINESS_REASON_CODES.PROVIDER_CATALOG_UNAVAILABLE, 'harness-catalog',
149
- );
150
- }
151
-
152
- for (const [id] of TARGET_ROWS) {
153
- rows[id] = normalizeEvidence(rows[id], evidence?.[id]);
154
- }
155
-
156
- const ordered = TARGET_ROWS.map(([id]) => rows[id]);
157
- const counts = Object.fromEntries(READINESS_STATUSES.map((status) => [
158
- status,
159
- ordered.filter((row) => row.status === status).length,
160
- ]));
161
-
162
- return {
163
- schema_version: 1,
164
- platform,
165
- conservative: true,
166
- summary: counts,
167
- rows: ordered,
168
- };
169
- }
1
+ // Conservative release/environment readiness matrix.
2
+ //
3
+ // A row is PASS only when the caller supplies direct evidence for that row.
4
+ // Missing evidence is NOT_RUN, not an inferred success. Runtime observations
5
+ // (Hub handshake / catalog read) are intentionally separate from execution
6
+ // verification (real worker, reviewer, cancellation, timeout, etc.).
7
+
8
+ export const READINESS_STATUSES = Object.freeze(['PASS', 'FAIL', 'BLOCKED', 'SKIP', 'NOT_RUN']);
9
+
10
+ export const READINESS_REASON_CODES = Object.freeze({
11
+ LIVE_CHECK_PASSED: 'LIVE_CHECK_PASSED',
12
+ HUB_UNREACHABLE: 'HUB_UNREACHABLE',
13
+ HUB_INCOMPATIBLE: 'HUB_INCOMPATIBLE',
14
+ PROVIDER_CATALOG_RESOLVED: 'PROVIDER_CATALOG_RESOLVED',
15
+ PROVIDER_CATALOG_UNAVAILABLE: 'PROVIDER_CATALOG_UNAVAILABLE',
16
+ PROVIDER_CATALOG_HEALTH_WARNING: 'PROVIDER_CATALOG_HEALTH_WARNING',
17
+ PROVIDER_CATALOG_NOT_REQUIRED: 'PROVIDER_CATALOG_NOT_REQUIRED',
18
+ PROVIDER_MODE_UNKNOWN: 'PROVIDER_MODE_UNKNOWN',
19
+ NO_CI_EVIDENCE: 'NO_CI_EVIDENCE',
20
+ NO_EXECUTION_EVIDENCE: 'NO_EXECUTION_EVIDENCE',
21
+ CREDENTIAL_STATUS_NOT_PROBED: 'CREDENTIAL_STATUS_NOT_PROBED',
22
+ EVIDENCE_REPORTED: 'EVIDENCE_REPORTED',
23
+ });
24
+
25
+ const TARGET_ROWS = Object.freeze([
26
+ ['linux_deterministic', 'ci'],
27
+ ['windows_regressions', 'ci'],
28
+ ['macos_smoke', 'ci'],
29
+ ['hub_compatibility', 'live-runtime'],
30
+ ['provider_catalog', 'live-runtime'],
31
+ ['deepseek_flash', 'real-execution'],
32
+ ['deepseek_pro', 'real-execution'],
33
+ ['opencode_go_mimo_qwen', 'real-execution'],
34
+ ['reviewer_pipeline', 'real-execution'],
35
+ ['cancellation_timeout_escalation', 'real-execution'],
36
+ ['standalone_official', 'real-execution'],
37
+ ]);
38
+
39
+ function baseRow(id, category, status, reasonCode, evidenceSource = 'none', extra = {}) {
40
+ return {
41
+ id,
42
+ category,
43
+ status,
44
+ reason_code: reasonCode,
45
+ evidence_source: evidenceSource,
46
+ ...extra,
47
+ };
48
+ }
49
+
50
+ function normalizeEvidence(row, evidence) {
51
+ if (!evidence || typeof evidence !== 'object') return row;
52
+ if (!READINESS_STATUSES.includes(evidence.status)) return row;
53
+ const reason = typeof evidence.reason_code === 'string' && evidence.reason_code.trim()
54
+ ? evidence.reason_code.trim()
55
+ : READINESS_REASON_CODES.EVIDENCE_REPORTED;
56
+ const source = typeof evidence.evidence_source === 'string' && evidence.evidence_source.trim()
57
+ ? evidence.evidence_source.trim()
58
+ : 'reported-evidence';
59
+ return {
60
+ ...row,
61
+ status: evidence.status,
62
+ reason_code: reason,
63
+ evidence_source: source,
64
+ ...(typeof evidence.evidence_ref === 'string' && evidence.evidence_ref.trim()
65
+ ? { evidence_ref: evidence.evidence_ref.trim() }
66
+ : {}),
67
+ };
68
+ }
69
+
70
+ function defaultRows() {
71
+ return Object.fromEntries(TARGET_ROWS.map(([id, category]) => {
72
+ const reason = category === 'ci'
73
+ ? READINESS_REASON_CODES.NO_CI_EVIDENCE
74
+ : id === 'standalone_official'
75
+ ? READINESS_REASON_CODES.CREDENTIAL_STATUS_NOT_PROBED
76
+ : READINESS_REASON_CODES.NO_EXECUTION_EVIDENCE;
77
+ return [id, baseRow(id, category, 'NOT_RUN', reason)];
78
+ }));
79
+ }
80
+
81
+ /**
82
+ * Build a secret-free readiness matrix from direct runtime observations plus
83
+ * optional trusted evidence supplied by a higher layer.
84
+ *
85
+ * `evidence` is deliberately inert metadata: this module never reads files,
86
+ * credentials, GitHub, provider config, or the network on its own.
87
+ */
88
+ export function buildReadinessMatrix({
89
+ platform = process.platform,
90
+ hubCompatibility = null,
91
+ workerProviderMode = null,
92
+ providerCatalogChecked = false,
93
+ providerCatalogOk = false,
94
+ evidence = {},
95
+ } = {}) {
96
+ const rows = defaultRows();
97
+
98
+ if (hubCompatibility?.compatible === true) {
99
+ rows.hub_compatibility = baseRow(
100
+ 'hub_compatibility', 'live-runtime', 'PASS',
101
+ READINESS_REASON_CODES.LIVE_CHECK_PASSED, 'hub-handshake',
102
+ {
103
+ runtime_version: hubCompatibility.runtime_version ?? null,
104
+ protocol_version: hubCompatibility.protocol_version ?? null,
105
+ },
106
+ );
107
+ } else if (hubCompatibility?.reachable === true) {
108
+ rows.hub_compatibility = baseRow(
109
+ 'hub_compatibility', 'live-runtime', 'FAIL',
110
+ READINESS_REASON_CODES.HUB_INCOMPATIBLE, 'hub-handshake',
111
+ { detail_code: hubCompatibility.code ?? null },
112
+ );
113
+ } else {
114
+ rows.hub_compatibility = baseRow(
115
+ 'hub_compatibility', 'live-runtime', 'BLOCKED',
116
+ READINESS_REASON_CODES.HUB_UNREACHABLE, 'hub-handshake',
117
+ { detail_code: hubCompatibility?.code ?? null },
118
+ );
119
+ }
120
+
121
+ if (workerProviderMode == null) {
122
+ rows.provider_catalog = baseRow(
123
+ 'provider_catalog', 'live-runtime', 'NOT_RUN',
124
+ READINESS_REASON_CODES.PROVIDER_MODE_UNKNOWN, 'none',
125
+ );
126
+ } else if (workerProviderMode === 'deepseek-official') {
127
+ rows.provider_catalog = baseRow(
128
+ 'provider_catalog', 'live-runtime', 'SKIP',
129
+ READINESS_REASON_CODES.PROVIDER_CATALOG_NOT_REQUIRED, 'runtime-policy',
130
+ );
131
+ } else if (!hubCompatibility?.compatible) {
132
+ rows.provider_catalog = baseRow(
133
+ 'provider_catalog', 'live-runtime', 'BLOCKED',
134
+ hubCompatibility?.reachable
135
+ ? READINESS_REASON_CODES.HUB_INCOMPATIBLE
136
+ : READINESS_REASON_CODES.HUB_UNREACHABLE,
137
+ 'hub-handshake',
138
+ { detail_code: hubCompatibility?.code ?? null },
139
+ );
140
+ } else if (providerCatalogChecked && providerCatalogOk) {
141
+ rows.provider_catalog = baseRow(
142
+ 'provider_catalog', 'live-runtime', 'PASS',
143
+ READINESS_REASON_CODES.PROVIDER_CATALOG_RESOLVED, 'harness-catalog',
144
+ );
145
+ } else if (providerCatalogChecked) {
146
+ rows.provider_catalog = baseRow(
147
+ 'provider_catalog', 'live-runtime', 'FAIL',
148
+ READINESS_REASON_CODES.PROVIDER_CATALOG_UNAVAILABLE, 'harness-catalog',
149
+ );
150
+ }
151
+
152
+ for (const [id] of TARGET_ROWS) {
153
+ rows[id] = normalizeEvidence(rows[id], evidence?.[id]);
154
+ }
155
+
156
+ const ordered = TARGET_ROWS.map(([id]) => rows[id]);
157
+ const counts = Object.fromEntries(READINESS_STATUSES.map((status) => [
158
+ status,
159
+ ordered.filter((row) => row.status === status).length,
160
+ ]));
161
+
162
+ return {
163
+ schema_version: 1,
164
+ platform,
165
+ conservative: true,
166
+ summary: counts,
167
+ rows: ordered,
168
+ };
169
+ }
@@ -1,90 +1,90 @@
1
- // Runtime control activation contract.
2
- //
3
- // This is deliberately data, not UI prose. MCP diagnostics and the Settings
4
- // surface consume the same boundary definitions so users are never told two
5
- // different stories about when a config change takes effect.
6
-
7
- export const ACTIVATION_BOUNDARY = Object.freeze({
8
- LIVE: 'live',
9
- NEXT_WORKFLOW: 'next-workflow',
10
- NEXT_SESSION: 'next-session',
11
- RESTART_REQUIRED: 'restart-required',
12
- });
13
-
14
- const N = ACTIVATION_BOUNDARY.NEXT_WORKFLOW;
15
- const S = ACTIVATION_BOUNDARY.NEXT_SESSION;
16
- const L = ACTIVATION_BOUNDARY.LIVE;
17
- const R = ACTIVATION_BOUNDARY.RESTART_REQUIRED;
18
-
19
- /**
20
- * `global` describes a write made through persisted Settings/config.
21
- * `session` describes an explicit dsh_worker_config override in the already
22
- * running MCP process. `session: null` means the setting is not a session
23
- * override surface.
24
- */
25
- export const RUNTIME_SETTING_ACTIVATION = Object.freeze({
26
- max_parallel: Object.freeze({ global: L, session: null, note: 'Admission limit refreshes before new workflow starts and when slots release; lowering never cancels active work.' }),
27
-
28
- subagents_enabled: Object.freeze({ global: N, session: N }),
29
- collaboration_mode: Object.freeze({ global: N, session: N }),
30
- main_agent_mode: Object.freeze({ global: N, session: N }),
31
- flash_state: Object.freeze({ global: N, session: N }),
32
- pro_state: Object.freeze({ global: N, session: N }),
33
- worker_state: Object.freeze({ global: N, session: N }),
34
- review_state: Object.freeze({ global: N, session: N }),
35
- auto_review: Object.freeze({ global: N, session: N }),
36
- pro_reviews_flash: Object.freeze({ global: N, session: N }),
37
- worker_provider_mode: Object.freeze({ global: N, session: null }),
38
- flash_model_priority: Object.freeze({ global: N, session: null }),
39
- flash_model_fallback: Object.freeze({ global: N, session: null }),
40
- pro_model_priority: Object.freeze({ global: N, session: null }),
41
- pro_model_fallback: Object.freeze({ global: N, session: null }),
42
- adaptive_routing: Object.freeze({ global: N, session: null, note: 'Opt-in provider health ordering is read for the next Hub model selection; existing explicit priorities remain authoritative.' }),
43
- isolation: Object.freeze({ global: N, session: null }),
44
- vision_provider: Object.freeze({ global: N, session: null }),
45
- vision_model: Object.freeze({ global: N, session: null }),
46
- imagegen_provider: Object.freeze({ global: N, session: null }),
47
-
48
- // These values are copied into the MCP session defaults at process startup.
49
- // dsh_worker_config can override them for subsequent workflows in that same
50
- // session, but persisted global edits require a new MCP session to inherit.
51
- default_tier: Object.freeze({ global: S, session: N }),
52
- default_effort: Object.freeze({ global: S, session: N }),
53
- mode: Object.freeze({ global: S, session: N }),
54
- default_timeout_seconds: Object.freeze({ global: S, session: N }),
55
- escalate_on_failure: Object.freeze({ global: S, session: N }),
56
- preset_flash: Object.freeze({ global: S, session: N }),
57
- preset_pro: Object.freeze({ global: S, session: N }),
58
-
59
- // hub-client freezes its base URL at module initialization. Crew Vision and
60
- // Image Generation tool registration is also decided at Hub plugin boot.
61
- hub_url: Object.freeze({ global: R, session: null }),
62
- vision_enabled: Object.freeze({ global: R, session: null }),
63
- imagegen_enabled: Object.freeze({ global: R, session: null }),
64
- });
65
-
66
- export function activationForSetting(key) {
67
- const entry = RUNTIME_SETTING_ACTIVATION[key];
68
- return entry ? { ...entry } : null;
69
- }
70
-
71
- export function runtimeActivationMetadata() {
72
- return Object.fromEntries(
73
- Object.entries(RUNTIME_SETTING_ACTIVATION).map(([key, value]) => [key, { ...value }]),
74
- );
75
- }
76
-
77
- export function summarizeActivationBoundaries(metadata = RUNTIME_SETTING_ACTIVATION) {
78
- const out = {
79
- live: [],
80
- 'next-workflow': [],
81
- 'next-session': [],
82
- 'restart-required': [],
83
- };
84
- for (const [key, entry] of Object.entries(metadata)) {
85
- const boundary = entry?.global;
86
- if (out[boundary]) out[boundary].push(key);
87
- }
88
- for (const values of Object.values(out)) values.sort();
89
- return out;
90
- }
1
+ // Runtime control activation contract.
2
+ //
3
+ // This is deliberately data, not UI prose. MCP diagnostics and the Settings
4
+ // surface consume the same boundary definitions so users are never told two
5
+ // different stories about when a config change takes effect.
6
+
7
+ export const ACTIVATION_BOUNDARY = Object.freeze({
8
+ LIVE: 'live',
9
+ NEXT_WORKFLOW: 'next-workflow',
10
+ NEXT_SESSION: 'next-session',
11
+ RESTART_REQUIRED: 'restart-required',
12
+ });
13
+
14
+ const N = ACTIVATION_BOUNDARY.NEXT_WORKFLOW;
15
+ const S = ACTIVATION_BOUNDARY.NEXT_SESSION;
16
+ const L = ACTIVATION_BOUNDARY.LIVE;
17
+ const R = ACTIVATION_BOUNDARY.RESTART_REQUIRED;
18
+
19
+ /**
20
+ * `global` describes a write made through persisted Settings/config.
21
+ * `session` describes an explicit dsh_worker_config override in the already
22
+ * running MCP process. `session: null` means the setting is not a session
23
+ * override surface.
24
+ */
25
+ export const RUNTIME_SETTING_ACTIVATION = Object.freeze({
26
+ max_parallel: Object.freeze({ global: L, session: null, note: 'Admission limit refreshes before new workflow starts and when slots release; lowering never cancels active work.' }),
27
+
28
+ subagents_enabled: Object.freeze({ global: N, session: N }),
29
+ collaboration_mode: Object.freeze({ global: N, session: N }),
30
+ main_agent_mode: Object.freeze({ global: N, session: N }),
31
+ flash_state: Object.freeze({ global: N, session: N }),
32
+ pro_state: Object.freeze({ global: N, session: N }),
33
+ worker_state: Object.freeze({ global: N, session: N }),
34
+ review_state: Object.freeze({ global: N, session: N }),
35
+ auto_review: Object.freeze({ global: N, session: N }),
36
+ pro_reviews_flash: Object.freeze({ global: N, session: N }),
37
+ worker_provider_mode: Object.freeze({ global: N, session: null }),
38
+ flash_model_priority: Object.freeze({ global: N, session: null }),
39
+ flash_model_fallback: Object.freeze({ global: N, session: null }),
40
+ pro_model_priority: Object.freeze({ global: N, session: null }),
41
+ pro_model_fallback: Object.freeze({ global: N, session: null }),
42
+ adaptive_routing: Object.freeze({ global: N, session: null, note: 'Opt-in provider health ordering is read for the next Hub model selection; existing explicit priorities remain authoritative.' }),
43
+ isolation: Object.freeze({ global: N, session: null }),
44
+ vision_provider: Object.freeze({ global: N, session: null }),
45
+ vision_model: Object.freeze({ global: N, session: null }),
46
+ imagegen_provider: Object.freeze({ global: N, session: null }),
47
+
48
+ // These values are copied into the MCP session defaults at process startup.
49
+ // dsh_worker_config can override them for subsequent workflows in that same
50
+ // session, but persisted global edits require a new MCP session to inherit.
51
+ default_tier: Object.freeze({ global: S, session: N }),
52
+ default_effort: Object.freeze({ global: S, session: N }),
53
+ mode: Object.freeze({ global: S, session: N }),
54
+ default_timeout_seconds: Object.freeze({ global: S, session: N }),
55
+ escalate_on_failure: Object.freeze({ global: S, session: N }),
56
+ preset_flash: Object.freeze({ global: S, session: N }),
57
+ preset_pro: Object.freeze({ global: S, session: N }),
58
+
59
+ // hub-client freezes its base URL at module initialization. Crew Vision and
60
+ // Image Generation tool registration is also decided at Hub plugin boot.
61
+ hub_url: Object.freeze({ global: R, session: null }),
62
+ vision_enabled: Object.freeze({ global: R, session: null }),
63
+ imagegen_enabled: Object.freeze({ global: R, session: null }),
64
+ });
65
+
66
+ export function activationForSetting(key) {
67
+ const entry = RUNTIME_SETTING_ACTIVATION[key];
68
+ return entry ? { ...entry } : null;
69
+ }
70
+
71
+ export function runtimeActivationMetadata() {
72
+ return Object.fromEntries(
73
+ Object.entries(RUNTIME_SETTING_ACTIVATION).map(([key, value]) => [key, { ...value }]),
74
+ );
75
+ }
76
+
77
+ export function summarizeActivationBoundaries(metadata = RUNTIME_SETTING_ACTIVATION) {
78
+ const out = {
79
+ live: [],
80
+ 'next-workflow': [],
81
+ 'next-session': [],
82
+ 'restart-required': [],
83
+ };
84
+ for (const [key, entry] of Object.entries(metadata)) {
85
+ const boundary = entry?.global;
86
+ if (out[boundary]) out[boundary].push(key);
87
+ }
88
+ for (const values of Object.values(out)) values.sort();
89
+ return out;
90
+ }