@evalops/maestro 0.10.50 → 0.10.51
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/dist/agent/agent-outcome.d.ts +54 -0
- package/dist/agent/agent-outcome.d.ts.map +1 -0
- package/dist/agent/agent-outcome.js +142 -0
- package/dist/agent/agent-outcome.js.map +1 -0
- package/dist/agent/agent-resume.d.ts.map +1 -1
- package/dist/agent/agent-resume.js +3 -3
- package/dist/agent/agent-resume.js.map +1 -1
- package/dist/agent/agent-run-summary.d.ts +37 -0
- package/dist/agent/agent-run-summary.d.ts.map +1 -0
- package/dist/agent/agent-run-summary.js +15 -0
- package/dist/agent/agent-run-summary.js.map +1 -0
- package/dist/agent/agent-work-board.d.ts +82 -0
- package/dist/agent/agent-work-board.d.ts.map +1 -0
- package/dist/agent/agent-work-board.js +312 -0
- package/dist/agent/agent-work-board.js.map +1 -0
- package/dist/agent/auto-compaction.d.ts +7 -2
- package/dist/agent/auto-compaction.d.ts.map +1 -1
- package/dist/agent/auto-compaction.js +23 -10
- package/dist/agent/auto-compaction.js.map +1 -1
- package/dist/agent/mission-artifacts.d.ts +62 -0
- package/dist/agent/mission-artifacts.d.ts.map +1 -0
- package/dist/agent/mission-artifacts.js +438 -0
- package/dist/agent/mission-artifacts.js.map +1 -0
- package/dist/agent/mission-manifest.d.ts +139 -3
- package/dist/agent/mission-manifest.d.ts.map +1 -1
- package/dist/agent/mission-manifest.js +549 -3
- package/dist/agent/mission-manifest.js.map +1 -1
- package/dist/agent/mission-store.d.ts +80 -0
- package/dist/agent/mission-store.d.ts.map +1 -0
- package/dist/agent/mission-store.js +603 -0
- package/dist/agent/mission-store.js.map +1 -0
- package/dist/agent/modes.d.ts +2 -2
- package/dist/agent/modes.d.ts.map +1 -1
- package/dist/agent/modes.js +10 -3
- package/dist/agent/modes.js.map +1 -1
- package/dist/agent/providers/codex-app-server.d.ts.map +1 -1
- package/dist/agent/providers/codex-app-server.js +1 -3
- package/dist/agent/providers/codex-app-server.js.map +1 -1
- package/dist/agent/providers/google-gemini-cli.js +203 -107
- package/dist/agent/providers/google.js +100 -41
- package/dist/agent/providers/scripted.d.ts.map +1 -1
- package/dist/agent/providers/scripted.js +1 -3
- package/dist/agent/providers/scripted.js.map +1 -1
- package/dist/agent/providers/validation.d.ts.map +1 -1
- package/dist/agent/providers/validation.js +1 -3
- package/dist/agent/providers/validation.js.map +1 -1
- package/dist/agent/providers/vertex.js +203 -107
- package/dist/agent/snapshot-store.d.ts +32 -0
- package/dist/agent/snapshot-store.d.ts.map +1 -0
- package/dist/agent/snapshot-store.js +195 -0
- package/dist/agent/snapshot-store.js.map +1 -0
- package/dist/agent/specialist-profiles.d.ts +36 -0
- package/dist/agent/specialist-profiles.d.ts.map +1 -0
- package/dist/agent/specialist-profiles.js +159 -0
- package/dist/agent/specialist-profiles.js.map +1 -0
- package/dist/agent/subagent-specs.d.ts +4 -1
- package/dist/agent/subagent-specs.d.ts.map +1 -1
- package/dist/agent/subagent-specs.js +81 -8
- package/dist/agent/subagent-specs.js.map +1 -1
- package/dist/agent/swarm/coverage-gate.d.ts +37 -0
- package/dist/agent/swarm/coverage-gate.d.ts.map +1 -0
- package/dist/agent/swarm/coverage-gate.js +48 -0
- package/dist/agent/swarm/coverage-gate.js.map +1 -0
- package/dist/agent/swarm/executor.d.ts +1 -0
- package/dist/agent/swarm/executor.d.ts.map +1 -1
- package/dist/agent/swarm/executor.js +151 -15
- package/dist/agent/swarm/executor.js.map +1 -1
- package/dist/agent/swarm/orchestrator-prompt.d.ts +25 -0
- package/dist/agent/swarm/orchestrator-prompt.d.ts.map +1 -0
- package/dist/agent/swarm/orchestrator-prompt.js +48 -0
- package/dist/agent/swarm/orchestrator-prompt.js.map +1 -0
- package/dist/agent/swarm/plan-parser.d.ts.map +1 -1
- package/dist/agent/swarm/plan-parser.js +27 -2
- package/dist/agent/swarm/plan-parser.js.map +1 -1
- package/dist/agent/swarm/types.d.ts +17 -0
- package/dist/agent/swarm/types.d.ts.map +1 -1
- package/dist/agent/swarm/types.js.map +1 -1
- package/dist/agent/swarm/validation-directive.d.ts +21 -0
- package/dist/agent/swarm/validation-directive.d.ts.map +1 -0
- package/dist/agent/swarm/validation-directive.js +25 -0
- package/dist/agent/swarm/validation-directive.js.map +1 -0
- package/dist/agent/transport/tool-execution-bridge.d.ts.map +1 -1
- package/dist/agent/transport/tool-execution-bridge.js +4 -1
- package/dist/agent/transport/tool-execution-bridge.js.map +1 -1
- package/dist/api/enterprise-routes.d.ts.map +1 -1
- package/dist/api/enterprise-routes.js +87 -10
- package/dist/api/enterprise-routes.js.map +1 -1
- package/dist/api/org-settings-merge.d.ts +12 -0
- package/dist/api/org-settings-merge.d.ts.map +1 -0
- package/dist/api/org-settings-merge.js +38 -0
- package/dist/api/org-settings-merge.js.map +1 -0
- package/dist/api/user-settings-merge.d.ts +16 -0
- package/dist/api/user-settings-merge.d.ts.map +1 -0
- package/dist/api/user-settings-merge.js +37 -0
- package/dist/api/user-settings-merge.js.map +1 -0
- package/dist/app-server/daemon-lifecycle-api.d.ts.map +1 -1
- package/dist/app-server/daemon-lifecycle-api.js +1 -3
- package/dist/app-server/daemon-lifecycle-api.js.map +1 -1
- package/dist/app-server/external-agent-import-api.d.ts.map +1 -1
- package/dist/app-server/external-agent-import-api.js +1 -3
- package/dist/app-server/external-agent-import-api.js.map +1 -1
- package/dist/app-server/network-governance-api.d.ts.map +1 -1
- package/dist/app-server/network-governance-api.js +1 -3
- package/dist/app-server/network-governance-api.js.map +1 -1
- package/dist/app-server/plugin-bundle-api.d.ts.map +1 -1
- package/dist/app-server/plugin-bundle-api.js +1 -3
- package/dist/app-server/plugin-bundle-api.js.map +1 -1
- package/dist/app-server/policy-control-api.d.ts.map +1 -1
- package/dist/app-server/policy-control-api.js +1 -3
- package/dist/app-server/policy-control-api.js.map +1 -1
- package/dist/app-server/protocol-modes-api.d.ts.map +1 -1
- package/dist/app-server/protocol-modes-api.js +1 -3
- package/dist/app-server/protocol-modes-api.js.map +1 -1
- package/dist/cli/args.d.ts +2 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +15 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/commands/a2a.d.ts.map +1 -1
- package/dist/cli/commands/a2a.js +1 -3
- package/dist/cli/commands/a2a.js.map +1 -1
- package/dist/cli/commands/agents.d.ts +4 -0
- package/dist/cli/commands/agents.d.ts.map +1 -1
- package/dist/cli/commands/agents.js +149 -0
- package/dist/cli/commands/agents.js.map +1 -1
- package/dist/cli/commands/mission.d.ts +4 -0
- package/dist/cli/commands/mission.d.ts.map +1 -0
- package/dist/cli/commands/mission.js +196 -0
- package/dist/cli/commands/mission.js.map +1 -0
- package/dist/cli/commands/value.d.ts +10 -0
- package/dist/cli/commands/value.d.ts.map +1 -0
- package/dist/cli/commands/value.js +33 -0
- package/dist/cli/commands/value.js.map +1 -0
- package/dist/cli/headless-protocol.d.ts.map +1 -1
- package/dist/cli/headless-protocol.js +1 -3
- package/dist/cli/headless-protocol.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +10 -0
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/system-prompt.d.ts.map +1 -1
- package/dist/cli/system-prompt.js +38 -7
- package/dist/cli/system-prompt.js.map +1 -1
- package/dist/cli-runtime.js +7756 -2800
- package/dist/cli-tui/client-tools/client-tool-controller.d.ts.map +1 -1
- package/dist/cli-tui/client-tools/client-tool-controller.js +1 -3
- package/dist/cli-tui/client-tools/client-tool-controller.js.map +1 -1
- package/dist/cli-tui/commands/undo-handlers.d.ts.map +1 -1
- package/dist/cli-tui/commands/undo-handlers.js +7 -2
- package/dist/cli-tui/commands/undo-handlers.js.map +1 -1
- package/dist/cli-tui/tui-renderer/skills-controller.d.ts +3 -0
- package/dist/cli-tui/tui-renderer/skills-controller.d.ts.map +1 -1
- package/dist/cli-tui/tui-renderer/skills-controller.js +77 -33
- package/dist/cli-tui/tui-renderer/skills-controller.js.map +1 -1
- package/dist/codex/app-server-client.d.ts.map +1 -1
- package/dist/codex/app-server-client.js +1 -3
- package/dist/codex/app-server-client.js.map +1 -1
- package/dist/codex/compatibility.d.ts.map +1 -1
- package/dist/codex/compatibility.js +1 -3
- package/dist/codex/compatibility.js.map +1 -1
- package/dist/codex/subagent-dispatch-table.d.ts +8 -0
- package/dist/codex/subagent-dispatch-table.d.ts.map +1 -1
- package/dist/codex/subagent-dispatch-table.js +23 -0
- package/dist/codex/subagent-dispatch-table.js.map +1 -1
- package/dist/context/manifest.d.ts.map +1 -1
- package/dist/context/manifest.js +1 -3
- package/dist/context/manifest.js.map +1 -1
- package/dist/conversation/render-model.d.ts +0 -36
- package/dist/conversation/render-model.d.ts.map +1 -1
- package/dist/conversation/render-model.js +1 -3
- package/dist/conversation/render-model.js.map +1 -1
- package/dist/customer-value/ambient-learning.d.ts +75 -0
- package/dist/customer-value/ambient-learning.d.ts.map +1 -0
- package/dist/customer-value/ambient-learning.js +472 -0
- package/dist/customer-value/ambient-learning.js.map +1 -0
- package/dist/customer-value/internal-helpers.d.ts +13 -0
- package/dist/customer-value/internal-helpers.d.ts.map +1 -0
- package/dist/customer-value/internal-helpers.js +70 -0
- package/dist/customer-value/internal-helpers.js.map +1 -0
- package/dist/customer-value/report.d.ts +282 -0
- package/dist/customer-value/report.d.ts.map +1 -0
- package/dist/customer-value/report.js +2085 -0
- package/dist/customer-value/report.js.map +1 -0
- package/dist/db/schema.d.ts +5 -1
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js.map +1 -1
- package/dist/evalops/agent-bootstrap.d.ts.map +1 -1
- package/dist/evalops/agent-bootstrap.js +1 -3
- package/dist/evalops/agent-bootstrap.js.map +1 -1
- package/dist/evalops/agent-mcp-metadata.d.ts.map +1 -1
- package/dist/evalops/agent-mcp-metadata.js +1 -3
- package/dist/evalops/agent-mcp-metadata.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/installers/maestro-review-workflow.d.ts +38 -0
- package/dist/installers/maestro-review-workflow.d.ts.map +1 -0
- package/dist/installers/maestro-review-workflow.js +163 -0
- package/dist/installers/maestro-review-workflow.js.map +1 -0
- package/dist/load-env.d.ts.map +1 -1
- package/dist/load-env.js +2 -1
- package/dist/load-env.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +92 -3
- package/dist/main.js.map +1 -1
- package/dist/mcp/config.d.ts.map +1 -1
- package/dist/mcp/config.js +1 -3
- package/dist/mcp/config.js.map +1 -1
- package/dist/mcp/elicitation.d.ts.map +1 -1
- package/dist/mcp/elicitation.js +1 -3
- package/dist/mcp/elicitation.js.map +1 -1
- package/dist/mcp/official-registry.d.ts.map +1 -1
- package/dist/mcp/official-registry.js +1 -3
- package/dist/mcp/official-registry.js.map +1 -1
- package/dist/mcp/workspace-trust.d.ts.map +1 -1
- package/dist/mcp/workspace-trust.js +1 -3
- package/dist/mcp/workspace-trust.js.map +1 -1
- package/dist/memory/service-client.d.ts.map +1 -1
- package/dist/memory/service-client.js +1 -3
- package/dist/memory/service-client.js.map +1 -1
- package/dist/models/config-loader.d.ts.map +1 -1
- package/dist/models/config-loader.js +1 -3
- package/dist/models/config-loader.js.map +1 -1
- package/dist/node_modules/@evalops/contracts/dist/index.d.ts +1 -0
- package/dist/node_modules/@evalops/contracts/dist/index.d.ts.map +1 -1
- package/dist/node_modules/@evalops/contracts/dist/index.js +1 -0
- package/dist/node_modules/@evalops/contracts/dist/index.js.map +1 -1
- package/dist/node_modules/@evalops/contracts/dist/maestro-settings.d.ts +61 -0
- package/dist/node_modules/@evalops/contracts/dist/maestro-settings.d.ts.map +1 -0
- package/dist/node_modules/@evalops/contracts/dist/maestro-settings.js +183 -0
- package/dist/node_modules/@evalops/contracts/dist/maestro-settings.js.map +1 -0
- package/dist/node_modules/@evalops/contracts/package.json +1 -1
- package/dist/node_modules/@evalops/tui/package.json +1 -1
- package/dist/oauth/connectors.d.ts.map +1 -1
- package/dist/oauth/connectors.js +1 -3
- package/dist/oauth/connectors.js.map +1 -1
- package/dist/oauth/evalops.d.ts.map +1 -1
- package/dist/oauth/evalops.js +1 -3
- package/dist/oauth/evalops.js.map +1 -1
- package/dist/platform/a2a-client.d.ts.map +1 -1
- package/dist/platform/a2a-client.js +1 -3
- package/dist/platform/a2a-client.js.map +1 -1
- package/dist/platform/a2a-cockpit.d.ts +1 -0
- package/dist/platform/a2a-cockpit.d.ts.map +1 -1
- package/dist/platform/a2a-cockpit.js +42 -11
- package/dist/platform/a2a-cockpit.js.map +1 -1
- package/dist/platform/a2a-completion-audit.d.ts +1 -1
- package/dist/platform/a2a-completion-audit.d.ts.map +1 -1
- package/dist/platform/a2a-completion-audit.js +7 -11
- package/dist/platform/a2a-completion-audit.js.map +1 -1
- package/dist/platform/a2a-maestro-peer.js +16 -0
- package/dist/platform/a2a-maestro-peer.js.map +1 -1
- package/dist/platform/a2a-peer-pairing.d.ts.map +1 -1
- package/dist/platform/a2a-peer-pairing.js +1 -3
- package/dist/platform/a2a-peer-pairing.js.map +1 -1
- package/dist/platform/a2a-peer-registry.d.ts.map +1 -1
- package/dist/platform/a2a-peer-registry.js +1 -3
- package/dist/platform/a2a-peer-registry.js.map +1 -1
- package/dist/platform/a2a-task-ledger.d.ts +20 -0
- package/dist/platform/a2a-task-ledger.d.ts.map +1 -1
- package/dist/platform/a2a-task-ledger.js +207 -11
- package/dist/platform/a2a-task-ledger.js.map +1 -1
- package/dist/platform/a2a-work-graph.d.ts.map +1 -1
- package/dist/platform/a2a-work-graph.js +1 -3
- package/dist/platform/a2a-work-graph.js.map +1 -1
- package/dist/platform/operating-layer.d.ts.map +1 -1
- package/dist/platform/operating-layer.js +14 -8
- package/dist/platform/operating-layer.js.map +1 -1
- package/dist/platform/tool-execution-client.d.ts.map +1 -1
- package/dist/platform/tool-execution-client.js +19 -2
- package/dist/platform/tool-execution-client.js.map +1 -1
- package/dist/providers/auth.d.ts.map +1 -1
- package/dist/providers/auth.js +1 -3
- package/dist/providers/auth.js.map +1 -1
- package/dist/runtime/env.d.ts +9 -1
- package/dist/runtime/env.d.ts.map +1 -1
- package/dist/runtime/env.js +63 -1
- package/dist/runtime/env.js.map +1 -1
- package/dist/safety/policy.d.ts.map +1 -1
- package/dist/safety/policy.js +1 -4
- package/dist/safety/policy.js.map +1 -1
- package/dist/sandbox/docker-sandbox.d.ts.map +1 -1
- package/dist/sandbox/docker-sandbox.js +6 -1
- package/dist/sandbox/docker-sandbox.js.map +1 -1
- package/dist/server/handlers/hosted-runner-drain.d.ts.map +1 -1
- package/dist/server/handlers/hosted-runner-drain.js +1 -3
- package/dist/server/handlers/hosted-runner-drain.js.map +1 -1
- package/dist/server/handlers/platform-a2a-push.d.ts.map +1 -1
- package/dist/server/handlers/platform-a2a-push.js +53 -2
- package/dist/server/handlers/platform-a2a-push.js.map +1 -1
- package/dist/server/handlers/runtime-app-server-ws.d.ts.map +1 -1
- package/dist/server/handlers/runtime-app-server-ws.js +1 -3
- package/dist/server/handlers/runtime-app-server-ws.js.map +1 -1
- package/dist/server/headless-runtime-service.d.ts +16 -0
- package/dist/server/headless-runtime-service.d.ts.map +1 -1
- package/dist/server/headless-runtime-service.js +232 -206
- package/dist/server/headless-runtime-service.js.map +1 -1
- package/dist/server/hosted-agent-runtime-progress.d.ts.map +1 -1
- package/dist/server/hosted-agent-runtime-progress.js +12 -3
- package/dist/server/hosted-agent-runtime-progress.js.map +1 -1
- package/dist/server/pending-request-payload.d.ts.map +1 -1
- package/dist/server/pending-request-payload.js +1 -3
- package/dist/server/pending-request-payload.js.map +1 -1
- package/dist/server/route-auth.d.ts.map +1 -1
- package/dist/server/route-auth.js +2 -0
- package/dist/server/route-auth.js.map +1 -1
- package/dist/server/session-serialization.d.ts.map +1 -1
- package/dist/server/session-serialization.js +1 -3
- package/dist/server/session-serialization.js.map +1 -1
- package/dist/services/compliance/normalize.d.ts.map +1 -1
- package/dist/services/compliance/normalize.js +1 -3
- package/dist/services/compliance/normalize.js.map +1 -1
- package/dist/services/intelligent-router/normalize.d.ts.map +1 -1
- package/dist/services/intelligent-router/normalize.js +1 -3
- package/dist/services/intelligent-router/normalize.js.map +1 -1
- package/dist/services/revenue-attribution/normalize.d.ts.map +1 -1
- package/dist/services/revenue-attribution/normalize.js +1 -3
- package/dist/services/revenue-attribution/normalize.js.map +1 -1
- package/dist/services/traces/normalize.d.ts.map +1 -1
- package/dist/services/traces/normalize.js +1 -3
- package/dist/services/traces/normalize.js.map +1 -1
- package/dist/services/workspace-config/normalize.d.ts.map +1 -1
- package/dist/services/workspace-config/normalize.js +1 -3
- package/dist/services/workspace-config/normalize.js.map +1 -1
- package/dist/skills/composer.d.ts.map +1 -1
- package/dist/skills/composer.js +13 -1
- package/dist/skills/composer.js.map +1 -1
- package/dist/skills/index.d.ts +1 -0
- package/dist/skills/index.d.ts.map +1 -1
- package/dist/skills/index.js +1 -0
- package/dist/skills/index.js.map +1 -1
- package/dist/skills/learned-guidelines.d.ts +33 -0
- package/dist/skills/learned-guidelines.d.ts.map +1 -0
- package/dist/skills/learned-guidelines.js +291 -0
- package/dist/skills/learned-guidelines.js.map +1 -0
- package/dist/skills/linter.d.ts.map +1 -1
- package/dist/skills/linter.js +1 -3
- package/dist/skills/linter.js.map +1 -1
- package/dist/skills/runtime-activation.d.ts +1 -0
- package/dist/skills/runtime-activation.d.ts.map +1 -1
- package/dist/skills/runtime-activation.js +2 -3
- package/dist/skills/runtime-activation.js.map +1 -1
- package/dist/skills/tool.d.ts.map +1 -1
- package/dist/skills/tool.js +26 -21
- package/dist/skills/tool.js.map +1 -1
- package/dist/skills/trust-cache.d.ts +7 -0
- package/dist/skills/trust-cache.d.ts.map +1 -1
- package/dist/skills/trust-cache.js +16 -0
- package/dist/skills/trust-cache.js.map +1 -1
- package/dist/telemetry/agent-workforce-native-event.d.ts.map +1 -1
- package/dist/telemetry/agent-workforce-native-event.js +1 -3
- package/dist/telemetry/agent-workforce-native-event.js.map +1 -1
- package/dist/telemetry/maestro-event-bus.d.ts.map +1 -1
- package/dist/telemetry/maestro-event-bus.js +42 -81
- package/dist/telemetry/maestro-event-bus.js.map +1 -1
- package/dist/telemetry/maestro-platform-replay-fixture.d.ts.map +1 -1
- package/dist/telemetry/maestro-platform-replay-fixture.js +1 -3
- package/dist/telemetry/maestro-platform-replay-fixture.js.map +1 -1
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +54 -43
- package/dist/telemetry.js.map +1 -1
- package/dist/theme/theme-loader.d.ts.map +1 -1
- package/dist/theme/theme-loader.js +1 -3
- package/dist/theme/theme-loader.js.map +1 -1
- package/dist/tools/apply-patch.d.ts.map +1 -1
- package/dist/tools/apply-patch.js +76 -8
- package/dist/tools/apply-patch.js.map +1 -1
- package/dist/tools/diff-preview.d.ts.map +1 -1
- package/dist/tools/diff-preview.js +10 -1
- package/dist/tools/diff-preview.js.map +1 -1
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +17 -0
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/write.d.ts.map +1 -1
- package/dist/tools/write.js +9 -0
- package/dist/tools/write.js.map +1 -1
- package/dist/undo/tracker.d.ts +5 -0
- package/dist/undo/tracker.d.ts.map +1 -1
- package/dist/undo/tracker.js +13 -0
- package/dist/undo/tracker.js.map +1 -1
- package/dist/utils/fs.d.ts +1 -1
- package/dist/utils/fs.d.ts.map +1 -1
- package/dist/utils/fs.js +29 -2
- package/dist/utils/fs.js.map +1 -1
- package/dist/utils/git-stash.d.ts.map +1 -1
- package/dist/utils/git-stash.js +15 -8
- package/dist/utils/git-stash.js.map +1 -1
- package/dist/utils/json.d.ts +11 -0
- package/dist/utils/json.d.ts.map +1 -1
- package/dist/utils/json.js +9 -0
- package/dist/utils/json.js.map +1 -1
- package/dist/utils/shell-env.d.ts.map +1 -1
- package/dist/utils/shell-env.js +2 -0
- package/dist/utils/shell-env.js.map +1 -1
- package/dist/utils/url-extractor-git.d.ts +26 -0
- package/dist/utils/url-extractor-git.d.ts.map +1 -0
- package/dist/utils/url-extractor-git.js +259 -0
- package/dist/utils/url-extractor-git.js.map +1 -0
- package/dist/utils/url-extractor.d.ts.map +1 -1
- package/dist/utils/url-extractor.js +23 -251
- package/dist/utils/url-extractor.js.map +1 -1
- package/dist/version.json +2 -2
- package/package.json +310 -306
- package/skills/incident-triage/SKILL.md +19 -1
- package/skills/install-code-review/SKILL.md +69 -0
- package/skills/security-review/SKILL.md +68 -0
- package/skills/security-review/reference/rubric.md +85 -0
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ambient learner subsystem for the customer-value report.
|
|
3
|
+
*
|
|
4
|
+
* Owns everything that reads/classifies the ambient learner outcome file:
|
|
5
|
+
* daemon flush, JSON parsing, pattern derivation, transient-failure
|
|
6
|
+
* classification, and the ambient customer-value/opportunity builders that
|
|
7
|
+
* turn learner evidence into report sections.
|
|
8
|
+
*
|
|
9
|
+
* Extracted from report.ts to isolate the highest-churn surface (transient
|
|
10
|
+
* classification + flush freshness evolve frequently) behind a stable module
|
|
11
|
+
* boundary. Runtime dependencies are one-directional: this module imports
|
|
12
|
+
* shared leaf helpers from ./internal-helpers.js and types from ./report.js
|
|
13
|
+
* (type-only). report.ts imports the summary/build entry points back here.
|
|
14
|
+
*/
|
|
15
|
+
import { spawn } from "node:child_process";
|
|
16
|
+
import { existsSync } from "node:fs";
|
|
17
|
+
import { readFile } from "node:fs/promises";
|
|
18
|
+
import { sanitizeWithStaticMask } from "../utils/secret-redactor.js";
|
|
19
|
+
import { isTimestampInRangeOrUnbounded, numberOrZero, parseTimestampMs, redactLine, sanitizeA2ALabel, slugify, sum, } from "./internal-helpers.js";
|
|
20
|
+
function shellQuote(value) {
|
|
21
|
+
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
22
|
+
}
|
|
23
|
+
export function ambientLearnerPresenceCommand(learnerPath) {
|
|
24
|
+
return `test -s ${shellQuote(learnerPath)}`;
|
|
25
|
+
}
|
|
26
|
+
export async function flushAmbientLearnerForReport(env, _learnerPath, flush) {
|
|
27
|
+
return flush(env);
|
|
28
|
+
}
|
|
29
|
+
export async function flushAmbientLearnerBeforeRead(env) {
|
|
30
|
+
return new Promise((resolve) => {
|
|
31
|
+
const child = spawn("ambient", ["flush"], {
|
|
32
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
33
|
+
});
|
|
34
|
+
let stdout = "";
|
|
35
|
+
let stderr = "";
|
|
36
|
+
let settled = false;
|
|
37
|
+
const finish = (result) => {
|
|
38
|
+
if (settled)
|
|
39
|
+
return;
|
|
40
|
+
settled = true;
|
|
41
|
+
clearTimeout(timeout);
|
|
42
|
+
resolve(result);
|
|
43
|
+
};
|
|
44
|
+
const timeout = setTimeout(() => {
|
|
45
|
+
child.kill();
|
|
46
|
+
finish({
|
|
47
|
+
flushed: false,
|
|
48
|
+
collectionGap: "Ambient learner flush timed out before report generation.",
|
|
49
|
+
});
|
|
50
|
+
}, 40000);
|
|
51
|
+
child.stdout?.setEncoding("utf8");
|
|
52
|
+
child.stdout?.on("data", (chunk) => {
|
|
53
|
+
stdout += chunk;
|
|
54
|
+
});
|
|
55
|
+
child.stderr?.setEncoding("utf8");
|
|
56
|
+
child.stderr?.on("data", (chunk) => {
|
|
57
|
+
stderr += chunk;
|
|
58
|
+
});
|
|
59
|
+
child.on("error", (error) => {
|
|
60
|
+
if (error.code === "ENOENT" &&
|
|
61
|
+
!existsSync(env.ambientSocketFile)) {
|
|
62
|
+
finish({ flushed: false });
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
finish({
|
|
66
|
+
flushed: false,
|
|
67
|
+
collectionGap: `Ambient learner flush could not start: ${sanitizeWithStaticMask(error.message)}.`,
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
child.on("close", (code) => {
|
|
71
|
+
if (code === 0) {
|
|
72
|
+
finish({
|
|
73
|
+
flushed: true,
|
|
74
|
+
learnerPath: parseAmbientFlushLearnerPath(stdout, env.ambientLearnerDefaultFile),
|
|
75
|
+
});
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const failureMessage = stderr.trim() || stdout.trim() || `exit ${code ?? "unknown"}`;
|
|
79
|
+
if (isAmbientDaemonNotRunningFlushFailure(failureMessage, env)) {
|
|
80
|
+
finish({ flushed: false });
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
finish({
|
|
84
|
+
flushed: false,
|
|
85
|
+
collectionGap: `Ambient learner flush failed before report generation: ${sanitizeWithStaticMask(failureMessage)}.`,
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
function isAmbientDaemonNotRunningFlushFailure(failureMessage, env) {
|
|
91
|
+
const normalized = failureMessage.toLowerCase();
|
|
92
|
+
return (normalized.includes("daemon is not running") ||
|
|
93
|
+
normalized.includes("daemon not running") ||
|
|
94
|
+
(normalized.includes("socket not found") &&
|
|
95
|
+
!existsSync(env.ambientSocketFile)));
|
|
96
|
+
}
|
|
97
|
+
function parseAmbientFlushLearnerPath(stdout, fallbackPath) {
|
|
98
|
+
const prefix = "Learner state flushed:";
|
|
99
|
+
const lines = stdout
|
|
100
|
+
.split(/\r?\n/u)
|
|
101
|
+
.map((line) => line.trim())
|
|
102
|
+
.filter(Boolean)
|
|
103
|
+
.reverse();
|
|
104
|
+
for (const line of lines) {
|
|
105
|
+
if (!line.startsWith(prefix))
|
|
106
|
+
continue;
|
|
107
|
+
const learnerPath = line.slice(prefix.length).trim();
|
|
108
|
+
if (learnerPath)
|
|
109
|
+
return learnerPath;
|
|
110
|
+
}
|
|
111
|
+
return fallbackPath;
|
|
112
|
+
}
|
|
113
|
+
export async function summarizeAmbientLearning(learnerPath, range, flushResult, requestedLearnerPath = learnerPath) {
|
|
114
|
+
const summary = {
|
|
115
|
+
learnerPath,
|
|
116
|
+
outcomes: [],
|
|
117
|
+
patterns: [],
|
|
118
|
+
collectionGaps: [],
|
|
119
|
+
};
|
|
120
|
+
if (flushResult?.collectionGap) {
|
|
121
|
+
summary.collectionGaps.push(flushResult.collectionGap);
|
|
122
|
+
}
|
|
123
|
+
if (flushResult?.learnerPath &&
|
|
124
|
+
requestedLearnerPath !== flushResult.learnerPath) {
|
|
125
|
+
summary.collectionGaps.push(`Ambient learner override at ${requestedLearnerPath} did not match the running daemon; report used flushed learner state from ${flushResult.learnerPath}.`);
|
|
126
|
+
}
|
|
127
|
+
if (!existsSync(learnerPath)) {
|
|
128
|
+
summary.collectionGaps.push(`Ambient learner file not found at ${learnerPath}. Run ambient work before claiming learned automation patterns.`);
|
|
129
|
+
return summary;
|
|
130
|
+
}
|
|
131
|
+
let raw = "";
|
|
132
|
+
try {
|
|
133
|
+
raw = await readFile(learnerPath, "utf8");
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
summary.collectionGaps.push(`Ambient learner file could not be read: ${sanitizeWithStaticMask(error instanceof Error ? error.message : String(error))}.`);
|
|
137
|
+
return summary;
|
|
138
|
+
}
|
|
139
|
+
let parsed;
|
|
140
|
+
try {
|
|
141
|
+
parsed = JSON.parse(raw);
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
summary.collectionGaps.push(`Ambient learner file at ${learnerPath} is not valid JSON.`);
|
|
145
|
+
return summary;
|
|
146
|
+
}
|
|
147
|
+
if (!parsed || typeof parsed !== "object") {
|
|
148
|
+
summary.collectionGaps.push(`Ambient learner file at ${learnerPath} did not contain an object.`);
|
|
149
|
+
return summary;
|
|
150
|
+
}
|
|
151
|
+
const record = parsed;
|
|
152
|
+
const outcomes = Array.isArray(record.outcomes) ? record.outcomes : [];
|
|
153
|
+
summary.outcomes = outcomes
|
|
154
|
+
.map(parseAmbientLearnerOutcome)
|
|
155
|
+
.filter((outcome) => Boolean(outcome))
|
|
156
|
+
.filter((outcome) => isTimestampInRangeOrUnbounded(outcome.timestamp, range));
|
|
157
|
+
summary.patterns = deriveAmbientLearnerPatterns(summary.outcomes);
|
|
158
|
+
if (summary.outcomes.length === 0) {
|
|
159
|
+
summary.collectionGaps.push(range.since === undefined && range.until === undefined
|
|
160
|
+
? `Ambient learner file at ${learnerPath} has no outcome evidence.`
|
|
161
|
+
: `Ambient learner file at ${learnerPath} has no outcome evidence for the selected range.`);
|
|
162
|
+
}
|
|
163
|
+
return summary;
|
|
164
|
+
}
|
|
165
|
+
function parseAmbientLearnerOutcome(value) {
|
|
166
|
+
if (!value || typeof value !== "object")
|
|
167
|
+
return undefined;
|
|
168
|
+
const record = value;
|
|
169
|
+
const success = record.success;
|
|
170
|
+
if (typeof success !== "boolean")
|
|
171
|
+
return undefined;
|
|
172
|
+
const labels = Array.isArray(record.labels)
|
|
173
|
+
? record.labels
|
|
174
|
+
.filter((label) => typeof label === "string")
|
|
175
|
+
.map((label) => sanitizeA2ALabel(label, 80))
|
|
176
|
+
: [];
|
|
177
|
+
return {
|
|
178
|
+
success,
|
|
179
|
+
...(typeof record.failure_reason === "string" &&
|
|
180
|
+
record.failure_reason.trim()
|
|
181
|
+
? { failureReason: redactLine(record.failure_reason) }
|
|
182
|
+
: {}),
|
|
183
|
+
labels,
|
|
184
|
+
...(typeof record.repo === "string"
|
|
185
|
+
? { repo: sanitizeA2ALabel(record.repo, 120) }
|
|
186
|
+
: {}),
|
|
187
|
+
...(typeof record.task_type === "string"
|
|
188
|
+
? { taskType: sanitizeA2ALabel(record.task_type, 80) }
|
|
189
|
+
: {}),
|
|
190
|
+
...(typeof record.event_type === "string"
|
|
191
|
+
? { eventType: sanitizeA2ALabel(record.event_type, 80) }
|
|
192
|
+
: {}),
|
|
193
|
+
costUsd: numberOrZero(record.cost_usd),
|
|
194
|
+
...(parseTimestampMs(record.timestamp) !== undefined
|
|
195
|
+
? { timestamp: parseTimestampMs(record.timestamp) }
|
|
196
|
+
: {}),
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function deriveAmbientLearnerPatterns(outcomes) {
|
|
200
|
+
const groups = new Map();
|
|
201
|
+
const add = (patternType, key, outcome) => {
|
|
202
|
+
if (!key)
|
|
203
|
+
return;
|
|
204
|
+
const groupKey = `${patternType}\u0000${key}`;
|
|
205
|
+
const group = groups.get(groupKey) ?? {
|
|
206
|
+
patternType,
|
|
207
|
+
key,
|
|
208
|
+
successCount: 0,
|
|
209
|
+
sampleCount: 0,
|
|
210
|
+
transientFailureCount: 0,
|
|
211
|
+
nonTransientFailureCount: 0,
|
|
212
|
+
};
|
|
213
|
+
group.sampleCount += 1;
|
|
214
|
+
if (outcome.success) {
|
|
215
|
+
group.successCount += 1;
|
|
216
|
+
}
|
|
217
|
+
else if (isTransientAmbientFailureOutcome(outcome)) {
|
|
218
|
+
group.transientFailureCount += 1;
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
group.nonTransientFailureCount += 1;
|
|
222
|
+
}
|
|
223
|
+
groups.set(groupKey, group);
|
|
224
|
+
};
|
|
225
|
+
for (const outcome of outcomes) {
|
|
226
|
+
for (const label of outcome.labels)
|
|
227
|
+
add("Label", label, outcome);
|
|
228
|
+
add("Repo", outcome.repo, outcome);
|
|
229
|
+
add("TaskType", outcome.taskType, outcome);
|
|
230
|
+
add("EventType", outcome.eventType, outcome);
|
|
231
|
+
}
|
|
232
|
+
return [...groups.values()]
|
|
233
|
+
.map((group) => ({
|
|
234
|
+
patternType: group.patternType,
|
|
235
|
+
key: group.key,
|
|
236
|
+
successRate: group.successCount / group.sampleCount,
|
|
237
|
+
sampleCount: group.sampleCount,
|
|
238
|
+
successCount: group.successCount,
|
|
239
|
+
transientFailureCount: group.transientFailureCount,
|
|
240
|
+
nonTransientFailureCount: group.nonTransientFailureCount,
|
|
241
|
+
nonTransientSampleCount: group.successCount + group.nonTransientFailureCount,
|
|
242
|
+
nonTransientSuccessRate: group.successCount + group.nonTransientFailureCount > 0
|
|
243
|
+
? group.successCount /
|
|
244
|
+
(group.successCount + group.nonTransientFailureCount)
|
|
245
|
+
: null,
|
|
246
|
+
}))
|
|
247
|
+
.sort((left, right) => right.sampleCount - left.sampleCount ||
|
|
248
|
+
right.successRate - left.successRate ||
|
|
249
|
+
left.patternType.localeCompare(right.patternType) ||
|
|
250
|
+
left.key.localeCompare(right.key));
|
|
251
|
+
}
|
|
252
|
+
export function buildAmbientCustomerValue(input) {
|
|
253
|
+
const successCount = input.learning.outcomes.filter((outcome) => outcome.success).length;
|
|
254
|
+
const failureCount = input.learning.outcomes.length - successCount;
|
|
255
|
+
const protectedTransientFailureCount = input.learning.outcomes.filter(isTransientAmbientFailureOutcome).length;
|
|
256
|
+
const actionablePatternCount = input.learning.patterns.filter((pattern) => pattern.nonTransientSampleCount >= 3).length;
|
|
257
|
+
const base = {
|
|
258
|
+
learnerPath: input.learning.learnerPath,
|
|
259
|
+
outcomeCount: input.learning.outcomes.length,
|
|
260
|
+
successCount,
|
|
261
|
+
failureCount,
|
|
262
|
+
successRate: input.learning.outcomes.length > 0
|
|
263
|
+
? successCount / input.learning.outcomes.length
|
|
264
|
+
: null,
|
|
265
|
+
totalCostUsd: sum(input.learning.outcomes, (outcome) => outcome.costUsd),
|
|
266
|
+
patternCount: input.learning.patterns.length,
|
|
267
|
+
actionablePatternCount,
|
|
268
|
+
protectedTransientFailureCount,
|
|
269
|
+
collectionGaps: input.learning.collectionGaps,
|
|
270
|
+
};
|
|
271
|
+
const automationOpportunities = buildAmbientAutomationOpportunities({
|
|
272
|
+
ambient: base,
|
|
273
|
+
multiAgent: input.multiAgent,
|
|
274
|
+
trustCards: input.trustCards,
|
|
275
|
+
handoffs: input.handoffs,
|
|
276
|
+
});
|
|
277
|
+
const playbookLearningOpportunities = buildPlaybookLearningOpportunities({
|
|
278
|
+
ambient: base,
|
|
279
|
+
learning: input.learning,
|
|
280
|
+
multiAgent: input.multiAgent,
|
|
281
|
+
trustCards: input.trustCards,
|
|
282
|
+
handoffs: input.handoffs,
|
|
283
|
+
});
|
|
284
|
+
return {
|
|
285
|
+
...base,
|
|
286
|
+
automationOpportunities,
|
|
287
|
+
playbookLearningOpportunities,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
function buildAmbientAutomationOpportunities(input) {
|
|
291
|
+
const opportunities = [];
|
|
292
|
+
if (input.multiAgent.delegatedPendingTaskCount > 0 ||
|
|
293
|
+
input.multiAgent.nextActions.length > 0) {
|
|
294
|
+
opportunities.push({
|
|
295
|
+
id: "a2a-followup-watchdog",
|
|
296
|
+
customerOutcome: "Wake operators only when delegated work needs a reply, wait, refresh, or evidence check.",
|
|
297
|
+
triggerEvidence: `${input.multiAgent.delegatedPendingTaskCount} pending delegated task(s) and ${input.multiAgent.nextActions.length} cockpit next action(s).`,
|
|
298
|
+
recommendedCadence: "hourly",
|
|
299
|
+
scriptGate: "maestro a2a cockpit --json | jq -e '.nextActions | length > 0'",
|
|
300
|
+
delivery: "Slack or CLI notification with the first cockpit next action and value-report link.",
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
const failedToolResults = sum(input.trustCards, (card) => card.failedToolResultCount);
|
|
304
|
+
if (failedToolResults > 0 || input.handoffs.blockedCount > 0) {
|
|
305
|
+
opportunities.push({
|
|
306
|
+
id: "failed-tool-digest",
|
|
307
|
+
customerOutcome: "Convert failed tool evidence into a daily repair queue instead of losing it in chat history.",
|
|
308
|
+
triggerEvidence: `${failedToolResults} failed tool result(s) and ${input.handoffs.blockedCount} blocked handoff(s).`,
|
|
309
|
+
recommendedCadence: "daily",
|
|
310
|
+
scriptGate: "maestro value yesterday --format json | jq -e '.handoffs.blockedCount > 0 or .summary.failedToolResultCount > 0'",
|
|
311
|
+
delivery: "Daily digest with blocked handoffs, failed tool counts, and replayable session paths.",
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
const memoryGapCount = input.trustCards.filter((card) => !card.evidence.hasMemoryProvenance).length;
|
|
315
|
+
if (memoryGapCount > 0) {
|
|
316
|
+
opportunities.push({
|
|
317
|
+
id: "memory-gap-digest",
|
|
318
|
+
customerOutcome: "Turn valuable one-off sessions into reusable customer context before the lessons go stale.",
|
|
319
|
+
triggerEvidence: `${memoryGapCount} trust card(s) lack durable memory provenance.`,
|
|
320
|
+
recommendedCadence: "weekly",
|
|
321
|
+
scriptGate: "maestro value week --format json | jq -e 'any(.trustCards[]?; .evidence.hasMemoryProvenance | not)'",
|
|
322
|
+
delivery: "Weekly report of sessions that need memory or playbook capture.",
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
if (input.ambient.outcomeCount > 0) {
|
|
326
|
+
opportunities.push({
|
|
327
|
+
id: "ambient-learner-review",
|
|
328
|
+
customerOutcome: "Review ambient outcomes on a schedule and promote only durable patterns into team playbooks.",
|
|
329
|
+
triggerEvidence: `${input.ambient.outcomeCount} learner outcome(s), ${input.ambient.actionablePatternCount} actionable pattern(s), ${input.ambient.protectedTransientFailureCount} protected transient failure(s).`,
|
|
330
|
+
recommendedCadence: "weekly",
|
|
331
|
+
scriptGate: ambientLearnerPresenceCommand(input.ambient.learnerPath),
|
|
332
|
+
delivery: "Weekly playbook review with successes, low-success patterns, and quarantined transient failures.",
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
return opportunities.slice(0, 5);
|
|
336
|
+
}
|
|
337
|
+
function buildPlaybookLearningOpportunities(input) {
|
|
338
|
+
const opportunities = [];
|
|
339
|
+
if (input.ambient.protectedTransientFailureCount > 0) {
|
|
340
|
+
opportunities.push({
|
|
341
|
+
id: "protect-transient-failures",
|
|
342
|
+
customerOutcome: "Prevent temporary setup failures from becoming permanent agent refusals or bad playbooks.",
|
|
343
|
+
evidenceSignal: `${input.ambient.protectedTransientFailureCount} learner failure(s) matched transient setup or environment patterns.`,
|
|
344
|
+
guardrail: "Capture the recovery command or setup prerequisite, not a durable claim that the tool is broken.",
|
|
345
|
+
recommendedArtifact: ".maestro/playbooks/ambient-transient-failure-guardrail.md",
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
const topSuccess = input.learning.patterns
|
|
349
|
+
.filter((pattern) => pattern.nonTransientSampleCount >= 3 &&
|
|
350
|
+
pattern.nonTransientSuccessRate !== null &&
|
|
351
|
+
pattern.nonTransientSuccessRate >= 0.75)
|
|
352
|
+
.sort((left, right) => (right.nonTransientSuccessRate ?? 0) -
|
|
353
|
+
(left.nonTransientSuccessRate ?? 0))[0];
|
|
354
|
+
if (topSuccess) {
|
|
355
|
+
opportunities.push({
|
|
356
|
+
id: "capture-successful-pattern",
|
|
357
|
+
customerOutcome: "Turn repeated ambient success into a reusable team playbook for similar work.",
|
|
358
|
+
evidenceSignal: `${topSuccess.patternType}=${topSuccess.key} succeeded ${((topSuccess.nonTransientSuccessRate ?? 0) * 100).toFixed(1)}% across ${topSuccess.nonTransientSampleCount} non-transient sample(s).`,
|
|
359
|
+
guardrail: "Promote the durable task shape, required evidence, and verification steps; do not copy one-off task details.",
|
|
360
|
+
recommendedArtifact: `.maestro/playbooks/ambient-${slugify(topSuccess.patternType)}-${slugify(topSuccess.key)}.md`,
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
const lowSuccess = input.learning.patterns
|
|
364
|
+
.filter((pattern) => pattern.nonTransientSampleCount >= 3 &&
|
|
365
|
+
pattern.nonTransientSuccessRate !== null &&
|
|
366
|
+
pattern.nonTransientSuccessRate < 0.45 &&
|
|
367
|
+
pattern.nonTransientFailureCount > 0)
|
|
368
|
+
.sort((left, right) => (left.nonTransientSuccessRate ?? 1) -
|
|
369
|
+
(right.nonTransientSuccessRate ?? 1))[0];
|
|
370
|
+
if (lowSuccess) {
|
|
371
|
+
opportunities.push({
|
|
372
|
+
id: "repair-low-success-pattern",
|
|
373
|
+
customerOutcome: "Reduce repeated ambient failures by tightening routing, approval, or verification for a known weak pattern.",
|
|
374
|
+
evidenceSignal: `${lowSuccess.patternType}=${lowSuccess.key} succeeded only ${((lowSuccess.nonTransientSuccessRate ?? 0) * 100).toFixed(1)}% across ${lowSuccess.nonTransientSampleCount} non-transient sample(s).`,
|
|
375
|
+
guardrail: "Prefer threshold/routing changes or added checks over broad bans on the task class.",
|
|
376
|
+
recommendedArtifact: `.maestro/playbooks/ambient-${slugify(lowSuccess.patternType)}-${slugify(lowSuccess.key)}-repair.md`,
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
if (input.multiAgent.delegatedEvidenceGapCount > 0 ||
|
|
380
|
+
input.multiAgent.nextActions.length > 0) {
|
|
381
|
+
opportunities.push({
|
|
382
|
+
id: "multi-agent-verification-playbook",
|
|
383
|
+
customerOutcome: "Make subagent work customer-trustworthy by requiring parent-side verification before value is claimed.",
|
|
384
|
+
evidenceSignal: `${input.multiAgent.delegatedEvidenceGapCount} delegated evidence gap(s) and ${input.multiAgent.nextActions.length} A2A next action(s).`,
|
|
385
|
+
guardrail: "Treat subagent summaries as self-reports until a URL, file path, task id, work graph, transcript, or test result is read back.",
|
|
386
|
+
recommendedArtifact: ".maestro/playbooks/multi-agent-verification.md",
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
if (input.handoffs.followupCount > 0 ||
|
|
390
|
+
input.handoffs.openWorkCount > 0 ||
|
|
391
|
+
input.trustCards.some((card) => card.riskSignals.length > 0)) {
|
|
392
|
+
opportunities.push({
|
|
393
|
+
id: "handoff-memory-playbook",
|
|
394
|
+
customerOutcome: "Convert unfinished work, blockers, and user corrections into durable next-session behavior.",
|
|
395
|
+
evidenceSignal: `${input.handoffs.followupCount} follow-up handoff(s), ${input.handoffs.openWorkCount} open work item(s).`,
|
|
396
|
+
guardrail: "Store user/workflow preferences as playbook steps, while keeping secrets and transient errors out of durable memory.",
|
|
397
|
+
recommendedArtifact: ".maestro/playbooks/customer-handoff-learning.md",
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
return opportunities.slice(0, 6);
|
|
401
|
+
}
|
|
402
|
+
function isTransientAmbientFailureOutcome(outcome) {
|
|
403
|
+
if (outcome.success || !outcome.failureReason)
|
|
404
|
+
return false;
|
|
405
|
+
return isTransientFailureText(outcome.failureReason);
|
|
406
|
+
}
|
|
407
|
+
function isTransientFailureText(text) {
|
|
408
|
+
const normalized = text.toLowerCase();
|
|
409
|
+
return ([
|
|
410
|
+
"command not found",
|
|
411
|
+
"no such file or directory",
|
|
412
|
+
"missing binary",
|
|
413
|
+
"missing credential",
|
|
414
|
+
"unconfigured",
|
|
415
|
+
"not configured",
|
|
416
|
+
"authentication required",
|
|
417
|
+
"connection refused",
|
|
418
|
+
"temporary failure in name resolution",
|
|
419
|
+
].some((needle) => normalized.includes(needle)) ||
|
|
420
|
+
isTransientRateLimitFailureText(normalized) ||
|
|
421
|
+
isTransientTransportFailureText(normalized));
|
|
422
|
+
}
|
|
423
|
+
function isTransientRateLimitFailureText(normalized) {
|
|
424
|
+
return (["429 too many requests", "http 429", "status 429"].some((needle) => normalized.includes(needle)) ||
|
|
425
|
+
(normalized.includes("rate limit") &&
|
|
426
|
+
hasTransientEnvironmentContext(normalized)));
|
|
427
|
+
}
|
|
428
|
+
function isTransientTransportFailureText(normalized) {
|
|
429
|
+
return ([
|
|
430
|
+
"etimedout",
|
|
431
|
+
"econnreset",
|
|
432
|
+
"enotfound",
|
|
433
|
+
"eai_again",
|
|
434
|
+
"connection timed out",
|
|
435
|
+
"socket timed out",
|
|
436
|
+
"network unreachable",
|
|
437
|
+
"network unavailable",
|
|
438
|
+
"network reset",
|
|
439
|
+
"temporary network",
|
|
440
|
+
].some((needle) => normalized.includes(needle)) ||
|
|
441
|
+
([
|
|
442
|
+
"request timed out",
|
|
443
|
+
"connect timed out",
|
|
444
|
+
"fetch timed out",
|
|
445
|
+
"timed out",
|
|
446
|
+
"network error",
|
|
447
|
+
"network failure",
|
|
448
|
+
"dns lookup",
|
|
449
|
+
"name resolution",
|
|
450
|
+
].some((needle) => normalized.includes(needle)) &&
|
|
451
|
+
hasTransientEnvironmentContext(normalized)));
|
|
452
|
+
}
|
|
453
|
+
function hasTransientEnvironmentContext(normalized) {
|
|
454
|
+
return [
|
|
455
|
+
"while bootstrapping",
|
|
456
|
+
"while fetching",
|
|
457
|
+
"while downloading",
|
|
458
|
+
"while installing",
|
|
459
|
+
"while authenticating",
|
|
460
|
+
"while connecting",
|
|
461
|
+
"while calling",
|
|
462
|
+
"fetching dependencies",
|
|
463
|
+
"downloading dependencies",
|
|
464
|
+
"installing dependencies",
|
|
465
|
+
"dependency install",
|
|
466
|
+
"fresh runner",
|
|
467
|
+
"github api",
|
|
468
|
+
"npm registry",
|
|
469
|
+
"package registry",
|
|
470
|
+
].some((needle) => normalized.includes(needle));
|
|
471
|
+
}
|
|
472
|
+
//# sourceMappingURL=ambient-learning.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ambient-learning.js","sourceRoot":"","sources":["../../src/customer-value/ambient-learning.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Ambient learner subsystem for the customer-value report.\n *\n * Owns everything that reads/classifies the ambient learner outcome file:\n * daemon flush, JSON parsing, pattern derivation, transient-failure\n * classification, and the ambient customer-value/opportunity builders that\n * turn learner evidence into report sections.\n *\n * Extracted from report.ts to isolate the highest-churn surface (transient\n * classification + flush freshness evolve frequently) behind a stable module\n * boundary. Runtime dependencies are one-directional: this module imports\n * shared leaf helpers from ./internal-helpers.js and types from ./report.js\n * (type-only). report.ts imports the summary/build entry points back here.\n */\nimport { spawn } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport type { RuntimeEnv } from \"../runtime/env.js\";\nimport { sanitizeWithStaticMask } from \"../utils/secret-redactor.js\";\nimport {\n\tisTimestampInRangeOrUnbounded,\n\tnumberOrZero,\n\tparseTimestampMs,\n\tredactLine,\n\tsanitizeA2ALabel,\n\tslugify,\n\tsum,\n} from \"./internal-helpers.js\";\nimport type {\n\tCustomerValueRange,\n\tCustomerValueReport,\n\tMultiAgentValue,\n\tTrustCard,\n} from \"./report.js\";\n\nfunction shellQuote(value: string): string {\n\treturn `'${value.replaceAll(\"'\", \"'\\\\''\")}'`;\n}\n\nexport function ambientLearnerPresenceCommand(learnerPath: string): string {\n\treturn `test -s ${shellQuote(learnerPath)}`;\n}\n\nexport interface AmbientLearnerFlushResult {\n\tflushed: boolean;\n\tlearnerPath?: string;\n\tcollectionGap?: string;\n}\n\nexport interface AmbientAutomationOpportunity {\n\tid:\n\t\t| \"a2a-followup-watchdog\"\n\t\t| \"failed-tool-digest\"\n\t\t| \"memory-gap-digest\"\n\t\t| \"ambient-learner-review\";\n\tcustomerOutcome: string;\n\ttriggerEvidence: string;\n\trecommendedCadence: \"hourly\" | \"daily\" | \"weekly\";\n\tscriptGate: string;\n\tdelivery: string;\n}\n\nexport interface PlaybookLearningOpportunity {\n\tid:\n\t\t| \"protect-transient-failures\"\n\t\t| \"capture-successful-pattern\"\n\t\t| \"repair-low-success-pattern\"\n\t\t| \"multi-agent-verification-playbook\"\n\t\t| \"handoff-memory-playbook\";\n\tcustomerOutcome: string;\n\tevidenceSignal: string;\n\tguardrail: string;\n\trecommendedArtifact: string;\n}\n\nexport interface AmbientCustomerValue {\n\tlearnerPath: string;\n\toutcomeCount: number;\n\tsuccessCount: number;\n\tfailureCount: number;\n\tsuccessRate: number | null;\n\ttotalCostUsd: number;\n\tpatternCount: number;\n\tactionablePatternCount: number;\n\tprotectedTransientFailureCount: number;\n\tautomationOpportunities: AmbientAutomationOpportunity[];\n\tplaybookLearningOpportunities: PlaybookLearningOpportunity[];\n\tcollectionGaps: string[];\n}\n\ninterface AmbientLearningSummary {\n\tlearnerPath: string;\n\toutcomes: AmbientLearnerOutcome[];\n\tpatterns: AmbientLearnerPattern[];\n\tcollectionGaps: string[];\n}\n\ninterface AmbientLearnerOutcome {\n\tsuccess: boolean;\n\tfailureReason?: string;\n\tlabels: string[];\n\trepo?: string;\n\ttaskType?: string;\n\teventType?: string;\n\tcostUsd: number;\n\ttimestamp?: number;\n}\n\ninterface AmbientLearnerPattern {\n\tpatternType: string;\n\tkey: string;\n\tsuccessRate: number;\n\tsampleCount: number;\n\tsuccessCount: number;\n\ttransientFailureCount: number;\n\tnonTransientFailureCount: number;\n\tnonTransientSampleCount: number;\n\tnonTransientSuccessRate: number | null;\n}\n\nexport async function flushAmbientLearnerForReport(\n\tenv: RuntimeEnv,\n\t_learnerPath: string,\n\tflush: (env: RuntimeEnv) => Promise<AmbientLearnerFlushResult>,\n): Promise<AmbientLearnerFlushResult> {\n\treturn flush(env);\n}\n\nexport async function flushAmbientLearnerBeforeRead(\n\tenv: RuntimeEnv,\n): Promise<AmbientLearnerFlushResult> {\n\treturn new Promise((resolve) => {\n\t\tconst child = spawn(\"ambient\", [\"flush\"], {\n\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t});\n\t\tlet stdout = \"\";\n\t\tlet stderr = \"\";\n\t\tlet settled = false;\n\t\tconst finish = (result: AmbientLearnerFlushResult) => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tclearTimeout(timeout);\n\t\t\tresolve(result);\n\t\t};\n\t\tconst timeout = setTimeout(() => {\n\t\t\tchild.kill();\n\t\t\tfinish({\n\t\t\t\tflushed: false,\n\t\t\t\tcollectionGap:\n\t\t\t\t\t\"Ambient learner flush timed out before report generation.\",\n\t\t\t});\n\t\t}, 40000);\n\t\tchild.stdout?.setEncoding(\"utf8\");\n\t\tchild.stdout?.on(\"data\", (chunk: string) => {\n\t\t\tstdout += chunk;\n\t\t});\n\t\tchild.stderr?.setEncoding(\"utf8\");\n\t\tchild.stderr?.on(\"data\", (chunk: string) => {\n\t\t\tstderr += chunk;\n\t\t});\n\t\tchild.on(\"error\", (error) => {\n\t\t\tif (\n\t\t\t\t(error as NodeJS.ErrnoException).code === \"ENOENT\" &&\n\t\t\t\t!existsSync(env.ambientSocketFile)\n\t\t\t) {\n\t\t\t\tfinish({ flushed: false });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfinish({\n\t\t\t\tflushed: false,\n\t\t\t\tcollectionGap: `Ambient learner flush could not start: ${sanitizeWithStaticMask(error.message)}.`,\n\t\t\t});\n\t\t});\n\t\tchild.on(\"close\", (code) => {\n\t\t\tif (code === 0) {\n\t\t\t\tfinish({\n\t\t\t\t\tflushed: true,\n\t\t\t\t\tlearnerPath: parseAmbientFlushLearnerPath(\n\t\t\t\t\t\tstdout,\n\t\t\t\t\t\tenv.ambientLearnerDefaultFile,\n\t\t\t\t\t),\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst failureMessage =\n\t\t\t\tstderr.trim() || stdout.trim() || `exit ${code ?? \"unknown\"}`;\n\t\t\tif (isAmbientDaemonNotRunningFlushFailure(failureMessage, env)) {\n\t\t\t\tfinish({ flushed: false });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfinish({\n\t\t\t\tflushed: false,\n\t\t\t\tcollectionGap: `Ambient learner flush failed before report generation: ${sanitizeWithStaticMask(failureMessage)}.`,\n\t\t\t});\n\t\t});\n\t});\n}\n\nfunction isAmbientDaemonNotRunningFlushFailure(\n\tfailureMessage: string,\n\tenv: RuntimeEnv,\n): boolean {\n\tconst normalized = failureMessage.toLowerCase();\n\treturn (\n\t\tnormalized.includes(\"daemon is not running\") ||\n\t\tnormalized.includes(\"daemon not running\") ||\n\t\t(normalized.includes(\"socket not found\") &&\n\t\t\t!existsSync(env.ambientSocketFile))\n\t);\n}\n\nfunction parseAmbientFlushLearnerPath(\n\tstdout: string,\n\tfallbackPath: string,\n): string {\n\tconst prefix = \"Learner state flushed:\";\n\tconst lines = stdout\n\t\t.split(/\\r?\\n/u)\n\t\t.map((line) => line.trim())\n\t\t.filter(Boolean)\n\t\t.reverse();\n\tfor (const line of lines) {\n\t\tif (!line.startsWith(prefix)) continue;\n\t\tconst learnerPath = line.slice(prefix.length).trim();\n\t\tif (learnerPath) return learnerPath;\n\t}\n\treturn fallbackPath;\n}\n\nexport async function summarizeAmbientLearning(\n\tlearnerPath: string,\n\trange: CustomerValueRange,\n\tflushResult?: AmbientLearnerFlushResult,\n\trequestedLearnerPath = learnerPath,\n): Promise<AmbientLearningSummary> {\n\tconst summary: AmbientLearningSummary = {\n\t\tlearnerPath,\n\t\toutcomes: [],\n\t\tpatterns: [],\n\t\tcollectionGaps: [],\n\t};\n\tif (flushResult?.collectionGap) {\n\t\tsummary.collectionGaps.push(flushResult.collectionGap);\n\t}\n\tif (\n\t\tflushResult?.learnerPath &&\n\t\trequestedLearnerPath !== flushResult.learnerPath\n\t) {\n\t\tsummary.collectionGaps.push(\n\t\t\t`Ambient learner override at ${requestedLearnerPath} did not match the running daemon; report used flushed learner state from ${flushResult.learnerPath}.`,\n\t\t);\n\t}\n\tif (!existsSync(learnerPath)) {\n\t\tsummary.collectionGaps.push(\n\t\t\t`Ambient learner file not found at ${learnerPath}. Run ambient work before claiming learned automation patterns.`,\n\t\t);\n\t\treturn summary;\n\t}\n\tlet raw = \"\";\n\ttry {\n\t\traw = await readFile(learnerPath, \"utf8\");\n\t} catch (error) {\n\t\tsummary.collectionGaps.push(\n\t\t\t`Ambient learner file could not be read: ${sanitizeWithStaticMask(error instanceof Error ? error.message : String(error))}.`,\n\t\t);\n\t\treturn summary;\n\t}\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch {\n\t\tsummary.collectionGaps.push(\n\t\t\t`Ambient learner file at ${learnerPath} is not valid JSON.`,\n\t\t);\n\t\treturn summary;\n\t}\n\tif (!parsed || typeof parsed !== \"object\") {\n\t\tsummary.collectionGaps.push(\n\t\t\t`Ambient learner file at ${learnerPath} did not contain an object.`,\n\t\t);\n\t\treturn summary;\n\t}\n\tconst record = parsed as Record<string, unknown>;\n\tconst outcomes = Array.isArray(record.outcomes) ? record.outcomes : [];\n\tsummary.outcomes = outcomes\n\t\t.map(parseAmbientLearnerOutcome)\n\t\t.filter((outcome): outcome is AmbientLearnerOutcome => Boolean(outcome))\n\t\t.filter((outcome) =>\n\t\t\tisTimestampInRangeOrUnbounded(outcome.timestamp, range),\n\t\t);\n\tsummary.patterns = deriveAmbientLearnerPatterns(summary.outcomes);\n\tif (summary.outcomes.length === 0) {\n\t\tsummary.collectionGaps.push(\n\t\t\trange.since === undefined && range.until === undefined\n\t\t\t\t? `Ambient learner file at ${learnerPath} has no outcome evidence.`\n\t\t\t\t: `Ambient learner file at ${learnerPath} has no outcome evidence for the selected range.`,\n\t\t);\n\t}\n\treturn summary;\n}\n\nfunction parseAmbientLearnerOutcome(\n\tvalue: unknown,\n): AmbientLearnerOutcome | undefined {\n\tif (!value || typeof value !== \"object\") return undefined;\n\tconst record = value as Record<string, unknown>;\n\tconst success = record.success;\n\tif (typeof success !== \"boolean\") return undefined;\n\tconst labels = Array.isArray(record.labels)\n\t\t? record.labels\n\t\t\t\t.filter((label): label is string => typeof label === \"string\")\n\t\t\t\t.map((label) => sanitizeA2ALabel(label, 80))\n\t\t: [];\n\treturn {\n\t\tsuccess,\n\t\t...(typeof record.failure_reason === \"string\" &&\n\t\trecord.failure_reason.trim()\n\t\t\t? { failureReason: redactLine(record.failure_reason) }\n\t\t\t: {}),\n\t\tlabels,\n\t\t...(typeof record.repo === \"string\"\n\t\t\t? { repo: sanitizeA2ALabel(record.repo, 120) }\n\t\t\t: {}),\n\t\t...(typeof record.task_type === \"string\"\n\t\t\t? { taskType: sanitizeA2ALabel(record.task_type, 80) }\n\t\t\t: {}),\n\t\t...(typeof record.event_type === \"string\"\n\t\t\t? { eventType: sanitizeA2ALabel(record.event_type, 80) }\n\t\t\t: {}),\n\t\tcostUsd: numberOrZero(record.cost_usd),\n\t\t...(parseTimestampMs(record.timestamp) !== undefined\n\t\t\t? { timestamp: parseTimestampMs(record.timestamp)! }\n\t\t\t: {}),\n\t};\n}\n\nfunction deriveAmbientLearnerPatterns(\n\toutcomes: AmbientLearnerOutcome[],\n): AmbientLearnerPattern[] {\n\tconst groups = new Map<\n\t\tstring,\n\t\t{\n\t\t\tpatternType: string;\n\t\t\tkey: string;\n\t\t\tsuccessCount: number;\n\t\t\tsampleCount: number;\n\t\t\ttransientFailureCount: number;\n\t\t\tnonTransientFailureCount: number;\n\t\t}\n\t>();\n\tconst add = (\n\t\tpatternType: string,\n\t\tkey: string | undefined,\n\t\toutcome: AmbientLearnerOutcome,\n\t) => {\n\t\tif (!key) return;\n\t\tconst groupKey = `${patternType}\\u0000${key}`;\n\t\tconst group = groups.get(groupKey) ?? {\n\t\t\tpatternType,\n\t\t\tkey,\n\t\t\tsuccessCount: 0,\n\t\t\tsampleCount: 0,\n\t\t\ttransientFailureCount: 0,\n\t\t\tnonTransientFailureCount: 0,\n\t\t};\n\t\tgroup.sampleCount += 1;\n\t\tif (outcome.success) {\n\t\t\tgroup.successCount += 1;\n\t\t} else if (isTransientAmbientFailureOutcome(outcome)) {\n\t\t\tgroup.transientFailureCount += 1;\n\t\t} else {\n\t\t\tgroup.nonTransientFailureCount += 1;\n\t\t}\n\t\tgroups.set(groupKey, group);\n\t};\n\tfor (const outcome of outcomes) {\n\t\tfor (const label of outcome.labels) add(\"Label\", label, outcome);\n\t\tadd(\"Repo\", outcome.repo, outcome);\n\t\tadd(\"TaskType\", outcome.taskType, outcome);\n\t\tadd(\"EventType\", outcome.eventType, outcome);\n\t}\n\treturn [...groups.values()]\n\t\t.map((group) => ({\n\t\t\tpatternType: group.patternType,\n\t\t\tkey: group.key,\n\t\t\tsuccessRate: group.successCount / group.sampleCount,\n\t\t\tsampleCount: group.sampleCount,\n\t\t\tsuccessCount: group.successCount,\n\t\t\ttransientFailureCount: group.transientFailureCount,\n\t\t\tnonTransientFailureCount: group.nonTransientFailureCount,\n\t\t\tnonTransientSampleCount:\n\t\t\t\tgroup.successCount + group.nonTransientFailureCount,\n\t\t\tnonTransientSuccessRate:\n\t\t\t\tgroup.successCount + group.nonTransientFailureCount > 0\n\t\t\t\t\t? group.successCount /\n\t\t\t\t\t\t(group.successCount + group.nonTransientFailureCount)\n\t\t\t\t\t: null,\n\t\t}))\n\t\t.sort(\n\t\t\t(left, right) =>\n\t\t\t\tright.sampleCount - left.sampleCount ||\n\t\t\t\tright.successRate - left.successRate ||\n\t\t\t\tleft.patternType.localeCompare(right.patternType) ||\n\t\t\t\tleft.key.localeCompare(right.key),\n\t\t);\n}\n\nexport function buildAmbientCustomerValue(input: {\n\tlearning: AmbientLearningSummary;\n\tmultiAgent: MultiAgentValue;\n\ttrustCards: TrustCard[];\n\thandoffs: CustomerValueReport[\"handoffs\"];\n}): AmbientCustomerValue {\n\tconst successCount = input.learning.outcomes.filter(\n\t\t(outcome) => outcome.success,\n\t).length;\n\tconst failureCount = input.learning.outcomes.length - successCount;\n\tconst protectedTransientFailureCount = input.learning.outcomes.filter(\n\t\tisTransientAmbientFailureOutcome,\n\t).length;\n\tconst actionablePatternCount = input.learning.patterns.filter(\n\t\t(pattern) => pattern.nonTransientSampleCount >= 3,\n\t).length;\n\tconst base: Omit<\n\t\tAmbientCustomerValue,\n\t\t\"automationOpportunities\" | \"playbookLearningOpportunities\"\n\t> = {\n\t\tlearnerPath: input.learning.learnerPath,\n\t\toutcomeCount: input.learning.outcomes.length,\n\t\tsuccessCount,\n\t\tfailureCount,\n\t\tsuccessRate:\n\t\t\tinput.learning.outcomes.length > 0\n\t\t\t\t? successCount / input.learning.outcomes.length\n\t\t\t\t: null,\n\t\ttotalCostUsd: sum(input.learning.outcomes, (outcome) => outcome.costUsd),\n\t\tpatternCount: input.learning.patterns.length,\n\t\tactionablePatternCount,\n\t\tprotectedTransientFailureCount,\n\t\tcollectionGaps: input.learning.collectionGaps,\n\t};\n\tconst automationOpportunities = buildAmbientAutomationOpportunities({\n\t\tambient: base,\n\t\tmultiAgent: input.multiAgent,\n\t\ttrustCards: input.trustCards,\n\t\thandoffs: input.handoffs,\n\t});\n\tconst playbookLearningOpportunities = buildPlaybookLearningOpportunities({\n\t\tambient: base,\n\t\tlearning: input.learning,\n\t\tmultiAgent: input.multiAgent,\n\t\ttrustCards: input.trustCards,\n\t\thandoffs: input.handoffs,\n\t});\n\treturn {\n\t\t...base,\n\t\tautomationOpportunities,\n\t\tplaybookLearningOpportunities,\n\t};\n}\n\nfunction buildAmbientAutomationOpportunities(input: {\n\tambient: Omit<\n\t\tAmbientCustomerValue,\n\t\t\"automationOpportunities\" | \"playbookLearningOpportunities\"\n\t>;\n\tmultiAgent: MultiAgentValue;\n\ttrustCards: TrustCard[];\n\thandoffs: CustomerValueReport[\"handoffs\"];\n}): AmbientAutomationOpportunity[] {\n\tconst opportunities: AmbientAutomationOpportunity[] = [];\n\tif (\n\t\tinput.multiAgent.delegatedPendingTaskCount > 0 ||\n\t\tinput.multiAgent.nextActions.length > 0\n\t) {\n\t\topportunities.push({\n\t\t\tid: \"a2a-followup-watchdog\",\n\t\t\tcustomerOutcome:\n\t\t\t\t\"Wake operators only when delegated work needs a reply, wait, refresh, or evidence check.\",\n\t\t\ttriggerEvidence: `${input.multiAgent.delegatedPendingTaskCount} pending delegated task(s) and ${input.multiAgent.nextActions.length} cockpit next action(s).`,\n\t\t\trecommendedCadence: \"hourly\",\n\t\t\tscriptGate:\n\t\t\t\t\"maestro a2a cockpit --json | jq -e '.nextActions | length > 0'\",\n\t\t\tdelivery:\n\t\t\t\t\"Slack or CLI notification with the first cockpit next action and value-report link.\",\n\t\t});\n\t}\n\tconst failedToolResults = sum(\n\t\tinput.trustCards,\n\t\t(card) => card.failedToolResultCount,\n\t);\n\tif (failedToolResults > 0 || input.handoffs.blockedCount > 0) {\n\t\topportunities.push({\n\t\t\tid: \"failed-tool-digest\",\n\t\t\tcustomerOutcome:\n\t\t\t\t\"Convert failed tool evidence into a daily repair queue instead of losing it in chat history.\",\n\t\t\ttriggerEvidence: `${failedToolResults} failed tool result(s) and ${input.handoffs.blockedCount} blocked handoff(s).`,\n\t\t\trecommendedCadence: \"daily\",\n\t\t\tscriptGate:\n\t\t\t\t\"maestro value yesterday --format json | jq -e '.handoffs.blockedCount > 0 or .summary.failedToolResultCount > 0'\",\n\t\t\tdelivery:\n\t\t\t\t\"Daily digest with blocked handoffs, failed tool counts, and replayable session paths.\",\n\t\t});\n\t}\n\tconst memoryGapCount = input.trustCards.filter(\n\t\t(card) => !card.evidence.hasMemoryProvenance,\n\t).length;\n\tif (memoryGapCount > 0) {\n\t\topportunities.push({\n\t\t\tid: \"memory-gap-digest\",\n\t\t\tcustomerOutcome:\n\t\t\t\t\"Turn valuable one-off sessions into reusable customer context before the lessons go stale.\",\n\t\t\ttriggerEvidence: `${memoryGapCount} trust card(s) lack durable memory provenance.`,\n\t\t\trecommendedCadence: \"weekly\",\n\t\t\tscriptGate:\n\t\t\t\t\"maestro value week --format json | jq -e 'any(.trustCards[]?; .evidence.hasMemoryProvenance | not)'\",\n\t\t\tdelivery:\n\t\t\t\t\"Weekly report of sessions that need memory or playbook capture.\",\n\t\t});\n\t}\n\tif (input.ambient.outcomeCount > 0) {\n\t\topportunities.push({\n\t\t\tid: \"ambient-learner-review\",\n\t\t\tcustomerOutcome:\n\t\t\t\t\"Review ambient outcomes on a schedule and promote only durable patterns into team playbooks.\",\n\t\t\ttriggerEvidence: `${input.ambient.outcomeCount} learner outcome(s), ${input.ambient.actionablePatternCount} actionable pattern(s), ${input.ambient.protectedTransientFailureCount} protected transient failure(s).`,\n\t\t\trecommendedCadence: \"weekly\",\n\t\t\tscriptGate: ambientLearnerPresenceCommand(input.ambient.learnerPath),\n\t\t\tdelivery:\n\t\t\t\t\"Weekly playbook review with successes, low-success patterns, and quarantined transient failures.\",\n\t\t});\n\t}\n\treturn opportunities.slice(0, 5);\n}\n\nfunction buildPlaybookLearningOpportunities(input: {\n\tambient: Omit<\n\t\tAmbientCustomerValue,\n\t\t\"automationOpportunities\" | \"playbookLearningOpportunities\"\n\t>;\n\tlearning: AmbientLearningSummary;\n\tmultiAgent: MultiAgentValue;\n\ttrustCards: TrustCard[];\n\thandoffs: CustomerValueReport[\"handoffs\"];\n}): PlaybookLearningOpportunity[] {\n\tconst opportunities: PlaybookLearningOpportunity[] = [];\n\tif (input.ambient.protectedTransientFailureCount > 0) {\n\t\topportunities.push({\n\t\t\tid: \"protect-transient-failures\",\n\t\t\tcustomerOutcome:\n\t\t\t\t\"Prevent temporary setup failures from becoming permanent agent refusals or bad playbooks.\",\n\t\t\tevidenceSignal: `${input.ambient.protectedTransientFailureCount} learner failure(s) matched transient setup or environment patterns.`,\n\t\t\tguardrail:\n\t\t\t\t\"Capture the recovery command or setup prerequisite, not a durable claim that the tool is broken.\",\n\t\t\trecommendedArtifact:\n\t\t\t\t\".maestro/playbooks/ambient-transient-failure-guardrail.md\",\n\t\t});\n\t}\n\tconst topSuccess = input.learning.patterns\n\t\t.filter(\n\t\t\t(pattern) =>\n\t\t\t\tpattern.nonTransientSampleCount >= 3 &&\n\t\t\t\tpattern.nonTransientSuccessRate !== null &&\n\t\t\t\tpattern.nonTransientSuccessRate >= 0.75,\n\t\t)\n\t\t.sort(\n\t\t\t(left, right) =>\n\t\t\t\t(right.nonTransientSuccessRate ?? 0) -\n\t\t\t\t(left.nonTransientSuccessRate ?? 0),\n\t\t)[0];\n\tif (topSuccess) {\n\t\topportunities.push({\n\t\t\tid: \"capture-successful-pattern\",\n\t\t\tcustomerOutcome:\n\t\t\t\t\"Turn repeated ambient success into a reusable team playbook for similar work.\",\n\t\t\tevidenceSignal: `${topSuccess.patternType}=${topSuccess.key} succeeded ${((topSuccess.nonTransientSuccessRate ?? 0) * 100).toFixed(1)}% across ${topSuccess.nonTransientSampleCount} non-transient sample(s).`,\n\t\t\tguardrail:\n\t\t\t\t\"Promote the durable task shape, required evidence, and verification steps; do not copy one-off task details.\",\n\t\t\trecommendedArtifact: `.maestro/playbooks/ambient-${slugify(topSuccess.patternType)}-${slugify(topSuccess.key)}.md`,\n\t\t});\n\t}\n\tconst lowSuccess = input.learning.patterns\n\t\t.filter(\n\t\t\t(pattern) =>\n\t\t\t\tpattern.nonTransientSampleCount >= 3 &&\n\t\t\t\tpattern.nonTransientSuccessRate !== null &&\n\t\t\t\tpattern.nonTransientSuccessRate < 0.45 &&\n\t\t\t\tpattern.nonTransientFailureCount > 0,\n\t\t)\n\t\t.sort(\n\t\t\t(left, right) =>\n\t\t\t\t(left.nonTransientSuccessRate ?? 1) -\n\t\t\t\t(right.nonTransientSuccessRate ?? 1),\n\t\t)[0];\n\tif (lowSuccess) {\n\t\topportunities.push({\n\t\t\tid: \"repair-low-success-pattern\",\n\t\t\tcustomerOutcome:\n\t\t\t\t\"Reduce repeated ambient failures by tightening routing, approval, or verification for a known weak pattern.\",\n\t\t\tevidenceSignal: `${lowSuccess.patternType}=${lowSuccess.key} succeeded only ${((lowSuccess.nonTransientSuccessRate ?? 0) * 100).toFixed(1)}% across ${lowSuccess.nonTransientSampleCount} non-transient sample(s).`,\n\t\t\tguardrail:\n\t\t\t\t\"Prefer threshold/routing changes or added checks over broad bans on the task class.\",\n\t\t\trecommendedArtifact: `.maestro/playbooks/ambient-${slugify(lowSuccess.patternType)}-${slugify(lowSuccess.key)}-repair.md`,\n\t\t});\n\t}\n\tif (\n\t\tinput.multiAgent.delegatedEvidenceGapCount > 0 ||\n\t\tinput.multiAgent.nextActions.length > 0\n\t) {\n\t\topportunities.push({\n\t\t\tid: \"multi-agent-verification-playbook\",\n\t\t\tcustomerOutcome:\n\t\t\t\t\"Make subagent work customer-trustworthy by requiring parent-side verification before value is claimed.\",\n\t\t\tevidenceSignal: `${input.multiAgent.delegatedEvidenceGapCount} delegated evidence gap(s) and ${input.multiAgent.nextActions.length} A2A next action(s).`,\n\t\t\tguardrail:\n\t\t\t\t\"Treat subagent summaries as self-reports until a URL, file path, task id, work graph, transcript, or test result is read back.\",\n\t\t\trecommendedArtifact: \".maestro/playbooks/multi-agent-verification.md\",\n\t\t});\n\t}\n\tif (\n\t\tinput.handoffs.followupCount > 0 ||\n\t\tinput.handoffs.openWorkCount > 0 ||\n\t\tinput.trustCards.some((card) => card.riskSignals.length > 0)\n\t) {\n\t\topportunities.push({\n\t\t\tid: \"handoff-memory-playbook\",\n\t\t\tcustomerOutcome:\n\t\t\t\t\"Convert unfinished work, blockers, and user corrections into durable next-session behavior.\",\n\t\t\tevidenceSignal: `${input.handoffs.followupCount} follow-up handoff(s), ${input.handoffs.openWorkCount} open work item(s).`,\n\t\t\tguardrail:\n\t\t\t\t\"Store user/workflow preferences as playbook steps, while keeping secrets and transient errors out of durable memory.\",\n\t\t\trecommendedArtifact: \".maestro/playbooks/customer-handoff-learning.md\",\n\t\t});\n\t}\n\treturn opportunities.slice(0, 6);\n}\n\nfunction isTransientAmbientFailureOutcome(\n\toutcome: AmbientLearnerOutcome,\n): boolean {\n\tif (outcome.success || !outcome.failureReason) return false;\n\treturn isTransientFailureText(outcome.failureReason);\n}\n\nfunction isTransientFailureText(text: string): boolean {\n\tconst normalized = text.toLowerCase();\n\treturn (\n\t\t[\n\t\t\t\"command not found\",\n\t\t\t\"no such file or directory\",\n\t\t\t\"missing binary\",\n\t\t\t\"missing credential\",\n\t\t\t\"unconfigured\",\n\t\t\t\"not configured\",\n\t\t\t\"authentication required\",\n\t\t\t\"connection refused\",\n\t\t\t\"temporary failure in name resolution\",\n\t\t].some((needle) => normalized.includes(needle)) ||\n\t\tisTransientRateLimitFailureText(normalized) ||\n\t\tisTransientTransportFailureText(normalized)\n\t);\n}\n\nfunction isTransientRateLimitFailureText(normalized: string): boolean {\n\treturn (\n\t\t[\"429 too many requests\", \"http 429\", \"status 429\"].some((needle) =>\n\t\t\tnormalized.includes(needle),\n\t\t) ||\n\t\t(normalized.includes(\"rate limit\") &&\n\t\t\thasTransientEnvironmentContext(normalized))\n\t);\n}\n\nfunction isTransientTransportFailureText(normalized: string): boolean {\n\treturn (\n\t\t[\n\t\t\t\"etimedout\",\n\t\t\t\"econnreset\",\n\t\t\t\"enotfound\",\n\t\t\t\"eai_again\",\n\t\t\t\"connection timed out\",\n\t\t\t\"socket timed out\",\n\t\t\t\"network unreachable\",\n\t\t\t\"network unavailable\",\n\t\t\t\"network reset\",\n\t\t\t\"temporary network\",\n\t\t].some((needle) => normalized.includes(needle)) ||\n\t\t([\n\t\t\t\"request timed out\",\n\t\t\t\"connect timed out\",\n\t\t\t\"fetch timed out\",\n\t\t\t\"timed out\",\n\t\t\t\"network error\",\n\t\t\t\"network failure\",\n\t\t\t\"dns lookup\",\n\t\t\t\"name resolution\",\n\t\t].some((needle) => normalized.includes(needle)) &&\n\t\t\thasTransientEnvironmentContext(normalized))\n\t);\n}\n\nfunction hasTransientEnvironmentContext(normalized: string): boolean {\n\treturn [\n\t\t\"while bootstrapping\",\n\t\t\"while fetching\",\n\t\t\"while downloading\",\n\t\t\"while installing\",\n\t\t\"while authenticating\",\n\t\t\"while connecting\",\n\t\t\"while calling\",\n\t\t\"fetching dependencies\",\n\t\t\"downloading dependencies\",\n\t\t\"installing dependencies\",\n\t\t\"dependency install\",\n\t\t\"fresh runner\",\n\t\t\"github api\",\n\t\t\"npm registry\",\n\t\t\"package registry\",\n\t].some((needle) => normalized.includes(needle));\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CustomerValueRange } from "./report.js";
|
|
2
|
+
export declare function sum<T>(values: T[], read: (value: T) => number): number;
|
|
3
|
+
export declare function parseTimestampMs(timestamp: unknown): number | undefined;
|
|
4
|
+
export declare function isTimestampInRange(timestamp: unknown, range: CustomerValueRange): boolean;
|
|
5
|
+
export declare function isTimestampInRangeOrUnbounded(timestamp: number | undefined, range: CustomerValueRange): boolean;
|
|
6
|
+
export declare function numberField(value: unknown): number | undefined;
|
|
7
|
+
export declare function numberOrZero(value: unknown): number;
|
|
8
|
+
export declare function slugify(text: string): string;
|
|
9
|
+
export declare function truncate(text: string, maxLength: number): string;
|
|
10
|
+
export declare function normalizeLine(text: string): string;
|
|
11
|
+
export declare function redactLine(text: string): string;
|
|
12
|
+
export declare function sanitizeA2ALabel(text: string, maxLength: number): string;
|
|
13
|
+
//# sourceMappingURL=internal-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal-helpers.d.ts","sourceRoot":"","sources":["../../src/customer-value/internal-helpers.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEtD,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,GAAG,MAAM,CAEtE;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CASvE;AAED,wBAAgB,kBAAkB,CACjC,SAAS,EAAE,OAAO,EAClB,KAAK,EAAE,kBAAkB,GACvB,OAAO,CAMT;AAED,wBAAgB,6BAA6B,CAC5C,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,KAAK,EAAE,kBAAkB,GACvB,OAAO,CAIT;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAI9D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEnD;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM5C;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAGhE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAExE"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared leaf helpers extracted from report.ts so that the ambient-learning
|
|
3
|
+
* subsystem and the report builder can both depend on them without creating a
|
|
4
|
+
* runtime cycle between report.ts and ambient-learning.ts.
|
|
5
|
+
*
|
|
6
|
+
* Dependency direction (runtime): report.ts -> internal-helpers.ts,
|
|
7
|
+
* ambient-learning.ts -> internal-helpers.ts. No runtime imports point back at
|
|
8
|
+
* report.ts; the CustomerValueRange reference below is type-only (erased).
|
|
9
|
+
*/
|
|
10
|
+
import { sanitizeWithStaticMask } from "../utils/secret-redactor.js";
|
|
11
|
+
export function sum(values, read) {
|
|
12
|
+
return values.reduce((total, value) => total + read(value), 0);
|
|
13
|
+
}
|
|
14
|
+
export function parseTimestampMs(timestamp) {
|
|
15
|
+
if (typeof timestamp === "number" && Number.isFinite(timestamp)) {
|
|
16
|
+
return timestamp;
|
|
17
|
+
}
|
|
18
|
+
if (typeof timestamp !== "string" || timestamp.trim() === "") {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
const parsed = Date.parse(timestamp);
|
|
22
|
+
return Number.isNaN(parsed) ? undefined : parsed;
|
|
23
|
+
}
|
|
24
|
+
export function isTimestampInRange(timestamp, range) {
|
|
25
|
+
const timestampMs = parseTimestampMs(timestamp);
|
|
26
|
+
if (timestampMs === undefined)
|
|
27
|
+
return false;
|
|
28
|
+
if (range.since !== undefined && timestampMs < range.since)
|
|
29
|
+
return false;
|
|
30
|
+
if (range.until !== undefined && timestampMs >= range.until)
|
|
31
|
+
return false;
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
export function isTimestampInRangeOrUnbounded(timestamp, range) {
|
|
35
|
+
if (range.since === undefined && range.until === undefined)
|
|
36
|
+
return true;
|
|
37
|
+
if (timestamp === undefined)
|
|
38
|
+
return false;
|
|
39
|
+
return isTimestampInRange(timestamp, range);
|
|
40
|
+
}
|
|
41
|
+
export function numberField(value) {
|
|
42
|
+
return typeof value === "number" && Number.isFinite(value)
|
|
43
|
+
? value
|
|
44
|
+
: undefined;
|
|
45
|
+
}
|
|
46
|
+
export function numberOrZero(value) {
|
|
47
|
+
return numberField(value) ?? 0;
|
|
48
|
+
}
|
|
49
|
+
export function slugify(text) {
|
|
50
|
+
return text
|
|
51
|
+
.toLowerCase()
|
|
52
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
53
|
+
.replace(/^-|-$/g, "")
|
|
54
|
+
.slice(0, 64);
|
|
55
|
+
}
|
|
56
|
+
export function truncate(text, maxLength) {
|
|
57
|
+
if (text.length <= maxLength)
|
|
58
|
+
return text;
|
|
59
|
+
return `${text.slice(0, maxLength - 3)}...`;
|
|
60
|
+
}
|
|
61
|
+
export function normalizeLine(text) {
|
|
62
|
+
return text.replace(/\s+/g, " ").trim();
|
|
63
|
+
}
|
|
64
|
+
export function redactLine(text) {
|
|
65
|
+
return sanitizeWithStaticMask(normalizeLine(text));
|
|
66
|
+
}
|
|
67
|
+
export function sanitizeA2ALabel(text, maxLength) {
|
|
68
|
+
return truncate(redactLine(text), maxLength);
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=internal-helpers.js.map
|