@bosun-sh/logbook 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +139 -0
- package/README.md +252 -272
- package/bin/logbook.cjs +18 -0
- package/dist/context/attachments.d.ts +55 -0
- package/dist/context/attachments.d.ts.map +1 -0
- package/dist/context/attachments.js +329 -0
- package/dist/context/attachments.js.map +1 -0
- package/dist/context/create.d.ts +31 -0
- package/dist/context/create.d.ts.map +1 -0
- package/dist/context/create.js +101 -0
- package/dist/context/create.js.map +1 -0
- package/dist/context/delete.d.ts +20 -0
- package/dist/context/delete.d.ts.map +1 -0
- package/dist/context/delete.js +55 -0
- package/dist/context/delete.js.map +1 -0
- package/dist/context/get.d.ts +20 -0
- package/dist/context/get.d.ts.map +1 -0
- package/dist/context/get.js +55 -0
- package/dist/context/get.js.map +1 -0
- package/dist/context/list.d.ts +30 -0
- package/dist/context/list.d.ts.map +1 -0
- package/dist/context/list.js +172 -0
- package/dist/context/list.js.map +1 -0
- package/dist/context/schema.d.ts +156 -0
- package/dist/context/schema.d.ts.map +1 -0
- package/dist/context/schema.js +34 -0
- package/dist/context/schema.js.map +1 -0
- package/dist/context/search.d.ts +27 -0
- package/dist/context/search.d.ts.map +1 -0
- package/dist/context/search.js +266 -0
- package/dist/context/search.js.map +1 -0
- package/dist/context/topics.d.ts +4 -0
- package/dist/context/topics.d.ts.map +1 -0
- package/dist/context/topics.js +54 -0
- package/dist/context/topics.js.map +1 -0
- package/dist/context/update.d.ts +29 -0
- package/dist/context/update.d.ts.map +1 -0
- package/dist/context/update.js +134 -0
- package/dist/context/update.js.map +1 -0
- package/dist/epic/cascade-delete.d.ts +30 -0
- package/dist/epic/cascade-delete.d.ts.map +1 -0
- package/dist/epic/cascade-delete.js +173 -0
- package/dist/epic/cascade-delete.js.map +1 -0
- package/dist/epic/create.d.ts +24 -0
- package/dist/epic/create.d.ts.map +1 -0
- package/dist/epic/create.js +54 -0
- package/dist/epic/create.js.map +1 -0
- package/dist/epic/delete.d.ts +21 -0
- package/dist/epic/delete.d.ts.map +1 -0
- package/dist/epic/delete.js +42 -0
- package/dist/epic/delete.js.map +1 -0
- package/dist/epic/get.d.ts +19 -0
- package/dist/epic/get.d.ts.map +1 -0
- package/dist/epic/get.js +31 -0
- package/dist/epic/get.js.map +1 -0
- package/dist/epic/list.d.ts +25 -0
- package/dist/epic/list.d.ts.map +1 -0
- package/dist/epic/list.js +114 -0
- package/dist/epic/list.js.map +1 -0
- package/dist/epic/rules.d.ts +34 -0
- package/dist/epic/rules.d.ts.map +1 -0
- package/dist/epic/rules.js +127 -0
- package/dist/epic/rules.js.map +1 -0
- package/dist/epic/schema.d.ts +85 -0
- package/dist/epic/schema.d.ts.map +1 -0
- package/dist/epic/schema.js +14 -0
- package/dist/epic/schema.js.map +1 -0
- package/dist/epic/update.d.ts +25 -0
- package/dist/epic/update.d.ts.map +1 -0
- package/dist/epic/update.js +69 -0
- package/dist/epic/update.js.map +1 -0
- package/dist/hook/list.d.ts +71 -0
- package/dist/hook/list.d.ts.map +1 -0
- package/dist/hook/list.js +364 -0
- package/dist/hook/list.js.map +1 -0
- package/dist/hook/ports.d.ts +16 -0
- package/dist/hook/ports.d.ts.map +1 -0
- package/dist/hook/ports.js +3 -0
- package/dist/hook/ports.js.map +1 -0
- package/dist/hook/run.d.ts +24 -0
- package/dist/hook/run.d.ts.map +1 -0
- package/dist/hook/run.js +185 -0
- package/dist/hook/run.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin/hook-tools.d.ts +8 -0
- package/dist/plugin/hook-tools.d.ts.map +1 -0
- package/dist/plugin/hook-tools.js +31 -0
- package/dist/plugin/hook-tools.js.map +1 -0
- package/dist/plugin/linear-pull-tool.d.ts +20 -0
- package/dist/plugin/linear-pull-tool.d.ts.map +1 -0
- package/dist/plugin/linear-pull-tool.js +19 -0
- package/dist/plugin/linear-pull-tool.js.map +1 -0
- package/dist/plugin/linear-push-tool.d.ts +20 -0
- package/dist/plugin/linear-push-tool.d.ts.map +1 -0
- package/dist/plugin/linear-push-tool.js +27 -0
- package/dist/plugin/linear-push-tool.js.map +1 -0
- package/dist/plugin/linear-setup-tool.d.ts +2 -0
- package/dist/plugin/linear-setup-tool.d.ts.map +1 -0
- package/dist/plugin/linear-setup-tool.js +22 -0
- package/dist/plugin/linear-setup-tool.js.map +1 -0
- package/dist/plugin/linear-status-tool.d.ts +10 -0
- package/dist/plugin/linear-status-tool.d.ts.map +1 -0
- package/dist/plugin/linear-status-tool.js +10 -0
- package/dist/plugin/linear-status-tool.js.map +1 -0
- package/dist/plugin/list.d.ts +15 -0
- package/dist/plugin/list.d.ts.map +1 -0
- package/dist/plugin/list.js +87 -0
- package/dist/plugin/list.js.map +1 -0
- package/dist/plugin/public-schemas.d.ts +42 -0
- package/dist/plugin/public-schemas.d.ts.map +1 -0
- package/dist/plugin/public-schemas.js +577 -0
- package/dist/plugin/public-schemas.js.map +1 -0
- package/dist/plugin/registry.d.ts +3 -0
- package/dist/plugin/registry.d.ts.map +1 -0
- package/dist/plugin/registry.js +3 -0
- package/dist/plugin/registry.js.map +1 -0
- package/dist/plugin/results.d.ts +8 -0
- package/dist/plugin/results.d.ts.map +1 -0
- package/dist/plugin/results.js +114 -0
- package/dist/plugin/results.js.map +1 -0
- package/dist/plugin/sync-conflict-tools.d.ts +2 -0
- package/dist/plugin/sync-conflict-tools.d.ts.map +1 -0
- package/dist/plugin/sync-conflict-tools.js +5 -0
- package/dist/plugin/sync-conflict-tools.js.map +1 -0
- package/dist/plugin/tool-registry.d.ts +23 -0
- package/dist/plugin/tool-registry.d.ts.map +1 -0
- package/dist/plugin/tool-registry.js +251 -0
- package/dist/plugin/tool-registry.js.map +1 -0
- package/dist/plugin/workspace-init-tool.d.ts +2 -0
- package/dist/plugin/workspace-init-tool.d.ts.map +1 -0
- package/dist/plugin/workspace-init-tool.js +16 -0
- package/dist/plugin/workspace-init-tool.js.map +1 -0
- package/dist/plugin/workspace-status-tool.d.ts +2 -0
- package/dist/plugin/workspace-status-tool.d.ts.map +1 -0
- package/dist/plugin/workspace-status-tool.js +15 -0
- package/dist/plugin/workspace-status-tool.js.map +1 -0
- package/dist/shared/ids.d.ts +3 -0
- package/dist/shared/ids.d.ts.map +1 -0
- package/dist/shared/ids.js +15 -0
- package/dist/shared/ids.js.map +1 -0
- package/dist/shared/pagination.d.ts +19 -0
- package/dist/shared/pagination.d.ts.map +1 -0
- package/dist/shared/pagination.js +110 -0
- package/dist/shared/pagination.js.map +1 -0
- package/dist/shared/result.d.ts +20 -0
- package/dist/shared/result.d.ts.map +1 -0
- package/dist/shared/result.js +6 -0
- package/dist/shared/result.js.map +1 -0
- package/dist/shared/schema/value-objects.d.ts +363 -0
- package/dist/shared/schema/value-objects.d.ts.map +1 -0
- package/dist/shared/schema/value-objects.js +112 -0
- package/dist/shared/schema/value-objects.js.map +1 -0
- package/dist/shared/storage/atomic-write.d.ts +25 -0
- package/dist/shared/storage/atomic-write.d.ts.map +1 -0
- package/dist/shared/storage/atomic-write.js +71 -0
- package/dist/shared/storage/atomic-write.js.map +1 -0
- package/dist/shared/storage/jsonl-repository.d.ts +85 -0
- package/dist/shared/storage/jsonl-repository.d.ts.map +1 -0
- package/dist/shared/storage/jsonl-repository.js +278 -0
- package/dist/shared/storage/jsonl-repository.js.map +1 -0
- package/dist/shared/storage/transaction.d.ts +3 -0
- package/dist/shared/storage/transaction.d.ts.map +1 -0
- package/dist/shared/storage/transaction.js +22 -0
- package/dist/shared/storage/transaction.js.map +1 -0
- package/dist/shared/time.d.ts +3 -0
- package/dist/shared/time.d.ts.map +1 -0
- package/dist/shared/time.js +3 -0
- package/dist/shared/time.js.map +1 -0
- package/dist/story/cascade-delete.d.ts +22 -0
- package/dist/story/cascade-delete.d.ts.map +1 -0
- package/dist/story/cascade-delete.js +117 -0
- package/dist/story/cascade-delete.js.map +1 -0
- package/dist/story/create.d.ts +30 -0
- package/dist/story/create.d.ts.map +1 -0
- package/dist/story/create.js +69 -0
- package/dist/story/create.js.map +1 -0
- package/dist/story/delete.d.ts +21 -0
- package/dist/story/delete.d.ts.map +1 -0
- package/dist/story/delete.js +42 -0
- package/dist/story/delete.js.map +1 -0
- package/dist/story/get.d.ts +19 -0
- package/dist/story/get.d.ts.map +1 -0
- package/dist/story/get.js +31 -0
- package/dist/story/get.js.map +1 -0
- package/dist/story/hierarchy.d.ts +20 -0
- package/dist/story/hierarchy.d.ts.map +1 -0
- package/dist/story/hierarchy.js +30 -0
- package/dist/story/hierarchy.js.map +1 -0
- package/dist/story/list.d.ts +25 -0
- package/dist/story/list.d.ts.map +1 -0
- package/dist/story/list.js +118 -0
- package/dist/story/list.js.map +1 -0
- package/dist/story/rules.d.ts +34 -0
- package/dist/story/rules.d.ts.map +1 -0
- package/dist/story/rules.js +100 -0
- package/dist/story/rules.js.map +1 -0
- package/dist/story/schema.d.ts +65 -0
- package/dist/story/schema.d.ts.map +1 -0
- package/dist/story/schema.js +14 -0
- package/dist/story/schema.js.map +1 -0
- package/dist/story/update.d.ts +23 -0
- package/dist/story/update.d.ts.map +1 -0
- package/dist/story/update.js +67 -0
- package/dist/story/update.js.map +1 -0
- package/dist/sync/base-snapshot.d.ts +38 -0
- package/dist/sync/base-snapshot.d.ts.map +1 -0
- package/dist/sync/base-snapshot.js +86 -0
- package/dist/sync/base-snapshot.js.map +1 -0
- package/dist/sync/conflict-tools.d.ts +75 -0
- package/dist/sync/conflict-tools.d.ts.map +1 -0
- package/dist/sync/conflict-tools.js +53 -0
- package/dist/sync/conflict-tools.js.map +1 -0
- package/dist/sync/conflicts.d.ts +201 -0
- package/dist/sync/conflicts.d.ts.map +1 -0
- package/dist/sync/conflicts.js +526 -0
- package/dist/sync/conflicts.js.map +1 -0
- package/dist/sync/deferred-providers.d.ts +2 -0
- package/dist/sync/deferred-providers.d.ts.map +1 -0
- package/dist/sync/deferred-providers.js +6 -0
- package/dist/sync/deferred-providers.js.map +1 -0
- package/dist/sync/events.d.ts +401 -0
- package/dist/sync/events.d.ts.map +1 -0
- package/dist/sync/events.js +357 -0
- package/dist/sync/events.js.map +1 -0
- package/dist/sync/external-links.d.ts +154 -0
- package/dist/sync/external-links.d.ts.map +1 -0
- package/dist/sync/external-links.js +306 -0
- package/dist/sync/external-links.js.map +1 -0
- package/dist/sync/linear/config.d.ts +60 -0
- package/dist/sync/linear/config.d.ts.map +1 -0
- package/dist/sync/linear/config.js +302 -0
- package/dist/sync/linear/config.js.map +1 -0
- package/dist/sync/linear/mapping.d.ts +115 -0
- package/dist/sync/linear/mapping.d.ts.map +1 -0
- package/dist/sync/linear/mapping.js +159 -0
- package/dist/sync/linear/mapping.js.map +1 -0
- package/dist/sync/linear/pull.d.ts +33 -0
- package/dist/sync/linear/pull.d.ts.map +1 -0
- package/dist/sync/linear/pull.js +376 -0
- package/dist/sync/linear/pull.js.map +1 -0
- package/dist/sync/linear/push.d.ts +34 -0
- package/dist/sync/linear/push.d.ts.map +1 -0
- package/dist/sync/linear/push.js +681 -0
- package/dist/sync/linear/push.js.map +1 -0
- package/dist/sync/linear/setup.d.ts +33 -0
- package/dist/sync/linear/setup.d.ts.map +1 -0
- package/dist/sync/linear/setup.js +129 -0
- package/dist/sync/linear/setup.js.map +1 -0
- package/dist/sync/linear/status.d.ts +35 -0
- package/dist/sync/linear/status.d.ts.map +1 -0
- package/dist/sync/linear/status.js +138 -0
- package/dist/sync/linear/status.js.map +1 -0
- package/dist/sync/linear/transport.d.ts +47 -0
- package/dist/sync/linear/transport.d.ts.map +1 -0
- package/dist/sync/linear/transport.js +249 -0
- package/dist/sync/linear/transport.js.map +1 -0
- package/dist/sync/provider-port.d.ts +81 -0
- package/dist/sync/provider-port.d.ts.map +1 -0
- package/dist/sync/provider-port.js +16 -0
- package/dist/sync/provider-port.js.map +1 -0
- package/dist/sync/provider-registry.d.ts +38 -0
- package/dist/sync/provider-registry.d.ts.map +1 -0
- package/dist/sync/provider-registry.js +115 -0
- package/dist/sync/provider-registry.js.map +1 -0
- package/dist/sync/schema.d.ts +147 -0
- package/dist/sync/schema.d.ts.map +1 -0
- package/dist/sync/schema.js +28 -0
- package/dist/sync/schema.js.map +1 -0
- package/dist/task/comments.d.ts +9 -0
- package/dist/task/comments.d.ts.map +1 -0
- package/dist/task/comments.js +79 -0
- package/dist/task/comments.js.map +1 -0
- package/dist/task/create.d.ts +34 -0
- package/dist/task/create.d.ts.map +1 -0
- package/dist/task/create.js +126 -0
- package/dist/task/create.js.map +1 -0
- package/dist/task/current.d.ts +18 -0
- package/dist/task/current.d.ts.map +1 -0
- package/dist/task/current.js +105 -0
- package/dist/task/current.js.map +1 -0
- package/dist/task/edit.d.ts +22 -0
- package/dist/task/edit.d.ts.map +1 -0
- package/dist/task/edit.js +105 -0
- package/dist/task/edit.js.map +1 -0
- package/dist/task/estimate.d.ts +20 -0
- package/dist/task/estimate.d.ts.map +1 -0
- package/dist/task/estimate.js +141 -0
- package/dist/task/estimate.js.map +1 -0
- package/dist/task/get.d.ts +13 -0
- package/dist/task/get.d.ts.map +1 -0
- package/dist/task/get.js +29 -0
- package/dist/task/get.js.map +1 -0
- package/dist/task/hierarchy.d.ts +18 -0
- package/dist/task/hierarchy.d.ts.map +1 -0
- package/dist/task/hierarchy.js +56 -0
- package/dist/task/hierarchy.js.map +1 -0
- package/dist/task/lifecycle.d.ts +14 -0
- package/dist/task/lifecycle.d.ts.map +1 -0
- package/dist/task/lifecycle.js +80 -0
- package/dist/task/lifecycle.js.map +1 -0
- package/dist/task/list.d.ts +24 -0
- package/dist/task/list.d.ts.map +1 -0
- package/dist/task/list.js +116 -0
- package/dist/task/list.js.map +1 -0
- package/dist/task/model-assignment.d.ts +33 -0
- package/dist/task/model-assignment.d.ts.map +1 -0
- package/dist/task/model-assignment.js +145 -0
- package/dist/task/model-assignment.js.map +1 -0
- package/dist/task/ordering.d.ts +4 -0
- package/dist/task/ordering.d.ts.map +1 -0
- package/dist/task/ordering.js +14 -0
- package/dist/task/ordering.js.map +1 -0
- package/dist/task/ports.d.ts +37 -0
- package/dist/task/ports.d.ts.map +1 -0
- package/dist/task/ports.js +3 -0
- package/dist/task/ports.js.map +1 -0
- package/dist/task/schema.d.ts +447 -0
- package/dist/task/schema.d.ts.map +1 -0
- package/dist/task/schema.js +35 -0
- package/dist/task/schema.js.map +1 -0
- package/dist/task/session-assignment.d.ts +23 -0
- package/dist/task/session-assignment.d.ts.map +1 -0
- package/dist/task/session-assignment.js +197 -0
- package/dist/task/session-assignment.js.map +1 -0
- package/dist/task/session-registry.d.ts +8 -0
- package/dist/task/session-registry.d.ts.map +1 -0
- package/dist/task/session-registry.js +3 -0
- package/dist/task/session-registry.js.map +1 -0
- package/dist/task/update.d.ts +23 -0
- package/dist/task/update.d.ts.map +1 -0
- package/dist/task/update.js +92 -0
- package/dist/task/update.js.map +1 -0
- package/dist/task/v1-compat.d.ts +94 -0
- package/dist/task/v1-compat.d.ts.map +1 -0
- package/dist/task/v1-compat.js +181 -0
- package/dist/task/v1-compat.js.map +1 -0
- package/dist/workspace/bin-cli.d.ts +2 -0
- package/dist/workspace/bin-cli.d.ts.map +1 -0
- package/dist/workspace/bin-cli.js +36 -0
- package/dist/workspace/bin-cli.js.map +1 -0
- package/dist/workspace/cli-adapter.d.ts +16 -0
- package/dist/workspace/cli-adapter.d.ts.map +1 -0
- package/dist/workspace/cli-adapter.js +229 -0
- package/dist/workspace/cli-adapter.js.map +1 -0
- package/dist/workspace/cli-commands.d.ts +11 -0
- package/dist/workspace/cli-commands.d.ts.map +1 -0
- package/dist/workspace/cli-commands.js +12 -0
- package/dist/workspace/cli-commands.js.map +1 -0
- package/dist/workspace/duckdb-index.d.ts +56 -0
- package/dist/workspace/duckdb-index.d.ts.map +1 -0
- package/dist/workspace/duckdb-index.js +178 -0
- package/dist/workspace/duckdb-index.js.map +1 -0
- package/dist/workspace/hook-templates/need-info-notify/config.json +10 -0
- package/dist/workspace/hook-templates/need-info-notify/script.mjs +68 -0
- package/dist/workspace/hook-templates/review-spawn/config.json +10 -0
- package/dist/workspace/hook-templates/review-spawn/script.mjs +100 -0
- package/dist/workspace/init-onboarding.d.ts +9 -0
- package/dist/workspace/init-onboarding.d.ts.map +1 -0
- package/dist/workspace/init-onboarding.js +259 -0
- package/dist/workspace/init-onboarding.js.map +1 -0
- package/dist/workspace/init.d.ts +20 -0
- package/dist/workspace/init.d.ts.map +1 -0
- package/dist/workspace/init.js +288 -0
- package/dist/workspace/init.js.map +1 -0
- package/dist/workspace/layers.d.ts +127 -0
- package/dist/workspace/layers.d.ts.map +1 -0
- package/dist/workspace/layers.js +50 -0
- package/dist/workspace/layers.js.map +1 -0
- package/dist/workspace/mcp-server.d.ts +28 -0
- package/dist/workspace/mcp-server.d.ts.map +1 -0
- package/dist/workspace/mcp-server.js +190 -0
- package/dist/workspace/mcp-server.js.map +1 -0
- package/dist/workspace/mcp-stdio.d.ts +2 -0
- package/dist/workspace/mcp-stdio.d.ts.map +1 -0
- package/dist/workspace/mcp-stdio.js +66 -0
- package/dist/workspace/mcp-stdio.js.map +1 -0
- package/dist/workspace/mcp-tools.d.ts +24 -0
- package/dist/workspace/mcp-tools.d.ts.map +1 -0
- package/dist/workspace/mcp-tools.js +43 -0
- package/dist/workspace/mcp-tools.js.map +1 -0
- package/dist/workspace/migrate-v1.d.ts +12 -0
- package/dist/workspace/migrate-v1.d.ts.map +1 -0
- package/dist/workspace/migrate-v1.js +301 -0
- package/dist/workspace/migrate-v1.js.map +1 -0
- package/dist/workspace/ohtools-app.d.ts +3 -0
- package/dist/workspace/ohtools-app.d.ts.map +1 -0
- package/dist/workspace/ohtools-app.js +10 -0
- package/dist/workspace/ohtools-app.js.map +1 -0
- package/dist/workspace/repositories.d.ts +25 -0
- package/dist/workspace/repositories.d.ts.map +1 -0
- package/dist/workspace/repositories.js +76 -0
- package/dist/workspace/repositories.js.map +1 -0
- package/dist/workspace/runtime.d.ts +123 -0
- package/dist/workspace/runtime.d.ts.map +1 -0
- package/dist/workspace/runtime.js +4 -0
- package/dist/workspace/runtime.js.map +1 -0
- package/dist/workspace/session-liveness.d.ts +6 -0
- package/dist/workspace/session-liveness.d.ts.map +1 -0
- package/dist/workspace/session-liveness.js +3 -0
- package/dist/workspace/session-liveness.js.map +1 -0
- package/dist/workspace/status.d.ts +46 -0
- package/dist/workspace/status.d.ts.map +1 -0
- package/dist/workspace/status.js +345 -0
- package/dist/workspace/status.js.map +1 -0
- package/dist/workspace/storage-layout.d.ts +19 -0
- package/dist/workspace/storage-layout.d.ts.map +1 -0
- package/dist/workspace/storage-layout.js +55 -0
- package/dist/workspace/storage-layout.js.map +1 -0
- package/dist/workspace/storage-paths.d.ts +16 -0
- package/dist/workspace/storage-paths.d.ts.map +1 -0
- package/dist/workspace/storage-paths.js +15 -0
- package/dist/workspace/storage-paths.js.map +1 -0
- package/dist/workspace/v1-cli-aliases.d.ts +18 -0
- package/dist/workspace/v1-cli-aliases.d.ts.map +1 -0
- package/dist/workspace/v1-cli-aliases.js +223 -0
- package/dist/workspace/v1-cli-aliases.js.map +1 -0
- package/dist/workspace/v1-cli-task.d.ts +2 -0
- package/dist/workspace/v1-cli-task.d.ts.map +1 -0
- package/dist/workspace/v1-cli-task.js +53 -0
- package/dist/workspace/v1-cli-task.js.map +1 -0
- package/package.json +29 -12
- package/quickstart.md +163 -0
- package/hooks/need-info-notify/config.yml +0 -3
- package/hooks/need-info-notify/script.ts +0 -69
- package/hooks/review-spawn/config.yml +0 -3
- package/hooks/review-spawn/script.ts +0 -96
- package/src/cli/init.ts +0 -90
- package/src/domain/fibonacci.ts +0 -39
- package/src/domain/kTokens.ts +0 -65
- package/src/domain/status-machine.ts +0 -49
- package/src/domain/types.ts +0 -66
- package/src/hook/hook-executor.ts +0 -70
- package/src/hook/ports.ts +0 -16
- package/src/infra/hook-config-loader.ts +0 -111
- package/src/infra/jsonl-task-repository.ts +0 -157
- package/src/infra/logger.ts +0 -40
- package/src/infra/pid-session-registry.ts +0 -67
- package/src/mcp/error-codes.ts +0 -213
- package/src/mcp/server.ts +0 -413
- package/src/mcp/session.ts +0 -1
- package/src/mcp/tool-create-task.ts +0 -28
- package/src/mcp/tool-current-task.ts +0 -19
- package/src/mcp/tool-edit-task.ts +0 -40
- package/src/mcp/tool-list-tasks.ts +0 -34
- package/src/mcp/tool-update-task.ts +0 -55
- package/src/task/create-task.ts +0 -67
- package/src/task/current-task.ts +0 -111
- package/src/task/edit-task.ts +0 -59
- package/src/task/list-tasks.ts +0 -35
- package/src/task/ports.ts +0 -15
- package/src/task/session-registry.ts +0 -9
- package/src/task/update-task.ts +0 -160
package/src/mcp/server.ts
DELETED
|
@@ -1,413 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
import { createInterface } from "node:readline"
|
|
3
|
-
import { Effect, Layer } from "effect"
|
|
4
|
-
import { runInit } from "../cli/init.js"
|
|
5
|
-
import { executeHooks } from "../hook/hook-executor.js"
|
|
6
|
-
import type { HookEvent } from "../hook/ports.js"
|
|
7
|
-
import { HookRunner } from "../hook/ports.js"
|
|
8
|
-
import { loadHookConfigs } from "../infra/hook-config-loader.js"
|
|
9
|
-
import { JsonlTaskRepository } from "../infra/jsonl-task-repository.js"
|
|
10
|
-
import { PidSessionRegistry } from "../infra/pid-session-registry.js"
|
|
11
|
-
import { TaskRepository } from "../task/ports.js"
|
|
12
|
-
import { SessionRegistry } from "../task/session-registry.js"
|
|
13
|
-
import { taskErrorToMcpError } from "./error-codes.js"
|
|
14
|
-
import { newSessionId } from "./session.js"
|
|
15
|
-
import { toolCreateTask } from "./tool-create-task.js"
|
|
16
|
-
import { toolCurrentTask } from "./tool-current-task.js"
|
|
17
|
-
import { toolEditTask } from "./tool-edit-task.js"
|
|
18
|
-
import { toolListTasks } from "./tool-list-tasks.js"
|
|
19
|
-
import { toolUpdateTask } from "./tool-update-task.js"
|
|
20
|
-
|
|
21
|
-
// ---------------------------------------------------------------------------
|
|
22
|
-
// JSON-RPC 2.0 types
|
|
23
|
-
// ---------------------------------------------------------------------------
|
|
24
|
-
|
|
25
|
-
interface JsonRpcRequest {
|
|
26
|
-
jsonrpc: "2.0"
|
|
27
|
-
id?: string | number | null
|
|
28
|
-
method: string
|
|
29
|
-
params?: unknown
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
interface JsonRpcSuccess {
|
|
33
|
-
jsonrpc: "2.0"
|
|
34
|
-
id: string | number | null
|
|
35
|
-
result: unknown
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
interface JsonRpcError {
|
|
39
|
-
jsonrpc: "2.0"
|
|
40
|
-
id: string | number | null
|
|
41
|
-
error: {
|
|
42
|
-
code: number
|
|
43
|
-
message: string
|
|
44
|
-
data?: unknown
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
type JsonRpcResponse = JsonRpcSuccess | JsonRpcError
|
|
49
|
-
|
|
50
|
-
// ---------------------------------------------------------------------------
|
|
51
|
-
// Response helpers (pure)
|
|
52
|
-
// ---------------------------------------------------------------------------
|
|
53
|
-
|
|
54
|
-
const successResponse = (id: string | number | null, result: unknown): JsonRpcSuccess => ({
|
|
55
|
-
jsonrpc: "2.0",
|
|
56
|
-
id,
|
|
57
|
-
result,
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
const errorResponse = (
|
|
61
|
-
id: string | number | null,
|
|
62
|
-
code: number,
|
|
63
|
-
message: string,
|
|
64
|
-
data?: unknown
|
|
65
|
-
): JsonRpcError => ({
|
|
66
|
-
jsonrpc: "2.0",
|
|
67
|
-
id,
|
|
68
|
-
error: data !== undefined ? { code, message, data } : { code, message },
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
const parseError = (id: string | number | null): JsonRpcError =>
|
|
72
|
-
errorResponse(id, -32700, "Parse error")
|
|
73
|
-
const methodNotFound = (id: string | number | null, method: string): JsonRpcError =>
|
|
74
|
-
errorResponse(id, -32601, `Method not found: ${method}`)
|
|
75
|
-
const internalError = (id: string | number | null, message: string): JsonRpcError =>
|
|
76
|
-
errorResponse(id, -32603, message)
|
|
77
|
-
|
|
78
|
-
// ---------------------------------------------------------------------------
|
|
79
|
-
// Agent instructions injected into the MCP initialize response
|
|
80
|
-
// ---------------------------------------------------------------------------
|
|
81
|
-
|
|
82
|
-
const AGENT_INSTRUCTIONS = `\
|
|
83
|
-
You are connected to the logbook MCP server. You MUST use it to track all tasks in this session.
|
|
84
|
-
|
|
85
|
-
## Session start
|
|
86
|
-
Call \`current_task\` immediately. If it returns \`no_current_task\`, pick a task from \`list_tasks\` with status \`todo\` and move it to \`in_progress\`, or create a new one with \`create_task\` then advance it: backlog → todo → in_progress.
|
|
87
|
-
|
|
88
|
-
## Task lifecycle
|
|
89
|
-
backlog → todo → in_progress → pending_review → done
|
|
90
|
-
Side-exits from in_progress: → need_info (awaiting clarification) or → blocked (external dependency). Return to in_progress once resolved.
|
|
91
|
-
Always attach a comment when moving to pending_review.
|
|
92
|
-
|
|
93
|
-
## Model selection when spawning sub-agents
|
|
94
|
-
Base the choice on the \`predictedKTokens\` you set at task creation:
|
|
95
|
-
|
|
96
|
-
| predictedKTokens | model | use for |
|
|
97
|
-
|------------------|----------------------------|----------------------------------|
|
|
98
|
-
| ≤ 5 | claude-haiku-4-5-20251001 | rote / mechanical tasks |
|
|
99
|
-
| 6 – 15 | claude-sonnet-4-6 | moderate complexity |
|
|
100
|
-
| 16+ | claude-sonnet-4-6 | large but well-scoped tasks |
|
|
101
|
-
|
|
102
|
-
Override to \`claude-opus-4-6\` regardless of size when the task involves: architectural design, security analysis, creative problem-solving, or complex multi-step reasoning.`
|
|
103
|
-
|
|
104
|
-
// ---------------------------------------------------------------------------
|
|
105
|
-
// MCP tools manifest (static, derived from Zod schemas in each tool file)
|
|
106
|
-
// ---------------------------------------------------------------------------
|
|
107
|
-
|
|
108
|
-
const STATUS_ENUM = [
|
|
109
|
-
"backlog",
|
|
110
|
-
"todo",
|
|
111
|
-
"need_info",
|
|
112
|
-
"blocked",
|
|
113
|
-
"in_progress",
|
|
114
|
-
"pending_review",
|
|
115
|
-
"done",
|
|
116
|
-
]
|
|
117
|
-
|
|
118
|
-
const TOOLS_LIST = [
|
|
119
|
-
{
|
|
120
|
-
name: "list_tasks",
|
|
121
|
-
description: "List tasks, optionally filtered by status. Defaults to in_progress.",
|
|
122
|
-
inputSchema: {
|
|
123
|
-
type: "object",
|
|
124
|
-
properties: {
|
|
125
|
-
status: {
|
|
126
|
-
oneOf: [
|
|
127
|
-
{ type: "string", enum: STATUS_ENUM },
|
|
128
|
-
{ type: "string", enum: ["*"] },
|
|
129
|
-
],
|
|
130
|
-
description: "Status filter. Use '*' for all tasks. Defaults to 'in_progress'.",
|
|
131
|
-
},
|
|
132
|
-
},
|
|
133
|
-
},
|
|
134
|
-
},
|
|
135
|
-
{
|
|
136
|
-
name: "current_task",
|
|
137
|
-
description:
|
|
138
|
-
"Return the highest-priority in_progress task for this session. Call this at session start before doing any work.",
|
|
139
|
-
inputSchema: { type: "object", properties: {} },
|
|
140
|
-
},
|
|
141
|
-
{
|
|
142
|
-
name: "create_task",
|
|
143
|
-
description:
|
|
144
|
-
"Create a new task in backlog. Set predictedKTokens to your estimated context use — this drives the Fibonacci estimation and model selection for sub-agents.",
|
|
145
|
-
inputSchema: {
|
|
146
|
-
type: "object",
|
|
147
|
-
required: [
|
|
148
|
-
"project",
|
|
149
|
-
"milestone",
|
|
150
|
-
"title",
|
|
151
|
-
"definition_of_done",
|
|
152
|
-
"description",
|
|
153
|
-
"predictedKTokens",
|
|
154
|
-
],
|
|
155
|
-
properties: {
|
|
156
|
-
project: { type: "string" },
|
|
157
|
-
milestone: { type: "string" },
|
|
158
|
-
title: { type: "string" },
|
|
159
|
-
definition_of_done: { type: "string" },
|
|
160
|
-
description: { type: "string" },
|
|
161
|
-
predictedKTokens: { type: "number" },
|
|
162
|
-
},
|
|
163
|
-
},
|
|
164
|
-
},
|
|
165
|
-
{
|
|
166
|
-
name: "update_task",
|
|
167
|
-
description:
|
|
168
|
-
"Transition a task's status. Attach a comment when moving to pending_review. Use need_info or blocked for side-exits from in_progress.",
|
|
169
|
-
inputSchema: {
|
|
170
|
-
type: "object",
|
|
171
|
-
required: ["id", "new_status"],
|
|
172
|
-
properties: {
|
|
173
|
-
id: { type: "string" },
|
|
174
|
-
new_status: { type: "string", enum: STATUS_ENUM },
|
|
175
|
-
comment: {
|
|
176
|
-
type: "object",
|
|
177
|
-
properties: {
|
|
178
|
-
id: {
|
|
179
|
-
type: "string",
|
|
180
|
-
format: "uuid",
|
|
181
|
-
description:
|
|
182
|
-
"Existing comment id — provide only when replying to a need_info comment.",
|
|
183
|
-
},
|
|
184
|
-
title: { type: "string" },
|
|
185
|
-
content: { type: "string" },
|
|
186
|
-
reply: {
|
|
187
|
-
type: "string",
|
|
188
|
-
description: "Reply text — only meaningful when id refers to a need_info comment.",
|
|
189
|
-
},
|
|
190
|
-
kind: { type: "string", enum: ["need_info", "regular"] },
|
|
191
|
-
},
|
|
192
|
-
},
|
|
193
|
-
},
|
|
194
|
-
},
|
|
195
|
-
},
|
|
196
|
-
{
|
|
197
|
-
name: "edit_task",
|
|
198
|
-
description: "Edit mutable fields of a task without changing its status.",
|
|
199
|
-
inputSchema: {
|
|
200
|
-
type: "object",
|
|
201
|
-
required: ["id"],
|
|
202
|
-
properties: {
|
|
203
|
-
id: { type: "string" },
|
|
204
|
-
title: { type: "string" },
|
|
205
|
-
description: { type: "string" },
|
|
206
|
-
definition_of_done: { type: "string" },
|
|
207
|
-
predictedKTokens: { type: "number" },
|
|
208
|
-
},
|
|
209
|
-
},
|
|
210
|
-
},
|
|
211
|
-
]
|
|
212
|
-
|
|
213
|
-
// ---------------------------------------------------------------------------
|
|
214
|
-
// Server bootstrap
|
|
215
|
-
// ---------------------------------------------------------------------------
|
|
216
|
-
|
|
217
|
-
export const startServer = async (): Promise<void> => {
|
|
218
|
-
const tasksFile = process.env.LOGBOOK_TASKS_FILE ?? "./tasks.jsonl"
|
|
219
|
-
const hooksDir = process.env.LOGBOOK_HOOKS_DIR ?? "./hooks"
|
|
220
|
-
|
|
221
|
-
const configs = await loadHookConfigs(hooksDir)
|
|
222
|
-
const repo = new JsonlTaskRepository(tasksFile)
|
|
223
|
-
const registry = new PidSessionRegistry(tasksFile)
|
|
224
|
-
|
|
225
|
-
const hookRunnerImpl: HookRunner = {
|
|
226
|
-
run: (event: HookEvent) => executeHooks(event, configs),
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
const repoLayer: Layer.Layer<TaskRepository> = Layer.succeed(TaskRepository, repo)
|
|
230
|
-
const fullLayer: Layer.Layer<TaskRepository | HookRunner | SessionRegistry> = Layer.merge(
|
|
231
|
-
Layer.merge(repoLayer, Layer.succeed(HookRunner, hookRunnerImpl)),
|
|
232
|
-
Layer.succeed(SessionRegistry, registry)
|
|
233
|
-
)
|
|
234
|
-
|
|
235
|
-
const sessionId = newSessionId()
|
|
236
|
-
await Effect.runPromise(registry.register(sessionId, process.pid))
|
|
237
|
-
|
|
238
|
-
// ---------------------------------------------------------------------------
|
|
239
|
-
// Tool dispatch
|
|
240
|
-
// ---------------------------------------------------------------------------
|
|
241
|
-
|
|
242
|
-
const dispatch = async (method: string, params: unknown): Promise<unknown> => {
|
|
243
|
-
switch (method) {
|
|
244
|
-
case "initialize":
|
|
245
|
-
return {
|
|
246
|
-
protocolVersion: "2024-11-05",
|
|
247
|
-
capabilities: { tools: {} },
|
|
248
|
-
serverInfo: { name: "logbook", version: "1.0.0" },
|
|
249
|
-
instructions: AGENT_INSTRUCTIONS,
|
|
250
|
-
}
|
|
251
|
-
case "tools/list":
|
|
252
|
-
return { tools: TOOLS_LIST }
|
|
253
|
-
case "tools/call": {
|
|
254
|
-
const p = params as { name: string; arguments?: unknown }
|
|
255
|
-
const result = await dispatch(p.name, p.arguments ?? {})
|
|
256
|
-
return { content: [{ type: "text", text: JSON.stringify(result) }] }
|
|
257
|
-
}
|
|
258
|
-
case "list_tasks":
|
|
259
|
-
return toolListTasks(params, repoLayer)
|
|
260
|
-
case "current_task":
|
|
261
|
-
return toolCurrentTask(sessionId, fullLayer)
|
|
262
|
-
case "update_task":
|
|
263
|
-
return toolUpdateTask(params, sessionId, fullLayer)
|
|
264
|
-
case "create_task":
|
|
265
|
-
return toolCreateTask(params, sessionId, repoLayer)
|
|
266
|
-
case "edit_task":
|
|
267
|
-
return toolEditTask(params, repoLayer)
|
|
268
|
-
default:
|
|
269
|
-
return Promise.reject(new MethodNotFoundError(method))
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// ---------------------------------------------------------------------------
|
|
274
|
-
// stdio JSON-RPC loop
|
|
275
|
-
// ---------------------------------------------------------------------------
|
|
276
|
-
|
|
277
|
-
const rl = createInterface({ input: process.stdin, terminal: false })
|
|
278
|
-
|
|
279
|
-
const send = (response: JsonRpcResponse): void => {
|
|
280
|
-
process.stdout.write(`${JSON.stringify(response)}\n`)
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
rl.on("line", (line) => {
|
|
284
|
-
const trimmed = line.trim()
|
|
285
|
-
if (trimmed === "") return
|
|
286
|
-
|
|
287
|
-
let request: JsonRpcRequest
|
|
288
|
-
try {
|
|
289
|
-
request = JSON.parse(trimmed) as JsonRpcRequest
|
|
290
|
-
} catch {
|
|
291
|
-
send(parseError(null))
|
|
292
|
-
return
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
// MCP notifications have no `id` field — do not send a response
|
|
296
|
-
if (!("id" in request)) {
|
|
297
|
-
void dispatch(request.method, request.params ?? {}).catch(() => {})
|
|
298
|
-
return
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
const id = request.id ?? null
|
|
302
|
-
|
|
303
|
-
dispatch(request.method, request.params ?? {})
|
|
304
|
-
.then((result) => {
|
|
305
|
-
send(successResponse(id, result))
|
|
306
|
-
})
|
|
307
|
-
.catch((err: unknown) => {
|
|
308
|
-
if (err instanceof MethodNotFoundError) {
|
|
309
|
-
send(methodNotFound(id, err.method))
|
|
310
|
-
return
|
|
311
|
-
}
|
|
312
|
-
// Task domain errors come through Effect.runPromise rejections
|
|
313
|
-
if (isTaskError(err)) {
|
|
314
|
-
const mcpErr = taskErrorToMcpError(err)
|
|
315
|
-
send(errorResponse(id, mcpErr.code, mcpErr.message, mcpErr.data))
|
|
316
|
-
return
|
|
317
|
-
}
|
|
318
|
-
// Zod parse errors from tool input validation
|
|
319
|
-
if (isZodError(err)) {
|
|
320
|
-
send(errorResponse(id, -32602, "Invalid params", { issues: err.errors }))
|
|
321
|
-
return
|
|
322
|
-
}
|
|
323
|
-
send(internalError(id, String(err)))
|
|
324
|
-
})
|
|
325
|
-
})
|
|
326
|
-
|
|
327
|
-
rl.on("close", () => {
|
|
328
|
-
void Effect.runPromise(registry.deregister(sessionId)).then(() => process.exit(0))
|
|
329
|
-
})
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
// ---------------------------------------------------------------------------
|
|
333
|
-
// Internal error sentinel
|
|
334
|
-
// ---------------------------------------------------------------------------
|
|
335
|
-
|
|
336
|
-
class MethodNotFoundError extends Error {
|
|
337
|
-
constructor(readonly method: string) {
|
|
338
|
-
super(`Method not found: ${method}`)
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
// ---------------------------------------------------------------------------
|
|
343
|
-
// Type narrowing helpers (pure)
|
|
344
|
-
// ---------------------------------------------------------------------------
|
|
345
|
-
|
|
346
|
-
const isTaskError = (e: unknown): e is import("../domain/types.js").TaskError =>
|
|
347
|
-
typeof e === "object" &&
|
|
348
|
-
e !== null &&
|
|
349
|
-
typeof (e as { _tag?: unknown })._tag === "string" &&
|
|
350
|
-
[
|
|
351
|
-
"not_found",
|
|
352
|
-
"transition_not_allowed",
|
|
353
|
-
"validation_error",
|
|
354
|
-
"missing_comment",
|
|
355
|
-
"conflict",
|
|
356
|
-
"no_current_task",
|
|
357
|
-
].includes((e as { _tag: string })._tag)
|
|
358
|
-
|
|
359
|
-
interface ZodError {
|
|
360
|
-
errors: unknown[]
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
const isZodError = (e: unknown): e is ZodError =>
|
|
364
|
-
typeof e === "object" &&
|
|
365
|
-
e !== null &&
|
|
366
|
-
Array.isArray((e as { errors?: unknown }).errors) &&
|
|
367
|
-
"name" in (e as object) &&
|
|
368
|
-
(e as { name: string }).name === "ZodError"
|
|
369
|
-
|
|
370
|
-
// ---------------------------------------------------------------------------
|
|
371
|
-
// CLI flag handling (before server startup)
|
|
372
|
-
// ---------------------------------------------------------------------------
|
|
373
|
-
|
|
374
|
-
const handleCliFlags = async (): Promise<void> => {
|
|
375
|
-
const arg = process.argv[2]
|
|
376
|
-
|
|
377
|
-
if (arg === "init") {
|
|
378
|
-
await runInit()
|
|
379
|
-
process.exit(0)
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
if (arg === "--version" || arg === "-v") {
|
|
383
|
-
const pkg = await import("../../package.json", { with: { type: "json" } })
|
|
384
|
-
process.stdout.write(`${pkg.default.version}\n`)
|
|
385
|
-
process.exit(0)
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
if (arg === "--help" || arg === "-h") {
|
|
389
|
-
process.stdout.write(`logbook-mcp [command]
|
|
390
|
-
|
|
391
|
-
Commands:
|
|
392
|
-
init Scaffold tasks.jsonl, hooks/, and emit client config snippets
|
|
393
|
-
(default) Start the MCP server (stdio transport)
|
|
394
|
-
|
|
395
|
-
Options:
|
|
396
|
-
--version Print version
|
|
397
|
-
--help Show this help
|
|
398
|
-
|
|
399
|
-
Environment:
|
|
400
|
-
LOGBOOK_TASKS_FILE Path to JSONL task store (default: ./tasks.jsonl)
|
|
401
|
-
LOGBOOK_HOOKS_DIR Directory for hook definitions (default: ./hooks)
|
|
402
|
-
LOGBOOK_LOG_LEVEL Log level: debug|info|warn|error (default: warn)
|
|
403
|
-
`)
|
|
404
|
-
process.exit(0)
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
// ---------------------------------------------------------------------------
|
|
409
|
-
// Entry point
|
|
410
|
-
// ---------------------------------------------------------------------------
|
|
411
|
-
|
|
412
|
-
await handleCliFlags()
|
|
413
|
-
await startServer()
|
package/src/mcp/session.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const newSessionId = (): string => crypto.randomUUID()
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { Effect, Either, type Layer } from "effect"
|
|
2
|
-
import { z } from "zod"
|
|
3
|
-
import { createTask } from "../task/create-task.js"
|
|
4
|
-
import type { TaskRepository } from "../task/ports.js"
|
|
5
|
-
|
|
6
|
-
const InputSchema = z.object({
|
|
7
|
-
project: z.string().min(1),
|
|
8
|
-
milestone: z.string().min(1),
|
|
9
|
-
title: z.string().min(1),
|
|
10
|
-
definition_of_done: z.string().min(1),
|
|
11
|
-
description: z.string().min(1),
|
|
12
|
-
predictedKTokens: z.number().positive(),
|
|
13
|
-
priority: z.number().int().min(0).default(0),
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
export const toolCreateTask = (
|
|
17
|
-
rawInput: unknown,
|
|
18
|
-
_sessionId: string,
|
|
19
|
-
layer: Layer.Layer<TaskRepository>
|
|
20
|
-
): Promise<{ task: unknown }> => {
|
|
21
|
-
const input = InputSchema.parse(rawInput)
|
|
22
|
-
return Effect.runPromise(
|
|
23
|
-
Effect.provide(Effect.either(createTask(input).pipe(Effect.map((task) => ({ task })))), layer)
|
|
24
|
-
).then((either) => {
|
|
25
|
-
if (Either.isLeft(either)) throw either.left
|
|
26
|
-
return either.right
|
|
27
|
-
})
|
|
28
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { Effect, Either, type Layer } from "effect"
|
|
2
|
-
import { currentTask } from "../task/current-task.js"
|
|
3
|
-
import type { TaskRepository } from "../task/ports.js"
|
|
4
|
-
import type { SessionRegistry } from "../task/session-registry.js"
|
|
5
|
-
|
|
6
|
-
export const toolCurrentTask = (
|
|
7
|
-
sessionId: string,
|
|
8
|
-
layer: Layer.Layer<TaskRepository | SessionRegistry>
|
|
9
|
-
): Promise<{ task: unknown }> => {
|
|
10
|
-
return Effect.runPromise(
|
|
11
|
-
Effect.provide(
|
|
12
|
-
Effect.either(currentTask(sessionId).pipe(Effect.map((task) => ({ task })))),
|
|
13
|
-
layer
|
|
14
|
-
)
|
|
15
|
-
).then((either) => {
|
|
16
|
-
if (Either.isLeft(either)) throw either.left
|
|
17
|
-
return either.right
|
|
18
|
-
})
|
|
19
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { Effect, Either, type Layer } from "effect"
|
|
2
|
-
import { z } from "zod"
|
|
3
|
-
import type { EditTaskInput } from "../task/edit-task.js"
|
|
4
|
-
import { editTask } from "../task/edit-task.js"
|
|
5
|
-
import type { TaskRepository } from "../task/ports.js"
|
|
6
|
-
|
|
7
|
-
const InputSchema = z.object({
|
|
8
|
-
id: z.string().min(1),
|
|
9
|
-
title: z.string().optional(),
|
|
10
|
-
description: z.string().optional(),
|
|
11
|
-
definition_of_done: z.string().optional(),
|
|
12
|
-
predictedKTokens: z.number().positive().optional(),
|
|
13
|
-
priority: z.number().int().min(0).optional(),
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
export const toolEditTask = (
|
|
17
|
-
rawInput: unknown,
|
|
18
|
-
layer: Layer.Layer<TaskRepository>
|
|
19
|
-
): Promise<{ task: unknown }> => {
|
|
20
|
-
const parsed = InputSchema.parse(rawInput)
|
|
21
|
-
const { id } = parsed
|
|
22
|
-
// Build updates by omitting undefined fields (exact optional property types compliance)
|
|
23
|
-
const updates: EditTaskInput = {}
|
|
24
|
-
if (parsed.title !== undefined) updates.title = parsed.title
|
|
25
|
-
if (parsed.description !== undefined) updates.description = parsed.description
|
|
26
|
-
if (parsed.definition_of_done !== undefined)
|
|
27
|
-
updates.definition_of_done = parsed.definition_of_done
|
|
28
|
-
if (parsed.predictedKTokens !== undefined) updates.predictedKTokens = parsed.predictedKTokens
|
|
29
|
-
if (parsed.priority !== undefined) updates.priority = parsed.priority
|
|
30
|
-
|
|
31
|
-
return Effect.runPromise(
|
|
32
|
-
Effect.provide(
|
|
33
|
-
Effect.either(editTask(id, updates).pipe(Effect.map((task) => ({ task })))),
|
|
34
|
-
layer
|
|
35
|
-
)
|
|
36
|
-
).then((either) => {
|
|
37
|
-
if (Either.isLeft(either)) throw either.left
|
|
38
|
-
return either.right
|
|
39
|
-
})
|
|
40
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { Effect, Either, type Layer } from "effect"
|
|
2
|
-
import { z } from "zod"
|
|
3
|
-
import { StatusSchema } from "../domain/types.js"
|
|
4
|
-
import { listTasks } from "../task/list-tasks.js"
|
|
5
|
-
import type { TaskRepository } from "../task/ports.js"
|
|
6
|
-
|
|
7
|
-
const InputSchema = z.object({
|
|
8
|
-
status: z.union([StatusSchema, z.literal("*")]).default("in_progress"),
|
|
9
|
-
project: z.string().optional(),
|
|
10
|
-
milestone: z.string().optional(),
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
export const toolListTasks = (
|
|
14
|
-
rawInput: unknown,
|
|
15
|
-
layer: Layer.Layer<TaskRepository>
|
|
16
|
-
): Promise<{ tasks: unknown[] }> => {
|
|
17
|
-
const input = InputSchema.parse(rawInput)
|
|
18
|
-
const options = {
|
|
19
|
-
status: input.status,
|
|
20
|
-
...(input.project !== undefined ? { project: input.project } : {}),
|
|
21
|
-
...(input.milestone !== undefined ? { milestone: input.milestone } : {}),
|
|
22
|
-
}
|
|
23
|
-
return Effect.runPromise(
|
|
24
|
-
Effect.provide(
|
|
25
|
-
Effect.either(
|
|
26
|
-
listTasks(options).pipe(Effect.map((tasks) => ({ tasks: tasks as unknown[] })))
|
|
27
|
-
),
|
|
28
|
-
layer
|
|
29
|
-
)
|
|
30
|
-
).then((either) => {
|
|
31
|
-
if (Either.isLeft(either)) throw either.left
|
|
32
|
-
return either.right
|
|
33
|
-
})
|
|
34
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { Effect, Either, type Layer } from "effect"
|
|
2
|
-
import { z } from "zod"
|
|
3
|
-
import { CommentKindSchema, StatusSchema } from "../domain/types.js"
|
|
4
|
-
import type { HookRunner } from "../hook/ports.js"
|
|
5
|
-
import type { TaskRepository } from "../task/ports.js"
|
|
6
|
-
import type { SessionRegistry } from "../task/session-registry.js"
|
|
7
|
-
import { updateTask } from "../task/update-task.js"
|
|
8
|
-
|
|
9
|
-
const CommentInputSchema = z
|
|
10
|
-
.object({
|
|
11
|
-
id: z.string().uuid().optional(), // provided only when replying to an existing comment
|
|
12
|
-
title: z.string().min(1),
|
|
13
|
-
content: z.string(),
|
|
14
|
-
reply: z.string().optional(), // reply text; only meaningful when id is provided
|
|
15
|
-
kind: CommentKindSchema,
|
|
16
|
-
})
|
|
17
|
-
.optional()
|
|
18
|
-
|
|
19
|
-
const InputSchema = z.object({
|
|
20
|
-
id: z.string().min(1),
|
|
21
|
-
new_status: StatusSchema,
|
|
22
|
-
comment: CommentInputSchema,
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
export const toolUpdateTask = (
|
|
26
|
-
rawInput: unknown,
|
|
27
|
-
sessionId: string,
|
|
28
|
-
layer: Layer.Layer<TaskRepository | HookRunner | SessionRegistry>
|
|
29
|
-
): Promise<{ ok: boolean }> => {
|
|
30
|
-
const input = InputSchema.parse(rawInput)
|
|
31
|
-
const comment = input.comment
|
|
32
|
-
? {
|
|
33
|
-
id: input.comment.id ?? crypto.randomUUID(),
|
|
34
|
-
timestamp: new Date(),
|
|
35
|
-
title: input.comment.title,
|
|
36
|
-
content: input.comment.content,
|
|
37
|
-
reply: input.comment.reply ?? "",
|
|
38
|
-
kind: input.comment.kind,
|
|
39
|
-
}
|
|
40
|
-
: null
|
|
41
|
-
|
|
42
|
-
return Effect.runPromise(
|
|
43
|
-
Effect.provide(
|
|
44
|
-
Effect.either(
|
|
45
|
-
updateTask(input.id, input.new_status, comment, sessionId).pipe(
|
|
46
|
-
Effect.map(() => ({ ok: true }))
|
|
47
|
-
)
|
|
48
|
-
),
|
|
49
|
-
layer
|
|
50
|
-
)
|
|
51
|
-
).then((either) => {
|
|
52
|
-
if (Either.isLeft(either)) throw either.left
|
|
53
|
-
return either.right
|
|
54
|
-
})
|
|
55
|
-
}
|
package/src/task/create-task.ts
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { Effect } from "effect"
|
|
2
|
-
import { estimateFromKTokens } from "../domain/kTokens.js"
|
|
3
|
-
import type { Task, TaskError } from "../domain/types.js"
|
|
4
|
-
import { TaskRepository } from "./ports.js"
|
|
5
|
-
|
|
6
|
-
export interface CreateTaskInput {
|
|
7
|
-
project: string
|
|
8
|
-
milestone: string
|
|
9
|
-
title: string
|
|
10
|
-
definition_of_done: string
|
|
11
|
-
description: string
|
|
12
|
-
predictedKTokens: number
|
|
13
|
-
priority?: number
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Creates a new task in `backlog` status with no assignee.
|
|
18
|
-
* Validates all fields and derives a Fibonacci estimation from predictedKTokens.
|
|
19
|
-
*/
|
|
20
|
-
export const createTask = (
|
|
21
|
-
input: CreateTaskInput
|
|
22
|
-
): Effect.Effect<Task, TaskError, TaskRepository> => {
|
|
23
|
-
// Validate required string fields
|
|
24
|
-
const requiredStringFields: Array<keyof CreateTaskInput> = [
|
|
25
|
-
"project",
|
|
26
|
-
"milestone",
|
|
27
|
-
"title",
|
|
28
|
-
"definition_of_done",
|
|
29
|
-
"description",
|
|
30
|
-
]
|
|
31
|
-
|
|
32
|
-
for (const field of requiredStringFields) {
|
|
33
|
-
if (typeof input[field] !== "string" || input[field] === "") {
|
|
34
|
-
return Effect.fail({
|
|
35
|
-
_tag: "validation_error" as const,
|
|
36
|
-
message: `${field} is required`,
|
|
37
|
-
})
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Validate predictedKTokens is defined and a number
|
|
42
|
-
if (input.predictedKTokens === undefined || input.predictedKTokens === null) {
|
|
43
|
-
return Effect.fail({
|
|
44
|
-
_tag: "validation_error" as const,
|
|
45
|
-
message: "predictedKTokens is required",
|
|
46
|
-
})
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Derive Fibonacci estimation from kTokens
|
|
50
|
-
return Effect.flatMap(estimateFromKTokens(input.predictedKTokens), (estimation) => {
|
|
51
|
-
const id = crypto.randomUUID()
|
|
52
|
-
const task: Task = {
|
|
53
|
-
project: input.project,
|
|
54
|
-
milestone: input.milestone,
|
|
55
|
-
id,
|
|
56
|
-
title: input.title,
|
|
57
|
-
definition_of_done: input.definition_of_done,
|
|
58
|
-
description: input.description,
|
|
59
|
-
estimation,
|
|
60
|
-
comments: [],
|
|
61
|
-
status: "backlog" as const,
|
|
62
|
-
priority: input.priority ?? 0,
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return Effect.flatMap(TaskRepository, (repo) => repo.save(task)).pipe(Effect.map(() => task))
|
|
66
|
-
})
|
|
67
|
-
}
|