agent-bober 0.18.0 → 0.19.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.
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +11 -0
- package/README.md +245 -6
- package/agents/bober-art-director.md +100 -0
- package/agents/bober-design-critic.md +114 -0
- package/agents/bober-frontend-builder.md +101 -0
- package/agents/bober-security-auditor.md +193 -0
- package/agents/bober-security-verifier.md +104 -0
- package/agents/bober-seo-strategist.md +144 -0
- package/agents/bober-seo-verifier.md +103 -0
- package/dist/calendar/calendar-egress.d.ts +26 -0
- package/dist/calendar/calendar-egress.d.ts.map +1 -0
- package/dist/calendar/calendar-egress.js +35 -0
- package/dist/calendar/calendar-egress.js.map +1 -0
- package/dist/calendar/calendar-token.d.ts +34 -0
- package/dist/calendar/calendar-token.d.ts.map +1 -0
- package/dist/calendar/calendar-token.js +56 -0
- package/dist/calendar/calendar-token.js.map +1 -0
- package/dist/calendar/connector.d.ts +22 -0
- package/dist/calendar/connector.d.ts.map +1 -0
- package/dist/calendar/connector.js +3 -0
- package/dist/calendar/connector.js.map +1 -0
- package/dist/calendar/finding-source.d.ts +20 -0
- package/dist/calendar/finding-source.d.ts.map +1 -0
- package/dist/calendar/finding-source.js +35 -0
- package/dist/calendar/finding-source.js.map +1 -0
- package/dist/calendar/google-connector.d.ts +65 -0
- package/dist/calendar/google-connector.d.ts.map +1 -0
- package/dist/calendar/google-connector.js +129 -0
- package/dist/calendar/google-connector.js.map +1 -0
- package/dist/calendar/ics-connector.d.ts +12 -0
- package/dist/calendar/ics-connector.d.ts.map +1 -0
- package/dist/calendar/ics-connector.js +48 -0
- package/dist/calendar/ics-connector.js.map +1 -0
- package/dist/calendar/proposal-gate.d.ts +84 -0
- package/dist/calendar/proposal-gate.d.ts.map +1 -0
- package/dist/calendar/proposal-gate.js +126 -0
- package/dist/calendar/proposal-gate.js.map +1 -0
- package/dist/calendar/slotter.d.ts +34 -0
- package/dist/calendar/slotter.d.ts.map +1 -0
- package/dist/calendar/slotter.js +196 -0
- package/dist/calendar/slotter.js.map +1 -0
- package/dist/calendar/types.d.ts +162 -0
- package/dist/calendar/types.d.ts.map +1 -0
- package/dist/calendar/types.js +28 -0
- package/dist/calendar/types.js.map +1 -0
- package/dist/chat/chat-session.d.ts +27 -0
- package/dist/chat/chat-session.d.ts.map +1 -1
- package/dist/chat/chat-session.js +101 -1
- package/dist/chat/chat-session.js.map +1 -1
- package/dist/chat/slash-commands.d.ts +6 -2
- package/dist/chat/slash-commands.d.ts.map +1 -1
- package/dist/chat/slash-commands.js +22 -2
- package/dist/chat/slash-commands.js.map +1 -1
- package/dist/chat/turn-classifier.d.ts +3 -0
- package/dist/chat/turn-classifier.d.ts.map +1 -1
- package/dist/chat/turn-classifier.js +7 -0
- package/dist/chat/turn-classifier.js.map +1 -1
- package/dist/cli/commands/calendar.d.ts +75 -0
- package/dist/cli/commands/calendar.d.ts.map +1 -0
- package/dist/cli/commands/calendar.js +203 -0
- package/dist/cli/commands/calendar.js.map +1 -0
- package/dist/cli/commands/do.d.ts +52 -0
- package/dist/cli/commands/do.d.ts.map +1 -0
- package/dist/cli/commands/do.js +216 -0
- package/dist/cli/commands/do.js.map +1 -0
- package/dist/cli/commands/hub.d.ts +29 -0
- package/dist/cli/commands/hub.d.ts.map +1 -0
- package/dist/cli/commands/hub.js +233 -0
- package/dist/cli/commands/hub.js.map +1 -0
- package/dist/cli/commands/medical.d.ts +25 -0
- package/dist/cli/commands/medical.d.ts.map +1 -1
- package/dist/cli/commands/medical.js +233 -0
- package/dist/cli/commands/medical.js.map +1 -1
- package/dist/cli/commands/research.d.ts +41 -0
- package/dist/cli/commands/research.d.ts.map +1 -0
- package/dist/cli/commands/research.js +313 -0
- package/dist/cli/commands/research.js.map +1 -0
- package/dist/cli/commands/security-audit.d.ts +89 -0
- package/dist/cli/commands/security-audit.d.ts.map +1 -0
- package/dist/cli/commands/security-audit.js +238 -0
- package/dist/cli/commands/security-audit.js.map +1 -0
- package/dist/cli/commands/task.d.ts +64 -0
- package/dist/cli/commands/task.d.ts.map +1 -0
- package/dist/cli/commands/task.js +422 -0
- package/dist/cli/commands/task.js.map +1 -0
- package/dist/cli/commands/telegram.d.ts +10 -0
- package/dist/cli/commands/telegram.d.ts.map +1 -0
- package/dist/cli/commands/telegram.js +44 -0
- package/dist/cli/commands/telegram.js.map +1 -0
- package/dist/cli/commands/vault.d.ts +40 -0
- package/dist/cli/commands/vault.d.ts.map +1 -0
- package/dist/cli/commands/vault.js +122 -0
- package/dist/cli/commands/vault.js.map +1 -0
- package/dist/cli/index.js +33 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/config/role-providers.d.ts +15 -0
- package/dist/config/role-providers.d.ts.map +1 -1
- package/dist/config/role-providers.js +8 -1
- package/dist/config/role-providers.js.map +1 -1
- package/dist/config/schema.d.ts +3522 -171
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +405 -2
- package/dist/config/schema.js.map +1 -1
- package/dist/do-bridge/coding-promoter.d.ts +19 -0
- package/dist/do-bridge/coding-promoter.d.ts.map +1 -0
- package/dist/do-bridge/coding-promoter.js +43 -0
- package/dist/do-bridge/coding-promoter.js.map +1 -0
- package/dist/do-bridge/finding-port.d.ts +88 -0
- package/dist/do-bridge/finding-port.d.ts.map +1 -0
- package/dist/do-bridge/finding-port.js +95 -0
- package/dist/do-bridge/finding-port.js.map +1 -0
- package/dist/do-bridge/launcher.d.ts +55 -0
- package/dist/do-bridge/launcher.d.ts.map +1 -0
- package/dist/do-bridge/launcher.js +37 -0
- package/dist/do-bridge/launcher.js.map +1 -0
- package/dist/do-bridge/promote.d.ts +50 -0
- package/dist/do-bridge/promote.d.ts.map +1 -0
- package/dist/do-bridge/promote.js +116 -0
- package/dist/do-bridge/promote.js.map +1 -0
- package/dist/do-bridge/reconcile.d.ts +50 -0
- package/dist/do-bridge/reconcile.d.ts.map +1 -0
- package/dist/do-bridge/reconcile.js +70 -0
- package/dist/do-bridge/reconcile.js.map +1 -0
- package/dist/do-bridge/registry.d.ts +23 -0
- package/dist/do-bridge/registry.d.ts.map +1 -0
- package/dist/do-bridge/registry.js +42 -0
- package/dist/do-bridge/registry.js.map +1 -0
- package/dist/do-bridge/types.d.ts +50 -0
- package/dist/do-bridge/types.d.ts.map +1 -0
- package/dist/do-bridge/types.js +17 -0
- package/dist/do-bridge/types.js.map +1 -0
- package/dist/fleet/child-config.d.ts.map +1 -1
- package/dist/fleet/child-config.js +7 -0
- package/dist/fleet/child-config.js.map +1 -1
- package/dist/fleet/coordinator.d.ts +27 -1
- package/dist/fleet/coordinator.d.ts.map +1 -1
- package/dist/fleet/coordinator.js +70 -0
- package/dist/fleet/coordinator.js.map +1 -1
- package/dist/fleet/critic-deep.d.ts +9 -1
- package/dist/fleet/critic-deep.d.ts.map +1 -1
- package/dist/fleet/critic-deep.js +5 -2
- package/dist/fleet/critic-deep.js.map +1 -1
- package/dist/fleet/decomposer-deep.d.ts +4 -11
- package/dist/fleet/decomposer-deep.d.ts.map +1 -1
- package/dist/fleet/decomposer-deep.js +5 -5
- package/dist/fleet/decomposer-deep.js.map +1 -1
- package/dist/fleet/index.d.ts +9 -0
- package/dist/fleet/index.d.ts.map +1 -1
- package/dist/fleet/index.js +87 -8
- package/dist/fleet/index.js.map +1 -1
- package/dist/fleet/manifest.d.ts +26 -0
- package/dist/fleet/manifest.d.ts.map +1 -1
- package/dist/fleet/manifest.js +8 -0
- package/dist/fleet/manifest.js.map +1 -1
- package/dist/fleet/reporter.d.ts +4 -1
- package/dist/fleet/reporter.d.ts.map +1 -1
- package/dist/fleet/reporter.js +2 -1
- package/dist/fleet/reporter.js.map +1 -1
- package/dist/fleet/scaffolder.d.ts +5 -1
- package/dist/fleet/scaffolder.d.ts.map +1 -1
- package/dist/fleet/scaffolder.js +11 -2
- package/dist/fleet/scaffolder.js.map +1 -1
- package/dist/graph/client.d.ts.map +1 -1
- package/dist/graph/client.js +115 -23
- package/dist/graph/client.js.map +1 -1
- package/dist/graph/mcp-client.d.ts +1 -0
- package/dist/graph/mcp-client.d.ts.map +1 -1
- package/dist/graph/mcp-client.js +58 -7
- package/dist/graph/mcp-client.js.map +1 -1
- package/dist/hub/collector.d.ts +12 -0
- package/dist/hub/collector.d.ts.map +1 -0
- package/dist/hub/collector.js +36 -0
- package/dist/hub/collector.js.map +1 -0
- package/dist/hub/finding-source.d.ts +22 -0
- package/dist/hub/finding-source.d.ts.map +1 -0
- package/dist/hub/finding-source.js +41 -0
- package/dist/hub/finding-source.js.map +1 -0
- package/dist/hub/finding-store.d.ts +68 -0
- package/dist/hub/finding-store.d.ts.map +1 -0
- package/dist/hub/finding-store.js +122 -0
- package/dist/hub/finding-store.js.map +1 -0
- package/dist/hub/finding.d.ts +54 -0
- package/dist/hub/finding.d.ts.map +1 -0
- package/dist/hub/finding.js +24 -0
- package/dist/hub/finding.js.map +1 -0
- package/dist/hub/gmail-to-task.d.ts +69 -0
- package/dist/hub/gmail-to-task.d.ts.map +1 -0
- package/dist/hub/gmail-to-task.js +102 -0
- package/dist/hub/gmail-to-task.js.map +1 -0
- package/dist/hub/hub-config.d.ts +18 -0
- package/dist/hub/hub-config.d.ts.map +1 -0
- package/dist/hub/hub-config.js +40 -0
- package/dist/hub/hub-config.js.map +1 -0
- package/dist/hub/judge.d.ts +30 -0
- package/dist/hub/judge.d.ts.map +1 -0
- package/dist/hub/judge.js +177 -0
- package/dist/hub/judge.js.map +1 -0
- package/dist/hub/lenses.d.ts +60 -0
- package/dist/hub/lenses.d.ts.map +1 -0
- package/dist/hub/lenses.js +123 -0
- package/dist/hub/lenses.js.map +1 -0
- package/dist/hub/priority-md.d.ts +21 -0
- package/dist/hub/priority-md.d.ts.map +1 -0
- package/dist/hub/priority-md.js +64 -0
- package/dist/hub/priority-md.js.map +1 -0
- package/dist/hub/repo-resolver.d.ts +11 -0
- package/dist/hub/repo-resolver.d.ts.map +1 -0
- package/dist/hub/repo-resolver.js +39 -0
- package/dist/hub/repo-resolver.js.map +1 -0
- package/dist/hub/scope.d.ts +39 -0
- package/dist/hub/scope.d.ts.map +1 -0
- package/dist/hub/scope.js +62 -0
- package/dist/hub/scope.js.map +1 -0
- package/dist/hub/task-inbox.d.ts +16 -0
- package/dist/hub/task-inbox.d.ts.map +1 -0
- package/dist/hub/task-inbox.js +39 -0
- package/dist/hub/task-inbox.js.map +1 -0
- package/dist/incident/resolution-verify.d.ts +2 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/medical/adapters/apple-health.js +1 -1
- package/dist/medical/adapters/apple-health.js.map +1 -1
- package/dist/medical/analysis/cadence.d.ts +32 -0
- package/dist/medical/analysis/cadence.d.ts.map +1 -0
- package/dist/medical/analysis/cadence.js +72 -0
- package/dist/medical/analysis/cadence.js.map +1 -0
- package/dist/medical/analysis/cross-marker.d.ts +33 -0
- package/dist/medical/analysis/cross-marker.d.ts.map +1 -0
- package/dist/medical/analysis/cross-marker.js +79 -0
- package/dist/medical/analysis/cross-marker.js.map +1 -0
- package/dist/medical/analysis/finding-writer.d.ts +26 -0
- package/dist/medical/analysis/finding-writer.d.ts.map +1 -0
- package/dist/medical/analysis/finding-writer.js +60 -0
- package/dist/medical/analysis/finding-writer.js.map +1 -0
- package/dist/medical/analysis/finding.d.ts +63 -0
- package/dist/medical/analysis/finding.d.ts.map +1 -0
- package/dist/medical/analysis/finding.js +70 -0
- package/dist/medical/analysis/finding.js.map +1 -0
- package/dist/medical/analysis/review-pass.d.ts +76 -0
- package/dist/medical/analysis/review-pass.d.ts.map +1 -0
- package/dist/medical/analysis/review-pass.js +119 -0
- package/dist/medical/analysis/review-pass.js.map +1 -0
- package/dist/medical/analysis/trends.d.ts +36 -0
- package/dist/medical/analysis/trends.d.ts.map +1 -0
- package/dist/medical/analysis/trends.js +157 -0
- package/dist/medical/analysis/trends.js.map +1 -0
- package/dist/medical/health-store.d.ts +5 -0
- package/dist/medical/health-store.d.ts.map +1 -1
- package/dist/medical/health-store.js +10 -0
- package/dist/medical/health-store.js.map +1 -1
- package/dist/medical/lab-note.d.ts +72 -0
- package/dist/medical/lab-note.d.ts.map +1 -0
- package/dist/medical/lab-note.js +161 -0
- package/dist/medical/lab-note.js.map +1 -0
- package/dist/medical/lab-pdf-parser.d.ts +19 -0
- package/dist/medical/lab-pdf-parser.d.ts.map +1 -0
- package/dist/medical/lab-pdf-parser.js +57 -0
- package/dist/medical/lab-pdf-parser.js.map +1 -0
- package/dist/medical/lab-reindex.d.ts +24 -0
- package/dist/medical/lab-reindex.d.ts.map +1 -0
- package/dist/medical/lab-reindex.js +45 -0
- package/dist/medical/lab-reindex.js.map +1 -0
- package/dist/medical/lab-types.d.ts +75 -0
- package/dist/medical/lab-types.d.ts.map +1 -0
- package/dist/medical/lab-types.js +17 -0
- package/dist/medical/lab-types.js.map +1 -0
- package/dist/medical/profile.d.ts +96 -0
- package/dist/medical/profile.d.ts.map +1 -0
- package/dist/medical/profile.js +273 -0
- package/dist/medical/profile.js.map +1 -0
- package/dist/medical/recommend/context.d.ts +48 -0
- package/dist/medical/recommend/context.d.ts.map +1 -0
- package/dist/medical/recommend/context.js +109 -0
- package/dist/medical/recommend/context.js.map +1 -0
- package/dist/medical/recommend/judge-panel.d.ts +49 -0
- package/dist/medical/recommend/judge-panel.d.ts.map +1 -0
- package/dist/medical/recommend/judge-panel.js +164 -0
- package/dist/medical/recommend/judge-panel.js.map +1 -0
- package/dist/medical/recommend/lenses.d.ts +72 -0
- package/dist/medical/recommend/lenses.d.ts.map +1 -0
- package/dist/medical/recommend/lenses.js +220 -0
- package/dist/medical/recommend/lenses.js.map +1 -0
- package/dist/medical/recommend/recommend.d.ts +86 -0
- package/dist/medical/recommend/recommend.d.ts.map +1 -0
- package/dist/medical/recommend/recommend.js +211 -0
- package/dist/medical/recommend/recommend.js.map +1 -0
- package/dist/medical/recommend/types.d.ts +98 -0
- package/dist/medical/recommend/types.d.ts.map +1 -0
- package/dist/medical/recommend/types.js +20 -0
- package/dist/medical/recommend/types.js.map +1 -0
- package/dist/medical/recommend/urgency.d.ts +26 -0
- package/dist/medical/recommend/urgency.d.ts.map +1 -0
- package/dist/medical/recommend/urgency.js +124 -0
- package/dist/medical/recommend/urgency.js.map +1 -0
- package/dist/medical/research/online-research.d.ts +65 -0
- package/dist/medical/research/online-research.d.ts.map +1 -0
- package/dist/medical/research/online-research.js +101 -0
- package/dist/medical/research/online-research.js.map +1 -0
- package/dist/medical/research/research-note.d.ts +32 -0
- package/dist/medical/research/research-note.d.ts.map +1 -0
- package/dist/medical/research/research-note.js +55 -0
- package/dist/medical/research/research-note.js.map +1 -0
- package/dist/medical/supplements.d.ts +82 -0
- package/dist/medical/supplements.d.ts.map +1 -0
- package/dist/medical/supplements.js +173 -0
- package/dist/medical/supplements.js.map +1 -0
- package/dist/orchestrator/agentic-loop.d.ts +160 -1
- package/dist/orchestrator/agentic-loop.d.ts.map +1 -1
- package/dist/orchestrator/agentic-loop.js +350 -41
- package/dist/orchestrator/agentic-loop.js.map +1 -1
- package/dist/orchestrator/compaction.d.ts +47 -0
- package/dist/orchestrator/compaction.d.ts.map +1 -0
- package/dist/orchestrator/compaction.js +75 -0
- package/dist/orchestrator/compaction.js.map +1 -0
- package/dist/orchestrator/generator-agent.d.ts +19 -0
- package/dist/orchestrator/generator-agent.d.ts.map +1 -1
- package/dist/orchestrator/generator-agent.js +27 -1
- package/dist/orchestrator/generator-agent.js.map +1 -1
- package/dist/orchestrator/loop-events.d.ts +98 -0
- package/dist/orchestrator/loop-events.d.ts.map +1 -0
- package/dist/orchestrator/loop-events.js +2 -0
- package/dist/orchestrator/loop-events.js.map +1 -0
- package/dist/orchestrator/model-resolver.d.ts.map +1 -1
- package/dist/orchestrator/model-resolver.js +10 -6
- package/dist/orchestrator/model-resolver.js.map +1 -1
- package/dist/orchestrator/pipeline.d.ts +10 -1
- package/dist/orchestrator/pipeline.d.ts.map +1 -1
- package/dist/orchestrator/pipeline.js +102 -4
- package/dist/orchestrator/pipeline.js.map +1 -1
- package/dist/orchestrator/security-audit-types.d.ts +53 -0
- package/dist/orchestrator/security-audit-types.d.ts.map +1 -0
- package/dist/orchestrator/security-audit-types.js +10 -0
- package/dist/orchestrator/security-audit-types.js.map +1 -0
- package/dist/orchestrator/security-auditor-agent.d.ts +68 -0
- package/dist/orchestrator/security-auditor-agent.d.ts.map +1 -0
- package/dist/orchestrator/security-auditor-agent.js +482 -0
- package/dist/orchestrator/security-auditor-agent.js.map +1 -0
- package/dist/orchestrator/security-gate.d.ts +73 -0
- package/dist/orchestrator/security-gate.d.ts.map +1 -0
- package/dist/orchestrator/security-gate.js +174 -0
- package/dist/orchestrator/security-gate.js.map +1 -0
- package/dist/orchestrator/security-hub.d.ts +45 -0
- package/dist/orchestrator/security-hub.d.ts.map +1 -0
- package/dist/orchestrator/security-hub.js +147 -0
- package/dist/orchestrator/security-hub.js.map +1 -0
- package/dist/orchestrator/security-knowledge/benchmark/harness.d.ts +43 -0
- package/dist/orchestrator/security-knowledge/benchmark/harness.d.ts.map +1 -0
- package/dist/orchestrator/security-knowledge/benchmark/harness.js +13 -0
- package/dist/orchestrator/security-knowledge/benchmark/harness.js.map +1 -0
- package/dist/orchestrator/security-knowledge/diff-provider.d.ts +79 -0
- package/dist/orchestrator/security-knowledge/diff-provider.d.ts.map +1 -0
- package/dist/orchestrator/security-knowledge/diff-provider.js +320 -0
- package/dist/orchestrator/security-knowledge/diff-provider.js.map +1 -0
- package/dist/orchestrator/security-knowledge/index.d.ts +22 -0
- package/dist/orchestrator/security-knowledge/index.d.ts.map +1 -0
- package/dist/orchestrator/security-knowledge/index.js +66 -0
- package/dist/orchestrator/security-knowledge/index.js.map +1 -0
- package/dist/orchestrator/security-knowledge/parser.d.ts +9 -0
- package/dist/orchestrator/security-knowledge/parser.d.ts.map +1 -0
- package/dist/orchestrator/security-knowledge/parser.js +137 -0
- package/dist/orchestrator/security-knowledge/parser.js.map +1 -0
- package/dist/orchestrator/security-knowledge/registry.d.ts +25 -0
- package/dist/orchestrator/security-knowledge/registry.d.ts.map +1 -0
- package/dist/orchestrator/security-knowledge/registry.js +114 -0
- package/dist/orchestrator/security-knowledge/registry.js.map +1 -0
- package/dist/orchestrator/security-knowledge/resolver.d.ts +48 -0
- package/dist/orchestrator/security-knowledge/resolver.d.ts.map +1 -0
- package/dist/orchestrator/security-knowledge/resolver.js +63 -0
- package/dist/orchestrator/security-knowledge/resolver.js.map +1 -0
- package/dist/orchestrator/security-knowledge/selector.d.ts +18 -0
- package/dist/orchestrator/security-knowledge/selector.d.ts.map +1 -0
- package/dist/orchestrator/security-knowledge/selector.js +46 -0
- package/dist/orchestrator/security-knowledge/selector.js.map +1 -0
- package/dist/orchestrator/security-knowledge/signature.d.ts +37 -0
- package/dist/orchestrator/security-knowledge/signature.d.ts.map +1 -0
- package/dist/orchestrator/security-knowledge/signature.js +2 -0
- package/dist/orchestrator/security-knowledge/signature.js.map +1 -0
- package/dist/orchestrator/security-knowledge/supply-chain-inspector.d.ts +29 -0
- package/dist/orchestrator/security-knowledge/supply-chain-inspector.d.ts.map +1 -0
- package/dist/orchestrator/security-knowledge/supply-chain-inspector.js +211 -0
- package/dist/orchestrator/security-knowledge/supply-chain-inspector.js.map +1 -0
- package/dist/orchestrator/security-scanners.d.ts +126 -0
- package/dist/orchestrator/security-scanners.d.ts.map +1 -0
- package/dist/orchestrator/security-scanners.js +501 -0
- package/dist/orchestrator/security-scanners.js.map +1 -0
- package/dist/orchestrator/security-verifier-agent.d.ts +62 -0
- package/dist/orchestrator/security-verifier-agent.d.ts.map +1 -0
- package/dist/orchestrator/security-verifier-agent.js +230 -0
- package/dist/orchestrator/security-verifier-agent.js.map +1 -0
- package/dist/orchestrator/session-store.d.ts +95 -0
- package/dist/orchestrator/session-store.d.ts.map +1 -0
- package/dist/orchestrator/session-store.js +186 -0
- package/dist/orchestrator/session-store.js.map +1 -0
- package/dist/orchestrator/stack-knowledge.d.ts +17 -0
- package/dist/orchestrator/stack-knowledge.d.ts.map +1 -0
- package/dist/orchestrator/stack-knowledge.js +35 -0
- package/dist/orchestrator/stack-knowledge.js.map +1 -0
- package/dist/orchestrator/subagents.d.ts +62 -0
- package/dist/orchestrator/subagents.d.ts.map +1 -0
- package/dist/orchestrator/subagents.js +143 -0
- package/dist/orchestrator/subagents.js.map +1 -0
- package/dist/orchestrator/tools/executor.d.ts +68 -0
- package/dist/orchestrator/tools/executor.d.ts.map +1 -0
- package/dist/orchestrator/tools/executor.js +104 -0
- package/dist/orchestrator/tools/executor.js.map +1 -0
- package/dist/orchestrator/tools/mcp-bridge.d.ts +76 -0
- package/dist/orchestrator/tools/mcp-bridge.d.ts.map +1 -0
- package/dist/orchestrator/tools/mcp-bridge.js +154 -0
- package/dist/orchestrator/tools/mcp-bridge.js.map +1 -0
- package/dist/orchestrator/tools/schemas.d.ts.map +1 -1
- package/dist/orchestrator/tools/schemas.js +3 -0
- package/dist/orchestrator/tools/schemas.js.map +1 -1
- package/dist/orchestrator/workflow/budget.d.ts +24 -2
- package/dist/orchestrator/workflow/budget.d.ts.map +1 -1
- package/dist/orchestrator/workflow/budget.js +39 -1
- package/dist/orchestrator/workflow/budget.js.map +1 -1
- package/dist/orchestrator/workflow/engine.d.ts +1 -1
- package/dist/orchestrator/workflow/engine.d.ts.map +1 -1
- package/dist/orchestrator/workflow/selector.d.ts.map +1 -1
- package/dist/orchestrator/workflow/selector.js +10 -0
- package/dist/orchestrator/workflow/selector.js.map +1 -1
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +116 -26
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/claude-code.d.ts.map +1 -1
- package/dist/providers/claude-code.js +17 -0
- package/dist/providers/claude-code.js.map +1 -1
- package/dist/providers/cost-meter.d.ts +52 -0
- package/dist/providers/cost-meter.d.ts.map +1 -0
- package/dist/providers/cost-meter.js +81 -0
- package/dist/providers/cost-meter.js.map +1 -0
- package/dist/providers/factory.d.ts +6 -1
- package/dist/providers/factory.d.ts.map +1 -1
- package/dist/providers/factory.js +24 -5
- package/dist/providers/factory.js.map +1 -1
- package/dist/providers/google.d.ts.map +1 -1
- package/dist/providers/google.js +29 -0
- package/dist/providers/google.js.map +1 -1
- package/dist/providers/grounded-search.d.ts +128 -0
- package/dist/providers/grounded-search.d.ts.map +1 -0
- package/dist/providers/grounded-search.js +160 -0
- package/dist/providers/grounded-search.js.map +1 -0
- package/dist/providers/openai-compat.d.ts +15 -1
- package/dist/providers/openai-compat.d.ts.map +1 -1
- package/dist/providers/openai-compat.js +24 -0
- package/dist/providers/openai-compat.js.map +1 -1
- package/dist/providers/openai.d.ts +7 -0
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +95 -4
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/types.d.ts +88 -0
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/research/cadence.d.ts +33 -0
- package/dist/research/cadence.d.ts.map +1 -0
- package/dist/research/cadence.js +55 -0
- package/dist/research/cadence.js.map +1 -0
- package/dist/research/digest.d.ts +80 -0
- package/dist/research/digest.d.ts.map +1 -0
- package/dist/research/digest.js +119 -0
- package/dist/research/digest.js.map +1 -0
- package/dist/research/egress.d.ts +28 -0
- package/dist/research/egress.d.ts.map +1 -0
- package/dist/research/egress.js +41 -0
- package/dist/research/egress.js.map +1 -0
- package/dist/research/job-store.d.ts +30 -0
- package/dist/research/job-store.d.ts.map +1 -0
- package/dist/research/job-store.js +100 -0
- package/dist/research/job-store.js.map +1 -0
- package/dist/research/model-diversity.d.ts +27 -0
- package/dist/research/model-diversity.d.ts.map +1 -0
- package/dist/research/model-diversity.js +52 -0
- package/dist/research/model-diversity.js.map +1 -0
- package/dist/research/note-writer.d.ts +36 -0
- package/dist/research/note-writer.d.ts.map +1 -0
- package/dist/research/note-writer.js +53 -0
- package/dist/research/note-writer.js.map +1 -0
- package/dist/research/online-retrieval.d.ts +27 -0
- package/dist/research/online-retrieval.d.ts.map +1 -0
- package/dist/research/online-retrieval.js +22 -0
- package/dist/research/online-retrieval.js.map +1 -0
- package/dist/research/runner.d.ts +80 -0
- package/dist/research/runner.d.ts.map +1 -0
- package/dist/research/runner.js +115 -0
- package/dist/research/runner.js.map +1 -0
- package/dist/research/scheduler.d.ts +61 -0
- package/dist/research/scheduler.d.ts.map +1 -0
- package/dist/research/scheduler.js +58 -0
- package/dist/research/scheduler.js.map +1 -0
- package/dist/research/types.d.ts +81 -0
- package/dist/research/types.d.ts.map +1 -0
- package/dist/research/types.js +57 -0
- package/dist/research/types.js.map +1 -0
- package/dist/seo/adapters/http.d.ts +43 -0
- package/dist/seo/adapters/http.d.ts.map +1 -0
- package/dist/seo/adapters/http.js +35 -0
- package/dist/seo/adapters/http.js.map +1 -0
- package/dist/seo/ai-visibility-provider.d.ts +171 -0
- package/dist/seo/ai-visibility-provider.d.ts.map +1 -0
- package/dist/seo/ai-visibility-provider.js +165 -0
- package/dist/seo/ai-visibility-provider.js.map +1 -0
- package/dist/seo/ai-visibility-scorer.d.ts +43 -0
- package/dist/seo/ai-visibility-scorer.d.ts.map +1 -0
- package/dist/seo/ai-visibility-scorer.js +102 -0
- package/dist/seo/ai-visibility-scorer.js.map +1 -0
- package/dist/seo/analyzer.d.ts +58 -0
- package/dist/seo/analyzer.d.ts.map +1 -0
- package/dist/seo/analyzer.js +265 -0
- package/dist/seo/analyzer.js.map +1 -0
- package/dist/seo/benchmark/harness.d.ts +56 -0
- package/dist/seo/benchmark/harness.d.ts.map +1 -0
- package/dist/seo/benchmark/harness.js +172 -0
- package/dist/seo/benchmark/harness.js.map +1 -0
- package/dist/seo/builder/approved-finding.d.ts +115 -0
- package/dist/seo/builder/approved-finding.d.ts.map +1 -0
- package/dist/seo/builder/approved-finding.js +145 -0
- package/dist/seo/builder/approved-finding.js.map +1 -0
- package/dist/seo/builder/build-runner.d.ts +41 -0
- package/dist/seo/builder/build-runner.d.ts.map +1 -0
- package/dist/seo/builder/build-runner.js +156 -0
- package/dist/seo/builder/build-runner.js.map +1 -0
- package/dist/seo/builder/draft-generators.d.ts +32 -0
- package/dist/seo/builder/draft-generators.d.ts.map +1 -0
- package/dist/seo/builder/draft-generators.js +31 -0
- package/dist/seo/builder/draft-generators.js.map +1 -0
- package/dist/seo/builder/draft-store.d.ts +30 -0
- package/dist/seo/builder/draft-store.d.ts.map +1 -0
- package/dist/seo/builder/draft-store.js +76 -0
- package/dist/seo/builder/draft-store.js.map +1 -0
- package/dist/seo/builder/draft-types.d.ts +36 -0
- package/dist/seo/builder/draft-types.d.ts.map +1 -0
- package/dist/seo/builder/draft-types.js +14 -0
- package/dist/seo/builder/draft-types.js.map +1 -0
- package/dist/seo/builder/hub-approved-source.d.ts +11 -0
- package/dist/seo/builder/hub-approved-source.d.ts.map +1 -0
- package/dist/seo/builder/hub-approved-source.js +48 -0
- package/dist/seo/builder/hub-approved-source.js.map +1 -0
- package/dist/seo/builder/seo-builder.d.ts +72 -0
- package/dist/seo/builder/seo-builder.d.ts.map +1 -0
- package/dist/seo/builder/seo-builder.js +72 -0
- package/dist/seo/builder/seo-builder.js.map +1 -0
- package/dist/seo/citation-gate.d.ts +36 -0
- package/dist/seo/citation-gate.d.ts.map +1 -0
- package/dist/seo/citation-gate.js +59 -0
- package/dist/seo/citation-gate.js.map +1 -0
- package/dist/seo/command.d.ts +11 -0
- package/dist/seo/command.d.ts.map +1 -0
- package/dist/seo/command.js +90 -0
- package/dist/seo/command.js.map +1 -0
- package/dist/seo/content-sanitizer.d.ts +56 -0
- package/dist/seo/content-sanitizer.d.ts.map +1 -0
- package/dist/seo/content-sanitizer.js +55 -0
- package/dist/seo/content-sanitizer.js.map +1 -0
- package/dist/seo/crawl-engine.d.ts +35 -0
- package/dist/seo/crawl-engine.d.ts.map +1 -0
- package/dist/seo/crawl-engine.js +2 -0
- package/dist/seo/crawl-engine.js.map +1 -0
- package/dist/seo/data-source.d.ts +156 -0
- package/dist/seo/data-source.d.ts.map +1 -0
- package/dist/seo/data-source.js +2 -0
- package/dist/seo/data-source.js.map +1 -0
- package/dist/seo/egress.d.ts +39 -0
- package/dist/seo/egress.d.ts.map +1 -0
- package/dist/seo/egress.js +64 -0
- package/dist/seo/egress.js.map +1 -0
- package/dist/seo/hub-emitter.d.ts +28 -0
- package/dist/seo/hub-emitter.d.ts.map +1 -0
- package/dist/seo/hub-emitter.js +95 -0
- package/dist/seo/hub-emitter.js.map +1 -0
- package/dist/seo/index.d.ts +42 -0
- package/dist/seo/index.d.ts.map +1 -0
- package/dist/seo/index.js +19 -0
- package/dist/seo/index.js.map +1 -0
- package/dist/seo/never-encode-filter.d.ts +45 -0
- package/dist/seo/never-encode-filter.d.ts.map +1 -0
- package/dist/seo/never-encode-filter.js +51 -0
- package/dist/seo/never-encode-filter.js.map +1 -0
- package/dist/seo/parser.d.ts +46 -0
- package/dist/seo/parser.d.ts.map +1 -0
- package/dist/seo/parser.js +113 -0
- package/dist/seo/parser.js.map +1 -0
- package/dist/seo/playbook-index.d.ts +19 -0
- package/dist/seo/playbook-index.d.ts.map +1 -0
- package/dist/seo/playbook-index.js +74 -0
- package/dist/seo/playbook-index.js.map +1 -0
- package/dist/seo/quota-governor.d.ts +100 -0
- package/dist/seo/quota-governor.d.ts.map +1 -0
- package/dist/seo/quota-governor.js +199 -0
- package/dist/seo/quota-governor.js.map +1 -0
- package/dist/seo/quota-ledger.d.ts +50 -0
- package/dist/seo/quota-ledger.d.ts.map +1 -0
- package/dist/seo/quota-ledger.js +95 -0
- package/dist/seo/quota-ledger.js.map +1 -0
- package/dist/seo/report-store.d.ts +30 -0
- package/dist/seo/report-store.d.ts.map +1 -0
- package/dist/seo/report-store.js +94 -0
- package/dist/seo/report-store.js.map +1 -0
- package/dist/seo/retriever.d.ts +34 -0
- package/dist/seo/retriever.d.ts.map +1 -0
- package/dist/seo/retriever.js +95 -0
- package/dist/seo/retriever.js.map +1 -0
- package/dist/seo/runner.d.ts +108 -0
- package/dist/seo/runner.d.ts.map +1 -0
- package/dist/seo/runner.js +512 -0
- package/dist/seo/runner.js.map +1 -0
- package/dist/seo/scrape-throttle.d.ts +84 -0
- package/dist/seo/scrape-throttle.d.ts.map +1 -0
- package/dist/seo/scrape-throttle.js +149 -0
- package/dist/seo/scrape-throttle.js.map +1 -0
- package/dist/seo/serp-provider.d.ts +52 -0
- package/dist/seo/serp-provider.d.ts.map +1 -0
- package/dist/seo/serp-provider.js +17 -0
- package/dist/seo/serp-provider.js.map +1 -0
- package/dist/seo/sources/ai-visibility-adapter.d.ts +87 -0
- package/dist/seo/sources/ai-visibility-adapter.d.ts.map +1 -0
- package/dist/seo/sources/ai-visibility-adapter.js +85 -0
- package/dist/seo/sources/ai-visibility-adapter.js.map +1 -0
- package/dist/seo/sources/api-spine-provider.d.ts +66 -0
- package/dist/seo/sources/api-spine-provider.d.ts.map +1 -0
- package/dist/seo/sources/api-spine-provider.js +68 -0
- package/dist/seo/sources/api-spine-provider.js.map +1 -0
- package/dist/seo/sources/citation-verifier.d.ts +95 -0
- package/dist/seo/sources/citation-verifier.d.ts.map +1 -0
- package/dist/seo/sources/citation-verifier.js +106 -0
- package/dist/seo/sources/citation-verifier.js.map +1 -0
- package/dist/seo/sources/crawl-source.d.ts +62 -0
- package/dist/seo/sources/crawl-source.d.ts.map +1 -0
- package/dist/seo/sources/crawl-source.js +87 -0
- package/dist/seo/sources/crawl-source.js.map +1 -0
- package/dist/seo/sources/damcrawler-crawl-engine.d.ts +151 -0
- package/dist/seo/sources/damcrawler-crawl-engine.d.ts.map +1 -0
- package/dist/seo/sources/damcrawler-crawl-engine.js +154 -0
- package/dist/seo/sources/damcrawler-crawl-engine.js.map +1 -0
- package/dist/seo/sources/damcrawler-serp-provider.d.ts +75 -0
- package/dist/seo/sources/damcrawler-serp-provider.d.ts.map +1 -0
- package/dist/seo/sources/damcrawler-serp-provider.js +60 -0
- package/dist/seo/sources/damcrawler-serp-provider.js.map +1 -0
- package/dist/seo/sources/dataforseo-adapter.d.ts +46 -0
- package/dist/seo/sources/dataforseo-adapter.d.ts.map +1 -0
- package/dist/seo/sources/dataforseo-adapter.js +335 -0
- package/dist/seo/sources/dataforseo-adapter.js.map +1 -0
- package/dist/seo/sources/dataforseo-serp-provider.d.ts +30 -0
- package/dist/seo/sources/dataforseo-serp-provider.d.ts.map +1 -0
- package/dist/seo/sources/dataforseo-serp-provider.js +20 -0
- package/dist/seo/sources/dataforseo-serp-provider.js.map +1 -0
- package/dist/seo/sources/engine-scrape-parser-chatgpt.d.ts +62 -0
- package/dist/seo/sources/engine-scrape-parser-chatgpt.d.ts.map +1 -0
- package/dist/seo/sources/engine-scrape-parser-chatgpt.js +72 -0
- package/dist/seo/sources/engine-scrape-parser-chatgpt.js.map +1 -0
- package/dist/seo/sources/engine-scrape-parser-perplexity.d.ts +10 -0
- package/dist/seo/sources/engine-scrape-parser-perplexity.d.ts.map +1 -0
- package/dist/seo/sources/engine-scrape-parser-perplexity.js +72 -0
- package/dist/seo/sources/engine-scrape-parser-perplexity.js.map +1 -0
- package/dist/seo/sources/gsc-adapter.d.ts +64 -0
- package/dist/seo/sources/gsc-adapter.d.ts.map +1 -0
- package/dist/seo/sources/gsc-adapter.js +221 -0
- package/dist/seo/sources/gsc-adapter.js.map +1 -0
- package/dist/seo/sources/local-export.d.ts +53 -0
- package/dist/seo/sources/local-export.d.ts.map +1 -0
- package/dist/seo/sources/local-export.js +307 -0
- package/dist/seo/sources/local-export.js.map +1 -0
- package/dist/seo/sources/mention-citation-extractor.d.ts +136 -0
- package/dist/seo/sources/mention-citation-extractor.d.ts.map +1 -0
- package/dist/seo/sources/mention-citation-extractor.js +272 -0
- package/dist/seo/sources/mention-citation-extractor.js.map +1 -0
- package/dist/seo/sources/scrape-arm-provider.d.ts +109 -0
- package/dist/seo/sources/scrape-arm-provider.d.ts.map +1 -0
- package/dist/seo/sources/scrape-arm-provider.js +129 -0
- package/dist/seo/sources/scrape-arm-provider.js.map +1 -0
- package/dist/seo/tracked-prompt-store.d.ts +33 -0
- package/dist/seo/tracked-prompt-store.d.ts.map +1 -0
- package/dist/seo/tracked-prompt-store.js +68 -0
- package/dist/seo/tracked-prompt-store.js.map +1 -0
- package/dist/seo/types.d.ts +128 -0
- package/dist/seo/types.d.ts.map +1 -0
- package/dist/seo/types.js +14 -0
- package/dist/seo/types.js.map +1 -0
- package/dist/seo/verifier.d.ts +34 -0
- package/dist/seo/verifier.d.ts.map +1 -0
- package/dist/seo/verifier.js +204 -0
- package/dist/seo/verifier.js.map +1 -0
- package/dist/seo/workflow-capabilities.d.ts +26 -0
- package/dist/seo/workflow-capabilities.d.ts.map +1 -0
- package/dist/seo/workflow-capabilities.js +12 -0
- package/dist/seo/workflow-capabilities.js.map +1 -0
- package/dist/state/facts.d.ts +5 -1
- package/dist/state/facts.d.ts.map +1 -1
- package/dist/state/facts.js +29 -19
- package/dist/state/facts.js.map +1 -1
- package/dist/state/index.d.ts +1 -1
- package/dist/state/index.d.ts.map +1 -1
- package/dist/state/index.js +1 -1
- package/dist/state/index.js.map +1 -1
- package/dist/state/outline-state.d.ts +0 -12
- package/dist/state/outline-state.d.ts.map +1 -1
- package/dist/state/outline-state.js +1 -18
- package/dist/state/outline-state.js.map +1 -1
- package/dist/state/security-audit-state.d.ts +20 -0
- package/dist/state/security-audit-state.d.ts.map +1 -0
- package/dist/state/security-audit-state.js +59 -0
- package/dist/state/security-audit-state.js.map +1 -0
- package/dist/teams/registry.d.ts.map +1 -1
- package/dist/teams/registry.js +17 -0
- package/dist/teams/registry.js.map +1 -1
- package/dist/telegram/bot.d.ts +137 -0
- package/dist/telegram/bot.d.ts.map +1 -0
- package/dist/telegram/bot.js +323 -0
- package/dist/telegram/bot.js.map +1 -0
- package/dist/telegram/digest.d.ts +19 -0
- package/dist/telegram/digest.d.ts.map +1 -0
- package/dist/telegram/digest.js +23 -0
- package/dist/telegram/digest.js.map +1 -0
- package/dist/telegram/fleet-view.d.ts +38 -0
- package/dist/telegram/fleet-view.d.ts.map +1 -0
- package/dist/telegram/fleet-view.js +98 -0
- package/dist/telegram/fleet-view.js.map +1 -0
- package/dist/telegram/handlers/approvals.d.ts +61 -0
- package/dist/telegram/handlers/approvals.d.ts.map +1 -0
- package/dist/telegram/handlers/approvals.js +122 -0
- package/dist/telegram/handlers/approvals.js.map +1 -0
- package/dist/telegram/handlers/capture.d.ts +43 -0
- package/dist/telegram/handlers/capture.d.ts.map +1 -0
- package/dist/telegram/handlers/capture.js +51 -0
- package/dist/telegram/handlers/capture.js.map +1 -0
- package/dist/telegram/handlers/prioritize.d.ts +50 -0
- package/dist/telegram/handlers/prioritize.d.ts.map +1 -0
- package/dist/telegram/handlers/prioritize.js +99 -0
- package/dist/telegram/handlers/prioritize.js.map +1 -0
- package/dist/telegram/handlers/upload.d.ts +105 -0
- package/dist/telegram/handlers/upload.d.ts.map +1 -0
- package/dist/telegram/handlers/upload.js +149 -0
- package/dist/telegram/handlers/upload.js.map +1 -0
- package/dist/telegram/keyboard.d.ts +48 -0
- package/dist/telegram/keyboard.d.ts.map +1 -0
- package/dist/telegram/keyboard.js +81 -0
- package/dist/telegram/keyboard.js.map +1 -0
- package/dist/telegram/outbound.d.ts +77 -0
- package/dist/telegram/outbound.d.ts.map +1 -0
- package/dist/telegram/outbound.js +45 -0
- package/dist/telegram/outbound.js.map +1 -0
- package/dist/telegram/router.d.ts +46 -0
- package/dist/telegram/router.d.ts.map +1 -0
- package/dist/telegram/router.js +63 -0
- package/dist/telegram/router.js.map +1 -0
- package/dist/telegram/streaming.d.ts +36 -0
- package/dist/telegram/streaming.d.ts.map +1 -0
- package/dist/telegram/streaming.js +55 -0
- package/dist/telegram/streaming.js.map +1 -0
- package/dist/telegram/whitelist.d.ts +20 -0
- package/dist/telegram/whitelist.d.ts.map +1 -0
- package/dist/telegram/whitelist.js +34 -0
- package/dist/telegram/whitelist.js.map +1 -0
- package/dist/utils/git.d.ts +0 -6
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js +0 -19
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/vault/conventions.d.ts +23 -0
- package/dist/vault/conventions.d.ts.map +1 -0
- package/dist/vault/conventions.js +22 -0
- package/dist/vault/conventions.js.map +1 -0
- package/dist/vault/frontmatter.d.ts +47 -0
- package/dist/vault/frontmatter.d.ts.map +1 -0
- package/dist/vault/frontmatter.js +149 -0
- package/dist/vault/frontmatter.js.map +1 -0
- package/dist/vault/index-map.d.ts +35 -0
- package/dist/vault/index-map.d.ts.map +1 -0
- package/dist/vault/index-map.js +67 -0
- package/dist/vault/index-map.js.map +1 -0
- package/dist/vault/mcp-adapter.d.ts +96 -0
- package/dist/vault/mcp-adapter.d.ts.map +1 -0
- package/dist/vault/mcp-adapter.js +176 -0
- package/dist/vault/mcp-adapter.js.map +1 -0
- package/dist/vault/note-io.d.ts +29 -0
- package/dist/vault/note-io.d.ts.map +1 -0
- package/dist/vault/note-io.js +44 -0
- package/dist/vault/note-io.js.map +1 -0
- package/dist/vault/profile.d.ts +35 -0
- package/dist/vault/profile.d.ts.map +1 -0
- package/dist/vault/profile.js +50 -0
- package/dist/vault/profile.js.map +1 -0
- package/dist/vault/reindex.d.ts +55 -0
- package/dist/vault/reindex.d.ts.map +1 -0
- package/dist/vault/reindex.js +69 -0
- package/dist/vault/reindex.js.map +1 -0
- package/dist/vault/types.d.ts +25 -0
- package/dist/vault/types.d.ts.map +1 -0
- package/dist/vault/types.js +9 -0
- package/dist/vault/types.js.map +1 -0
- package/package.json +20 -4
- package/scripts/sync-targets.json +2 -1
- package/skills/bober.design/SKILL.md +190 -0
- package/skills/bober.design/references/1-anti-slop.md +102 -0
- package/skills/bober.design/references/2-design-brief.md +84 -0
- package/skills/bober.design/references/3-critique-rubric.md +62 -0
- package/skills/bober.design/references/4-copy-guide.md +43 -0
- package/skills/bober.plan/SKILL.md +15 -1
- package/skills/bober.run/SKILL.md +7 -4
- package/skills/bober.security-anchor/SKILL.md +172 -0
- package/skills/bober.security-audit/SKILL.md +288 -0
- package/skills/bober.security-dex-backend/SKILL.md +306 -0
- package/skills/bober.security-generic/SKILL.md +295 -0
- package/skills/bober.security-igaming/SKILL.md +290 -0
- package/skills/bober.security-node/SKILL.md +267 -0
- package/skills/bober.security-payments/SKILL.md +249 -0
- package/skills/bober.security-react/SKILL.md +194 -0
- package/skills/bober.security-solidity/SKILL.md +306 -0
- package/skills/bober.seo/SKILL.md +132 -0
- package/skills/bober.seo-ai-visibility/SKILL.md +110 -0
- package/skills/bober.seo-content-decay/SKILL.md +99 -0
- package/skills/bober.seo-generic/SKILL.md +173 -0
- package/skills/bober.seo-internal-linking/SKILL.md +87 -0
- package/skills/bober.seo-parasite-watch/SKILL.md +121 -0
- package/skills/bober.seo-rank-track/SKILL.md +98 -0
- package/skills/bober.seo-schema-audit/SKILL.md +97 -0
- package/skills/bober.seo-technical-audit/SKILL.md +113 -0
- package/skills/bober.seo-topical-map/SKILL.md +100 -0
- package/skills/bober.seo-verticals/SKILL.md +133 -0
- package/skills/bober.using-bober/SKILL.md +1 -0
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
import { createClient } from "../providers/factory.js";
|
|
2
|
+
import { FactStore, factsDbPath, ensureFactsDir } from "../state/facts.js";
|
|
3
|
+
import { ingestFinding } from "../hub/finding-store.js";
|
|
4
|
+
import { logger } from "../utils/logger.js";
|
|
5
|
+
import { LiveGroundedSearchClient, PerplexitySonarClient } from "../providers/grounded-search.js";
|
|
6
|
+
import { ScrapeThrottle } from "./scrape-throttle.js";
|
|
7
|
+
import { SeoPlaybookIndex } from "./playbook-index.js";
|
|
8
|
+
import { SeoPlaybookRetriever } from "./retriever.js";
|
|
9
|
+
import { SeoEgressGuard } from "./egress.js";
|
|
10
|
+
import { SeoQuotaGovernor } from "./quota-governor.js";
|
|
11
|
+
import { LocalExportSource } from "./sources/local-export.js";
|
|
12
|
+
import { GscAdapter } from "./sources/gsc-adapter.js";
|
|
13
|
+
import { DataForSeoAdapter } from "./sources/dataforseo-adapter.js";
|
|
14
|
+
import { CrawlSource } from "./sources/crawl-source.js";
|
|
15
|
+
import { DamcrawlerCrawlEngine } from "./sources/damcrawler-crawl-engine.js";
|
|
16
|
+
import { ContentSanitizer } from "./content-sanitizer.js";
|
|
17
|
+
import { resolveSerpProvider } from "./serp-provider.js";
|
|
18
|
+
import { AiVisibilityAdapter } from "./sources/ai-visibility-adapter.js";
|
|
19
|
+
import { resolveAiVisibilityProvider } from "./ai-visibility-provider.js";
|
|
20
|
+
import { DeterministicMentionCitationExtractor } from "./sources/mention-citation-extractor.js";
|
|
21
|
+
import { WORKFLOW_CAPABILITIES } from "./workflow-capabilities.js";
|
|
22
|
+
import { TrackedPromptStore } from "./tracked-prompt-store.js";
|
|
23
|
+
import { SeoAnalyzer } from "./analyzer.js";
|
|
24
|
+
import { SeoCitationGate } from "./citation-gate.js";
|
|
25
|
+
import { NeverEncodeFilter } from "./never-encode-filter.js";
|
|
26
|
+
import { SeoReportStore, deriveReportId } from "./report-store.js";
|
|
27
|
+
import { SeoHubEmitter } from "./hub-emitter.js";
|
|
28
|
+
import { SeoRecommendationVerifier } from "./verifier.js";
|
|
29
|
+
// ── Defaults ─────────────────────────────────────────────────────────
|
|
30
|
+
const DEFAULT_TARGET_FALLBACK = "unspecified-target";
|
|
31
|
+
/**
|
|
32
|
+
* bober: `config.seo` has no `model` field — this is the sole model the
|
|
33
|
+
* runner defaults to for the analyzer's LLM client. Add
|
|
34
|
+
* `config.seo.model` if per-project model choice is ever needed.
|
|
35
|
+
*/
|
|
36
|
+
const DEFAULT_SEO_MODEL = "sonnet";
|
|
37
|
+
function buildDefaultAnalyzer() {
|
|
38
|
+
// createClient is the ONLY place SDKs are imported. BOBER_TEST_DETERMINISTIC=1
|
|
39
|
+
// makes this an inert stub client, but tests should still inject a scripted
|
|
40
|
+
// analyzer (via input.analyzer) so a real network call is never even attempted.
|
|
41
|
+
const client = createClient(undefined, null, undefined, DEFAULT_SEO_MODEL, "seo");
|
|
42
|
+
return new SeoAnalyzer(client, DEFAULT_SEO_MODEL);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* bober: per-engine default model is hardcoded here (not read from config —
|
|
46
|
+
* `config.seo.aiVisibility.engines[]` carries no `model` field this
|
|
47
|
+
* sprint). Promote to a per-engine config field if a project ever
|
|
48
|
+
* needs a different model than these defaults. "perplexity" has no
|
|
49
|
+
* entry: it does NOT go through `createClient`/`LLMClient` at all
|
|
50
|
+
* (Sprint 7) — `PerplexitySonarClient` reads its own model default,
|
|
51
|
+
* so it is intentionally absent from this table, not merely unset.
|
|
52
|
+
*/
|
|
53
|
+
const AI_VISIBILITY_DEFAULT_MODEL = {
|
|
54
|
+
anthropic: DEFAULT_SEO_MODEL,
|
|
55
|
+
openai: "gpt-4.1",
|
|
56
|
+
};
|
|
57
|
+
/** Env var each engine's key is read from — mirrors `factory.ts`'s `validateApiKey`. */
|
|
58
|
+
const AI_VISIBILITY_KEY_ENV = {
|
|
59
|
+
anthropic: "ANTHROPIC_API_KEY",
|
|
60
|
+
openai: "OPENAI_API_KEY",
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Production `AiVisibilityDeps.makeClient` — returns `undefined` (no-key-safe)
|
|
64
|
+
* for any engine lacking its documented env-var key. "perplexity" is handled
|
|
65
|
+
* by an EARLY, separate branch (Sprint 7): Perplexity Sonar is a direct HTTP
|
|
66
|
+
* `chat/completions` API, not an `LLMClient` provider, so it is constructed
|
|
67
|
+
* directly as a `PerplexitySonarClient` and MUST NOT fall through to the
|
|
68
|
+
* generic `createClient` path below (that path has no "perplexity" entry in
|
|
69
|
+
* either table above, so it would otherwise return `undefined` — this branch
|
|
70
|
+
* exists so a Perplexity-keyed engine composes a real arm instead). Only
|
|
71
|
+
* when a key is present does the generic path call `createClient`, so a
|
|
72
|
+
* misconfigured/no-key run never throws the zero-network guard error that
|
|
73
|
+
* `runner.test.ts:34-44` asserts on.
|
|
74
|
+
*/
|
|
75
|
+
function defaultMakeClient(engine) {
|
|
76
|
+
if (engine === "perplexity") {
|
|
77
|
+
// Sonar is BYOK HTTP, not routed through createClient — no-key-safe:
|
|
78
|
+
// absent PERPLEXITY_API_KEY => undefined, arm skipped (sc-7-2).
|
|
79
|
+
if (!process.env["PERPLEXITY_API_KEY"])
|
|
80
|
+
return undefined;
|
|
81
|
+
return new PerplexitySonarClient(); // defaults: env key + global-fetch transport + "sonar"
|
|
82
|
+
}
|
|
83
|
+
const envVar = AI_VISIBILITY_KEY_ENV[engine];
|
|
84
|
+
const model = AI_VISIBILITY_DEFAULT_MODEL[engine];
|
|
85
|
+
if (!envVar || !model || !process.env[envVar])
|
|
86
|
+
return undefined;
|
|
87
|
+
const client = createClient(undefined, null, undefined, model, "ai-visibility");
|
|
88
|
+
return new LiveGroundedSearchClient(engine, client, model);
|
|
89
|
+
}
|
|
90
|
+
// ── selectSource + CapabilitySeoRouter (sc-9-1, sc-9-2, sc-9-3) ─────────
|
|
91
|
+
function quotaLedgerPath(projectRoot) {
|
|
92
|
+
return `${projectRoot}/.bober/seo/quota-ledger.json`;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* The scrape arm's proxy/rate ledger — DISTINCT from `quotaLedgerPath` above
|
|
96
|
+
* (Pitfall 6, sc-11-2): the two ledgers are never cross-reconciled
|
|
97
|
+
* (`scrape-throttle.ts` docstring lines 8-12).
|
|
98
|
+
*/
|
|
99
|
+
function scrapeThrottleLedgerPath(projectRoot) {
|
|
100
|
+
return `${projectRoot}/.bober/seo/scrape-throttle-ledger.json`;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Production `AiVisibilityDeps` — real client builder + the deterministic
|
|
104
|
+
* extractor (Sprint 2), plus (Sprint 11) a real `ScrapeThrottle` and a
|
|
105
|
+
* no-key-safe judge-llm builder, both built ONLY when their config section is
|
|
106
|
+
* present:
|
|
107
|
+
*
|
|
108
|
+
* - `scrapeThrottle` (sc-11-2) is constructed from `config.seo.aiVisibility.scrape`
|
|
109
|
+
* (path under `projectRoot`, caps from config) ONLY when that section is
|
|
110
|
+
* present — absent config leaves `scrapeThrottle` undefined, so
|
|
111
|
+
* `resolveAiVisibilityProvider` never composes a scrape arm (no-config-safe,
|
|
112
|
+
* mirrors `defaultMakeClient`'s no-key-safe idiom). This is what makes the
|
|
113
|
+
* `ai-visibility-scrape` axis + a configured scrape engine LIVE in a real
|
|
114
|
+
* `selectSource` run (Pitfall 1: BOTH `ai-visibility` and
|
|
115
|
+
* `ai-visibility-scrape` must be on for the scrape arm to produce rows,
|
|
116
|
+
* since it is routed through the LOCKED `AiVisibilityAdapter`'s
|
|
117
|
+
* `ai-visibility` gate).
|
|
118
|
+
* - `makeJudgeLlm` (sc-11-3) mirrors `defaultMakeClient`'s guard order
|
|
119
|
+
* (Pattern B): it returns `undefined` BEFORE calling `createClient` when
|
|
120
|
+
* `ANTHROPIC_API_KEY` is absent — no-key-safe. Only built when
|
|
121
|
+
* `config.seo.aiVisibility.judge?.enabled` is true; otherwise `makeJudgeLlm`
|
|
122
|
+
* stays undefined and `resolveAiVisibilityProvider` never constructs a
|
|
123
|
+
* judge (byte-identical-when-disabled, sc-11-3).
|
|
124
|
+
*
|
|
125
|
+
* `scrapeLoad` is intentionally NOT set here — production always uses each
|
|
126
|
+
* `ScrapeArmEngineProvider`'s own real lazy `damcrawler` loader (the class's
|
|
127
|
+
* constructor default); only tests inject a fake.
|
|
128
|
+
*/
|
|
129
|
+
function defaultAiVisibilityDeps(config, projectRoot) {
|
|
130
|
+
const deps = {
|
|
131
|
+
makeClient: defaultMakeClient,
|
|
132
|
+
extractor: new DeterministicMentionCitationExtractor(),
|
|
133
|
+
};
|
|
134
|
+
const scrapeCfg = config.seo?.aiVisibility?.scrape;
|
|
135
|
+
if (scrapeCfg) {
|
|
136
|
+
deps.scrapeThrottle = new ScrapeThrottle(scrapeThrottleLedgerPath(projectRoot), {
|
|
137
|
+
maxPerWindow: scrapeCfg.maxPerWindow,
|
|
138
|
+
windowMs: scrapeCfg.windowMs,
|
|
139
|
+
maxProxyUsd: scrapeCfg.maxProxyUsd,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
const judgeCfg = config.seo?.aiVisibility?.judge;
|
|
143
|
+
if (judgeCfg?.enabled) {
|
|
144
|
+
deps.makeJudgeLlm = () => {
|
|
145
|
+
// Pitfall 3 / Pattern B: return undefined BEFORE createClient when
|
|
146
|
+
// unkeyed — runner.test.ts mocks createClient to THROW, so an eager
|
|
147
|
+
// call here would fail the whole file on a no-key run.
|
|
148
|
+
if (!process.env["ANTHROPIC_API_KEY"])
|
|
149
|
+
return undefined;
|
|
150
|
+
const model = judgeCfg.model ?? DEFAULT_SEO_MODEL;
|
|
151
|
+
const client = createClient(undefined, null, undefined, model, "ai-visibility");
|
|
152
|
+
return { client, model };
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
return deps;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Shared "unrouted" stub — every method resolves `{ kind: "disabled" }`
|
|
159
|
+
* regardless of which capability method is invoked. `CapabilitySeoRouter`
|
|
160
|
+
* dispatches to this for any capability key absent from its `routes` map.
|
|
161
|
+
*/
|
|
162
|
+
const DISABLED_SOURCE = {
|
|
163
|
+
capabilities: () => [],
|
|
164
|
+
searchAnalytics: async () => ({ kind: "disabled" }),
|
|
165
|
+
urlInspection: async () => ({ kind: "disabled" }),
|
|
166
|
+
serp: async () => ({ kind: "disabled" }),
|
|
167
|
+
keywords: async () => ({ kind: "disabled" }),
|
|
168
|
+
backlinks: async () => ({ kind: "disabled" }),
|
|
169
|
+
aiVisibility: async () => ({ kind: "disabled" }),
|
|
170
|
+
linkGraph: async () => ({ kind: "disabled" }),
|
|
171
|
+
};
|
|
172
|
+
/**
|
|
173
|
+
* CapabilitySeoRouter — dispatches each `SeoDataSource` capability method to
|
|
174
|
+
* the ONE source that owns that capability key (spec-20260717-seo-improver-
|
|
175
|
+
* builder, Sprint 9; replaces `CompositeSeoSource`). Assembled by
|
|
176
|
+
* `selectSource` per the ADR-8/ADR-10 route table (sc-9-3). An unrouted
|
|
177
|
+
* capability (absent from `routes`) resolves `{ kind: "disabled" }` via
|
|
178
|
+
* `DISABLED_SOURCE` — the router itself never throws (sc-9-1).
|
|
179
|
+
*/
|
|
180
|
+
class CapabilitySeoRouter {
|
|
181
|
+
routes;
|
|
182
|
+
constructor(routes) {
|
|
183
|
+
this.routes = routes;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* `Object.keys(routes)`, NOT a union of each routed source's OWN
|
|
187
|
+
* `capabilities()` — a routed source may itself advertise capabilities
|
|
188
|
+
* this router does not route to it (sprint briefing §11 Pitfall 8).
|
|
189
|
+
*/
|
|
190
|
+
capabilities() {
|
|
191
|
+
return Object.keys(this.routes);
|
|
192
|
+
}
|
|
193
|
+
searchAnalytics(q) {
|
|
194
|
+
return (this.routes["search-analytics"] ?? DISABLED_SOURCE).searchAnalytics(q);
|
|
195
|
+
}
|
|
196
|
+
urlInspection(q) {
|
|
197
|
+
return (this.routes["url-inspection"] ?? DISABLED_SOURCE).urlInspection(q);
|
|
198
|
+
}
|
|
199
|
+
serp(q) {
|
|
200
|
+
return (this.routes["serp"] ?? DISABLED_SOURCE).serp(q);
|
|
201
|
+
}
|
|
202
|
+
keywords(q) {
|
|
203
|
+
return (this.routes["keywords"] ?? DISABLED_SOURCE).keywords(q);
|
|
204
|
+
}
|
|
205
|
+
backlinks(q) {
|
|
206
|
+
return (this.routes["backlinks"] ?? DISABLED_SOURCE).backlinks(q);
|
|
207
|
+
}
|
|
208
|
+
aiVisibility(q) {
|
|
209
|
+
return (this.routes["ai-visibility"] ?? DISABLED_SOURCE).aiVisibility(q);
|
|
210
|
+
}
|
|
211
|
+
linkGraph(q) {
|
|
212
|
+
return (this.routes["link-graph"] ?? DISABLED_SOURCE).linkGraph(q);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* SerpProviderSource — adapts a `SerpProvider` port's `serp(keyword,
|
|
217
|
+
* location)` (`serp-provider.ts:36-45`) into this file's `SeoDataSource`
|
|
218
|
+
* seam, whose `serp` method takes a single `SerpQuery` (sprint briefing
|
|
219
|
+
* Pattern C). Serves ONLY `serp`; every other capability is
|
|
220
|
+
* `{ kind: "disabled" }` unconditionally. `q.priority` is dropped by this
|
|
221
|
+
* shim — byte-identical, because `DataForSeoAdapter.serp` already defaults
|
|
222
|
+
* an absent `priority` to `"standard"` (`dataforseo-adapter.ts:199`).
|
|
223
|
+
*/
|
|
224
|
+
class SerpProviderSource {
|
|
225
|
+
provider;
|
|
226
|
+
constructor(provider) {
|
|
227
|
+
this.provider = provider;
|
|
228
|
+
}
|
|
229
|
+
capabilities() {
|
|
230
|
+
return ["serp"];
|
|
231
|
+
}
|
|
232
|
+
serp(q) {
|
|
233
|
+
return this.provider.serp(q.keyword, q.location);
|
|
234
|
+
}
|
|
235
|
+
async searchAnalytics(_q) {
|
|
236
|
+
return { kind: "disabled" };
|
|
237
|
+
}
|
|
238
|
+
async urlInspection(_q) {
|
|
239
|
+
return { kind: "disabled" };
|
|
240
|
+
}
|
|
241
|
+
async keywords(_q) {
|
|
242
|
+
return { kind: "disabled" };
|
|
243
|
+
}
|
|
244
|
+
async backlinks(_q) {
|
|
245
|
+
return { kind: "disabled" };
|
|
246
|
+
}
|
|
247
|
+
async aiVisibility(_q) {
|
|
248
|
+
return { kind: "disabled" };
|
|
249
|
+
}
|
|
250
|
+
async linkGraph(_q) {
|
|
251
|
+
return { kind: "disabled" };
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Build the `SeoDataSource` for a run from the FOUR independent egress axes
|
|
256
|
+
* (widened from two, spec-20260717-seo-improver-builder Sprint 9). ALL FOUR
|
|
257
|
+
* axes off (default) -> `LocalExportSource` (zero egress, no credentials
|
|
258
|
+
* touched, no governor/ledger constructed, `import('damcrawler')` never
|
|
259
|
+
* evaluated — sc-9-2). This `return` is the FIRST statement after the
|
|
260
|
+
* predicate, strictly BEFORE `SeoQuotaGovernor.load` (sprint briefing
|
|
261
|
+
* Pattern B / Pitfall 2) — that ordering is what makes the all-off path
|
|
262
|
+
* provably zero-construction.
|
|
263
|
+
*
|
|
264
|
+
* Otherwise, assemble a `CapabilitySeoRouter` per the deterministic
|
|
265
|
+
* ADR-8/ADR-10 route table (sc-9-3):
|
|
266
|
+
* - `url-inspection`: `GscAdapter` when `search-console` is on (GSC always
|
|
267
|
+
* wins, ADR-8); else `CrawlSource` when `site-crawl` is on.
|
|
268
|
+
* - `link-graph`: `CrawlSource` when `site-crawl` is on.
|
|
269
|
+
* - `serp`: the config-selected `SerpProvider` (`resolveSerpProvider`,
|
|
270
|
+
* ADR-10), wrapped in `SerpProviderSource`, whenever `serp-provider` OR
|
|
271
|
+
* `site-crawl` is on (whichever axis the selected provider itself
|
|
272
|
+
* requires; each provider re-asserts its own axis on call).
|
|
273
|
+
* - `keywords`/`backlinks`: `DataForSeoAdapter` when `serp-provider` is on.
|
|
274
|
+
* - `ai-visibility`: `AiVisibilityAdapter` wrapping the composed
|
|
275
|
+
* `resolveAiVisibilityProvider(...)` result when `ai-visibility` is on
|
|
276
|
+
* AND at least one configured engine is keyed (Sprint 3); the offline
|
|
277
|
+
* `LocalExportSource` arm otherwise (no-key-safe fallback).
|
|
278
|
+
*/
|
|
279
|
+
export async function selectSource(config, projectRoot, deps) {
|
|
280
|
+
const egress = SeoEgressGuard.fromConfig(config);
|
|
281
|
+
const searchConsoleAllowed = egress.isAllowed("search-console");
|
|
282
|
+
const serpProviderAllowed = egress.isAllowed("serp-provider");
|
|
283
|
+
const aiVisibilityAllowed = egress.isAllowed("ai-visibility");
|
|
284
|
+
const siteCrawlAllowed = egress.isAllowed("site-crawl");
|
|
285
|
+
if (!searchConsoleAllowed && !serpProviderAllowed && !aiVisibilityAllowed && !siteCrawlAllowed) {
|
|
286
|
+
return new LocalExportSource();
|
|
287
|
+
}
|
|
288
|
+
const governor = await SeoQuotaGovernor.load(quotaLedgerPath(projectRoot), config);
|
|
289
|
+
const routes = {};
|
|
290
|
+
if (searchConsoleAllowed) {
|
|
291
|
+
const gsc = new GscAdapter(egress, governor);
|
|
292
|
+
routes["search-analytics"] = gsc;
|
|
293
|
+
routes["url-inspection"] = gsc; // ADR-8: GSC wins url-inspection when on
|
|
294
|
+
}
|
|
295
|
+
if (siteCrawlAllowed) {
|
|
296
|
+
const crawlSource = new CrawlSource(governor, new DamcrawlerCrawlEngine(egress),
|
|
297
|
+
// bober: identity sanitizer for CrawlSource's OWN (defense-in-depth,
|
|
298
|
+
// sc-7-3) layer only. As of the Sprint 9 fix, `DamcrawlerCrawlEngine`
|
|
299
|
+
// sanitizes EVERY method (crawl/urlVisibility/linkGraph) at the
|
|
300
|
+
// network->in-process boundary via the real `dam.sanitize`
|
|
301
|
+
// (damcrawler-crawl-engine.ts F1) — that is now the genuine, load-
|
|
302
|
+
// bearing sanitization layer for every row this source returns.
|
|
303
|
+
// Leaving this second layer as identity is safe (it is redundant, not
|
|
304
|
+
// sole) — wiring the loaded module's `sanitize` export through here
|
|
305
|
+
// too would require exposing the engine's already-loaded damcrawler
|
|
306
|
+
// module, which `selectSource` cannot reach without duplicating the
|
|
307
|
+
// engine's own guard/load sequence. Follow-up: thread a real
|
|
308
|
+
// `dam.sanitize` here if CrawlSource is ever given its own loader.
|
|
309
|
+
new ContentSanitizer((raw) => ({ content: raw, hadThreats: false })));
|
|
310
|
+
routes["link-graph"] = crawlSource;
|
|
311
|
+
if (!searchConsoleAllowed) {
|
|
312
|
+
routes["url-inspection"] = crawlSource; // ADR-8: fallback only when GSC is off
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
// Built unconditionally on this (not-all-off) branch and reused for
|
|
316
|
+
// keywords/backlinks AND as the resolveSerpProvider dependency — each
|
|
317
|
+
// self-gates its own axis on call, so constructing it here is inert until
|
|
318
|
+
// a routed method is actually invoked (sprint briefing §4).
|
|
319
|
+
const dataForSeo = new DataForSeoAdapter(egress, governor);
|
|
320
|
+
if (serpProviderAllowed) {
|
|
321
|
+
routes["keywords"] = dataForSeo;
|
|
322
|
+
routes["backlinks"] = dataForSeo;
|
|
323
|
+
}
|
|
324
|
+
if (serpProviderAllowed || siteCrawlAllowed) {
|
|
325
|
+
routes["serp"] = new SerpProviderSource(resolveSerpProvider(config, dataForSeo, egress)); // ADR-10
|
|
326
|
+
}
|
|
327
|
+
if (aiVisibilityAllowed) {
|
|
328
|
+
// Sprint 3 (in-house-ai-visibility): compose the in-house API-spine
|
|
329
|
+
// multiplexer via the factory. No-key-safe: when no configured engine
|
|
330
|
+
// is keyed (or `config.seo.aiVisibility` is absent/empty), the factory
|
|
331
|
+
// returns `undefined` and this falls back to the offline
|
|
332
|
+
// `LocalExportSource` arm exactly as before — never a bogus live
|
|
333
|
+
// adapter with zero arms.
|
|
334
|
+
const aiVisibilityProvider = resolveAiVisibilityProvider(config, egress, deps ?? defaultAiVisibilityDeps(config, projectRoot));
|
|
335
|
+
routes["ai-visibility"] = aiVisibilityProvider
|
|
336
|
+
? new AiVisibilityAdapter(egress, governor, aiVisibilityProvider)
|
|
337
|
+
: new LocalExportSource();
|
|
338
|
+
}
|
|
339
|
+
return new CapabilitySeoRouter(routes);
|
|
340
|
+
}
|
|
341
|
+
// ── Data gathering ───────────────────────────────────────────────────
|
|
342
|
+
/**
|
|
343
|
+
* Gathers ONLY the capabilities `WORKFLOW_CAPABILITIES` lists for `workflow`
|
|
344
|
+
* (spec-20260717-seo-improver-builder, Sprint 9; ADR-7) — an omitted
|
|
345
|
+
* capability is never called on `source` at all (not called-then-discarded),
|
|
346
|
+
* so the metered `ai-visibility` capability incurs zero cost/network for a
|
|
347
|
+
* workflow that does not consume it (sc-9-4). An omitted arm resolves
|
|
348
|
+
* `undefined` on `SeoDataBundle`, which the analyzer already renders as "not
|
|
349
|
+
* requested" (`analyzer.ts:127-128`).
|
|
350
|
+
*
|
|
351
|
+
* The `ai-visibility` arm (spec-20260718-in-house-ai-visibility, Sprint 6)
|
|
352
|
+
* loads the committed `TrackedPromptStore` set for `target` INSIDE the
|
|
353
|
+
* `requested.has("ai-visibility")` ternary — never hoisted above
|
|
354
|
+
* `Promise.all` — so a workflow that does not request `ai-visibility` never
|
|
355
|
+
* touches the filesystem for this store (sc-6-4). Only `prompts`/`locale`
|
|
356
|
+
* flow into the LOCKED `AiVisibilityQuery` (`data-source.ts:61`); the file's
|
|
357
|
+
* `engines`/`samplesPerPrompt` are advisory and are NOT forwarded (contract
|
|
358
|
+
* nonGoal — config resolves the real N/engines at provider construction).
|
|
359
|
+
*/
|
|
360
|
+
async function gatherDataBundle(source, workflow, target, now, projectRoot) {
|
|
361
|
+
const day = now.slice(0, 10);
|
|
362
|
+
const requested = new Set(WORKFLOW_CAPABILITIES[workflow]);
|
|
363
|
+
const searchAnalyticsQuery = {
|
|
364
|
+
siteUrl: target,
|
|
365
|
+
startDate: day,
|
|
366
|
+
endDate: day,
|
|
367
|
+
dimensions: ["query", "page"],
|
|
368
|
+
};
|
|
369
|
+
const urlInspectionQuery = { siteUrl: target, inspectionUrl: target };
|
|
370
|
+
const serpQuery = { keyword: target, location: "us" };
|
|
371
|
+
const keywordQuery = { keywords: [target], location: "us" };
|
|
372
|
+
const backlinkQuery = { target };
|
|
373
|
+
const linkGraphQuery = { rootUrl: target };
|
|
374
|
+
const [searchAnalytics, urlInspection, serp, keywords, backlinks, aiVisibility, linkGraph] = await Promise.all([
|
|
375
|
+
requested.has("search-analytics") ? source.searchAnalytics(searchAnalyticsQuery) : undefined,
|
|
376
|
+
requested.has("url-inspection") ? source.urlInspection(urlInspectionQuery) : undefined,
|
|
377
|
+
requested.has("serp") ? source.serp(serpQuery) : undefined,
|
|
378
|
+
requested.has("keywords") ? source.keywords(keywordQuery) : undefined,
|
|
379
|
+
requested.has("backlinks") ? source.backlinks(backlinkQuery) : undefined,
|
|
380
|
+
requested.has("ai-visibility")
|
|
381
|
+
? (async () => {
|
|
382
|
+
const set = await new TrackedPromptStore(projectRoot).load(target);
|
|
383
|
+
const query = { target, prompts: set.prompts };
|
|
384
|
+
if (set.locale !== undefined)
|
|
385
|
+
query.locale = set.locale; // omit key entirely when absent (sc-6-2)
|
|
386
|
+
return source.aiVisibility(query);
|
|
387
|
+
})()
|
|
388
|
+
: undefined,
|
|
389
|
+
requested.has("link-graph") ? source.linkGraph(linkGraphQuery) : undefined,
|
|
390
|
+
]);
|
|
391
|
+
return { searchAnalytics, urlInspection, serp, keywords, backlinks, aiVisibility, linkGraph };
|
|
392
|
+
}
|
|
393
|
+
// ── Hub emission ─────────────────────────────────────────────────────
|
|
394
|
+
/**
|
|
395
|
+
* Emit `analysis`'s cited findings into the priority hub. Best-effort:
|
|
396
|
+
* `SeoHubEmitter.emit` already catches and logs sink failures internally,
|
|
397
|
+
* so this helper never throws and never affects the runner's exit code.
|
|
398
|
+
*
|
|
399
|
+
* An injected `findingSink` (tests) is used as-is. Otherwise a `FactStore`
|
|
400
|
+
* is opened lazily — only when there is at least one Finding to emit — so a
|
|
401
|
+
* clean/all-uncited run never touches the filesystem for hub purposes.
|
|
402
|
+
*/
|
|
403
|
+
async function emitFindingsToHub(analysis, projectRoot, now, findingSink) {
|
|
404
|
+
const emitter = new SeoHubEmitter();
|
|
405
|
+
if (findingSink !== undefined) {
|
|
406
|
+
await emitter.emit(analysis, findingSink, logger, now);
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
// Check emptiness BEFORE opening a store — mapToFindings is pure and cheap.
|
|
410
|
+
if (emitter.mapToFindings(analysis, now).length === 0)
|
|
411
|
+
return;
|
|
412
|
+
let store;
|
|
413
|
+
try {
|
|
414
|
+
await ensureFactsDir(projectRoot);
|
|
415
|
+
const opened = new FactStore(factsDbPath(projectRoot));
|
|
416
|
+
store = opened;
|
|
417
|
+
const defaultSink = async (finding) => {
|
|
418
|
+
await ingestFinding(opened, finding, { now });
|
|
419
|
+
};
|
|
420
|
+
await emitter.emit(analysis, defaultSink, logger, now);
|
|
421
|
+
}
|
|
422
|
+
catch (err) {
|
|
423
|
+
logger.warn(`SEO hub emission failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
424
|
+
}
|
|
425
|
+
finally {
|
|
426
|
+
store?.close();
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
// ── SeoWorkflowRunner ────────────────────────────────────────────────
|
|
430
|
+
export class SeoWorkflowRunner {
|
|
431
|
+
/**
|
|
432
|
+
* Run one SEO workflow end-to-end. NEVER throws — every failure mode
|
|
433
|
+
* (context/source/gather/analyze/persist errors, a `parsed: false`
|
|
434
|
+
* analysis, or a blocked citation gate) resolves to `exitCode: 2`;
|
|
435
|
+
* only a fully successful, non-blocked run resolves to `exitCode: 0`.
|
|
436
|
+
*/
|
|
437
|
+
async run(input) {
|
|
438
|
+
try {
|
|
439
|
+
const target = input.target ?? input.config.seo?.defaultTarget ?? DEFAULT_TARGET_FALLBACK;
|
|
440
|
+
const context = await new SeoPlaybookRetriever(new SeoPlaybookIndex()).retrieve({
|
|
441
|
+
workflow: input.workflow,
|
|
442
|
+
target,
|
|
443
|
+
});
|
|
444
|
+
const source = input.dataSource ?? (await selectSource(input.config, input.projectRoot));
|
|
445
|
+
const data = await gatherDataBundle(source, input.workflow, target, input.now, input.projectRoot);
|
|
446
|
+
const analyzer = input.analyzer ?? buildDefaultAnalyzer();
|
|
447
|
+
const analysis = await analyzer.analyze({
|
|
448
|
+
workflow: input.workflow,
|
|
449
|
+
target,
|
|
450
|
+
context,
|
|
451
|
+
data,
|
|
452
|
+
config: input.config,
|
|
453
|
+
now: input.now,
|
|
454
|
+
});
|
|
455
|
+
if (!analysis.parsed) {
|
|
456
|
+
// Fail-closed (sc-11-5): no report, ZERO hub emits.
|
|
457
|
+
return { exitCode: 2 };
|
|
458
|
+
}
|
|
459
|
+
// Third never-encode belt (spec-20260717-seo-improver-builder, Sprint 2;
|
|
460
|
+
// ADR-3): drops an LLM-synthesized banned tactic BEFORE the citation
|
|
461
|
+
// gate, even when it carries a well-formed citationUrl that would
|
|
462
|
+
// otherwise sail through `SeoCitationGate` untouched.
|
|
463
|
+
const scrubbed = new NeverEncodeFilter().apply(analysis.findings);
|
|
464
|
+
const threshold = input.config.seo?.blockThreshold ?? "critical-uncited";
|
|
465
|
+
const gate = new SeoCitationGate().apply(scrubbed.kept, threshold);
|
|
466
|
+
// Opt-in, downgrade-only adversarial verifier stage (Sprint 12),
|
|
467
|
+
// between the citation gate and persistence. The `enabled` check
|
|
468
|
+
// lives HERE (not just inside `verify()`) so the disabled path never
|
|
469
|
+
// even constructs a `SeoRecommendationVerifier` or makes a provider
|
|
470
|
+
// call — byte-identical to the no-verifier run (sc-12-2). The
|
|
471
|
+
// verifier consumes ONLY `gate.cited` and can only shrink/downgrade
|
|
472
|
+
// it; `gate.blocked` (used below) is derived from `gate.dropped` and
|
|
473
|
+
// is NEVER recomputed from the verifier's output, so a verifier
|
|
474
|
+
// failure structurally cannot change the exit code or block decision
|
|
475
|
+
// (sc-12-4).
|
|
476
|
+
let cited = gate.cited;
|
|
477
|
+
if (input.config.seo?.verifier?.enabled === true) {
|
|
478
|
+
const verifier = input.verifier ?? new SeoRecommendationVerifier();
|
|
479
|
+
const verifyResult = await verifier.verify({
|
|
480
|
+
findings: gate.cited,
|
|
481
|
+
config: input.config,
|
|
482
|
+
projectRoot: input.projectRoot,
|
|
483
|
+
now: input.now,
|
|
484
|
+
});
|
|
485
|
+
cited = verifyResult.findings;
|
|
486
|
+
}
|
|
487
|
+
const report = {
|
|
488
|
+
reportId: deriveReportId(input.now, input.workflow, target),
|
|
489
|
+
workflow: input.workflow,
|
|
490
|
+
target,
|
|
491
|
+
generatedAt: input.now,
|
|
492
|
+
findings: cited,
|
|
493
|
+
droppedUncited: gate.dropped.length,
|
|
494
|
+
droppedNeverEncode: scrubbed.dropped.length,
|
|
495
|
+
dataProvenance: analysis.dataProvenance,
|
|
496
|
+
verdict: gate.blocked ? "blocked" : "pass",
|
|
497
|
+
};
|
|
498
|
+
await new SeoReportStore().save(input.projectRoot, report);
|
|
499
|
+
// Best-effort hub emit of the (possibly verifier-folded) cited
|
|
500
|
+
// findings ONLY, AFTER persist. A hub failure never changes the exit
|
|
501
|
+
// code.
|
|
502
|
+
const citedAnalysis = { ...analysis, findings: cited };
|
|
503
|
+
await emitFindingsToHub(citedAnalysis, input.projectRoot, input.now, input.findingSink);
|
|
504
|
+
return { report, exitCode: gate.blocked ? 2 : 0 };
|
|
505
|
+
}
|
|
506
|
+
catch {
|
|
507
|
+
// Unexpected throw (context/source/gather/analyze/persist) -> fail-closed.
|
|
508
|
+
return { exitCode: 2 };
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/seo/runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ScrapeThrottle — per-engine scrape rate window + proxy-USD ledger,
|
|
3
|
+
* SEPARATE from the governor USD ledger, SAME mutex + atomic-write +
|
|
4
|
+
* fail-closed discipline as `SeoQuotaGovernor` (spec-20260718-in-house-
|
|
5
|
+
* ai-visibility, Sprint 9; arch ScrapeThrottle §208-220 / ADR-3).
|
|
6
|
+
*
|
|
7
|
+
* The scrape arm's `estCostUsdPerPrompt` is booked as $0 to the
|
|
8
|
+
* `SeoQuotaGovernor` — its real proxy cost is tracked HERE, in an
|
|
9
|
+
* independent, independently-capped filesystem ledger keyed by engine
|
|
10
|
+
* string at `.bober/seo/scrape-throttle-ledger.json` (a DISTINCT path
|
|
11
|
+
* from `.bober/seo/quota-ledger.json`). The two ledgers are never
|
|
12
|
+
* cross-reconciled (arch §320).
|
|
13
|
+
*
|
|
14
|
+
* `acquire(engine)` both DECIDES and CONSUMES a rate slot in one
|
|
15
|
+
* read-modify-write under the shared per-path mutex (`withLedgerLock`,
|
|
16
|
+
* reused from `quota-ledger.ts` — path-generic, so this ledger gets its
|
|
17
|
+
* own serialization chain and cannot interfere with the governor's).
|
|
18
|
+
* It writes ONLY on the granting branch — a refusal has no side effect,
|
|
19
|
+
* mirroring `SeoQuotaGovernor.admit()`.
|
|
20
|
+
*
|
|
21
|
+
* `recordProxyCost(engine, usd)` is the governor's `record()` twin:
|
|
22
|
+
* heals a corrupt ledger back to `{}`, accrues a NaN/negative-guarded
|
|
23
|
+
* USD amount, and writes atomically (temp-file + rename) so a crash
|
|
24
|
+
* mid-write never leaves a torn file.
|
|
25
|
+
*
|
|
26
|
+
* Fail-closed: a corrupt/unreadable ledger makes `acquire` treat proxy
|
|
27
|
+
* spend as `+Infinity` (mirrors the governor's Infinity-on-corrupt
|
|
28
|
+
* refuse) and deny with `reason: "proxy-budget"`. A MISSING ledger
|
|
29
|
+
* (first run) is a fresh `{}` — allow.
|
|
30
|
+
*
|
|
31
|
+
* The clock is INJECTED (`() => ISO string`, mirrors
|
|
32
|
+
* `DamcrawlerCrawlEngine.now`), never `Date.now()` — deterministic
|
|
33
|
+
* rate-window tests drive it across the window boundary explicitly.
|
|
34
|
+
*
|
|
35
|
+
* ISOLATED sprint: no scrape-provider wiring (Sprint 10), no config-
|
|
36
|
+
* schema field (caps come from the constructor), no egress coupling.
|
|
37
|
+
*/
|
|
38
|
+
/** Persisted at `.bober/seo/scrape-throttle-ledger.json` — keyed by engine string. */
|
|
39
|
+
export type ScrapeProxyLedger = {
|
|
40
|
+
[engine: string]: {
|
|
41
|
+
windowStart: number;
|
|
42
|
+
count: number;
|
|
43
|
+
proxyUsdSpent: number;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
/** `acquire()` decision. Note `proceed`, NOT `allowed` — per contract sc-9-1. */
|
|
47
|
+
export type ThrottleDecision = {
|
|
48
|
+
proceed: true;
|
|
49
|
+
} | {
|
|
50
|
+
proceed: false;
|
|
51
|
+
reason: "rate-window" | "proxy-budget";
|
|
52
|
+
};
|
|
53
|
+
/** Caps injected via constructor — no config-schema field this sprint (isolation). */
|
|
54
|
+
export type ScrapeThrottleLimits = {
|
|
55
|
+
/** Max `acquire()` grants per rolling fixed window, per engine. */
|
|
56
|
+
maxPerWindow: number;
|
|
57
|
+
/** Fixed-window length in milliseconds. */
|
|
58
|
+
windowMs: number;
|
|
59
|
+
/** Max cumulative `proxyUsdSpent` per engine before `acquire` denies. */
|
|
60
|
+
maxProxyUsd: number;
|
|
61
|
+
};
|
|
62
|
+
export declare class ScrapeThrottle {
|
|
63
|
+
private readonly ledgerPath;
|
|
64
|
+
private readonly limits;
|
|
65
|
+
private readonly now;
|
|
66
|
+
constructor(ledgerPath: string, limits: ScrapeThrottleLimits, now?: () => string);
|
|
67
|
+
/**
|
|
68
|
+
* Decide whether `engine` may scrape now, consuming a rate slot on grant.
|
|
69
|
+
* Read-modify-write under the per-path mutex; writes ONLY on the granting
|
|
70
|
+
* branch (a refusal has no side effect on the ledger, mirroring
|
|
71
|
+
* `SeoQuotaGovernor.admit()`/`record()` no-write-on-refuse).
|
|
72
|
+
*/
|
|
73
|
+
acquire(engine: string): Promise<ThrottleDecision>;
|
|
74
|
+
/**
|
|
75
|
+
* Persist completed proxy spend for `engine`. Heals a corrupt ledger back
|
|
76
|
+
* to `{}` (corruption blocks `acquire`, not `recordProxyCost` — mirrors
|
|
77
|
+
* `SeoQuotaGovernor.record()`). Guards NaN/negative/zero cost so a bad
|
|
78
|
+
* value can never corrupt or reduce the running total. Concurrent calls
|
|
79
|
+
* sharing `ledgerPath` never lose an update (per-path mutex + read-fresh-
|
|
80
|
+
* inside-lock + atomic write).
|
|
81
|
+
*/
|
|
82
|
+
recordProxyCost(engine: string, usd: number): Promise<void>;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=scrape-throttle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scrape-throttle.d.ts","sourceRoot":"","sources":["../../src/seo/scrape-throttle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAWH,sFAAsF;AACtF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;CACjF,CAAC;AAEF,iFAAiF;AACjF,MAAM,MAAM,gBAAgB,GAAG;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,aAAa,GAAG,cAAc,CAAA;CAAE,CAAC;AAE9G,sFAAsF;AACtF,MAAM,MAAM,oBAAoB,GAAG;IACjC,mEAAmE;IACnE,YAAY,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AA0CF,qBAAa,cAAc;IAEvB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAEvB,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAHH,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,oBAAoB,EAE5B,GAAG,GAAE,MAAM,MAAuC;IAGrE;;;;;OAKG;IACG,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAkCxD;;;;;;;OAOG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAelE"}
|