verbolab 0.1.0-alpha.1
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/LICENSE +21 -0
- package/README.md +71 -0
- package/dist/bin/verbo.d.ts +3 -0
- package/dist/bin/verbo.d.ts.map +1 -0
- package/dist/bin/verbo.js +1156 -0
- package/dist/bin/verbo.js.map +1 -0
- package/dist/relay/index.d.ts +2 -0
- package/dist/relay/index.d.ts.map +1 -0
- package/dist/relay/index.js +15 -0
- package/dist/relay/index.js.map +1 -0
- package/dist/src/agent/agent-launcher.d.ts +64 -0
- package/dist/src/agent/agent-launcher.d.ts.map +1 -0
- package/dist/src/agent/agent-launcher.js +326 -0
- package/dist/src/agent/agent-launcher.js.map +1 -0
- package/dist/src/agent/agent-monitor.d.ts +16 -0
- package/dist/src/agent/agent-monitor.d.ts.map +1 -0
- package/dist/src/agent/agent-monitor.js +41 -0
- package/dist/src/agent/agent-monitor.js.map +1 -0
- package/dist/src/agent/fun-names.d.ts +9 -0
- package/dist/src/agent/fun-names.d.ts.map +1 -0
- package/dist/src/agent/fun-names.js +118 -0
- package/dist/src/agent/fun-names.js.map +1 -0
- package/dist/src/agent/mcp-shim.d.ts +45 -0
- package/dist/src/agent/mcp-shim.d.ts.map +1 -0
- package/dist/src/agent/mcp-shim.js +192 -0
- package/dist/src/agent/mcp-shim.js.map +1 -0
- package/dist/src/agent/personas.d.ts +47 -0
- package/dist/src/agent/personas.d.ts.map +1 -0
- package/dist/src/agent/personas.js +86 -0
- package/dist/src/agent/personas.js.map +1 -0
- package/dist/src/agent/provider-detection.d.ts +21 -0
- package/dist/src/agent/provider-detection.d.ts.map +1 -0
- package/dist/src/agent/provider-detection.js +47 -0
- package/dist/src/agent/provider-detection.js.map +1 -0
- package/dist/src/agent/providers/claude-provider.d.ts +3 -0
- package/dist/src/agent/providers/claude-provider.d.ts.map +1 -0
- package/dist/src/agent/providers/claude-provider.js +119 -0
- package/dist/src/agent/providers/claude-provider.js.map +1 -0
- package/dist/src/agent/providers/gemini-provider.d.ts +13 -0
- package/dist/src/agent/providers/gemini-provider.d.ts.map +1 -0
- package/dist/src/agent/providers/gemini-provider.js +143 -0
- package/dist/src/agent/providers/gemini-provider.js.map +1 -0
- package/dist/src/agent/providers/openai-provider.d.ts +3 -0
- package/dist/src/agent/providers/openai-provider.d.ts.map +1 -0
- package/dist/src/agent/providers/openai-provider.js +127 -0
- package/dist/src/agent/providers/openai-provider.js.map +1 -0
- package/dist/src/agent/providers/registry.d.ts +19 -0
- package/dist/src/agent/providers/registry.d.ts.map +1 -0
- package/dist/src/agent/providers/registry.js +30 -0
- package/dist/src/agent/providers/registry.js.map +1 -0
- package/dist/src/agent/providers/types.d.ts +118 -0
- package/dist/src/agent/providers/types.d.ts.map +1 -0
- package/dist/src/agent/providers/types.js +2 -0
- package/dist/src/agent/providers/types.js.map +1 -0
- package/dist/src/approval/approval-server.d.ts +17 -0
- package/dist/src/approval/approval-server.d.ts.map +1 -0
- package/dist/src/approval/approval-server.js +90 -0
- package/dist/src/approval/approval-server.js.map +1 -0
- package/dist/src/approval/approval-store.d.ts +29 -0
- package/dist/src/approval/approval-store.d.ts.map +1 -0
- package/dist/src/approval/approval-store.js +94 -0
- package/dist/src/approval/approval-store.js.map +1 -0
- package/dist/src/auth/auth-store.d.ts +18 -0
- package/dist/src/auth/auth-store.d.ts.map +1 -0
- package/dist/src/auth/auth-store.js +34 -0
- package/dist/src/auth/auth-store.js.map +1 -0
- package/dist/src/auth/device-code-client.d.ts +32 -0
- package/dist/src/auth/device-code-client.d.ts.map +1 -0
- package/dist/src/auth/device-code-client.js +41 -0
- package/dist/src/auth/device-code-client.js.map +1 -0
- package/dist/src/auth/plan-enforcer.d.ts +8 -0
- package/dist/src/auth/plan-enforcer.d.ts.map +1 -0
- package/dist/src/auth/plan-enforcer.js +14 -0
- package/dist/src/auth/plan-enforcer.js.map +1 -0
- package/dist/src/commands/audit.d.ts +7 -0
- package/dist/src/commands/audit.d.ts.map +1 -0
- package/dist/src/commands/audit.js +92 -0
- package/dist/src/commands/audit.js.map +1 -0
- package/dist/src/commands/team.d.ts +48 -0
- package/dist/src/commands/team.d.ts.map +1 -0
- package/dist/src/commands/team.js +175 -0
- package/dist/src/commands/team.js.map +1 -0
- package/dist/src/config/verbo-config.d.ts +43 -0
- package/dist/src/config/verbo-config.d.ts.map +1 -0
- package/dist/src/config/verbo-config.js +111 -0
- package/dist/src/config/verbo-config.js.map +1 -0
- package/dist/src/core/agent-session-store.d.ts +69 -0
- package/dist/src/core/agent-session-store.d.ts.map +1 -0
- package/dist/src/core/agent-session-store.js +168 -0
- package/dist/src/core/agent-session-store.js.map +1 -0
- package/dist/src/core/audit-log-store.d.ts +33 -0
- package/dist/src/core/audit-log-store.d.ts.map +1 -0
- package/dist/src/core/audit-log-store.js +104 -0
- package/dist/src/core/audit-log-store.js.map +1 -0
- package/dist/src/core/compliance.d.ts +50 -0
- package/dist/src/core/compliance.d.ts.map +1 -0
- package/dist/src/core/compliance.js +59 -0
- package/dist/src/core/compliance.js.map +1 -0
- package/dist/src/core/conflict-detector.d.ts +19 -0
- package/dist/src/core/conflict-detector.d.ts.map +1 -0
- package/dist/src/core/conflict-detector.js +87 -0
- package/dist/src/core/conflict-detector.js.map +1 -0
- package/dist/src/core/conflict-enforcer.d.ts +37 -0
- package/dist/src/core/conflict-enforcer.d.ts.map +1 -0
- package/dist/src/core/conflict-enforcer.js +139 -0
- package/dist/src/core/conflict-enforcer.js.map +1 -0
- package/dist/src/core/cost-store.d.ts +55 -0
- package/dist/src/core/cost-store.d.ts.map +1 -0
- package/dist/src/core/cost-store.js +140 -0
- package/dist/src/core/cost-store.js.map +1 -0
- package/dist/src/core/hot-files.d.ts +19 -0
- package/dist/src/core/hot-files.d.ts.map +1 -0
- package/dist/src/core/hot-files.js +64 -0
- package/dist/src/core/hot-files.js.map +1 -0
- package/dist/src/core/human-action-store.d.ts +33 -0
- package/dist/src/core/human-action-store.d.ts.map +1 -0
- package/dist/src/core/human-action-store.js +92 -0
- package/dist/src/core/human-action-store.js.map +1 -0
- package/dist/src/core/learning-store.d.ts +32 -0
- package/dist/src/core/learning-store.d.ts.map +1 -0
- package/dist/src/core/learning-store.js +95 -0
- package/dist/src/core/learning-store.js.map +1 -0
- package/dist/src/core/merge-queue.d.ts +28 -0
- package/dist/src/core/merge-queue.d.ts.map +1 -0
- package/dist/src/core/merge-queue.js +92 -0
- package/dist/src/core/merge-queue.js.map +1 -0
- package/dist/src/core/notification-service.d.ts +13 -0
- package/dist/src/core/notification-service.d.ts.map +1 -0
- package/dist/src/core/notification-service.js +126 -0
- package/dist/src/core/notification-service.js.map +1 -0
- package/dist/src/core/notifications.d.ts +10 -0
- package/dist/src/core/notifications.d.ts.map +1 -0
- package/dist/src/core/notifications.js +33 -0
- package/dist/src/core/notifications.js.map +1 -0
- package/dist/src/core/orchestrator-store.d.ts +44 -0
- package/dist/src/core/orchestrator-store.d.ts.map +1 -0
- package/dist/src/core/orchestrator-store.js +69 -0
- package/dist/src/core/orchestrator-store.js.map +1 -0
- package/dist/src/core/parallelizer.d.ts +47 -0
- package/dist/src/core/parallelizer.d.ts.map +1 -0
- package/dist/src/core/parallelizer.js +224 -0
- package/dist/src/core/parallelizer.js.map +1 -0
- package/dist/src/core/pipeline-rollback.d.ts +29 -0
- package/dist/src/core/pipeline-rollback.d.ts.map +1 -0
- package/dist/src/core/pipeline-rollback.js +84 -0
- package/dist/src/core/pipeline-rollback.js.map +1 -0
- package/dist/src/core/pipeline-runner.d.ts +73 -0
- package/dist/src/core/pipeline-runner.d.ts.map +1 -0
- package/dist/src/core/pipeline-runner.js +165 -0
- package/dist/src/core/pipeline-runner.js.map +1 -0
- package/dist/src/core/pr-creator.d.ts +22 -0
- package/dist/src/core/pr-creator.d.ts.map +1 -0
- package/dist/src/core/pr-creator.js +55 -0
- package/dist/src/core/pr-creator.js.map +1 -0
- package/dist/src/core/rbac.d.ts +27 -0
- package/dist/src/core/rbac.d.ts.map +1 -0
- package/dist/src/core/rbac.js +76 -0
- package/dist/src/core/rbac.js.map +1 -0
- package/dist/src/core/startup-cleanup.d.ts +47 -0
- package/dist/src/core/startup-cleanup.d.ts.map +1 -0
- package/dist/src/core/startup-cleanup.js +150 -0
- package/dist/src/core/startup-cleanup.js.map +1 -0
- package/dist/src/core/task-store.d.ts +96 -0
- package/dist/src/core/task-store.d.ts.map +1 -0
- package/dist/src/core/task-store.js +309 -0
- package/dist/src/core/task-store.js.map +1 -0
- package/dist/src/core/verbo-config-editor.d.ts +44 -0
- package/dist/src/core/verbo-config-editor.d.ts.map +1 -0
- package/dist/src/core/verbo-config-editor.js +204 -0
- package/dist/src/core/verbo-config-editor.js.map +1 -0
- package/dist/src/core/verbo-config.d.ts +35 -0
- package/dist/src/core/verbo-config.d.ts.map +1 -0
- package/dist/src/core/verbo-config.js +55 -0
- package/dist/src/core/verbo-config.js.map +1 -0
- package/dist/src/core/verbo-md.d.ts +96 -0
- package/dist/src/core/verbo-md.d.ts.map +1 -0
- package/dist/src/core/verbo-md.js +410 -0
- package/dist/src/core/verbo-md.js.map +1 -0
- package/dist/src/db/database.d.ts +9 -0
- package/dist/src/db/database.d.ts.map +1 -0
- package/dist/src/db/database.js +37 -0
- package/dist/src/db/database.js.map +1 -0
- package/dist/src/db/migrations/001-personas-subtasks.d.ts +10 -0
- package/dist/src/db/migrations/001-personas-subtasks.d.ts.map +1 -0
- package/dist/src/db/migrations/001-personas-subtasks.js +32 -0
- package/dist/src/db/migrations/001-personas-subtasks.js.map +1 -0
- package/dist/src/db/migrations/002-rbac.d.ts +9 -0
- package/dist/src/db/migrations/002-rbac.d.ts.map +1 -0
- package/dist/src/db/migrations/002-rbac.js +31 -0
- package/dist/src/db/migrations/002-rbac.js.map +1 -0
- package/dist/src/db/migrations/003-provider-column.d.ts +8 -0
- package/dist/src/db/migrations/003-provider-column.d.ts.map +1 -0
- package/dist/src/db/migrations/003-provider-column.js +12 -0
- package/dist/src/db/migrations/003-provider-column.js.map +1 -0
- package/dist/src/db/migrations/004-pipeline-cost.d.ts +8 -0
- package/dist/src/db/migrations/004-pipeline-cost.d.ts.map +1 -0
- package/dist/src/db/migrations/004-pipeline-cost.js +23 -0
- package/dist/src/db/migrations/004-pipeline-cost.js.map +1 -0
- package/dist/src/db/migrations/005-audit-log-timestamp.d.ts +10 -0
- package/dist/src/db/migrations/005-audit-log-timestamp.d.ts.map +1 -0
- package/dist/src/db/migrations/005-audit-log-timestamp.js +39 -0
- package/dist/src/db/migrations/005-audit-log-timestamp.js.map +1 -0
- package/dist/src/db/migrations/006-human-action-type.d.ts +9 -0
- package/dist/src/db/migrations/006-human-action-type.d.ts.map +1 -0
- package/dist/src/db/migrations/006-human-action-type.js +16 -0
- package/dist/src/db/migrations/006-human-action-type.js.map +1 -0
- package/dist/src/db/schema.d.ts +6 -0
- package/dist/src/db/schema.d.ts.map +1 -0
- package/dist/src/db/schema.js +255 -0
- package/dist/src/db/schema.js.map +1 -0
- package/dist/src/deps/dependabot-generator.d.ts +22 -0
- package/dist/src/deps/dependabot-generator.d.ts.map +1 -0
- package/dist/src/deps/dependabot-generator.js +83 -0
- package/dist/src/deps/dependabot-generator.js.map +1 -0
- package/dist/src/deps/dependabot-monitor.d.ts +22 -0
- package/dist/src/deps/dependabot-monitor.d.ts.map +1 -0
- package/dist/src/deps/dependabot-monitor.js +28 -0
- package/dist/src/deps/dependabot-monitor.js.map +1 -0
- package/dist/src/deps/package-auditor.d.ts +24 -0
- package/dist/src/deps/package-auditor.d.ts.map +1 -0
- package/dist/src/deps/package-auditor.js +118 -0
- package/dist/src/deps/package-auditor.js.map +1 -0
- package/dist/src/init/ensure-init.d.ts +6 -0
- package/dist/src/init/ensure-init.d.ts.map +1 -0
- package/dist/src/init/ensure-init.js +27 -0
- package/dist/src/init/ensure-init.js.map +1 -0
- package/dist/src/init/project-detector.d.ts +11 -0
- package/dist/src/init/project-detector.d.ts.map +1 -0
- package/dist/src/init/project-detector.js +117 -0
- package/dist/src/init/project-detector.js.map +1 -0
- package/dist/src/init/questionnaire.d.ts +5 -0
- package/dist/src/init/questionnaire.d.ts.map +1 -0
- package/dist/src/init/questionnaire.js +112 -0
- package/dist/src/init/questionnaire.js.map +1 -0
- package/dist/src/init/template.d.ts +17 -0
- package/dist/src/init/template.d.ts.map +1 -0
- package/dist/src/init/template.js +46 -0
- package/dist/src/init/template.js.map +1 -0
- package/dist/src/intelligence/claude-client.d.ts +3 -0
- package/dist/src/intelligence/claude-client.d.ts.map +1 -0
- package/dist/src/intelligence/claude-client.js +12 -0
- package/dist/src/intelligence/claude-client.js.map +1 -0
- package/dist/src/intelligence/conflict-mediator.d.ts +17 -0
- package/dist/src/intelligence/conflict-mediator.d.ts.map +1 -0
- package/dist/src/intelligence/conflict-mediator.js +83 -0
- package/dist/src/intelligence/conflict-mediator.js.map +1 -0
- package/dist/src/intelligence/github-orchestrator.d.ts +30 -0
- package/dist/src/intelligence/github-orchestrator.d.ts.map +1 -0
- package/dist/src/intelligence/github-orchestrator.js +270 -0
- package/dist/src/intelligence/github-orchestrator.js.map +1 -0
- package/dist/src/intelligence/kill-switch.d.ts +10 -0
- package/dist/src/intelligence/kill-switch.d.ts.map +1 -0
- package/dist/src/intelligence/kill-switch.js +12 -0
- package/dist/src/intelligence/kill-switch.js.map +1 -0
- package/dist/src/intelligence/learnings-extractor.d.ts +13 -0
- package/dist/src/intelligence/learnings-extractor.d.ts.map +1 -0
- package/dist/src/intelligence/learnings-extractor.js +74 -0
- package/dist/src/intelligence/learnings-extractor.js.map +1 -0
- package/dist/src/intelligence/project-scanner.d.ts +2 -0
- package/dist/src/intelligence/project-scanner.d.ts.map +1 -0
- package/dist/src/intelligence/project-scanner.js +28 -0
- package/dist/src/intelligence/project-scanner.js.map +1 -0
- package/dist/src/intelligence/task-decomposer.d.ts +14 -0
- package/dist/src/intelligence/task-decomposer.d.ts.map +1 -0
- package/dist/src/intelligence/task-decomposer.js +97 -0
- package/dist/src/intelligence/task-decomposer.js.map +1 -0
- package/dist/src/intelligence/types.d.ts +14 -0
- package/dist/src/intelligence/types.d.ts.map +1 -0
- package/dist/src/intelligence/types.js +2 -0
- package/dist/src/intelligence/types.js.map +1 -0
- package/dist/src/mcp/server.d.ts +63 -0
- package/dist/src/mcp/server.d.ts.map +1 -0
- package/dist/src/mcp/server.js +537 -0
- package/dist/src/mcp/server.js.map +1 -0
- package/dist/src/mcp/stdio-entry.d.ts +2 -0
- package/dist/src/mcp/stdio-entry.d.ts.map +1 -0
- package/dist/src/mcp/stdio-entry.js +124 -0
- package/dist/src/mcp/stdio-entry.js.map +1 -0
- package/dist/src/mcp/subtask-handlers.d.ts +7 -0
- package/dist/src/mcp/subtask-handlers.d.ts.map +1 -0
- package/dist/src/mcp/subtask-handlers.js +50 -0
- package/dist/src/mcp/subtask-handlers.js.map +1 -0
- package/dist/src/security/network-proxy.d.ts +20 -0
- package/dist/src/security/network-proxy.d.ts.map +1 -0
- package/dist/src/security/network-proxy.js +125 -0
- package/dist/src/security/network-proxy.js.map +1 -0
- package/dist/src/security/network-sandbox.d.ts +19 -0
- package/dist/src/security/network-sandbox.d.ts.map +1 -0
- package/dist/src/security/network-sandbox.js +100 -0
- package/dist/src/security/network-sandbox.js.map +1 -0
- package/dist/src/security/sanitize.d.ts +13 -0
- package/dist/src/security/sanitize.d.ts.map +1 -0
- package/dist/src/security/sanitize.js +19 -0
- package/dist/src/security/sanitize.js.map +1 -0
- package/dist/src/security/secrets-patterns.d.ts +29 -0
- package/dist/src/security/secrets-patterns.d.ts.map +1 -0
- package/dist/src/security/secrets-patterns.js +430 -0
- package/dist/src/security/secrets-patterns.js.map +1 -0
- package/dist/src/security/secrets-scanner.d.ts +26 -0
- package/dist/src/security/secrets-scanner.d.ts.map +1 -0
- package/dist/src/security/secrets-scanner.js +62 -0
- package/dist/src/security/secrets-scanner.js.map +1 -0
- package/dist/src/skills/classifier.d.ts +9 -0
- package/dist/src/skills/classifier.d.ts.map +1 -0
- package/dist/src/skills/classifier.js +41 -0
- package/dist/src/skills/classifier.js.map +1 -0
- package/dist/src/skills/registry.d.ts +16 -0
- package/dist/src/skills/registry.d.ts.map +1 -0
- package/dist/src/skills/registry.js +61 -0
- package/dist/src/skills/registry.js.map +1 -0
- package/dist/src/sync/events.d.ts +9 -0
- package/dist/src/sync/events.d.ts.map +1 -0
- package/dist/src/sync/events.js +2 -0
- package/dist/src/sync/events.js.map +1 -0
- package/dist/src/sync/relay-server.d.ts +18 -0
- package/dist/src/sync/relay-server.d.ts.map +1 -0
- package/dist/src/sync/relay-server.js +131 -0
- package/dist/src/sync/relay-server.js.map +1 -0
- package/dist/src/sync/sync-client.d.ts +31 -0
- package/dist/src/sync/sync-client.d.ts.map +1 -0
- package/dist/src/sync/sync-client.js +314 -0
- package/dist/src/sync/sync-client.js.map +1 -0
- package/dist/src/tui/app.d.ts +35 -0
- package/dist/src/tui/app.d.ts.map +1 -0
- package/dist/src/tui/app.js +676 -0
- package/dist/src/tui/app.js.map +1 -0
- package/dist/src/tui/components/activity-feed.d.ts +12 -0
- package/dist/src/tui/components/activity-feed.d.ts.map +1 -0
- package/dist/src/tui/components/activity-feed.js +82 -0
- package/dist/src/tui/components/activity-feed.js.map +1 -0
- package/dist/src/tui/components/agent-list.d.ts +19 -0
- package/dist/src/tui/components/agent-list.d.ts.map +1 -0
- package/dist/src/tui/components/agent-list.js +33 -0
- package/dist/src/tui/components/agent-list.js.map +1 -0
- package/dist/src/tui/components/agent-row.d.ts +12 -0
- package/dist/src/tui/components/agent-row.d.ts.map +1 -0
- package/dist/src/tui/components/agent-row.js +37 -0
- package/dist/src/tui/components/agent-row.js.map +1 -0
- package/dist/src/tui/components/approval-terminal.d.ts +13 -0
- package/dist/src/tui/components/approval-terminal.d.ts.map +1 -0
- package/dist/src/tui/components/approval-terminal.js +34 -0
- package/dist/src/tui/components/approval-terminal.js.map +1 -0
- package/dist/src/tui/components/audit-viewer.d.ts +16 -0
- package/dist/src/tui/components/audit-viewer.d.ts.map +1 -0
- package/dist/src/tui/components/audit-viewer.js +46 -0
- package/dist/src/tui/components/audit-viewer.js.map +1 -0
- package/dist/src/tui/components/auth-gate.d.ts +9 -0
- package/dist/src/tui/components/auth-gate.d.ts.map +1 -0
- package/dist/src/tui/components/auth-gate.js +112 -0
- package/dist/src/tui/components/auth-gate.js.map +1 -0
- package/dist/src/tui/components/command-palette.d.ts +12 -0
- package/dist/src/tui/components/command-palette.d.ts.map +1 -0
- package/dist/src/tui/components/command-palette.js +51 -0
- package/dist/src/tui/components/command-palette.js.map +1 -0
- package/dist/src/tui/components/compliance-badge.d.ts +11 -0
- package/dist/src/tui/components/compliance-badge.d.ts.map +1 -0
- package/dist/src/tui/components/compliance-badge.js +12 -0
- package/dist/src/tui/components/compliance-badge.js.map +1 -0
- package/dist/src/tui/components/decomposition-review.d.ts +10 -0
- package/dist/src/tui/components/decomposition-review.d.ts.map +1 -0
- package/dist/src/tui/components/decomposition-review.js +19 -0
- package/dist/src/tui/components/decomposition-review.js.map +1 -0
- package/dist/src/tui/components/dependency-graph.d.ts +13 -0
- package/dist/src/tui/components/dependency-graph.d.ts.map +1 -0
- package/dist/src/tui/components/dependency-graph.js +143 -0
- package/dist/src/tui/components/dependency-graph.js.map +1 -0
- package/dist/src/tui/components/diff-viewer.d.ts +11 -0
- package/dist/src/tui/components/diff-viewer.d.ts.map +1 -0
- package/dist/src/tui/components/diff-viewer.js +82 -0
- package/dist/src/tui/components/diff-viewer.js.map +1 -0
- package/dist/src/tui/components/edit-task-input.d.ts +10 -0
- package/dist/src/tui/components/edit-task-input.d.ts.map +1 -0
- package/dist/src/tui/components/edit-task-input.js +20 -0
- package/dist/src/tui/components/edit-task-input.js.map +1 -0
- package/dist/src/tui/components/footer.d.ts +12 -0
- package/dist/src/tui/components/footer.d.ts.map +1 -0
- package/dist/src/tui/components/footer.js +41 -0
- package/dist/src/tui/components/footer.js.map +1 -0
- package/dist/src/tui/components/header.d.ts +8 -0
- package/dist/src/tui/components/header.d.ts.map +1 -0
- package/dist/src/tui/components/header.js +20 -0
- package/dist/src/tui/components/header.js.map +1 -0
- package/dist/src/tui/components/human-actions.d.ts +14 -0
- package/dist/src/tui/components/human-actions.d.ts.map +1 -0
- package/dist/src/tui/components/human-actions.js +43 -0
- package/dist/src/tui/components/human-actions.js.map +1 -0
- package/dist/src/tui/components/log-panel.d.ts +10 -0
- package/dist/src/tui/components/log-panel.d.ts.map +1 -0
- package/dist/src/tui/components/log-panel.js +38 -0
- package/dist/src/tui/components/log-panel.js.map +1 -0
- package/dist/src/tui/components/memory-viewer.d.ts +10 -0
- package/dist/src/tui/components/memory-viewer.d.ts.map +1 -0
- package/dist/src/tui/components/memory-viewer.js +44 -0
- package/dist/src/tui/components/memory-viewer.js.map +1 -0
- package/dist/src/tui/components/new-task-input.d.ts +9 -0
- package/dist/src/tui/components/new-task-input.d.ts.map +1 -0
- package/dist/src/tui/components/new-task-input.js +21 -0
- package/dist/src/tui/components/new-task-input.js.map +1 -0
- package/dist/src/tui/components/orchestrator-status.d.ts +9 -0
- package/dist/src/tui/components/orchestrator-status.d.ts.map +1 -0
- package/dist/src/tui/components/orchestrator-status.js +15 -0
- package/dist/src/tui/components/orchestrator-status.js.map +1 -0
- package/dist/src/tui/components/parallelize-banner.d.ts +8 -0
- package/dist/src/tui/components/parallelize-banner.d.ts.map +1 -0
- package/dist/src/tui/components/parallelize-banner.js +9 -0
- package/dist/src/tui/components/parallelize-banner.js.map +1 -0
- package/dist/src/tui/components/progress-bar.d.ts +9 -0
- package/dist/src/tui/components/progress-bar.d.ts.map +1 -0
- package/dist/src/tui/components/progress-bar.js +15 -0
- package/dist/src/tui/components/progress-bar.js.map +1 -0
- package/dist/src/tui/components/review-queue.d.ts +13 -0
- package/dist/src/tui/components/review-queue.d.ts.map +1 -0
- package/dist/src/tui/components/review-queue.js +78 -0
- package/dist/src/tui/components/review-queue.js.map +1 -0
- package/dist/src/tui/components/rich-header.d.ts +11 -0
- package/dist/src/tui/components/rich-header.d.ts.map +1 -0
- package/dist/src/tui/components/rich-header.js +25 -0
- package/dist/src/tui/components/rich-header.js.map +1 -0
- package/dist/src/tui/components/spinner.d.ts +7 -0
- package/dist/src/tui/components/spinner.d.ts.map +1 -0
- package/dist/src/tui/components/spinner.js +8 -0
- package/dist/src/tui/components/spinner.js.map +1 -0
- package/dist/src/tui/components/status-bar.d.ts +23 -0
- package/dist/src/tui/components/status-bar.d.ts.map +1 -0
- package/dist/src/tui/components/status-bar.js +28 -0
- package/dist/src/tui/components/status-bar.js.map +1 -0
- package/dist/src/tui/components/task-queue.d.ts +11 -0
- package/dist/src/tui/components/task-queue.d.ts.map +1 -0
- package/dist/src/tui/components/task-queue.js +30 -0
- package/dist/src/tui/components/task-queue.js.map +1 -0
- package/dist/src/tui/components/team-view.d.ts +13 -0
- package/dist/src/tui/components/team-view.d.ts.map +1 -0
- package/dist/src/tui/components/team-view.js +12 -0
- package/dist/src/tui/components/team-view.js.map +1 -0
- package/dist/src/tui/graph-renderer.d.ts +11 -0
- package/dist/src/tui/graph-renderer.d.ts.map +1 -0
- package/dist/src/tui/graph-renderer.js +296 -0
- package/dist/src/tui/graph-renderer.js.map +1 -0
- package/dist/src/tui/hooks/use-bell.d.ts +21 -0
- package/dist/src/tui/hooks/use-bell.d.ts.map +1 -0
- package/dist/src/tui/hooks/use-bell.js +38 -0
- package/dist/src/tui/hooks/use-bell.js.map +1 -0
- package/dist/src/tui/hooks/use-ci-status.d.ts +16 -0
- package/dist/src/tui/hooks/use-ci-status.d.ts.map +1 -0
- package/dist/src/tui/hooks/use-ci-status.js +97 -0
- package/dist/src/tui/hooks/use-ci-status.js.map +1 -0
- package/dist/src/tui/hooks/use-command-palette.d.ts +37 -0
- package/dist/src/tui/hooks/use-command-palette.d.ts.map +1 -0
- package/dist/src/tui/hooks/use-command-palette.js +108 -0
- package/dist/src/tui/hooks/use-command-palette.js.map +1 -0
- package/dist/src/tui/hooks/use-diff-view.d.ts +16 -0
- package/dist/src/tui/hooks/use-diff-view.d.ts.map +1 -0
- package/dist/src/tui/hooks/use-diff-view.js +75 -0
- package/dist/src/tui/hooks/use-diff-view.js.map +1 -0
- package/dist/src/tui/hooks/use-keyboard.d.ts +3 -0
- package/dist/src/tui/hooks/use-keyboard.d.ts.map +1 -0
- package/dist/src/tui/hooks/use-keyboard.js +70 -0
- package/dist/src/tui/hooks/use-keyboard.js.map +1 -0
- package/dist/src/tui/hooks/use-log-stream.d.ts +25 -0
- package/dist/src/tui/hooks/use-log-stream.d.ts.map +1 -0
- package/dist/src/tui/hooks/use-log-stream.js +83 -0
- package/dist/src/tui/hooks/use-log-stream.js.map +1 -0
- package/dist/src/tui/hooks/use-spinner.d.ts +3 -0
- package/dist/src/tui/hooks/use-spinner.d.ts.map +1 -0
- package/dist/src/tui/hooks/use-spinner.js +13 -0
- package/dist/src/tui/hooks/use-spinner.js.map +1 -0
- package/dist/src/tui/hooks/use-store.d.ts +33 -0
- package/dist/src/tui/hooks/use-store.d.ts.map +1 -0
- package/dist/src/tui/hooks/use-store.js +21 -0
- package/dist/src/tui/hooks/use-store.js.map +1 -0
- package/dist/src/tui/lib/diff-parser.d.ts +24 -0
- package/dist/src/tui/lib/diff-parser.d.ts.map +1 -0
- package/dist/src/tui/lib/diff-parser.js +115 -0
- package/dist/src/tui/lib/diff-parser.js.map +1 -0
- package/dist/src/tui/lib/palette-commands.d.ts +14 -0
- package/dist/src/tui/lib/palette-commands.d.ts.map +1 -0
- package/dist/src/tui/lib/palette-commands.js +101 -0
- package/dist/src/tui/lib/palette-commands.js.map +1 -0
- package/dist/src/tui/tui.d.ts +8 -0
- package/dist/src/tui/tui.d.ts.map +1 -0
- package/dist/src/tui/tui.js +8 -0
- package/dist/src/tui/tui.js.map +1 -0
- package/package.json +66 -0
- package/skills/api-design.md +84 -0
- package/skills/backend-typescript.md +76 -0
- package/skills/data-modeling.md +73 -0
- package/skills/devops-ci.md +82 -0
- package/skills/frontend-design.md +69 -0
- package/skills/observability.md +73 -0
- package/skills/react-nextjs.md +76 -0
- package/skills/refactoring.md +77 -0
- package/skills/security.md +75 -0
- package/skills/testing.md +69 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useState, useEffect, useRef } from 'react';
|
|
2
|
+
export function useStore(getState, intervalMs = 1000) {
|
|
3
|
+
const [state, setState] = useState(getState);
|
|
4
|
+
const snapshotRef = useRef('');
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
// Store initial snapshot
|
|
7
|
+
snapshotRef.current = JSON.stringify(state);
|
|
8
|
+
const timer = setInterval(() => {
|
|
9
|
+
const next = getState();
|
|
10
|
+
const nextSnapshot = JSON.stringify(next);
|
|
11
|
+
// Only trigger re-render when state actually changed
|
|
12
|
+
if (nextSnapshot !== snapshotRef.current) {
|
|
13
|
+
snapshotRef.current = nextSnapshot;
|
|
14
|
+
setState(next);
|
|
15
|
+
}
|
|
16
|
+
}, intervalMs);
|
|
17
|
+
return () => clearInterval(timer);
|
|
18
|
+
}, [getState, intervalMs]);
|
|
19
|
+
return state;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=use-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-store.js","sourceRoot":"","sources":["../../../../src/tui/hooks/use-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAmCpD,MAAM,UAAU,QAAQ,CACtB,QAA0B,EAC1B,UAAU,GAAG,IAAI;IAEjB,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAa,QAAQ,CAAC,CAAC;IACzD,MAAM,WAAW,GAAG,MAAM,CAAS,EAAE,CAAC,CAAC;IAEvC,SAAS,CAAC,GAAG,EAAE;QACb,yBAAyB;QACzB,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAE5C,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;YAC7B,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;YACxB,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAC1C,qDAAqD;YACrD,IAAI,YAAY,KAAK,WAAW,CAAC,OAAO,EAAE,CAAC;gBACzC,WAAW,CAAC,OAAO,GAAG,YAAY,CAAC;gBACnC,QAAQ,CAAC,IAAI,CAAC,CAAC;YACjB,CAAC;QACH,CAAC,EAAE,UAAU,CAAC,CAAC;QACf,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC;IAE3B,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface DiffLine {
|
|
2
|
+
type: 'context' | 'added' | 'removed';
|
|
3
|
+
content: string;
|
|
4
|
+
oldLineNo: number | null;
|
|
5
|
+
newLineNo: number | null;
|
|
6
|
+
}
|
|
7
|
+
export interface DiffHunk {
|
|
8
|
+
header: string;
|
|
9
|
+
oldStart: number;
|
|
10
|
+
oldCount: number;
|
|
11
|
+
newStart: number;
|
|
12
|
+
newCount: number;
|
|
13
|
+
lines: DiffLine[];
|
|
14
|
+
}
|
|
15
|
+
export interface DiffFile {
|
|
16
|
+
oldPath: string;
|
|
17
|
+
newPath: string;
|
|
18
|
+
hunks: DiffHunk[];
|
|
19
|
+
isNew: boolean;
|
|
20
|
+
isDeleted: boolean;
|
|
21
|
+
isBinary: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare function parseDiff(raw: string): DiffFile[];
|
|
24
|
+
//# sourceMappingURL=diff-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-parser.d.ts","sourceRoot":"","sources":["../../../../src/tui/lib/diff-parser.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAwCD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,EAAE,CAkFjD"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// Unified diff parser: converts raw `git diff` output into structured DiffFile[].
|
|
2
|
+
// Regex for unified diff hunk header: @@ -oldStart,oldCount +newStart,newCount @@
|
|
3
|
+
const HUNK_HEADER_RE = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(.*)/;
|
|
4
|
+
function stripGitPrefix(raw) {
|
|
5
|
+
if (raw.startsWith('a/') || raw.startsWith('b/'))
|
|
6
|
+
return raw.slice(2);
|
|
7
|
+
return raw;
|
|
8
|
+
}
|
|
9
|
+
function parseHunk(header, bodyLines) {
|
|
10
|
+
const m = HUNK_HEADER_RE.exec(header);
|
|
11
|
+
if (!m) {
|
|
12
|
+
return { header, oldStart: 0, oldCount: 0, newStart: 0, newCount: 0, lines: [] };
|
|
13
|
+
}
|
|
14
|
+
const oldStart = parseInt(m[1], 10);
|
|
15
|
+
const oldCount = m[2] !== undefined ? parseInt(m[2], 10) : 1;
|
|
16
|
+
const newStart = parseInt(m[3], 10);
|
|
17
|
+
const newCount = m[4] !== undefined ? parseInt(m[4], 10) : 1;
|
|
18
|
+
const contextSuffix = m[5] ?? '';
|
|
19
|
+
const lines = [];
|
|
20
|
+
let oldNo = oldStart;
|
|
21
|
+
let newNo = newStart;
|
|
22
|
+
for (const raw of bodyLines) {
|
|
23
|
+
if (raw.startsWith('+') && !raw.startsWith('+++')) {
|
|
24
|
+
lines.push({ type: 'added', content: raw.slice(1), oldLineNo: null, newLineNo: newNo++ });
|
|
25
|
+
}
|
|
26
|
+
else if (raw.startsWith('-') && !raw.startsWith('---')) {
|
|
27
|
+
lines.push({ type: 'removed', content: raw.slice(1), oldLineNo: oldNo++, newLineNo: null });
|
|
28
|
+
}
|
|
29
|
+
else if (raw.startsWith(' ')) {
|
|
30
|
+
lines.push({ type: 'context', content: raw.slice(1), oldLineNo: oldNo++, newLineNo: newNo++ });
|
|
31
|
+
}
|
|
32
|
+
// Skip '\' and other meta-lines
|
|
33
|
+
}
|
|
34
|
+
return { header: header + contextSuffix, oldStart, oldCount, newStart, newCount, lines };
|
|
35
|
+
}
|
|
36
|
+
export function parseDiff(raw) {
|
|
37
|
+
if (!raw || raw.trim() === '')
|
|
38
|
+
return [];
|
|
39
|
+
const files = [];
|
|
40
|
+
const lines = raw.split('\n');
|
|
41
|
+
let i = 0;
|
|
42
|
+
while (i < lines.length) {
|
|
43
|
+
if (!lines[i].startsWith('diff --git ')) {
|
|
44
|
+
i++;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
// Extract paths from "diff --git a/X b/Y"
|
|
48
|
+
const diffLine = lines[i];
|
|
49
|
+
const gitPathMatch = /^diff --git a\/(.+) b\/(.+)$/.exec(diffLine);
|
|
50
|
+
let oldPath = gitPathMatch ? gitPathMatch[1] : '';
|
|
51
|
+
let newPath = gitPathMatch ? gitPathMatch[2] : '';
|
|
52
|
+
let isNew = false;
|
|
53
|
+
let isDeleted = false;
|
|
54
|
+
let isBinary = false;
|
|
55
|
+
const hunks = [];
|
|
56
|
+
i++;
|
|
57
|
+
// Parse file header block until first hunk or next diff header
|
|
58
|
+
while (i < lines.length && !lines[i].startsWith('diff --git ')) {
|
|
59
|
+
const l = lines[i];
|
|
60
|
+
if (l.startsWith('new file mode')) {
|
|
61
|
+
isNew = true;
|
|
62
|
+
i++;
|
|
63
|
+
}
|
|
64
|
+
else if (l.startsWith('deleted file mode')) {
|
|
65
|
+
isDeleted = true;
|
|
66
|
+
i++;
|
|
67
|
+
}
|
|
68
|
+
else if (l.startsWith('Binary files')) {
|
|
69
|
+
isBinary = true;
|
|
70
|
+
const binM = /^Binary files (.+) and (.+) differ/.exec(l);
|
|
71
|
+
if (binM) {
|
|
72
|
+
oldPath = stripGitPrefix(binM[1]);
|
|
73
|
+
newPath = stripGitPrefix(binM[2]);
|
|
74
|
+
}
|
|
75
|
+
i++;
|
|
76
|
+
}
|
|
77
|
+
else if (l.startsWith('--- ')) {
|
|
78
|
+
const stripped = l.slice(4);
|
|
79
|
+
oldPath = stripped === '/dev/null' ? '/dev/null' : stripGitPrefix(stripped);
|
|
80
|
+
i++;
|
|
81
|
+
}
|
|
82
|
+
else if (l.startsWith('+++ ')) {
|
|
83
|
+
const stripped = l.slice(4);
|
|
84
|
+
newPath = stripped === '/dev/null' ? '/dev/null' : stripGitPrefix(stripped);
|
|
85
|
+
i++;
|
|
86
|
+
}
|
|
87
|
+
else if (HUNK_HEADER_RE.test(l)) {
|
|
88
|
+
const hunkHeader = l;
|
|
89
|
+
i++;
|
|
90
|
+
const hunkBody = [];
|
|
91
|
+
while (i < lines.length &&
|
|
92
|
+
!lines[i].startsWith('diff --git ') &&
|
|
93
|
+
!HUNK_HEADER_RE.test(lines[i])) {
|
|
94
|
+
hunkBody.push(lines[i]);
|
|
95
|
+
i++;
|
|
96
|
+
}
|
|
97
|
+
hunks.push(parseHunk(hunkHeader, hunkBody));
|
|
98
|
+
// Don't increment — outer loop will check for another hunk header
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
i++;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
files.push({
|
|
105
|
+
oldPath: oldPath || newPath,
|
|
106
|
+
newPath: newPath || oldPath,
|
|
107
|
+
hunks,
|
|
108
|
+
isNew,
|
|
109
|
+
isDeleted,
|
|
110
|
+
isBinary,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
return files;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=diff-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-parser.js","sourceRoot":"","sources":["../../../../src/tui/lib/diff-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { KeyAction } from '../hooks/use-keyboard.js';
|
|
2
|
+
export interface PaletteCommand {
|
|
3
|
+
id: string;
|
|
4
|
+
label: string;
|
|
5
|
+
description: string;
|
|
6
|
+
shortcut?: string;
|
|
7
|
+
action: KeyAction;
|
|
8
|
+
}
|
|
9
|
+
export interface PaletteCommandContext {
|
|
10
|
+
hasLogLines: boolean;
|
|
11
|
+
hasLearnings: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare function buildPaletteCommands(ctx: PaletteCommandContext): PaletteCommand[];
|
|
14
|
+
//# sourceMappingURL=palette-commands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"palette-commands.d.ts","sourceRoot":"","sources":["../../../../src/tui/lib/palette-commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAE1D,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,qBAAqB,GAAG,cAAc,EAAE,CAsGjF"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
export function buildPaletteCommands(ctx) {
|
|
2
|
+
const commands = [
|
|
3
|
+
{
|
|
4
|
+
id: 'new-task',
|
|
5
|
+
label: 'New Task',
|
|
6
|
+
description: 'Create a new task',
|
|
7
|
+
shortcut: 'n',
|
|
8
|
+
action: 'new-task',
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
id: 'launch',
|
|
12
|
+
label: 'Launch Agent',
|
|
13
|
+
description: 'Launch agent for selected task',
|
|
14
|
+
shortcut: 'l',
|
|
15
|
+
action: 'launch',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: 'kill',
|
|
19
|
+
label: 'Kill Agent',
|
|
20
|
+
description: 'Kill selected running agent',
|
|
21
|
+
shortcut: 'x',
|
|
22
|
+
action: 'kill',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: 'parallelize',
|
|
26
|
+
label: 'Parallelize Batch',
|
|
27
|
+
description: 'Launch all queued parallel tasks',
|
|
28
|
+
shortcut: '↵',
|
|
29
|
+
action: 'parallelize',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: 'toggle-review',
|
|
33
|
+
label: 'Toggle Review Queue',
|
|
34
|
+
description: 'Show or hide the PR review queue',
|
|
35
|
+
shortcut: 'r',
|
|
36
|
+
action: 'toggle-review',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: 'toggle-feed',
|
|
40
|
+
label: 'Toggle Activity Feed',
|
|
41
|
+
description: 'Show or hide the activity feed',
|
|
42
|
+
shortcut: 'f',
|
|
43
|
+
action: 'toggle-feed',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: 'yolo-toggle',
|
|
47
|
+
label: 'Toggle Auto Mode',
|
|
48
|
+
description: 'Auto-approve all agent actions',
|
|
49
|
+
shortcut: '!',
|
|
50
|
+
action: 'yolo-toggle',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
id: 'factory-toggle',
|
|
54
|
+
label: 'Toggle Factory Mode',
|
|
55
|
+
description: 'Enable continuous task generation',
|
|
56
|
+
shortcut: '@',
|
|
57
|
+
action: 'factory-toggle',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: 'cycle-trust',
|
|
61
|
+
label: 'Cycle Trust Level',
|
|
62
|
+
description: 'Switch trust level: low → medium → high',
|
|
63
|
+
shortcut: 'T',
|
|
64
|
+
action: 'cycle-trust',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
id: 'diff',
|
|
68
|
+
label: 'Diff / Decompose',
|
|
69
|
+
description: 'View worktree diff or decompose selected task',
|
|
70
|
+
shortcut: 'd',
|
|
71
|
+
action: 'diff',
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
id: 'help',
|
|
75
|
+
label: 'Toggle Help',
|
|
76
|
+
description: 'Show or hide keyboard shortcuts reference',
|
|
77
|
+
shortcut: '?',
|
|
78
|
+
action: 'help',
|
|
79
|
+
},
|
|
80
|
+
];
|
|
81
|
+
if (ctx.hasLogLines) {
|
|
82
|
+
commands.push({
|
|
83
|
+
id: 'open-log',
|
|
84
|
+
label: 'Open Log Panel',
|
|
85
|
+
description: 'View streaming agent logs',
|
|
86
|
+
shortcut: 'o',
|
|
87
|
+
action: 'open-log',
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
if (ctx.hasLearnings) {
|
|
91
|
+
commands.push({
|
|
92
|
+
id: 'memory',
|
|
93
|
+
label: 'Memory Viewer',
|
|
94
|
+
description: 'Browse agent learnings and context',
|
|
95
|
+
shortcut: 'm',
|
|
96
|
+
action: 'memory',
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return commands;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=palette-commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"palette-commands.js","sourceRoot":"","sources":["../../../../src/tui/lib/palette-commands.ts"],"names":[],"mappings":"AAeA,MAAM,UAAU,oBAAoB,CAAC,GAA0B;IAC7D,MAAM,QAAQ,GAAqB;QACjC;YACE,EAAE,EAAE,UAAU;YACd,KAAK,EAAE,UAAU;YACjB,WAAW,EAAE,mBAAmB;YAChC,QAAQ,EAAE,GAAG;YACb,MAAM,EAAE,UAAU;SACnB;QACD;YACE,EAAE,EAAE,QAAQ;YACZ,KAAK,EAAE,cAAc;YACrB,WAAW,EAAE,gCAAgC;YAC7C,QAAQ,EAAE,GAAG;YACb,MAAM,EAAE,QAAQ;SACjB;QACD;YACE,EAAE,EAAE,MAAM;YACV,KAAK,EAAE,YAAY;YACnB,WAAW,EAAE,6BAA6B;YAC1C,QAAQ,EAAE,GAAG;YACb,MAAM,EAAE,MAAM;SACf;QACD;YACE,EAAE,EAAE,aAAa;YACjB,KAAK,EAAE,mBAAmB;YAC1B,WAAW,EAAE,kCAAkC;YAC/C,QAAQ,EAAE,GAAG;YACb,MAAM,EAAE,aAAa;SACtB;QACD;YACE,EAAE,EAAE,eAAe;YACnB,KAAK,EAAE,qBAAqB;YAC5B,WAAW,EAAE,kCAAkC;YAC/C,QAAQ,EAAE,GAAG;YACb,MAAM,EAAE,eAAe;SACxB;QACD;YACE,EAAE,EAAE,aAAa;YACjB,KAAK,EAAE,sBAAsB;YAC7B,WAAW,EAAE,gCAAgC;YAC7C,QAAQ,EAAE,GAAG;YACb,MAAM,EAAE,aAAa;SACtB;QACD;YACE,EAAE,EAAE,aAAa;YACjB,KAAK,EAAE,kBAAkB;YACzB,WAAW,EAAE,gCAAgC;YAC7C,QAAQ,EAAE,GAAG;YACb,MAAM,EAAE,aAAa;SACtB;QACD;YACE,EAAE,EAAE,gBAAgB;YACpB,KAAK,EAAE,qBAAqB;YAC5B,WAAW,EAAE,mCAAmC;YAChD,QAAQ,EAAE,GAAG;YACb,MAAM,EAAE,gBAAgB;SACzB;QACD;YACE,EAAE,EAAE,aAAa;YACjB,KAAK,EAAE,mBAAmB;YAC1B,WAAW,EAAE,yCAAyC;YACtD,QAAQ,EAAE,GAAG;YACb,MAAM,EAAE,aAAa;SACtB;QACD;YACE,EAAE,EAAE,MAAM;YACV,KAAK,EAAE,kBAAkB;YACzB,WAAW,EAAE,+CAA+C;YAC5D,QAAQ,EAAE,GAAG;YACb,MAAM,EAAE,MAAM;SACf;QACD;YACE,EAAE,EAAE,MAAM;YACV,KAAK,EAAE,aAAa;YACpB,WAAW,EAAE,2CAA2C;YACxD,QAAQ,EAAE,GAAG;YACb,MAAM,EAAE,MAAM;SACf;KACF,CAAC;IAEF,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;QACpB,QAAQ,CAAC,IAAI,CAAC;YACZ,EAAE,EAAE,UAAU;YACd,KAAK,EAAE,gBAAgB;YACvB,WAAW,EAAE,2BAA2B;YACxC,QAAQ,EAAE,GAAG;YACb,MAAM,EAAE,UAAU;SACnB,CAAC,CAAC;IACL,CAAC;IAED,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;QACrB,QAAQ,CAAC,IAAI,CAAC;YACZ,EAAE,EAAE,QAAQ;YACZ,KAAK,EAAE,eAAe;YACtB,WAAW,EAAE,oCAAoC;YACjD,QAAQ,EAAE,GAAG;YACb,MAAM,EAAE,QAAQ;SACjB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AppProps } from './app.js';
|
|
2
|
+
export type TuiOptions = AppProps;
|
|
3
|
+
export interface TuiInstance {
|
|
4
|
+
waitUntilExit: () => Promise<unknown>;
|
|
5
|
+
unmount: () => void;
|
|
6
|
+
}
|
|
7
|
+
export declare function startTui(options: TuiOptions): TuiInstance;
|
|
8
|
+
//# sourceMappingURL=tui.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../../../src/tui/tui.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;AAElC,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACtC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,WAAW,CAGzD"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { render } from 'ink';
|
|
3
|
+
import { App } from './app.js';
|
|
4
|
+
export function startTui(options) {
|
|
5
|
+
const { waitUntilExit, unmount } = render(_jsx(App, { ...options }));
|
|
6
|
+
return { waitUntilExit, unmount };
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=tui.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui.js","sourceRoot":"","sources":["../../../src/tui/tui.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAU/B,MAAM,UAAU,QAAQ,CAAC,OAAmB;IAC1C,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,KAAC,GAAG,OAAK,OAAO,GAAI,CAAC,CAAC;IAChE,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC;AACpC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "verbolab",
|
|
3
|
+
"version": "0.1.0-alpha.1",
|
|
4
|
+
"description": "Orchestrate multiple AI coding agents with human control",
|
|
5
|
+
"main": "dist/bin/verbo.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"verbo": "./dist/bin/verbo.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist/",
|
|
12
|
+
"skills/",
|
|
13
|
+
"README.md",
|
|
14
|
+
"LICENSE"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"dev": "tsx bin/verbo.ts",
|
|
18
|
+
"test": "vitest run",
|
|
19
|
+
"test:watch": "vitest",
|
|
20
|
+
"build": "tsc",
|
|
21
|
+
"prepublishOnly": "npm run build",
|
|
22
|
+
"postinstall": "echo 'Run: verbo --help'",
|
|
23
|
+
"relay": "tsx relay/index.ts"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"ai",
|
|
27
|
+
"agents",
|
|
28
|
+
"claude",
|
|
29
|
+
"orchestration",
|
|
30
|
+
"cli",
|
|
31
|
+
"developer-tools"
|
|
32
|
+
],
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "https://github.com/franciscomelloc/Verbo-orchestra.git"
|
|
36
|
+
},
|
|
37
|
+
"author": "VerboLab",
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@anthropic-ai/sdk": "^0.80.0",
|
|
41
|
+
"@modelcontextprotocol/sdk": "^1.28.0",
|
|
42
|
+
"@octokit/rest": "^22.0.1",
|
|
43
|
+
"better-sqlite3": "^12.8.0",
|
|
44
|
+
"commander": "^14.0.3",
|
|
45
|
+
"ink": "^6.8.0",
|
|
46
|
+
"ink-text-input": "^6.0.0",
|
|
47
|
+
"minimatch": "^10.2.4",
|
|
48
|
+
"react": "^19.2.4",
|
|
49
|
+
"simple-git": "^3.33.0",
|
|
50
|
+
"smol-toml": "^1.6.1",
|
|
51
|
+
"ulid": "^3.0.2",
|
|
52
|
+
"ws": "^8.20.0",
|
|
53
|
+
"zod": "^4.3.6"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
57
|
+
"@types/minimatch": "^5.1.2",
|
|
58
|
+
"@types/node": "^25.5.0",
|
|
59
|
+
"@types/react": "^19.2.14",
|
|
60
|
+
"@types/ws": "^8.18.1",
|
|
61
|
+
"@vitest/coverage-v8": "^4.1.2",
|
|
62
|
+
"tsx": "^4.21.0",
|
|
63
|
+
"typescript": "^6.0.2",
|
|
64
|
+
"vitest": "^4.1.2"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: api-design
|
|
3
|
+
description: REST maturity, contract-first design, validation, idempotency, error envelopes, versioning
|
|
4
|
+
domain: engineering
|
|
5
|
+
subdomain: api
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# API Design
|
|
9
|
+
|
|
10
|
+
## Context
|
|
11
|
+
You are designing or modifying a REST API — adding endpoints, defining request/response shapes, handling errors, or planning versioning. Apply contract-first design, validate at boundaries, and aim for Richardson Maturity Level 2+.
|
|
12
|
+
|
|
13
|
+
## Core Principles
|
|
14
|
+
|
|
15
|
+
**Richardson Maturity Model** (Richardson & Amundsen, *RESTful Web APIs*): Level 0 — single URI, single verb (RPC tunnel). Level 1 — individual resources (`/tasks/123`). Level 2 — correct HTTP verbs and status codes (GET reads, POST creates, PUT replaces, PATCH updates, DELETE removes). Level 3 — hypermedia controls (HATEOAS). Target Level 2 minimum; add Level 3 links when clients benefit from discoverability.
|
|
16
|
+
|
|
17
|
+
**Contract-First Design** (Zalando, *RESTful API Guidelines*): Define the OpenAPI/JSON Schema before writing implementation code. The schema is the source of truth — generate types and validation from it. Changing the contract is a deliberate decision, not a side effect of refactoring.
|
|
18
|
+
|
|
19
|
+
**Validate at Boundaries** (RFC 7231): Never trust caller input. Parse and validate every request body, query param, and path param at the handler layer using a schema validator (zod, ajv). Internal service code receives already-validated, typed data.
|
|
20
|
+
|
|
21
|
+
**Idempotency Keys for Unsafe Methods**: POST and PATCH are not inherently idempotent. Accept an `Idempotency-Key` header; store the response for that key and replay it on retry. PUT and DELETE are idempotent by definition — no key needed.
|
|
22
|
+
|
|
23
|
+
**Never Break Consumers** (Zalando, *RESTful API Guidelines*): Version via URI prefix (`/v1/`) for public APIs or `Accept` header for internal APIs. Additive changes (new fields, new endpoints) are non-breaking. Removing or renaming fields is breaking — deprecate first, remove in the next major version.
|
|
24
|
+
|
|
25
|
+
## Patterns
|
|
26
|
+
|
|
27
|
+
**Structured error envelope:**
|
|
28
|
+
```typescript
|
|
29
|
+
// Every error response uses this shape
|
|
30
|
+
interface ErrorResponse {
|
|
31
|
+
error: {
|
|
32
|
+
code: string; // machine-readable, e.g. "VALIDATION_FAILED"
|
|
33
|
+
message: string; // human-readable summary
|
|
34
|
+
details?: unknown; // optional field-level errors or context
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
// Usage
|
|
38
|
+
res.status(422).json({
|
|
39
|
+
error: { code: 'VALIDATION_FAILED', message: 'Invalid input', details: issues }
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Idempotency key middleware:**
|
|
44
|
+
```typescript
|
|
45
|
+
async function idempotency(req, res, next) {
|
|
46
|
+
const key = req.headers['idempotency-key'];
|
|
47
|
+
if (!key) return next();
|
|
48
|
+
const cached = await store.get(key);
|
|
49
|
+
if (cached) return res.status(cached.status).json(cached.body);
|
|
50
|
+
res.on('finish', () => store.set(key, { status: res.statusCode, body: res.body }));
|
|
51
|
+
next();
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**Contract-first with zod:**
|
|
56
|
+
```typescript
|
|
57
|
+
// Define schema first — derive type from it
|
|
58
|
+
const CreateTaskBody = z.object({ title: z.string().min(1), priority: z.enum(['p0','p1','p2']) });
|
|
59
|
+
type CreateTaskBody = z.infer<typeof CreateTaskBody>;
|
|
60
|
+
// Validate at handler boundary
|
|
61
|
+
const body = CreateTaskBody.parse(req.body); // throws ZodError → caught by error middleware
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Anti-patterns
|
|
65
|
+
- Tunneling all operations through POST to a single endpoint — stuck at Level 0.
|
|
66
|
+
- Returning `200 OK` with an error body — use correct status codes (4xx for client errors, 5xx for server errors).
|
|
67
|
+
- Validating inside business logic instead of at the handler boundary — mixes concerns.
|
|
68
|
+
- Exposing internal IDs, stack traces, or DB column names in error responses.
|
|
69
|
+
- Versioning by adding `?v=2` query params — use URI prefix or Accept header.
|
|
70
|
+
- Making POST endpoints without idempotency protection — clients that retry create duplicates.
|
|
71
|
+
|
|
72
|
+
## Checklist
|
|
73
|
+
- [ ] Every endpoint uses correct HTTP verb and status code (Level 2+)
|
|
74
|
+
- [ ] Request/response schemas defined before implementation
|
|
75
|
+
- [ ] All input validated with zod/ajv at the handler layer
|
|
76
|
+
- [ ] Error responses follow `{ error: { code, message, details } }` envelope
|
|
77
|
+
- [ ] POST/PATCH endpoints accept `Idempotency-Key` header
|
|
78
|
+
- [ ] No breaking changes to existing consumers — additive only or versioned
|
|
79
|
+
- [ ] No internal details leaked in error responses (stack traces, DB columns)
|
|
80
|
+
|
|
81
|
+
## References
|
|
82
|
+
- *RESTful Web APIs* — Leonard Richardson & Mike Amundsen
|
|
83
|
+
- *RFC 7231: HTTP/1.1 Semantics and Content* — IETF
|
|
84
|
+
- *RESTful API Guidelines* — Zalando
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-typescript
|
|
3
|
+
description: Node.js/TypeScript backend patterns, async, DI, error handling
|
|
4
|
+
domain: engineering
|
|
5
|
+
subdomain: backend
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Backend TypeScript
|
|
9
|
+
|
|
10
|
+
## Context
|
|
11
|
+
You are working on a Node.js/TypeScript backend. Apply Clean Architecture layering, factory-based dependency injection, and structured error handling. Tasks include adding endpoints, business logic, DB queries, or refactoring existing modules.
|
|
12
|
+
|
|
13
|
+
## Core Principles
|
|
14
|
+
|
|
15
|
+
**Dependency Rule** (Martin, *Clean Architecture*): Source code dependencies point inward only — domain logic never imports infrastructure. Inject all I/O through interfaces at the boundary.
|
|
16
|
+
|
|
17
|
+
**Factory Dependency Injection** (Casciaro, *Node.js Design Patterns*): Prefer factory functions (`createX(deps): X`) over classes with `new`. Factories make dependencies explicit and enable easy mocking without class hierarchies.
|
|
18
|
+
|
|
19
|
+
**Typed Error Hierarchy**: Define a base `AppError` class; derive specific errors from it. Callers can `instanceof`-check without parsing strings. Never throw generic `Error` from domain code.
|
|
20
|
+
|
|
21
|
+
**Explicit Contracts**: Every exported function carries explicit return types and input validation via zod at the system boundary — trust nothing from outside, trust everything that passed the boundary.
|
|
22
|
+
|
|
23
|
+
**Graceful Shutdown**: Register `SIGTERM`/`SIGINT` handlers that stop accepting connections, drain in-flight requests, close DB, then `process.exit(0)`. Skipping this causes data loss in containers.
|
|
24
|
+
|
|
25
|
+
## Patterns
|
|
26
|
+
|
|
27
|
+
**Factory DI:**
|
|
28
|
+
```typescript
|
|
29
|
+
// deps interface keeps module testable
|
|
30
|
+
export interface TaskRepoDeps { db: Database }
|
|
31
|
+
export function createTaskRepo(deps: TaskRepoDeps): TaskRepo {
|
|
32
|
+
const insert = deps.db.prepare('INSERT INTO tasks ...');
|
|
33
|
+
return { create: (t) => insert.run(t) };
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**AppError hierarchy:**
|
|
38
|
+
```typescript
|
|
39
|
+
export class AppError extends Error {
|
|
40
|
+
constructor(message: string, public readonly code: string) {
|
|
41
|
+
super(message); this.name = 'AppError';
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export class NotFoundError extends AppError {
|
|
45
|
+
constructor(id: string) { super(`Not found: ${id}`, 'NOT_FOUND'); }
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Graceful shutdown:**
|
|
50
|
+
```typescript
|
|
51
|
+
const shutdown = async () => {
|
|
52
|
+
server.close(() => { db.close(); process.exit(0); });
|
|
53
|
+
};
|
|
54
|
+
process.on('SIGTERM', shutdown);
|
|
55
|
+
process.on('SIGINT', shutdown);
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Anti-patterns
|
|
59
|
+
- Classes with `new` for modules — use factory functions.
|
|
60
|
+
- `any` type — use `unknown` and narrow with guards.
|
|
61
|
+
- Mutable shared state between modules — pass state through DI.
|
|
62
|
+
- `try/catch` that swallows errors silently — always rethrow or return typed error.
|
|
63
|
+
- Domain logic importing DB/HTTP directly — violates Dependency Rule.
|
|
64
|
+
|
|
65
|
+
## Checklist
|
|
66
|
+
- [ ] All exported functions have explicit return types
|
|
67
|
+
- [ ] No `any` types introduced
|
|
68
|
+
- [ ] Factory pattern used for new modules
|
|
69
|
+
- [ ] AppError subclass thrown, not generic Error
|
|
70
|
+
- [ ] No SQL string interpolation
|
|
71
|
+
- [ ] Graceful shutdown handles SIGTERM
|
|
72
|
+
- [ ] Input validated with zod at system boundary
|
|
73
|
+
|
|
74
|
+
## References
|
|
75
|
+
- *Clean Architecture* — Robert C. Martin
|
|
76
|
+
- *Node.js Design Patterns* — Mario Casciaro & Luciano Mammino
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: data-modeling
|
|
3
|
+
description: SQLite schema design, WAL mode, JSON fields, migrations, queries
|
|
4
|
+
domain: engineering
|
|
5
|
+
subdomain: data
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Data Modeling
|
|
9
|
+
|
|
10
|
+
## Context
|
|
11
|
+
You are working with SQLite databases — schema design, queries, indexes, migrations, or data access patterns. Apply normalization deliberately, index for your query patterns, and use WAL mode for concurrent workloads.
|
|
12
|
+
|
|
13
|
+
## Core Principles
|
|
14
|
+
|
|
15
|
+
**Normal Form Decision Tree** (Kleppmann, *Designing Data-Intensive Applications*): 1NF (atomic values, no repeating groups) → 2NF (no partial key dependency) → 3NF (no transitive dependency). Stop at 3NF for OLTP. Denormalize only when profiling confirms a join is a bottleneck — not by anticipation.
|
|
16
|
+
|
|
17
|
+
**Composite Index Column Order** (SQLite Documentation, Hipp): Place equality-filtered columns first, range-filtered columns last. An index on `(status, created_at)` serves `WHERE status = ? AND created_at > ?` perfectly; reversed it cannot use the range efficiently.
|
|
18
|
+
|
|
19
|
+
**N+1 Detection Pattern** (Kleppmann, *Designing Data-Intensive Applications*): If you load a list then fetch related rows in a loop, you have N+1. Fix with a JOIN or a single `WHERE id IN (...)` query. One SQL statement per request, not one per row.
|
|
20
|
+
|
|
21
|
+
**WAL Mode Rationale** (SQLite Documentation, Hipp): WAL (Write-Ahead Log) allows concurrent reads during a write transaction — readers never block writers, writers never block readers. Essential for any multi-process or multi-thread SQLite usage. Enable at connection time: `PRAGMA journal_mode=WAL`.
|
|
22
|
+
|
|
23
|
+
**JSON Column Discipline**: Queryable fields belong in typed columns with indexes. Use JSON only for opaque blobs — configuration objects, metadata, serialized state — where you never filter or sort by inner fields in SQL.
|
|
24
|
+
|
|
25
|
+
## Patterns
|
|
26
|
+
|
|
27
|
+
**Connection initialization:**
|
|
28
|
+
```typescript
|
|
29
|
+
const db = new Database('app.db');
|
|
30
|
+
db.pragma('journal_mode = WAL');
|
|
31
|
+
db.pragma('foreign_keys = ON');
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Composite index for common query pattern:**
|
|
35
|
+
```sql
|
|
36
|
+
-- Query: WHERE status = ? AND created_at > ? ORDER BY created_at
|
|
37
|
+
CREATE INDEX idx_tasks_status_created ON tasks (status, created_at);
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**Fix N+1 with IN clause:**
|
|
41
|
+
```typescript
|
|
42
|
+
// Bad: N+1
|
|
43
|
+
const tasks = db.prepare('SELECT * FROM tasks').all();
|
|
44
|
+
tasks.forEach(t => t.user = db.prepare('SELECT * FROM users WHERE id = ?').get(t.userId));
|
|
45
|
+
|
|
46
|
+
// Good: single query
|
|
47
|
+
const ids = tasks.map(t => t.userId);
|
|
48
|
+
const users = db.prepare(`SELECT * FROM users WHERE id IN (${ids.map(() => '?').join(',')})`).all(...ids);
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Safe JSON field read:**
|
|
52
|
+
```typescript
|
|
53
|
+
const meta = (() => { try { return JSON.parse(row.meta); } catch { return {}; } })();
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Anti-patterns
|
|
57
|
+
- String interpolation in SQL — parameterize everything.
|
|
58
|
+
- Missing indexes on WHERE/JOIN columns — profile first, index what you query.
|
|
59
|
+
- Storing queryable values in JSON columns — they can't be indexed.
|
|
60
|
+
- `DATETIME('now')` in SQL — use application-level ISO 8601 timestamps for portability.
|
|
61
|
+
- Schema changes without migration plan — existing data must satisfy new constraints.
|
|
62
|
+
|
|
63
|
+
## Checklist
|
|
64
|
+
- [ ] WAL mode and foreign keys enabled at connection init
|
|
65
|
+
- [ ] Composite indexes ordered: equality columns first, range last
|
|
66
|
+
- [ ] No N+1 queries: lists use JOIN or IN clause
|
|
67
|
+
- [ ] JSON fields parsed with try/catch fallback
|
|
68
|
+
- [ ] All queries use prepared statements with named parameters
|
|
69
|
+
- [ ] Timestamps are ISO 8601 strings from application code
|
|
70
|
+
|
|
71
|
+
## References
|
|
72
|
+
- *Designing Data-Intensive Applications* — Martin Kleppmann
|
|
73
|
+
- *SQLite Documentation* — D. Richard Hipp
|