@ran-sh/dsh-crew 0.5.7 → 1.0.0

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.
@@ -0,0 +1,87 @@
1
+ // Single, bounded readiness projection shared by the Hub extension surface,
2
+ // MCP diagnostics and the client. It consumes already-collected evidence and
3
+ // never performs I/O or carries raw task/result/error/credential content.
4
+
5
+ const MAX_HEALTH = 128;
6
+
7
+ function text(value) { return typeof value === 'string' && value.trim() ? value.trim() : null; }
8
+
9
+ function projectRuntime(runtime) {
10
+ if (!runtime || typeof runtime !== 'object') return null;
11
+ return {
12
+ execution_plane: text(runtime.execution_plane),
13
+ profile: text(runtime.profile),
14
+ listen_port: Number.isFinite(Number(runtime.listen_port)) ? Number(runtime.listen_port) : null,
15
+ runtime_id: text(runtime.runtime_id),
16
+ };
17
+ }
18
+
19
+ function projectSelection(value) {
20
+ if (!value || typeof value !== 'object') return null;
21
+ const provider = text(value.provider);
22
+ const model = text(value.model);
23
+ if (!provider || !model) return null;
24
+ return { provider, model, ...(text(value.source) ? { source: text(value.source) } : {}) };
25
+ }
26
+
27
+ function projectHealth(entry) {
28
+ if (!entry || typeof entry !== 'object') return null;
29
+ const provider = text(entry.provider);
30
+ const model = text(entry.model);
31
+ const state = text(entry.state);
32
+ if (!provider || !model || !state) return null;
33
+ return {
34
+ provider,
35
+ model,
36
+ state,
37
+ ...(text(entry.reason_code) ? { reason_code: text(entry.reason_code) } : {}),
38
+ ...(Number.isFinite(entry.observed_at) ? { observed_at: entry.observed_at } : {}),
39
+ ...(Number.isFinite(entry.expires_at) ? { expires_at: entry.expires_at } : {}),
40
+ fresh: entry.fresh === true,
41
+ };
42
+ }
43
+
44
+ function matrixRow(matrix, id) {
45
+ return Array.isArray(matrix?.rows) ? matrix.rows.find((row) => row?.id === id) ?? null : null;
46
+ }
47
+
48
+ function projectWorkspace(workspace) {
49
+ if (!workspace || typeof workspace !== 'object') return null;
50
+ return {
51
+ ...(text(workspace.status) ? { status: text(workspace.status) } : {}),
52
+ ...(text(workspace.reason_code) ? { reason_code: text(workspace.reason_code) } : {}),
53
+ };
54
+ }
55
+
56
+ export function buildRuntimeReadinessSnapshot({
57
+ runtime = null,
58
+ readinessMatrix = null,
59
+ selections = {},
60
+ health = [],
61
+ jobs = [],
62
+ workspace = null,
63
+ } = {}) {
64
+ const projectedHealth = (Array.isArray(health) ? health : []).map(projectHealth).filter(Boolean).slice(0, MAX_HEALTH);
65
+ const projectedJobs = Array.isArray(jobs) ? jobs : [];
66
+ const verified = projectedJobs.filter((job) => job?.status === 'done' && job?.task_status === 'success' && job?.delivery_complete === true).length;
67
+ const workerJobs = projectedJobs.filter((job) => job?.role === 'worker').length;
68
+ const reviewerJobs = projectedJobs.filter((job) => job?.role === 'reviewer').length;
69
+ const workerSelection = projectSelection(selections.worker ?? selections.flash);
70
+ const reviewerSelection = projectSelection(selections.reviewer ?? selections.pro);
71
+ return {
72
+ schema_version: 1,
73
+ runtime: projectRuntime(runtime),
74
+ readiness_matrix: readinessMatrix && typeof readinessMatrix === 'object' ? structuredClone(readinessMatrix) : null,
75
+ provider_lifecycle: matrixRow(readinessMatrix, 'provider_lifecycle_consistent'),
76
+ health: projectedHealth,
77
+ worker: { selected: workerSelection, health: projectedHealth.filter((entry) => entry.provider === workerSelection?.provider && entry.model === workerSelection?.model) },
78
+ reviewer: { selected: reviewerSelection, health: projectedHealth.filter((entry) => entry.provider === reviewerSelection?.provider && entry.model === reviewerSelection?.model) },
79
+ historical_evidence: {
80
+ job_count: projectedJobs.length,
81
+ verified_job_count: verified,
82
+ worker_job_count: workerJobs,
83
+ reviewer_job_count: reviewerJobs,
84
+ },
85
+ workspace: projectWorkspace(workspace),
86
+ };
87
+ }
package/src/server.mjs CHANGED
@@ -9,7 +9,8 @@ import { hubCompatibilityMessage, resolveHubExecutionMode } from './hub-compatib
9
9
  import { RUNTIME_VERSION, getHubRuntimeIdentity } from './runtime-identity.mjs';
10
10
  import { resolveWorkerModel } from './model-routing.mjs';
11
11
  import { runtimeActivationMetadata } from './runtime-controls.mjs';
12
- import { buildConfigReadinessMatrix } from './config-readiness.mjs';
12
+ import { buildConfigReadinessMatrix } from './config-readiness.mjs';
13
+ import { buildRuntimeReadinessSnapshot } from './runtime-readiness-snapshot.mjs';
13
14
  import { classifyFailure, classifyFailureCode } from './failure-classification.mjs';
14
15
  import {
15
16
  normalizeGlobalConfig,
@@ -331,6 +332,8 @@ async function buildConfigReport() {
331
332
  let providerCatalogBody = null;
332
333
  let providerInventoryChecked = false;
333
334
  let providerInventoryBody = null;
335
+ let providerHealthChecked = false;
336
+ let providerHealthBody = null;
334
337
  let hubJobsChecked = false;
335
338
  let hubJobsBody = null;
336
339
  const workerProviderMode = globalConfig.worker_provider_mode ?? 'deepseek-official';
@@ -378,6 +381,16 @@ async function buildConfigReport() {
378
381
  providerInventoryBody = { ok: false, code: 'PROVIDER_INVENTORY_UNAVAILABLE' };
379
382
  }
380
383
  }
384
+ if (hubCompatibility.compatible) {
385
+ try {
386
+ providerHealthChecked = true;
387
+ const healthRes = await fetch(`${globalConfig.hub_url}/_dsh/dsh-crew/provider-health`, { signal: AbortSignal.timeout(800) });
388
+ providerHealthBody = healthRes.ok ? await healthRes.json() : { ok: false, code: 'PROVIDER_HEALTH_UNAVAILABLE' };
389
+ } catch {
390
+ providerHealthChecked = true;
391
+ providerHealthBody = { ok: false, code: 'PROVIDER_HEALTH_UNAVAILABLE' };
392
+ }
393
+ }
381
394
  if (hubCompatibility.compatible) {
382
395
  try {
383
396
  hubJobsChecked = true;
@@ -395,12 +408,22 @@ async function buildConfigReport() {
395
408
  providerCatalogBody,
396
409
  providerInventoryChecked,
397
410
  providerInventoryBody,
411
+ providerHealthChecked,
412
+ providerHealthBody,
398
413
  hubJobsChecked,
399
414
  hubJobsBody,
400
415
  });
401
416
  const roleProfiles = loadRoleProfiles();
402
- const workspaceReadiness = await assessWorkspaceReadiness({ cwd: process.cwd() });
403
- const extensionContract = buildExtensionContract({
417
+ const workspaceReadiness = await assessWorkspaceReadiness({ cwd: process.cwd() });
418
+ const readinessSnapshot = buildRuntimeReadinessSnapshot({
419
+ runtime: getHubRuntimeIdentity(),
420
+ readinessMatrix,
421
+ selections: { worker: effectiveWorkerSelection.worker ?? effectiveWorkerSelection.flash, reviewer: effectiveWorkerSelection.reviewer ?? effectiveWorkerSelection.pro },
422
+ health: providerHealthBody?.health,
423
+ jobs: hubJobsBody?.jobs,
424
+ workspace: workspaceReadiness,
425
+ });
426
+ const extensionContract = buildExtensionContract({
404
427
  config: {
405
428
  ...globalConfig,
406
429
  subagents_enabled: sessionConfig.enabled !== false && globalConfig.subagents_enabled !== false,
@@ -408,7 +431,8 @@ async function buildConfigReport() {
408
431
  review_state: globalConfig.review_state,
409
432
  escalate_on_failure: sessionConfig.escalate_on_failure ?? legacy.escalate_on_failure,
410
433
  },
411
- readinessMatrix,
434
+ readinessMatrix,
435
+ readinessSnapshot,
412
436
  workspace: workspaceReadiness,
413
437
  profiles: roleProfiles,
414
438
  runtime: getHubRuntimeIdentity(),
@@ -450,7 +474,8 @@ async function buildConfigReport() {
450
474
  global_defaults: Object.fromEntries(SAFE_GLOBAL_KEYS.map((k) => [k, globalConfig[k]])),
451
475
  runtime_controls: runtimeControls,
452
476
  activation_boundaries: activationBoundaries,
453
- readiness_matrix: readinessMatrix,
477
+ readiness_matrix: readinessMatrix,
478
+ readiness_snapshot: readinessSnapshot,
454
479
  role_profiles: roleProfiles,
455
480
  extension_contract: extensionContract,
456
481
  hub_reachable: hubCompatibility.reachable,