codetrellis 0.0.0-stage → 0.3.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 +41 -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/cli-install.js +249 -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/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/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 +275 -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 +209 -0
- package/src/cli/conformity.js +106 -0
- package/src/cli/desktop.js +91 -0
- package/src/cli/main.js +411 -0
- package/src/cli/pipeline.js +109 -0
- package/src/cli/plan-verbs.js +259 -0
- package/src/cli/review-adapters.js +220 -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 +360 -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,470 @@
|
|
|
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 spec_proposals_service_exports = {};
|
|
19
|
+
__export(spec_proposals_service_exports, {
|
|
20
|
+
decideProposal: () => decideProposal,
|
|
21
|
+
decisionProblem: () => decisionProblem,
|
|
22
|
+
directEditNote: () => directEditNote,
|
|
23
|
+
getProposal: () => getProposal,
|
|
24
|
+
impactProblem: () => impactProblem,
|
|
25
|
+
listProposals: () => listProposals,
|
|
26
|
+
pageVersion: () => pageVersion,
|
|
27
|
+
proposalNoticeFor: () => proposalNoticeFor,
|
|
28
|
+
proposalProblem: () => proposalProblem,
|
|
29
|
+
proposalReads: () => proposalReads,
|
|
30
|
+
proposeSpecChange: () => proposeSpecChange,
|
|
31
|
+
replyToProposal: () => replyToProposal,
|
|
32
|
+
specChangedFor: () => specChangedFor
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(spec_proposals_service_exports);
|
|
35
|
+
var import_node_crypto = require("node:crypto");
|
|
36
|
+
var import_database = require("./database");
|
|
37
|
+
var import_persistence = require("./persistence");
|
|
38
|
+
var import_plan_item_service = require("./plan-item-service");
|
|
39
|
+
var import_plan_event_service = require("./plan-event-service");
|
|
40
|
+
var import_breakpoint_service = require("./breakpoint-service");
|
|
41
|
+
var import_agent_event_log = require("./agent-event-log");
|
|
42
|
+
var import_push_notification_service = require("./push-notification-service");
|
|
43
|
+
var import_plan_service = require("./plan-service");
|
|
44
|
+
var import_channel_event_service = require("./channel-event-service");
|
|
45
|
+
var import_spec_links_service = require("./spec-links-service");
|
|
46
|
+
var import_spec_sections = require("../../shared/lib/spec-sections");
|
|
47
|
+
const rows = (sql, params = []) => (0, import_database.getDb)().exec(sql, params)[0]?.values ?? [];
|
|
48
|
+
const parse = (s, fallback) => {
|
|
49
|
+
try {
|
|
50
|
+
return JSON.parse(String(s));
|
|
51
|
+
} catch {
|
|
52
|
+
return fallback;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
function pageVersion(pageUid) {
|
|
56
|
+
return rows("SELECT COALESCE(MAX(version), 1) FROM plan_item_versions WHERE item_uid = ?", [pageUid])[0]?.[0] ?? 1;
|
|
57
|
+
}
|
|
58
|
+
function proposalProblem(input) {
|
|
59
|
+
const page = (0, import_plan_item_service.getItem)(input.page);
|
|
60
|
+
if (!page) return `No page ${input.page}.`;
|
|
61
|
+
if (page.kind !== "object") return `"${page.title}" is a task, not a page: only a spec page can be changed by proposal.`;
|
|
62
|
+
if (input.section && !(0, import_spec_sections.findSection)(page.body ?? "", input.section)) {
|
|
63
|
+
return `"${page.title}" has no heading "${input.section}". Sections are addressed by their heading's slug, such as "fields" for "## Fields".`;
|
|
64
|
+
}
|
|
65
|
+
if (!input.text.trim()) return "The proposal needs the new text.";
|
|
66
|
+
if (!input.why.trim()) return "The proposal needs a why: what is wrong with the spec as it is.";
|
|
67
|
+
const before = input.section ? (0, import_spec_sections.sectionText)(page.body ?? "", input.section) ?? "" : page.body ?? "";
|
|
68
|
+
if (before.trim() === input.text.trim()) return "The proposed text is the same as the page has now.";
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
const affectedWords = (affected) => {
|
|
72
|
+
const w = (0, import_spec_links_service.reliedOnWords)(affected);
|
|
73
|
+
return w ? w.replace(/^Relied on by /, "") + (affected.length === 1 ? " relies on this" : " rely on this") : null;
|
|
74
|
+
};
|
|
75
|
+
function fromRow(r) {
|
|
76
|
+
const pageUid = r[1];
|
|
77
|
+
const page = (0, import_plan_item_service.getItem)(pageUid);
|
|
78
|
+
const section = r[3];
|
|
79
|
+
const base = r[4];
|
|
80
|
+
const current = page ? pageVersion(pageUid) : base;
|
|
81
|
+
const affected = parse(r[9], []);
|
|
82
|
+
return {
|
|
83
|
+
uid: r[0],
|
|
84
|
+
pageUid,
|
|
85
|
+
pageTitle: page?.title ?? "",
|
|
86
|
+
planUid: r[2],
|
|
87
|
+
section,
|
|
88
|
+
sectionTitle: section && page ? (0, import_spec_sections.findSection)(page.body ?? "", section)?.title ?? null : null,
|
|
89
|
+
baseVersion: base,
|
|
90
|
+
currentVersion: current,
|
|
91
|
+
pageChangedSince: current !== base,
|
|
92
|
+
beforeText: r[5],
|
|
93
|
+
proposedText: r[6],
|
|
94
|
+
why: r[7],
|
|
95
|
+
evidence: parse(r[8], {}),
|
|
96
|
+
affected,
|
|
97
|
+
affectedWords: affectedWords(affected),
|
|
98
|
+
author: r[10],
|
|
99
|
+
authorType: r[11],
|
|
100
|
+
sessionId: r[12] ?? null,
|
|
101
|
+
status: r[13],
|
|
102
|
+
createdAt: r[14],
|
|
103
|
+
decidedAt: r[15] ?? null,
|
|
104
|
+
decidedBy: r[16] ?? null,
|
|
105
|
+
decidedByType: r[17] ?? null,
|
|
106
|
+
decisionNote: r[18] ?? null,
|
|
107
|
+
impacts: impactsOf(r[0]),
|
|
108
|
+
hitRef: r[19] ?? null,
|
|
109
|
+
decidedText: r[20] ?? null,
|
|
110
|
+
pageBreakpoint: guardOf(pageUid)
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function guardOf(pageUid) {
|
|
114
|
+
const bp = (0, import_breakpoint_service.specBreakpointOn)(pageUid);
|
|
115
|
+
return bp ? { id: bp.id, note: bp.note } : null;
|
|
116
|
+
}
|
|
117
|
+
function impactsOf(proposalUid) {
|
|
118
|
+
return rows(
|
|
119
|
+
`SELECT id, impact, words, tasks, item_uid, plan_uid, author, author_type, session_id, created_at
|
|
120
|
+
FROM spec_proposal_impacts WHERE proposal_uid = ? ORDER BY created_at, id`,
|
|
121
|
+
[proposalUid]
|
|
122
|
+
).map((r) => {
|
|
123
|
+
const itemUid = r[4] ?? null;
|
|
124
|
+
const planUid = r[5] ?? null;
|
|
125
|
+
return {
|
|
126
|
+
id: r[0],
|
|
127
|
+
impact: r[1],
|
|
128
|
+
words: r[2],
|
|
129
|
+
tasks: r[3] ?? null,
|
|
130
|
+
itemUid,
|
|
131
|
+
itemTitle: itemUid ? (0, import_plan_item_service.getItem)(itemUid)?.title ?? null : null,
|
|
132
|
+
planUid,
|
|
133
|
+
planTitle: planUid ? (0, import_plan_service.getPlan)(planUid)?.title ?? null : null,
|
|
134
|
+
author: r[6],
|
|
135
|
+
authorType: r[7],
|
|
136
|
+
sessionId: r[8] ?? null,
|
|
137
|
+
createdAt: r[9]
|
|
138
|
+
};
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
const COLUMNS = `uid, page_uid, plan_uid, section, base_version, before_text, proposed_text, why, evidence, affected,
|
|
142
|
+
author, author_type, session_id, status, created_at, decided_at, decided_by, decided_by_type, decision_note, hit_ref, decided_text`;
|
|
143
|
+
function proposeSpecChange(input, by) {
|
|
144
|
+
const page = (0, import_plan_item_service.getItem)(input.page);
|
|
145
|
+
const section = input.section ?? "";
|
|
146
|
+
const before = section ? (0, import_spec_sections.sectionText)(page.body ?? "", section) ?? "" : page.body ?? "";
|
|
147
|
+
const affected = (0, import_spec_links_service.reliedOnBy)(page.uid, section || void 0);
|
|
148
|
+
const uid = (0, import_node_crypto.randomUUID)();
|
|
149
|
+
(0, import_database.getDb)().run(
|
|
150
|
+
`INSERT INTO spec_proposals (uid, page_uid, plan_uid, section, base_version, before_text, proposed_text, why, evidence,
|
|
151
|
+
affected, author, author_type, session_id, status, created_at)
|
|
152
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'open', ?)`,
|
|
153
|
+
[
|
|
154
|
+
uid,
|
|
155
|
+
page.uid,
|
|
156
|
+
page.planUid,
|
|
157
|
+
section,
|
|
158
|
+
pageVersion(page.uid),
|
|
159
|
+
before,
|
|
160
|
+
input.text,
|
|
161
|
+
input.why.trim(),
|
|
162
|
+
JSON.stringify(input.evidence ?? {}),
|
|
163
|
+
JSON.stringify(affected),
|
|
164
|
+
by.author,
|
|
165
|
+
by.authorType,
|
|
166
|
+
by.sessionId ?? null,
|
|
167
|
+
Date.now()
|
|
168
|
+
]
|
|
169
|
+
);
|
|
170
|
+
raiseHit(uid, page.planUid, page.uid, by);
|
|
171
|
+
(0, import_persistence.markDirty)();
|
|
172
|
+
return getProposal(uid);
|
|
173
|
+
}
|
|
174
|
+
function raiseHit(uid, planUid, pageUid, by, now = Date.now()) {
|
|
175
|
+
const bp = `bp_${(0, import_node_crypto.randomBytes)(6).toString("hex")}`;
|
|
176
|
+
(0, import_database.getDb)().run(
|
|
177
|
+
`INSERT INTO breakpoints (id, kind, target, plan_uid, note, created_at, created_by, created_by_type)
|
|
178
|
+
VALUES (?, 'proposal', ?, ?, NULL, ?, ?, ?)`,
|
|
179
|
+
[bp, uid, planUid, now, by.author, by.authorType]
|
|
180
|
+
);
|
|
181
|
+
const ref = `bp-${(0, import_node_crypto.randomBytes)(5).toString("hex")}`;
|
|
182
|
+
const workstream = by.sessionId ? rows("SELECT workstream_root FROM agent_sessions WHERE session_id = ?", [by.sessionId])[0]?.[0] ?? null : null;
|
|
183
|
+
(0, import_database.getDb)().run(
|
|
184
|
+
`INSERT INTO breakpoint_hits (ref, breakpoint_id, tool, action, item_uid, plan_uid, agent, session_id, workstream_root, hit_at)
|
|
185
|
+
VALUES (?, ?, 'propose_spec_change', 'propose', ?, ?, ?, ?, ?, ?)`,
|
|
186
|
+
[ref, bp, pageUid, planUid, by.author, by.sessionId ?? null, workstream, now]
|
|
187
|
+
);
|
|
188
|
+
(0, import_database.getDb)().run("UPDATE spec_proposals SET hit_ref = ? WHERE uid = ?", [ref, uid]);
|
|
189
|
+
const hit = (0, import_breakpoint_service.getHit)(ref);
|
|
190
|
+
(0, import_agent_event_log.recordBreakpointEvent)("breakpoint_hit", { ref, kind: "proposal", action: "propose", tool: hit.tool, itemUid: pageUid, itemTitle: hit.itemTitle, planUid, agent: by.author, breakpointId: bp, on: uid }, by.author);
|
|
191
|
+
void (0, import_push_notification_service.pushForBreakpoint)(hit).catch(() => {
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
function getProposal(uid) {
|
|
195
|
+
const r = rows(`SELECT ${COLUMNS} FROM spec_proposals WHERE uid = ?`, [uid])[0];
|
|
196
|
+
return r ? fromRow(r) : null;
|
|
197
|
+
}
|
|
198
|
+
function listProposals(filter = {}) {
|
|
199
|
+
const where2 = [];
|
|
200
|
+
const params = [];
|
|
201
|
+
if (filter.pageUid) {
|
|
202
|
+
where2.push("s.page_uid = ?");
|
|
203
|
+
params.push(filter.pageUid);
|
|
204
|
+
}
|
|
205
|
+
if (filter.status) {
|
|
206
|
+
where2.push("s.status = ?");
|
|
207
|
+
params.push(filter.status);
|
|
208
|
+
}
|
|
209
|
+
if (filter.projectPath) {
|
|
210
|
+
where2.push("s.plan_uid IN (SELECT uid FROM plans WHERE project_path = ? OR project_path = ?)");
|
|
211
|
+
params.push(filter.projectPath, filter.projectPath.replace(/[\\/]+$/, ""));
|
|
212
|
+
}
|
|
213
|
+
const cols = COLUMNS.split(",").map((c) => `s.${c.trim()}`).join(", ");
|
|
214
|
+
return rows(
|
|
215
|
+
`SELECT ${cols} FROM spec_proposals s ${where2.length ? `WHERE ${where2.join(" AND ")}` : ""} ORDER BY s.created_at DESC`,
|
|
216
|
+
params
|
|
217
|
+
).map(fromRow);
|
|
218
|
+
}
|
|
219
|
+
function directEditNote(pageUid) {
|
|
220
|
+
const affected = (0, import_spec_links_service.reliedOnBy)(pageUid);
|
|
221
|
+
if (affected.length === 0) return null;
|
|
222
|
+
const names = affected.slice(0, 4).map((a) => `"${a.title}" (${a.planTitle})`).join(", ");
|
|
223
|
+
const more = affected.length > 4 ? ` and ${affected.length - 4} more` : "";
|
|
224
|
+
return `${(0, import_spec_links_service.reliedOnWords)(affected)}: ${names}${more}. The edit is saved; to change a spec others rely on, propose_spec_change lets their agents weigh in and a person decide first.`;
|
|
225
|
+
}
|
|
226
|
+
const where = (p) => `${p.section ? `\xA7 ${p.sectionTitle ?? p.section} of ` : ""}"${p.pageTitle}"`;
|
|
227
|
+
function heldBy(sessionId, p) {
|
|
228
|
+
const relying = (0, import_spec_links_service.reliedOnBy)(p.pageUid, p.section || void 0);
|
|
229
|
+
if (relying.length === 0) return [];
|
|
230
|
+
const mine = new Set(rows(
|
|
231
|
+
`SELECT uid FROM plan_items WHERE assignee_session = ? AND uid IN (${relying.map(() => "?").join(",")})`,
|
|
232
|
+
[sessionId, ...relying.map((r) => r.itemUid)]
|
|
233
|
+
).map((r) => r[0]));
|
|
234
|
+
return relying.filter((r) => mine.has(r.itemUid));
|
|
235
|
+
}
|
|
236
|
+
const quoted = (text, max = 20) => {
|
|
237
|
+
const lines = text.replace(/\n+$/, "").split("\n");
|
|
238
|
+
const shown = lines.slice(0, max).map((l) => `> ${l}`);
|
|
239
|
+
if (lines.length > max) shown.push(`> \u2026 ${lines.length - max} more lines (list_spec_proposals has it all)`);
|
|
240
|
+
return shown;
|
|
241
|
+
};
|
|
242
|
+
function noticeText(p, mine) {
|
|
243
|
+
const tasks = mine.map((t) => `"${t.title}" (${t.planTitle})`).join(", ");
|
|
244
|
+
const ev = [
|
|
245
|
+
p.evidence.tests?.length ? `tests ${p.evidence.tests.join(", ")}` : null,
|
|
246
|
+
p.evidence.files?.length ? `files ${p.evidence.files.join(", ")}` : null,
|
|
247
|
+
p.evidence.commits?.length ? `commits ${p.evidence.commits.join(", ")}` : null,
|
|
248
|
+
p.evidence.note ? p.evidence.note : null
|
|
249
|
+
].filter(Boolean).join("; ");
|
|
250
|
+
return [
|
|
251
|
+
`${p.author} proposes a change to ${where(p)}. Your ${mine.length === 1 ? "task" : "tasks"} ${tasks} ${mine.length === 1 ? "relies" : "rely"} on it.`,
|
|
252
|
+
`Why: ${p.why}`,
|
|
253
|
+
...ev ? [`Evidence: ${ev}`] : [],
|
|
254
|
+
"Now:",
|
|
255
|
+
...quoted(p.beforeText || "(empty)"),
|
|
256
|
+
"Proposed:",
|
|
257
|
+
...quoted(p.proposedText),
|
|
258
|
+
`Nothing changes until a person decides. Say what it would mean for your work: reply_to_spec_proposal("${p.uid}", impact: "none" | "changes", words).`
|
|
259
|
+
].join("\n");
|
|
260
|
+
}
|
|
261
|
+
function proposalNoticeFor(sessionId, agentType, now = Date.now(), onTold) {
|
|
262
|
+
try {
|
|
263
|
+
const changed = specChangedNotice(sessionId, now);
|
|
264
|
+
if (changed && changed.items.length > 0) onTold?.(changed.items);
|
|
265
|
+
const later = [changed?.text ?? null, outcomeNotice(sessionId, now)].filter((x) => !!x);
|
|
266
|
+
const holds = rows("SELECT 1 FROM plan_items WHERE assignee_session = ? LIMIT 1", [sessionId]).length > 0;
|
|
267
|
+
const unread = !holds ? [] : rows(
|
|
268
|
+
`SELECT uid FROM spec_proposals s WHERE s.status = 'open' AND (s.session_id IS NULL OR s.session_id != ?)
|
|
269
|
+
AND NOT EXISTS (SELECT 1 FROM spec_proposal_reads d WHERE d.proposal_uid = s.uid AND d.session_id = ?)
|
|
270
|
+
ORDER BY s.created_at`,
|
|
271
|
+
[sessionId, sessionId]
|
|
272
|
+
).map((r) => r[0]);
|
|
273
|
+
const told = [];
|
|
274
|
+
for (const uid of unread) {
|
|
275
|
+
const p = getProposal(uid);
|
|
276
|
+
if (!p) continue;
|
|
277
|
+
const mine = heldBy(sessionId, p);
|
|
278
|
+
if (mine.length === 0) continue;
|
|
279
|
+
told.push(noticeText(p, mine));
|
|
280
|
+
(0, import_database.getDb)().run(
|
|
281
|
+
"INSERT OR IGNORE INTO spec_proposal_reads (proposal_uid, session_id, agent_type, read_at) VALUES (?, ?, ?, ?)",
|
|
282
|
+
[uid, sessionId, agentType, now]
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
const notices = [...told.length ? [[`\u2500\u2500 CodeTrellis: spec change proposed \u2500\u2500`, told.join("\n\n")].join("\n")] : [], ...later];
|
|
286
|
+
if (notices.length === 0) return null;
|
|
287
|
+
(0, import_persistence.markDirty)();
|
|
288
|
+
return notices.join("\n\n");
|
|
289
|
+
} catch (err) {
|
|
290
|
+
console.warn("[Spec] proposal notice failed:", err instanceof Error ? err.message : err);
|
|
291
|
+
return null;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
function proposalReads(uid) {
|
|
295
|
+
return rows("SELECT session_id, agent_type, read_at FROM spec_proposal_reads WHERE proposal_uid = ? ORDER BY read_at", [uid]).map((r) => ({ sessionId: r[0], agentType: r[1] ?? null, readAt: r[2] }));
|
|
296
|
+
}
|
|
297
|
+
function impactProblem(input) {
|
|
298
|
+
const p = getProposal(input.uid);
|
|
299
|
+
if (!p) return `No proposal ${input.uid}.`;
|
|
300
|
+
if (p.status !== "open") return `The proposal to change ${where(p)} was ${p.status}; there is nothing left to weigh in on.`;
|
|
301
|
+
if (input.impact === "changes" && !input.words?.trim()) return "Say in a sentence what it would change for your work.";
|
|
302
|
+
if (input.tasks !== void 0 && (!Number.isInteger(input.tasks) || input.tasks < 0)) return "tasks is how many of your tasks it would change: a whole number.";
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
function replyToProposal(input, by, now = Date.now()) {
|
|
306
|
+
const p = getProposal(input.uid);
|
|
307
|
+
const task = by.sessionId ? heldBy(by.sessionId, p)[0] ?? null : null;
|
|
308
|
+
const words = input.words?.trim() ?? "";
|
|
309
|
+
(0, import_database.getDb)().run(
|
|
310
|
+
`INSERT INTO spec_proposal_impacts (proposal_uid, impact, words, tasks, item_uid, plan_uid, author, author_type, session_id, created_at)
|
|
311
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
312
|
+
[
|
|
313
|
+
p.uid,
|
|
314
|
+
input.impact,
|
|
315
|
+
words,
|
|
316
|
+
input.tasks ?? null,
|
|
317
|
+
task?.itemUid ?? null,
|
|
318
|
+
task?.planUid ?? null,
|
|
319
|
+
by.author,
|
|
320
|
+
by.authorType,
|
|
321
|
+
by.sessionId ?? null,
|
|
322
|
+
now
|
|
323
|
+
]
|
|
324
|
+
);
|
|
325
|
+
(0, import_persistence.markDirty)();
|
|
326
|
+
const impact = impactsOf(p.uid).at(-1);
|
|
327
|
+
const proposerTask = p.sessionId ? rows("SELECT uid, plan_uid FROM plan_items WHERE assignee_session = ? ORDER BY updated_at DESC LIMIT 1", [p.sessionId])[0] : void 0;
|
|
328
|
+
const from = task ? `"${task.title}" (${task.planTitle})` : by.author;
|
|
329
|
+
const said = input.impact === "none" ? `no impact on ${from}.` : `${from} would change${input.tasks !== void 0 ? ` (${input.tasks} ${input.tasks === 1 ? "task" : "tasks"})` : ""}: ${words}`;
|
|
330
|
+
const event = (0, import_channel_event_service.postChannelEvent)({
|
|
331
|
+
planUid: proposerTask?.[1] ?? p.planUid,
|
|
332
|
+
itemUid: proposerTask?.[0] ?? null,
|
|
333
|
+
eventType: "weigh-in",
|
|
334
|
+
payload: {
|
|
335
|
+
message: `On the proposed change to ${where(p)}: ${said}`,
|
|
336
|
+
references: { items: [p.pageUid, ...task ? [task.itemUid] : []] }
|
|
337
|
+
},
|
|
338
|
+
author: by.author,
|
|
339
|
+
authorType: by.authorType
|
|
340
|
+
});
|
|
341
|
+
return { impact, event };
|
|
342
|
+
}
|
|
343
|
+
function pageWith(p, text) {
|
|
344
|
+
const page = (0, import_plan_item_service.getItem)(p.pageUid);
|
|
345
|
+
if (!page) return null;
|
|
346
|
+
return (0, import_spec_sections.withSectionText)(page.body ?? "", p.section || null, text) ?? null;
|
|
347
|
+
}
|
|
348
|
+
function decisionProblem(input) {
|
|
349
|
+
const p = getProposal(input.uid);
|
|
350
|
+
if (!p) return `No proposal ${input.uid}.`;
|
|
351
|
+
if (p.status !== "open") return `The proposal to change ${where(p)} was already ${p.status}.`;
|
|
352
|
+
if (!["accept", "amend", "reject"].includes(input.decision)) return "decision is accept, amend or reject.";
|
|
353
|
+
if (input.decision === "amend" && !input.text?.trim()) return "Amend needs the text as it should read.";
|
|
354
|
+
if (input.decision !== "reject") {
|
|
355
|
+
if (!(0, import_plan_item_service.getItem)(p.pageUid)) return "The page no longer exists.";
|
|
356
|
+
const text = input.decision === "amend" ? input.text : p.proposedText;
|
|
357
|
+
if (pageWith(p, text) === null) return `"${p.pageTitle}" no longer has the heading "${p.section}". Reject this and ask for a new proposal.`;
|
|
358
|
+
}
|
|
359
|
+
return null;
|
|
360
|
+
}
|
|
361
|
+
function decideProposal(input, by, now = Date.now()) {
|
|
362
|
+
const p = getProposal(input.uid);
|
|
363
|
+
const note = input.note?.trim() || null;
|
|
364
|
+
const accept = input.decision !== "reject";
|
|
365
|
+
const text = input.decision === "amend" ? input.text : p.proposedText;
|
|
366
|
+
let flagged = [];
|
|
367
|
+
if (accept) {
|
|
368
|
+
(0, import_plan_item_service.updateItem)(p.pageUid, {
|
|
369
|
+
body: pageWith(p, text),
|
|
370
|
+
changeSummary: `Accepted spec proposal ${p.uid.slice(0, 8)}${input.decision === "amend" ? ", amended" : ""}: ${p.why}`,
|
|
371
|
+
author: by.author,
|
|
372
|
+
authorType: by.authorType
|
|
373
|
+
});
|
|
374
|
+
flagged = (0, import_spec_links_service.reliedOnBy)(p.pageUid, p.section || void 0);
|
|
375
|
+
for (const t of flagged) {
|
|
376
|
+
(0, import_database.getDb)().run("INSERT OR IGNORE INTO spec_change_flags (item_uid, proposal_uid, created_at) VALUES (?, ?, ?)", [t.itemUid, p.uid, now]);
|
|
377
|
+
(0, import_plan_event_service.appendPlanEvent)({
|
|
378
|
+
planUid: t.planUid,
|
|
379
|
+
itemUid: t.itemUid,
|
|
380
|
+
eventType: "spec_changed",
|
|
381
|
+
afterState: { proposalUid: p.uid, pageUid: p.pageUid, section: p.section },
|
|
382
|
+
summary: `The spec "${t.title}" relies on changed: ${where(p)}`,
|
|
383
|
+
author: by.author,
|
|
384
|
+
authorType: by.authorType,
|
|
385
|
+
createdAt: now
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
(0, import_database.getDb)().run(
|
|
390
|
+
`UPDATE spec_proposals SET status = ?, decided_at = ?, decided_by = ?, decided_by_type = ?, decision_note = ?, decided_text = ?
|
|
391
|
+
WHERE uid = ? AND status = 'open'`,
|
|
392
|
+
[accept ? "accepted" : "rejected", now, by.author, by.authorType, note, input.decision === "amend" ? text : null, p.uid]
|
|
393
|
+
);
|
|
394
|
+
(0, import_agent_event_log.recordDecision)("spec_decided", {
|
|
395
|
+
proposalUid: p.uid,
|
|
396
|
+
planUid: p.planUid,
|
|
397
|
+
pageUid: p.pageUid,
|
|
398
|
+
section: p.section,
|
|
399
|
+
decision: input.decision,
|
|
400
|
+
...note ? { note: note.slice(0, 200) } : {},
|
|
401
|
+
author: by.author,
|
|
402
|
+
authorType: by.authorType
|
|
403
|
+
}, by.authorType === "agent" ? by.author : by.authorType);
|
|
404
|
+
if (p.hitRef) {
|
|
405
|
+
(0, import_breakpoint_service.answerHit)({ ref: p.hitRef, decision: accept ? "continue" : "stop", note: note ?? (input.decision === "amend" ? "Accepted with changes." : null), by: by.author, byType: by.authorType, now });
|
|
406
|
+
(0, import_database.getDb)().run(`UPDATE breakpoints SET cleared_at = ?, cleared_by = ?, cleared_by_type = ? WHERE kind = 'proposal' AND target = ? AND cleared_at IS NULL`, [now, by.author, by.authorType, p.uid]);
|
|
407
|
+
}
|
|
408
|
+
(0, import_persistence.markDirty)();
|
|
409
|
+
return { proposal: getProposal(p.uid), flagged };
|
|
410
|
+
}
|
|
411
|
+
function specChangedFor(itemUid) {
|
|
412
|
+
return rows("SELECT proposal_uid, created_at, read_at FROM spec_change_flags WHERE item_uid = ? ORDER BY created_at DESC", [itemUid]).flatMap((r) => {
|
|
413
|
+
const p = getProposal(r[0]);
|
|
414
|
+
return p ? [{ proposalUid: p.uid, pageUid: p.pageUid, pageTitle: p.pageTitle, section: p.section, sectionTitle: p.sectionTitle, at: r[1], toldAt: r[2] ?? null }] : [];
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
function specChangedNotice(sessionId, now) {
|
|
418
|
+
const flags = rows(
|
|
419
|
+
`SELECT f.item_uid, f.proposal_uid, i.title FROM spec_change_flags f JOIN plan_items i ON i.uid = f.item_uid
|
|
420
|
+
WHERE f.read_at IS NULL AND i.assignee_session = ? ORDER BY f.created_at`,
|
|
421
|
+
[sessionId]
|
|
422
|
+
);
|
|
423
|
+
if (flags.length === 0) return null;
|
|
424
|
+
const items = [...new Set(flags.map((f) => f[0]))];
|
|
425
|
+
const parts = flags.map(([itemUid, proposalUid, title]) => {
|
|
426
|
+
(0, import_database.getDb)().run("UPDATE spec_change_flags SET read_at = ?, read_by_session = ? WHERE item_uid = ? AND proposal_uid = ?", [now, sessionId, itemUid, proposalUid]);
|
|
427
|
+
const p = getProposal(proposalUid);
|
|
428
|
+
if (!p) return null;
|
|
429
|
+
return [
|
|
430
|
+
`${where(p)} changed: a person accepted ${p.author}'s proposal${p.decidedText ? ", with changes" : ""}. Your task "${title}" relies on it.`,
|
|
431
|
+
...p.decisionNote ? [`Their note: ${p.decisionNote}`] : [],
|
|
432
|
+
"It now reads:",
|
|
433
|
+
...quoted(p.decidedText ?? p.proposedText),
|
|
434
|
+
"Work to the new text; get_spec_links shows the page."
|
|
435
|
+
].join("\n");
|
|
436
|
+
}).filter((x) => !!x);
|
|
437
|
+
return parts.length ? { text: ["\u2500\u2500 CodeTrellis: spec changed \u2500\u2500", parts.join("\n\n")].join("\n"), items } : null;
|
|
438
|
+
}
|
|
439
|
+
function outcomeNotice(sessionId, now) {
|
|
440
|
+
const decided = rows(
|
|
441
|
+
`SELECT uid FROM spec_proposals s WHERE s.session_id = ? AND s.status IN ('accepted', 'rejected')
|
|
442
|
+
AND NOT EXISTS (SELECT 1 FROM spec_proposal_outcome_reads o WHERE o.proposal_uid = s.uid AND o.session_id = ?)
|
|
443
|
+
ORDER BY s.decided_at`,
|
|
444
|
+
[sessionId, sessionId]
|
|
445
|
+
).map((r) => r[0]);
|
|
446
|
+
if (decided.length === 0) return null;
|
|
447
|
+
const parts = decided.map((uid) => {
|
|
448
|
+
(0, import_database.getDb)().run("INSERT OR IGNORE INTO spec_proposal_outcome_reads (proposal_uid, session_id, read_at) VALUES (?, ?, ?)", [uid, sessionId, now]);
|
|
449
|
+
const p = getProposal(uid);
|
|
450
|
+
const note = p.decisionNote ? ` Their note: ${p.decisionNote}` : "";
|
|
451
|
+
return p.status === "rejected" ? `Your proposal to change ${where(p)} was not accepted.${note} The page is as it was; carry on with the spec as it is.` : `Your proposal to change ${where(p)} was accepted${p.decidedText ? ", with changes" : ""}; the page has its new version.${note}`;
|
|
452
|
+
});
|
|
453
|
+
return ["\u2500\u2500 CodeTrellis: spec proposal decided \u2500\u2500", parts.join("\n")].join("\n");
|
|
454
|
+
}
|
|
455
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
456
|
+
0 && (module.exports = {
|
|
457
|
+
decideProposal,
|
|
458
|
+
decisionProblem,
|
|
459
|
+
directEditNote,
|
|
460
|
+
getProposal,
|
|
461
|
+
impactProblem,
|
|
462
|
+
listProposals,
|
|
463
|
+
pageVersion,
|
|
464
|
+
proposalNoticeFor,
|
|
465
|
+
proposalProblem,
|
|
466
|
+
proposalReads,
|
|
467
|
+
proposeSpecChange,
|
|
468
|
+
replyToProposal,
|
|
469
|
+
specChangedFor
|
|
470
|
+
});
|
|
@@ -0,0 +1,95 @@
|
|
|
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 embedded_exports = {};
|
|
19
|
+
__export(embedded_exports, {
|
|
20
|
+
extractEmbeddedSql: () => extractEmbeddedSql
|
|
21
|
+
});
|
|
22
|
+
module.exports = __toCommonJS(embedded_exports);
|
|
23
|
+
var import_refs = require("./refs");
|
|
24
|
+
var import_index = require("./index");
|
|
25
|
+
function scanStringLiterals(content) {
|
|
26
|
+
const out = [];
|
|
27
|
+
const len = content.length;
|
|
28
|
+
let i = 0;
|
|
29
|
+
let line = 1;
|
|
30
|
+
const openers = [
|
|
31
|
+
{ open: '"""', close: '"""', raw: true },
|
|
32
|
+
{ open: "'''", close: "'''", raw: true },
|
|
33
|
+
{ open: "`", close: "`", raw: true },
|
|
34
|
+
{ open: '"', close: '"', raw: false },
|
|
35
|
+
{ open: "'", close: "'", raw: false }
|
|
36
|
+
];
|
|
37
|
+
while (i < len) {
|
|
38
|
+
if (content[i] === "\n") {
|
|
39
|
+
line++;
|
|
40
|
+
i++;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
const opener = openers.find((o) => content.startsWith(o.open, i));
|
|
44
|
+
if (!opener) {
|
|
45
|
+
i++;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
const startLine = line;
|
|
49
|
+
const bodyStart = i + opener.open.length;
|
|
50
|
+
let j = bodyStart;
|
|
51
|
+
let body = "";
|
|
52
|
+
while (j < len) {
|
|
53
|
+
if (!opener.raw && content[j] === "\\" && j + 1 < len) {
|
|
54
|
+
body += content[j + 1];
|
|
55
|
+
j += 2;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (content.startsWith(opener.close, j)) break;
|
|
59
|
+
if (content[j] === "\n") {
|
|
60
|
+
line++;
|
|
61
|
+
if (!opener.raw) {
|
|
62
|
+
body = "";
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
body += content[j];
|
|
67
|
+
j++;
|
|
68
|
+
}
|
|
69
|
+
if (body) out.push({ body, line: startLine });
|
|
70
|
+
i = j + opener.close.length;
|
|
71
|
+
}
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
74
|
+
function extractEmbeddedSql(content) {
|
|
75
|
+
const out = [];
|
|
76
|
+
for (const literal of scanStringLiterals(content)) {
|
|
77
|
+
if (!(0, import_refs.looksLikeSql)(literal.body)) continue;
|
|
78
|
+
const refs = (0, import_refs.extractTableRefs)(literal.body);
|
|
79
|
+
if (refs.length === 0) continue;
|
|
80
|
+
out.push(...(0, import_index.sqlRefsToCallsites)(refs, "embedded", literal.body, literal.line));
|
|
81
|
+
}
|
|
82
|
+
return dedupe(out);
|
|
83
|
+
}
|
|
84
|
+
function dedupe(callsites) {
|
|
85
|
+
const seen = /* @__PURE__ */ new Map();
|
|
86
|
+
for (const cs of callsites) {
|
|
87
|
+
const key = `${cs.urlPattern}:${cs.method}`;
|
|
88
|
+
if (!seen.has(key)) seen.set(key, cs);
|
|
89
|
+
}
|
|
90
|
+
return [...seen.values()];
|
|
91
|
+
}
|
|
92
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
93
|
+
0 && (module.exports = {
|
|
94
|
+
extractEmbeddedSql
|
|
95
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
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 sql_exports = {};
|
|
19
|
+
__export(sql_exports, {
|
|
20
|
+
applyMigrationFold: () => import_schema.applyMigrationFold,
|
|
21
|
+
extractSchemaStatements: () => import_schema.extractSchemaStatements,
|
|
22
|
+
extractSqlSymbols: () => import_schema.extractSqlSymbols,
|
|
23
|
+
extractTableRefs: () => import_refs.extractTableRefs,
|
|
24
|
+
foldMigrations: () => import_schema.foldMigrations,
|
|
25
|
+
isNameToken: () => import_tokenizer.isNameToken,
|
|
26
|
+
isWord: () => import_tokenizer.isWord,
|
|
27
|
+
looksLikeMigrationsDir: () => import_schema.looksLikeMigrationsDir,
|
|
28
|
+
looksLikeSql: () => import_refs.looksLikeSql,
|
|
29
|
+
sortMigrations: () => import_schema.sortMigrations,
|
|
30
|
+
sqlRefsToCallsites: () => sqlRefsToCallsites,
|
|
31
|
+
tokenize: () => import_tokenizer.tokenize
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(sql_exports);
|
|
34
|
+
var import_tokenizer = require("./tokenizer");
|
|
35
|
+
var import_refs = require("./refs");
|
|
36
|
+
var import_schema = require("./schema");
|
|
37
|
+
const MAX_SQL_TEXT = 400;
|
|
38
|
+
function sqlRefsToCallsites(refs, context, sqlText, line) {
|
|
39
|
+
return refs.map((ref) => ({
|
|
40
|
+
kind: "sql_query",
|
|
41
|
+
protocol: "sql",
|
|
42
|
+
line: line ?? ref.line,
|
|
43
|
+
method: ref.op.toUpperCase(),
|
|
44
|
+
urlPattern: ref.table,
|
|
45
|
+
sqlText: sqlText ? sqlText.slice(0, MAX_SQL_TEXT) : void 0,
|
|
46
|
+
context: `${context}:${ref.keyword}`
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
50
|
+
0 && (module.exports = {
|
|
51
|
+
applyMigrationFold,
|
|
52
|
+
extractSchemaStatements,
|
|
53
|
+
extractSqlSymbols,
|
|
54
|
+
extractTableRefs,
|
|
55
|
+
foldMigrations,
|
|
56
|
+
isNameToken,
|
|
57
|
+
isWord,
|
|
58
|
+
looksLikeMigrationsDir,
|
|
59
|
+
looksLikeSql,
|
|
60
|
+
sortMigrations,
|
|
61
|
+
sqlRefsToCallsites,
|
|
62
|
+
tokenize
|
|
63
|
+
});
|