create-walle 0.9.21 → 0.9.23
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/README.md +27 -5
- package/package.json +2 -2
- package/template/CLAUDE.md +2 -2
- package/template/LICENSE +1 -1
- package/template/bin/ctm-dev-cleanup.js +24 -3
- package/template/bin/ctm-launch.sh +13 -0
- package/template/bin/dev.sh +156 -18
- package/template/bin/node-bin.sh +84 -0
- package/template/bin/pin-node.sh +51 -0
- package/template/claude-task-manager/api-prompts.js +1203 -182
- package/template/claude-task-manager/api-reviews.js +109 -15
- package/template/claude-task-manager/approval-agent.js +1360 -280
- package/template/claude-task-manager/bin/restart-ctm.sh +64 -23
- package/template/claude-task-manager/bin/storage-migration-supervisor.js +338 -0
- package/template/claude-task-manager/db.js +4417 -295
- package/template/claude-task-manager/docs/app-update-refresh-protocol.md +69 -0
- package/template/claude-task-manager/docs/approval-ai-refinement.md +138 -0
- package/template/claude-task-manager/docs/approval-rescue-loop.md +74 -0
- package/template/claude-task-manager/docs/codex-operational-warning-health.md +107 -0
- package/template/claude-task-manager/docs/codex-resume-state-guard-design.md +17 -12
- package/template/claude-task-manager/docs/codex-terminal-render-controller-handoff.md +311 -0
- package/template/claude-task-manager/docs/coding-agent-hooks-architecture.md +418 -0
- package/template/claude-task-manager/docs/conversation-import-freshness.md +20 -0
- package/template/claude-task-manager/docs/google-workspace-auth-health.md +77 -0
- package/template/claude-task-manager/docs/image-paste-ux.md +13 -0
- package/template/claude-task-manager/docs/ipad-web-preview.md +88 -0
- package/template/claude-task-manager/docs/main-loop-offload-architecture.md +66 -0
- package/template/claude-task-manager/docs/microsoft-dev-tunnel-phone-access-design.md +274 -519
- package/template/claude-task-manager/docs/mobile-live-streaming.md +27 -5
- package/template/claude-task-manager/docs/mobile-remote-submission-lifecycle.md +69 -0
- package/template/claude-task-manager/docs/phone-access-design.md +53 -15
- package/template/claude-task-manager/docs/phone-passkey-identity.md +122 -0
- package/template/claude-task-manager/docs/phone-setup.md +3 -0
- package/template/claude-task-manager/docs/prompt-editing-tree-design.md +25 -1
- package/template/claude-task-manager/docs/remote-desktop-access-design.md +268 -0
- package/template/claude-task-manager/docs/restart-lifecycle-architecture.md +95 -0
- package/template/claude-task-manager/docs/runtime-work-control-plane.md +53 -0
- package/template/claude-task-manager/docs/session-interactive-wait-surfaces.md +38 -0
- package/template/claude-task-manager/docs/session-needs-you-dismissal.md +84 -0
- package/template/claude-task-manager/docs/session-render-state-management-design.md +91 -3
- package/template/claude-task-manager/docs/session-standup-command-center-design.md +25 -1
- package/template/claude-task-manager/docs/session-title-authority.md +32 -0
- package/template/claude-task-manager/docs/session-workspace-binding.md +33 -0
- package/template/claude-task-manager/docs/skill-intent-resolution-design.md +72 -0
- package/template/claude-task-manager/docs/walle-mcp-supervisor-health.md +86 -0
- package/template/claude-task-manager/docs/walle-relay-phone-access-design.md +24 -15
- package/template/claude-task-manager/docs/walle-session-history-hydration.md +114 -0
- package/template/claude-task-manager/docs/walle-session-input-queue.md +104 -0
- package/template/claude-task-manager/docs/walle-session-model-catalog.md +90 -0
- package/template/claude-task-manager/docs/walle-session-model-preferences.md +15 -6
- package/template/claude-task-manager/git-utils.js +897 -27
- package/template/claude-task-manager/lib/agent-capabilities.js +33 -0
- package/template/claude-task-manager/lib/agent-cli-cache.js +37 -7
- package/template/claude-task-manager/lib/agent-hooks-installer.js +26 -2
- package/template/claude-task-manager/lib/agent-presets.js +17 -1
- package/template/claude-task-manager/lib/all-sessions-query.js +108 -0
- package/template/claude-task-manager/lib/approval-ai-refinement.js +488 -0
- package/template/claude-task-manager/lib/approval-self-adapt.js +168 -0
- package/template/claude-task-manager/lib/async-semaphore.js +44 -0
- package/template/claude-task-manager/lib/auth-context.js +5 -0
- package/template/claude-task-manager/lib/auth-rate-limit.js +47 -4
- package/template/claude-task-manager/lib/auth-rules.js +29 -2
- package/template/claude-task-manager/lib/auto-approval-verifier.js +129 -16
- package/template/claude-task-manager/lib/background-llm.js +144 -17
- package/template/claude-task-manager/lib/branch-inventory.js +212 -0
- package/template/claude-task-manager/lib/claude-desktop-sessions.js +15 -3
- package/template/claude-task-manager/lib/coalesce-sync-frames.js +151 -0
- package/template/claude-task-manager/lib/codex-launch-health.js +762 -0
- package/template/claude-task-manager/lib/codex-transcript-pager.js +51 -0
- package/template/claude-task-manager/lib/codex-zst.js +124 -0
- package/template/claude-task-manager/lib/coding-agent-models.js +233 -30
- package/template/claude-task-manager/lib/connection-health.js +232 -0
- package/template/claude-task-manager/lib/conversation-blob-parser.js +42 -0
- package/template/claude-task-manager/lib/conversation-tail-merge.js +89 -26
- package/template/claude-task-manager/lib/ctm-session-context-api.js +39 -10
- package/template/claude-task-manager/lib/cursor-conversation-store.js +354 -0
- package/template/claude-task-manager/lib/db-owner-worker-client.js +315 -0
- package/template/claude-task-manager/lib/document-review.js +141 -6
- package/template/claude-task-manager/lib/escalation-review.js +152 -0
- package/template/claude-task-manager/lib/graceful-shutdown.js +159 -0
- package/template/claude-task-manager/lib/headless-term-service.js +678 -0
- package/template/claude-task-manager/lib/heavy-worker-fallback.js +38 -0
- package/template/claude-task-manager/lib/jsonl-conversation-parser.js +542 -0
- package/template/claude-task-manager/lib/jsonl-range-reader.js +112 -0
- package/template/claude-task-manager/lib/main-db-census.js +216 -0
- package/template/claude-task-manager/lib/message-pagination.js +106 -4
- package/template/claude-task-manager/lib/microsoft-dev-tunnel-setup.js +750 -26
- package/template/claude-task-manager/lib/mobile-auth-api.js +274 -7
- package/template/claude-task-manager/lib/mobile-auth-store.js +592 -10
- package/template/claude-task-manager/lib/mobile-notification-dispatcher.js +15 -0
- package/template/claude-task-manager/lib/model-overview-brain-fallback.js +311 -0
- package/template/claude-task-manager/lib/model-overview-cache.js +141 -0
- package/template/claude-task-manager/lib/models-health-routing-notice.js +126 -0
- package/template/claude-task-manager/lib/node-pin-guard.js +93 -0
- package/template/claude-task-manager/lib/perf-tracker.js +242 -6
- package/template/claude-task-manager/lib/permission-match.js +76 -0
- package/template/claude-task-manager/lib/permission-sync.js +133 -20
- package/template/claude-task-manager/lib/process-title.js +35 -0
- package/template/claude-task-manager/lib/prompt-executions-query.js +25 -0
- package/template/claude-task-manager/lib/prompt-index-disk-cache.js +44 -0
- package/template/claude-task-manager/lib/prompt-intent.js +132 -0
- package/template/claude-task-manager/lib/provider-user-context.js +34 -0
- package/template/claude-task-manager/lib/read-pool-client.js +313 -0
- package/template/claude-task-manager/lib/readpool-breaker.js +31 -0
- package/template/claude-task-manager/lib/recent-sessions-breaker.js +12 -0
- package/template/claude-task-manager/lib/remote-feedback-client.js +72 -0
- package/template/claude-task-manager/lib/remote-relay-protocol.js +37 -4
- package/template/claude-task-manager/lib/remote-relay-store.js +159 -0
- package/template/claude-task-manager/lib/remote-submission-observer.js +278 -0
- package/template/claude-task-manager/lib/restart-guard.js +109 -0
- package/template/claude-task-manager/lib/restore-interruption-detector.js +439 -0
- package/template/claude-task-manager/lib/restore-policy.js +13 -0
- package/template/claude-task-manager/lib/restore-resume-batch.js +74 -0
- package/template/claude-task-manager/lib/restore-runtime.js +68 -0
- package/template/claude-task-manager/lib/restore-storm.js +34 -0
- package/template/claude-task-manager/lib/resume-cwd.js +36 -0
- package/template/claude-task-manager/lib/resume-preflight.js +313 -0
- package/template/claude-task-manager/lib/runtime-work-registry.js +444 -0
- package/template/claude-task-manager/lib/sanitize-openai-auth.js +31 -0
- package/template/claude-task-manager/lib/scheduler.js +21 -1
- package/template/claude-task-manager/lib/scrollback-snapshot-store.js +159 -0
- package/template/claude-task-manager/lib/serial-task-queue.js +64 -0
- package/template/claude-task-manager/lib/server-listeners.js +239 -0
- package/template/claude-task-manager/lib/session-capture.js +42 -7
- package/template/claude-task-manager/lib/session-content-backfill.js +131 -0
- package/template/claude-task-manager/lib/session-history.js +388 -43
- package/template/claude-task-manager/lib/session-host-manager.js +287 -0
- package/template/claude-task-manager/lib/session-image-refs.js +209 -0
- package/template/claude-task-manager/lib/session-jobs.js +399 -59
- package/template/claude-task-manager/lib/session-prompt-index.js +137 -0
- package/template/claude-task-manager/lib/session-restore.js +53 -0
- package/template/claude-task-manager/lib/session-standup.js +123 -23
- package/template/claude-task-manager/lib/session-state-bus.js +14 -0
- package/template/claude-task-manager/lib/session-stream.js +64 -16
- package/template/claude-task-manager/lib/session-timeline-summary.js +260 -0
- package/template/claude-task-manager/lib/session-token-usage.js +494 -0
- package/template/claude-task-manager/lib/session-workspace-binding.js +356 -0
- package/template/claude-task-manager/lib/setup-network-config.js +9 -0
- package/template/claude-task-manager/lib/size-cap.js +45 -0
- package/template/claude-task-manager/lib/size-cap.test.js +62 -0
- package/template/claude-task-manager/lib/skill-autocomplete.js +180 -1
- package/template/claude-task-manager/lib/skill-intent-resolver.js +304 -0
- package/template/claude-task-manager/lib/sqlite-driver.js +19 -3
- package/template/claude-task-manager/lib/standup-attention.js +7 -3
- package/template/claude-task-manager/lib/status-authority.js +39 -0
- package/template/claude-task-manager/lib/status-hooks.js +4 -0
- package/template/claude-task-manager/lib/storage-migration.js +235 -0
- package/template/claude-task-manager/lib/structured-capture.js +298 -0
- package/template/claude-task-manager/lib/sync-io-census.js +163 -0
- package/template/claude-task-manager/lib/tailscale-setup.js +6 -0
- package/template/claude-task-manager/lib/terminal-activity-evidence.js +33 -0
- package/template/claude-task-manager/lib/terminal-choice.js +364 -0
- package/template/claude-task-manager/lib/terminal-control-sanitize.js +17 -0
- package/template/claude-task-manager/lib/terminal-fingerprint.js +48 -0
- package/template/claude-task-manager/lib/terminal-output-flush.js +84 -0
- package/template/claude-task-manager/lib/timeline-order.js +122 -0
- package/template/claude-task-manager/lib/transcript-store.js +348 -43
- package/template/claude-task-manager/lib/transport-security.js +84 -1
- package/template/claude-task-manager/lib/wait-state.js +184 -0
- package/template/claude-task-manager/lib/walle-client.js +47 -5
- package/template/claude-task-manager/lib/walle-ctm-history.js +564 -4
- package/template/claude-task-manager/lib/walle-external-actions.js +135 -16
- package/template/claude-task-manager/lib/walle-history-hydration.js +46 -0
- package/template/claude-task-manager/lib/walle-native-health.js +403 -0
- package/template/claude-task-manager/lib/walle-repair.js +701 -0
- package/template/claude-task-manager/lib/walle-session-cache.js +109 -0
- package/template/claude-task-manager/lib/walle-session-context.js +57 -21
- package/template/claude-task-manager/lib/walle-session-model-catalog.js +34 -0
- package/template/claude-task-manager/lib/walle-supervisor.js +539 -63
- package/template/claude-task-manager/lib/walle-transcript.js +52 -0
- package/template/claude-task-manager/lib/worktree-active-sync.js +11 -7
- package/template/claude-task-manager/lib/worktree-cwd.js +32 -1
- package/template/claude-task-manager/package.json +1 -1
- package/template/claude-task-manager/prompt-harvest.js +89 -66
- package/template/claude-task-manager/providers/claude-code.js +51 -3
- package/template/claude-task-manager/providers/cursor.js +140 -45
- package/template/claude-task-manager/public/css/reviews.css +551 -61
- package/template/claude-task-manager/public/css/setup.css +191 -0
- package/template/claude-task-manager/public/css/walle-session.css +865 -10
- package/template/claude-task-manager/public/css/walle.css +154 -0
- package/template/claude-task-manager/public/designs/ai-providers-consolidation-v2.html +830 -0
- package/template/claude-task-manager/public/index.html +18516 -2058
- package/template/claude-task-manager/public/ipad.html +363 -0
- package/template/claude-task-manager/public/js/document-review-links.js +301 -0
- package/template/claude-task-manager/public/js/image-normalize.js +69 -36
- package/template/claude-task-manager/public/js/message-renderer.js +1265 -77
- package/template/claude-task-manager/public/js/prompts.js +66 -29
- package/template/claude-task-manager/public/js/reviews.js +901 -133
- package/template/claude-task-manager/public/js/session-activity-utils.js +11 -1
- package/template/claude-task-manager/public/js/session-search-utils.js +94 -10
- package/template/claude-task-manager/public/js/session-status-precedence.js +23 -5
- package/template/claude-task-manager/public/js/setup.js +1273 -176
- package/template/claude-task-manager/public/js/stream-view.js +691 -73
- package/template/claude-task-manager/public/js/terminal-reconciler.js +210 -0
- package/template/claude-task-manager/public/js/walle-session.js +2455 -158
- package/template/claude-task-manager/public/js/walle.js +455 -28
- package/template/claude-task-manager/public/m/app.css +2909 -262
- package/template/claude-task-manager/public/m/app.js +6601 -398
- package/template/claude-task-manager/public/m/claim.html +224 -17
- package/template/claude-task-manager/public/m/index.html +117 -21
- package/template/claude-task-manager/public/m/sw.js +3 -1
- package/template/claude-task-manager/public/manifest.json +2 -2
- package/template/claude-task-manager/public/prompts.html +30 -14
- package/template/claude-task-manager/queue-engine.js +507 -28
- package/template/claude-task-manager/scripts/repair-claude-session-images.js +27 -8
- package/template/claude-task-manager/server.js +14341 -2197
- package/template/claude-task-manager/session-integrity.js +160 -18
- package/template/claude-task-manager/session-search-ranking.js +1 -0
- package/template/claude-task-manager/session-utils.js +25 -5
- package/template/claude-task-manager/workers/approval-blocklist.js +96 -6
- package/template/claude-task-manager/workers/approval-widget-validator.js +14 -8
- package/template/claude-task-manager/workers/conversation-import-worker.js +11 -50
- package/template/claude-task-manager/workers/db-owner-worker.js +386 -0
- package/template/claude-task-manager/workers/harvest-worker.js +9 -55
- package/template/claude-task-manager/workers/headless-term-worker.js +9 -530
- package/template/claude-task-manager/workers/read-pool-worker.js +387 -0
- package/template/claude-task-manager/workers/scrollback-worker.js +11 -72
- package/template/claude-task-manager/workers/session-host-process.js +146 -0
- package/template/claude-task-manager/workers/session-integrity-worker.js +10 -54
- package/template/claude-task-manager/workers/state-detectors/base.js +18 -1
- package/template/claude-task-manager/workers/state-detectors/claude-code.js +182 -9
- package/template/claude-task-manager/workers/state-detectors/codex.js +150 -2
- package/template/claude-task-manager/workers/state-detectors/cursor.js +127 -0
- package/template/claude-task-manager/workers/state-detectors/gemini.js +21 -0
- package/template/claude-task-manager/workers/state-detectors/index.js +29 -0
- package/template/claude-task-manager/workers/state-detectors/opencode.js +103 -0
- package/template/docs/design/markdown-review-pane.md +206 -0
- package/template/docs/designs/2026-05-17-portkey-gateway-provider-ux.md +129 -38
- package/template/docs/designs/2026-05-20-mobile-worktree-finish-command.md +27 -0
- package/template/docs/designs/2026-05-22-ai-configuration-consolidation.md +248 -0
- package/template/docs/designs/ai-configuration-consolidation-mock.html +812 -0
- package/template/docs/private-memory-and-pii-policy.md +69 -0
- package/template/package.json +2 -1
- package/template/scripts/check-private-data.js +201 -0
- package/template/shared/sqlite-owner-guard.js +30 -0
- package/template/shared/sqlite-owner-write-queue.js +225 -0
- package/template/shared/sqlite-storage-policy.js +111 -0
- package/template/shared/sqlite-write-lock.js +428 -0
- package/template/wall-e/agent-runners/claude-code.js +5 -0
- package/template/wall-e/agent.js +166 -22
- package/template/wall-e/api-walle.js +524 -70
- package/template/wall-e/auth/provider-flows.js +11 -1
- package/template/wall-e/bin/walle-mcp-stdio.js +341 -17
- package/template/wall-e/brain.js +1614 -141
- package/template/wall-e/chat/attachment-blocks.js +96 -0
- package/template/wall-e/chat/attachments.js +2 -1
- package/template/wall-e/chat/capability-resolver.js +7 -7
- package/template/wall-e/chat/context-messages.js +28 -0
- package/template/wall-e/chat/conversation-frame.js +630 -0
- package/template/wall-e/chat/provider-messages.js +125 -0
- package/template/wall-e/chat.js +1002 -233
- package/template/wall-e/coding/acceptance-contract.js +170 -0
- package/template/wall-e/coding/acp-adapter.js +1 -1
- package/template/wall-e/coding/agent-catalog.js +3 -0
- package/template/wall-e/coding/artifact-store.js +93 -0
- package/template/wall-e/coding/capability-router.js +120 -0
- package/template/wall-e/coding/coding-run-controller.js +423 -0
- package/template/wall-e/coding/compaction-service.js +157 -12
- package/template/wall-e/coding/frontend-verification.js +258 -0
- package/template/wall-e/coding/lifecycle-hooks.js +75 -0
- package/template/wall-e/coding/local-preview-contract.js +157 -0
- package/template/wall-e/coding/permission-service.js +57 -13
- package/template/wall-e/coding/prompt-bundle.js +19 -1
- package/template/wall-e/coding/prompt-section-registry.js +227 -0
- package/template/wall-e/coding/provider-compat.js +15 -0
- package/template/wall-e/coding/runtime-events.js +224 -0
- package/template/wall-e/coding/runtime-mode.js +3 -0
- package/template/wall-e/coding/side-git-snapshot.js +160 -4
- package/template/wall-e/coding/snapshot-service.js +143 -1
- package/template/wall-e/coding/stream-processor.js +388 -34
- package/template/wall-e/coding/task-tool.js +141 -4
- package/template/wall-e/coding/tool-execution-controller.js +365 -0
- package/template/wall-e/coding/tool-registry.js +43 -5
- package/template/wall-e/coding/user-hooks.js +217 -0
- package/template/wall-e/coding-orchestrator.js +1330 -221
- package/template/wall-e/coding-prompts.js +20 -4
- package/template/wall-e/context/context-builder.js +15 -2
- package/template/wall-e/decision/confidence.js +1 -1
- package/template/wall-e/docs/coding-acceptance-contract.md +41 -0
- package/template/wall-e/docs/external-action-controller.md +26 -6
- package/template/wall-e/docs/telemetry-lifecycle.md +8 -2
- package/template/wall-e/embeddings.js +591 -53
- package/template/wall-e/external-action-controller.js +12 -0
- package/template/wall-e/http/auth.js +1 -0
- package/template/wall-e/http/chat-api.js +46 -11
- package/template/wall-e/http/model-admin.js +836 -34
- package/template/wall-e/lib/boot-profile.js +88 -0
- package/template/wall-e/lib/event-loop-monitor.js +93 -0
- package/template/wall-e/lib/service-health.js +194 -0
- package/template/wall-e/llm/anthropic.js +130 -5
- package/template/wall-e/llm/client.js +266 -63
- package/template/wall-e/llm/default-fallback.js +382 -0
- package/template/wall-e/llm/health.js +19 -0
- package/template/wall-e/llm/message-guard.js +78 -0
- package/template/wall-e/llm/model-catalog.js +252 -1
- package/template/wall-e/llm/openai.js +26 -4
- package/template/wall-e/llm/portkey-sync.js +654 -0
- package/template/wall-e/llm/provider-error.js +30 -2
- package/template/wall-e/llm/registry.js +5 -1
- package/template/wall-e/llm/request-compat.js +67 -0
- package/template/wall-e/loops/backfill.js +79 -23
- package/template/wall-e/loops/brain-optimize.js +67 -0
- package/template/wall-e/loops/ingest.js +25 -10
- package/template/wall-e/loops/question-digest.js +160 -0
- package/template/wall-e/loops/reflect.js +6 -4
- package/template/wall-e/loops/think.js +39 -12
- package/template/wall-e/mcp-server.js +318 -36
- package/template/wall-e/memory/ctm-context-client.js +52 -14
- package/template/wall-e/memory/ctm-operational-context.js +237 -0
- package/template/wall-e/memory/ctm-prompt-executions-client.js +128 -0
- package/template/wall-e/memory/ctm-session-context.js +111 -63
- package/template/wall-e/prompts/coding/deepseek.txt +3 -0
- package/template/wall-e/prompts/coding/gemini.txt +6 -0
- package/template/wall-e/prompts/coding/gpt.txt +6 -0
- package/template/wall-e/prompts/coding/local.txt +7 -0
- package/template/wall-e/runtime/decision-hooks.js +115 -0
- package/template/wall-e/runtime/devbox-gateway.js +82 -8
- package/template/wall-e/runtime/prompt-manifest.js +86 -0
- package/template/wall-e/runtime/tool-executor.js +269 -0
- package/template/wall-e/runtime/tool-result-envelope.js +138 -0
- package/template/wall-e/runtime/transcript-projection.js +60 -0
- package/template/wall-e/runtime/walle-runtime.js +224 -0
- package/template/wall-e/scripts/db-optimize/migrate.js +162 -0
- package/template/wall-e/scripts/db-optimize/recall-eval.js +117 -0
- package/template/wall-e/server.js +15 -0
- package/template/wall-e/session-files.js +9 -0
- package/template/wall-e/skills/_bundled/google-calendar/run.js +1 -1
- package/template/wall-e/skills/_bundled/gws-workspace/run.js +1 -1
- package/template/wall-e/skills/_bundled/slack-mentions/run.js +76 -6
- package/template/wall-e/skills/claude-code-reader.js +7 -3
- package/template/wall-e/skills/script-skill-runner.js +10 -0
- package/template/wall-e/skills/skill-planner.js +38 -0
- package/template/wall-e/tools/builtin-middleware.js +19 -9
- package/template/wall-e/tools/local-tools.js +1428 -16
- package/template/wall-e/tools/permission-checker.js +73 -5
- package/template/wall-e/tools/question-manager.js +117 -7
- package/template/wall-e/training/harvester.js +12 -28
- package/template/wall-e/training/replay.js +25 -80
- package/template/website/index.html +10 -10
- package/template/wall-e/eval/ab-test.js +0 -203
- package/template/wall-e/eval/agent-runner.js +0 -772
- package/template/wall-e/eval/agent-scorer.js +0 -461
- package/template/wall-e/eval/aggregator.js +0 -414
- package/template/wall-e/eval/allowed-test-commands.js +0 -34
- package/template/wall-e/eval/benchmark-generator.js +0 -113
- package/template/wall-e/eval/benchmarks/chat-eval.json +0 -1662
- package/template/wall-e/eval/benchmarks/chat.json +0 -82
- package/template/wall-e/eval/benchmarks/coding-agent-real.json +0 -1
- package/template/wall-e/eval/benchmarks/coding-agent.json +0 -1581
- package/template/wall-e/eval/benchmarks/coding.json +0 -122
- package/template/wall-e/eval/benchmarks/memory-retrieval.json +0 -234
- package/template/wall-e/eval/benchmarks/reasoning.json +0 -82
- package/template/wall-e/eval/benchmarks/swebench-lite-30.json +0 -212
- package/template/wall-e/eval/benchmarks.js +0 -669
- package/template/wall-e/eval/cc-replay.js +0 -719
- package/template/wall-e/eval/chat-eval.js +0 -525
- package/template/wall-e/eval/check-keys.js +0 -15
- package/template/wall-e/eval/check-providers.js +0 -42
- package/template/wall-e/eval/codex-cli-baseline.js +0 -669
- package/template/wall-e/eval/coding-agent-real.js +0 -570
- package/template/wall-e/eval/context-compactor.js +0 -251
- package/template/wall-e/eval/debug-agent003.js +0 -68
- package/template/wall-e/eval/diagnostics.js +0 -216
- package/template/wall-e/eval/eval-orchestrator.js +0 -642
- package/template/wall-e/eval/evaluate.js +0 -202
- package/template/wall-e/eval/evaluator.js +0 -373
- package/template/wall-e/eval/exporter.js +0 -212
- package/template/wall-e/eval/fixtures/express-basic/package.json +0 -9
- package/template/wall-e/eval/fixtures/express-basic/server.js +0 -115
- package/template/wall-e/eval/fixtures/express-basic/test.js +0 -83
- package/template/wall-e/eval/fixtures/express-buggy/package.json +0 -9
- package/template/wall-e/eval/fixtures/express-buggy/server.js +0 -113
- package/template/wall-e/eval/fixtures/express-buggy/test.js +0 -83
- package/template/wall-e/eval/fixtures/express-buggy-items/package.json +0 -9
- package/template/wall-e/eval/fixtures/express-buggy-items/server.js +0 -112
- package/template/wall-e/eval/fixtures/express-buggy-items/test.js +0 -83
- package/template/wall-e/eval/fixtures/express-buggy-search/package.json +0 -9
- package/template/wall-e/eval/fixtures/express-buggy-search/server.js +0 -121
- package/template/wall-e/eval/fixtures/express-buggy-search/test.js +0 -83
- package/template/wall-e/eval/fixtures/express-rename-data/data.js +0 -34
- package/template/wall-e/eval/fixtures/express-rename-data/package.json +0 -9
- package/template/wall-e/eval/fixtures/express-rename-data/server.js +0 -97
- package/template/wall-e/eval/fixtures/express-rename-data/test.js +0 -88
- package/template/wall-e/eval/fixtures/express-xss/package.json +0 -12
- package/template/wall-e/eval/fixtures/express-xss/server.js +0 -90
- package/template/wall-e/eval/fixtures/express-xss/test.js +0 -67
- package/template/wall-e/eval/fixtures/express-xss/views/profile.ejs +0 -9
- package/template/wall-e/eval/fixtures/fullstack-app/config/default.js +0 -9
- package/template/wall-e/eval/fixtures/fullstack-app/config/test.js +0 -13
- package/template/wall-e/eval/fixtures/fullstack-app/package.json +0 -11
- package/template/wall-e/eval/fixtures/fullstack-app/public/css/style.css +0 -137
- package/template/wall-e/eval/fixtures/fullstack-app/public/index.html +0 -46
- package/template/wall-e/eval/fixtures/fullstack-app/public/js/app.js +0 -121
- package/template/wall-e/eval/fixtures/fullstack-app/public/js/auth.js +0 -71
- package/template/wall-e/eval/fixtures/fullstack-app/public/js/items.js +0 -80
- package/template/wall-e/eval/fixtures/fullstack-app/public/js/users.js +0 -46
- package/template/wall-e/eval/fixtures/fullstack-app/public/login.html +0 -45
- package/template/wall-e/eval/fixtures/fullstack-app/public/register.html +0 -38
- package/template/wall-e/eval/fixtures/fullstack-app/scripts/migrate.js +0 -23
- package/template/wall-e/eval/fixtures/fullstack-app/scripts/seed.js +0 -46
- package/template/wall-e/eval/fixtures/fullstack-app/server/db.js +0 -99
- package/template/wall-e/eval/fixtures/fullstack-app/server/index.js +0 -94
- package/template/wall-e/eval/fixtures/fullstack-app/server/middleware/auth.js +0 -19
- package/template/wall-e/eval/fixtures/fullstack-app/server/middleware/logger.js +0 -19
- package/template/wall-e/eval/fixtures/fullstack-app/server/router.js +0 -50
- package/template/wall-e/eval/fixtures/fullstack-app/server/routes/auth.js +0 -69
- package/template/wall-e/eval/fixtures/fullstack-app/server/routes/health.js +0 -23
- package/template/wall-e/eval/fixtures/fullstack-app/server/routes/items.js +0 -88
- package/template/wall-e/eval/fixtures/fullstack-app/server/routes/users.js +0 -75
- package/template/wall-e/eval/fixtures/fullstack-app/server/test.js +0 -198
- package/template/wall-e/eval/fixtures/fullstack-app/server/utils/response.js +0 -34
- package/template/wall-e/eval/fixtures/fullstack-app/server/utils/validate.js +0 -26
- package/template/wall-e/eval/fixtures/fullstack-app/server.js +0 -8
- package/template/wall-e/eval/fixtures/fullstack-app/test.js +0 -12
- package/template/wall-e/eval/fixtures/monorepo-basic/package.json +0 -8
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/data.js +0 -58
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/middleware.js +0 -46
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/package.json +0 -8
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/routes.js +0 -64
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/server.js +0 -56
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/api/test.js +0 -116
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/commands.js +0 -61
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/index.js +0 -62
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/output.js +0 -43
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/package.json +0 -11
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/cli/test.js +0 -44
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/formatters.js +0 -43
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/index.js +0 -12
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/package.json +0 -5
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/test.js +0 -55
- package/template/wall-e/eval/fixtures/monorepo-basic/packages/shared/validators.js +0 -29
- package/template/wall-e/eval/fixtures/monorepo-basic/test.js +0 -46
- package/template/wall-e/eval/fixtures/node-cli/index.js +0 -78
- package/template/wall-e/eval/fixtures/node-cli/package.json +0 -10
- package/template/wall-e/eval/fixtures/node-cli/test.js +0 -57
- package/template/wall-e/eval/fixtures/node-typed/package.json +0 -8
- package/template/wall-e/eval/fixtures/node-typed/src/handlers.js +0 -31
- package/template/wall-e/eval/fixtures/node-typed/src/utils.js +0 -33
- package/template/wall-e/eval/fixtures/node-typed/test.js +0 -36
- package/template/wall-e/eval/fixtures/python-flask/app.py +0 -14
- package/template/wall-e/eval/fixtures/python-flask/requirements.txt +0 -2
- package/template/wall-e/eval/fixtures/python-flask/test_app.py +0 -25
- package/template/wall-e/eval/fixtures/wall-e-subset/brain.js +0 -105
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/aggregator.js +0 -101
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks/chat.json +0 -20
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks/coding.json +0 -32
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/benchmarks.js +0 -64
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/package.json +0 -6
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/server.js +0 -31
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/test.js +0 -18
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/fixtures/simple-project/utils.js +0 -34
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/runner.js +0 -104
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/scorer.js +0 -73
- package/template/wall-e/eval/fixtures/wall-e-subset/eval/test.js +0 -134
- package/template/wall-e/eval/fixtures/wall-e-subset/llm/client.js +0 -99
- package/template/wall-e/eval/fixtures/wall-e-subset/llm/providers.js +0 -63
- package/template/wall-e/eval/fixtures/wall-e-subset/llm/test.js +0 -70
- package/template/wall-e/eval/fixtures/wall-e-subset/package.json +0 -10
- package/template/wall-e/eval/fixtures/wall-e-subset/test.js +0 -86
- package/template/wall-e/eval/harvester.js +0 -685
- package/template/wall-e/eval/head-to-head.js +0 -388
- package/template/wall-e/eval/humaneval-adapter.js +0 -321
- package/template/wall-e/eval/list-models.js +0 -31
- package/template/wall-e/eval/livecodebench-adapter.js +0 -291
- package/template/wall-e/eval/mail-integration.js +0 -443
- package/template/wall-e/eval/manifest.js +0 -186
- package/template/wall-e/eval/meta-harness/adapters/coding-agent.js +0 -57
- package/template/wall-e/eval/meta-harness/bootstrap-snapshot.js +0 -149
- package/template/wall-e/eval/meta-harness/candidate-store.js +0 -117
- package/template/wall-e/eval/meta-harness/cli.js +0 -86
- package/template/wall-e/eval/meta-harness/domain-spec.js +0 -154
- package/template/wall-e/eval/meta-harness/domains/coding-agent.domain.json +0 -84
- package/template/wall-e/eval/meta-harness/examples/env-bootstrap-candidate.js +0 -29
- package/template/wall-e/eval/meta-harness/experience-store.js +0 -174
- package/template/wall-e/eval/meta-harness/frontier.js +0 -96
- package/template/wall-e/eval/meta-harness/harness-interface.js +0 -90
- package/template/wall-e/eval/meta-harness/leakage-guard.js +0 -80
- package/template/wall-e/eval/meta-harness/optimizer.js +0 -207
- package/template/wall-e/eval/meta-harness/proposer-runner.js +0 -110
- package/template/wall-e/eval/meta-harness/reporting.js +0 -58
- package/template/wall-e/eval/meta-harness/telemetry.js +0 -27
- package/template/wall-e/eval/meta-harness/validation.js +0 -81
- package/template/wall-e/eval/promoter.js +0 -228
- package/template/wall-e/eval/provider-normalizer.js +0 -33
- package/template/wall-e/eval/replay.js +0 -395
- package/template/wall-e/eval/run-agent-benchmarks.js +0 -386
- package/template/wall-e/eval/run-codex-cli-baseline.js +0 -177
- package/template/wall-e/eval/run-coding-agent-real.js +0 -187
- package/template/wall-e/eval/run-eval.js +0 -435
- package/template/wall-e/eval/run-model-comparison.js +0 -142
- package/template/wall-e/eval/session-evaluator.js +0 -187
- package/template/wall-e/eval/session-miner.js +0 -207
- package/template/wall-e/eval/session-retrieval-benchmark.js +0 -150
- package/template/wall-e/eval/session-transcripts.js +0 -509
- package/template/wall-e/eval/shadow.js +0 -161
- package/template/wall-e/eval/swebench-adapter.js +0 -345
- package/template/wall-e/eval/swebench-docker.js +0 -192
- package/template/wall-e/eval/train.py +0 -320
- package/template/wall-e/eval/trainer.js +0 -232
- package/template/wall-e/eval/weekly-eval-loop.js +0 -241
|
@@ -146,6 +146,14 @@ function loadSkill(skillDir, source) {
|
|
|
146
146
|
execution: parsed.meta.execution || '',
|
|
147
147
|
source,
|
|
148
148
|
agents: declaredAgents.length ? declaredAgents : skillCompatibleAgentsForSource(source),
|
|
149
|
+
capabilities: normalizeSkillCapabilities(
|
|
150
|
+
parsed.meta.capabilities ||
|
|
151
|
+
parsed.meta.capability ||
|
|
152
|
+
parsed.meta.skills_capabilities ||
|
|
153
|
+
parsed.meta.skill_capabilities
|
|
154
|
+
),
|
|
155
|
+
intents: normalizeSkillCapabilities(parsed.meta.intents || parsed.meta.intent),
|
|
156
|
+
invocation: normalizeSkillInvocation(parsed.meta.invocation || parsed.meta.command_prefix || parsed.meta.prefix),
|
|
149
157
|
filePath: skillMdPath,
|
|
150
158
|
path: skillMdPath,
|
|
151
159
|
};
|
|
@@ -170,7 +178,24 @@ function parseFrontmatter(text) {
|
|
|
170
178
|
if (!line || line.startsWith('#')) continue;
|
|
171
179
|
const match = line.match(/^([A-Za-z0-9_.-]+):\s*(.*)$/);
|
|
172
180
|
if (!match) continue;
|
|
173
|
-
const
|
|
181
|
+
const valueText = String(match[2] || '').trim();
|
|
182
|
+
if (!valueText) {
|
|
183
|
+
const list = [];
|
|
184
|
+
let j = i + 1;
|
|
185
|
+
for (; j < lines.length; j += 1) {
|
|
186
|
+
const next = lines[j];
|
|
187
|
+
if (!next.trim()) continue;
|
|
188
|
+
const itemMatch = next.match(/^\s*-\s*(.+)$/);
|
|
189
|
+
if (!itemMatch) break;
|
|
190
|
+
list.push(parseFrontmatterValue(itemMatch[1]));
|
|
191
|
+
}
|
|
192
|
+
if (list.length) {
|
|
193
|
+
meta[match[1]] = list.flat ? list.flat(Infinity) : list;
|
|
194
|
+
i = j - 1;
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
const blockStyle = valueText.match(/^([>|])[-+]?$/);
|
|
174
199
|
if (blockStyle) {
|
|
175
200
|
const block = [];
|
|
176
201
|
let j = i + 1;
|
|
@@ -219,6 +244,38 @@ function normalizeSkillAgents(value) {
|
|
|
219
244
|
return out;
|
|
220
245
|
}
|
|
221
246
|
|
|
247
|
+
function normalizeSkillCapabilities(value) {
|
|
248
|
+
if (!value) return [];
|
|
249
|
+
const raw = Array.isArray(value)
|
|
250
|
+
? value
|
|
251
|
+
: typeof value === 'string'
|
|
252
|
+
? value.split(/[,\s]+/)
|
|
253
|
+
: [value];
|
|
254
|
+
const out = [];
|
|
255
|
+
const seen = new Set();
|
|
256
|
+
for (const item of raw.flat ? raw.flat(Infinity) : raw) {
|
|
257
|
+
const normalized = String(item || '')
|
|
258
|
+
.trim()
|
|
259
|
+
.toLowerCase()
|
|
260
|
+
.replace(/_/g, '.')
|
|
261
|
+
.replace(/:+/g, '.')
|
|
262
|
+
.replace(/[^a-z0-9.-]+/g, '.')
|
|
263
|
+
.replace(/^\.+|\.+$/g, '');
|
|
264
|
+
if (!normalized || seen.has(normalized)) continue;
|
|
265
|
+
seen.add(normalized);
|
|
266
|
+
out.push(normalized);
|
|
267
|
+
}
|
|
268
|
+
return out;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function normalizeSkillInvocation(value) {
|
|
272
|
+
const text = String(value || '').trim();
|
|
273
|
+
if (text === '$' || text === '/') return text;
|
|
274
|
+
if (/^dollar$/i.test(text)) return '$';
|
|
275
|
+
if (/^slash$/i.test(text)) return '/';
|
|
276
|
+
return '';
|
|
277
|
+
}
|
|
278
|
+
|
|
222
279
|
function skillCompatibleAgentsForSource(source) {
|
|
223
280
|
const s = String(source || '').toLowerCase();
|
|
224
281
|
if (s.startsWith('agents-')) return ['claude', 'codex', 'gemini', 'opencode', 'walle'];
|
|
@@ -260,6 +317,123 @@ function skillSourcePriorityForAgent(source, agentType) {
|
|
|
260
317
|
return 20;
|
|
261
318
|
}
|
|
262
319
|
|
|
320
|
+
function normalizeSkillAutocompleteQuery(value) {
|
|
321
|
+
const text = String(value || '').trim().replace(/^[$/]+/, '').toLowerCase();
|
|
322
|
+
return text.replace(/[^a-z0-9_.:-]/g, '');
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function skillAutocompleteMatch(name, query) {
|
|
326
|
+
const q = normalizeSkillAutocompleteQuery(query);
|
|
327
|
+
const n = normalizeSkillAutocompleteQuery(name);
|
|
328
|
+
if (!n) return null;
|
|
329
|
+
if (!q) return {
|
|
330
|
+
tier: 100,
|
|
331
|
+
index: 0,
|
|
332
|
+
gap: 0,
|
|
333
|
+
lengthDelta: n.length,
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
const qCompact = q.replace(/[_.:-]+/g, '');
|
|
337
|
+
const nCompact = n.replace(/[_.:-]+/g, '');
|
|
338
|
+
|
|
339
|
+
if (n === q) return { tier: 0, index: 0, gap: 0, lengthDelta: 0 };
|
|
340
|
+
if (n.startsWith(q)) return { tier: 1, index: 0, gap: 0, lengthDelta: n.length - q.length };
|
|
341
|
+
|
|
342
|
+
const segments = n.split(/[_.:-]+/).filter(Boolean);
|
|
343
|
+
let bestSegmentDelta = Infinity;
|
|
344
|
+
for (const segment of segments) {
|
|
345
|
+
if (segment.startsWith(q)) bestSegmentDelta = Math.min(bestSegmentDelta, segment.length - q.length);
|
|
346
|
+
}
|
|
347
|
+
if (Number.isFinite(bestSegmentDelta)) {
|
|
348
|
+
return { tier: 2, index: 0, gap: 0, lengthDelta: bestSegmentDelta };
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
if (qCompact && nCompact === qCompact) return { tier: 3, index: 0, gap: 0, lengthDelta: 0 };
|
|
352
|
+
if (qCompact && nCompact.startsWith(qCompact)) {
|
|
353
|
+
return { tier: 4, index: 0, gap: 0, lengthDelta: nCompact.length - qCompact.length };
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const index = n.indexOf(q);
|
|
357
|
+
if (index >= 0) {
|
|
358
|
+
return { tier: 5, index, gap: 0, lengthDelta: n.length - q.length };
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
const fuzzy = fuzzySubsequenceMatch(n, q);
|
|
362
|
+
if (fuzzy) {
|
|
363
|
+
return {
|
|
364
|
+
tier: 8,
|
|
365
|
+
index: fuzzy.firstIndex,
|
|
366
|
+
gap: fuzzy.gap,
|
|
367
|
+
lengthDelta: n.length - q.length,
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
return null;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
function fuzzySubsequenceMatch(name, query) {
|
|
375
|
+
if (!query) return { firstIndex: 0, gap: 0 };
|
|
376
|
+
let qi = 0;
|
|
377
|
+
let firstIndex = -1;
|
|
378
|
+
let previousIndex = -1;
|
|
379
|
+
let gap = 0;
|
|
380
|
+
for (let i = 0; i < name.length && qi < query.length; i += 1) {
|
|
381
|
+
if (name[i] !== query[qi]) continue;
|
|
382
|
+
if (firstIndex < 0) firstIndex = i;
|
|
383
|
+
if (previousIndex >= 0) gap += i - previousIndex - 1;
|
|
384
|
+
previousIndex = i;
|
|
385
|
+
qi += 1;
|
|
386
|
+
}
|
|
387
|
+
return qi === query.length ? { firstIndex: Math.max(0, firstIndex), gap } : null;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function filterAndSortSkillAutocompleteItems(items, query, agentType) {
|
|
391
|
+
const q = normalizeSkillAutocompleteQuery(query);
|
|
392
|
+
const agent = normalizeSkillAgentType(agentType);
|
|
393
|
+
const matches = [];
|
|
394
|
+
for (const item of safeArray(items)) {
|
|
395
|
+
const match = skillAutocompleteMatch(item?.name, q);
|
|
396
|
+
if (!match) continue;
|
|
397
|
+
matches.push({ item, match });
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
matches.sort((a, b) => compareSkillAutocompleteMatches(a, b, q, agent));
|
|
401
|
+
return matches.map((entry) => entry.item);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
function compareSkillAutocompleteMatches(a, b, query, agentType) {
|
|
405
|
+
const aMatch = a?.match || {};
|
|
406
|
+
const bMatch = b?.match || {};
|
|
407
|
+
if (query) {
|
|
408
|
+
if (aMatch.tier !== bMatch.tier) return aMatch.tier - bMatch.tier;
|
|
409
|
+
if (aMatch.index !== bMatch.index) return aMatch.index - bMatch.index;
|
|
410
|
+
if (aMatch.gap !== bMatch.gap) return aMatch.gap - bMatch.gap;
|
|
411
|
+
if (aMatch.lengthDelta !== bMatch.lengthDelta) return aMatch.lengthDelta - bMatch.lengthDelta;
|
|
412
|
+
const nameLengthDelta = normalizeSkillAutocompleteQuery(a?.item?.name).length -
|
|
413
|
+
normalizeSkillAutocompleteQuery(b?.item?.name).length;
|
|
414
|
+
if (nameLengthDelta) return nameLengthDelta;
|
|
415
|
+
} else {
|
|
416
|
+
const aFreq = Number(a?.item?.frequency || 0);
|
|
417
|
+
const bFreq = Number(b?.item?.frequency || 0);
|
|
418
|
+
if (bFreq !== aFreq) return bFreq - aFreq;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
const sourceDelta = skillSourcePriorityForAgent(a?.item?.source, agentType) -
|
|
422
|
+
skillSourcePriorityForAgent(b?.item?.source, agentType);
|
|
423
|
+
if (sourceDelta) return sourceDelta;
|
|
424
|
+
|
|
425
|
+
if (query) {
|
|
426
|
+
const aFreq = Number(a?.item?.frequency || 0);
|
|
427
|
+
const bFreq = Number(b?.item?.frequency || 0);
|
|
428
|
+
if (bFreq !== aFreq) return bFreq - aFreq;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
return String(a?.item?.name || '').localeCompare(String(b?.item?.name || ''), undefined, {
|
|
432
|
+
numeric: true,
|
|
433
|
+
sensitivity: 'base',
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
|
|
263
437
|
function normalizeSkillName(value) {
|
|
264
438
|
const name = String(value || '').trim().replace(/^@skill\//, '').replace(/\s+/g, '-');
|
|
265
439
|
return /^[A-Za-z0-9_.:-]{1,80}$/.test(name) ? name : '';
|
|
@@ -290,9 +464,14 @@ function reloadSkills() {
|
|
|
290
464
|
}
|
|
291
465
|
|
|
292
466
|
module.exports = {
|
|
467
|
+
filterAndSortSkillAutocompleteItems,
|
|
293
468
|
filterSkillsForAgent,
|
|
469
|
+
isSkillCompatibleWithAgent,
|
|
294
470
|
loadAllSkillEntries,
|
|
295
471
|
normalizeSkillAgentType,
|
|
472
|
+
normalizeSkillAutocompleteQuery,
|
|
473
|
+
normalizeSkillCapabilities,
|
|
296
474
|
reloadSkills,
|
|
475
|
+
skillAutocompleteMatch,
|
|
297
476
|
skillSourcePriorityForAgent,
|
|
298
477
|
};
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const skillAutocomplete = require('./skill-autocomplete');
|
|
5
|
+
|
|
6
|
+
const SUPPORTED_INTENTS = Object.freeze({
|
|
7
|
+
finish_and_merge: true,
|
|
8
|
+
commit_main: true,
|
|
9
|
+
create_pr: true,
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const MESSAGE_ONLY_REASON = 'message_only';
|
|
13
|
+
let intentCache = new Map();
|
|
14
|
+
|
|
15
|
+
function normalizeIntent(value) {
|
|
16
|
+
const text = String(value || '').trim().toLowerCase().replace(/[-\s]+/g, '_');
|
|
17
|
+
if (text === 'finish' || text === 'finish_merge' || text === 'merge_main') return 'finish_and_merge';
|
|
18
|
+
if (text === 'commit' || text === 'commit_local' || text === 'main_commit') return 'commit_main';
|
|
19
|
+
if (text === 'pr' || text === 'pull_request' || text === 'create_pull_request') return 'create_pr';
|
|
20
|
+
return SUPPORTED_INTENTS[text] ? text : '';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function resolveSkillIntent(options = {}) {
|
|
24
|
+
const intent = normalizeIntent(options.intent);
|
|
25
|
+
if (!intent) {
|
|
26
|
+
return {
|
|
27
|
+
ok: false,
|
|
28
|
+
error: 'unsupported_intent',
|
|
29
|
+
intent: String(options.intent || ''),
|
|
30
|
+
skill: null,
|
|
31
|
+
candidates: [],
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const agent = skillAutocomplete.normalizeSkillAgentType(options.agent) || 'all';
|
|
36
|
+
const cwd = normalizeCwd(options.cwd);
|
|
37
|
+
const cacheKey = `${cwd}\0${agent}\0${intent}`;
|
|
38
|
+
const cached = intentCache.get(cacheKey);
|
|
39
|
+
if (cached) return cloneResult({ ...cached, cached: true });
|
|
40
|
+
|
|
41
|
+
const raw = skillAutocomplete.loadAllSkillEntries(cwd || undefined);
|
|
42
|
+
const compatible = raw
|
|
43
|
+
.filter((skill) => agent === 'all' || skillAutocomplete.isSkillCompatibleWithAgent(skill, agent))
|
|
44
|
+
.sort((a, b) => {
|
|
45
|
+
const sourceDelta = skillAutocomplete.skillSourcePriorityForAgent(a.source, agent) -
|
|
46
|
+
skillAutocomplete.skillSourcePriorityForAgent(b.source, agent);
|
|
47
|
+
if (sourceDelta) return sourceDelta;
|
|
48
|
+
return String(a.name || '').localeCompare(String(b.name || ''), undefined, {
|
|
49
|
+
numeric: true,
|
|
50
|
+
sensitivity: 'base',
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const result = resolveSkillIntentFromSkills(compatible, { intent, agent, cwd });
|
|
55
|
+
intentCache.set(cacheKey, cloneResult({ ...result, cached: false }));
|
|
56
|
+
return cloneResult(result);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function resolveSkillIntentFromSkills(skills, options = {}) {
|
|
60
|
+
const intent = normalizeIntent(options.intent);
|
|
61
|
+
const agent = skillAutocomplete.normalizeSkillAgentType(options.agent) || 'all';
|
|
62
|
+
const assessed = safeArray(skills)
|
|
63
|
+
.map((skill, index) => assessSkillForIntent(skill, { intent, agent, index }))
|
|
64
|
+
.sort(compareIntentCandidates);
|
|
65
|
+
const candidates = assessed.filter((candidate) => candidate.score > 0 || candidate.eligible || candidate.negative.length > 0).slice(0, 12);
|
|
66
|
+
const selected = assessed.find((candidate) => candidate.eligible) || null;
|
|
67
|
+
return {
|
|
68
|
+
ok: true,
|
|
69
|
+
intent,
|
|
70
|
+
agent,
|
|
71
|
+
cwd: options.cwd || '',
|
|
72
|
+
cached: false,
|
|
73
|
+
generatedAt: new Date().toISOString(),
|
|
74
|
+
skill: selected ? publicCandidate(selected) : null,
|
|
75
|
+
candidates: candidates.map(publicCandidate),
|
|
76
|
+
totalSkills: safeArray(skills).length,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function assessSkillForIntent(skill, options = {}) {
|
|
81
|
+
const intent = normalizeIntent(options.intent);
|
|
82
|
+
const agent = skillAutocomplete.normalizeSkillAgentType(options.agent) || 'all';
|
|
83
|
+
const name = String(skill?.name || '').trim();
|
|
84
|
+
const source = String(skill?.source || '');
|
|
85
|
+
const description = String(skill?.description || '');
|
|
86
|
+
const text = searchableSkillText(skill);
|
|
87
|
+
const explicit = explicitCapabilities(skill);
|
|
88
|
+
const inferred = inferCapabilities(skill, explicit);
|
|
89
|
+
const caps = new Set([...explicit, ...inferred]);
|
|
90
|
+
const reasons = [];
|
|
91
|
+
const negative = [];
|
|
92
|
+
const messageOnly = isMessageOnlySkill(skill, text);
|
|
93
|
+
if (messageOnly) negative.push(MESSAGE_ONLY_REASON);
|
|
94
|
+
|
|
95
|
+
let eligible = false;
|
|
96
|
+
let score = 0;
|
|
97
|
+
|
|
98
|
+
if (intent === 'create_pr') {
|
|
99
|
+
eligible = !messageOnly && hasAny(caps, ['github.pr.create', 'git.pr.create', 'pr.create']);
|
|
100
|
+
score += add(capScore(caps, explicit, 'github.pr.create'), 'creates pull requests', reasons);
|
|
101
|
+
score += add(capScore(caps, explicit, 'git.review'), 'reviews changes', reasons);
|
|
102
|
+
score += add(capScore(caps, explicit, 'git.commit'), 'can commit before PR', reasons);
|
|
103
|
+
score += textBonus(/\bgithub\b|\bpull[- ]?request\b|\bcreate[- ]?pr\b|\bpr\b/, text, 8, 'PR language', reasons);
|
|
104
|
+
} else if (intent === 'commit_main') {
|
|
105
|
+
eligible = !messageOnly && hasAny(caps, ['git.commit']);
|
|
106
|
+
score += add(capScore(caps, explicit, 'git.commit'), 'commits local changes', reasons);
|
|
107
|
+
score += add(capScore(caps, explicit, 'git.review'), 'reviews before commit', reasons);
|
|
108
|
+
score += add(capScore(caps, explicit, 'git.quality'), 'quality gate', reasons);
|
|
109
|
+
score += textBonus(/\bsafe[- ]?commit\b|\breview[- ]?and[- ]?commit\b|\bpre[- ]?commit\b|\btl[- ]?commit\b/, text, 10, 'safe commit language', reasons);
|
|
110
|
+
} else if (intent === 'finish_and_merge') {
|
|
111
|
+
const canCommitOrFinish = hasAny(caps, ['git.commit', 'git.branch.finish']);
|
|
112
|
+
const canMerge = hasAny(caps, ['git.merge.main', 'git.branch.finish']);
|
|
113
|
+
eligible = !messageOnly && canCommitOrFinish && canMerge;
|
|
114
|
+
score += add(capScore(caps, explicit, 'git.commit'), 'commits local changes', reasons);
|
|
115
|
+
score += add(capScore(caps, explicit, 'git.merge.main'), 'merges to main', reasons);
|
|
116
|
+
score += add(capScore(caps, explicit, 'git.branch.finish'), 'finishes development branches', reasons);
|
|
117
|
+
score += add(capScore(caps, explicit, 'git.review'), 'reviews before integration', reasons);
|
|
118
|
+
score += add(capScore(caps, explicit, 'git.quality'), 'quality gate', reasons);
|
|
119
|
+
score += textBonus(/\bto main\b|\bmerge\b.*\bmain\b|\bintegrat\w*\b.*\bmain\b|\bfinish(?:ing)?[- ]a[- ]development[- ]branch\b/, text, 12, 'main integration language', reasons);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
score += sourceBonus(source, agent);
|
|
123
|
+
const frequency = Number(skill?.frequency || 0);
|
|
124
|
+
if (Number.isFinite(frequency) && frequency > 0) score += Math.min(frequency, 20) / 20;
|
|
125
|
+
if (messageOnly) score -= 100;
|
|
126
|
+
if (!eligible) score = Math.max(0, score);
|
|
127
|
+
|
|
128
|
+
const prefix = invocationPrefixForSkill(skill, agent);
|
|
129
|
+
return {
|
|
130
|
+
skill,
|
|
131
|
+
name,
|
|
132
|
+
description,
|
|
133
|
+
source,
|
|
134
|
+
agents: Array.isArray(skill?.agents) ? skill.agents : [],
|
|
135
|
+
prefix,
|
|
136
|
+
intent,
|
|
137
|
+
agent,
|
|
138
|
+
score,
|
|
139
|
+
eligible,
|
|
140
|
+
capabilities: [...caps].sort(),
|
|
141
|
+
explicitCapabilities: [...explicit].sort(),
|
|
142
|
+
reasons,
|
|
143
|
+
negative,
|
|
144
|
+
originalIndex: Number.isFinite(options.index) ? options.index : 0,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function inferCapabilities(skill, explicit) {
|
|
149
|
+
const text = searchableSkillText(skill);
|
|
150
|
+
const caps = new Set();
|
|
151
|
+
const messageOnly = isMessageOnlySkill(skill, text);
|
|
152
|
+
if (!messageOnly && /\bcommit\b|\bstaged changes\b|\blocal changes\b/.test(text)) caps.add('git.commit');
|
|
153
|
+
if (/\breview\b|\baudit\b|\bverify\b|\bquality\b|\bpre[- ]?commit\b|\bsafe[- ]?commit\b|\btl[- ]?commit\b/.test(text)) caps.add('git.review');
|
|
154
|
+
if (/\bquality\b|\bsafe\b|\bsecurity\b|\bpii\b|\bsecret\b|\bpre[- ]?commit\b|\btl[- ]?commit\b/.test(text)) caps.add('git.quality');
|
|
155
|
+
if (/\bmerge\b.*\bmain\b|\bmain\b.*\bmerge\b|\bintegrat\w*\b.*\bmain\b|\bto main\b/.test(text)) caps.add('git.merge.main');
|
|
156
|
+
if (/\bfinish(?:ing)?[- ]a[- ]development[- ]branch\b|\bcomplete\b.*\bdevelopment work\b|\bguide\w*\b.*\bmerge\b.*\bpr\b.*\bcleanup\b/.test(text)) {
|
|
157
|
+
caps.add('git.branch.finish');
|
|
158
|
+
caps.add('git.merge.main');
|
|
159
|
+
}
|
|
160
|
+
if (/\bcreate\b.*\b(?:pr|pull[- ]?request)\b|\b(?:pr|pull[- ]?request)\b.*\bcreate\b|\bgithub\b.*\b(?:pr|pull[- ]?request)\b/.test(text)) {
|
|
161
|
+
caps.add('github.pr.create');
|
|
162
|
+
}
|
|
163
|
+
for (const cap of explicit) caps.add(cap);
|
|
164
|
+
return caps;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function explicitCapabilities(skill) {
|
|
168
|
+
const raw = [
|
|
169
|
+
...safeArray(skill?.capabilities),
|
|
170
|
+
...safeArray(skill?.intents),
|
|
171
|
+
];
|
|
172
|
+
return new Set(skillAutocomplete.normalizeSkillCapabilities(raw).flatMap(expandCapabilityAlias));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function expandCapabilityAlias(value) {
|
|
176
|
+
const cap = String(value || '').toLowerCase();
|
|
177
|
+
const out = [cap];
|
|
178
|
+
if (cap === 'commit' || cap === 'git.commit.local') out.push('git.commit');
|
|
179
|
+
if (cap === 'review' || cap === 'code.review') out.push('git.review');
|
|
180
|
+
if (cap === 'quality' || cap === 'safety') out.push('git.quality');
|
|
181
|
+
if (cap === 'merge' || cap === 'merge.main' || cap === 'git.merge') out.push('git.merge.main');
|
|
182
|
+
if (cap === 'finish' || cap === 'finish.branch' || cap === 'branch.finish') out.push('git.branch.finish');
|
|
183
|
+
if (cap === 'pr' || cap === 'pull.request' || cap === 'github.pr') out.push('github.pr.create');
|
|
184
|
+
return out;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function isMessageOnlySkill(skill, text = searchableSkillText(skill)) {
|
|
188
|
+
const name = String(skill?.name || '').toLowerCase();
|
|
189
|
+
return /(?:^|[-_.:])commit[-_.:]?messages?(?:$|[-_.:])/.test(name) ||
|
|
190
|
+
/\bwriting[- ]commit[- ]messages?\b/.test(text) ||
|
|
191
|
+
/\bwrite\w*\b.*\bcommit messages?\b/.test(text) ||
|
|
192
|
+
/\bcommit message quality\b/.test(text) ||
|
|
193
|
+
/\bcommit message help\b/.test(text);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function invocationPrefixForSkill(skill, agentType) {
|
|
197
|
+
if (skill?.invocation === '$' || skill?.invocation === '/') return skill.invocation;
|
|
198
|
+
const agent = skillAutocomplete.normalizeSkillAgentType(agentType);
|
|
199
|
+
const source = String(skill?.source || '').toLowerCase();
|
|
200
|
+
if (agent === 'claude') return '/';
|
|
201
|
+
if (agent === 'codex' || agent === 'opencode' || agent === 'gemini') return '$';
|
|
202
|
+
if (source.startsWith('claude-')) return '/';
|
|
203
|
+
return '$';
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function capScore(caps, explicit, cap) {
|
|
207
|
+
if (explicit.has(cap)) return 34;
|
|
208
|
+
if (caps.has(cap)) return 18;
|
|
209
|
+
return 0;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function add(value, reason, reasons) {
|
|
213
|
+
if (value > 0 && reason) reasons.push(reason);
|
|
214
|
+
return value;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function textBonus(pattern, text, score, reason, reasons) {
|
|
218
|
+
if (!pattern.test(text)) return 0;
|
|
219
|
+
if (reason) reasons.push(reason);
|
|
220
|
+
return score;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
function sourceBonus(source, agent) {
|
|
224
|
+
const priority = skillAutocomplete.skillSourcePriorityForAgent(source, agent);
|
|
225
|
+
if (priority <= 1) return 3;
|
|
226
|
+
if (priority <= 3) return 2;
|
|
227
|
+
if (priority <= 5) return 1;
|
|
228
|
+
return 0;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function hasAny(caps, values) {
|
|
232
|
+
return values.some((value) => caps.has(value));
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function compareIntentCandidates(a, b) {
|
|
236
|
+
if (a.eligible !== b.eligible) return a.eligible ? -1 : 1;
|
|
237
|
+
if (b.score !== a.score) return b.score - a.score;
|
|
238
|
+
const agent = a.intent === b.intent ? (a.agent || b.agent || 'all') : 'all';
|
|
239
|
+
const sourceDelta = skillAutocomplete.skillSourcePriorityForAgent(a.source, agent) -
|
|
240
|
+
skillAutocomplete.skillSourcePriorityForAgent(b.source, agent);
|
|
241
|
+
if (sourceDelta) return sourceDelta;
|
|
242
|
+
return String(a.name || '').localeCompare(String(b.name || ''), undefined, {
|
|
243
|
+
numeric: true,
|
|
244
|
+
sensitivity: 'base',
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function publicCandidate(candidate) {
|
|
249
|
+
if (!candidate) return null;
|
|
250
|
+
return {
|
|
251
|
+
name: candidate.name,
|
|
252
|
+
description: candidate.description,
|
|
253
|
+
source: candidate.source,
|
|
254
|
+
agents: candidate.agents,
|
|
255
|
+
prefix: candidate.prefix,
|
|
256
|
+
invocation: candidate.prefix,
|
|
257
|
+
score: Math.round(candidate.score * 100) / 100,
|
|
258
|
+
eligible: !!candidate.eligible,
|
|
259
|
+
capabilities: candidate.capabilities,
|
|
260
|
+
reasons: candidate.reasons.slice(0, 5),
|
|
261
|
+
negative: candidate.negative,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function searchableSkillText(skill) {
|
|
266
|
+
return [
|
|
267
|
+
skill?.name,
|
|
268
|
+
skill?.description,
|
|
269
|
+
skill?.execution,
|
|
270
|
+
...(Array.isArray(skill?.capabilities) ? skill.capabilities : []),
|
|
271
|
+
...(Array.isArray(skill?.intents) ? skill.intents : []),
|
|
272
|
+
].join(' ').toLowerCase().replace(/[_:./]+/g, ' ');
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function normalizeCwd(value) {
|
|
276
|
+
const text = String(value || '').trim();
|
|
277
|
+
return text ? path.resolve(text) : '';
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function safeArray(value) {
|
|
281
|
+
return Array.isArray(value) ? value : [];
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function cloneResult(value) {
|
|
285
|
+
return JSON.parse(JSON.stringify(value));
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function clearSkillIntentCache() {
|
|
289
|
+
intentCache = new Map();
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function skillIntentCacheStats() {
|
|
293
|
+
return { entries: intentCache.size };
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
module.exports = {
|
|
297
|
+
assessSkillForIntent,
|
|
298
|
+
clearSkillIntentCache,
|
|
299
|
+
invocationPrefixForSkill,
|
|
300
|
+
normalizeIntent,
|
|
301
|
+
resolveSkillIntent,
|
|
302
|
+
resolveSkillIntentFromSkills,
|
|
303
|
+
skillIntentCacheStats,
|
|
304
|
+
};
|
|
@@ -124,7 +124,7 @@ function smokeTestDatabase(Database) {
|
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
function runNpm(args, label) {
|
|
127
|
+
function runNpm(args, label, extraEnv = {}) {
|
|
128
128
|
const timeout = Number(process.env.CTM_SQLITE_REPAIR_TIMEOUT_MS || DEFAULT_REPAIR_TIMEOUT_MS);
|
|
129
129
|
const started = Date.now();
|
|
130
130
|
try {
|
|
@@ -135,9 +135,16 @@ function runNpm(args, label) {
|
|
|
135
135
|
timeout: Number.isFinite(timeout) && timeout > 0 ? timeout : DEFAULT_REPAIR_TIMEOUT_MS,
|
|
136
136
|
env: {
|
|
137
137
|
...process.env,
|
|
138
|
+
// Compile/resolve under the SAME Node that's loading the driver. Without this,
|
|
139
|
+
// execFileSync('npm') resolves `npm`/`node-gyp`/`node` from the ambient PATH (often
|
|
140
|
+
// a different Node major), so even a from-source rebuild targets the WRONG ABI and
|
|
141
|
+
// the brick persists. Prepending process.execPath's dir pins the toolchain to the
|
|
142
|
+
// running Node, so the rebuilt binary matches this process. This is the ABI-ping-pong fix.
|
|
143
|
+
PATH: `${path.dirname(process.execPath)}${path.delimiter}${process.env.PATH || ''}`,
|
|
138
144
|
npm_config_audit: 'false',
|
|
139
145
|
npm_config_fund: 'false',
|
|
140
146
|
npm_config_update_notifier: 'false',
|
|
147
|
+
...extraEnv,
|
|
141
148
|
},
|
|
142
149
|
});
|
|
143
150
|
return { label, ok: true, ms: Date.now() - started, output: String(output || '').slice(-4000) };
|
|
@@ -155,9 +162,18 @@ function runNpm(args, label) {
|
|
|
155
162
|
function defaultRepairRunner(cause) {
|
|
156
163
|
const attempts = [];
|
|
157
164
|
const spec = packageSpec();
|
|
165
|
+
// FROM-SOURCE FIRST. The node-ABI ping-pong: when several processes on different Node
|
|
166
|
+
// majors (e.g. the pinned 25.x primary + a system-26 dev/agent) share one node_modules,
|
|
167
|
+
// each one's load fails the ABI smoke test and triggers repair. Plain `npm rebuild` /
|
|
168
|
+
// `npm install` resolve a PREBUILT binary (or no-op "up to date") that is compiled for
|
|
169
|
+
// SOME other Node ABI — so the smoke test still fails and the primary bricks on restart.
|
|
170
|
+
// Forcing a source compile (`npm_config_build_from_source`) produces a binary matching
|
|
171
|
+
// THIS process's Node, so every process reliably self-heals instead of bricking.
|
|
172
|
+
const fromSource = { npm_config_build_from_source: 'true' };
|
|
158
173
|
const commands = [
|
|
174
|
+
{ label: 'npm rebuild better-sqlite3 (from source)', args: ['rebuild', 'better-sqlite3', '--foreground-scripts'], env: fromSource },
|
|
159
175
|
{ label: 'npm rebuild better-sqlite3', args: ['rebuild', 'better-sqlite3'] },
|
|
160
|
-
{ label: `npm install better-sqlite3@${spec}`, args: ['install', `better-sqlite3@${spec}`, '--no-audit', '--no-fund'] },
|
|
176
|
+
{ label: `npm install better-sqlite3@${spec} (from source)`, args: ['install', `better-sqlite3@${spec}`, '--no-audit', '--no-fund'], env: fromSource },
|
|
161
177
|
];
|
|
162
178
|
if (process.env.CTM_SQLITE_ALLOW_MAJOR_UPGRADE !== '0' && spec !== 'latest') {
|
|
163
179
|
commands.push({ label: 'npm install better-sqlite3@latest', args: ['install', 'better-sqlite3@latest', '--no-audit', '--no-fund'] });
|
|
@@ -168,7 +184,7 @@ function defaultRepairRunner(cause) {
|
|
|
168
184
|
action: command.label,
|
|
169
185
|
cause: String(cause?.message || cause || '').slice(0, 1000),
|
|
170
186
|
});
|
|
171
|
-
const result = runNpm(command.args, command.label);
|
|
187
|
+
const result = runNpm(command.args, command.label, command.env || {});
|
|
172
188
|
attempts.push(result);
|
|
173
189
|
recordDriverEvent(result.ok ? 'sqlite_driver_repair_command_ok' : 'sqlite_driver_repair_command_failed', result);
|
|
174
190
|
if (!result.ok) continue;
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
const crypto = require('crypto');
|
|
4
4
|
|
|
5
5
|
const STICKY_ATTENTION_MS = 12 * 60 * 60 * 1000;
|
|
6
|
+
const HARD_FAILURE_RE = /\b(cannot proceed|blocked|blocker|stuck|permission denied|fatal|panic|segmentation fault|uncaught|unhandled exception|traceback|command failed|build failed|tests? failed|npm err!|failed to run step|exceeded max retries|max retries|something went wrong)\b/i;
|
|
7
|
+
const HARD_FAILURE_EVIDENCE_RE = /(cannot proceed|blocked|blocker|stuck|permission denied|fatal|unhandled exception|command failed|build failed|tests? failed|failed to run step|exceeded max retries|max retries|something went wrong)/i;
|
|
6
8
|
|
|
7
9
|
function compactText(value) {
|
|
8
10
|
if (!value) return '';
|
|
@@ -68,6 +70,7 @@ function attentionContextHash(text) {
|
|
|
68
70
|
function buildStandupAttentionContext({ session = {}, summary = {}, status = {} } = {}) {
|
|
69
71
|
const evidence = Array.isArray(summary.statusEvidence) ? summary.statusEvidence : [];
|
|
70
72
|
const progress = summary.progress || {};
|
|
73
|
+
const terminalAttentionText = summary.terminalAttentionText || summary.terminal_attention_text || session.terminalAttentionText || '';
|
|
71
74
|
const lines = [
|
|
72
75
|
`Title: ${compactText(session.label || summary.displayPrompt || summary.lastPrompt || session.id || '')}`,
|
|
73
76
|
`Agent: ${compactText(session.agentType || session.agent || session.type || '')}`,
|
|
@@ -77,6 +80,7 @@ function buildStandupAttentionContext({ session = {}, summary = {}, status = {}
|
|
|
77
80
|
`Summary: ${compactText(summary.summary || '')}`,
|
|
78
81
|
`Progress: ${compactText(progress)}`,
|
|
79
82
|
`Evidence: ${evidence.map(compactText).filter(Boolean).join('; ')}`,
|
|
83
|
+
`Terminal: ${compactText(terminalAttentionText)}`,
|
|
80
84
|
].filter(line => !/:\s*$/.test(line));
|
|
81
85
|
const text = truncateText(lines.join('\n'), 2500);
|
|
82
86
|
return {
|
|
@@ -87,7 +91,7 @@ function buildStandupAttentionContext({ session = {}, summary = {}, status = {}
|
|
|
87
91
|
}
|
|
88
92
|
|
|
89
93
|
function hasAttentionLanguage(text) {
|
|
90
|
-
return /\b(warn(?:ing|ed)?|caution|risk|blocked|blocker|failed|failing|failure|error|exception|permission denied|cannot proceed|stuck|needs attention)\b/i.test(String(text || ''));
|
|
94
|
+
return /\b(warn(?:ing|ed)?|caution|risk|blocked|blocker|failed|failing|failure|error|exception|permission denied|cannot proceed|stuck|needs attention|exceeded max retries|max retries|something went wrong)\b/i.test(String(text || ''));
|
|
91
95
|
}
|
|
92
96
|
|
|
93
97
|
function hasResolutionSignal(text) {
|
|
@@ -98,7 +102,7 @@ function heuristicStandupAttention(context) {
|
|
|
98
102
|
const text = String(context?.text || context || '');
|
|
99
103
|
const lower = text.toLowerCase();
|
|
100
104
|
const resolved = hasResolutionSignal(lower);
|
|
101
|
-
const hardFailure =
|
|
105
|
+
const hardFailure = HARD_FAILURE_RE.test(lower);
|
|
102
106
|
const warning = /\b(warn(?:ing|ed)?|caution|risk|heads up|possible issue|needs attention)\b/i.test(lower);
|
|
103
107
|
const weakFailure = /\b(failed|failing|failure|error|exception)\b/i.test(lower);
|
|
104
108
|
|
|
@@ -109,7 +113,7 @@ function heuristicStandupAttention(context) {
|
|
|
109
113
|
return normalizeAttention({
|
|
110
114
|
severity: 'failure',
|
|
111
115
|
recommendation: 'A current blocker or failure appears to need attention.',
|
|
112
|
-
evidence: [firstMatchingPhrase(text,
|
|
116
|
+
evidence: [firstMatchingPhrase(text, HARD_FAILURE_EVIDENCE_RE)],
|
|
113
117
|
source: 'heuristic',
|
|
114
118
|
confidence: 'medium',
|
|
115
119
|
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
// Status authority inversion.
|
|
3
|
+
//
|
|
4
|
+
// CTM derives session status from two kinds of evidence:
|
|
5
|
+
// 1. Structured signals — OTLP telemetry (codex) and provider hooks
|
|
6
|
+
// (claude/gemini), surfaced via lib/telemetry-receiver. These say
|
|
7
|
+
// exactly when a turn starts and ends.
|
|
8
|
+
// 2. PTY byte inference — provider state detectors classifying raw
|
|
9
|
+
// terminal chunks (workers/state-detectors/*).
|
|
10
|
+
//
|
|
11
|
+
// Byte inference is inherently low-precision for full-screen TUIs: an idle
|
|
12
|
+
// codex still repaints (background MCP/rate-limit fetches, focus events,
|
|
13
|
+
// animation frames), and one misclassified chunk holds the sidebar on
|
|
14
|
+
// "Running" for the provider's whole idle-debounce window. So when a
|
|
15
|
+
// structured source owns a session, generic bytes must not CREATE a running
|
|
16
|
+
// state out of idle — only the provider's own busy-status line ("Working …
|
|
17
|
+
// esc to interrupt", matched strictly) or the structured source itself may.
|
|
18
|
+
//
|
|
19
|
+
// Two deliberate escape hatches keep this safe:
|
|
20
|
+
// - No structured source (fresh install, otel/notify not configured):
|
|
21
|
+
// full byte inference remains, it is the only signal available.
|
|
22
|
+
// - Provider without a precise busy channel (no textHasCodexBusyStatus
|
|
23
|
+
// on its detector): never strand it — its hooks can lag and generic
|
|
24
|
+
// output is the only unstick signal it has.
|
|
25
|
+
|
|
26
|
+
function ptyActivityMayDriveRunning({
|
|
27
|
+
hasAuthoritativeSource = false,
|
|
28
|
+
busyEvidenceCapable = false,
|
|
29
|
+
lastBusyStatusAt = 0,
|
|
30
|
+
now = Date.now(),
|
|
31
|
+
busyHoldMs = 15000,
|
|
32
|
+
} = {}) {
|
|
33
|
+
if (!hasAuthoritativeSource) return true;
|
|
34
|
+
if (!busyEvidenceCapable) return true;
|
|
35
|
+
const busyAt = Number(lastBusyStatusAt) || 0;
|
|
36
|
+
return !!(busyAt && (now - busyAt) < busyHoldMs);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
module.exports = { ptyActivityMayDriveRunning };
|
|
@@ -60,6 +60,9 @@ function onApprovalDetected(sessionId) {
|
|
|
60
60
|
function onApprovalResolved(sessionId) {
|
|
61
61
|
bus.onApprovalResolved(sessionId);
|
|
62
62
|
}
|
|
63
|
+
function clearWaitingInput(sessionId) {
|
|
64
|
+
bus.clearWaitingInput(sessionId);
|
|
65
|
+
}
|
|
63
66
|
|
|
64
67
|
// Wire bus events → hook-executor.
|
|
65
68
|
bus.on('statechange', async (ev) => {
|
|
@@ -101,6 +104,7 @@ module.exports = {
|
|
|
101
104
|
onOutput,
|
|
102
105
|
onApprovalDetected,
|
|
103
106
|
onApprovalResolved,
|
|
107
|
+
clearWaitingInput,
|
|
104
108
|
// Introspection / tests
|
|
105
109
|
_bus: bus,
|
|
106
110
|
_sessionMeta,
|