@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/README.md
CHANGED
|
@@ -1,361 +1,341 @@
|
|
|
1
|
-
# logbook
|
|
1
|
+
# logbook — kanban for ai agents
|
|
2
2
|
|
|
3
|
-
logbook is a kanban board
|
|
3
|
+
logbook is a file-system kanban board for autonomous AI agents. It tracks epics, stories, tasks, and context entries across a structured lifecycle so agents and humans share a single source of truth without context bloat.
|
|
4
4
|
|
|
5
|
-
→ **new here?** see [quickstart.md](quickstart.md) to get running in
|
|
5
|
+
→ **new here?** see [quickstart.md](quickstart.md) to get running in 5 minutes.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## why logbook
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
autonomous agents work in parallel, forget context across sessions, and have no shared task state. logbook solves three problems:
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
- **human visibility** — agents record every task they touch in a file the whole team can read and diff
|
|
12
|
+
- **agent coordination** — `task.current` resolves FIFO per-session, so multiple agents can't claim the same task
|
|
13
|
+
- **context budget** — structured JSONL with a DuckDB optional query layer lets agents find relevant records without loading the whole store
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
- hard for agents to track tasks in-progress and done: **not a centralized way to track tasks so each instance haves to figure this out**
|
|
15
|
-
- existing tools add too much overload and are human-centered: **if an agent is going to use it, then it should be tailored for agents**
|
|
15
|
+
v2 adds: *epics → stories → tasks* hierarchy, reusable *context entries* (knowledge that survives across tasks), and Linear two-way sync as a first-class plugin.
|
|
16
16
|
|
|
17
|
-
##
|
|
17
|
+
## quickstart
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
| 1 | task already assigned to this session | return highest priority (tie-break: oldest) |
|
|
29
|
-
| 2 | unassigned `in_progress` task | claim highest priority, return |
|
|
30
|
-
| 3 | `in_progress` task with a dead-session assignee | claim highest priority, return |
|
|
31
|
-
| 4 | `todo` task | auto-transition highest priority to `in_progress`, claim, return |
|
|
32
|
-
| 5 | nothing available | fail with `no_current_task` |
|
|
33
|
-
- the agent can call `update_task(id, new_status, comment)` to transition a task, add a comment, or reply to a `need_info` blocking comment
|
|
34
|
-
- the agent can call `create_task(input)` to open a new task in `backlog`, passing `predictedKTokens` so the server derives a Fibonacci estimation automatically
|
|
35
|
-
- the agent can call `edit_task(id, updates)` to change mutable fields without altering status
|
|
36
|
-
|
|
37
|
-
each one of these tools has the sole purpose of removing overload from the agent context, handling the _"heavy load"_ programmatically on the MCP server.
|
|
38
|
-
|
|
39
|
-
## walkthrough
|
|
40
|
-
|
|
41
|
-
a complete agent session from start to done:
|
|
42
|
-
|
|
43
|
-
**1. agent starts — get current task**
|
|
44
|
-
|
|
45
|
-
```
|
|
46
|
-
current_task()
|
|
47
|
-
→ { id: "abc-123", title: "implement login endpoint", status: "in_progress", ... }
|
|
19
|
+
```bash
|
|
20
|
+
npm install -g @bosun-sh/logbook # install the CLI
|
|
21
|
+
logbook init # scaffold .logbook/, configure MCP, optionally set up Linear
|
|
22
|
+
logbook task:create \
|
|
23
|
+
--title "Implement login endpoint" \
|
|
24
|
+
--description "JWT auth, see docs/auth.md" \
|
|
25
|
+
--definition-of-done "Tests pass and endpoint is documented" \
|
|
26
|
+
--project myapp --milestone v1
|
|
27
|
+
logbook task:list --status "*"
|
|
48
28
|
```
|
|
49
29
|
|
|
50
|
-
|
|
30
|
+
see [quickstart.md](quickstart.md) for the full walkthrough including Linear sync.
|
|
51
31
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
title: "which auth provider?",
|
|
55
|
-
content: "should i use jwt or session-based auth? the spec doesn't say.",
|
|
56
|
-
kind: "need_info"
|
|
57
|
-
})
|
|
58
|
-
→ hook fires: user is notified with the comment
|
|
59
|
-
```
|
|
32
|
+
for one-off local use, run commands through your package manager, for example
|
|
33
|
+
`npx @bosun-sh/logbook --help` or `bunx @bosun-sh/logbook --help`.
|
|
60
34
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
```
|
|
64
|
-
update_task("abc-123", "in_progress", {
|
|
65
|
-
id: "<comment-id>",
|
|
66
|
-
reply: "use jwt, see the auth spec in docs/auth.md",
|
|
67
|
-
title: "jwt confirmed",
|
|
68
|
-
content: "jwt confirmed",
|
|
69
|
-
kind: "need_info"
|
|
70
|
-
})
|
|
71
|
-
→ task returns to in_progress
|
|
72
|
-
```
|
|
35
|
+
## workspace layout
|
|
73
36
|
|
|
74
|
-
|
|
37
|
+
`logbook init` creates the following structure through `workspace.init`:
|
|
75
38
|
|
|
76
39
|
```
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
40
|
+
.logbook/
|
|
41
|
+
├── config.json # workspace config (Linear credentials, hook overrides)
|
|
42
|
+
├── workspace.json # workspace metadata
|
|
43
|
+
├── hooks/
|
|
44
|
+
│ ├── review-spawn/ # spawns a reviewer agent on pending_review
|
|
45
|
+
│ │ ├── config.json
|
|
46
|
+
│ │ └── script.mjs
|
|
47
|
+
│ └── need-info-notify/ # notifies user when a task needs info
|
|
48
|
+
│ ├── config.json
|
|
49
|
+
│ └── script.mjs
|
|
50
|
+
└── storage/
|
|
51
|
+
├── epics.jsonl
|
|
52
|
+
├── stories.jsonl
|
|
53
|
+
├── tasks.jsonl
|
|
54
|
+
├── context-entries.jsonl
|
|
55
|
+
├── external-links.jsonl
|
|
56
|
+
├── sync-events.jsonl
|
|
57
|
+
└── sync-conflicts.jsonl
|
|
83
58
|
```
|
|
84
59
|
|
|
85
|
-
|
|
60
|
+
add `.logbook/storage/` to `.gitignore` to keep runtime data out of version control:
|
|
86
61
|
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
current_task() → gets the review task
|
|
90
|
-
update_task("<review-task-id>", "done")
|
|
91
|
-
→ original task abc-123 → done automatically
|
|
62
|
+
```gitignore
|
|
63
|
+
.logbook/storage/
|
|
92
64
|
```
|
|
93
65
|
|
|
94
|
-
|
|
66
|
+
## mcp tools by plugin
|
|
95
67
|
|
|
96
|
-
|
|
68
|
+
connect `logbook mcp` as an MCP server and call any of the 38 tools below.
|
|
97
69
|
|
|
98
|
-
|
|
99
|
-
You are connected to the logbook MCP server. Call current_task() immediately at session start.
|
|
100
|
-
```
|
|
70
|
+
### task plugin
|
|
101
71
|
|
|
102
|
-
|
|
72
|
+
| Tool ID | Purpose |
|
|
73
|
+
|---------|---------|
|
|
74
|
+
| `task.create` | Create a task in backlog |
|
|
75
|
+
| `task.get` | Load one task by id |
|
|
76
|
+
| `task.list` | List tasks (default status: `in_progress`) |
|
|
77
|
+
| `task.current` | Claim and return the highest-priority in-progress task for this session |
|
|
78
|
+
| `task.update` | Transition task status, add comments, reply to need_info |
|
|
79
|
+
| `task.edit` | Edit mutable fields without status change |
|
|
80
|
+
| `task.assign.session` | Assign a session to a task |
|
|
81
|
+
| `task.assign.model` | Assign a model to a task |
|
|
82
|
+
| `task.assign.phase-model` | Set a per-phase model override |
|
|
83
|
+
| `task.estimate` | Compute or re-compute a Fibonacci estimation |
|
|
103
84
|
|
|
104
|
-
|
|
85
|
+
`task.current` priority chain: session-owned in_progress → unassigned in_progress → orphaned in_progress (dead session) → highest-priority todo (auto-transitions) → `no_current_task` error.
|
|
105
86
|
|
|
106
|
-
|
|
107
|
-
- **effect system**: Effect.ts — all async operations and errors are modeled as `Effect<A, E, R>`
|
|
108
|
-
- **architecture**: hexagonal (ports & adapters), organized by vertical slices per domain concept (task, hook)
|
|
109
|
-
- **validation**: Zod at every system boundary (MCP input, filesystem reads)
|
|
110
|
-
- **persistence**: JSONL — one task per line, append-only writes, full file scan for reads
|
|
87
|
+
### epic plugin
|
|
111
88
|
|
|
112
|
-
|
|
89
|
+
| Tool ID | Purpose |
|
|
90
|
+
|---------|---------|
|
|
91
|
+
| `epic.create` | Create an epic |
|
|
92
|
+
| `epic.get` | Load one epic |
|
|
93
|
+
| `epic.list` | List epics |
|
|
94
|
+
| `epic.update` | Update an epic |
|
|
95
|
+
| `epic.delete` | Tombstone an epic |
|
|
113
96
|
|
|
114
|
-
###
|
|
97
|
+
### story plugin
|
|
115
98
|
|
|
116
|
-
|
|
117
|
-
|
|
99
|
+
| Tool ID | Purpose |
|
|
100
|
+
|---------|---------|
|
|
101
|
+
| `story.create` | Create a story within an epic |
|
|
102
|
+
| `story.get` | Load one story |
|
|
103
|
+
| `story.list` | List stories |
|
|
104
|
+
| `story.update` | Update a story |
|
|
105
|
+
| `story.delete` | Tombstone a story |
|
|
118
106
|
|
|
119
|
-
|
|
120
|
-
- after moving a task to `pending_review`, a reviewer sub-agent spawns and a review task is automatically generated for it.
|
|
121
|
-
- when a second task is moved to `in_progress`, a built-in hook fires and requires a comment justifying the overlap before proceeding.
|
|
107
|
+
### context plugin
|
|
122
108
|
|
|
123
|
-
|
|
109
|
+
| Tool ID | Purpose |
|
|
110
|
+
|---------|---------|
|
|
111
|
+
| `context.create` | Create a reusable context entry |
|
|
112
|
+
| `context.get` | Load one context entry |
|
|
113
|
+
| `context.list` | List context entries |
|
|
114
|
+
| `context.update` | Update a context entry |
|
|
115
|
+
| `context.delete` | Tombstone a context entry |
|
|
116
|
+
| `context.attach` | Attach a context entry to an epic, story, or task |
|
|
117
|
+
| `context.detach` | Remove an attachment |
|
|
118
|
+
| `context.search` | Full-text search over context entries |
|
|
124
119
|
|
|
125
|
-
|
|
126
|
-
hooks/
|
|
127
|
-
└── example_hook/
|
|
128
|
-
├── config.yml
|
|
129
|
-
└── script.ts
|
|
130
|
-
```
|
|
120
|
+
### sync plugin (Linear)
|
|
131
121
|
|
|
132
|
-
|
|
122
|
+
| Tool ID | Purpose |
|
|
123
|
+
|---------|---------|
|
|
124
|
+
| `sync.linear.pull` | Pull issues from Linear into logbook (since-cursor pagination) |
|
|
125
|
+
| `sync.linear.push` | Push logbook tasks to Linear |
|
|
126
|
+
| `sync.linear.setup` | Configure Linear sync from a team URL or explicit ids |
|
|
127
|
+
| `sync.linear.status` | Check Linear configuration and connectivity |
|
|
128
|
+
| `sync.conflicts.list` | List unresolved sync conflicts |
|
|
129
|
+
| `sync.conflicts.resolve` | Resolve a conflict (`use_local`, `use_remote`, or `manual`) |
|
|
133
130
|
|
|
134
|
-
|
|
135
|
-
# config.yml
|
|
136
|
-
event: task.status_changed # lifecycle event that triggers the hook
|
|
137
|
-
condition: "new_status == 'need_info'" # optional; JS-like expression
|
|
138
|
-
timeout_ms: 5000 # optional; default 5000
|
|
139
|
-
```
|
|
131
|
+
### workspace plugin
|
|
140
132
|
|
|
141
|
-
|
|
133
|
+
| Tool ID | Purpose |
|
|
134
|
+
|---------|---------|
|
|
135
|
+
| `workspace.init` | Initialize or re-scaffold the `.logbook/` workspace |
|
|
136
|
+
| `workspace.status` | Report workspace health and provider status |
|
|
142
137
|
|
|
143
|
-
|
|
138
|
+
### hook plugin
|
|
144
139
|
|
|
145
|
-
|
|
140
|
+
| Tool ID | Purpose |
|
|
141
|
+
|---------|---------|
|
|
142
|
+
| `hook.list` | List registered hooks |
|
|
143
|
+
| `hook.run` | Run a hook manually |
|
|
146
144
|
|
|
147
|
-
|
|
145
|
+
### plugin plugin
|
|
148
146
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
PR -->|review-spawn hook| SPAWN[review task created\nreviewer agent spawned]
|
|
153
|
-
SPAWN --> CL{classify findings}
|
|
147
|
+
| Tool ID | Purpose |
|
|
148
|
+
|---------|---------|
|
|
149
|
+
| `plugin.list` | List all registered plugins and their tool IDs |
|
|
154
150
|
|
|
155
|
-
|
|
151
|
+
## cli
|
|
156
152
|
|
|
157
|
-
|
|
158
|
-
CL -->|consider only| CO[original → in_progress\nneed_info: implementer decides\nfix now or backlog]
|
|
159
|
-
CL -->|clean| DONE[original → done]
|
|
153
|
+
every tool is available as `logbook <tool-id-with-colons>`:
|
|
160
154
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
155
|
+
```bash
|
|
156
|
+
# preferred onboarding
|
|
157
|
+
logbook init
|
|
158
|
+
logbook init --mcp-client claude --no-linear
|
|
159
|
+
|
|
160
|
+
# workspace
|
|
161
|
+
logbook workspace:init
|
|
162
|
+
logbook workspace:status
|
|
163
|
+
|
|
164
|
+
# tasks
|
|
165
|
+
logbook task:create --title "x" --description "y" --definition-of-done "z" --project p --milestone m
|
|
166
|
+
logbook task:list --status "*"
|
|
167
|
+
logbook task:list --status in_progress
|
|
168
|
+
logbook task:current
|
|
169
|
+
logbook task:update --id <uuid> --new-status pending_review
|
|
170
|
+
logbook task:edit --id <uuid> --title "New title"
|
|
171
|
+
|
|
172
|
+
# epics and stories
|
|
173
|
+
logbook epic:create --title "Auth" --description "Login and session management" --outcome "Users can log in"
|
|
174
|
+
logbook story:create --epic-id <uuid> --title "JWT login" --description "..." --user-value "Users can authenticate"
|
|
175
|
+
|
|
176
|
+
# context
|
|
177
|
+
logbook context:create --title "Auth spec" --body "Use JWT RS256. See docs/auth.md."
|
|
178
|
+
logbook context:attach --context-entry-id <uuid> --task-id <uuid>
|
|
179
|
+
|
|
180
|
+
# Linear sync
|
|
181
|
+
logbook sync:linear:setup --team-url https://linear.app/<workspace>/team/<team>
|
|
182
|
+
logbook sync:linear:pull
|
|
183
|
+
logbook sync:linear:push --dry-run
|
|
184
|
+
logbook sync:linear:status
|
|
185
|
+
|
|
186
|
+
# v1 aliases (still work, emit a compatibility warning)
|
|
187
|
+
logbook create-task --title "..." --definition-of-done "..." --predicted-k-tokens 3
|
|
188
|
+
logbook list-tasks --status in_progress
|
|
189
|
+
```
|
|
164
190
|
|
|
165
|
-
|
|
191
|
+
all commands write a single-line JSON envelope to stdout:
|
|
192
|
+
|
|
193
|
+
```json
|
|
194
|
+
{"ok":true,"data":{"task":{...}}}
|
|
195
|
+
{"ok":false,"error":{"code":"not_found","message":"task abc was not found"}}
|
|
166
196
|
```
|
|
167
197
|
|
|
168
|
-
|
|
169
|
-
|-----------------|---------------|-------------|-------------|
|
|
170
|
-
| **must-fix** | `→ in_progress` + `need_info` | `→ done` | — |
|
|
171
|
-
| **consider** | `→ in_progress` + `need_info` | `→ done` | implementer replies: fix now or backlog |
|
|
172
|
-
| **nice-to-have** | unchanged | — | `[tech debt]` backlog task created |
|
|
173
|
-
| **clean** | `→ done` | `→ done` | — |
|
|
198
|
+
## linear integration
|
|
174
199
|
|
|
175
|
-
|
|
200
|
+
### setup
|
|
176
201
|
|
|
177
|
-
|
|
202
|
+
The preferred setup path is `logbook init`, which prompts for Linear sync setup.
|
|
203
|
+
To configure Linear separately:
|
|
178
204
|
|
|
179
|
-
|
|
205
|
+
1. create a Linear API key at **Linear → Settings → API → Personal API keys**
|
|
206
|
+
2. add it to `.env` or export it in your shell:
|
|
207
|
+
```bash
|
|
208
|
+
echo "LINEAR_API_KEY=lin_api_..." >> .env
|
|
209
|
+
```
|
|
210
|
+
3. configure Logbook from your Linear team URL:
|
|
211
|
+
```bash
|
|
212
|
+
logbook sync:linear:setup --team-url https://linear.app/bosun/team/BOSUN
|
|
213
|
+
```
|
|
180
214
|
|
|
181
|
-
|
|
215
|
+
The setup command resolves the workspace and team ids and writes the public config to `.logbook/config.json`.
|
|
216
|
+
It never writes the API key there. To let setup write `.env` for you, pass the token once:
|
|
182
217
|
|
|
183
|
-
|
|
218
|
+
```bash
|
|
219
|
+
logbook sync:linear:setup \
|
|
220
|
+
--team-url https://linear.app/bosun/team/BOSUN \
|
|
221
|
+
--api-token lin_api_... \
|
|
222
|
+
--write-env
|
|
223
|
+
```
|
|
184
224
|
|
|
185
|
-
|
|
186
|
-
type Agent = {
|
|
187
|
-
id: string, // session_id assigned by the server on connection
|
|
188
|
-
title: string,
|
|
189
|
-
description: string
|
|
190
|
-
}
|
|
225
|
+
Manual setup is also supported:
|
|
191
226
|
|
|
192
|
-
|
|
227
|
+
```bash
|
|
228
|
+
logbook sync:linear:setup \
|
|
229
|
+
--workspace-id <workspace-id> \
|
|
230
|
+
--team-id <team-id>
|
|
231
|
+
```
|
|
193
232
|
|
|
194
|
-
|
|
195
|
-
id: string,
|
|
196
|
-
timestamp: Date,
|
|
197
|
-
title: string,
|
|
198
|
-
content: string,
|
|
199
|
-
reply: string, // user's reply, populated when responding to a need_info comment
|
|
200
|
-
kind: 'need_info' | 'regular' // drives the reply cycle — only need_info comments accept replies
|
|
201
|
-
}
|
|
233
|
+
This produces a `linear` block like:
|
|
202
234
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
assignee: Agent,
|
|
213
|
-
status: Status,
|
|
214
|
-
in_progress_since?: Date // set when task enters in_progress; used as tie-breaker in current_task
|
|
215
|
-
priority: number // integer ≥ 0; higher = more urgent; defaults to 0
|
|
216
|
-
}
|
|
235
|
+
```json
|
|
236
|
+
{
|
|
237
|
+
"linear": {
|
|
238
|
+
"apiTokenEnv": "LINEAR_API_KEY",
|
|
239
|
+
"workspaceId": "your-workspace-id",
|
|
240
|
+
"defaultTeamId": "your-team-id"
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
```
|
|
217
244
|
|
|
218
|
-
|
|
219
|
-
// project and milestone are optional; all provided filters compose (AND semantics)
|
|
220
|
-
type ListTasks = (options: { status: Status | '*', project?: string, milestone?: string }) => Task[]
|
|
221
|
-
|
|
222
|
-
// returns the highest-priority task for the current session using a priority chain:
|
|
223
|
-
// 1. own in_progress → 2. unassigned in_progress → 3. orphaned in_progress
|
|
224
|
-
// (dead-session assignee) → 4. highest-priority todo (auto-transitioned) → 5. no_current_task error.
|
|
225
|
-
// within each step, tasks are ordered by priority DESC, tie-broken by in_progress_since ASC.
|
|
226
|
-
// if a second task is moved to in_progress, a built-in hook fires and
|
|
227
|
-
// requires a comment justifying the overlap.
|
|
228
|
-
type GetCurrentTask = () => Task
|
|
229
|
-
|
|
230
|
-
// transitions a task to a new status; sessionId is injected server-side.
|
|
231
|
-
// to reply to a need_info comment, pass a comment with the existing comment's id and a reply string.
|
|
232
|
-
type UpdateTask = (id: string, new_status: Status, comment: CommentInput | null, sessionId: string) => void
|
|
233
|
-
|
|
234
|
-
type CommentInput = {
|
|
235
|
-
id?: string, // existing comment id — only when replying to a need_info comment
|
|
236
|
-
title: string,
|
|
237
|
-
content: string,
|
|
238
|
-
reply?: string, // reply text — only meaningful when id refers to a need_info comment
|
|
239
|
-
kind: 'need_info' | 'regular'
|
|
240
|
-
}
|
|
245
|
+
### pull / push
|
|
241
246
|
|
|
242
|
-
|
|
243
|
-
// predictedKTokens is mapped to a Fibonacci estimation by the server.
|
|
244
|
-
type CreateTask = (input: CreateTaskInput, sessionId: string) => Task
|
|
245
|
-
|
|
246
|
-
type CreateTaskInput = {
|
|
247
|
-
project: string,
|
|
248
|
-
milestone: string,
|
|
249
|
-
title: string,
|
|
250
|
-
definition_of_done: string,
|
|
251
|
-
description: string,
|
|
252
|
-
predictedKTokens: number, // positive number; server maps this to a Fibonacci estimation (max 20)
|
|
253
|
-
priority?: number // integer ≥ 0; defaults to 0
|
|
254
|
-
}
|
|
247
|
+
when Logbook runs through MCP, task-facing tools automatically pull before the call and push successful task writes back to Linear. the explicit commands below are still available for manual refreshes, dry runs, and targeted syncs.
|
|
255
248
|
|
|
256
|
-
|
|
257
|
-
|
|
249
|
+
```bash
|
|
250
|
+
# pull issues from Linear since the last cursor
|
|
251
|
+
logbook sync:linear:pull
|
|
258
252
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
description?: string,
|
|
262
|
-
definition_of_done?: string,
|
|
263
|
-
predictedKTokens?: number, // re-derives estimation if provided
|
|
264
|
-
priority?: number // integer ≥ 0; re-assigns priority if provided
|
|
265
|
-
}
|
|
266
|
-
```
|
|
253
|
+
# pull with options
|
|
254
|
+
logbook sync:linear:pull --dry-run --team-id <id>
|
|
267
255
|
|
|
268
|
-
|
|
256
|
+
# push logbook tasks to Linear
|
|
257
|
+
logbook sync:linear:push
|
|
269
258
|
|
|
270
|
-
|
|
259
|
+
# push only specific tasks
|
|
260
|
+
logbook sync:linear:push --task-ids '["task_abc","task_xyz"]' --dry-run
|
|
271
261
|
|
|
272
|
-
|
|
273
|
-
|
|
262
|
+
# check status (connectivity + cursor position)
|
|
263
|
+
logbook sync:linear:status --check-provider
|
|
274
264
|
```
|
|
275
265
|
|
|
276
|
-
|
|
266
|
+
### conflicts
|
|
277
267
|
|
|
278
|
-
|
|
268
|
+
when the same record is modified in both logbook and Linear, a conflict entry is written to `sync-conflicts.jsonl`:
|
|
279
269
|
|
|
280
270
|
```bash
|
|
281
|
-
logbook
|
|
271
|
+
logbook sync:conflicts:list
|
|
272
|
+
logbook sync:conflicts:resolve --id <conflict-uuid> --resolution use_local
|
|
273
|
+
# resolutions: use_local | use_remote | manual
|
|
282
274
|
```
|
|
283
275
|
|
|
284
|
-
|
|
276
|
+
conflict states: `open` → `resolved` or `ignored`.
|
|
285
277
|
|
|
286
|
-
|
|
278
|
+
### external links
|
|
287
279
|
|
|
288
|
-
|
|
280
|
+
bidirectional `linear:<id>` mappings are stored in `external-links.jsonl` and updated automatically by pull/push.
|
|
289
281
|
|
|
290
|
-
|
|
282
|
+
## hooks
|
|
291
283
|
|
|
292
|
-
|
|
284
|
+
hooks execute shell commands on task lifecycle events. configuration lives in `.logbook/hooks/<id>/config.json`:
|
|
293
285
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
286
|
+
```json
|
|
287
|
+
{
|
|
288
|
+
"id": "need-info-notify",
|
|
289
|
+
"event": "task.status_changed",
|
|
290
|
+
"condition": { "status": "need_info" },
|
|
291
|
+
"command": ["node", ".logbook/hooks/need-info-notify/script.mjs"],
|
|
292
|
+
"timeoutMs": 5000
|
|
293
|
+
}
|
|
294
|
+
```
|
|
301
295
|
|
|
302
|
-
|
|
296
|
+
two hooks are materialized by `workspace.init`:
|
|
303
297
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
sessions.json
|
|
307
|
-
```
|
|
298
|
+
- **`need-info-notify`** — prints the blocking comment when a task moves to `need_info`
|
|
299
|
+
- **`review-spawn`** — creates a review task and spawns a reviewer agent when a task moves to `pending_review`
|
|
308
300
|
|
|
309
|
-
|
|
301
|
+
hooks are stateless — execute and forget. the `command` field is an argv array; no shell expansion is performed.
|
|
310
302
|
|
|
311
|
-
|
|
303
|
+
## environment variables
|
|
312
304
|
|
|
313
|
-
|
|
305
|
+
| Variable | Default | Description |
|
|
306
|
+
|----------|---------|-------------|
|
|
307
|
+
| `LOGBOOK_WORKSPACE_ROOT` | `process.cwd()` | workspace root used by the compiled binaries |
|
|
308
|
+
| `LOGBOOK_LOG_LEVEL` | `warn` | log level: `debug`, `info`, `warn`, `error` |
|
|
309
|
+
| `LINEAR_API_KEY` | — | Linear API token (or the env var named in `linear.apiTokenEnv`) |
|
|
314
310
|
|
|
315
|
-
|
|
316
|
-
{
|
|
317
|
-
"mcpServers": {
|
|
318
|
-
"logbook": {
|
|
319
|
-
"command": "logbook-mcp"
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
```
|
|
311
|
+
## optional duckdb index
|
|
324
312
|
|
|
325
|
-
|
|
313
|
+
logbook uses `@duckdb/node-api` to run ad-hoc SQL over the canonical JSONL files. the index is in-memory — no separate index file is written or maintained:
|
|
326
314
|
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
"type": "local",
|
|
332
|
-
"command": ["logbook-mcp"],
|
|
333
|
-
"enabled": true
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
}
|
|
315
|
+
```sql
|
|
316
|
+
-- example: find all in_progress tasks for a specific project
|
|
317
|
+
SELECT id, title, status FROM read_json_auto('.logbook/storage/tasks.jsonl', format='newline_delimited')
|
|
318
|
+
WHERE status = 'in_progress' AND project = 'myapp'
|
|
337
319
|
```
|
|
338
320
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
### hook conditions are trusted code
|
|
321
|
+
the DuckDB path is opt-in via `workspace.status` and is non-canonical — the JSONL files remain the source of truth.
|
|
342
322
|
|
|
343
|
-
|
|
323
|
+
## migrating from v1
|
|
344
324
|
|
|
345
|
-
|
|
325
|
+
if your project has a `tasks.jsonl` at the repository root, `workspace.init` detects it and migrates all records to `.logbook/storage/tasks.jsonl` automatically:
|
|
346
326
|
|
|
347
|
-
-
|
|
348
|
-
-
|
|
349
|
-
-
|
|
350
|
-
- if a condition throws or is malformed, the hook is skipped silently and execution continues — it fails safe.
|
|
327
|
+
- field names renamed from `snake_case` to `camelCase`
|
|
328
|
+
- `kind: "task"` injected on every record
|
|
329
|
+
- v1 comment shape converted to v2 shape
|
|
351
330
|
|
|
352
|
-
|
|
331
|
+
v1 CLI commands (`create-task`, `list-tasks`, `current-task`, `update-task`, `edit-task`, `init`) remain registered and emit a `compatibility_mapping_applied` warning. remove the deprecated commands from your scripts when ready.
|
|
353
332
|
|
|
354
|
-
|
|
333
|
+
see `CHANGELOG.md` for the full v2.0.0 breaking-change list.
|
|
355
334
|
|
|
356
|
-
|
|
335
|
+
## stack
|
|
357
336
|
|
|
358
|
-
- **
|
|
359
|
-
- **
|
|
360
|
-
- **
|
|
361
|
-
- **
|
|
337
|
+
- **runtime**: Node.js / TypeScript
|
|
338
|
+
- **effect system**: Effect.ts — all async operations and errors modeled as `Effect<A, E, R>`
|
|
339
|
+
- **architecture**: ohtools plugin registry, hexagonal adapters (CLI + MCP), vertical slices per entity
|
|
340
|
+
- **persistence**: JSONL — append-only, one record per line, full-scan reads; DuckDB for optional ad-hoc queries
|
|
341
|
+
- **validation**: Zod at every public boundary (MCP input, CLI flags, filesystem reads)
|
package/bin/logbook.cjs
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const { spawnSync } = require("node:child_process")
|
|
3
|
+
const { existsSync } = require("node:fs")
|
|
4
|
+
const path = require("node:path")
|
|
5
|
+
|
|
6
|
+
const entry = path.join(__dirname, "..", "dist", "workspace", "bin-cli.js")
|
|
7
|
+
if (!existsSync(entry)) {
|
|
8
|
+
console.error(
|
|
9
|
+
`logbook entrypoint not found at ${entry}. Reinstall the package or run the build step before publishing.`
|
|
10
|
+
)
|
|
11
|
+
process.exit(1)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const result = spawnSync(process.execPath, [entry, ...process.argv.slice(2)], { stdio: "inherit" })
|
|
15
|
+
if (result.error) {
|
|
16
|
+
throw result.error
|
|
17
|
+
}
|
|
18
|
+
process.exit(result.status ?? 0)
|