Resolves #13914
Related: #13860
Related: #13936
Adds the public inspect_deployment MCP operation on both KB and MC as a read-only alias over the deployment-state bridge snapshot. The internal orchestrator bridge now includes a bounded recent recovery-run ledger section, so public KB/MC inspection can show current allowlisted service state, bounded log tails, current diagnoses, provider-residency proof, and recent recovery-run proof without adding a public daemon route or putting Docker/socket authority on KB/MC.
Evidence: L2 (unit coverage for bridge recovery-run/provider-residency projection plus KB/MC OpenAPI/toolService drift checks) -> L3 required (live cloud smoke through the deployed public KB/MC tool path). Residual: live smoke tracked by #13936.
Deltas from ticket
- Implements the corrected post-#13935 shape: public surfaces stay KB + MC only; orchestrator/runtime daemons remain internal.
- Adds
inspect_deployment while preserving get_deployment_state_snapshot compatibility.
- Publishes bounded recovery-run history into the bridge snapshot via
readRecentRecoveryRunStates, capped by NEO_DEPLOYMENT_STATE_BRIDGE_RECOVERY_RUN_LIMIT with default 10.
- Keeps provider-residency visibility read-only and bounded through the existing provider readiness probe.
- Keeps the response read-only: no shell, exec, restart, socket, or public orchestrator/daemon route is exposed.
- Rebased onto current
dev and kept ADR-19 shape: direct AiConfig leaf reads, no runtimeAccessService.configValues, no hidden defaults/type coercions for recoveryRunLimit.
Test Evidence
npm run test-unit -- test/playwright/unit/ai/daemons/orchestrator/services/DeploymentStateBridgeService.spec.mjs test/playwright/unit/ai/services/memory-core/helpers/deploymentStateBridgeStore.spec.mjs test/playwright/unit/ai/mcp/server/McpServerListToolsSmoke.spec.mjs -> 36 passed after rebasing onto current origin/dev.
npm run agent-preflight -- --no-fix ai/config.template.mjs ai/daemons/orchestrator/services/DeploymentStateBridgeService.mjs ai/mcp/server/knowledge-base/openapi.yaml ai/mcp/server/knowledge-base/toolService.mjs ai/mcp/server/memory-core/openapi.yaml ai/mcp/server/memory-core/toolService.mjs ai/services/memory-core/helpers/deploymentStateBridgeStore.mjs test/playwright/unit/ai/daemons/orchestrator/services/DeploymentStateBridgeService.spec.mjs test/playwright/unit/ai/mcp/server/McpServerListToolsSmoke.spec.mjs -> passed.
git diff --check origin/dev..HEAD -> passed.
Post-Merge Validation
Commits
14e8121d4f — feat(ai): expose deployment inspection MCP surface (#13914)
88f508300c — fix(ai): read deployment bridge config leaves directly (#13914)
Authored by Euclid (GPT-5, Codex Desktop). Session 02b1972b-2925-4458-89c7-287df50c726e.
ADR-19 cleanup update
Patched the deployment bridge after operator catch: DeploymentStateBridgeService no longer aliases AiConfig.orchestrator.deploymentStateBridge into bridgeConfig; it reads the resolved config leaves directly at the use sites.
New head: 2482cc3039 — fix(ai): read deployment bridge config leaves directly (#13914)
Validation run after the patch:
node --check ai/daemons/orchestrator/services/DeploymentStateBridgeService.mjs
node ./buildScripts/util/check-block-alignment.mjs ai/daemons/orchestrator/services/DeploymentStateBridgeService.mjs
npm run test-unit -- test/playwright/unit/ai/daemons/orchestrator/services/DeploymentStateBridgeService.spec.mjs test/playwright/unit/ai/mcp/server/McpServerListToolsSmoke.spec.mjs — 32 passed
npm run agent-preflight -- ai/daemons/orchestrator/services/DeploymentStateBridgeService.mjs test/playwright/unit/ai/daemons/orchestrator/services/DeploymentStateBridgeService.spec.mjs test/playwright/unit/ai/mcp/server/McpServerListToolsSmoke.spec.mjs
npm run ai:lint-config-template-ssot
git diff --check
@neo-gpt commented on 2026-06-24T10:43:40Z
Rebased #13938 onto current dev and pushed head 88f508300c.
Rebase notes:
- Combined both deployment-state bridge config leaves:
providerResidencyServiceKeys and recoveryRunLimit.
- Kept
getServiceKeys() on direct AiConfig.orchestrator.deploymentRuntimeAccess.allowedServices; did not use runtimeAccessService.configValues.
- Removed the ADR-19 violation in
collectRecoveryRunSnapshot: no Math.max(Number(... ) || 0) hidden default/type coercion. recoveryRunLimit is read from the typed leaf and negative values fail loudly.
Validation:
npm run test-unit -- test/playwright/unit/ai/daemons/orchestrator/services/DeploymentStateBridgeService.spec.mjs test/playwright/unit/ai/services/memory-core/helpers/deploymentStateBridgeStore.spec.mjs test/playwright/unit/ai/mcp/server/McpServerListToolsSmoke.spec.mjs -> 36 passed
npm run agent-preflight -- --no-fix ai/config.template.mjs ai/daemons/orchestrator/services/DeploymentStateBridgeService.mjs ai/mcp/server/knowledge-base/openapi.yaml ai/mcp/server/knowledge-base/toolService.mjs ai/mcp/server/memory-core/openapi.yaml ai/mcp/server/memory-core/toolService.mjs ai/services/memory-core/helpers/deploymentStateBridgeStore.mjs test/playwright/unit/ai/daemons/orchestrator/services/DeploymentStateBridgeService.spec.mjs test/playwright/unit/ai/mcp/server/McpServerListToolsSmoke.spec.mjs -> passed
git diff --check origin/dev..HEAD -> passed
CI is running again on the rebased head; tobiu remains requested.
@neo-gpt commented on 2026-06-24T15:46:13Z
Self-review polish pushed on rebased head a1b0ee3249.
Delta:
- Added a narrow
recoveryRunStateReader instance seam so the recovery-ledger test no longer needs to mutate recoveryRunStateDir / per-test bridge leaves.
- Added fail-loud validation for
deploymentStateBridge.recoveryRunLimit; a stale/missing leaf now throws instead of silently producing an empty recovery ledger.
- Kept production reads ADR-19 aligned: resolved
AiConfig leaves are still read at the use site; no runtimeAccessService.configValues, no hidden defaults, no type coercion fallback.
- Rebased onto current
origin/dev after the stale-branch warning.
Validation after rebase:
npm run test-unit -- test/playwright/unit/ai/daemons/orchestrator/services/DeploymentStateBridgeService.spec.mjs test/playwright/unit/ai/services/memory-core/helpers/deploymentStateBridgeStore.spec.mjs test/playwright/unit/ai/mcp/server/McpServerListToolsSmoke.spec.mjs -> 36 passed
npm run agent-preflight -- --no-fix ... -> passed
git diff --check origin/dev..HEAD -> passed
CI is running again on the rebased head.
Resolves #13914
Related: #13860 Related: #13936
Adds the public
inspect_deploymentMCP operation on both KB and MC as a read-only alias over the deployment-state bridge snapshot. The internal orchestrator bridge now includes a bounded recent recovery-run ledger section, so public KB/MC inspection can show current allowlisted service state, bounded log tails, current diagnoses, provider-residency proof, and recent recovery-run proof without adding a public daemon route or putting Docker/socket authority on KB/MC.Evidence: L2 (unit coverage for bridge recovery-run/provider-residency projection plus KB/MC OpenAPI/toolService drift checks) -> L3 required (live cloud smoke through the deployed public KB/MC tool path). Residual: live smoke tracked by #13936.
Deltas from ticket
inspect_deploymentwhile preservingget_deployment_state_snapshotcompatibility.readRecentRecoveryRunStates, capped byNEO_DEPLOYMENT_STATE_BRIDGE_RECOVERY_RUN_LIMITwith default10.devand kept ADR-19 shape: direct AiConfig leaf reads, noruntimeAccessService.configValues, no hidden defaults/type coercions forrecoveryRunLimit.Test Evidence
npm run test-unit -- test/playwright/unit/ai/daemons/orchestrator/services/DeploymentStateBridgeService.spec.mjs test/playwright/unit/ai/services/memory-core/helpers/deploymentStateBridgeStore.spec.mjs test/playwright/unit/ai/mcp/server/McpServerListToolsSmoke.spec.mjs-> 36 passed after rebasing onto currentorigin/dev.npm run agent-preflight -- --no-fix ai/config.template.mjs ai/daemons/orchestrator/services/DeploymentStateBridgeService.mjs ai/mcp/server/knowledge-base/openapi.yaml ai/mcp/server/knowledge-base/toolService.mjs ai/mcp/server/memory-core/openapi.yaml ai/mcp/server/memory-core/toolService.mjs ai/services/memory-core/helpers/deploymentStateBridgeStore.mjs test/playwright/unit/ai/daemons/orchestrator/services/DeploymentStateBridgeService.spec.mjs test/playwright/unit/ai/mcp/server/McpServerListToolsSmoke.spec.mjs-> passed.git diff --check origin/dev..HEAD-> passed.Post-Merge Validation
NEO_DEPLOYMENT_STATE_BRIDGE_RECOVERY_RUN_LIMIT.inspect_deployment.Commits
14e8121d4f—feat(ai): expose deployment inspection MCP surface (#13914)88f508300c—fix(ai): read deployment bridge config leaves directly (#13914)Authored by Euclid (GPT-5, Codex Desktop). Session 02b1972b-2925-4458-89c7-287df50c726e.
ADR-19 cleanup update
Patched the deployment bridge after operator catch:
DeploymentStateBridgeServiceno longer aliasesAiConfig.orchestrator.deploymentStateBridgeintobridgeConfig; it reads the resolved config leaves directly at the use sites.New head:
2482cc3039—fix(ai): read deployment bridge config leaves directly (#13914)Validation run after the patch:
node --check ai/daemons/orchestrator/services/DeploymentStateBridgeService.mjsnode ./buildScripts/util/check-block-alignment.mjs ai/daemons/orchestrator/services/DeploymentStateBridgeService.mjsnpm run test-unit -- test/playwright/unit/ai/daemons/orchestrator/services/DeploymentStateBridgeService.spec.mjs test/playwright/unit/ai/mcp/server/McpServerListToolsSmoke.spec.mjs— 32 passednpm run agent-preflight -- ai/daemons/orchestrator/services/DeploymentStateBridgeService.mjs test/playwright/unit/ai/daemons/orchestrator/services/DeploymentStateBridgeService.spec.mjs test/playwright/unit/ai/mcp/server/McpServerListToolsSmoke.spec.mjsnpm run ai:lint-config-template-ssotgit diff --check@neo-gptcommented on 2026-06-24T10:43:40ZRebased #13938 onto current
devand pushed head88f508300c.Rebase notes:
providerResidencyServiceKeysandrecoveryRunLimit.getServiceKeys()on directAiConfig.orchestrator.deploymentRuntimeAccess.allowedServices; did not useruntimeAccessService.configValues.collectRecoveryRunSnapshot: noMath.max(Number(... ) || 0)hidden default/type coercion.recoveryRunLimitis read from the typed leaf and negative values fail loudly.Validation:
npm run test-unit -- test/playwright/unit/ai/daemons/orchestrator/services/DeploymentStateBridgeService.spec.mjs test/playwright/unit/ai/services/memory-core/helpers/deploymentStateBridgeStore.spec.mjs test/playwright/unit/ai/mcp/server/McpServerListToolsSmoke.spec.mjs-> 36 passednpm run agent-preflight -- --no-fix ai/config.template.mjs ai/daemons/orchestrator/services/DeploymentStateBridgeService.mjs ai/mcp/server/knowledge-base/openapi.yaml ai/mcp/server/knowledge-base/toolService.mjs ai/mcp/server/memory-core/openapi.yaml ai/mcp/server/memory-core/toolService.mjs ai/services/memory-core/helpers/deploymentStateBridgeStore.mjs test/playwright/unit/ai/daemons/orchestrator/services/DeploymentStateBridgeService.spec.mjs test/playwright/unit/ai/mcp/server/McpServerListToolsSmoke.spec.mjs-> passedgit diff --check origin/dev..HEAD-> passedCI is running again on the rebased head;
tobiuremains requested.@neo-gptcommented on 2026-06-24T15:46:13ZSelf-review polish pushed on rebased head
a1b0ee3249.Delta:
recoveryRunStateReaderinstance seam so the recovery-ledger test no longer needs to mutaterecoveryRunStateDir/ per-test bridge leaves.deploymentStateBridge.recoveryRunLimit; a stale/missing leaf now throws instead of silently producing an empty recovery ledger.AiConfigleaves are still read at the use site; noruntimeAccessService.configValues, no hidden defaults, no type coercion fallback.origin/devafter the stale-branch warning.Validation after rebase:
npm run test-unit -- test/playwright/unit/ai/daemons/orchestrator/services/DeploymentStateBridgeService.spec.mjs test/playwright/unit/ai/services/memory-core/helpers/deploymentStateBridgeStore.spec.mjs test/playwright/unit/ai/mcp/server/McpServerListToolsSmoke.spec.mjs-> 36 passednpm run agent-preflight -- --no-fix ...-> passedgit diff --check origin/dev..HEAD-> passedCI is running again on the rebased head.