codetrellis 0.0.0-stage → 0.2.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 +201 -0
- package/README.md +27 -2
- package/bin/codetrellis.mjs +4 -0
- package/package.json +43 -4
- package/reader/material-reader.mjs +130346 -0
- package/resources/tree-sitter/README.md +150 -0
- package/resources/tree-sitter/tree-sitter-c-sharp.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-go.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-java.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-javascript.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-kotlin.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-php.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-python.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-ruby.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-rust.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-swift.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-tsx.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-typescript.wasm +0 -0
- package/resources/tree-sitter/tree-sitter.wasm +0 -0
- package/src/backend/agent/claude-code-watcher.js +270 -0
- package/src/backend/index.js +8 -0
- package/src/backend/lib/sha256-file.js +39 -0
- package/src/backend/lib/zip-entries.js +98 -0
- package/src/backend/lifecycle.js +102 -0
- package/src/backend/mcp/binding-headers.js +54 -0
- package/src/backend/mcp/client-identity.js +44 -0
- package/src/backend/mcp/connector/command.js +110 -0
- package/src/backend/mcp/connector/core.js +278 -0
- package/src/backend/mcp/connector/files.js +121 -0
- package/src/backend/mcp/connector/hook.js +284 -0
- package/src/backend/mcp/connector/main.js +126 -0
- package/src/backend/mcp/connector/sse-upstream.js +152 -0
- package/src/backend/mcp/helpers.js +43 -0
- package/src/backend/mcp/prompt-builders.js +104 -0
- package/src/backend/mcp/resources.js +197 -0
- package/src/backend/mcp/server.js +813 -0
- package/src/backend/mcp/skill-guide.js +1528 -0
- package/src/backend/mcp/tools/architecture-tools.js +273 -0
- package/src/backend/mcp/tools/audio-tools.js +117 -0
- package/src/backend/mcp/tools/awareness-tools.js +623 -0
- package/src/backend/mcp/tools/budget-tools.js +185 -0
- package/src/backend/mcp/tools/channel-tools.js +205 -0
- package/src/backend/mcp/tools/contribution-tools.js +181 -0
- package/src/backend/mcp/tools/drift-tools.js +252 -0
- package/src/backend/mcp/tools/git-tools.js +316 -0
- package/src/backend/mcp/tools/governance-tools.js +175 -0
- package/src/backend/mcp/tools/graph-tools.js +181 -0
- package/src/backend/mcp/tools/intake-tools.js +244 -0
- package/src/backend/mcp/tools/mobile-tools.js +118 -0
- package/src/backend/mcp/tools/peer-tools.js +330 -0
- package/src/backend/mcp/tools/plan-item-tools.js +1601 -0
- package/src/backend/mcp/tools/plan-tools.js +680 -0
- package/src/backend/mcp/tools/presence-tools.js +185 -0
- package/src/backend/mcp/tools/project-config-tools.js +150 -0
- package/src/backend/mcp/tools/review-tools.js +172 -0
- package/src/backend/mcp/tools/session-tools.js +554 -0
- package/src/backend/mcp/tools/system-docs-tools.js +168 -0
- package/src/backend/mcp/tools/terminal-tools.js +186 -0
- package/src/backend/mcp/tools/test-tools.js +117 -0
- package/src/backend/mcp/tools/ui-tools.js +356 -0
- package/src/backend/mcp/types.js +15 -0
- package/src/backend/middleware/local-auth.js +116 -0
- package/src/backend/server.js +5951 -0
- package/src/backend/services/agent-event-log.js +350 -0
- package/src/backend/services/architecture-rule.js +584 -0
- package/src/backend/services/architecture-rules.js +275 -0
- package/src/backend/services/artefact-content-service.js +181 -0
- package/src/backend/services/artefact-service.js +305 -0
- package/src/backend/services/artefact-watcher.js +167 -0
- package/src/backend/services/ast-parser.js +327 -0
- package/src/backend/services/audio-buffer-service.js +152 -0
- package/src/backend/services/awareness-notices.js +139 -0
- package/src/backend/services/awareness-replies.js +194 -0
- package/src/backend/services/awareness-service.js +344 -0
- package/src/backend/services/awareness-signals.js +267 -0
- package/src/backend/services/baseline-store.js +83 -0
- package/src/backend/services/branch-workstreams.js +341 -0
- package/src/backend/services/breakpoint-service.js +584 -0
- package/src/backend/services/brief-service.js +299 -0
- package/src/backend/services/budget-service.js +528 -0
- package/src/backend/services/callsites/base.js +15 -0
- package/src/backend/services/callsites/csharp.js +148 -0
- package/src/backend/services/callsites/go.js +163 -0
- package/src/backend/services/callsites/index.js +53 -0
- package/src/backend/services/callsites/kotlin.js +123 -0
- package/src/backend/services/callsites/process-env.js +125 -0
- package/src/backend/services/callsites/python.js +91 -0
- package/src/backend/services/callsites/ruby.js +164 -0
- package/src/backend/services/callsites/shared.js +198 -0
- package/src/backend/services/callsites/swift.js +115 -0
- package/src/backend/services/callsites/typescript.js +87 -0
- package/src/backend/services/capability-token.js +108 -0
- package/src/backend/services/change-check.js +156 -0
- package/src/backend/services/channel-dispatcher-service.js +235 -0
- package/src/backend/services/channel-event-file-service.js +125 -0
- package/src/backend/services/channel-event-service.js +297 -0
- package/src/backend/services/check-runs.js +177 -0
- package/src/backend/services/checkout-identity.js +73 -0
- package/src/backend/services/claude-code-parallel.js +221 -0
- package/src/backend/services/claude-desktop-config.js +186 -0
- package/src/backend/services/clock.js +57 -0
- package/src/backend/services/cloud-files.js +191 -0
- package/src/backend/services/coalesce.js +50 -0
- package/src/backend/services/code-breakpoints.js +291 -0
- package/src/backend/services/comment-service.js +168 -0
- package/src/backend/services/commit-attribution.js +134 -0
- package/src/backend/services/commit-edges.js +99 -0
- package/src/backend/services/confined-fs.js +241 -0
- package/src/backend/services/conformity-gate.js +132 -0
- package/src/backend/services/contribution-service.js +409 -0
- package/src/backend/services/coverage-service.js +173 -0
- package/src/backend/services/criteria-service.js +721 -0
- package/src/backend/services/criterion-checks.js +387 -0
- package/src/backend/services/criterion-loop-service.js +411 -0
- package/src/backend/services/cross-system-service.js +231 -0
- package/src/backend/services/database.js +916 -0
- package/src/backend/services/db-schema.js +1358 -0
- package/src/backend/services/deviation-service.js +344 -0
- package/src/backend/services/diff-engine.js +168 -0
- package/src/backend/services/evidence.js +363 -0
- package/src/backend/services/external-intake-service.js +269 -0
- package/src/backend/services/external-pointer-service.js +195 -0
- package/src/backend/services/external-refs-service.js +214 -0
- package/src/backend/services/file-history.js +158 -0
- package/src/backend/services/file-watcher.js +193 -0
- package/src/backend/services/folder-requests.js +118 -0
- package/src/backend/services/freeze-service.js +189 -0
- package/src/backend/services/gemini-cli-hook.js +172 -0
- package/src/backend/services/git-activity-service.js +325 -0
- package/src/backend/services/git-blobs.js +70 -0
- package/src/backend/services/git-branches.js +357 -0
- package/src/backend/services/git-checkout.js +153 -0
- package/src/backend/services/git-commit-service.js +91 -0
- package/src/backend/services/git-env.js +121 -0
- package/src/backend/services/git-identity.js +84 -0
- package/src/backend/services/git-refs.js +386 -0
- package/src/backend/services/git-safety.js +58 -0
- package/src/backend/services/grant-guard.js +67 -0
- package/src/backend/services/html-view-policy.js +135 -0
- package/src/backend/services/human-decision.js +55 -0
- package/src/backend/services/importers.js +159 -0
- package/src/backend/services/intent-service.js +105 -0
- package/src/backend/services/ipc-dispatcher.js +164 -0
- package/src/backend/services/item-git-state.js +208 -0
- package/src/backend/services/line-changes.js +232 -0
- package/src/backend/services/line-history.js +174 -0
- package/src/backend/services/local-api-changes.js +40 -0
- package/src/backend/services/logger.js +217 -0
- package/src/backend/services/material-footprints.js +203 -0
- package/src/backend/services/material-place.js +82 -0
- package/src/backend/services/material-reader/child.js +4 -0
- package/src/backend/services/material-reader/docx-markdown.js +198 -0
- package/src/backend/services/material-reader/fixtures.test-helper.js +169 -0
- package/src/backend/services/material-reader/quote.js +44 -0
- package/src/backend/services/material-reader/read.js +430 -0
- package/src/backend/services/material-reader/reader-host.js +202 -0
- package/src/backend/services/material-signals.js +141 -0
- package/src/backend/services/mcp-capabilities.js +390 -0
- package/src/backend/services/mdns-service.js +304 -0
- package/src/backend/services/mobile-api-server.js +281 -0
- package/src/backend/services/mobile-approvals.js +306 -0
- package/src/backend/services/mobile-awareness.js +180 -0
- package/src/backend/services/mobile-breakpoints.js +115 -0
- package/src/backend/services/mobile-budget.js +98 -0
- package/src/backend/services/mobile-freeze.js +106 -0
- package/src/backend/services/mobile-proposals.js +100 -0
- package/src/backend/services/mobile-rpc-service.js +1289 -0
- package/src/backend/services/mobile-workstreams.js +160 -0
- package/src/backend/services/monorepo-detector.js +131 -0
- package/src/backend/services/other-work.js +45 -0
- package/src/backend/services/pack-seal.js +129 -0
- package/src/backend/services/paired-device-service.js +192 -0
- package/src/backend/services/pairing-server.js +323 -0
- package/src/backend/services/pairing-service.js +200 -0
- package/src/backend/services/pantry-resolution-service.js +166 -0
- package/src/backend/services/parsers/base.js +124 -0
- package/src/backend/services/parsers/csharp.js +224 -0
- package/src/backend/services/parsers/go.js +180 -0
- package/src/backend/services/parsers/index.js +101 -0
- package/src/backend/services/parsers/java.js +103 -0
- package/src/backend/services/parsers/kotlin.js +252 -0
- package/src/backend/services/parsers/php.js +113 -0
- package/src/backend/services/parsers/python.js +189 -0
- package/src/backend/services/parsers/ruby.js +212 -0
- package/src/backend/services/parsers/rust.js +97 -0
- package/src/backend/services/parsers/swift.js +221 -0
- package/src/backend/services/parsers/typescript.js +235 -0
- package/src/backend/services/pattern-scan.js +65 -0
- package/src/backend/services/patterns.js +281 -0
- package/src/backend/services/peer-audit-service.js +123 -0
- package/src/backend/services/peer-auth.js +153 -0
- package/src/backend/services/peer-capabilities.js +209 -0
- package/src/backend/services/peer-connection-service.js +450 -0
- package/src/backend/services/peer-grants.js +33 -0
- package/src/backend/services/persistence.js +116 -0
- package/src/backend/services/personal-sync-service.js +232 -0
- package/src/backend/services/pipeline-approvals.js +72 -0
- package/src/backend/services/pipeline.js +232 -0
- package/src/backend/services/plan-arrivals.js +68 -0
- package/src/backend/services/plan-changes-service.js +273 -0
- package/src/backend/services/plan-conflict-service.js +288 -0
- package/src/backend/services/plan-dependencies.js +91 -0
- package/src/backend/services/plan-doc-guard.js +90 -0
- package/src/backend/services/plan-documents-service.js +275 -0
- package/src/backend/services/plan-event-service.js +154 -0
- package/src/backend/services/plan-file-refs.js +106 -0
- package/src/backend/services/plan-file-service.js +1564 -0
- package/src/backend/services/plan-history-service.js +156 -0
- package/src/backend/services/plan-import-service.js +261 -0
- package/src/backend/services/plan-item-service.js +1223 -0
- package/src/backend/services/plan-migrate-service.js +395 -0
- package/src/backend/services/plan-overlay-service.js +173 -0
- package/src/backend/services/plan-phases-service.js +182 -0
- package/src/backend/services/plan-progress-service.js +134 -0
- package/src/backend/services/plan-review-service.js +262 -0
- package/src/backend/services/plan-service.js +682 -0
- package/src/backend/services/plan-status.js +113 -0
- package/src/backend/services/plan-template-publish-service.js +217 -0
- package/src/backend/services/plan-templates-service.js +242 -0
- package/src/backend/services/plan-templates.js +1164 -0
- package/src/backend/services/planned-overlap-actions.js +200 -0
- package/src/backend/services/plans-home.js +224 -0
- package/src/backend/services/play-forward.js +256 -0
- package/src/backend/services/playback-service.js +117 -0
- package/src/backend/services/power-service.js +167 -0
- package/src/backend/services/power-signals.js +81 -0
- package/src/backend/services/pr-draft-service.js +142 -0
- package/src/backend/services/presence-service.js +122 -0
- package/src/backend/services/pricing.js +60 -0
- package/src/backend/services/project-config-service.js +474 -0
- package/src/backend/services/project-scanner.js +184 -0
- package/src/backend/services/projection-service.js +69 -0
- package/src/backend/services/push-notification-service.js +288 -0
- package/src/backend/services/recent-projects-service.js +204 -0
- package/src/backend/services/record-chain.js +162 -0
- package/src/backend/services/recurrence-rule.js +63 -0
- package/src/backend/services/recurring-agent.js +89 -0
- package/src/backend/services/recurring-scheduler.js +77 -0
- package/src/backend/services/recurring-service.js +276 -0
- package/src/backend/services/reference-service.js +169 -0
- package/src/backend/services/release-public-key.js +30 -0
- package/src/backend/services/release-signature.js +64 -0
- package/src/backend/services/remote-audio-service.js +224 -0
- package/src/backend/services/remote-interaction-service.js +275 -0
- package/src/backend/services/remote-terminal-service.js +324 -0
- package/src/backend/services/rendition/child/main.js +76 -0
- package/src/backend/services/rendition/engine-host.js +249 -0
- package/src/backend/services/rendition/engine-lock.js +39 -0
- package/src/backend/services/rendition/engine-lock.json +14 -0
- package/src/backend/services/rendition/engine-manifest.js +97 -0
- package/src/backend/services/rendition/network-proof.js +73 -0
- package/src/backend/services/rendition/rendition-service.js +175 -0
- package/src/backend/services/replay-frames.js +387 -0
- package/src/backend/services/replay-state.js +201 -0
- package/src/backend/services/resolvers/base.js +108 -0
- package/src/backend/services/resolvers/csharp.js +109 -0
- package/src/backend/services/resolvers/go.js +105 -0
- package/src/backend/services/resolvers/index.js +60 -0
- package/src/backend/services/resolvers/java.js +63 -0
- package/src/backend/services/resolvers/kotlin.js +109 -0
- package/src/backend/services/resolvers/php.js +89 -0
- package/src/backend/services/resolvers/python.js +154 -0
- package/src/backend/services/resolvers/ruby.js +103 -0
- package/src/backend/services/resolvers/rust.js +77 -0
- package/src/backend/services/resolvers/swift.js +98 -0
- package/src/backend/services/resolvers/typescript.js +71 -0
- package/src/backend/services/retention.js +54 -0
- package/src/backend/services/review-architecture.js +236 -0
- package/src/backend/services/review-attest.js +68 -0
- package/src/backend/services/review-bundle.js +226 -0
- package/src/backend/services/review-graduation.js +93 -0
- package/src/backend/services/review-host/bitbucket.js +79 -0
- package/src/backend/services/review-host/detect.js +80 -0
- package/src/backend/services/review-host/github.js +97 -0
- package/src/backend/services/review-host/gitlab.js +77 -0
- package/src/backend/services/review-host/host-state.js +103 -0
- package/src/backend/services/review-host/http.js +58 -0
- package/src/backend/services/review-host/switch.js +120 -0
- package/src/backend/services/review-marks.js +72 -0
- package/src/backend/services/review-notes.js +169 -0
- package/src/backend/services/review-other-work.js +90 -0
- package/src/backend/services/review-queue-service.js +147 -0
- package/src/backend/services/review-risk.js +127 -0
- package/src/backend/services/review-task.js +121 -0
- package/src/backend/services/rule-approvals.js +268 -0
- package/src/backend/services/rule-baseline.js +134 -0
- package/src/backend/services/rule-changes.js +162 -0
- package/src/backend/services/rule-preview.js +47 -0
- package/src/backend/services/rule-proposals.js +104 -0
- package/src/backend/services/rule-scope.js +76 -0
- package/src/backend/services/rulebook.js +286 -0
- package/src/backend/services/rules-at.js +56 -0
- package/src/backend/services/rules-overview.js +88 -0
- package/src/backend/services/schema-reconciler.js +250 -0
- package/src/backend/services/secret-store.js +119 -0
- package/src/backend/services/section-workstreams.js +95 -0
- package/src/backend/services/self-write-tracker.js +75 -0
- package/src/backend/services/sensor-bridge-service.js +285 -0
- package/src/backend/services/session-service.js +192 -0
- package/src/backend/services/settings-service.js +324 -0
- package/src/backend/services/signal-breakpoints.js +172 -0
- package/src/backend/services/signed-approval-record.js +86 -0
- package/src/backend/services/signed-approvals.js +244 -0
- package/src/backend/services/signoff-pack.js +328 -0
- package/src/backend/services/signoff-rows.js +114 -0
- package/src/backend/services/skill-arrival-service.js +138 -0
- package/src/backend/services/skill-model.js +193 -0
- package/src/backend/services/skill-use-service.js +140 -0
- package/src/backend/services/skills-service.js +150 -0
- package/src/backend/services/snapshot-compare-service.js +397 -0
- package/src/backend/services/source-control.js +189 -0
- package/src/backend/services/spec-links-service.js +123 -0
- package/src/backend/services/spec-proposal-withdraw.js +50 -0
- package/src/backend/services/spec-proposals-service.js +470 -0
- package/src/backend/services/sql/embedded.js +95 -0
- package/src/backend/services/sql/index.js +63 -0
- package/src/backend/services/sql/refs.js +357 -0
- package/src/backend/services/sql/schema.js +312 -0
- package/src/backend/services/sql/tokenizer.js +195 -0
- package/src/backend/services/stack-overlaps.js +117 -0
- package/src/backend/services/stack-service.js +225 -0
- package/src/backend/services/state-sync-service.js +384 -0
- package/src/backend/services/stuck-sensor-service.js +200 -0
- package/src/backend/services/system-discovery.js +481 -0
- package/src/backend/services/system-docs-service.js +701 -0
- package/src/backend/services/task-attachments-service.js +340 -0
- package/src/backend/services/task-grounding.js +60 -0
- package/src/backend/services/task-records/check-run-record.js +146 -0
- package/src/backend/services/task-records/check-runs.js +115 -0
- package/src/backend/services/task-records/heads.js +88 -0
- package/src/backend/services/task-records/material-reads.js +225 -0
- package/src/backend/services/task-records/read-record.js +100 -0
- package/src/backend/services/task-records/record.js +173 -0
- package/src/backend/services/task-records/run-record.js +136 -0
- package/src/backend/services/task-records/shared-state.js +548 -0
- package/src/backend/services/task-records/signing.js +140 -0
- package/src/backend/services/task-records/split-signals.js +52 -0
- package/src/backend/services/task-records/test-runs.js +164 -0
- package/src/backend/services/task-records/trust.js +243 -0
- package/src/backend/services/task-rules.js +81 -0
- package/src/backend/services/task-workstreams.js +90 -0
- package/src/backend/services/terminal-history-service.js +266 -0
- package/src/backend/services/terminal-service.js +267 -0
- package/src/backend/services/test-clock.js +53 -0
- package/src/backend/services/tests/grounding.js +266 -0
- package/src/backend/services/tests/junit.js +104 -0
- package/src/backend/services/tests/teammate-runs.js +134 -0
- package/src/backend/services/tests/test-results.js +234 -0
- package/src/backend/services/tree-watcher.js +204 -0
- package/src/backend/services/trellis-service.js +204 -0
- package/src/backend/services/trusted-roots.js +186 -0
- package/src/backend/services/update-download-service.js +342 -0
- package/src/backend/services/update-service.js +266 -0
- package/src/backend/services/watch-ignore.js +76 -0
- package/src/backend/services/webhook-egress.js +206 -0
- package/src/backend/services/webrtc-service.js +413 -0
- package/src/backend/services/work-changes.js +59 -0
- package/src/backend/services/workstream-binding.js +82 -0
- package/src/backend/services/workstream-commits.js +116 -0
- package/src/backend/services/workstream-imports.js +177 -0
- package/src/backend/services/workstream-service.js +335 -0
- package/src/backend/services/workstream-symbols.js +223 -0
- package/src/backend/services/workstream-watch-service.js +391 -0
- package/src/backend/services/worktree-service.js +235 -0
- package/src/cli/agent.js +100 -0
- package/src/cli/args.js +201 -0
- package/src/cli/conformity.js +106 -0
- package/src/cli/desktop.js +91 -0
- package/src/cli/main.js +409 -0
- package/src/cli/pipeline.js +109 -0
- package/src/cli/plan-verbs.js +259 -0
- package/src/cli/review-adapters.js +218 -0
- package/src/cli/review-output.js +93 -0
- package/src/cli/review-post.js +89 -0
- package/src/cli/review-sink.js +183 -0
- package/src/cli/review-skill.js +44 -0
- package/src/cli/review-verify.js +104 -0
- package/src/cli/review.js +386 -0
- package/src/cli/sarif.js +148 -0
- package/src/cli/verbs.js +359 -0
- package/src/shared/build-info.js +39 -0
- package/src/shared/lib/agent-review.js +199 -0
- package/src/shared/lib/agent-turns.js +140 -0
- package/src/shared/lib/awareness-digest.js +120 -0
- package/src/shared/lib/branch-name.js +45 -0
- package/src/shared/lib/breakpoint-words.js +118 -0
- package/src/shared/lib/budget-words.js +56 -0
- package/src/shared/lib/burst.js +69 -0
- package/src/shared/lib/call-entry.js +105 -0
- package/src/shared/lib/check-compare.js +42 -0
- package/src/shared/lib/check-words.js +216 -0
- package/src/shared/lib/csv.js +62 -0
- package/src/shared/lib/folder-entry.js +87 -0
- package/src/shared/lib/freeze-words.js +60 -0
- package/src/shared/lib/fuzzy.js +84 -0
- package/src/shared/lib/git-state-words.js +80 -0
- package/src/shared/lib/grep-entry.js +86 -0
- package/src/shared/lib/grounding-line.js +61 -0
- package/src/shared/lib/import-line.js +71 -0
- package/src/shared/lib/item-status.js +249 -0
- package/src/shared/lib/line-changes.js +53 -0
- package/src/shared/lib/locator.js +71 -0
- package/src/shared/lib/matcher.js +120 -0
- package/src/shared/lib/merge-order.js +65 -0
- package/src/shared/lib/open-findings.js +68 -0
- package/src/shared/lib/other-work.js +108 -0
- package/src/shared/lib/package-entry.js +142 -0
- package/src/shared/lib/plan-vocab.js +40 -0
- package/src/shared/lib/pptx-xml.js +86 -0
- package/src/shared/lib/proposal-words.js +61 -0
- package/src/shared/lib/recurrence.js +183 -0
- package/src/shared/lib/references.js +72 -0
- package/src/shared/lib/rule-pattern.js +56 -0
- package/src/shared/lib/sdp-fingerprint.js +115 -0
- package/src/shared/lib/sdp-minimal.js +123 -0
- package/src/shared/lib/secret-paths.js +34 -0
- package/src/shared/lib/signal-words.js +172 -0
- package/src/shared/lib/signoff.js +56 -0
- package/src/shared/lib/skills-note.js +60 -0
- package/src/shared/lib/spec-sections.js +78 -0
- package/src/shared/lib/symbol-entry.js +60 -0
- package/src/shared/lib/tool-phrasing.js +338 -0
- package/src/shared/lib/turn-gap.js +27 -0
- package/src/shared/lib/workstream-words.js +38 -0
- package/src/shared/lib/xlsx-xml.js +144 -0
- package/src/shared/lib/zip-reader.js +99 -0
- package/src/shared/types/agent.js +27 -0
- package/src/shared/types/architecture-rules.js +30 -0
- package/src/shared/types/ast.js +15 -0
- package/src/shared/types/breakpoint.js +33 -0
- package/src/shared/types/channel.js +41 -0
- package/src/shared/types/criteria.js +15 -0
- package/src/shared/types/graph.js +15 -0
- package/src/shared/types/index.js +53 -0
- package/src/shared/types/peer.js +36 -0
- package/src/shared/types/pipeline.js +15 -0
- package/src/shared/types/plan.js +15 -0
- package/src/shared/types/play-forward.js +15 -0
- package/src/shared/types/power.js +15 -0
- package/src/shared/types/presence.js +15 -0
- package/src/shared/types/project-config.js +35 -0
- package/src/shared/types/project.js +15 -0
- package/src/shared/types/record.js +15 -0
- package/src/shared/types/recurring.js +15 -0
- package/src/shared/types/review.js +15 -0
- package/src/shared/types/settings.js +114 -0
- package/src/shared/types/stack.js +15 -0
- package/src/shared/types/system-doc.js +15 -0
- package/src/shared/types/system.js +15 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var planned_overlap_actions_exports = {};
|
|
19
|
+
__export(planned_overlap_actions_exports, {
|
|
20
|
+
OverlapActionError: () => OverlapActionError,
|
|
21
|
+
approvalNotices: () => approvalNotices,
|
|
22
|
+
leaveOverlap: () => leaveOverlap,
|
|
23
|
+
markNoticeSeen: () => markNoticeSeen,
|
|
24
|
+
noteApproval: () => noteApproval,
|
|
25
|
+
plannedOverlapNoticeFor: () => plannedOverlapNoticeFor,
|
|
26
|
+
resequence: () => resequence,
|
|
27
|
+
tellAgents: () => tellAgents
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(planned_overlap_actions_exports);
|
|
30
|
+
var import_database = require("./database");
|
|
31
|
+
var import_persistence = require("./persistence");
|
|
32
|
+
var import_play_forward = require("./play-forward");
|
|
33
|
+
var import_plan_item_service = require("./plan-item-service");
|
|
34
|
+
class OverlapActionError extends Error {
|
|
35
|
+
constructor(status, message) {
|
|
36
|
+
super(message);
|
|
37
|
+
this.status = status;
|
|
38
|
+
}
|
|
39
|
+
status;
|
|
40
|
+
}
|
|
41
|
+
const rows = (sql, params = []) => (0, import_database.getDb)().exec(sql, params)[0]?.values ?? [];
|
|
42
|
+
function find(projectRoot, overlapId) {
|
|
43
|
+
const forward = (0, import_play_forward.buildPlayForward)(projectRoot);
|
|
44
|
+
const overlap = forward.overlaps.find((o) => o.id === overlapId);
|
|
45
|
+
if (!overlap) throw new OverlapActionError(404, "No such planned overlap: the plans may have changed since. Play forward again.");
|
|
46
|
+
return { forward, overlap };
|
|
47
|
+
}
|
|
48
|
+
function record(projectRoot, overlapId, action, words, by, now) {
|
|
49
|
+
(0, import_database.getDb)().run(
|
|
50
|
+
"INSERT INTO planned_overlap_decisions (overlap_id, project_root, action, words, by_name, by_type, at) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
|
51
|
+
[overlapId, projectRoot, action, words, by.author, by.authorType, now]
|
|
52
|
+
);
|
|
53
|
+
(0, import_persistence.markDirty)();
|
|
54
|
+
}
|
|
55
|
+
function waitsOn(from, to, seen = /* @__PURE__ */ new Set()) {
|
|
56
|
+
if (seen.has(from)) return false;
|
|
57
|
+
seen.add(from);
|
|
58
|
+
for (const d of (0, import_plan_item_service.getItem)(from)?.dependencies ?? []) {
|
|
59
|
+
if (to.has(d) || waitsOn(d, to, seen)) return true;
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
function resequence(projectRoot, overlapId, firstPlanUid, by, now = Date.now()) {
|
|
64
|
+
const { overlap } = find(projectRoot, overlapId);
|
|
65
|
+
const first = overlap.plans.find((p) => p.uid === firstPlanUid);
|
|
66
|
+
if (!first) throw new OverlapActionError(400, `That plan is not in this planned overlap. Choose one of: ${overlap.plans.map((p) => p.label).join(", ")}.`);
|
|
67
|
+
const firstTasks = first.tasks.map((t) => t.uid);
|
|
68
|
+
const later = overlap.plans.filter((p) => p.uid !== firstPlanUid).flatMap((p) => p.tasks);
|
|
69
|
+
const laterSet = new Set(later.map((t) => t.uid));
|
|
70
|
+
const loop = firstTasks.find((t) => waitsOn(t, laterSet));
|
|
71
|
+
if (loop) {
|
|
72
|
+
throw new OverlapActionError(409, `${first.label} cannot go first: its task "${(0, import_plan_item_service.getItem)(loop)?.title ?? loop}" already waits on the other plan's work, so they would wait on each other.`);
|
|
73
|
+
}
|
|
74
|
+
const waiting = [];
|
|
75
|
+
for (const t of later) {
|
|
76
|
+
const item = (0, import_plan_item_service.getItem)(t.uid);
|
|
77
|
+
if (!item) continue;
|
|
78
|
+
const deps = [.../* @__PURE__ */ new Set([...item.dependencies ?? [], ...firstTasks])];
|
|
79
|
+
if (deps.length === (item.dependencies ?? []).length) continue;
|
|
80
|
+
(0, import_plan_item_service.updateItem)(item.uid, {
|
|
81
|
+
dependencies: deps,
|
|
82
|
+
author: by.author,
|
|
83
|
+
authorType: by.authorType,
|
|
84
|
+
changeSummary: `Waits on ${first.label} (re-sequenced over a planned overlap on ${overlap.subject})`
|
|
85
|
+
});
|
|
86
|
+
waiting.push({ uid: item.uid, title: item.title });
|
|
87
|
+
}
|
|
88
|
+
const others = overlap.plans.filter((p) => p.uid !== firstPlanUid).map((p) => p.label).join(", ");
|
|
89
|
+
record(projectRoot, overlapId, "resequence", `${first.label} goes first; ${others} waits`, by, now);
|
|
90
|
+
return { overlap: find(projectRoot, overlapId).overlap, waiting };
|
|
91
|
+
}
|
|
92
|
+
function tellText(o, sessionTaskUids, by) {
|
|
93
|
+
const mine = o.plans.flatMap((p) => p.tasks.filter((t) => sessionTaskUids.has(t.uid)).map((t) => `"${t.title}" (${p.label})`));
|
|
94
|
+
const theirs = o.plans.flatMap((p) => p.tasks.filter((t) => !sessionTaskUids.has(t.uid)).map((t) => `"${t.title}" in ${p.label}`));
|
|
95
|
+
return [
|
|
96
|
+
"\u2500\u2500 CodeTrellis: planned overlap \u2500\u2500",
|
|
97
|
+
`${by} asks you to know: ${o.words.replace(/^◇ planned overlap: /, "")}.`,
|
|
98
|
+
theirs.length ? `Your ${mine.length === 1 ? "task" : "tasks"} ${mine.join(", ")} and ${theirs.join(", ")} both plan to touch ${o.kind === "material" ? "it" : o.subject}.` : `Your tasks ${mine.join(", ")} all plan to touch ${o.kind === "material" ? "it" : o.subject}.`,
|
|
99
|
+
`${o.serious ? "This one is serious. " : ""}Agree an order before changing it: get_play_forward shows the plans, and a person can re-sequence them.`
|
|
100
|
+
].join("\n");
|
|
101
|
+
}
|
|
102
|
+
function tellAgents(projectRoot, overlapId, by, now = Date.now()) {
|
|
103
|
+
const { overlap } = find(projectRoot, overlapId);
|
|
104
|
+
const bySession = /* @__PURE__ */ new Map();
|
|
105
|
+
const without = [];
|
|
106
|
+
for (const p of overlap.plans) {
|
|
107
|
+
for (const t of p.tasks) {
|
|
108
|
+
const session = (0, import_plan_item_service.getItem)(t.uid)?.assigneeSession ?? null;
|
|
109
|
+
if (!session) {
|
|
110
|
+
without.push(t.title);
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
bySession.set(session, (bySession.get(session) ?? /* @__PURE__ */ new Set()).add(t.uid));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
for (const [session, taskUids] of bySession) {
|
|
117
|
+
(0, import_database.getDb)().run(
|
|
118
|
+
`INSERT INTO planned_overlap_tells (overlap_id, session_id, text, created_at, read_at) VALUES (?, ?, ?, ?, NULL)
|
|
119
|
+
ON CONFLICT(overlap_id, session_id) DO UPDATE SET text = excluded.text, created_at = excluded.created_at, read_at = NULL`,
|
|
120
|
+
[overlapId, session, tellText(overlap, taskUids, by.author), now]
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
const n = bySession.size;
|
|
124
|
+
record(
|
|
125
|
+
projectRoot,
|
|
126
|
+
overlapId,
|
|
127
|
+
"tell",
|
|
128
|
+
n === 0 ? "No agent holds these tasks yet: nobody was told" : `Told ${n} ${n === 1 ? "agent" : "agents"}${without.length ? `; ${without.length} ${without.length === 1 ? "task has" : "tasks have"} no agent yet` : ""}`,
|
|
129
|
+
by,
|
|
130
|
+
now
|
|
131
|
+
);
|
|
132
|
+
return { told: n, tasksWithoutAgent: without };
|
|
133
|
+
}
|
|
134
|
+
function leaveOverlap(projectRoot, overlapId, by, now = Date.now()) {
|
|
135
|
+
find(projectRoot, overlapId);
|
|
136
|
+
record(projectRoot, overlapId, "leave", `Left as it is by ${by.author}`, by, now);
|
|
137
|
+
}
|
|
138
|
+
function plannedOverlapNoticeFor(sessionId, now = Date.now()) {
|
|
139
|
+
try {
|
|
140
|
+
const unread = rows("SELECT overlap_id, text FROM planned_overlap_tells WHERE session_id = ? AND read_at IS NULL ORDER BY created_at", [sessionId]);
|
|
141
|
+
if (unread.length === 0) return null;
|
|
142
|
+
(0, import_database.getDb)().run("UPDATE planned_overlap_tells SET read_at = ? WHERE session_id = ? AND read_at IS NULL", [now, sessionId]);
|
|
143
|
+
(0, import_persistence.markDirty)();
|
|
144
|
+
return unread.map((r) => String(r[1])).join("\n\n");
|
|
145
|
+
} catch (err) {
|
|
146
|
+
console.warn("[PlayForward] planned overlap notice failed:", err instanceof Error ? err.message : err);
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function noteApproval(projectRoot, planUid, now = Date.now()) {
|
|
151
|
+
try {
|
|
152
|
+
const forward = (0, import_play_forward.buildPlayForward)(projectRoot);
|
|
153
|
+
const label = forward.plans.find((p) => p.uid === planUid)?.label ?? planUid;
|
|
154
|
+
const open = forward.overlaps.filter((o) => !o.sequenced && !o.left && o.plans.some((p) => p.uid === planUid));
|
|
155
|
+
if (open.length === 0) return { overlaps: [], noticeId: null };
|
|
156
|
+
const words = open.map((o) => o.words);
|
|
157
|
+
(0, import_database.getDb)().run(
|
|
158
|
+
"INSERT INTO planned_overlap_notices (project_root, plan_uid, plan_label, words_json, at) VALUES (?, ?, ?, ?, ?)",
|
|
159
|
+
[projectRoot, planUid, label, JSON.stringify(words), now]
|
|
160
|
+
);
|
|
161
|
+
const id = Number(rows("SELECT MAX(id) FROM planned_overlap_notices")[0]?.[0] ?? 0);
|
|
162
|
+
(0, import_persistence.markDirty)();
|
|
163
|
+
return { overlaps: words, noticeId: id };
|
|
164
|
+
} catch (err) {
|
|
165
|
+
console.warn("[PlayForward] approval notice failed:", err instanceof Error ? err.message : err);
|
|
166
|
+
return { overlaps: [], noticeId: null };
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const noticeTitle = (label, n) => `Approving ${label} puts it in ${n === 1 ? "a planned overlap" : `${n} planned overlaps`}`;
|
|
170
|
+
function approvalNotices(projectRoot) {
|
|
171
|
+
return rows(
|
|
172
|
+
"SELECT id, plan_uid, plan_label, words_json, at FROM planned_overlap_notices WHERE project_root = ? AND seen_at IS NULL ORDER BY at DESC, id DESC",
|
|
173
|
+
[projectRoot]
|
|
174
|
+
).map((r) => {
|
|
175
|
+
let overlaps = [];
|
|
176
|
+
try {
|
|
177
|
+
overlaps = JSON.parse(String(r[3]));
|
|
178
|
+
} catch {
|
|
179
|
+
}
|
|
180
|
+
return { id: Number(r[0]), planUid: String(r[1]), planLabel: String(r[2]), title: noticeTitle(String(r[2]), overlaps.length), overlaps, at: Number(r[4]) };
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
function markNoticeSeen(projectRoot, id, by, now = Date.now()) {
|
|
184
|
+
const open = rows("SELECT 1 FROM planned_overlap_notices WHERE id = ? AND project_root = ? AND seen_at IS NULL", [id, projectRoot]).length > 0;
|
|
185
|
+
if (!open) return false;
|
|
186
|
+
(0, import_database.getDb)().run("UPDATE planned_overlap_notices SET seen_at = ?, seen_by = ? WHERE id = ?", [now, by.author, id]);
|
|
187
|
+
(0, import_persistence.markDirty)();
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
191
|
+
0 && (module.exports = {
|
|
192
|
+
OverlapActionError,
|
|
193
|
+
approvalNotices,
|
|
194
|
+
leaveOverlap,
|
|
195
|
+
markNoticeSeen,
|
|
196
|
+
noteApproval,
|
|
197
|
+
plannedOverlapNoticeFor,
|
|
198
|
+
resequence,
|
|
199
|
+
tellAgents
|
|
200
|
+
});
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
var plans_home_exports = {};
|
|
29
|
+
__export(plans_home_exports, {
|
|
30
|
+
PlansFolderError: () => PlansFolderError,
|
|
31
|
+
folderWords: () => folderWords,
|
|
32
|
+
getPlansFolder: () => getPlansFolder,
|
|
33
|
+
linkPlansFolder: () => linkPlansFolder,
|
|
34
|
+
linkedPlansHomes: () => linkedPlansHomes,
|
|
35
|
+
matchesRef: () => matchesRef,
|
|
36
|
+
namePlansFolder: () => namePlansFolder,
|
|
37
|
+
normaliseRemote: () => normaliseRemote,
|
|
38
|
+
plansHome: () => plansHome,
|
|
39
|
+
projectOfPlansHome: () => projectOfPlansHome,
|
|
40
|
+
unlinkPlansFolder: () => unlinkPlansFolder
|
|
41
|
+
});
|
|
42
|
+
module.exports = __toCommonJS(plans_home_exports);
|
|
43
|
+
var import_node_fs = __toESM(require("node:fs"));
|
|
44
|
+
var import_node_path = __toESM(require("node:path"));
|
|
45
|
+
var import_node_child_process = require("node:child_process");
|
|
46
|
+
var import_database = require("./database");
|
|
47
|
+
var import_persistence = require("./persistence");
|
|
48
|
+
var import_project_config_service = require("./project-config-service");
|
|
49
|
+
var import_cloud_files = require("./cloud-files");
|
|
50
|
+
const MAX_WALK = 2e4;
|
|
51
|
+
function countPlaceholders(home) {
|
|
52
|
+
let n = 0;
|
|
53
|
+
let seen = 0;
|
|
54
|
+
const walk = (dir) => {
|
|
55
|
+
let entries;
|
|
56
|
+
try {
|
|
57
|
+
entries = import_node_fs.default.readdirSync(dir, { withFileTypes: true });
|
|
58
|
+
} catch {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
for (const e of entries) {
|
|
62
|
+
if (++seen > MAX_WALK) return;
|
|
63
|
+
const p = import_node_path.default.join(dir, e.name);
|
|
64
|
+
if (e.isDirectory()) walk(p);
|
|
65
|
+
else if (e.isFile() && (0, import_cloud_files.isPlaceholder)(p)) n++;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
walk(import_node_path.default.join(home, ".codetrellis"));
|
|
69
|
+
return n;
|
|
70
|
+
}
|
|
71
|
+
class PlansFolderError extends Error {
|
|
72
|
+
}
|
|
73
|
+
function linkRow(projectRoot) {
|
|
74
|
+
const db = (0, import_database.getDb)();
|
|
75
|
+
let v = db.exec(
|
|
76
|
+
"SELECT local_path, ref, confirmed_at, confirmed_by FROM linked_plans_folder WHERE project_root = ?",
|
|
77
|
+
[projectRoot]
|
|
78
|
+
)[0]?.values[0];
|
|
79
|
+
if (!v) {
|
|
80
|
+
const want = canonical(projectRoot);
|
|
81
|
+
if (want) {
|
|
82
|
+
v = (db.exec("SELECT project_root, local_path, ref, confirmed_at, confirmed_by FROM linked_plans_folder")[0]?.values ?? []).find((r) => canonical(String(r[0])) === want)?.slice(1);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return v ? { path: String(v[0]), ref: String(v[1]), confirmedAt: Number(v[2]), confirmedBy: String(v[3]) } : null;
|
|
86
|
+
}
|
|
87
|
+
const refKey = (ref) => JSON.stringify(ref);
|
|
88
|
+
function folderWords(ref) {
|
|
89
|
+
if (ref.kind === "git") return `the planning repository ${normaliseRemote(ref.remote)}`;
|
|
90
|
+
const provider = ref.provider === "onedrive" ? "OneDrive" : ref.provider === "sharepoint" ? "SharePoint" : "a synced folder";
|
|
91
|
+
return `${provider}: ${ref.place}`;
|
|
92
|
+
}
|
|
93
|
+
function stateOf(projectRoot) {
|
|
94
|
+
const named = (0, import_project_config_service.getProjectConfig)(projectRoot).plans?.folder ?? null;
|
|
95
|
+
const row = linkRow(projectRoot);
|
|
96
|
+
if (!named) return { named, state: "here", row };
|
|
97
|
+
if (!row) return { named, state: "unlinked", row };
|
|
98
|
+
if (row.ref !== refKey(named)) return { named, state: "changed", row };
|
|
99
|
+
let dir = false;
|
|
100
|
+
try {
|
|
101
|
+
dir = import_node_fs.default.statSync(row.path).isDirectory();
|
|
102
|
+
} catch {
|
|
103
|
+
}
|
|
104
|
+
return { named, state: dir ? "linked" : "missing", row };
|
|
105
|
+
}
|
|
106
|
+
function plansHome(projectRoot) {
|
|
107
|
+
const { state, row } = stateOf(projectRoot);
|
|
108
|
+
if (state === "here") return projectRoot;
|
|
109
|
+
return state === "linked" ? row.path : null;
|
|
110
|
+
}
|
|
111
|
+
function projectOfPlansHome(dir) {
|
|
112
|
+
const canon = canonical(dir);
|
|
113
|
+
if (!canon) return null;
|
|
114
|
+
for (const r of (0, import_database.getDb)().exec("SELECT project_root, local_path FROM linked_plans_folder")[0]?.values ?? []) {
|
|
115
|
+
if (canonical(String(r[1])) === canon && plansHome(String(r[0])) !== null) return String(r[0]);
|
|
116
|
+
}
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
function linkedPlansHomes() {
|
|
120
|
+
return ((0, import_database.getDb)().exec("SELECT project_root FROM linked_plans_folder")[0]?.values ?? []).map((r) => String(r[0])).map((project) => ({ project, home: plansHome(project) })).filter((x) => !!x.home && x.home !== x.project);
|
|
121
|
+
}
|
|
122
|
+
function getPlansFolder(projectRoot) {
|
|
123
|
+
const { named, state, row } = stateOf(projectRoot);
|
|
124
|
+
const linked = row && state !== "unlinked" ? { path: row.path, confirmedAt: row.confirmedAt, confirmedBy: row.confirmedBy } : null;
|
|
125
|
+
const where = named ? folderWords(named) : "";
|
|
126
|
+
const says = {
|
|
127
|
+
here: "This project's plans live in the project itself, under .codetrellis/plans.",
|
|
128
|
+
linked: `This project's plans live in ${where}. On this device that is ${row?.path}.`,
|
|
129
|
+
unlinked: `This project's plans live in ${where}. Link your copy of it on this device to see them; until then nothing there is read.`,
|
|
130
|
+
changed: `The project now names ${where} for its plans, not the folder linked on this device. Link your copy of it; until then nothing is read.`,
|
|
131
|
+
missing: `This project's plans live in ${where}, linked on this device at ${row?.path}, which is not there now. Nothing is read until it is back or linked again.`
|
|
132
|
+
}[state];
|
|
133
|
+
const home = state === "linked" ? row.path : state === "here" ? projectRoot : null;
|
|
134
|
+
const notOnDevice = home ? countPlaceholders(home) : 0;
|
|
135
|
+
const roots = (0, import_cloud_files.cloudRoots)();
|
|
136
|
+
const found = named?.kind === "synced" && named.provider !== "folder" && state !== "linked" ? (0, import_cloud_files.findPlace)(named.provider, named.place, roots) : null;
|
|
137
|
+
const keep = notOnDevice ? ` ${notOnDevice} ${notOnDevice === 1 ? "file in it is" : "files in it are"} not on this device yet and ${notOnDevice === 1 ? "is" : "are"} not read until ${notOnDevice === 1 ? "it is" : "they are"}: set the folder to "Always keep on this device" in OneDrive.` : "";
|
|
138
|
+
return { project: projectRoot, named, state, linked, says: says + keep, roots, found, notOnDevice };
|
|
139
|
+
}
|
|
140
|
+
function namePlansFolder(projectRoot, ref) {
|
|
141
|
+
(0, import_project_config_service.updateProjectConfig)(projectRoot, { plans: { folder: ref ?? void 0 } });
|
|
142
|
+
return getPlansFolder(projectRoot);
|
|
143
|
+
}
|
|
144
|
+
function canonical(p) {
|
|
145
|
+
try {
|
|
146
|
+
return import_node_fs.default.realpathSync.native(import_node_path.default.resolve(p));
|
|
147
|
+
} catch {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function normaliseRemote(remote) {
|
|
152
|
+
let r = remote.trim();
|
|
153
|
+
const scp = /^[^@/\s]+@([^:/\s]+):(.+)$/.exec(r);
|
|
154
|
+
if (scp) r = `${scp[1]}/${scp[2]}`;
|
|
155
|
+
else r = r.replace(/^[a-z][a-z0-9+.-]*:\/\//i, "").replace(/^[^@/]*@/, "");
|
|
156
|
+
r = r.replace(/\.git\/?$/i, "").replace(/\/+$/, "");
|
|
157
|
+
const slash = r.indexOf("/");
|
|
158
|
+
return slash < 0 ? r.toLowerCase() : r.slice(0, slash).toLowerCase() + r.slice(slash);
|
|
159
|
+
}
|
|
160
|
+
function remotesOf(dir) {
|
|
161
|
+
try {
|
|
162
|
+
const out = (0, import_node_child_process.execFileSync)("git", ["-C", dir, "remote", "-v"], { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"], timeout: 5e3 });
|
|
163
|
+
return [...new Set(out.split("\n").map((l) => l.split(/\s+/)[1]).filter((x) => !!x))];
|
|
164
|
+
} catch {
|
|
165
|
+
return [];
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function matchesRef(dir, ref) {
|
|
169
|
+
if (ref.kind === "git") {
|
|
170
|
+
const want = normaliseRemote(ref.remote);
|
|
171
|
+
const have = remotesOf(dir);
|
|
172
|
+
if (have.length === 0) return { ok: false, why: "it is not a git repository with a remote" };
|
|
173
|
+
return have.some((r) => normaliseRemote(r) === want) ? { ok: true } : { ok: false, why: `its remote is ${normaliseRemote(have[0])}, not ${want}` };
|
|
174
|
+
}
|
|
175
|
+
const tail = ref.place.split("/");
|
|
176
|
+
const segs = dir.split(/[\\/]/).filter(Boolean);
|
|
177
|
+
const same = (a, b) => process.platform === "linux" ? a === b : a.toLowerCase() === b.toLowerCase();
|
|
178
|
+
const ends = segs.length >= tail.length && tail.every((t, i) => same(segs[segs.length - tail.length + i], t));
|
|
179
|
+
return ends ? { ok: true } : { ok: false, why: `it is not a folder named ${ref.place}` };
|
|
180
|
+
}
|
|
181
|
+
function linkPlansFolder(projectRoot, localPath, by) {
|
|
182
|
+
const named = (0, import_project_config_service.getProjectConfig)(projectRoot).plans?.folder;
|
|
183
|
+
if (!named) throw new PlansFolderError("This project keeps its plans in the project itself, so there is no folder to link.");
|
|
184
|
+
if (typeof localPath !== "string" || !import_node_path.default.isAbsolute(localPath)) throw new PlansFolderError("Choose the folder on this device: a full path.");
|
|
185
|
+
const dir = canonical(localPath);
|
|
186
|
+
if (!dir) throw new PlansFolderError(`${localPath} is not on this device.`);
|
|
187
|
+
let isDir = false;
|
|
188
|
+
try {
|
|
189
|
+
isDir = import_node_fs.default.statSync(dir).isDirectory();
|
|
190
|
+
} catch {
|
|
191
|
+
}
|
|
192
|
+
if (!isDir) throw new PlansFolderError(`${localPath} is not a folder.`);
|
|
193
|
+
const project = canonical(projectRoot);
|
|
194
|
+
if (project && dir === project) throw new PlansFolderError("That is the project itself. Choose your copy of the plans folder.");
|
|
195
|
+
const match = matchesRef(dir, named);
|
|
196
|
+
if (!match.ok) throw new PlansFolderError(`${localPath} is not ${folderWords(named)}: ${match.why}.`);
|
|
197
|
+
(0, import_database.getDb)().run(
|
|
198
|
+
`INSERT INTO linked_plans_folder (project_root, local_path, ref, confirmed_at, confirmed_by) VALUES (?, ?, ?, ?, ?)
|
|
199
|
+
ON CONFLICT(project_root) DO UPDATE SET local_path = excluded.local_path, ref = excluded.ref,
|
|
200
|
+
confirmed_at = excluded.confirmed_at, confirmed_by = excluded.confirmed_by`,
|
|
201
|
+
[projectRoot, dir, refKey(named), Date.now(), by]
|
|
202
|
+
);
|
|
203
|
+
(0, import_persistence.markDirty)();
|
|
204
|
+
return getPlansFolder(projectRoot);
|
|
205
|
+
}
|
|
206
|
+
function unlinkPlansFolder(projectRoot) {
|
|
207
|
+
(0, import_database.getDb)().run("DELETE FROM linked_plans_folder WHERE project_root = ?", [projectRoot]);
|
|
208
|
+
(0, import_persistence.markDirty)();
|
|
209
|
+
return getPlansFolder(projectRoot);
|
|
210
|
+
}
|
|
211
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
212
|
+
0 && (module.exports = {
|
|
213
|
+
PlansFolderError,
|
|
214
|
+
folderWords,
|
|
215
|
+
getPlansFolder,
|
|
216
|
+
linkPlansFolder,
|
|
217
|
+
linkedPlansHomes,
|
|
218
|
+
matchesRef,
|
|
219
|
+
namePlansFolder,
|
|
220
|
+
normaliseRemote,
|
|
221
|
+
plansHome,
|
|
222
|
+
projectOfPlansHome,
|
|
223
|
+
unlinkPlansFolder
|
|
224
|
+
});
|