light-plan 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +3181 -2
- package/assets/README.md +111 -0
- package/assets/agents/lpm-developer.md +468 -0
- package/assets/agents/lpm-planner.md +532 -0
- package/assets/harnesses/claude.yml +43 -0
- package/assets/harnesses/copilot.yml +54 -0
- package/assets/harnesses/reasonix.yml +49 -0
- package/assets/hcm/light-plan.yml +45 -0
- package/assets/skills/lpm-board-health.md +243 -0
- package/assets/skills/lpm-board-setup.md +354 -0
- package/assets/skills/lpm-delivery.md +344 -0
- package/assets/skills/lpm-planning.md +411 -0
- package/assets/skills/lpm-templates.md +144 -0
- package/assets/skills/lpm.md +267 -0
- package/dist/cli/agent-view.d.ts +27 -0
- package/dist/cli/agent-view.js +247 -0
- package/dist/cli/agent-view.js.map +1 -0
- package/dist/cli/commands/agent/assets.d.ts +64 -0
- package/dist/cli/commands/agent/assets.js +106 -0
- package/dist/cli/commands/agent/assets.js.map +1 -0
- package/dist/cli/commands/agent/glob.d.ts +25 -0
- package/dist/cli/commands/agent/glob.js +82 -0
- package/dist/cli/commands/agent/glob.js.map +1 -0
- package/dist/cli/commands/agent/index.d.ts +11 -0
- package/dist/cli/commands/agent/index.js +284 -0
- package/dist/cli/commands/agent/index.js.map +1 -0
- package/dist/cli/commands/agent/install.d.ts +59 -0
- package/dist/cli/commands/agent/install.js +131 -0
- package/dist/cli/commands/agent/install.js.map +1 -0
- package/dist/cli/commands/agent/mapping.d.ts +175 -0
- package/dist/cli/commands/agent/mapping.js +256 -0
- package/dist/cli/commands/agent/mapping.js.map +1 -0
- package/dist/cli/commands/check.d.ts +2 -0
- package/dist/cli/commands/check.js +81 -0
- package/dist/cli/commands/check.js.map +1 -0
- package/dist/cli/commands/comment.d.ts +2 -0
- package/dist/cli/commands/comment.js +104 -0
- package/dist/cli/commands/comment.js.map +1 -0
- package/dist/cli/commands/convert.d.ts +2 -0
- package/dist/cli/commands/convert.js +115 -0
- package/dist/cli/commands/convert.js.map +1 -0
- package/dist/cli/commands/copy.d.ts +2 -0
- package/dist/cli/commands/copy.js +69 -0
- package/dist/cli/commands/copy.js.map +1 -0
- package/dist/cli/commands/export.d.ts +11 -0
- package/dist/cli/commands/export.js +226 -0
- package/dist/cli/commands/export.js.map +1 -0
- package/dist/cli/commands/flag.d.ts +2 -0
- package/dist/cli/commands/flag.js +172 -0
- package/dist/cli/commands/flag.js.map +1 -0
- package/dist/cli/commands/git.d.ts +11 -0
- package/dist/cli/commands/git.js +357 -0
- package/dist/cli/commands/git.js.map +1 -0
- package/dist/cli/commands/hcm/bundle.d.ts +60 -0
- package/dist/cli/commands/hcm/bundle.js +166 -0
- package/dist/cli/commands/hcm/bundle.js.map +1 -0
- package/dist/cli/commands/hcm/index.d.ts +11 -0
- package/dist/cli/commands/hcm/index.js +162 -0
- package/dist/cli/commands/hcm/index.js.map +1 -0
- package/dist/cli/commands/init.d.ts +2 -0
- package/dist/cli/commands/init.js +81 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/insert.d.ts +2 -0
- package/dist/cli/commands/insert.js +70 -0
- package/dist/cli/commands/insert.js.map +1 -0
- package/dist/cli/commands/instructions.d.ts +7 -0
- package/dist/cli/commands/instructions.js +256 -0
- package/dist/cli/commands/instructions.js.map +1 -0
- package/dist/cli/commands/link.d.ts +2 -0
- package/dist/cli/commands/link.js +121 -0
- package/dist/cli/commands/link.js.map +1 -0
- package/dist/cli/commands/mcp/config.d.ts +71 -0
- package/dist/cli/commands/mcp/config.js +119 -0
- package/dist/cli/commands/mcp/config.js.map +1 -0
- package/dist/cli/commands/mcp/index.d.ts +9 -0
- package/dist/cli/commands/mcp/index.js +92 -0
- package/dist/cli/commands/mcp/index.js.map +1 -0
- package/dist/cli/commands/mcp/serve.d.ts +1 -0
- package/dist/cli/commands/mcp/serve.js +76 -0
- package/dist/cli/commands/mcp/serve.js.map +1 -0
- package/dist/cli/commands/mcp/setup.d.ts +1 -0
- package/dist/cli/commands/mcp/setup.js +83 -0
- package/dist/cli/commands/mcp/setup.js.map +1 -0
- package/dist/cli/commands/me.d.ts +2 -0
- package/dist/cli/commands/me.js +85 -0
- package/dist/cli/commands/me.js.map +1 -0
- package/dist/cli/commands/move.d.ts +2 -0
- package/dist/cli/commands/move.js +81 -0
- package/dist/cli/commands/move.js.map +1 -0
- package/dist/cli/commands/new.d.ts +2 -0
- package/dist/cli/commands/new.js +222 -0
- package/dist/cli/commands/new.js.map +1 -0
- package/dist/cli/commands/open.d.ts +2 -0
- package/dist/cli/commands/open.js +43 -0
- package/dist/cli/commands/open.js.map +1 -0
- package/dist/cli/commands/period.d.ts +10 -0
- package/dist/cli/commands/period.js +165 -0
- package/dist/cli/commands/period.js.map +1 -0
- package/dist/cli/commands/profile.d.ts +2 -0
- package/dist/cli/commands/profile.js +133 -0
- package/dist/cli/commands/profile.js.map +1 -0
- package/dist/cli/commands/queue.d.ts +2 -0
- package/dist/cli/commands/queue.js +582 -0
- package/dist/cli/commands/queue.js.map +1 -0
- package/dist/cli/commands/remote.d.ts +10 -0
- package/dist/cli/commands/remote.js +3142 -0
- package/dist/cli/commands/remote.js.map +1 -0
- package/dist/cli/commands/rm.d.ts +2 -0
- package/dist/cli/commands/rm.js +63 -0
- package/dist/cli/commands/rm.js.map +1 -0
- package/dist/cli/commands/set.d.ts +2 -0
- package/dist/cli/commands/set.js +139 -0
- package/dist/cli/commands/set.js.map +1 -0
- package/dist/cli/commands/split.d.ts +2 -0
- package/dist/cli/commands/split.js +90 -0
- package/dist/cli/commands/split.js.map +1 -0
- package/dist/cli/commands/task.d.ts +2 -0
- package/dist/cli/commands/task.js +298 -0
- package/dist/cli/commands/task.js.map +1 -0
- package/dist/cli/commands/team.d.ts +2 -0
- package/dist/cli/commands/team.js +114 -0
- package/dist/cli/commands/team.js.map +1 -0
- package/dist/cli/commands/template.d.ts +2 -0
- package/dist/cli/commands/template.js +338 -0
- package/dist/cli/commands/template.js.map +1 -0
- package/dist/cli/commands/ui.d.ts +2 -0
- package/dist/cli/commands/ui.js +98 -0
- package/dist/cli/commands/ui.js.map +1 -0
- package/dist/cli/commands/upstream.d.ts +2 -0
- package/dist/cli/commands/upstream.js +218 -0
- package/dist/cli/commands/upstream.js.map +1 -0
- package/dist/cli/context.d.ts +24 -0
- package/dist/cli/context.js +52 -0
- package/dist/cli/context.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +208 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/live.d.ts +71 -0
- package/dist/cli/live.js +182 -0
- package/dist/cli/live.js.map +1 -0
- package/dist/cli/plan.d.ts +28 -0
- package/dist/cli/plan.js +76 -0
- package/dist/cli/plan.js.map +1 -0
- package/dist/cli/prompt.d.ts +60 -0
- package/dist/cli/prompt.js +185 -0
- package/dist/cli/prompt.js.map +1 -0
- package/dist/cli/ui.d.ts +65 -0
- package/dist/cli/ui.js +79 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/core/board/dependency-rollup.d.ts +54 -0
- package/dist/core/board/dependency-rollup.js +72 -0
- package/dist/core/board/dependency-rollup.js.map +1 -0
- package/dist/core/board/flag-rollup.d.ts +33 -0
- package/dist/core/board/flag-rollup.js +56 -0
- package/dist/core/board/flag-rollup.js.map +1 -0
- package/dist/core/board/index.d.ts +21 -0
- package/dist/core/board/index.js +22 -0
- package/dist/core/board/index.js.map +1 -0
- package/dist/core/board/load/cache.d.ts +52 -0
- package/dist/core/board/load/cache.js +105 -0
- package/dist/core/board/load/cache.js.map +1 -0
- package/dist/core/board/load/fields.d.ts +33 -0
- package/dist/core/board/load/fields.js +154 -0
- package/dist/core/board/load/fields.js.map +1 -0
- package/dist/core/board/load/scan.d.ts +39 -0
- package/dist/core/board/load/scan.js +88 -0
- package/dist/core/board/load/scan.js.map +1 -0
- package/dist/core/board/load/tree.d.ts +10 -0
- package/dist/core/board/load/tree.js +114 -0
- package/dist/core/board/load/tree.js.map +1 -0
- package/dist/core/board/load.d.ts +69 -0
- package/dist/core/board/load.js +204 -0
- package/dist/core/board/load.js.map +1 -0
- package/dist/core/board/query.d.ts +126 -0
- package/dist/core/board/query.js +291 -0
- package/dist/core/board/query.js.map +1 -0
- package/dist/core/board/registry.d.ts +51 -0
- package/dist/core/board/registry.js +98 -0
- package/dist/core/board/registry.js.map +1 -0
- package/dist/core/board/remote-scopes.d.ts +71 -0
- package/dist/core/board/remote-scopes.js +103 -0
- package/dist/core/board/remote-scopes.js.map +1 -0
- package/dist/core/board/rollup.d.ts +32 -0
- package/dist/core/board/rollup.js +67 -0
- package/dist/core/board/rollup.js.map +1 -0
- package/dist/core/board/scope.d.ts +81 -0
- package/dist/core/board/scope.js +134 -0
- package/dist/core/board/scope.js.map +1 -0
- package/dist/core/board/simulate.d.ts +138 -0
- package/dist/core/board/simulate.js +141 -0
- package/dist/core/board/simulate.js.map +1 -0
- package/dist/core/board/tasks/index.d.ts +25 -0
- package/dist/core/board/tasks/index.js +26 -0
- package/dist/core/board/tasks/index.js.map +1 -0
- package/dist/core/board/tasks/ranking.d.ts +155 -0
- package/dist/core/board/tasks/ranking.js +374 -0
- package/dist/core/board/tasks/ranking.js.map +1 -0
- package/dist/core/board/tasks/roster.d.ts +42 -0
- package/dist/core/board/tasks/roster.js +82 -0
- package/dist/core/board/tasks/roster.js.map +1 -0
- package/dist/core/board/tasks.d.ts +1 -0
- package/dist/core/board/tasks.js +2 -0
- package/dist/core/board/tasks.js.map +1 -0
- package/dist/core/config/index.d.ts +9 -0
- package/dist/core/config/index.js +10 -0
- package/dist/core/config/index.js.map +1 -0
- package/dist/core/config/lookup.d.ts +114 -0
- package/dist/core/config/lookup.js +221 -0
- package/dist/core/config/lookup.js.map +1 -0
- package/dist/core/config/remote-blocks.d.ts +17 -0
- package/dist/core/config/remote-blocks.js +47 -0
- package/dist/core/config/remote-blocks.js.map +1 -0
- package/dist/core/config/schema.d.ts +10 -0
- package/dist/core/config/schema.js +451 -0
- package/dist/core/config/schema.js.map +1 -0
- package/dist/core/errors.d.ts +23 -0
- package/dist/core/errors.js +31 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/gitsync/hosts.d.ts +40 -0
- package/dist/core/gitsync/hosts.js +115 -0
- package/dist/core/gitsync/hosts.js.map +1 -0
- package/dist/core/gitsync/index.d.ts +25 -0
- package/dist/core/gitsync/index.js +25 -0
- package/dist/core/gitsync/index.js.map +1 -0
- package/dist/core/gitsync/integrate.d.ts +72 -0
- package/dist/core/gitsync/integrate.js +115 -0
- package/dist/core/gitsync/integrate.js.map +1 -0
- package/dist/core/gitsync/repo.d.ts +61 -0
- package/dist/core/gitsync/repo.js +213 -0
- package/dist/core/gitsync/repo.js.map +1 -0
- package/dist/core/gitsync/run.d.ts +58 -0
- package/dist/core/gitsync/run.js +102 -0
- package/dist/core/gitsync/run.js.map +1 -0
- package/dist/core/gitsync/status.d.ts +59 -0
- package/dist/core/gitsync/status.js +81 -0
- package/dist/core/gitsync/status.js.map +1 -0
- package/dist/core/gitsync/sync.d.ts +111 -0
- package/dist/core/gitsync/sync.js +275 -0
- package/dist/core/gitsync/sync.js.map +1 -0
- package/dist/core/index.d.ts +31 -0
- package/dist/core/index.js +32 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/instructions/analyze.d.ts +70 -0
- package/dist/core/instructions/analyze.js +275 -0
- package/dist/core/instructions/analyze.js.map +1 -0
- package/dist/core/instructions/builtin.d.ts +21 -0
- package/dist/core/instructions/builtin.js +133 -0
- package/dist/core/instructions/builtin.js.map +1 -0
- package/dist/core/instructions/context.d.ts +155 -0
- package/dist/core/instructions/context.js +209 -0
- package/dist/core/instructions/context.js.map +1 -0
- package/dist/core/instructions/index.d.ts +29 -0
- package/dist/core/instructions/index.js +30 -0
- package/dist/core/instructions/index.js.map +1 -0
- package/dist/core/instructions/instructions.d.ts +90 -0
- package/dist/core/instructions/instructions.js +179 -0
- package/dist/core/instructions/instructions.js.map +1 -0
- package/dist/core/instructions/template.d.ts +108 -0
- package/dist/core/instructions/template.js +252 -0
- package/dist/core/instructions/template.js.map +1 -0
- package/dist/core/model/attributes.d.ts +16 -0
- package/dist/core/model/attributes.js +119 -0
- package/dist/core/model/attributes.js.map +1 -0
- package/dist/core/model/index.d.ts +10 -0
- package/dist/core/model/index.js +11 -0
- package/dist/core/model/index.js.map +1 -0
- package/dist/core/model/links.d.ts +34 -0
- package/dist/core/model/links.js +114 -0
- package/dist/core/model/links.js.map +1 -0
- package/dist/core/model/profile.d.ts +31 -0
- package/dist/core/model/profile.js +8 -0
- package/dist/core/model/profile.js.map +1 -0
- package/dist/core/model/types.d.ts +441 -0
- package/dist/core/model/types.js +167 -0
- package/dist/core/model/types.js.map +1 -0
- package/dist/core/model/zod.d.ts +6 -0
- package/dist/core/model/zod.js +11 -0
- package/dist/core/model/zod.js.map +1 -0
- package/dist/core/operations/board-index.d.ts +45 -0
- package/dist/core/operations/board-index.js +147 -0
- package/dist/core/operations/board-index.js.map +1 -0
- package/dist/core/operations/claim.d.ts +69 -0
- package/dist/core/operations/claim.js +115 -0
- package/dist/core/operations/claim.js.map +1 -0
- package/dist/core/operations/comment.d.ts +30 -0
- package/dist/core/operations/comment.js +46 -0
- package/dist/core/operations/comment.js.map +1 -0
- package/dist/core/operations/create.d.ts +82 -0
- package/dist/core/operations/create.js +306 -0
- package/dist/core/operations/create.js.map +1 -0
- package/dist/core/operations/flag.d.ts +58 -0
- package/dist/core/operations/flag.js +95 -0
- package/dist/core/operations/flag.js.map +1 -0
- package/dist/core/operations/git-sync.d.ts +148 -0
- package/dist/core/operations/git-sync.js +341 -0
- package/dist/core/operations/git-sync.js.map +1 -0
- package/dist/core/operations/index.d.ts +44 -0
- package/dist/core/operations/index.js +45 -0
- package/dist/core/operations/index.js.map +1 -0
- package/dist/core/operations/init.d.ts +25 -0
- package/dist/core/operations/init.js +122 -0
- package/dist/core/operations/init.js.map +1 -0
- package/dist/core/operations/link.d.ts +40 -0
- package/dist/core/operations/link.js +131 -0
- package/dist/core/operations/link.js.map +1 -0
- package/dist/core/operations/move.d.ts +43 -0
- package/dist/core/operations/move.js +103 -0
- package/dist/core/operations/move.js.map +1 -0
- package/dist/core/operations/profile.d.ts +23 -0
- package/dist/core/operations/profile.js +26 -0
- package/dist/core/operations/profile.js.map +1 -0
- package/dist/core/operations/remotes-off.d.ts +12 -0
- package/dist/core/operations/remotes-off.js +67 -0
- package/dist/core/operations/remotes-off.js.map +1 -0
- package/dist/core/operations/remove.d.ts +18 -0
- package/dist/core/operations/remove.js +114 -0
- package/dist/core/operations/remove.js.map +1 -0
- package/dist/core/operations/retype.d.ts +25 -0
- package/dist/core/operations/retype.js +59 -0
- package/dist/core/operations/retype.js.map +1 -0
- package/dist/core/operations/rollup.d.ts +74 -0
- package/dist/core/operations/rollup.js +121 -0
- package/dist/core/operations/rollup.js.map +1 -0
- package/dist/core/operations/shared.d.ts +133 -0
- package/dist/core/operations/shared.js +383 -0
- package/dist/core/operations/shared.js.map +1 -0
- package/dist/core/operations/update.d.ts +43 -0
- package/dist/core/operations/update.js +161 -0
- package/dist/core/operations/update.js.map +1 -0
- package/dist/core/operations/user.d.ts +27 -0
- package/dist/core/operations/user.js +68 -0
- package/dist/core/operations/user.js.map +1 -0
- package/dist/core/profile/current.d.ts +35 -0
- package/dist/core/profile/current.js +31 -0
- package/dist/core/profile/current.js.map +1 -0
- package/dist/core/profile/index.d.ts +14 -0
- package/dist/core/profile/index.js +15 -0
- package/dist/core/profile/index.js.map +1 -0
- package/dist/core/profile/schema.d.ts +9 -0
- package/dist/core/profile/schema.js +100 -0
- package/dist/core/profile/schema.js.map +1 -0
- package/dist/core/storage/activity.d.ts +78 -0
- package/dist/core/storage/activity.js +131 -0
- package/dist/core/storage/activity.js.map +1 -0
- package/dist/core/storage/atomic.d.ts +34 -0
- package/dist/core/storage/atomic.js +117 -0
- package/dist/core/storage/atomic.js.map +1 -0
- package/dist/core/storage/comments.d.ts +39 -0
- package/dist/core/storage/comments.js +88 -0
- package/dist/core/storage/comments.js.map +1 -0
- package/dist/core/storage/document.d.ts +16 -0
- package/dist/core/storage/document.js +98 -0
- package/dist/core/storage/document.js.map +1 -0
- package/dist/core/storage/frontmatter.d.ts +16 -0
- package/dist/core/storage/frontmatter.js +33 -0
- package/dist/core/storage/frontmatter.js.map +1 -0
- package/dist/core/storage/git.d.ts +8 -0
- package/dist/core/storage/git.js +48 -0
- package/dist/core/storage/git.js.map +1 -0
- package/dist/core/storage/index.d.ts +27 -0
- package/dist/core/storage/index.js +28 -0
- package/dist/core/storage/index.js.map +1 -0
- package/dist/core/storage/local.d.ts +57 -0
- package/dist/core/storage/local.js +133 -0
- package/dist/core/storage/local.js.map +1 -0
- package/dist/core/storage/lock.d.ts +85 -0
- package/dist/core/storage/lock.js +364 -0
- package/dist/core/storage/lock.js.map +1 -0
- package/dist/core/storage/paths.d.ts +125 -0
- package/dist/core/storage/paths.js +202 -0
- package/dist/core/storage/paths.js.map +1 -0
- package/dist/core/storage/state.d.ts +32 -0
- package/dist/core/storage/state.js +71 -0
- package/dist/core/storage/state.js.map +1 -0
- package/dist/core/storage/templates.d.ts +29 -0
- package/dist/core/storage/templates.js +62 -0
- package/dist/core/storage/templates.js.map +1 -0
- package/dist/core/storage/views.d.ts +18 -0
- package/dist/core/storage/views.js +62 -0
- package/dist/core/storage/views.js.map +1 -0
- package/dist/core/validation/check.d.ts +4 -0
- package/dist/core/validation/check.js +22 -0
- package/dist/core/validation/check.js.map +1 -0
- package/dist/core/validation/checks/collection.d.ts +4 -0
- package/dist/core/validation/checks/collection.js +152 -0
- package/dist/core/validation/checks/collection.js.map +1 -0
- package/dist/core/validation/checks/counters.d.ts +3 -0
- package/dist/core/validation/checks/counters.js +23 -0
- package/dist/core/validation/checks/counters.js.map +1 -0
- package/dist/core/validation/checks/dependencies.d.ts +3 -0
- package/dist/core/validation/checks/dependencies.js +58 -0
- package/dist/core/validation/checks/dependencies.js.map +1 -0
- package/dist/core/validation/checks/gitignore.d.ts +10 -0
- package/dist/core/validation/checks/gitignore.js +22 -0
- package/dist/core/validation/checks/gitignore.js.map +1 -0
- package/dist/core/validation/checks/index-file.d.ts +8 -0
- package/dist/core/validation/checks/index-file.js +26 -0
- package/dist/core/validation/checks/index-file.js.map +1 -0
- package/dist/core/validation/checks/index.d.ts +20 -0
- package/dist/core/validation/checks/index.js +21 -0
- package/dist/core/validation/checks/index.js.map +1 -0
- package/dist/core/validation/checks/issues.d.ts +3 -0
- package/dist/core/validation/checks/issues.js +152 -0
- package/dist/core/validation/checks/issues.js.map +1 -0
- package/dist/core/validation/checks/periods.d.ts +3 -0
- package/dist/core/validation/checks/periods.js +89 -0
- package/dist/core/validation/checks/periods.js.map +1 -0
- package/dist/core/validation/checks/remotes.d.ts +20 -0
- package/dist/core/validation/checks/remotes.js +42 -0
- package/dist/core/validation/checks/remotes.js.map +1 -0
- package/dist/core/validation/checks/resources.d.ts +3 -0
- package/dist/core/validation/checks/resources.js +77 -0
- package/dist/core/validation/checks/resources.js.map +1 -0
- package/dist/core/validation/checks/rollup.d.ts +27 -0
- package/dist/core/validation/checks/rollup.js +53 -0
- package/dist/core/validation/checks/rollup.js.map +1 -0
- package/dist/core/validation/checks/squads.d.ts +3 -0
- package/dist/core/validation/checks/squads.js +42 -0
- package/dist/core/validation/checks/squads.js.map +1 -0
- package/dist/core/validation/checks/templates.d.ts +14 -0
- package/dist/core/validation/checks/templates.js +119 -0
- package/dist/core/validation/checks/templates.js.map +1 -0
- package/dist/core/validation/fix.d.ts +7 -0
- package/dist/core/validation/fix.js +273 -0
- package/dist/core/validation/fix.js.map +1 -0
- package/dist/core/validation/index.d.ts +7 -0
- package/dist/core/validation/index.js +8 -0
- package/dist/core/validation/index.js.map +1 -0
- package/dist/core/validation/shared.d.ts +47 -0
- package/dist/core/validation/shared.js +66 -0
- package/dist/core/validation/shared.js.map +1 -0
- package/dist/mcp/context.d.ts +70 -0
- package/dist/mcp/context.js +110 -0
- package/dist/mcp/context.js.map +1 -0
- package/dist/mcp/index.d.ts +49 -0
- package/dist/mcp/index.js +90 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/reply.d.ts +28 -0
- package/dist/mcp/reply.js +34 -0
- package/dist/mcp/reply.js.map +1 -0
- package/dist/mcp/tools/plan/create.d.ts +3 -0
- package/dist/mcp/tools/plan/create.js +128 -0
- package/dist/mcp/tools/plan/create.js.map +1 -0
- package/dist/mcp/tools/plan/delete.d.ts +3 -0
- package/dist/mcp/tools/plan/delete.js +35 -0
- package/dist/mcp/tools/plan/delete.js.map +1 -0
- package/dist/mcp/tools/plan/graph.d.ts +3 -0
- package/dist/mcp/tools/plan/graph.js +53 -0
- package/dist/mcp/tools/plan/graph.js.map +1 -0
- package/dist/mcp/tools/plan/index.d.ts +15 -0
- package/dist/mcp/tools/plan/index.js +16 -0
- package/dist/mcp/tools/plan/index.js.map +1 -0
- package/dist/mcp/tools/plan/link.d.ts +3 -0
- package/dist/mcp/tools/plan/link.js +46 -0
- package/dist/mcp/tools/plan/link.js.map +1 -0
- package/dist/mcp/tools/plan/registrar.d.ts +10 -0
- package/dist/mcp/tools/plan/registrar.js +24 -0
- package/dist/mcp/tools/plan/registrar.js.map +1 -0
- package/dist/mcp/tools/plan/reshape.d.ts +3 -0
- package/dist/mcp/tools/plan/reshape.js +95 -0
- package/dist/mcp/tools/plan/reshape.js.map +1 -0
- package/dist/mcp/tools/plan/timeline.d.ts +3 -0
- package/dist/mcp/tools/plan/timeline.js +68 -0
- package/dist/mcp/tools/plan/timeline.js.map +1 -0
- package/dist/mcp/tools/plan/upstream.d.ts +14 -0
- package/dist/mcp/tools/plan/upstream.js +69 -0
- package/dist/mcp/tools/plan/upstream.js.map +1 -0
- package/dist/mcp/tools/plan.d.ts +1 -0
- package/dist/mcp/tools/plan.js +2 -0
- package/dist/mcp/tools/plan.js.map +1 -0
- package/dist/mcp/tools/read.d.ts +3 -0
- package/dist/mcp/tools/read.js +339 -0
- package/dist/mcp/tools/read.js.map +1 -0
- package/dist/mcp/tools/remote.d.ts +3 -0
- package/dist/mcp/tools/remote.js +254 -0
- package/dist/mcp/tools/remote.js.map +1 -0
- package/dist/mcp/tools/templates.d.ts +12 -0
- package/dist/mcp/tools/templates.js +165 -0
- package/dist/mcp/tools/templates.js.map +1 -0
- package/dist/mcp/tools/work.d.ts +16 -0
- package/dist/mcp/tools/work.js +359 -0
- package/dist/mcp/tools/work.js.map +1 -0
- package/dist/remote/accounts.d.ts +158 -0
- package/dist/remote/accounts.js +207 -0
- package/dist/remote/accounts.js.map +1 -0
- package/dist/remote/adopt.d.ts +139 -0
- package/dist/remote/adopt.js +181 -0
- package/dist/remote/adopt.js.map +1 -0
- package/dist/remote/anchor.d.ts +35 -0
- package/dist/remote/anchor.js +53 -0
- package/dist/remote/anchor.js.map +1 -0
- package/dist/remote/attributes.d.ts +103 -0
- package/dist/remote/attributes.js +245 -0
- package/dist/remote/attributes.js.map +1 -0
- package/dist/remote/audit.d.ts +112 -0
- package/dist/remote/audit.js +215 -0
- package/dist/remote/audit.js.map +1 -0
- package/dist/remote/capabilities.d.ts +267 -0
- package/dist/remote/capabilities.js +225 -0
- package/dist/remote/capabilities.js.map +1 -0
- package/dist/remote/check.d.ts +49 -0
- package/dist/remote/check.js +356 -0
- package/dist/remote/check.js.map +1 -0
- package/dist/remote/comments.d.ts +86 -0
- package/dist/remote/comments.js +87 -0
- package/dist/remote/comments.js.map +1 -0
- package/dist/remote/config-file.d.ts +237 -0
- package/dist/remote/config-file.js +640 -0
- package/dist/remote/config-file.js.map +1 -0
- package/dist/remote/conflicts.d.ts +110 -0
- package/dist/remote/conflicts.js +188 -0
- package/dist/remote/conflicts.js.map +1 -0
- package/dist/remote/connection-catalogue.d.ts +65 -0
- package/dist/remote/connection-catalogue.js +66 -0
- package/dist/remote/connection-catalogue.js.map +1 -0
- package/dist/remote/connection.d.ts +84 -0
- package/dist/remote/connection.js +229 -0
- package/dist/remote/connection.js.map +1 -0
- package/dist/remote/coverage.d.ts +65 -0
- package/dist/remote/coverage.js +244 -0
- package/dist/remote/coverage.js.map +1 -0
- package/dist/remote/credentials.d.ts +95 -0
- package/dist/remote/credentials.js +210 -0
- package/dist/remote/credentials.js.map +1 -0
- package/dist/remote/execute.d.ts +178 -0
- package/dist/remote/execute.js +1245 -0
- package/dist/remote/execute.js.map +1 -0
- package/dist/remote/fingerprint.d.ts +172 -0
- package/dist/remote/fingerprint.js +337 -0
- package/dist/remote/fingerprint.js.map +1 -0
- package/dist/remote/fixtures.d.ts +176 -0
- package/dist/remote/fixtures.js +432 -0
- package/dist/remote/fixtures.js.map +1 -0
- package/dist/remote/guard.d.ts +90 -0
- package/dist/remote/guard.js +83 -0
- package/dist/remote/guard.js.map +1 -0
- package/dist/remote/hierarchy.d.ts +141 -0
- package/dist/remote/hierarchy.js +129 -0
- package/dist/remote/hierarchy.js.map +1 -0
- package/dist/remote/index.d.ts +145 -0
- package/dist/remote/index.js +146 -0
- package/dist/remote/index.js.map +1 -0
- package/dist/remote/inspect.d.ts +103 -0
- package/dist/remote/inspect.js +152 -0
- package/dist/remote/inspect.js.map +1 -0
- package/dist/remote/labels.d.ts +75 -0
- package/dist/remote/labels.js +137 -0
- package/dist/remote/labels.js.map +1 -0
- package/dist/remote/ladder.d.ts +145 -0
- package/dist/remote/ladder.js +387 -0
- package/dist/remote/ladder.js.map +1 -0
- package/dist/remote/ledger.d.ts +97 -0
- package/dist/remote/ledger.js +148 -0
- package/dist/remote/ledger.js.map +1 -0
- package/dist/remote/lifecycle.d.ts +175 -0
- package/dist/remote/lifecycle.js +274 -0
- package/dist/remote/lifecycle.js.map +1 -0
- package/dist/remote/links.d.ts +411 -0
- package/dist/remote/links.js +748 -0
- package/dist/remote/links.js.map +1 -0
- package/dist/remote/managed-block.d.ts +182 -0
- package/dist/remote/managed-block.js +406 -0
- package/dist/remote/managed-block.js.map +1 -0
- package/dist/remote/managed-comment.d.ts +104 -0
- package/dist/remote/managed-comment.js +92 -0
- package/dist/remote/managed-comment.js.map +1 -0
- package/dist/remote/mapping.d.ts +282 -0
- package/dist/remote/mapping.js +336 -0
- package/dist/remote/mapping.js.map +1 -0
- package/dist/remote/merge.d.ts +172 -0
- package/dist/remote/merge.js +221 -0
- package/dist/remote/merge.js.map +1 -0
- package/dist/remote/periods.d.ts +209 -0
- package/dist/remote/periods.js +224 -0
- package/dist/remote/periods.js.map +1 -0
- package/dist/remote/plan.d.ts +671 -0
- package/dist/remote/plan.js +1210 -0
- package/dist/remote/plan.js.map +1 -0
- package/dist/remote/policy.d.ts +67 -0
- package/dist/remote/policy.js +67 -0
- package/dist/remote/policy.js.map +1 -0
- package/dist/remote/preflight.d.ts +112 -0
- package/dist/remote/preflight.js +342 -0
- package/dist/remote/preflight.js.map +1 -0
- package/dist/remote/prerequisites.d.ts +113 -0
- package/dist/remote/prerequisites.js +161 -0
- package/dist/remote/prerequisites.js.map +1 -0
- package/dist/remote/provider.d.ts +802 -0
- package/dist/remote/provider.js +27 -0
- package/dist/remote/provider.js.map +1 -0
- package/dist/remote/providers/github/config.d.ts +84 -0
- package/dist/remote/providers/github/config.js +161 -0
- package/dist/remote/providers/github/config.js.map +1 -0
- package/dist/remote/providers/github/connector.d.ts +33 -0
- package/dist/remote/providers/github/connector.js +774 -0
- package/dist/remote/providers/github/connector.js.map +1 -0
- package/dist/remote/providers/github/edges.d.ts +29 -0
- package/dist/remote/providers/github/edges.js +56 -0
- package/dist/remote/providers/github/edges.js.map +1 -0
- package/dist/remote/providers/github/hierarchy.d.ts +21 -0
- package/dist/remote/providers/github/hierarchy.js +46 -0
- package/dist/remote/providers/github/hierarchy.js.map +1 -0
- package/dist/remote/providers/github/index.d.ts +26 -0
- package/dist/remote/providers/github/index.js +69 -0
- package/dist/remote/providers/github/index.js.map +1 -0
- package/dist/remote/providers/github/project-iteration.d.ts +71 -0
- package/dist/remote/providers/github/project-iteration.js +203 -0
- package/dist/remote/providers/github/project-iteration.js.map +1 -0
- package/dist/remote/providers/github/project-provision.d.ts +130 -0
- package/dist/remote/providers/github/project-provision.js +247 -0
- package/dist/remote/providers/github/project-provision.js.map +1 -0
- package/dist/remote/providers/github/project-status.d.ts +115 -0
- package/dist/remote/providers/github/project-status.js +317 -0
- package/dist/remote/providers/github/project-status.js.map +1 -0
- package/dist/remote/providers/github/projects.d.ts +181 -0
- package/dist/remote/providers/github/projects.js +481 -0
- package/dist/remote/providers/github/projects.js.map +1 -0
- package/dist/remote/providers/github/translator.d.ts +103 -0
- package/dist/remote/providers/github/translator.js +400 -0
- package/dist/remote/providers/github/translator.js.map +1 -0
- package/dist/remote/providers/jira/config.d.ts +96 -0
- package/dist/remote/providers/jira/config.js +200 -0
- package/dist/remote/providers/jira/config.js.map +1 -0
- package/dist/remote/providers/jira/connector.d.ts +42 -0
- package/dist/remote/providers/jira/connector.js +1688 -0
- package/dist/remote/providers/jira/connector.js.map +1 -0
- package/dist/remote/providers/jira/fields.d.ts +292 -0
- package/dist/remote/providers/jira/fields.js +463 -0
- package/dist/remote/providers/jira/fields.js.map +1 -0
- package/dist/remote/providers/jira/hierarchy.d.ts +28 -0
- package/dist/remote/providers/jira/hierarchy.js +60 -0
- package/dist/remote/providers/jira/hierarchy.js.map +1 -0
- package/dist/remote/providers/jira/index.d.ts +29 -0
- package/dist/remote/providers/jira/index.js +100 -0
- package/dist/remote/providers/jira/index.js.map +1 -0
- package/dist/remote/providers/jira/links.d.ts +41 -0
- package/dist/remote/providers/jira/links.js +102 -0
- package/dist/remote/providers/jira/links.js.map +1 -0
- package/dist/remote/providers/jira/sprints.d.ts +80 -0
- package/dist/remote/providers/jira/sprints.js +107 -0
- package/dist/remote/providers/jira/sprints.js.map +1 -0
- package/dist/remote/providers/jira/translator.d.ts +61 -0
- package/dist/remote/providers/jira/translator.js +382 -0
- package/dist/remote/providers/jira/translator.js.map +1 -0
- package/dist/remote/providers/jira/types.d.ts +112 -0
- package/dist/remote/providers/jira/types.js +160 -0
- package/dist/remote/providers/jira/types.js.map +1 -0
- package/dist/remote/providers/jira/vocabulary.d.ts +55 -0
- package/dist/remote/providers/jira/vocabulary.js +91 -0
- package/dist/remote/providers/jira/vocabulary.js.map +1 -0
- package/dist/remote/providers/jsonfile/config.d.ts +61 -0
- package/dist/remote/providers/jsonfile/config.js +83 -0
- package/dist/remote/providers/jsonfile/config.js.map +1 -0
- package/dist/remote/providers/jsonfile/connector.d.ts +34 -0
- package/dist/remote/providers/jsonfile/connector.js +251 -0
- package/dist/remote/providers/jsonfile/connector.js.map +1 -0
- package/dist/remote/providers/jsonfile/index.d.ts +38 -0
- package/dist/remote/providers/jsonfile/index.js +90 -0
- package/dist/remote/providers/jsonfile/index.js.map +1 -0
- package/dist/remote/providers/jsonfile/store.d.ts +59 -0
- package/dist/remote/providers/jsonfile/store.js +48 -0
- package/dist/remote/providers/jsonfile/store.js.map +1 -0
- package/dist/remote/providers/jsonfile/translator.d.ts +54 -0
- package/dist/remote/providers/jsonfile/translator.js +199 -0
- package/dist/remote/providers/jsonfile/translator.js.map +1 -0
- package/dist/remote/providers/linear/config.d.ts +83 -0
- package/dist/remote/providers/linear/config.js +140 -0
- package/dist/remote/providers/linear/config.js.map +1 -0
- package/dist/remote/providers/linear/connector.d.ts +36 -0
- package/dist/remote/providers/linear/connector.js +438 -0
- package/dist/remote/providers/linear/connector.js.map +1 -0
- package/dist/remote/providers/linear/estimate.d.ts +63 -0
- package/dist/remote/providers/linear/estimate.js +112 -0
- package/dist/remote/providers/linear/estimate.js.map +1 -0
- package/dist/remote/providers/linear/index.d.ts +31 -0
- package/dist/remote/providers/linear/index.js +75 -0
- package/dist/remote/providers/linear/index.js.map +1 -0
- package/dist/remote/providers/linear/labels.d.ts +51 -0
- package/dist/remote/providers/linear/labels.js +129 -0
- package/dist/remote/providers/linear/labels.js.map +1 -0
- package/dist/remote/providers/linear/states.d.ts +97 -0
- package/dist/remote/providers/linear/states.js +124 -0
- package/dist/remote/providers/linear/states.js.map +1 -0
- package/dist/remote/providers/linear/translator.d.ts +48 -0
- package/dist/remote/providers/linear/translator.js +343 -0
- package/dist/remote/providers/linear/translator.js.map +1 -0
- package/dist/remote/providers/linear/vocabulary.d.ts +27 -0
- package/dist/remote/providers/linear/vocabulary.js +42 -0
- package/dist/remote/providers/linear/vocabulary.js.map +1 -0
- package/dist/remote/provision.d.ts +45 -0
- package/dist/remote/provision.js +81 -0
- package/dist/remote/provision.js.map +1 -0
- package/dist/remote/pull.d.ts +52 -0
- package/dist/remote/pull.js +116 -0
- package/dist/remote/pull.js.map +1 -0
- package/dist/remote/readiness.d.ts +67 -0
- package/dist/remote/readiness.js +336 -0
- package/dist/remote/readiness.js.map +1 -0
- package/dist/remote/rebase.d.ts +157 -0
- package/dist/remote/rebase.js +255 -0
- package/dist/remote/rebase.js.map +1 -0
- package/dist/remote/reconcile.d.ts +115 -0
- package/dist/remote/reconcile.js +140 -0
- package/dist/remote/reconcile.js.map +1 -0
- package/dist/remote/redact.d.ts +70 -0
- package/dist/remote/redact.js +132 -0
- package/dist/remote/redact.js.map +1 -0
- package/dist/remote/registry.d.ts +32 -0
- package/dist/remote/registry.js +54 -0
- package/dist/remote/registry.js.map +1 -0
- package/dist/remote/remotes.d.ts +94 -0
- package/dist/remote/remotes.js +182 -0
- package/dist/remote/remotes.js.map +1 -0
- package/dist/remote/render.d.ts +147 -0
- package/dist/remote/render.js +683 -0
- package/dist/remote/render.js.map +1 -0
- package/dist/remote/report.d.ts +63 -0
- package/dist/remote/report.js +345 -0
- package/dist/remote/report.js.map +1 -0
- package/dist/remote/resolutions.d.ts +115 -0
- package/dist/remote/resolutions.js +217 -0
- package/dist/remote/resolutions.js.map +1 -0
- package/dist/remote/scaffold.d.ts +134 -0
- package/dist/remote/scaffold.js +370 -0
- package/dist/remote/scaffold.js.map +1 -0
- package/dist/remote/scope.d.ts +57 -0
- package/dist/remote/scope.js +91 -0
- package/dist/remote/scope.js.map +1 -0
- package/dist/remote/selection.d.ts +38 -0
- package/dist/remote/selection.js +50 -0
- package/dist/remote/selection.js.map +1 -0
- package/dist/remote/shape.d.ts +141 -0
- package/dist/remote/shape.js +220 -0
- package/dist/remote/shape.js.map +1 -0
- package/dist/remote/status.d.ts +104 -0
- package/dist/remote/status.js +238 -0
- package/dist/remote/status.js.map +1 -0
- package/dist/remote/sync.d.ts +182 -0
- package/dist/remote/sync.js +523 -0
- package/dist/remote/sync.js.map +1 -0
- package/dist/remote/transport/budget.d.ts +48 -0
- package/dist/remote/transport/budget.js +68 -0
- package/dist/remote/transport/budget.js.map +1 -0
- package/dist/remote/transport/connector.d.ts +115 -0
- package/dist/remote/transport/connector.js +21 -0
- package/dist/remote/transport/connector.js.map +1 -0
- package/dist/remote/transport/error.d.ts +88 -0
- package/dist/remote/transport/error.js +196 -0
- package/dist/remote/transport/error.js.map +1 -0
- package/dist/remote/transport/gh.d.ts +20 -0
- package/dist/remote/transport/gh.js +41 -0
- package/dist/remote/transport/gh.js.map +1 -0
- package/dist/remote/transport/graphql.d.ts +25 -0
- package/dist/remote/transport/graphql.js +81 -0
- package/dist/remote/transport/graphql.js.map +1 -0
- package/dist/remote/transport/http.d.ts +47 -0
- package/dist/remote/transport/http.js +195 -0
- package/dist/remote/transport/http.js.map +1 -0
- package/dist/remote/transport/index.d.ts +18 -0
- package/dist/remote/transport/index.js +19 -0
- package/dist/remote/transport/index.js.map +1 -0
- package/dist/remote/transport/process.d.ts +39 -0
- package/dist/remote/transport/process.js +121 -0
- package/dist/remote/transport/process.js.map +1 -0
- package/dist/remote/transport/rest.d.ts +22 -0
- package/dist/remote/transport/rest.js +57 -0
- package/dist/remote/transport/rest.js.map +1 -0
- package/dist/remote/transport/retry.d.ts +91 -0
- package/dist/remote/transport/retry.js +138 -0
- package/dist/remote/transport/retry.js.map +1 -0
- package/dist/remote/transport-error.d.ts +19 -0
- package/dist/remote/transport-error.js +22 -0
- package/dist/remote/transport-error.js.map +1 -0
- package/dist/remote/vocabulary.d.ts +126 -0
- package/dist/remote/vocabulary.js +57 -0
- package/dist/remote/vocabulary.js.map +1 -0
- package/dist/runner/config.d.ts +7 -0
- package/dist/runner/config.js +61 -0
- package/dist/runner/config.js.map +1 -0
- package/dist/runner/git.d.ts +19 -0
- package/dist/runner/git.js +26 -0
- package/dist/runner/git.js.map +1 -0
- package/dist/runner/index.d.ts +20 -0
- package/dist/runner/index.js +21 -0
- package/dist/runner/index.js.map +1 -0
- package/dist/runner/loop.d.ts +46 -0
- package/dist/runner/loop.js +243 -0
- package/dist/runner/loop.js.map +1 -0
- package/dist/runner/pi.d.ts +39 -0
- package/dist/runner/pi.js +276 -0
- package/dist/runner/pi.js.map +1 -0
- package/dist/runner/shell.d.ts +44 -0
- package/dist/runner/shell.js +174 -0
- package/dist/runner/shell.js.map +1 -0
- package/dist/runner/stats.d.ts +19 -0
- package/dist/runner/stats.js +58 -0
- package/dist/runner/stats.js.map +1 -0
- package/dist/runner/types.d.ts +218 -0
- package/dist/runner/types.js +37 -0
- package/dist/runner/types.js.map +1 -0
- package/dist/server/git.d.ts +8 -0
- package/dist/server/git.js +50 -0
- package/dist/server/git.js.map +1 -0
- package/dist/server/http/respond.d.ts +13 -0
- package/dist/server/http/respond.js +59 -0
- package/dist/server/http/respond.js.map +1 -0
- package/dist/server/http/router.d.ts +27 -0
- package/dist/server/http/router.js +48 -0
- package/dist/server/http/router.js.map +1 -0
- package/dist/server/http/static.d.ts +14 -0
- package/dist/server/http/static.js +55 -0
- package/dist/server/http/static.js.map +1 -0
- package/dist/server/index.d.ts +58 -0
- package/dist/server/index.js +124 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/routes/board.d.ts +8 -0
- package/dist/server/routes/board.js +19 -0
- package/dist/server/routes/board.js.map +1 -0
- package/dist/server/routes/comments.d.ts +13 -0
- package/dist/server/routes/comments.js +36 -0
- package/dist/server/routes/comments.js.map +1 -0
- package/dist/server/routes/flags.d.ts +16 -0
- package/dist/server/routes/flags.js +37 -0
- package/dist/server/routes/flags.js.map +1 -0
- package/dist/server/routes/git.d.ts +13 -0
- package/dist/server/routes/git.js +84 -0
- package/dist/server/routes/git.js.map +1 -0
- package/dist/server/routes/remotes.d.ts +36 -0
- package/dist/server/routes/remotes.js +749 -0
- package/dist/server/routes/remotes.js.map +1 -0
- package/dist/server/routes/views.d.ts +10 -0
- package/dist/server/routes/views.js +63 -0
- package/dist/server/routes/views.js.map +1 -0
- package/dist/server/views/schema.d.ts +2 -0
- package/dist/server/views/schema.js +121 -0
- package/dist/server/views/schema.js.map +1 -0
- package/dist/server/views/store.d.ts +17 -0
- package/dist/server/views/store.js +67 -0
- package/dist/server/views/store.js.map +1 -0
- package/dist/shared/adf.d.ts +83 -0
- package/dist/shared/adf.js +795 -0
- package/dist/shared/adf.js.map +1 -0
- package/dist/shared/blocking.d.ts +130 -0
- package/dist/shared/blocking.js +179 -0
- package/dist/shared/blocking.js.map +1 -0
- package/dist/shared/changes.d.ts +100 -0
- package/dist/shared/changes.js +112 -0
- package/dist/shared/changes.js.map +1 -0
- package/dist/shared/cohesion.d.ts +75 -0
- package/dist/shared/cohesion.js +132 -0
- package/dist/shared/cohesion.js.map +1 -0
- package/dist/shared/dependency-rollup.d.ts +91 -0
- package/dist/shared/dependency-rollup.js +132 -0
- package/dist/shared/dependency-rollup.js.map +1 -0
- package/dist/shared/errors.d.ts +23 -0
- package/dist/shared/errors.js +24 -0
- package/dist/shared/errors.js.map +1 -0
- package/dist/shared/flag-rollup.d.ts +88 -0
- package/dist/shared/flag-rollup.js +119 -0
- package/dist/shared/flag-rollup.js.map +1 -0
- package/dist/shared/git-sync.d.ts +90 -0
- package/dist/shared/git-sync.js +9 -0
- package/dist/shared/git-sync.js.map +1 -0
- package/dist/shared/index.d.ts +40 -0
- package/dist/shared/index.js +41 -0
- package/dist/shared/index.js.map +1 -0
- package/dist/shared/model.d.ts +218 -0
- package/dist/shared/model.js +95 -0
- package/dist/shared/model.js.map +1 -0
- package/dist/shared/period-query.d.ts +21 -0
- package/dist/shared/period-query.js +26 -0
- package/dist/shared/period-query.js.map +1 -0
- package/dist/shared/period-stance.d.ts +45 -0
- package/dist/shared/period-stance.js +50 -0
- package/dist/shared/period-stance.js.map +1 -0
- package/dist/shared/plans/breakdown.d.ts +66 -0
- package/dist/shared/plans/breakdown.js +186 -0
- package/dist/shared/plans/breakdown.js.map +1 -0
- package/dist/shared/plans/index.d.ts +21 -0
- package/dist/shared/plans/index.js +22 -0
- package/dist/shared/plans/index.js.map +1 -0
- package/dist/shared/plans/instantiate.d.ts +61 -0
- package/dist/shared/plans/instantiate.js +184 -0
- package/dist/shared/plans/instantiate.js.map +1 -0
- package/dist/shared/plans/reading.d.ts +79 -0
- package/dist/shared/plans/reading.js +149 -0
- package/dist/shared/plans/reading.js.map +1 -0
- package/dist/shared/plans/reparent.d.ts +54 -0
- package/dist/shared/plans/reparent.js +217 -0
- package/dist/shared/plans/reparent.js.map +1 -0
- package/dist/shared/plans/timeline.d.ts +93 -0
- package/dist/shared/plans/timeline.js +224 -0
- package/dist/shared/plans/timeline.js.map +1 -0
- package/dist/shared/plans/upstream.d.ts +67 -0
- package/dist/shared/plans/upstream.js +73 -0
- package/dist/shared/plans/upstream.js.map +1 -0
- package/dist/shared/remote-api.d.ts +413 -0
- package/dist/shared/remote-api.js +11 -0
- package/dist/shared/remote-api.js.map +1 -0
- package/dist/shared/remote-coverage.d.ts +120 -0
- package/dist/shared/remote-coverage.js +98 -0
- package/dist/shared/remote-coverage.js.map +1 -0
- package/dist/shared/remote-readiness.d.ts +162 -0
- package/dist/shared/remote-readiness.js +49 -0
- package/dist/shared/remote-readiness.js.map +1 -0
- package/dist/shared/remote-status.d.ts +268 -0
- package/dist/shared/remote-status.js +79 -0
- package/dist/shared/remote-status.js.map +1 -0
- package/dist/shared/rollup.d.ts +90 -0
- package/dist/shared/rollup.js +119 -0
- package/dist/shared/rollup.js.map +1 -0
- package/dist/shared/static.d.ts +65 -0
- package/dist/shared/static.js +107 -0
- package/dist/shared/static.js.map +1 -0
- package/dist/shared/template-params.d.ts +80 -0
- package/dist/shared/template-params.js +141 -0
- package/dist/shared/template-params.js.map +1 -0
- package/dist/shared/view.d.ts +105 -0
- package/dist/shared/view.js +44 -0
- package/dist/shared/view.js.map +1 -0
- package/dist/shared/work-unit.d.ts +34 -0
- package/dist/shared/work-unit.js +47 -0
- package/dist/shared/work-unit.js.map +1 -0
- package/dist/sync/apply.d.ts +21 -0
- package/dist/sync/apply.js +149 -0
- package/dist/sync/apply.js.map +1 -0
- package/dist/sync/dto.d.ts +9 -0
- package/dist/sync/dto.js +162 -0
- package/dist/sync/dto.js.map +1 -0
- package/dist/sync/index.d.ts +24 -0
- package/dist/sync/index.js +25 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/patch.d.ts +13 -0
- package/dist/sync/patch.js +212 -0
- package/dist/sync/patch.js.map +1 -0
- package/dist/sync/session.d.ts +31 -0
- package/dist/sync/session.js +55 -0
- package/dist/sync/session.js.map +1 -0
- package/dist/sync/static.d.ts +11 -0
- package/dist/sync/static.js +33 -0
- package/dist/sync/static.js.map +1 -0
- package/package.json +95 -4
- package/templates/blank.yml +71 -0
- package/templates/context/bug.md +107 -0
- package/templates/context/default.md +119 -0
- package/templates/context/epic.md +81 -0
- package/templates/context/feature.md +91 -0
- package/templates/context/research.md +87 -0
- package/templates/context/review.md +81 -0
- package/templates/context/story.md +94 -0
- package/templates/context/sub_task.md +108 -0
- package/templates/context/task.md +86 -0
- package/templates/context/test.md +73 -0
- package/templates/context/user_story.md +147 -0
- package/templates/kanban.yml +226 -0
- package/templates/scrum.yml +567 -0
- package/web/dist/assets/index-D0j8OnHq.js +35 -0
- package/web/dist/assets/index-DFL7v8aP.css +1 -0
- package/web/dist/index.html +13 -0
- package/web/dist-viewer/assets/index-Bcns6OuC.css +1 -0
- package/web/dist-viewer/assets/index-vVXzeiFo.js +7 -0
- package/web/dist-viewer/index.html +14 -0
|
@@ -0,0 +1,748 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The correspondence store — which document is which remote issue, and what it
|
|
3
|
+
* looked like last time both sides agreed.
|
|
4
|
+
*
|
|
5
|
+
* Lives under `.lpm/remotes/<name>/links.json`, committed like everything else.
|
|
6
|
+
* Its sibling `mapping.json` holds the mapping fingerprint every sync compares
|
|
7
|
+
* against (LP-370, `fingerprint.ts`).
|
|
8
|
+
*
|
|
9
|
+
* Why not a frontmatter field? `remote_id:` would be a breaking reserved field
|
|
10
|
+
* (it would shadow a user attribute of that name), it does not extend to two
|
|
11
|
+
* remotes, and it has nowhere to keep the base snapshot. Same reasoning that
|
|
12
|
+
* keeps derived inverses out of the documents.
|
|
13
|
+
*
|
|
14
|
+
* ## Merge safety
|
|
15
|
+
*
|
|
16
|
+
* Keys are written sorted and each link entry is a contiguous line-group, so
|
|
17
|
+
* two people syncing different issues on different branches produce a
|
|
18
|
+
* non-overlapping diff. The file ends with a trailing newline. A hand-edited
|
|
19
|
+
* or merge-mangled file is rejected with a `BoardError` naming the path and the
|
|
20
|
+
* offending key — never a bare JSON parse error.
|
|
21
|
+
*
|
|
22
|
+
* ## Concurrency
|
|
23
|
+
*
|
|
24
|
+
* Two syncs can race on this file (CI plus a laptop, two teammates). The
|
|
25
|
+
* design decision is **last-writer-wins with git as the backstop**: no lockfile
|
|
26
|
+
* in the per-remote folder. The store's public API (`loadLinkStore` /
|
|
27
|
+
* `saveLinkStore`) is free of the single-file assumption so a per-document split
|
|
28
|
+
* under `links/` remains an internal change if the single file proves
|
|
29
|
+
* conflict-prone in practice.
|
|
30
|
+
*/
|
|
31
|
+
import { createHash } from 'node:crypto';
|
|
32
|
+
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
33
|
+
import path from 'node:path';
|
|
34
|
+
import { BoardError } from '../core/errors.js';
|
|
35
|
+
import { isManagedCommentBody } from './managed-comment.js';
|
|
36
|
+
import { MANAGED_BLOCK_BEGIN, MANAGED_BLOCK_END } from './managed-block.js';
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// Managed-block convention
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
/**
|
|
41
|
+
* When a provider cannot hold a field natively it is encoded into a managed
|
|
42
|
+
* block inside the issue body. The block is our output, not their content —
|
|
43
|
+
* so it must be excluded when hashing the body for the base snapshot, or every
|
|
44
|
+
* push would look like a remote edit on the next pull.
|
|
45
|
+
*
|
|
46
|
+
* The delimiters are the one definition in `managed-block.ts`, shared with the
|
|
47
|
+
* codec that writes the block (LP-276) so the hash and the writer can never
|
|
48
|
+
* drift apart.
|
|
49
|
+
*/
|
|
50
|
+
/** Escape regex metacharacters so a delimiter is matched literally. */
|
|
51
|
+
function escapeRegExp(text) {
|
|
52
|
+
return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Regex that matches a managed block and everything inside it. The block may
|
|
56
|
+
* appear at any position in the body and there may be at most one.
|
|
57
|
+
*/
|
|
58
|
+
const MANAGED_BLOCK_RE = new RegExp(`${escapeRegExp(MANAGED_BLOCK_BEGIN)}[\\s\\S]*?${escapeRegExp(MANAGED_BLOCK_END)}`, 'g');
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
// I/O
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
/** The path to one remote's link store. */
|
|
63
|
+
export function linksPath(paths, remoteName) {
|
|
64
|
+
return path.join(paths.remotesDir, remoteName, 'links.json');
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Read the link store from disk. A missing file is a valid empty store — the
|
|
68
|
+
* first sync creates it. A file that exists but cannot be parsed is a
|
|
69
|
+
* `BoardError` naming the path.
|
|
70
|
+
*/
|
|
71
|
+
export function loadLinkStore(paths, remoteName) {
|
|
72
|
+
const file = linksPath(paths, remoteName);
|
|
73
|
+
let raw;
|
|
74
|
+
try {
|
|
75
|
+
raw = readFileSync(file, 'utf8');
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// File does not exist yet — the first sync will create it.
|
|
79
|
+
return emptyStore();
|
|
80
|
+
}
|
|
81
|
+
let parsed;
|
|
82
|
+
try {
|
|
83
|
+
parsed = JSON.parse(raw);
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
throw new BoardError(`Cannot parse link store: ${file}`, [
|
|
87
|
+
error.message,
|
|
88
|
+
'Delete it to start fresh (all links will be lost), or repair the JSON.',
|
|
89
|
+
]);
|
|
90
|
+
}
|
|
91
|
+
const store = parsed;
|
|
92
|
+
if (store.version !== 1) {
|
|
93
|
+
const newer = typeof store.version === 'number' && store.version > 1;
|
|
94
|
+
throw new BoardError(newer
|
|
95
|
+
? `Link store at ${file} was written by a newer version of light-plan`
|
|
96
|
+
: `Unsupported link store version in ${file}`, newer
|
|
97
|
+
? [
|
|
98
|
+
`This file is version ${store.version}; this build of light-plan understands version 1.`,
|
|
99
|
+
'Upgrade light-plan to read this file, or delete it to start fresh (all links will be lost).',
|
|
100
|
+
]
|
|
101
|
+
: [
|
|
102
|
+
`Found version ${JSON.stringify(store.version)}; expected 1.`,
|
|
103
|
+
'Delete it to start fresh (all links will be lost), or repair the version field.',
|
|
104
|
+
]);
|
|
105
|
+
}
|
|
106
|
+
const links = new Map();
|
|
107
|
+
const byRemote = new Map();
|
|
108
|
+
const tombstones = new Map();
|
|
109
|
+
// The recorded hierarchy encoding (LP-493): a per-remote fact, like the
|
|
110
|
+
// cursor. Absent on a store that has never synced.
|
|
111
|
+
let hierarchy;
|
|
112
|
+
if (store.hierarchy !== undefined && store.hierarchy !== null) {
|
|
113
|
+
const raw = store.hierarchy;
|
|
114
|
+
if (typeof raw !== 'object' ||
|
|
115
|
+
Array.isArray(raw) ||
|
|
116
|
+
(raw.kind !== 'sub-issues' && raw.kind !== 'labels') ||
|
|
117
|
+
typeof raw.nativeDepth !== 'number') {
|
|
118
|
+
throw new BoardError(`Invalid link store: ${file}`, [
|
|
119
|
+
`The hierarchy record is malformed (got ${JSON.stringify(store.hierarchy)}).`,
|
|
120
|
+
'Delete the hierarchy field to let the next sync record a fresh one, or repair it.',
|
|
121
|
+
]);
|
|
122
|
+
}
|
|
123
|
+
hierarchy = {
|
|
124
|
+
kind: raw.kind,
|
|
125
|
+
nativeDepth: raw.nativeDepth,
|
|
126
|
+
// The anchor is part of the carrier decision, so dropping it on read
|
|
127
|
+
// makes every twin look mis-parented on the next plan: the record says
|
|
128
|
+
// "root" (the absent default), the resolution says "leaf", and the push
|
|
129
|
+
// re-parents all of them, every time, for ever.
|
|
130
|
+
...(raw.anchor === 'root' || raw.anchor === 'leaf'
|
|
131
|
+
? { anchor: raw.anchor }
|
|
132
|
+
: {}),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
if (store.links && typeof store.links === 'object') {
|
|
136
|
+
for (const [localId, entry] of Object.entries(store.links)) {
|
|
137
|
+
if (!entry || typeof entry !== 'object') {
|
|
138
|
+
throw new BoardError(`Invalid link store: ${file}`, [
|
|
139
|
+
`Link "${localId}" is not an object (got ${typeof entry}).`,
|
|
140
|
+
'Delete it to start fresh (all links will be lost), or repair the entry.',
|
|
141
|
+
]);
|
|
142
|
+
}
|
|
143
|
+
const link = entry;
|
|
144
|
+
// remoteId is the only hard-required field — without it there is no link.
|
|
145
|
+
if (typeof link.remoteId !== 'string' || !link.remoteId) {
|
|
146
|
+
throw new BoardError(`Invalid link store: ${file}`, [
|
|
147
|
+
`Link "${localId}" is missing a valid remoteId (got ${JSON.stringify(link.remoteId)}).`,
|
|
148
|
+
'Every link must carry a non-empty remoteId string.',
|
|
149
|
+
'Delete the entry to remove the link, or provide a valid remoteId.',
|
|
150
|
+
]);
|
|
151
|
+
}
|
|
152
|
+
// Validate types of optional fields so a hand-edited file surfaces
|
|
153
|
+
// mistakes as BoardErrors rather than silently swallowing them.
|
|
154
|
+
validateLinkField(link, localId, 'remoteKey', 'string', file);
|
|
155
|
+
validateLinkField(link, localId, 'remoteUrl', 'string', file);
|
|
156
|
+
validateLinkField(link, localId, 'syncedAt', 'string', file);
|
|
157
|
+
validateLinkField(link, localId, 'remoteRev', 'string', file);
|
|
158
|
+
validateLinkField(link, localId, 'managedCommentId', 'string', file);
|
|
159
|
+
validateLinkField(link, localId, 'nodeId', 'string', file);
|
|
160
|
+
if (link.base !== undefined && link.base !== null) {
|
|
161
|
+
if (typeof link.base !== 'object') {
|
|
162
|
+
throw new BoardError(`Invalid link store: ${file}`, [
|
|
163
|
+
`Link "${localId}".base must be an object (got ${typeof link.base}).`,
|
|
164
|
+
'Delete the base field to clear the snapshot, or provide a valid object.',
|
|
165
|
+
]);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (link.baseHash !== undefined && link.baseHash !== null) {
|
|
169
|
+
if (typeof link.baseHash !== 'string') {
|
|
170
|
+
throw new BoardError(`Invalid link store: ${file}`, [
|
|
171
|
+
`Link "${localId}".baseHash must be a string (got ${typeof link.baseHash}).`,
|
|
172
|
+
'Delete the baseHash field to let it be recomputed, or provide a valid hash.',
|
|
173
|
+
]);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
const linkEntry = {
|
|
177
|
+
remoteId: link.remoteId,
|
|
178
|
+
remoteKey: typeof link.remoteKey === 'string' ? link.remoteKey : link.remoteId,
|
|
179
|
+
remoteUrl: typeof link.remoteUrl === 'string' ? link.remoteUrl : '',
|
|
180
|
+
syncedAt: typeof link.syncedAt === 'string' ? link.syncedAt : '',
|
|
181
|
+
remoteRev: typeof link.remoteRev === 'string' ? link.remoteRev : '',
|
|
182
|
+
};
|
|
183
|
+
if (typeof link.managedCommentId === 'string') {
|
|
184
|
+
linkEntry.managedCommentId = link.managedCommentId;
|
|
185
|
+
}
|
|
186
|
+
if (typeof link.nodeId === 'string') {
|
|
187
|
+
linkEntry.nodeId = link.nodeId;
|
|
188
|
+
}
|
|
189
|
+
// `null` is a value here — "filed with no remote parent" — so it is
|
|
190
|
+
// carried through rather than treated as absent.
|
|
191
|
+
if (typeof link.parentRemoteId === 'string' || link.parentRemoteId === null) {
|
|
192
|
+
linkEntry.parentRemoteId = link.parentRemoteId;
|
|
193
|
+
}
|
|
194
|
+
if (link.commentIds !== undefined && link.commentIds !== null) {
|
|
195
|
+
if (typeof link.commentIds !== 'object' || Array.isArray(link.commentIds)) {
|
|
196
|
+
throw new BoardError(`Invalid link store: ${file}`, [
|
|
197
|
+
`Link "${localId}".commentIds must be an object of comment ids (got ${Array.isArray(link.commentIds) ? 'an array' : typeof link.commentIds}).`,
|
|
198
|
+
'Delete the commentIds field to clear the recorded ids, or provide a valid object.',
|
|
199
|
+
]);
|
|
200
|
+
}
|
|
201
|
+
const commentIds = {};
|
|
202
|
+
for (const [index, commentId] of Object.entries(link.commentIds)) {
|
|
203
|
+
if (typeof commentId !== 'string') {
|
|
204
|
+
throw new BoardError(`Invalid link store: ${file}`, [
|
|
205
|
+
`Link "${localId}".commentIds["${index}"] must be a string (got ${typeof commentId}).`,
|
|
206
|
+
'Delete the entry to clear it, or provide a valid comment id.',
|
|
207
|
+
]);
|
|
208
|
+
}
|
|
209
|
+
commentIds[index] = commentId;
|
|
210
|
+
}
|
|
211
|
+
linkEntry.commentIds = commentIds;
|
|
212
|
+
}
|
|
213
|
+
if (link.base !== undefined && link.base !== null && typeof link.base === 'object') {
|
|
214
|
+
linkEntry.base = link.base;
|
|
215
|
+
}
|
|
216
|
+
if (typeof link.baseHash === 'string') {
|
|
217
|
+
linkEntry.baseHash = link.baseHash;
|
|
218
|
+
}
|
|
219
|
+
links.set(localId, linkEntry);
|
|
220
|
+
byRemote.set(linkEntry.remoteId, localId);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (store.tombstones && typeof store.tombstones === 'object') {
|
|
224
|
+
for (const [localId, raw] of Object.entries(store.tombstones)) {
|
|
225
|
+
if (!raw || typeof raw !== 'object') {
|
|
226
|
+
throw new BoardError(`Invalid link store: ${file}`, [
|
|
227
|
+
`Tombstone "${localId}" is not an object (got ${typeof raw}).`,
|
|
228
|
+
'Delete the tombstone to remove the decoupled marker, or repair the entry.',
|
|
229
|
+
]);
|
|
230
|
+
}
|
|
231
|
+
const entry = raw;
|
|
232
|
+
validateLinkField(entry, localId, 'remoteKey', 'string', file);
|
|
233
|
+
validateLinkField(entry, localId, 'reason', 'string', file);
|
|
234
|
+
validateLinkField(entry, localId, 'at', 'string', file);
|
|
235
|
+
tombstones.set(localId, {
|
|
236
|
+
remoteKey: typeof entry.remoteKey === 'string' ? entry.remoteKey : '',
|
|
237
|
+
reason: typeof entry.reason === 'string' ? entry.reason : '',
|
|
238
|
+
at: typeof entry.at === 'string' ? entry.at : '',
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
// A document may not be both linked and decoupled — the two are opposites,
|
|
243
|
+
// and only a hand-edited or merge-mangled file could hold both. Reject it
|
|
244
|
+
// rather than let one silently outrank the other.
|
|
245
|
+
for (const localId of tombstones.keys()) {
|
|
246
|
+
if (links.has(localId)) {
|
|
247
|
+
throw new BoardError(`Invalid link store: ${file}`, [
|
|
248
|
+
`Document "${localId}" is both linked and decoupled.`,
|
|
249
|
+
'Delete either the link or the tombstone — the two cannot both be true.',
|
|
250
|
+
]);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return {
|
|
254
|
+
version: store.version,
|
|
255
|
+
cursor: typeof store.cursor === 'string' ? store.cursor : null,
|
|
256
|
+
links,
|
|
257
|
+
byRemote,
|
|
258
|
+
tombstones,
|
|
259
|
+
...(hierarchy !== undefined ? { hierarchy } : {}),
|
|
260
|
+
...(typeof store.consentedAt === 'string' && store.consentedAt !== ''
|
|
261
|
+
? { consentedAt: store.consentedAt }
|
|
262
|
+
: {}),
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Write the link store to disk. Creates the per-remote folder if it does not
|
|
267
|
+
* exist. Keys are written in sorted order so two people syncing different
|
|
268
|
+
* issues produce a mergeable diff.
|
|
269
|
+
*/
|
|
270
|
+
export function saveLinkStore(paths, remoteName, store) {
|
|
271
|
+
const file = linksPath(paths, remoteName);
|
|
272
|
+
mkdirSync(path.dirname(file), { recursive: true });
|
|
273
|
+
// Build a plain object with sorted keys.
|
|
274
|
+
const sortedIds = [...store.links.keys()].sort();
|
|
275
|
+
const links = {};
|
|
276
|
+
for (const id of sortedIds) {
|
|
277
|
+
links[id] = store.links.get(id);
|
|
278
|
+
}
|
|
279
|
+
const onDisk = {
|
|
280
|
+
version: 1,
|
|
281
|
+
cursor: store.cursor,
|
|
282
|
+
links,
|
|
283
|
+
};
|
|
284
|
+
if (store.hierarchy !== undefined) {
|
|
285
|
+
onDisk.hierarchy = store.hierarchy;
|
|
286
|
+
}
|
|
287
|
+
if (store.consentedAt !== undefined) {
|
|
288
|
+
onDisk.consentedAt = store.consentedAt;
|
|
289
|
+
}
|
|
290
|
+
const tombstoneIds = [...store.tombstones.keys()].sort();
|
|
291
|
+
if (tombstoneIds.length > 0) {
|
|
292
|
+
const tombstones = {};
|
|
293
|
+
for (const id of tombstoneIds)
|
|
294
|
+
tombstones[id] = store.tombstones.get(id);
|
|
295
|
+
onDisk.tombstones = tombstones;
|
|
296
|
+
}
|
|
297
|
+
writeFileSync(file, `${JSON.stringify(onDisk, null, 2)}\n`, 'utf8');
|
|
298
|
+
}
|
|
299
|
+
// ---------------------------------------------------------------------------
|
|
300
|
+
// Queries
|
|
301
|
+
// ---------------------------------------------------------------------------
|
|
302
|
+
/** The remote twin of `localId`, or undefined when it is not linked. */
|
|
303
|
+
export function getLink(store, localId) {
|
|
304
|
+
return store.links.get(localId);
|
|
305
|
+
}
|
|
306
|
+
/** The tombstone for `localId`, when the document was deliberately decoupled. */
|
|
307
|
+
export function getTombstone(store, localId) {
|
|
308
|
+
return store.tombstones.get(localId);
|
|
309
|
+
}
|
|
310
|
+
/** True when `localId` was deliberately decoupled (LP-366 records these). */
|
|
311
|
+
export function isDecoupled(store, localId) {
|
|
312
|
+
return store.tombstones.has(localId);
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Record (or replace) the tombstone for `localId`. A tombstone is the memory
|
|
316
|
+
* that a human dropped the link on purpose; it never names a living twin.
|
|
317
|
+
*/
|
|
318
|
+
export function setTombstone(store, localId, tombstone) {
|
|
319
|
+
store.tombstones.set(localId, tombstone);
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Remove the tombstone for `localId` — the document is free to be linked (and
|
|
323
|
+
* therefore filed) again. Returns true when there was one to remove.
|
|
324
|
+
*/
|
|
325
|
+
export function clearTombstone(store, localId) {
|
|
326
|
+
return store.tombstones.delete(localId);
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Decouple a document: drop its link (and with it the base snapshot — there is
|
|
330
|
+
* nothing left to be a base for) and record a tombstone carrying the last
|
|
331
|
+
* known remote key, the reason, and when it happened. The remote twin is
|
|
332
|
+
* never touched by this — decoupling is a local decision that leaves the
|
|
333
|
+
* remote issue alone.
|
|
334
|
+
*
|
|
335
|
+
* Works whether or not the document is currently linked: a never-linked
|
|
336
|
+
* document is decoupled with an empty remote key, which still marks it as
|
|
337
|
+
* "never file this". Returns the tombstone written.
|
|
338
|
+
*/
|
|
339
|
+
export function decoupleLink(store, localId, reason, at) {
|
|
340
|
+
const link = store.links.get(localId);
|
|
341
|
+
const remoteKey = link?.remoteKey ?? '';
|
|
342
|
+
removeLink(store, localId); // drops the link, the base snapshot and the reverse index
|
|
343
|
+
const tombstone = { remoteKey, reason, at };
|
|
344
|
+
store.tombstones.set(localId, tombstone);
|
|
345
|
+
return tombstone;
|
|
346
|
+
}
|
|
347
|
+
/** The local id linked to `remoteId`, or undefined when it is not linked. */
|
|
348
|
+
export function getLocalId(store, remoteId) {
|
|
349
|
+
return store.byRemote.get(remoteId);
|
|
350
|
+
}
|
|
351
|
+
/** True when `localId` has a recorded remote twin. */
|
|
352
|
+
export function isLinked(store, localId) {
|
|
353
|
+
return store.links.has(localId);
|
|
354
|
+
}
|
|
355
|
+
// ---------------------------------------------------------------------------
|
|
356
|
+
// Mutations
|
|
357
|
+
// ---------------------------------------------------------------------------
|
|
358
|
+
/**
|
|
359
|
+
* Record (or replace) the remote twin of `localId`. If this local id was
|
|
360
|
+
* previously linked to a different remote id the old reverse entry is dropped.
|
|
361
|
+
*/
|
|
362
|
+
export function setLink(store, localId, entry) {
|
|
363
|
+
const old = store.links.get(localId);
|
|
364
|
+
if (old && old.remoteId !== entry.remoteId) {
|
|
365
|
+
store.byRemote.delete(old.remoteId);
|
|
366
|
+
}
|
|
367
|
+
store.links.set(localId, entry);
|
|
368
|
+
store.byRemote.set(entry.remoteId, localId);
|
|
369
|
+
// A live link is the opposite of a tombstone: linking (or re-linking) a
|
|
370
|
+
// document ends its decoupled state, so the tombstone must not linger and
|
|
371
|
+
// outrank the link in the lifecycle resolver.
|
|
372
|
+
store.tombstones.delete(localId);
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Remove the link for `localId`. Returns true when there was one to remove.
|
|
376
|
+
*/
|
|
377
|
+
export function removeLink(store, localId) {
|
|
378
|
+
const entry = store.links.get(localId);
|
|
379
|
+
if (!entry)
|
|
380
|
+
return false;
|
|
381
|
+
store.byRemote.delete(entry.remoteId);
|
|
382
|
+
store.links.delete(localId);
|
|
383
|
+
return true;
|
|
384
|
+
}
|
|
385
|
+
/** The remote id of the managed comment recorded for `localId`, or undefined. */
|
|
386
|
+
export function getManagedCommentId(store, localId) {
|
|
387
|
+
return store.links.get(localId)?.managedCommentId;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* True when a remote comment is the managed comment for `localId` — our own
|
|
391
|
+
* output, excluded from comment sync in both directions (LP-278). Known by
|
|
392
|
+
* id where the link store records it; by body where the id was lost. A push
|
|
393
|
+
* never re-posts it as a user comment, and a pull never imports it as one.
|
|
394
|
+
*/
|
|
395
|
+
export function isManagedComment(store, localId, commentId, body) {
|
|
396
|
+
if (getManagedCommentId(store, localId) === commentId)
|
|
397
|
+
return true;
|
|
398
|
+
return isManagedCommentBody(body);
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Record (or clear) the managed comment id for `localId`. A no-op when the
|
|
402
|
+
* document is not linked — the comment is an attribute of an existing link.
|
|
403
|
+
*/
|
|
404
|
+
export function setManagedCommentId(store, localId, commentId) {
|
|
405
|
+
const link = store.links.get(localId);
|
|
406
|
+
if (!link)
|
|
407
|
+
return;
|
|
408
|
+
if (commentId === undefined)
|
|
409
|
+
delete link.managedCommentId;
|
|
410
|
+
else
|
|
411
|
+
link.managedCommentId = commentId;
|
|
412
|
+
}
|
|
413
|
+
// ---------------------------------------------------------------------------
|
|
414
|
+
// User-comment correspondence (LP-316)
|
|
415
|
+
// ---------------------------------------------------------------------------
|
|
416
|
+
/**
|
|
417
|
+
* The local comment indexes (1-based, as a string) already synced for
|
|
418
|
+
* `localId`, or an empty set when the document is unlinked or has none. The
|
|
419
|
+
* push posts only indexes absent from this set; a comment the log has since
|
|
420
|
+
* grown past (new entries appended below) is still present, because appends
|
|
421
|
+
* never shift the indexes recorded for earlier entries.
|
|
422
|
+
*/
|
|
423
|
+
export function getSyncedCommentIndexes(store, localId) {
|
|
424
|
+
const record = store.links.get(localId)?.commentIds;
|
|
425
|
+
const indexes = new Set();
|
|
426
|
+
if (!record)
|
|
427
|
+
return indexes;
|
|
428
|
+
for (const key of Object.keys(record)) {
|
|
429
|
+
const index = Number(key);
|
|
430
|
+
if (Number.isInteger(index) && index > 0)
|
|
431
|
+
indexes.add(index);
|
|
432
|
+
}
|
|
433
|
+
return indexes;
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* The remote comment ids already synced for `localId`, or an empty set. The
|
|
437
|
+
* pull appends only remote ids absent from this set; the managed comment's id
|
|
438
|
+
* is deliberately not among them, so the caller still excludes it by body/id
|
|
439
|
+
* rather than trusting the absence to be meaningful.
|
|
440
|
+
*/
|
|
441
|
+
export function getSyncedRemoteCommentIds(store, localId) {
|
|
442
|
+
const record = store.links.get(localId)?.commentIds;
|
|
443
|
+
const ids = new Set();
|
|
444
|
+
if (!record)
|
|
445
|
+
return ids;
|
|
446
|
+
for (const value of Object.values(record))
|
|
447
|
+
ids.add(value);
|
|
448
|
+
return ids;
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Record that the local comment at `index` (1-based) is the remote comment
|
|
452
|
+
* `commentId` for `localId` (LP-316). A no-op when the document is not
|
|
453
|
+
* linked. Clearing a synced comment is not offered — the log is append-only
|
|
454
|
+
* and a recorded id stays recorded, so nothing is ever posted twice.
|
|
455
|
+
*/
|
|
456
|
+
export function setCommentId(store, localId, index, commentId) {
|
|
457
|
+
const link = store.links.get(localId);
|
|
458
|
+
if (!link)
|
|
459
|
+
return;
|
|
460
|
+
if (link.commentIds === undefined)
|
|
461
|
+
link.commentIds = {};
|
|
462
|
+
link.commentIds[String(index)] = commentId;
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Change the local id a link is keyed under. Does nothing when `oldId` has no
|
|
466
|
+
* link or when the two ids are equal, and overwrites any existing link at
|
|
467
|
+
* `newId` as the safe default — the caller must resolve that collision first.
|
|
468
|
+
*/
|
|
469
|
+
export function rewriteLinkId(store, oldId, newId) {
|
|
470
|
+
if (oldId === newId)
|
|
471
|
+
return;
|
|
472
|
+
const entry = store.links.get(oldId);
|
|
473
|
+
if (!entry)
|
|
474
|
+
return;
|
|
475
|
+
// If newId already had a link the old one is dropped — that is the safe
|
|
476
|
+
// default, and the caller checks for collisions before calling.
|
|
477
|
+
const oldAtNew = store.links.get(newId);
|
|
478
|
+
if (oldAtNew)
|
|
479
|
+
store.byRemote.delete(oldAtNew.remoteId);
|
|
480
|
+
store.links.delete(oldId);
|
|
481
|
+
store.links.set(newId, entry);
|
|
482
|
+
store.byRemote.set(entry.remoteId, newId);
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Report links whose local document no longer exists. Never prunes silently —
|
|
486
|
+
* the caller decides whether to call `removeLink` for each. The returned array
|
|
487
|
+
* is the list of local ids that have no matching document.
|
|
488
|
+
*/
|
|
489
|
+
export function findMissingLinks(store, existingIds) {
|
|
490
|
+
const missing = [];
|
|
491
|
+
for (const localId of store.links.keys()) {
|
|
492
|
+
if (!existingIds.has(localId)) {
|
|
493
|
+
missing.push(localId);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
return missing;
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Remove every link whose local document is not in `existingIds`. Returns the
|
|
500
|
+
* ids that were pruned.
|
|
501
|
+
*/
|
|
502
|
+
export function pruneMissingLinks(store, existingIds) {
|
|
503
|
+
const missing = findMissingLinks(store, existingIds);
|
|
504
|
+
for (const id of missing) {
|
|
505
|
+
removeLink(store, id);
|
|
506
|
+
}
|
|
507
|
+
return missing;
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* Tombstones whose local document no longer exists. Like `findMissingLinks`,
|
|
511
|
+
* never prunes silently — the caller decides. A tombstone left behind by a
|
|
512
|
+
* deleted document is dead weight, not a correctness bug, but `lpm check`
|
|
513
|
+
* reports it so the store stays honest.
|
|
514
|
+
*/
|
|
515
|
+
export function findMissingTombstones(store, existingIds) {
|
|
516
|
+
const missing = [];
|
|
517
|
+
for (const localId of store.tombstones.keys()) {
|
|
518
|
+
if (!existingIds.has(localId))
|
|
519
|
+
missing.push(localId);
|
|
520
|
+
}
|
|
521
|
+
return missing;
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Remove every tombstone whose local document is not in `existingIds`.
|
|
525
|
+
* Returns the ids that were pruned.
|
|
526
|
+
*/
|
|
527
|
+
export function pruneMissingTombstones(store, existingIds) {
|
|
528
|
+
const missing = findMissingTombstones(store, existingIds);
|
|
529
|
+
for (const id of missing) {
|
|
530
|
+
store.tombstones.delete(id);
|
|
531
|
+
}
|
|
532
|
+
return missing;
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Strip the managed block from a body, returning the text the remote side
|
|
536
|
+
* wrote — the content the hash should represent. When there is no managed
|
|
537
|
+
* block the body is returned unchanged.
|
|
538
|
+
*/
|
|
539
|
+
export function stripManagedBlock(body) {
|
|
540
|
+
return body.replace(MANAGED_BLOCK_RE, '').trim();
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* Compute a stable hash of the *normalised* body — managed block excluded — so
|
|
544
|
+
* the base snapshot stores a short token rather than the full text. The
|
|
545
|
+
* returned string carries a `sha256:` prefix so a reader can tell a hash from
|
|
546
|
+
* a literal body value at a glance.
|
|
547
|
+
*
|
|
548
|
+
* The hash is over the trimmed text after the managed block is removed; two
|
|
549
|
+
* bodies that differ only in trailing whitespace outside the managed block
|
|
550
|
+
* produce the same hash.
|
|
551
|
+
*
|
|
552
|
+
* **Line endings are normalised first**, and that is not cosmetic. A board
|
|
553
|
+
* checked out on Windows has `
|
|
554
|
+
` in every document; a remote hands its text
|
|
555
|
+
* back with `
|
|
556
|
+
`. Hashing them apart makes every document permanently *ahead*:
|
|
557
|
+
* the push rewrites all of them, the next push does it again, and two
|
|
558
|
+
* teammates on different operating systems fight over bodies neither has
|
|
559
|
+
* edited.
|
|
560
|
+
*
|
|
561
|
+
* `normalize` is the same argument made for a remote whose body format is not
|
|
562
|
+
* markdown (`Translator.normalizeBody`): Jira stores ADF, which has paragraphs
|
|
563
|
+
* but no source line breaks, so a hard-wrapped body comes back as one long
|
|
564
|
+
* line and would differ from itself for ever. Pass it when hashing a **board**
|
|
565
|
+
* body that will be compared against a base recorded from the remote's echo;
|
|
566
|
+
* never when hashing prose the remote just handed back, which has already been
|
|
567
|
+
* through that round trip.
|
|
568
|
+
*/
|
|
569
|
+
export function hashBody(body, normalize) {
|
|
570
|
+
const stripped = stripManagedBlock(body).replace(/\r\n/g, '\n');
|
|
571
|
+
const normalised = normalize === undefined ? stripped : normalize(stripped).trim();
|
|
572
|
+
const hash = createHash('sha256').update(normalised, 'utf8').digest('hex');
|
|
573
|
+
return `sha256:${hash}`;
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* True when `value` looks like a body hash — a string that starts with
|
|
577
|
+
* `sha256:` followed by 64 hex digits.
|
|
578
|
+
*/
|
|
579
|
+
export function isBodyHash(value) {
|
|
580
|
+
return typeof value === 'string' && /^sha256:[0-9a-f]{64}$/.test(value);
|
|
581
|
+
}
|
|
582
|
+
// ---------------------------------------------------------------------------
|
|
583
|
+
// Base snapshots
|
|
584
|
+
// ---------------------------------------------------------------------------
|
|
585
|
+
/**
|
|
586
|
+
* Compute the base snapshot for one document: every mapped field's value as it
|
|
587
|
+
* stands right now. The body is stored as a hash (`hashBody`), not as the full
|
|
588
|
+
* text. Fields carried in the managed block still appear under their local
|
|
589
|
+
* names — the base is vocabulary-agnostic.
|
|
590
|
+
*
|
|
591
|
+
* `mappedFields` is the set of local attribute names the mapping declares.
|
|
592
|
+
* Only those fields land in the snapshot; nothing else is included, because a
|
|
593
|
+
* field the mapping does not mention cannot diverge.
|
|
594
|
+
*/
|
|
595
|
+
export function computeBase(document, mappedFields, normalizeBody) {
|
|
596
|
+
const base = {};
|
|
597
|
+
for (const field of mappedFields) {
|
|
598
|
+
if (field === 'body') {
|
|
599
|
+
base.body = hashBody(document.body, normalizeBody);
|
|
600
|
+
}
|
|
601
|
+
else if (field === 'title') {
|
|
602
|
+
base.title = document.title;
|
|
603
|
+
}
|
|
604
|
+
else if (field === 'status' ||
|
|
605
|
+
field === 'assignee' ||
|
|
606
|
+
field === 'period') {
|
|
607
|
+
base[field] = document[field] ?? null;
|
|
608
|
+
}
|
|
609
|
+
else if (field === 'dependsOn' ||
|
|
610
|
+
field === 'depends_on' ||
|
|
611
|
+
field === 'relatesTo' ||
|
|
612
|
+
field === 'relates_to' ||
|
|
613
|
+
field === 'relatedFiles' ||
|
|
614
|
+
field === 'related_files') {
|
|
615
|
+
// List fields — snapshot a sorted copy so the order is stable.
|
|
616
|
+
// Normalise the field name for lookup: the document shape uses
|
|
617
|
+
// camelCase, but the mapping may declare either spelling.
|
|
618
|
+
const lookupKey = field === 'depends_on' ? 'dependsOn' :
|
|
619
|
+
field === 'relates_to' ? 'relatesTo' :
|
|
620
|
+
field === 'related_files' ? 'relatedFiles' :
|
|
621
|
+
field;
|
|
622
|
+
const list = document[lookupKey];
|
|
623
|
+
base[field] = Array.isArray(list) ? [...list].sort() : [];
|
|
624
|
+
}
|
|
625
|
+
else {
|
|
626
|
+
// Config-declared attribute or unknown field.
|
|
627
|
+
base[field] = document.attributes[field] ?? null;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
return base;
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* Update the base snapshot for one linked document. After a successful sync
|
|
634
|
+
* only the documents that landed should have their base updated — a partially
|
|
635
|
+
* failed sync must not snapshot work that did not reach the remote.
|
|
636
|
+
*
|
|
637
|
+
* The `base` value here should come from `computeBase`; the `baseHash` is
|
|
638
|
+
* derived from it automatically.
|
|
639
|
+
*/
|
|
640
|
+
export function updateBase(store, localId, base, remoteRev, syncedAt) {
|
|
641
|
+
const link = store.links.get(localId);
|
|
642
|
+
if (!link)
|
|
643
|
+
return;
|
|
644
|
+
const hash = createHash('sha256')
|
|
645
|
+
.update(JSON.stringify(base), 'utf8')
|
|
646
|
+
.digest('hex');
|
|
647
|
+
link.base = base;
|
|
648
|
+
link.baseHash = `sha256:${hash}`;
|
|
649
|
+
link.remoteRev = remoteRev;
|
|
650
|
+
link.syncedAt = syncedAt;
|
|
651
|
+
}
|
|
652
|
+
// ---------------------------------------------------------------------------
|
|
653
|
+
// Cursor management
|
|
654
|
+
// ---------------------------------------------------------------------------
|
|
655
|
+
/**
|
|
656
|
+
* Return the cursor to hand to the provider on the next pull, or `null` when
|
|
657
|
+
* a full scan should be performed.
|
|
658
|
+
*
|
|
659
|
+
* A stored cursor lets the pull ask the remote only for issues updated since
|
|
660
|
+
* the last successful sync. The cursor is an opaque value the remote supplied
|
|
661
|
+
* — a page token, a timestamp, a revision hash — and its meaning is the
|
|
662
|
+
* provider's alone.
|
|
663
|
+
*
|
|
664
|
+
* When `fullSync` is `true` (the default on the CLI; `--changed` asks for the
|
|
665
|
+
* incremental listing instead) the stored cursor
|
|
666
|
+
* is ignored and `null` is returned, forcing a full listing. When the
|
|
667
|
+
* provider does not support incremental queries the caller should also pass
|
|
668
|
+
* `null` regardless; this function does not inspect capabilities — the caller
|
|
669
|
+
* knows which provider it is talking to.
|
|
670
|
+
*/
|
|
671
|
+
export function getCursorForPull(store, opts) {
|
|
672
|
+
if (opts?.fullSync)
|
|
673
|
+
return null;
|
|
674
|
+
return store.cursor;
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
* Advance the cursor to a value the **remote** supplied.
|
|
678
|
+
*
|
|
679
|
+
* The cursor must come from the remote's response (a `nextCursor` or
|
|
680
|
+
* equivalent field), never from `Date.now()`. Using local wall-clock time
|
|
681
|
+
* would miss edits made during the sync window whenever the clocks differ —
|
|
682
|
+
* every provider that supports incremental queries returns a server-side
|
|
683
|
+
* marker, and the caller must use it.
|
|
684
|
+
*
|
|
685
|
+
* This function does not validate the value at runtime; the contract is
|
|
686
|
+
* enforced by the pull planner, which is the only caller.
|
|
687
|
+
*/
|
|
688
|
+
export function advanceCursor(store, cursor) {
|
|
689
|
+
store.cursor = cursor;
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Reset the cursor to `null`, forcing the next pull to do a full scan.
|
|
693
|
+
*
|
|
694
|
+
* Safe to call at any time — a store with no cursor is a valid state (it is
|
|
695
|
+
* how every store starts). Useful after a failed pull, when the remote
|
|
696
|
+
* configuration changes, or when the operator wants to rebuild the link
|
|
697
|
+
* store from a fresh crawl.
|
|
698
|
+
*/
|
|
699
|
+
export function clearCursor(store) {
|
|
700
|
+
store.cursor = null;
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Record the one-time first-write consent (LP-350): a person confirmed that
|
|
704
|
+
* writing to this remote is intended, so the next sync no longer asks. Set
|
|
705
|
+
* once; an existing consent is never overwritten, because the confirmation is
|
|
706
|
+
* a fact about the remote, not about this particular run.
|
|
707
|
+
*/
|
|
708
|
+
export function recordConsent(store, at) {
|
|
709
|
+
if (store.consentedAt === undefined)
|
|
710
|
+
store.consentedAt = at;
|
|
711
|
+
}
|
|
712
|
+
/** True when first-write consent has been recorded for this remote. */
|
|
713
|
+
export function isConsented(store) {
|
|
714
|
+
return store.consentedAt !== undefined;
|
|
715
|
+
}
|
|
716
|
+
// ---------------------------------------------------------------------------
|
|
717
|
+
// Validation
|
|
718
|
+
// ---------------------------------------------------------------------------
|
|
719
|
+
/**
|
|
720
|
+
* Validate that an optional field on a link entry has the expected type.
|
|
721
|
+
* Throws `BoardError` naming the path and the offending key when the field is
|
|
722
|
+
* present but of the wrong type — so a hand-edited or merge-mangled file
|
|
723
|
+
* surfaces the mistake rather than silently correcting it.
|
|
724
|
+
*/
|
|
725
|
+
function validateLinkField(link, localId, field, expected, file) {
|
|
726
|
+
const value = link[field];
|
|
727
|
+
if (value === undefined || value === null)
|
|
728
|
+
return; // absent is fine
|
|
729
|
+
if (typeof value !== expected) {
|
|
730
|
+
throw new BoardError(`Invalid link store: ${file}`, [
|
|
731
|
+
`Link "${localId}".${field} must be a ${expected} (got ${typeof value}).`,
|
|
732
|
+
`Delete the ${field} field to clear it, or provide a valid ${expected}.`,
|
|
733
|
+
]);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
// ---------------------------------------------------------------------------
|
|
737
|
+
// Helpers
|
|
738
|
+
// ---------------------------------------------------------------------------
|
|
739
|
+
function emptyStore() {
|
|
740
|
+
return {
|
|
741
|
+
version: 1,
|
|
742
|
+
cursor: null,
|
|
743
|
+
links: new Map(),
|
|
744
|
+
byRemote: new Map(),
|
|
745
|
+
tombstones: new Map(),
|
|
746
|
+
};
|
|
747
|
+
}
|
|
748
|
+
//# sourceMappingURL=links.js.map
|