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
package/src/cli/verbs.js
ADDED
|
@@ -0,0 +1,360 @@
|
|
|
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 verbs_exports = {};
|
|
29
|
+
__export(verbs_exports, {
|
|
30
|
+
UsageError: () => UsageError,
|
|
31
|
+
VERBS: () => VERBS,
|
|
32
|
+
projectRoot: () => projectRoot,
|
|
33
|
+
runVerb: () => runVerb
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(verbs_exports);
|
|
36
|
+
var import_node_child_process = require("node:child_process");
|
|
37
|
+
var import_node_fs = __toESM(require("node:fs"));
|
|
38
|
+
var import_node_path = __toESM(require("node:path"));
|
|
39
|
+
var import_args = require("./args");
|
|
40
|
+
var import_sarif = require("./sarif");
|
|
41
|
+
var import_review_output = require("./review-output");
|
|
42
|
+
var import_rule_baseline = require("../backend/services/rule-baseline");
|
|
43
|
+
var import_confined_fs = require("../backend/services/confined-fs");
|
|
44
|
+
var import_package = require("../../package.json");
|
|
45
|
+
var import_conformity = require("./conformity");
|
|
46
|
+
var import_pipeline = require("../backend/services/pipeline");
|
|
47
|
+
var import_pipeline2 = require("./pipeline");
|
|
48
|
+
const VERBS = /* @__PURE__ */ new Set(["next", "claim", "update", "stuck", "done", "request", "brief", "awareness", "check", "report-tests", "rules"]);
|
|
49
|
+
class UsageError extends Error {
|
|
50
|
+
}
|
|
51
|
+
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
52
|
+
const asObj = (v) => v && typeof v === "object" && !Array.isArray(v) ? v : {};
|
|
53
|
+
function projectRoot(cwd) {
|
|
54
|
+
try {
|
|
55
|
+
const top = (0, import_node_child_process.execFileSync)("git", ["-C", cwd, "rev-parse", "--show-toplevel"], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
56
|
+
if (top) return import_node_fs.default.realpathSync(top);
|
|
57
|
+
} catch {
|
|
58
|
+
}
|
|
59
|
+
return import_node_fs.default.realpathSync(cwd);
|
|
60
|
+
}
|
|
61
|
+
function said(a, words, ctx) {
|
|
62
|
+
if (a.isError) return { out: a.text, code: 1 };
|
|
63
|
+
if (ctx.json) return { out: a.json !== null ? JSON.stringify(a.json) : JSON.stringify({ text: a.text }), code: 0 };
|
|
64
|
+
return { out: a.json !== null ? words(asObj(a.json)) : a.text, code: 0 };
|
|
65
|
+
}
|
|
66
|
+
async function plansHere(ctx) {
|
|
67
|
+
const a = await ctx.agent.call("list_plans", { project_path: projectRoot(ctx.cwd), limit: 100 });
|
|
68
|
+
if (a.isError) return [];
|
|
69
|
+
return asObj(a.json).plans ?? [];
|
|
70
|
+
}
|
|
71
|
+
async function planOf(ctx) {
|
|
72
|
+
const named = (0, import_args.flag)(ctx.p, "plan");
|
|
73
|
+
if (named) return named;
|
|
74
|
+
const plans = (await plansHere(ctx)).filter((pl) => pl.status !== "archived" && pl.status !== "done");
|
|
75
|
+
if (plans.length === 1) return plans[0].uid;
|
|
76
|
+
if (plans.length === 0) throw new UsageError(`No plan in ${projectRoot(ctx.cwd)}. Name one with --plan <uid>.`);
|
|
77
|
+
throw new UsageError(`Several plans in this project; name one with --plan:
|
|
78
|
+
${plans.map((pl) => ` ${pl.uid} ${pl.title}`).join("\n")}`);
|
|
79
|
+
}
|
|
80
|
+
async function taskOf(ctx, ref) {
|
|
81
|
+
if (!ref) throw new UsageError("Which task? Give its uid, or the first characters of it.");
|
|
82
|
+
const want = ref.replace(/^task\s+/i, "").trim().toLowerCase();
|
|
83
|
+
if (UUID.test(want)) return want;
|
|
84
|
+
if (!/^[0-9a-f-]{6,}$/.test(want)) throw new UsageError(`"${ref}" is not a task uid or the start of one.`);
|
|
85
|
+
const found = [];
|
|
86
|
+
for (const pl of await plansHere(ctx)) {
|
|
87
|
+
const a = await ctx.agent.call("list_items", { plan_uid: pl.uid, limit: 500 });
|
|
88
|
+
for (const it of asObj(a.json).items ?? []) {
|
|
89
|
+
if (it.uid.toLowerCase().startsWith(want)) found.push(it);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (found.length === 1) return found[0].uid;
|
|
93
|
+
if (found.length === 0) throw new UsageError(`No task starting "${want}" in this project's plans.`);
|
|
94
|
+
throw new UsageError(`"${want}" names ${found.length} tasks; give more of the uid:
|
|
95
|
+
${found.map((t) => ` ${t.uid} ${t.title}`).join("\n")}`);
|
|
96
|
+
}
|
|
97
|
+
const taskWords = (t) => `${t.title ?? "a task"} (${t.uid ?? "?"})${t.status ? `, ${String(t.status).replace("_", " ")}` : ""}`;
|
|
98
|
+
async function runVerb(verb, agent, p, cwd) {
|
|
99
|
+
const ctx = { agent, p, cwd, json: p.flags.json === true };
|
|
100
|
+
const [first, ...more] = p.rest;
|
|
101
|
+
switch (verb) {
|
|
102
|
+
case "next": {
|
|
103
|
+
const a = await agent.call("get_next_item", { plan_uid: await planOf(ctx) });
|
|
104
|
+
return said(a, (j) => {
|
|
105
|
+
const item = asObj(j.item ?? j.next ?? j);
|
|
106
|
+
return item.uid ? `Next: ${taskWords(item)}${j.reason ? `
|
|
107
|
+
${String(j.reason)}` : ""}` : typeof j.message === "string" ? j.message : "Nothing to pick up: every task is done, claimed or waiting.";
|
|
108
|
+
}, ctx);
|
|
109
|
+
}
|
|
110
|
+
case "claim": {
|
|
111
|
+
const a = await agent.call("claim_item", { uid: await taskOf(ctx, first) });
|
|
112
|
+
return said(a, (j) => `Claimed ${taskWords(asObj(j.item ?? j))}.`, ctx);
|
|
113
|
+
}
|
|
114
|
+
case "update": {
|
|
115
|
+
const uid = await taskOf(ctx, first);
|
|
116
|
+
const raw = (0, import_args.flag)(p, "progress");
|
|
117
|
+
const percent = raw === void 0 ? NaN : Number(raw);
|
|
118
|
+
if (!Number.isInteger(percent) || percent < 0 || percent > 100) throw new UsageError("--progress takes a whole number from 0 to 100.");
|
|
119
|
+
const note = (0, import_args.flag)(p, "note");
|
|
120
|
+
const a = await agent.call("update_item_progress", { uid, percent, ...note ? { message: note } : {} });
|
|
121
|
+
return said(a, () => `${percent}%${note ? `: ${note}` : ""}`, ctx);
|
|
122
|
+
}
|
|
123
|
+
case "stuck": {
|
|
124
|
+
const uid = await taskOf(ctx, first);
|
|
125
|
+
const reason = more.join(" ").trim();
|
|
126
|
+
if (!reason) throw new UsageError("Say why: codetrellis stuck <task> <why\u2026>");
|
|
127
|
+
const a = await agent.call("set_item_blocked", { uid, reason });
|
|
128
|
+
return said(a, () => `Blocked: ${reason}`, ctx);
|
|
129
|
+
}
|
|
130
|
+
case "done": {
|
|
131
|
+
const uid = await taskOf(ctx, first);
|
|
132
|
+
const list = await agent.call("list_criteria", { item_uid: uid });
|
|
133
|
+
const criteria = Array.isArray(list.json) ? list.json : asObj(list.json).criteria ?? [];
|
|
134
|
+
const failing = [];
|
|
135
|
+
for (const c of criteria) {
|
|
136
|
+
const chk = await agent.call("check_criterion", { criterion_uid: c.uid });
|
|
137
|
+
const j = asObj(chk.json);
|
|
138
|
+
if (!chk.isError && j.ok === false) {
|
|
139
|
+
const findings = (j.findings ?? []).filter((f) => f.status === "fail").map((f) => f.message);
|
|
140
|
+
failing.push({ text: c.text, findings });
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (failing.length) {
|
|
144
|
+
if (ctx.json) return { out: JSON.stringify({ done: false, failing }), code: 1 };
|
|
145
|
+
return { out: `Not marked done: ${failing.length === 1 ? "a criterion's check fails" : `${failing.length} criteria's checks fail`}.
|
|
146
|
+
${failing.map((f) => ` \u2717 ${f.text}${f.findings.length ? `
|
|
147
|
+
${f.findings.join("\n ")}` : ""}`).join("\n")}`, code: 1 };
|
|
148
|
+
}
|
|
149
|
+
const a = await agent.call("update_item", { uid, status: "done" });
|
|
150
|
+
return said(a, (j) => `Done: ${taskWords(asObj(j.item ?? j))}`, ctx);
|
|
151
|
+
}
|
|
152
|
+
case "request":
|
|
153
|
+
return request(ctx, [first, ...more].filter(Boolean).join(" ").trim());
|
|
154
|
+
case "brief": {
|
|
155
|
+
const a = await agent.call("get_brief", { item_uid: await taskOf(ctx, first) });
|
|
156
|
+
if (a.isError) return { out: a.text, code: 1 };
|
|
157
|
+
return { out: ctx.json || a.json === null ? a.json !== null ? JSON.stringify(a.json) : a.text : JSON.stringify(a.json, null, 2), code: 0 };
|
|
158
|
+
}
|
|
159
|
+
case "awareness": {
|
|
160
|
+
const a = await agent.call("get_awareness", { project_path: projectRoot(cwd) });
|
|
161
|
+
return said(a, (j) => {
|
|
162
|
+
const signals = j.signals ?? [];
|
|
163
|
+
return signals.length ? signals.map((s) => `${s.severity === "high" ? "\u26A0" : "\xB7"} ${s.summary}`).join("\n") : "Nothing overlaps your work.";
|
|
164
|
+
}, ctx);
|
|
165
|
+
}
|
|
166
|
+
case "check":
|
|
167
|
+
return check(ctx, first);
|
|
168
|
+
case "rules": {
|
|
169
|
+
if (first !== "baseline") throw new UsageError("codetrellis rules baseline \u2014 record each rule's breaches now, so the check fails on new ones");
|
|
170
|
+
return writeBaseline(ctx, projectRoot(cwd));
|
|
171
|
+
}
|
|
172
|
+
case "report-tests": {
|
|
173
|
+
if (!first) throw new UsageError("Which report? codetrellis report-tests <junit.xml>");
|
|
174
|
+
const a = await agent.call("report_tests", { path: first, project_path: projectRoot(cwd) });
|
|
175
|
+
return said(a, (j) => {
|
|
176
|
+
const failing = j.failing ?? [];
|
|
177
|
+
return [typeof j.says === "string" ? j.says : JSON.stringify(j), ...failing.map((f) => ` \u2717 ${f.test}${f.why ? ` \u2014 ${f.why}` : ""}`)].join("\n");
|
|
178
|
+
}, ctx);
|
|
179
|
+
}
|
|
180
|
+
default:
|
|
181
|
+
throw new UsageError(`unknown verb ${verb}`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
async function request(ctx, question) {
|
|
185
|
+
if (!question) throw new UsageError("Ask something: codetrellis request <question\u2026>");
|
|
186
|
+
const plan = await planOf(ctx);
|
|
187
|
+
const item = (0, import_args.flag)(ctx.p, "item") ? await taskOf(ctx, (0, import_args.flag)(ctx.p, "item")) : null;
|
|
188
|
+
const options = ((0, import_args.flag)(ctx.p, "options") ?? "").split(",").map((o) => o.trim()).filter(Boolean);
|
|
189
|
+
const since = Date.now() - 1e3;
|
|
190
|
+
const posted = await ctx.agent.call("post_channel_event", {
|
|
191
|
+
plan_uid: plan,
|
|
192
|
+
item_uid: item,
|
|
193
|
+
message: question,
|
|
194
|
+
event_type: options.length ? "need-decision" : "need-context",
|
|
195
|
+
...options.length ? { options } : {}
|
|
196
|
+
});
|
|
197
|
+
if (posted.isError) return { out: posted.text, code: 1 };
|
|
198
|
+
const uid = String(asObj(posted.json).uid ?? "");
|
|
199
|
+
if (ctx.p.flags["no-wait"]) {
|
|
200
|
+
return { out: ctx.json ? JSON.stringify({ asked: uid, answered: false }) : `Asked (${uid}). Not waiting for the answer.`, code: 0 };
|
|
201
|
+
}
|
|
202
|
+
const timeout = Number((0, import_args.flag)(ctx.p, "timeout") ?? 300);
|
|
203
|
+
if (!Number.isFinite(timeout) || timeout < 0) throw new UsageError("--timeout takes seconds.");
|
|
204
|
+
const until = Date.now() + timeout * 1e3;
|
|
205
|
+
for (; ; ) {
|
|
206
|
+
const a = await ctx.agent.call("list_channel_events", { plan_uid: plan, event_types: ["steer"], since_ms: since });
|
|
207
|
+
const events = Array.isArray(a.json) ? a.json : asObj(a.json).events ?? [];
|
|
208
|
+
const reply = events.find((e) => {
|
|
209
|
+
const payload = asObj(e.payload);
|
|
210
|
+
return e.respondsTo === uid || e.responds_to === uid || payload.respondsTo === uid || payload.responds_to === uid;
|
|
211
|
+
});
|
|
212
|
+
if (reply) {
|
|
213
|
+
const text = String(reply.message ?? asObj(reply.payload).message ?? "");
|
|
214
|
+
const by = String(reply.author ?? reply.authorName ?? "the person");
|
|
215
|
+
return { out: ctx.json ? JSON.stringify({ asked: uid, answered: true, answer: text, by }) : `${by}: ${text}`, code: 0 };
|
|
216
|
+
}
|
|
217
|
+
if (Date.now() >= until) {
|
|
218
|
+
return { out: ctx.json ? JSON.stringify({ asked: uid, answered: false, timedOut: true }) : `No answer yet to ${uid}; it stays open on the plan.`, code: 3 };
|
|
219
|
+
}
|
|
220
|
+
await new Promise((r) => setTimeout(r, Math.min(2e3, Math.max(100, until - Date.now()))));
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
async function check(ctx, file) {
|
|
224
|
+
const root = projectRoot(ctx.cwd);
|
|
225
|
+
if (!file) return conforms(ctx, root);
|
|
226
|
+
const rel = import_node_path.default.isAbsolute(file) ? import_node_path.default.relative(root, file) : import_node_path.default.relative(root, import_node_path.default.resolve(ctx.cwd, file));
|
|
227
|
+
const footprint = await ctx.agent.call("check_footprint", { paths: [rel], project_path: root });
|
|
228
|
+
const breakpoint = await ctx.agent.call("check_breakpoint", { path: rel });
|
|
229
|
+
const bp = asObj(breakpoint.json);
|
|
230
|
+
const held = bp.status === "paused" || bp.status === "stop";
|
|
231
|
+
if (ctx.json) return { out: JSON.stringify({ path: rel, held, footprint: footprint.json ?? footprint.text, breakpoint: breakpoint.json ?? breakpoint.text }), code: held ? 3 : 0 };
|
|
232
|
+
const lines = [];
|
|
233
|
+
if (held) lines.push(`\u270B ${String(bp.message ?? breakpoint.text)}`);
|
|
234
|
+
else if (bp.status === "continue") lines.push(`${rel}: go ahead${bp.steer ? `, with this steer: ${String(bp.steer)}` : ""}.`);
|
|
235
|
+
else lines.push(`${rel}: no breakpoint holds it.`);
|
|
236
|
+
const entry = asObj((asObj(footprint.json).paths ?? [])[0]);
|
|
237
|
+
const changedIn = entry.changed_in ?? [];
|
|
238
|
+
const importedBy = entry.imported_by ?? [];
|
|
239
|
+
if (changedIn.length) lines.push(` also changed in ${changedIn.map((c) => c.branch ?? c.workstream).join(", ")}`);
|
|
240
|
+
if (importedBy.length) lines.push(` imported by ${importedBy.length} file${importedBy.length === 1 ? "" : "s"}: ${importedBy.slice(0, 5).join(", ")}${importedBy.length > 5 ? ", \u2026" : ""}`);
|
|
241
|
+
if (footprint.isError) lines.push(footprint.text);
|
|
242
|
+
return { out: lines.join("\n"), code: held ? 3 : 0 };
|
|
243
|
+
}
|
|
244
|
+
async function conforms(ctx, root) {
|
|
245
|
+
let changed;
|
|
246
|
+
try {
|
|
247
|
+
changed = (0, import_conformity.changedFiles)(root, (0, import_args.flag)(ctx.p, "base"), process.env);
|
|
248
|
+
} catch (err) {
|
|
249
|
+
throw new UsageError(err.message);
|
|
250
|
+
}
|
|
251
|
+
if (ctx.p.flags.pipeline === true || (0, import_args.flag)(ctx.p, "stage") !== void 0) {
|
|
252
|
+
const piped = await pipelined(ctx, root, changed);
|
|
253
|
+
if (piped) return piped;
|
|
254
|
+
}
|
|
255
|
+
const g = await (0, import_conformity.gate)(ctx.agent, root, changed, ctx.p.flags.strict === true, { suite: (0, import_args.flag)(ctx.p, "suite"), rule: (0, import_args.flag)(ctx.p, "rule"), path: (0, import_args.flag)(ctx.p, "path"), tag: (0, import_args.flag)(ctx.p, "tag") });
|
|
256
|
+
if ("error" in g) return { out: g.error, code: 1 };
|
|
257
|
+
const format = (0, import_args.flag)(ctx.p, "format") ?? (ctx.json ? "json" : "text");
|
|
258
|
+
if (format === "sarif") {
|
|
259
|
+
const read2 = (rel) => {
|
|
260
|
+
try {
|
|
261
|
+
return import_node_fs.default.readFileSync(import_node_path.default.join(root, rel), "utf8");
|
|
262
|
+
} catch {
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
return { out: JSON.stringify((0, import_sarif.toSarif)(g, { version: import_package.version, root, read: read2, ruleFile: (0, import_sarif.ruleFileIn)(root) }), null, 2), code: g.ok ? 0 : 3 };
|
|
267
|
+
}
|
|
268
|
+
const read = (rel) => {
|
|
269
|
+
try {
|
|
270
|
+
return import_node_fs.default.readFileSync(import_node_path.default.join(root, rel), "utf8");
|
|
271
|
+
} catch {
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
if (format === "json") return { out: JSON.stringify({ ...g, rules: (0, import_conformity.withPlaces)(g, read).rules }), code: g.ok ? 0 : 3 };
|
|
276
|
+
if (format === "markdown") return { out: (0, import_conformity.gateMarkdown)(g, read), code: g.ok ? 0 : 3 };
|
|
277
|
+
if (format !== "text") throw new UsageError(`--format is text, json, markdown or sarif, not ${format}`);
|
|
278
|
+
return { out: (0, import_conformity.gateWords)(g, { read, color: (0, import_conformity.wantsColor)(process.stdout, process.env, ctx.p.flags["no-color"] === true) }), code: g.ok ? 0 : 3 };
|
|
279
|
+
}
|
|
280
|
+
async function pipelined(ctx, root, changed) {
|
|
281
|
+
const got = changed.since ? await (0, import_pipeline.pipelineAt)(root, changed.since) : (0, import_pipeline.readPipeline)(root);
|
|
282
|
+
if (!got) return null;
|
|
283
|
+
if (!got.pipeline) return { out: `The pipeline${changed.since ? ` at ${changed.since.slice(0, 7)}` : ""} could not be read: ${got.problems.join("; ")}`, code: 1 };
|
|
284
|
+
const strict = ctx.p.flags.strict === true;
|
|
285
|
+
let review = null;
|
|
286
|
+
if ((0, import_args.flag)(ctx.p, "agent") !== void 0) {
|
|
287
|
+
const { review: runReview, reviewOptions, ReviewUsageError } = await Promise.resolve().then(() => __toESM(require("./review")));
|
|
288
|
+
let o;
|
|
289
|
+
try {
|
|
290
|
+
o = reviewOptions(ctx.p, ctx.cwd, process.env);
|
|
291
|
+
} catch (err) {
|
|
292
|
+
if (err instanceof ReviewUsageError) throw new UsageError(err.message);
|
|
293
|
+
throw err;
|
|
294
|
+
}
|
|
295
|
+
const me = (0, import_args.selfCommand)(import_node_path.default.resolve(__dirname, "..", "..", "bin"), { execPath: process.execPath, electron: process.versions.electron });
|
|
296
|
+
const sinkFor = (dir) => ({ command: me.command, args: [...me.args, "review-sink", "--pass", dir], env: me.env });
|
|
297
|
+
review = async (stage, scope, grounding) => {
|
|
298
|
+
const r = await runReview(ctx.agent, { ...o, scope: { suite: scope.suite, rule: scope.rule, path: scope.path, engine: scope.engine, strength: scope.strength, tag: scope.tag }, stage: stage.id, grounding, format: "json", failOn: /* @__PURE__ */ new Set(["block"]), post: null }, ctx.cwd, process.env, sinkFor, { version: import_package.version });
|
|
299
|
+
let j;
|
|
300
|
+
try {
|
|
301
|
+
j = JSON.parse(r.out);
|
|
302
|
+
} catch {
|
|
303
|
+
return { error: r.out };
|
|
304
|
+
}
|
|
305
|
+
if (j.error) return { error: j.error };
|
|
306
|
+
const findings = (j.passes ?? []).flatMap((pass) => pass.kept.filter((k) => k.path).map((k) => ({ stage: stage.id, path: k.path, says: k.says, rule: k.rule })));
|
|
307
|
+
return { ok: r.code === 0, out: j.says ?? (j.passes ?? []).flatMap((pass) => [`review: ${pass.says}`, ...pass.kept.map((k) => ` ${(0, import_review_output.findingWords)(k)}`)]).join("\n"), findings };
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
const result = await (0, import_pipeline2.runPipeline)(got.pipeline, { gate: (scope) => (0, import_conformity.gate)(ctx.agent, root, changed, strict, scope), review }, (0, import_args.flag)(ctx.p, "stage"));
|
|
311
|
+
const code = result.stages.some((s) => !s.ok && !s.advisory && (s.gate && "error" in s.gate)) ? 1 : result.ok ? 0 : 3;
|
|
312
|
+
if (ctx.json || (0, import_args.flag)(ctx.p, "format") === "json") return { out: JSON.stringify(result), code };
|
|
313
|
+
const read = (rel) => {
|
|
314
|
+
try {
|
|
315
|
+
return import_node_fs.default.readFileSync(import_node_path.default.join(root, rel), "utf8");
|
|
316
|
+
} catch {
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
const color = (0, import_conformity.wantsColor)(process.stdout, process.env, ctx.p.flags["no-color"] === true);
|
|
321
|
+
return { out: (0, import_pipeline2.pipelineWords)(result, (g) => (0, import_conformity.gateWords)(g, { read, color })), code };
|
|
322
|
+
}
|
|
323
|
+
async function writeBaseline(ctx, root) {
|
|
324
|
+
const a = await ctx.agent.call("list_rules", { project_path: root });
|
|
325
|
+
if (a.isError) return { out: a.text, code: 1 };
|
|
326
|
+
const views = asObj(a.json).rules ?? [];
|
|
327
|
+
if (views.some((v) => v.rule.strength !== "guide" && v.breaches === null)) {
|
|
328
|
+
return { out: "The rules' breaches could not be read: this project's imports are not loaded. Run `codetrellis start` in it first.", code: 1 };
|
|
329
|
+
}
|
|
330
|
+
const now = new Map(views.filter((v) => v.rule.strength !== "guide").map((v) => [v.rule.id, new Set((v.breaches ?? []).map((b) => `${b.from} > ${b.to}`))]));
|
|
331
|
+
const before = (0, import_rule_baseline.readBaseline)(root);
|
|
332
|
+
const next = /* @__PURE__ */ new Map();
|
|
333
|
+
const lines = [];
|
|
334
|
+
let held = 0;
|
|
335
|
+
for (const [id, entries] of now) {
|
|
336
|
+
const was = before?.get(id);
|
|
337
|
+
if (!was) {
|
|
338
|
+
next.set(id, entries);
|
|
339
|
+
lines.push(` ${id}: ${entries.size} ${entries.size === 1 ? "breach" : "breaches"} recorded`);
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
const kept = new Set([...entries].filter((e) => was.has(e)));
|
|
343
|
+
held += entries.size - kept.size;
|
|
344
|
+
next.set(id, kept);
|
|
345
|
+
lines.push(` ${id}: ${kept.size}${kept.size < was.size ? `, down from ${was.size}` : ""}`);
|
|
346
|
+
}
|
|
347
|
+
(0, import_confined_fs.writeFileWithin)(root, import_rule_baseline.BASELINE_FILE, (0, import_rule_baseline.baselineYaml)(next), "rule baseline");
|
|
348
|
+
if (ctx.json) return { out: JSON.stringify({ file: import_rule_baseline.BASELINE_FILE, rules: Object.fromEntries([...next].map(([k, v]) => [k, [...v]])), notAdded: held }), code: 0 };
|
|
349
|
+
return {
|
|
350
|
+
out: [`Wrote ${import_rule_baseline.BASELINE_FILE}:`, ...lines, ...held ? [`${held} new ${held === 1 ? "breach is" : "breaches are"} not added: a baseline only shrinks. Fix ${held === 1 ? "it" : "them"}, or change the rule in the app.`] : [], "Commit it with the code."].join("\n"),
|
|
351
|
+
code: 0
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
355
|
+
0 && (module.exports = {
|
|
356
|
+
UsageError,
|
|
357
|
+
VERBS,
|
|
358
|
+
projectRoot,
|
|
359
|
+
runVerb
|
|
360
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
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 build_info_exports = {};
|
|
19
|
+
__export(build_info_exports, {
|
|
20
|
+
BUILD_INFO: () => BUILD_INFO
|
|
21
|
+
});
|
|
22
|
+
module.exports = __toCommonJS(build_info_exports);
|
|
23
|
+
var import_package = require("../../package.json");
|
|
24
|
+
const UNSTAMPED = {
|
|
25
|
+
buildTime: "",
|
|
26
|
+
buildNumber: 0,
|
|
27
|
+
commit: "",
|
|
28
|
+
commitShort: "",
|
|
29
|
+
branch: "",
|
|
30
|
+
dirty: false
|
|
31
|
+
};
|
|
32
|
+
const BUILD_INFO = {
|
|
33
|
+
version: import_package.version,
|
|
34
|
+
...typeof __CODETRELLIS_BUILD__ === "undefined" ? UNSTAMPED : __CODETRELLIS_BUILD__
|
|
35
|
+
};
|
|
36
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
37
|
+
0 && (module.exports = {
|
|
38
|
+
BUILD_INFO
|
|
39
|
+
});
|
|
@@ -0,0 +1,199 @@
|
|
|
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 agent_review_exports = {};
|
|
19
|
+
__export(agent_review_exports, {
|
|
20
|
+
FINDING_KINDS: () => FINDING_KINDS,
|
|
21
|
+
TOPIC_RE: () => TOPIC_RE,
|
|
22
|
+
agentFindingLine: () => agentFindingLine,
|
|
23
|
+
parseAgentReview: () => parseAgentReview,
|
|
24
|
+
parseUnifiedDiff: () => parseUnifiedDiff,
|
|
25
|
+
reviewBlockWords: () => reviewBlockWords,
|
|
26
|
+
reviewOutcome: () => reviewOutcome,
|
|
27
|
+
reviewWords: () => reviewWords,
|
|
28
|
+
verifyFindings: () => verifyFindings,
|
|
29
|
+
wholeFile: () => wholeFile
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(agent_review_exports);
|
|
32
|
+
const FINDING_KINDS = ["rule", "bug", "risk", "question", "suspicious"];
|
|
33
|
+
const TOPIC_RE = /^[a-z0-9][a-z0-9-]{1,62}$/;
|
|
34
|
+
function parseUnifiedDiff(text2) {
|
|
35
|
+
const out = /* @__PURE__ */ new Map();
|
|
36
|
+
let file = null;
|
|
37
|
+
let line = 0;
|
|
38
|
+
for (const raw of text2.split("\n")) {
|
|
39
|
+
if (raw.startsWith("+++ ")) {
|
|
40
|
+
const p = raw.slice(4).trim();
|
|
41
|
+
file = p === "/dev/null" ? null : p.replace(/^b\//, "");
|
|
42
|
+
if (file && !out.has(file)) out.set(file, /* @__PURE__ */ new Map());
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (raw.startsWith("--- ") || raw.startsWith("diff ") || raw.startsWith("index ")) continue;
|
|
46
|
+
const hunk = /^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/.exec(raw);
|
|
47
|
+
if (hunk) {
|
|
48
|
+
line = Number(hunk[1]);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (!file || line === 0) continue;
|
|
52
|
+
if (raw.startsWith("+") || raw.startsWith(" ")) {
|
|
53
|
+
out.get(file).set(line, raw.slice(1));
|
|
54
|
+
line += 1;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
59
|
+
function wholeFile(text2) {
|
|
60
|
+
const lines = text2.split("\n");
|
|
61
|
+
if (lines.length && lines[lines.length - 1] === "") lines.pop();
|
|
62
|
+
return new Map(lines.map((l, i) => [i + 1, l]));
|
|
63
|
+
}
|
|
64
|
+
const MAX_FINDINGS = 100;
|
|
65
|
+
const MAX_SPAN = 200;
|
|
66
|
+
const squash = (s) => s.replace(/\s+/g, " ").trim();
|
|
67
|
+
const text = (v, max) => typeof v === "string" && v.trim() ? v.trim().slice(0, max) : null;
|
|
68
|
+
function verifyFindings(diff, rules, reported) {
|
|
69
|
+
const kept = [];
|
|
70
|
+
const dropped = [];
|
|
71
|
+
const seen = /* @__PURE__ */ new Set();
|
|
72
|
+
for (const r of reported.slice(0, MAX_FINDINGS)) {
|
|
73
|
+
const says = text(r.says, 1e3);
|
|
74
|
+
const drop = (why) => dropped.push({ says: says ?? "(no words)", why });
|
|
75
|
+
if (!says) {
|
|
76
|
+
drop("it says nothing");
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (!FINDING_KINDS.includes(r.kind)) {
|
|
80
|
+
drop(`its kind, ${String(r.kind)}, is not one of ${FINDING_KINDS.join(", ")}`);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const kind = r.kind;
|
|
84
|
+
const cited = !!(r.file || r.start_line || r.quote);
|
|
85
|
+
let path = null;
|
|
86
|
+
let start = null;
|
|
87
|
+
let end = null;
|
|
88
|
+
let quote = null;
|
|
89
|
+
if (cited || kind !== "question") {
|
|
90
|
+
path = text(r.file, 500);
|
|
91
|
+
const lines = path ? diff.get(path) : void 0;
|
|
92
|
+
if (!path || !lines) {
|
|
93
|
+
drop(path ? `${path} is not in the change` : "it names no file");
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
start = Number.isSafeInteger(r.start_line) ? r.start_line : null;
|
|
97
|
+
end = Number.isSafeInteger(r.end_line) ? r.end_line : start;
|
|
98
|
+
if (start === null || end === null || end < start || end - start > MAX_SPAN) {
|
|
99
|
+
drop("it names no line range in the file");
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
const span = [];
|
|
103
|
+
for (let n = start; n <= end; n++) {
|
|
104
|
+
const l = lines.get(n);
|
|
105
|
+
if (l === void 0) break;
|
|
106
|
+
span.push(l);
|
|
107
|
+
}
|
|
108
|
+
if (span.length !== end - start + 1) {
|
|
109
|
+
drop(`lines ${start}\u2013${end} of ${path} are not in the diff`);
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
quote = text(r.quote, 2e3);
|
|
113
|
+
if (!quote) {
|
|
114
|
+
drop("it quotes no code");
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (!squash(span.join("\n")).includes(squash(quote))) {
|
|
118
|
+
drop(`its quote is not what lines ${start}\u2013${end} of ${path} say`);
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const rule = text(r.rule, 63);
|
|
123
|
+
if (kind === "rule" && (!rule || !rules.has(rule))) {
|
|
124
|
+
drop(rule ? `the rule ${rule} is not in scope` : "a rule finding names no rule");
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const key = `${kind}|${path}|${start}|${end}|${squash(says)}`;
|
|
128
|
+
if (seen.has(key)) continue;
|
|
129
|
+
seen.add(key);
|
|
130
|
+
const topic = typeof r.topic === "string" && TOPIC_RE.test(r.topic.trim()) ? r.topic.trim() : null;
|
|
131
|
+
kept.push({ kind, path, start, end, quote, says, rule: kind === "rule" ? rule : rule && rules.has(rule) ? rule : null, fix: text(r.fix, 500), topic });
|
|
132
|
+
}
|
|
133
|
+
if (reported.length > MAX_FINDINGS) dropped.push({ says: `${reported.length - MAX_FINDINGS} more`, why: `a review reports at most ${MAX_FINDINGS} findings` });
|
|
134
|
+
return { kept, dropped };
|
|
135
|
+
}
|
|
136
|
+
function reviewOutcome(reported, kept) {
|
|
137
|
+
if (reported.inconclusive) return { outcome: "inconclusive", reason: reported.inconclusive };
|
|
138
|
+
if (kept.length > 0) return { outcome: "findings", reason: null };
|
|
139
|
+
if (reported.findings.length > 0) return { outcome: "inconclusive", reason: "none of its findings could be grounded in the change" };
|
|
140
|
+
return { outcome: "pass", reason: null };
|
|
141
|
+
}
|
|
142
|
+
const GLYPH = { rule: "\u2717", bug: "\u2717", risk: "\u26A0", question: "?", suspicious: "\u2691" };
|
|
143
|
+
function reviewWords(r) {
|
|
144
|
+
const dropped = r.dropped.length ? ` \xB7 ${r.dropped.length} dropped` : "";
|
|
145
|
+
if (r.outcome === "error") return `\u2717 error: ${r.reason ?? "the agent could not run"}`;
|
|
146
|
+
if (r.outcome === "inconclusive") return `? inconclusive: ${r.reason ?? "no reason given"}${dropped}`;
|
|
147
|
+
if (r.outcome === "pass") return `\u2713 nothing found${dropped}`;
|
|
148
|
+
const questions = r.findings.filter((f) => f.kind === "question").length;
|
|
149
|
+
const others = r.findings.length - questions;
|
|
150
|
+
return [
|
|
151
|
+
others ? `\u26A0 ${others} ${others === 1 ? "finding" : "findings"}` : null,
|
|
152
|
+
questions ? `? ${questions} ${questions === 1 ? "question" : "questions"}` : null
|
|
153
|
+
].filter(Boolean).join(" \xB7 ") + dropped;
|
|
154
|
+
}
|
|
155
|
+
function reviewBlockWords(r, blocks) {
|
|
156
|
+
return `${blocks > 0 ? `\u2717 ${blocks} block \xB7 ` : ""}${reviewWords(r)}`;
|
|
157
|
+
}
|
|
158
|
+
function agentFindingLine(f) {
|
|
159
|
+
const where = f.path ? `${f.path}${f.start ? `:${f.start}${f.end && f.end !== f.start ? `\u2013${f.end}` : ""}` : ""}` : "the change";
|
|
160
|
+
return `${GLYPH[f.kind]} ${f.kind}${f.rule ? ` (${f.rule})` : ""} \xB7 ${where}: ${f.says}${f.fix ? ` \u2192 ${f.fix}` : ""}`;
|
|
161
|
+
}
|
|
162
|
+
function parseAgentReview(raw) {
|
|
163
|
+
if (!raw || typeof raw !== "object") return null;
|
|
164
|
+
const r = raw;
|
|
165
|
+
const outcome = ["pass", "findings", "inconclusive", "error"].find((o) => o === r.outcome);
|
|
166
|
+
if (!outcome) return null;
|
|
167
|
+
const findings = (Array.isArray(r.findings) ? r.findings : []).slice(0, MAX_FINDINGS).flatMap((x) => {
|
|
168
|
+
const f = x && typeof x === "object" ? x : {};
|
|
169
|
+
const kind = FINDING_KINDS.includes(f.kind) ? f.kind : null;
|
|
170
|
+
const says = text(f.says, 1e3);
|
|
171
|
+
if (!kind || !says) return [];
|
|
172
|
+
const n = (v) => Number.isSafeInteger(v) && v > 0 ? v : null;
|
|
173
|
+
const p = typeof f.path === "string" && f.path && !f.path.startsWith("/") && !f.path.split("/").includes("..") ? f.path.slice(0, 500) : null;
|
|
174
|
+
const topic = typeof f.topic === "string" && TOPIC_RE.test(f.topic) ? f.topic : null;
|
|
175
|
+
return [{ kind, path: p, start: n(f.start), end: n(f.end), quote: text(f.quote, 2e3), says, rule: text(f.rule, 63), fix: text(f.fix, 500), topic }];
|
|
176
|
+
});
|
|
177
|
+
const dropped = (Array.isArray(r.dropped) ? r.dropped : []).slice(0, 200).flatMap((x) => {
|
|
178
|
+
const d = x && typeof x === "object" ? x : {};
|
|
179
|
+
const says = text(d.says, 1e3);
|
|
180
|
+
const why = text(d.why, 300);
|
|
181
|
+
return says && why ? [{ says, why }] : [];
|
|
182
|
+
});
|
|
183
|
+
const refused = (Array.isArray(r.refused) ? r.refused : []).map((x) => text(x, 300)).filter((x) => !!x).slice(0, 200);
|
|
184
|
+
const retries = Number.isSafeInteger(r.retries) && r.retries > 0 ? Math.min(r.retries, 10) : 0;
|
|
185
|
+
return { outcome, reason: text(r.reason, 500), agent: text(r.agent, 80) ?? "an agent", findings, dropped, refused, pass: text(r.pass, 80), retries, verify: text(r.verify, 300) };
|
|
186
|
+
}
|
|
187
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
188
|
+
0 && (module.exports = {
|
|
189
|
+
FINDING_KINDS,
|
|
190
|
+
TOPIC_RE,
|
|
191
|
+
agentFindingLine,
|
|
192
|
+
parseAgentReview,
|
|
193
|
+
parseUnifiedDiff,
|
|
194
|
+
reviewBlockWords,
|
|
195
|
+
reviewOutcome,
|
|
196
|
+
reviewWords,
|
|
197
|
+
verifyFindings,
|
|
198
|
+
wholeFile
|
|
199
|
+
});
|