mixdog 0.9.2 → 0.9.4
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/package.json +8 -3
- package/scripts/anthropic-maxtokens-test.mjs +119 -0
- package/scripts/bench/lead-review-tasks-r3.json +20 -0
- package/scripts/bench/lead-review-tasks.json +20 -0
- package/scripts/bench/r4-mixed-tasks.json +20 -0
- package/scripts/bench/review-tasks.json +20 -0
- package/scripts/bench/round-codex.json +114 -0
- package/scripts/bench/round-mixdog-lead-r3.json +269 -0
- package/scripts/bench/round-mixdog-lead.json +269 -0
- package/scripts/bench/round-mixdog.json +126 -0
- package/scripts/bench/round-r10-bigsample.json +679 -0
- package/scripts/bench/round-r11-codexalign.json +257 -0
- package/scripts/bench/round-r4-codex.json +114 -0
- package/scripts/bench/round-r4-mixed.json +225 -0
- package/scripts/bench/round-r5-gpt-lead.json +259 -0
- package/scripts/bench/round-r6-codex.json +114 -0
- package/scripts/bench/round-r6-solo.json +257 -0
- package/scripts/bench/round-r7-full.json +254 -0
- package/scripts/bench/round-r8-fulldefault.json +255 -0
- package/scripts/bench-run.mjs +215 -29
- package/scripts/build-tui.mjs +13 -1
- package/scripts/explore-bench.mjs +124 -0
- package/scripts/freevar-smoke.mjs +95 -0
- package/scripts/hook-bus-test.mjs +191 -0
- package/scripts/internal-comms-bench.mjs +1 -0
- package/scripts/internal-comms-smoke.mjs +10 -9
- package/scripts/mouse-probe.mjs +45 -0
- package/scripts/output-style-bench.mjs +13 -6
- package/scripts/output-style-smoke.mjs +4 -4
- package/scripts/path-suffix-test.mjs +57 -0
- package/scripts/provider-toolcall-test.mjs +7 -3
- package/scripts/recall-bench.mjs +207 -0
- package/scripts/recall-usecase-cases.json +18 -0
- package/scripts/recall-usecase-probe.json +6 -0
- package/scripts/session-bench.mjs +152 -6
- package/scripts/tool-smoke.mjs +30 -67
- package/scripts/tui-render-smoke.mjs +90 -0
- package/scripts/webhook-smoke.mjs +208 -0
- package/src/agents/debugger/AGENT.md +5 -2
- package/src/agents/heavy-worker/AGENT.md +21 -11
- package/src/agents/maintainer/AGENT.md +4 -0
- package/src/agents/reviewer/AGENT.md +3 -2
- package/src/agents/worker/AGENT.md +21 -11
- package/src/lib/rules-builder.cjs +4 -0
- package/src/mixdog-session-runtime.mjs +933 -3731
- package/src/output-styles/default.md +34 -9
- package/src/output-styles/{oneline.md → extreme-minimal.md} +5 -4
- package/src/output-styles/minimal.md +4 -1
- package/src/output-styles/simple.md +22 -7
- package/src/repl.mjs +5 -5
- package/src/rules/agent/00-common.md +2 -0
- package/src/rules/agent/30-explorer.md +8 -11
- package/src/rules/lead/lead-brief.md +12 -0
- package/src/rules/lead/lead-tool.md +2 -9
- package/src/rules/shared/01-tool.md +11 -5
- package/src/runtime/agent/orchestrator/agent-runtime/agent-loop-policy.mjs +25 -0
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +100 -23
- package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +6 -15
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +362 -0
- package/src/runtime/agent/orchestrator/agent-trace-io.mjs +410 -0
- package/src/runtime/agent/orchestrator/agent-trace.mjs +16 -735
- package/src/runtime/agent/orchestrator/config.mjs +69 -2
- package/src/runtime/agent/orchestrator/context/collect.mjs +51 -0
- package/src/runtime/agent/orchestrator/mcp/client.mjs +6 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-effort.mjs +63 -21
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +93 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-model-resolve.mjs +209 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +489 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +97 -1343
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +607 -0
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +78 -10
- package/src/runtime/agent/orchestrator/providers/api-usage.mjs +1 -13
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +81 -0
- package/src/runtime/agent/orchestrator/providers/gemini-cache.mjs +248 -0
- package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +303 -0
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +505 -0
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +44 -1014
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +18 -4
- package/src/runtime/agent/orchestrator/providers/lib/usage-primitives.mjs +32 -0
- package/src/runtime/agent/orchestrator/providers/model-catalog.mjs +86 -11
- package/src/runtime/agent/orchestrator/providers/model-list-sanitize.mjs +348 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +54 -20
- package/src/runtime/agent/orchestrator/providers/openai-codex-model.mjs +108 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +19 -12
- package/src/runtime/agent/orchestrator/providers/openai-compat-trace.mjs +58 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-wire.mjs +368 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai.mjs +760 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +41 -1142
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +732 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +193 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +303 -2119
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +140 -995
- package/src/runtime/agent/orchestrator/providers/openai-ws-delta.mjs +227 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-events.mjs +67 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +436 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +1105 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +38 -12
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +7 -8
- package/src/runtime/agent/orchestrator/session/compact/budget.mjs +288 -0
- package/src/runtime/agent/orchestrator/session/compact/constants.mjs +85 -0
- package/src/runtime/agent/orchestrator/session/compact/engine.mjs +749 -0
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +82 -0
- package/src/runtime/agent/orchestrator/session/compact/summary-schema.mjs +315 -0
- package/src/runtime/agent/orchestrator/session/compact/summary.mjs +643 -0
- package/src/runtime/agent/orchestrator/session/compact/text-utils.mjs +326 -0
- package/src/runtime/agent/orchestrator/session/compact.mjs +40 -2282
- package/src/runtime/agent/orchestrator/session/loop/compact-debug.mjs +28 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +274 -0
- package/src/runtime/agent/orchestrator/session/loop/completion-guards.mjs +61 -0
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +38 -0
- package/src/runtime/agent/orchestrator/session/loop/env.mjs +14 -0
- package/src/runtime/agent/orchestrator/session/loop/hidden-agents.mjs +21 -0
- package/src/runtime/agent/orchestrator/session/loop/pre-dispatch-deny.mjs +47 -0
- package/src/runtime/agent/orchestrator/session/loop/recall-fasttrack.mjs +182 -0
- package/src/runtime/agent/orchestrator/session/loop/steering-ladder.mjs +173 -0
- package/src/runtime/agent/orchestrator/session/loop/steering.mjs +63 -0
- package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +100 -0
- package/src/runtime/agent/orchestrator/session/loop/termination.mjs +58 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-classify.mjs +52 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +239 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +218 -0
- package/src/runtime/agent/orchestrator/session/loop/transcript-repair.mjs +101 -0
- package/src/runtime/agent/orchestrator/session/loop/usage.mjs +35 -0
- package/src/runtime/agent/orchestrator/session/loop.mjs +409 -1304
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +471 -0
- package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +230 -0
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +235 -0
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +149 -0
- package/src/runtime/agent/orchestrator/session/manager/rules-cache.mjs +155 -0
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +406 -0
- package/src/runtime/agent/orchestrator/session/manager/status-telemetry.mjs +80 -0
- package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +303 -0
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +210 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +226 -2114
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +189 -0
- package/src/runtime/agent/orchestrator/session/store.mjs +74 -179
- package/src/runtime/agent/orchestrator/stall-policy.mjs +3 -3
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +70 -20
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +22 -2
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +33 -42
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +241 -0
- package/src/runtime/agent/orchestrator/tools/builtin/fuzzy-match.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +40 -0
- package/src/runtime/agent/orchestrator/tools/builtin/path-diagnostics.mjs +42 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +11 -4
- package/src/runtime/agent/orchestrator/tools/builtin/rg-runner.mjs +29 -0
- package/src/runtime/agent/orchestrator/tools/builtin/search-builders.mjs +8 -0
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +126 -0
- package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +81 -87
- package/src/runtime/agent/orchestrator/tools/builtin/shell-job-paths.mjs +161 -0
- package/src/runtime/agent/orchestrator/tools/builtin/shell-job-process.mjs +108 -0
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +78 -304
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +11 -6
- package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +303 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/constants.mjs +43 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +382 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +551 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-binary.mjs +295 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/graph-model.mjs +158 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/keyword-match.mjs +82 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/lang-predicates.mjs +128 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/memory-cache.mjs +66 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/project-root.mjs +44 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/search.mjs +1080 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/source-access.mjs +81 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/span.mjs +19 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/symbol-index.mjs +280 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/text-columns.mjs +45 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/text-mask.mjs +347 -0
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +6 -6
- package/src/runtime/agent/orchestrator/tools/code-graph.mjs +36 -4277
- package/src/runtime/agent/orchestrator/tools/graph-binary-fetcher.mjs +6 -3
- package/src/runtime/agent/orchestrator/tools/patch/constants.mjs +9 -0
- package/src/runtime/agent/orchestrator/tools/patch/dispatch.mjs +171 -0
- package/src/runtime/agent/orchestrator/tools/patch/matcher.mjs +471 -0
- package/src/runtime/agent/orchestrator/tools/patch/native-server.mjs +436 -0
- package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +342 -0
- package/src/runtime/agent/orchestrator/tools/patch/parsing.mjs +359 -0
- package/src/runtime/agent/orchestrator/tools/patch/paths.mjs +340 -0
- package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +643 -0
- package/src/runtime/agent/orchestrator/tools/patch.mjs +36 -2959
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +1 -23
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +10 -74
- package/src/runtime/agent/orchestrator/tools/shell-powershell.mjs +77 -0
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +2 -4
- package/src/runtime/agent/orchestrator/tools/shell-state.mjs +154 -0
- package/src/runtime/channels/backends/discord-access.mjs +32 -0
- package/src/runtime/channels/backends/discord-attachments.mjs +65 -0
- package/src/runtime/channels/backends/discord-gateway.mjs +233 -0
- package/src/runtime/channels/backends/discord.mjs +12 -292
- package/src/runtime/channels/index.mjs +241 -894
- package/src/runtime/channels/lib/backend-dispatch.mjs +44 -0
- package/src/runtime/channels/lib/boot-profile.mjs +23 -0
- package/src/runtime/channels/lib/crash-log.mjs +106 -0
- package/src/runtime/channels/lib/event-pipeline.mjs +18 -1
- package/src/runtime/channels/lib/event-queue.mjs +63 -4
- package/src/runtime/channels/lib/inbound-routing.mjs +111 -0
- package/src/runtime/channels/lib/index-drop-trace.mjs +72 -0
- package/src/runtime/channels/lib/output-forwarder.mjs +9 -1
- package/src/runtime/channels/lib/owner-heartbeat.mjs +75 -0
- package/src/runtime/channels/lib/parent-bridge.mjs +88 -0
- package/src/runtime/channels/lib/runtime-paths.mjs +14 -4
- package/src/runtime/channels/lib/session-discovery.mjs +56 -4
- package/src/runtime/channels/lib/telegram-format.mjs +19 -22
- package/src/runtime/channels/lib/tool-dispatch.mjs +158 -0
- package/src/runtime/channels/lib/tool-format.mjs +1 -1
- package/src/runtime/channels/lib/transcript-discovery.mjs +4 -4
- package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +6 -3
- package/src/runtime/channels/lib/voice-transcription.mjs +179 -0
- package/src/runtime/channels/lib/webhook/deliveries.mjs +312 -0
- package/src/runtime/channels/lib/webhook/log.mjs +42 -0
- package/src/runtime/channels/lib/webhook/ngrok.mjs +181 -0
- package/src/runtime/channels/lib/webhook/signature.mjs +60 -0
- package/src/runtime/channels/lib/webhook.mjs +36 -570
- package/src/runtime/channels/lib/whisper-language.mjs +42 -0
- package/src/runtime/channels/tool-defs.mjs +11 -130
- package/src/runtime/memory/index.mjs +258 -2050
- package/src/runtime/memory/lib/core-memory-store.mjs +351 -1
- package/src/runtime/memory/lib/cycle-llm-adapters.mjs +58 -0
- package/src/runtime/memory/lib/cycle-scheduler.mjs +497 -0
- package/src/runtime/memory/lib/cycle-signatures.mjs +34 -0
- package/src/runtime/memory/lib/embedding-warmup.mjs +58 -0
- package/src/runtime/memory/lib/http-wire.mjs +57 -0
- package/src/runtime/memory/lib/memory-config-flags.mjs +91 -0
- package/src/runtime/memory/lib/memory-cycle.mjs +1 -1
- package/src/runtime/memory/lib/memory-cycle2-gate.mjs +515 -0
- package/src/runtime/memory/lib/memory-cycle2-mutations.mjs +324 -0
- package/src/runtime/memory/lib/memory-cycle2-shared.mjs +18 -0
- package/src/runtime/memory/lib/memory-cycle2.mjs +72 -837
- package/src/runtime/memory/lib/memory-embed.mjs +149 -0
- package/src/runtime/memory/lib/memory-process-lock.mjs +162 -0
- package/src/runtime/memory/lib/memory-recall-scope-filter.mjs +24 -0
- package/src/runtime/memory/lib/memory-recall-store.mjs +22 -2
- package/src/runtime/memory/lib/memory-retrievers.mjs +8 -0
- package/src/runtime/memory/lib/memory.mjs +20 -0
- package/src/runtime/memory/lib/pg/supervisor.mjs +1 -1
- package/src/runtime/memory/lib/promotion-fingerprint.mjs +50 -0
- package/src/runtime/memory/lib/query-handlers.mjs +780 -0
- package/src/runtime/memory/lib/recall-format.mjs +238 -0
- package/src/runtime/memory/lib/runtime-fetcher.mjs +8 -3
- package/src/runtime/memory/lib/transcript-ingest.mjs +425 -0
- package/src/runtime/memory/tool-defs.mjs +6 -14
- package/src/runtime/search/lib/http-fetch.mjs +274 -0
- package/src/runtime/search/lib/ssrf-guard.mjs +333 -0
- package/src/runtime/search/lib/web-tools.mjs +24 -602
- package/src/runtime/shared/abort-controller.mjs +1 -1
- package/src/runtime/shared/atomic-file.mjs +26 -1
- package/src/runtime/shared/background-tasks.mjs +2 -3
- package/src/runtime/shared/buffered-appender.mjs +149 -0
- package/src/runtime/shared/launcher-control.mjs +2 -2
- package/src/runtime/shared/task-notification-envelope.mjs +98 -0
- package/src/runtime/shared/tool-execution-contract.mjs +2 -2
- package/src/runtime/shared/tool-primitives.mjs +308 -0
- package/src/runtime/shared/tool-result-summary.mjs +515 -0
- package/src/runtime/shared/tool-surface.mjs +80 -898
- package/src/runtime/shared/transcript-writer.mjs +52 -2
- package/src/runtime/shared/update-checker.mjs +7 -4
- package/src/session-runtime/config-helpers.mjs +291 -0
- package/src/session-runtime/config-lifecycle.mjs +232 -0
- package/src/session-runtime/cwd-plugins.mjs +226 -0
- package/src/session-runtime/effort.mjs +128 -0
- package/src/session-runtime/fs-utils.mjs +10 -0
- package/src/session-runtime/mcp-glue.mjs +177 -0
- package/src/session-runtime/model-capabilities.mjs +130 -0
- package/src/session-runtime/model-recency.mjs +111 -0
- package/src/session-runtime/native-search.mjs +247 -0
- package/src/session-runtime/output-styles.mjs +126 -0
- package/src/session-runtime/plugin-mcp.mjs +114 -0
- package/src/session-runtime/prewarm.mjs +142 -0
- package/src/session-runtime/provider-models.mjs +278 -0
- package/src/session-runtime/provider-usage.mjs +120 -0
- package/src/session-runtime/quick-model-rows.mjs +170 -0
- package/src/session-runtime/quick-search-models.mjs +46 -0
- package/src/session-runtime/session-hooks.mjs +93 -0
- package/src/session-runtime/session-text.mjs +100 -0
- package/src/session-runtime/settings-api.mjs +319 -0
- package/src/session-runtime/statusline-route.mjs +35 -0
- package/src/session-runtime/tool-catalog.mjs +720 -0
- package/src/session-runtime/tool-defs.mjs +84 -0
- package/src/session-runtime/warmup-schedulers.mjs +201 -0
- package/src/session-runtime/workflow.mjs +358 -0
- package/src/standalone/agent-tool/helpers.mjs +237 -0
- package/src/standalone/agent-tool/notify.mjs +107 -0
- package/src/standalone/agent-tool/provider-init.mjs +143 -0
- package/src/standalone/agent-tool/render.mjs +152 -0
- package/src/standalone/agent-tool/tool-def.mjs +55 -0
- package/src/standalone/agent-tool.mjs +155 -677
- package/src/standalone/channel-worker.mjs +7 -9
- package/src/standalone/explore-tool.mjs +40 -12
- package/src/standalone/hook-bus/config.mjs +207 -0
- package/src/standalone/hook-bus/constants.mjs +90 -0
- package/src/standalone/hook-bus/handlers.mjs +481 -0
- package/src/standalone/hook-bus/payload.mjs +31 -0
- package/src/standalone/hook-bus/rules.mjs +77 -0
- package/src/standalone/hook-bus.mjs +110 -746
- package/src/standalone/memory-runtime-proxy.mjs +7 -0
- package/src/standalone/opencode-go-login.mjs +125 -0
- package/src/standalone/provider-admin.mjs +15 -19
- package/src/standalone/usage-dashboard.mjs +3 -1
- package/src/tui/App.jsx +1163 -7571
- package/src/tui/app/app-format.mjs +206 -0
- package/src/tui/app/channel-pickers.mjs +510 -0
- package/src/tui/app/clipboard.mjs +67 -0
- package/src/tui/app/core-memory-picker.mjs +210 -0
- package/src/tui/app/extension-pickers.mjs +506 -0
- package/src/tui/app/input-parsers.mjs +193 -0
- package/src/tui/app/maintenance-pickers.mjs +324 -0
- package/src/tui/app/model-options.mjs +330 -0
- package/src/tui/app/model-picker.mjs +365 -0
- package/src/tui/app/onboarding-steps.mjs +400 -0
- package/src/tui/app/project-picker.mjs +247 -0
- package/src/tui/app/provider-setup-picker.mjs +580 -0
- package/src/tui/app/resume-picker.mjs +55 -0
- package/src/tui/app/route-pickers.mjs +419 -0
- package/src/tui/app/settings-picker.mjs +490 -0
- package/src/tui/app/slash-commands.mjs +101 -0
- package/src/tui/app/slash-dispatch.mjs +427 -0
- package/src/tui/app/text-layout.mjs +46 -0
- package/src/tui/app/theme-effort-pickers.mjs +154 -0
- package/src/tui/app/transcript-window.mjs +671 -0
- package/src/tui/app/use-mouse-input.mjs +460 -0
- package/src/tui/app/use-prompt-handlers.mjs +310 -0
- package/src/tui/app/use-transcript-scroll.mjs +510 -0
- package/src/tui/app/use-transcript-window.mjs +589 -0
- package/src/tui/components/ConfirmBar.jsx +1 -1
- package/src/tui/components/Picker.jsx +32 -4
- package/src/tui/components/PromptInput.jsx +259 -80
- package/src/tui/components/SlashCommandPalette.jsx +8 -1
- package/src/tui/components/StatusLine.jsx +63 -12
- package/src/tui/components/TextEntryPanel.jsx +11 -0
- package/src/tui/components/ToolExecution.jsx +56 -588
- package/src/tui/components/TranscriptItem.jsx +105 -0
- package/src/tui/components/UsagePanel.jsx +18 -4
- package/src/tui/components/prompt-input/edit-helpers.mjs +72 -0
- package/src/tui/components/prompt-input/voice-indicator.mjs +39 -0
- package/src/tui/components/tool-execution/ResultBody.jsx +56 -0
- package/src/tui/components/tool-execution/surface-detail.mjs +405 -0
- package/src/tui/components/tool-execution/text-format.mjs +161 -0
- package/src/tui/components/tool-output-format.mjs +2 -2
- package/src/tui/display-width.mjs +20 -3
- package/src/tui/dist/index.mjs +18034 -17188
- package/src/tui/engine/agent-envelope.mjs +296 -0
- package/src/tui/engine/agent-job-feed.mjs +133 -0
- package/src/tui/engine/boot-profile.mjs +21 -0
- package/src/tui/engine/labels.mjs +67 -0
- package/src/tui/engine/notice-text.mjs +112 -0
- package/src/tui/engine/notification-plan.mjs +76 -0
- package/src/tui/engine/queue-helpers.mjs +161 -0
- package/src/tui/engine/render-timing.mjs +17 -0
- package/src/tui/engine/session-stats.mjs +46 -0
- package/src/tui/engine/tool-approval.mjs +94 -0
- package/src/tui/engine/tool-call-fields.mjs +23 -0
- package/src/tui/engine/tool-card-results.mjs +234 -0
- package/src/tui/engine/tool-result-status.mjs +135 -0
- package/src/tui/engine/tool-result-text.mjs +126 -0
- package/src/tui/engine.mjs +405 -1385
- package/src/tui/figures.mjs +5 -0
- package/src/tui/index.jsx +105 -0
- package/src/tui/input-editing.mjs +60 -10
- package/src/tui/keyboard-protocol.mjs +2 -2
- package/src/tui/lib/voice-recorder.mjs +35 -19
- package/src/tui/markdown/format-token.mjs +11 -9
- package/src/tui/paste-attachments.mjs +38 -0
- package/src/tui/statusline-ansi-bridge.mjs +11 -3
- package/src/tui/theme.mjs +6 -0
- package/src/tui/themes/base.mjs +2 -2
- package/src/tui/themes/kanagawa.mjs +4 -4
- package/src/tui/themes/teal.mjs +4 -5
- package/src/tui/themes/utils.mjs +1 -1
- package/src/ui/statusline-agents.mjs +213 -0
- package/src/ui/statusline-format.mjs +146 -0
- package/src/ui/statusline-segments.mjs +148 -0
- package/src/ui/statusline.mjs +77 -462
- package/src/ui/tool-card.mjs +0 -1
- package/src/vendor/statusline/bin/statusline-route.mjs +15 -2
- package/src/workflows/default/WORKFLOW.md +16 -9
- package/src/workflows/sequential/WORKFLOW.md +16 -11
- package/src/workflows/solo/WORKFLOW.md +5 -1
- package/vendor/ink/build/display-width.js +19 -3
- package/vendor/ink/build/ink.js +103 -6
- package/vendor/ink/build/log-update.js +17 -3
- package/vendor/ink/build/wrap-text.js +125 -0
- package/scripts/_test-folder-dialog.mjs +0 -30
- package/scripts/fix-brief-fn.mjs +0 -35
- package/scripts/fix-format-tool-surface.mjs +0 -24
- package/scripts/fix-tool-exec-visible.mjs +0 -42
- package/scripts/patch-agent-brief.mjs +0 -48
- package/scripts/patch-app.mjs +0 -21
- package/scripts/patch-app2.mjs +0 -18
- package/scripts/patch-dist-brief.mjs +0 -96
- package/scripts/patch-tool-exec.mjs +0 -70
- package/src/examples/schedules/SCHEDULE.example.md +0 -32
- package/src/examples/webhooks/WEBHOOK.example.md +0 -40
- package/src/runtime/agent/orchestrator/session/manager.reactive-persist.test.mjs +0 -107
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.test.mjs +0 -143
- package/src/runtime/agent/orchestrator/tools/builtin/diagnostics-tool.mjs +0 -285
- package/src/runtime/agent/orchestrator/tools/builtin/open-config-tool.mjs +0 -26
- package/src/runtime/shared/channel-notification-routing.test.mjs +0 -45
- package/src/runtime/shared/tool-execution-contract.test.mjs +0 -183
- package/src/standalone/agent-task-status.test.mjs +0 -76
- package/src/tui/components/tool-output-format.test.mjs +0 -399
- package/src/tui/display-width.test.mjs +0 -35
- package/src/tui/engine-runtime-notification.test.mjs +0 -115
- package/src/tui/engine-tool-result-text.test.mjs +0 -75
- package/src/tui/markdown/format-token.test.mjs +0 -354
- package/src/tui/markdown/render-ansi.test.mjs +0 -108
- package/src/tui/markdown/stream-fence.test.mjs +0 -26
- package/src/tui/markdown/streaming-markdown.test.mjs +0 -70
- package/src/tui/prompt-history-store.test.mjs +0 -52
- package/src/tui/statusline-ansi-bridge.test.mjs +0 -159
- package/src/tui/transcript-tool-failures.test.mjs +0 -111
- package/src/ui/markdown.test.mjs +0 -70
- package/src/ui/statusline-context-label.test.mjs +0 -15
- package/src/vendor/statusline/bin/statusline-lib.mjs +0 -186
- package/src/vendor/statusline/bin/statusline-route.test.mjs +0 -80
package/scripts/tool-smoke.mjs
CHANGED
|
@@ -11,7 +11,7 @@ import { buildHeadlessSpawnArgs } from '../src/headless-role.mjs';
|
|
|
11
11
|
import { createStandaloneChannelWorker } from '../src/standalone/channel-worker.mjs';
|
|
12
12
|
import { OpenAIOAuthProvider, buildRequestBody, sendViaHttpSse } from '../src/runtime/agent/orchestrator/providers/openai-oauth.mjs';
|
|
13
13
|
import { _test as _anthropicOAuthTest } from '../src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs';
|
|
14
|
-
import { _logicalResponseItemMatch
|
|
14
|
+
import { _logicalResponseItemMatch } from '../src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs';
|
|
15
15
|
import { _mergePendingMessageEntries, applyAskTerminalUsageTotals, closeSession, createSession, drainPendingMessages, enqueuePendingMessage, resumeSession } from '../src/runtime/agent/orchestrator/session/manager.mjs';
|
|
16
16
|
import {
|
|
17
17
|
contentHasImage,
|
|
@@ -137,46 +137,6 @@ function assertOk(name, result, pattern = null) {
|
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
{
|
|
140
|
-
const fullPolicy = _resolveOpenAiPromptCacheRatePolicy({}, {
|
|
141
|
-
mode: 'full',
|
|
142
|
-
frameInputItems: 40,
|
|
143
|
-
deltaTokens: 9000,
|
|
144
|
-
hasPreviousResponseId: false,
|
|
145
|
-
});
|
|
146
|
-
assert(fullPolicy.policy === 'full_guard' && fullPolicy.limitPerMin === 12, `full cache lane should keep 12rpm guard: ${JSON.stringify(fullPolicy)}`);
|
|
147
|
-
|
|
148
|
-
const deltaPolicy = _resolveOpenAiPromptCacheRatePolicy({}, {
|
|
149
|
-
mode: 'delta',
|
|
150
|
-
frameInputItems: 1,
|
|
151
|
-
deltaTokens: 9000,
|
|
152
|
-
hasPreviousResponseId: true,
|
|
153
|
-
});
|
|
154
|
-
assert(deltaPolicy.policy === 'delta_relaxed' && deltaPolicy.limitPerMin === 60, `small delta should use relaxed cache lane rpm: ${JSON.stringify(deltaPolicy)}`);
|
|
155
|
-
|
|
156
|
-
const largeDeltaPolicy = _resolveOpenAiPromptCacheRatePolicy({}, {
|
|
157
|
-
mode: 'delta',
|
|
158
|
-
frameInputItems: 20,
|
|
159
|
-
deltaTokens: 9000,
|
|
160
|
-
hasPreviousResponseId: true,
|
|
161
|
-
});
|
|
162
|
-
assert(largeDeltaPolicy.policy === 'delta_guarded' && largeDeltaPolicy.limitPerMin === 12, `large delta should fall back to full guard: ${JSON.stringify(largeDeltaPolicy)}`);
|
|
163
|
-
|
|
164
|
-
const customDeltaPolicy = _resolveOpenAiPromptCacheRatePolicy({ openaiCacheLaneDeltaRateLimitPerMin: 90 }, {
|
|
165
|
-
mode: 'delta',
|
|
166
|
-
frameInputItems: 1,
|
|
167
|
-
deltaTokens: 9000,
|
|
168
|
-
hasPreviousResponseId: true,
|
|
169
|
-
});
|
|
170
|
-
assert(customDeltaPolicy.limitPerMin === 90, `custom delta rpm should be honored: ${JSON.stringify(customDeltaPolicy)}`);
|
|
171
|
-
|
|
172
|
-
const unlimitedDeltaPolicy = _resolveOpenAiPromptCacheRatePolicy({ openaiCacheLaneDeltaRateLimitPerMin: 0 }, {
|
|
173
|
-
mode: 'delta',
|
|
174
|
-
frameInputItems: 1,
|
|
175
|
-
deltaTokens: 9000,
|
|
176
|
-
hasPreviousResponseId: true,
|
|
177
|
-
});
|
|
178
|
-
assert(unlimitedDeltaPolicy.policy === 'delta_unlimited' && unlimitedDeltaPolicy.limitPerMin === 0, `delta rpm=0 should disable delta rate wait: ${JSON.stringify(unlimitedDeltaPolicy)}`);
|
|
179
|
-
|
|
180
140
|
const originalFunctionCall = {
|
|
181
141
|
type: 'function_call',
|
|
182
142
|
call_id: 'call_tool_1',
|
|
@@ -589,20 +549,28 @@ if (grepContextPolicyArgs['-C'] !== GREP_CONTEXT_MAX || Object.prototype.hasOwnP
|
|
|
589
549
|
throw new Error(`grep context policy must canonicalize and clamp explicit context: ${JSON.stringify(grepContextPolicyArgs)}`);
|
|
590
550
|
}
|
|
591
551
|
|
|
592
|
-
|
|
552
|
+
// Multiple absolute paths in one string are now auto-split into a path array
|
|
553
|
+
// (arg-guard splitMultipleAbsoluteWindowsPaths) instead of rejected.
|
|
554
|
+
const multiGrepPathArgs = {
|
|
593
555
|
pattern: 'providerStatus',
|
|
594
556
|
path: 'C:\\Project\\mixdog\\src\\tui C:\\Project\\mixdog\\src\\mixdog-session-runtime.mjs',
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
|
|
557
|
+
};
|
|
558
|
+
const multiGrepPathErr = validateBuiltinArgs('grep', multiGrepPathArgs);
|
|
559
|
+
if (multiGrepPathErr) {
|
|
560
|
+
throw new Error(`grep multi-path auto-split should pass validation: ${multiGrepPathErr}`);
|
|
561
|
+
}
|
|
562
|
+
if (!Array.isArray(multiGrepPathArgs.path) || multiGrepPathArgs.path.length !== 2) {
|
|
563
|
+
throw new Error(`grep multi-path auto-split should coerce to 2-element array: ${JSON.stringify(multiGrepPathArgs.path)}`);
|
|
598
564
|
}
|
|
599
565
|
|
|
600
|
-
|
|
566
|
+
// Lookaround/backrefs are no longer rejected at validation time: search-tool
|
|
567
|
+
// routes them to rg --pcre2 at runtime (arg-guard.mjs comment near globKeys).
|
|
568
|
+
const lookaroundGrepErr = validateBuiltinArgs('grep', {
|
|
601
569
|
pattern: 'C:\\\\Project(?!\\\\mixdog)',
|
|
602
570
|
path: root,
|
|
603
571
|
});
|
|
604
|
-
if (
|
|
605
|
-
throw new Error(`grep
|
|
572
|
+
if (lookaroundGrepErr) {
|
|
573
|
+
throw new Error(`grep lookaround pattern should pass validation (PCRE2 runtime routing): ${lookaroundGrepErr}`);
|
|
606
574
|
}
|
|
607
575
|
|
|
608
576
|
// Windows drive path + no explicit shell used to be rejected with a retry hint;
|
|
@@ -747,7 +715,7 @@ if (agentProps.mode || agentProps.wait) throw new Error('agent schema should not
|
|
|
747
715
|
agentRules: '# Tool Use',
|
|
748
716
|
skillManifest: '',
|
|
749
717
|
});
|
|
750
|
-
if (!heavyPrompt.stableSystemContext.includes('## heavy-worker')
|
|
718
|
+
if (!heavyPrompt.stableSystemContext.includes('## heavy-worker')) {
|
|
751
719
|
throw new Error(`heavy-worker AGENT.md must be included in scoped role instructions: ${heavyPrompt.stableSystemContext}`);
|
|
752
720
|
}
|
|
753
721
|
const workerPrompt = composeSystemPrompt({
|
|
@@ -756,7 +724,7 @@ if (agentProps.mode || agentProps.wait) throw new Error('agent schema should not
|
|
|
756
724
|
agentRules: '# Tool Use',
|
|
757
725
|
skillManifest: '',
|
|
758
726
|
});
|
|
759
|
-
if (!workerPrompt.stableSystemContext.includes('## worker')
|
|
727
|
+
if (!workerPrompt.stableSystemContext.includes('## worker')) {
|
|
760
728
|
throw new Error(`worker AGENT.md must be included in scoped role instructions: ${workerPrompt.stableSystemContext}`);
|
|
761
729
|
}
|
|
762
730
|
}
|
|
@@ -991,10 +959,7 @@ setInternalToolsProvider({
|
|
|
991
959
|
{ name: 'recall', description: 'Memory recall surface.', inputSchema: { type: 'object', properties: {} }, annotations: { readOnlyHint: true } },
|
|
992
960
|
{ name: 'search', description: 'Web search surface.', inputSchema: { type: 'object', properties: {} }, annotations: { readOnlyHint: true, openWorldHint: true } },
|
|
993
961
|
{ name: 'reply', description: 'Channel reply surface.', inputSchema: { type: 'object', properties: {} }, annotations: { destructiveHint: true } },
|
|
994
|
-
{ name: 'edit_message', description: 'Channel edit surface.', inputSchema: { type: 'object', properties: {} }, annotations: { destructiveHint: true } },
|
|
995
962
|
{ name: 'web_fetch', description: 'Web fetch surface.', inputSchema: { type: 'object', properties: {} }, annotations: { readOnlyHint: true, openWorldHint: true } },
|
|
996
|
-
{ name: 'reload_config', description: 'Config reload surface.', inputSchema: { type: 'object', properties: {} }, annotations: { destructiveHint: true } },
|
|
997
|
-
{ name: 'inject_command', description: 'Command injection surface.', inputSchema: { type: 'object', properties: {} }, annotations: { destructiveHint: true } },
|
|
998
963
|
],
|
|
999
964
|
});
|
|
1000
965
|
{
|
|
@@ -1091,7 +1056,7 @@ setInternalToolsProvider({
|
|
|
1091
1056
|
if (!/Read-only retrieval role/i.test(visible) || /# environment/i.test(visible) || /git operations deferred to Lead/i.test(visible)) {
|
|
1092
1057
|
throw new Error(`explorer hidden retrieval context should stay slim: ${visible.slice(0, 1200)}`);
|
|
1093
1058
|
}
|
|
1094
|
-
if (!/# Role: explorer/i.test(systemVisible) || /# Role: explorer/i.test(userReminderVisible) || !/
|
|
1059
|
+
if (!/# Role: explorer/i.test(systemVisible) || /# Role: explorer/i.test(userReminderVisible) || !/one-shot locator/i.test(systemVisible)) {
|
|
1095
1060
|
throw new Error(`explorer role md must ride BP2 system, not BP3 user reminder: system=${systemVisible.slice(0, 600)} user=${userReminderVisible.slice(0, 600)}`);
|
|
1096
1061
|
}
|
|
1097
1062
|
const visibleBytes = Buffer.byteLength(visible, 'utf8');
|
|
@@ -1197,12 +1162,12 @@ setInternalToolsProvider({
|
|
|
1197
1162
|
if (readTools.includes('shell') || writeTools.includes('shell')) {
|
|
1198
1163
|
throw new Error(`read/read-write agent schemas must omit shell: read=${readTools.join(', ')} write=${writeTools.join(', ')}`);
|
|
1199
1164
|
}
|
|
1200
|
-
for (const name of ['shell', 'apply_patch', 'task'
|
|
1165
|
+
for (const name of ['shell', 'apply_patch', 'task']) {
|
|
1201
1166
|
if (readTools.includes(name)) {
|
|
1202
1167
|
throw new Error(`read agent schema must omit non-read tool ${name}: read=${readTools.join(', ')}`);
|
|
1203
1168
|
}
|
|
1204
1169
|
}
|
|
1205
|
-
for (const name of ['apply_patch', 'task'
|
|
1170
|
+
for (const name of ['apply_patch', 'task']) {
|
|
1206
1171
|
if (name === 'apply_patch' && !writeTools.includes(name)) {
|
|
1207
1172
|
throw new Error(`read-write agent schema must preserve apply_patch: write=${writeTools.join(', ')}`);
|
|
1208
1173
|
}
|
|
@@ -1210,12 +1175,7 @@ setInternalToolsProvider({
|
|
|
1210
1175
|
throw new Error(`read-write agent schema must omit non-edit tool ${name}: write=${writeTools.join(', ')}`);
|
|
1211
1176
|
}
|
|
1212
1177
|
}
|
|
1213
|
-
for (const name of ['
|
|
1214
|
-
if (writeTools.includes(name)) {
|
|
1215
|
-
throw new Error(`read-write agent schema must omit config/skill tool ${name}: write=${writeTools.join(', ')}`);
|
|
1216
|
-
}
|
|
1217
|
-
}
|
|
1218
|
-
for (const name of ['memory', 'recall', 'reply', 'edit_message', 'reload_config', 'inject_command']) {
|
|
1178
|
+
for (const name of ['memory', 'recall', 'reply']) {
|
|
1219
1179
|
if (readTools.includes(name) || writeTools.includes(name)) {
|
|
1220
1180
|
throw new Error(`read/read-write agent schema must not expose full-runtime internal tool ${name}: read=${readTools.join(', ')} write=${writeTools.join(', ')}`);
|
|
1221
1181
|
}
|
|
@@ -1293,7 +1253,7 @@ setInternalToolsProvider({
|
|
|
1293
1253
|
const hiddenAgents = JSON.parse(readFileSync(join(root, 'src', 'defaults', 'agents.json'), 'utf8')).agents || [];
|
|
1294
1254
|
const hiddenPreset = { id: 'hidden-smoke', name: 'hidden-smoke', type: 'agent', provider: 'openai-oauth', model: 'tool-smoke-model', tools: 'full' };
|
|
1295
1255
|
const hiddenRuntimeSpec = { scopeKey: 'hidden-role-smoke', lane: 'agent' };
|
|
1296
|
-
const hiddenBadTools = new Set(['shell', 'task', '
|
|
1256
|
+
const hiddenBadTools = new Set(['shell', 'task', 'Skill', 'memory', 'reply', 'recall']);
|
|
1297
1257
|
const expectedForHiddenAgent = (permission, schemaAllowedTools) => {
|
|
1298
1258
|
if (Array.isArray(schemaAllowedTools)) return schemaAllowedTools.slice();
|
|
1299
1259
|
if (permission === 'none') return [];
|
|
@@ -1434,9 +1394,12 @@ for (const requiredGrammarLine of [
|
|
|
1434
1394
|
}
|
|
1435
1395
|
const readPathSchema = BUILTIN_TOOLS.find((tool) => tool.name === 'read')?.inputSchema?.properties?.path || {};
|
|
1436
1396
|
const readPathDescription = readPathSchema.description || '';
|
|
1437
|
-
if (!/File path/i.test(readPathDescription) || !/\{path,offset,limit\}\[\]/i.test(readPathDescription) || !/Pass arrays directly/i.test(readPathDescription) || !/legacy recovery only/i.test(readPathDescription)
|
|
1397
|
+
if (!/File path/i.test(readPathDescription) || !/\{path,offset,limit\}\[\]/i.test(readPathDescription) || !/Pass arrays directly/i.test(readPathDescription) || !/legacy recovery only/i.test(readPathDescription)) {
|
|
1438
1398
|
throw new Error('read schema must keep directory-vs-file guidance');
|
|
1439
1399
|
}
|
|
1400
|
+
if (!/Dirs use list/i.test((BUILTIN_TOOLS.find((tool) => tool.name === 'read')?.description) || '')) {
|
|
1401
|
+
throw new Error('read description must keep directory-vs-file guidance');
|
|
1402
|
+
}
|
|
1440
1403
|
const readTool = BUILTIN_TOOLS.find((tool) => tool.name === 'read');
|
|
1441
1404
|
const readDescription = readTool?.description || '';
|
|
1442
1405
|
const readProps = readTool?.inputSchema?.properties || {};
|
|
@@ -1514,7 +1477,7 @@ if (!/before text grep/i.test(codeGraphDescription)) {
|
|
|
1514
1477
|
if (!/repo-local/i.test(codeGraphDescription) || !/NOT web search|not web/i.test(codeGraphDescription)) {
|
|
1515
1478
|
throw new Error('code_graph description must mark itself repo-local (not web search)');
|
|
1516
1479
|
}
|
|
1517
|
-
if (!/repo-local|not web/i.test(codeGraphProps.mode?.description || '') || !/source file/i.test(codeGraphProps.
|
|
1480
|
+
if (!/repo-local|not web/i.test(codeGraphProps.mode?.description || '') || !/source file/i.test(codeGraphProps.files?.description || '')) {
|
|
1518
1481
|
throw new Error('code_graph schema must keep compact, repo-local field descriptions');
|
|
1519
1482
|
}
|
|
1520
1483
|
const recallTool = MEMORY_TOOL_DEFS.find((tool) => tool.name === 'recall');
|
|
@@ -1585,7 +1548,7 @@ if (!recallProps.sessionOnly || !/session only/i.test(recallProps.sessionOnly?.d
|
|
|
1585
1548
|
}
|
|
1586
1549
|
const memoryTool = MEMORY_TOOL_DEFS.find((tool) => tool.name === 'memory');
|
|
1587
1550
|
const memoryProps = memoryTool?.inputSchema?.properties || {};
|
|
1588
|
-
if (!/
|
|
1551
|
+
if (!/mutation/i.test(memoryTool?.description || '') || !/Exact confirmation phrase/i.test(memoryProps.confirm?.description || '')) {
|
|
1589
1552
|
throw new Error('memory schema must preserve mutation/destructive confirmation guidance');
|
|
1590
1553
|
}
|
|
1591
1554
|
const searchTool = SEARCH_TOOL_DEFS.find((tool) => tool.name === 'search');
|
|
@@ -1780,7 +1743,7 @@ if (grepTool?.inputSchema?.properties?.head_limit?.minimum !== 0 || !/keep small
|
|
|
1780
1743
|
if (grepTool?.inputSchema?.properties?.type) {
|
|
1781
1744
|
throw new Error('grep type schema must stay hidden; prefer glob for extension narrowing');
|
|
1782
1745
|
}
|
|
1783
|
-
if (!/code flow before text search/i.test(codeGraphProps.mode?.description || '') || !/one anchor is enough/i.test(codeGraphProps.
|
|
1746
|
+
if (!/code flow before text search/i.test(codeGraphProps.mode?.description || '') || !/one anchor is enough/i.test(codeGraphProps.symbols?.description || '') || !/one call/i.test(codeGraphProps.symbols?.description || '')) {
|
|
1784
1747
|
throw new Error('code_graph schema fields must steer away from repeated lookup loops');
|
|
1785
1748
|
}
|
|
1786
1749
|
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* scripts/tui-render-smoke.mjs — undeclared-identifier gate for the TUI bundle.
|
|
4
|
+
*
|
|
5
|
+
* Why: esbuild does not flag free (undeclared) identifiers in JSX modules —
|
|
6
|
+
* they may legitimately be runtime globals — and no smoke actually renders
|
|
7
|
+
* App. That gap shipped two ReferenceErrors (promptContentRows,
|
|
8
|
+
* TRANSCRIPT_WINDOW_OVERSCAN_ROWS) during the App.jsx split.
|
|
9
|
+
*
|
|
10
|
+
* How: parse src/tui/dist/index.mjs with acorn, run eslint-scope, and fail on
|
|
11
|
+
* any reference that resolves to no binding and is not a known JS/Node/DOM
|
|
12
|
+
* global. Static, deterministic, no terminal or engine session needed.
|
|
13
|
+
*
|
|
14
|
+
* Run: node scripts/tui-render-smoke.mjs (or `npm run smoke:tui`)
|
|
15
|
+
* Exit: 0 = clean, 1 = undeclared identifiers found or bundle missing.
|
|
16
|
+
*/
|
|
17
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
18
|
+
import { dirname, join } from 'node:path';
|
|
19
|
+
import { fileURLToPath } from 'node:url';
|
|
20
|
+
import { parse } from 'acorn';
|
|
21
|
+
import { analyze } from 'eslint-scope';
|
|
22
|
+
|
|
23
|
+
const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..');
|
|
24
|
+
const BUNDLE = join(ROOT, 'src', 'tui', 'dist', 'index.mjs');
|
|
25
|
+
|
|
26
|
+
// Globals that are legal free identifiers in the bundle. Anything outside
|
|
27
|
+
// this set that resolves to no binding is a guaranteed ReferenceError at
|
|
28
|
+
// runtime (module scope is strict; there is no window fallback in node ESM).
|
|
29
|
+
const KNOWN_GLOBALS = new Set([
|
|
30
|
+
// ECMAScript builtins
|
|
31
|
+
'Array', 'ArrayBuffer', 'Atomics', 'BigInt', 'BigInt64Array', 'BigUint64Array', 'Boolean',
|
|
32
|
+
'DataView', 'Date', 'Error', 'EvalError', 'FinalizationRegistry', 'Float32Array',
|
|
33
|
+
'Float64Array', 'Function', 'Infinity', 'Int8Array', 'Int16Array', 'Int32Array',
|
|
34
|
+
'Intl', 'JSON', 'Map', 'Math', 'NaN', 'Number', 'Object', 'Promise', 'Proxy',
|
|
35
|
+
'RangeError', 'ReferenceError', 'Reflect', 'RegExp', 'Set', 'SharedArrayBuffer',
|
|
36
|
+
'String', 'Symbol', 'SyntaxError', 'TypeError', 'URIError', 'Uint8Array',
|
|
37
|
+
'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', 'WeakRef', 'WeakSet',
|
|
38
|
+
'decodeURI', 'decodeURIComponent', 'encodeURI', 'encodeURIComponent', 'eval',
|
|
39
|
+
'globalThis', 'isFinite', 'isNaN', 'parseFloat', 'parseInt', 'undefined',
|
|
40
|
+
// Node.js globals
|
|
41
|
+
'AbortController', 'AbortSignal', 'Blob', 'Buffer', 'ByteLengthQueuingStrategy',
|
|
42
|
+
'CompressionStream', 'CountQueuingStrategy', 'Crypto', 'CryptoKey', 'CustomEvent',
|
|
43
|
+
'DecompressionStream', 'Event', 'EventTarget', 'File', 'FormData', 'Headers',
|
|
44
|
+
'MessageChannel', 'MessageEvent', 'MessagePort', 'Navigator', 'PerformanceEntry',
|
|
45
|
+
'PerformanceObserver', 'ReadableStream', 'ReadableStreamDefaultReader', 'Request',
|
|
46
|
+
'Response', 'SubtleCrypto', 'TextDecoder', 'TextDecoderStream', 'TextEncoder',
|
|
47
|
+
'TextEncoderStream', 'TransformStream', 'URL', 'URLSearchParams', 'WebAssembly',
|
|
48
|
+
'WebSocket', 'WritableStream', 'atob', 'btoa', 'clearImmediate', 'clearInterval',
|
|
49
|
+
'clearTimeout', 'console', 'crypto', 'fetch', 'navigator', 'performance',
|
|
50
|
+
'process', 'queueMicrotask', 'require', 'setImmediate', 'setInterval',
|
|
51
|
+
'setTimeout', 'structuredClone',
|
|
52
|
+
// Bundler/runtime artifacts occasionally referenced defensively
|
|
53
|
+
'window', 'document', 'reportError',
|
|
54
|
+
]);
|
|
55
|
+
|
|
56
|
+
if (!existsSync(BUNDLE)) {
|
|
57
|
+
console.error(`tui-render-smoke: FAIL — bundle not found at ${BUNDLE}; run \`npm run build:tui\` first`);
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const source = readFileSync(BUNDLE, 'utf8');
|
|
62
|
+
|
|
63
|
+
let ast;
|
|
64
|
+
try {
|
|
65
|
+
ast = parse(source, { ecmaVersion: 'latest', sourceType: 'module', locations: true, ranges: true });
|
|
66
|
+
} catch (err) {
|
|
67
|
+
console.error(`tui-render-smoke: FAIL — bundle does not parse: ${err.message}`);
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const scopeManager = analyze(ast, { ecmaVersion: 2022, sourceType: 'module' });
|
|
72
|
+
const unresolved = scopeManager.globalScope.through.filter(
|
|
73
|
+
(ref) => !KNOWN_GLOBALS.has(ref.identifier.name),
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
if (unresolved.length > 0) {
|
|
77
|
+
const seen = new Map();
|
|
78
|
+
for (const ref of unresolved) {
|
|
79
|
+
const { name } = ref.identifier;
|
|
80
|
+
if (!seen.has(name)) seen.set(name, ref.identifier.loc?.start);
|
|
81
|
+
}
|
|
82
|
+
console.error(`tui-render-smoke: FAIL — ${seen.size} undeclared identifier(s) in src/tui/dist/index.mjs:`);
|
|
83
|
+
for (const [name, loc] of seen) {
|
|
84
|
+
console.error(` ${name} (dist/index.mjs:${loc ? `${loc.line}:${loc.column}` : '?'})`);
|
|
85
|
+
}
|
|
86
|
+
console.error('These throw ReferenceError when the TUI renders. Fix missing imports in src/tui/ and rebuild.');
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
console.log('tui-render-smoke: ok — no undeclared identifiers in TUI bundle');
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import * as crypto from 'node:crypto';
|
|
4
|
+
import { mkdirSync, mkdtempSync, writeFileSync } from 'node:fs';
|
|
5
|
+
import { tmpdir } from 'node:os';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
import { readMarkdownDocument } from '../src/runtime/shared/markdown-frontmatter.mjs';
|
|
8
|
+
|
|
9
|
+
// DATA_DIR resolves from MIXDOG_DATA_DIR at module import time (via
|
|
10
|
+
// ./config.mjs -> resolvePluginData), so the env var MUST be set before
|
|
11
|
+
// the first dynamic import of webhook.mjs.
|
|
12
|
+
const dataDir = mkdtempSync(join(tmpdir(), 'mixdog-webhook-test-'));
|
|
13
|
+
process.env.MIXDOG_DATA_DIR = dataDir;
|
|
14
|
+
|
|
15
|
+
const {
|
|
16
|
+
extractSignature,
|
|
17
|
+
verifySignature,
|
|
18
|
+
loadEndpointConfig,
|
|
19
|
+
STRIPE_TOLERANCE_MS,
|
|
20
|
+
} = await import('../src/runtime/channels/lib/webhook.mjs');
|
|
21
|
+
|
|
22
|
+
function hmacHex(secret, payload) {
|
|
23
|
+
return crypto.createHmac('sha256', secret).update(payload).digest('hex');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// ── verifySignature: github/generic hex HMAC ──────────────────────────
|
|
27
|
+
|
|
28
|
+
test('verifySignature: github parser accepts a valid sha256 hex signature', () => {
|
|
29
|
+
const secret = 'shh';
|
|
30
|
+
const body = '{"hello":"world"}';
|
|
31
|
+
const sig = hmacHex(secret, body);
|
|
32
|
+
assert.equal(verifySignature(secret, body, sig, 'github'), true);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('verifySignature: generic parser accepts a valid sha256 hex signature', () => {
|
|
36
|
+
const secret = 'shh';
|
|
37
|
+
const body = '{"hello":"world"}';
|
|
38
|
+
const sig = hmacHex(secret, body);
|
|
39
|
+
assert.equal(verifySignature(secret, body, sig, 'generic'), true);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('verifySignature: github/generic reject a wrong signature', () => {
|
|
43
|
+
const secret = 'shh';
|
|
44
|
+
const body = '{"hello":"world"}';
|
|
45
|
+
const wrong = hmacHex('other-secret', body);
|
|
46
|
+
assert.equal(verifySignature(secret, body, wrong, 'github'), false);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test('verifySignature: length-mismatch hex signature returns false without throwing', () => {
|
|
50
|
+
const secret = 'shh';
|
|
51
|
+
const body = 'payload';
|
|
52
|
+
// Valid hex, wrong byte length vs the 32-byte sha256 digest.
|
|
53
|
+
assert.doesNotThrow(() => {
|
|
54
|
+
assert.equal(verifySignature(secret, body, 'ab', 'github'), false);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test('verifySignature: malformed (non-hex) signature returns false without throwing', () => {
|
|
59
|
+
const secret = 'shh';
|
|
60
|
+
const body = 'payload';
|
|
61
|
+
assert.doesNotThrow(() => {
|
|
62
|
+
assert.equal(verifySignature(secret, body, 'not-hex-zzzz', 'github'), false);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// ── verifySignature: stripe t= / v1= scheme ───────────────────────────
|
|
67
|
+
|
|
68
|
+
test('verifySignature: stripe accepts a valid t+v1 pair', () => {
|
|
69
|
+
const secret = 'stripe-secret';
|
|
70
|
+
const body = '{"id":"evt_1"}';
|
|
71
|
+
const t = Math.floor(Date.now() / 1000);
|
|
72
|
+
const v1 = hmacHex(secret, `${t}.${body}`);
|
|
73
|
+
assert.equal(verifySignature(secret, body, `t=${t},v1=${v1}`, 'stripe'), true);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test('verifySignature: stripe rejects a header missing t=', () => {
|
|
77
|
+
const secret = 'stripe-secret';
|
|
78
|
+
const body = '{"id":"evt_1"}';
|
|
79
|
+
const t = Math.floor(Date.now() / 1000);
|
|
80
|
+
const v1 = hmacHex(secret, `${t}.${body}`);
|
|
81
|
+
assert.equal(verifySignature(secret, body, `v1=${v1}`, 'stripe'), false);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('verifySignature: stripe rejects a header missing v1=', () => {
|
|
85
|
+
const secret = 'stripe-secret';
|
|
86
|
+
const body = '{"id":"evt_1"}';
|
|
87
|
+
const t = Math.floor(Date.now() / 1000);
|
|
88
|
+
assert.equal(verifySignature(secret, body, `t=${t}`, 'stripe'), false);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test('verifySignature: stripe rejects a stale timestamp beyond the tolerance window (replay)', () => {
|
|
92
|
+
const secret = 'stripe-secret';
|
|
93
|
+
const body = '{"id":"evt_1"}';
|
|
94
|
+
const staleT = Math.floor((Date.now() - STRIPE_TOLERANCE_MS - 60_000) / 1000);
|
|
95
|
+
const v1 = hmacHex(secret, `${staleT}.${body}`);
|
|
96
|
+
assert.equal(verifySignature(secret, body, `t=${staleT},v1=${v1}`, 'stripe'), false);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test('verifySignature: stripe rejects a tampered v1 (HMAC mismatch) with a fresh t', () => {
|
|
100
|
+
const secret = 'stripe-secret';
|
|
101
|
+
const body = '{"id":"evt_1"}';
|
|
102
|
+
const t = Math.floor(Date.now() / 1000);
|
|
103
|
+
const tamperedV1 = hmacHex('wrong-secret', `${t}.${body}`);
|
|
104
|
+
assert.equal(verifySignature(secret, body, `t=${t},v1=${tamperedV1}`, 'stripe'), false);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// ── extractSignature: parser mapping + fallback scan ──────────────────
|
|
108
|
+
|
|
109
|
+
test('extractSignature: github parser strips the sha256= prefix from x-hub-signature-256', () => {
|
|
110
|
+
const headers = { 'x-hub-signature-256': 'sha256=deadbeef' };
|
|
111
|
+
assert.equal(extractSignature(headers, 'github'), 'deadbeef');
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test('extractSignature: generic parser strips the sha256= prefix from x-signature-256', () => {
|
|
115
|
+
const headers = { 'x-signature-256': 'sha256=cafebabe' };
|
|
116
|
+
assert.equal(extractSignature(headers, 'generic'), 'cafebabe');
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test('extractSignature: stripe parser returns the raw stripe-signature value (no prefix)', () => {
|
|
120
|
+
const headers = { 'stripe-signature': 't=1,v1=abc123' };
|
|
121
|
+
assert.equal(extractSignature(headers, 'stripe'), 't=1,v1=abc123');
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test('extractSignature: sentry parser returns the raw sentry-hook-signature value', () => {
|
|
125
|
+
const headers = { 'sentry-hook-signature': 'raw-sig-value' };
|
|
126
|
+
assert.equal(extractSignature(headers, 'sentry'), 'raw-sig-value');
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test('extractSignature: unknown parser name falls back to scanning all known headers', () => {
|
|
130
|
+
const headers = { 'x-signature-256': 'sha256=fallback-hit' };
|
|
131
|
+
assert.equal(extractSignature(headers, 'no-such-parser'), 'fallback-hit');
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test('extractSignature: no parser given scans known headers in declaration order', () => {
|
|
135
|
+
const headers = { 'x-hub-signature-256': 'sha256=github-hit' };
|
|
136
|
+
assert.equal(extractSignature(headers, undefined), 'github-hit');
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test('extractSignature: returns null when no known signature header is present', () => {
|
|
140
|
+
const headers = { 'x-some-other-header': 'value' };
|
|
141
|
+
assert.equal(extractSignature(headers, 'github'), null);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// ── endpoint config loader: WEBHOOK.md frontmatter + secret side file ─
|
|
145
|
+
|
|
146
|
+
test('loadEndpointConfig: loads frontmatter + reads secret from side file', () => {
|
|
147
|
+
const name = 'my-endpoint';
|
|
148
|
+
const dir = join(dataDir, 'webhooks', name);
|
|
149
|
+
mkdirSync(dir, { recursive: true });
|
|
150
|
+
writeFileSync(
|
|
151
|
+
join(dir, 'WEBHOOK.md'),
|
|
152
|
+
[
|
|
153
|
+
'---',
|
|
154
|
+
'channel: main',
|
|
155
|
+
'parser: github',
|
|
156
|
+
'enabled: true',
|
|
157
|
+
'---',
|
|
158
|
+
'',
|
|
159
|
+
'Handle this webhook by summarizing the payload.',
|
|
160
|
+
'',
|
|
161
|
+
].join('\n'),
|
|
162
|
+
'utf8',
|
|
163
|
+
);
|
|
164
|
+
writeFileSync(join(dir, 'secret'), 'my-webhook-secret\n', 'utf8');
|
|
165
|
+
|
|
166
|
+
const cfg = loadEndpointConfig(name);
|
|
167
|
+
assert.equal(cfg.channel, 'main');
|
|
168
|
+
assert.equal(cfg.parser, 'github');
|
|
169
|
+
assert.equal(cfg.enabled, true);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
test('loadEndpointConfig: enabled: false frontmatter casts to boolean false', () => {
|
|
173
|
+
const name = 'disabled-endpoint';
|
|
174
|
+
const dir = join(dataDir, 'webhooks', name);
|
|
175
|
+
mkdirSync(dir, { recursive: true });
|
|
176
|
+
writeFileSync(
|
|
177
|
+
join(dir, 'WEBHOOK.md'),
|
|
178
|
+
['---', 'channel: main', 'enabled: false', '---', '', 'body text', ''].join('\n'),
|
|
179
|
+
'utf8',
|
|
180
|
+
);
|
|
181
|
+
const cfg = loadEndpointConfig(name);
|
|
182
|
+
assert.equal(cfg.enabled, false);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
test('loadEndpointConfig: returns null for a name with no WEBHOOK.md', () => {
|
|
186
|
+
assert.equal(loadEndpointConfig('never-registered'), null);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// loadEndpointConfig only surfaces the frontmatter (by design — see
|
|
190
|
+
// webhook.mjs comment above loadEndpointConfig); confirm the underlying
|
|
191
|
+
// shared parser it delegates to also recovers the markdown body, since
|
|
192
|
+
// the loader's frontmatter/body split is not independently exercised
|
|
193
|
+
// through the exported loadEndpointConfig surface.
|
|
194
|
+
test('readMarkdownDocument: WEBHOOK.md-shaped input yields frontmatter + body', () => {
|
|
195
|
+
const raw = [
|
|
196
|
+
'---',
|
|
197
|
+
'channel: main',
|
|
198
|
+
'parser: github',
|
|
199
|
+
'---',
|
|
200
|
+
'',
|
|
201
|
+
'Handle this webhook by summarizing the payload.',
|
|
202
|
+
'',
|
|
203
|
+
].join('\n');
|
|
204
|
+
const { frontmatter, body } = readMarkdownDocument(raw);
|
|
205
|
+
assert.equal(frontmatter.channel, 'main');
|
|
206
|
+
assert.equal(frontmatter.parser, 'github');
|
|
207
|
+
assert.equal(body, 'Handle this webhook by summarizing the payload.');
|
|
208
|
+
});
|
|
@@ -7,5 +7,8 @@ permission: read
|
|
|
7
7
|
Root-cause analysis agent.
|
|
8
8
|
|
|
9
9
|
Smallest confirmed cause chain before fixes. Return likely cause, evidence
|
|
10
|
-
(`file:line`), smallest next check/fix.
|
|
11
|
-
|
|
10
|
+
(`file:line`), smallest next check/fix. Mark confirmed facts vs inferences;
|
|
11
|
+
avoid broad speculation. Fragments only; no narration, no report bloat.
|
|
12
|
+
|
|
13
|
+
Converge, don't sweep: when new reads stop adding evidence, report the best
|
|
14
|
+
cause chain so far — a partial/blocked report is a valid completion.
|
|
@@ -1,11 +1,21 @@
|
|
|
1
|
-
---
|
|
2
|
-
permission: read-write
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Heavy Worker
|
|
6
|
-
Broad implementation agent.
|
|
7
|
-
|
|
8
|
-
Bounded slices; smallest coherent change, not rewrite. Stop: unclear scope,
|
|
9
|
-
growing blast radius, or Lead-only verification.
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
---
|
|
2
|
+
permission: read-write
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Heavy Worker
|
|
6
|
+
Broad implementation agent.
|
|
7
|
+
|
|
8
|
+
Bounded slices; smallest coherent change, not rewrite. Stop: unclear scope,
|
|
9
|
+
growing blast radius, or Lead-only verification.
|
|
10
|
+
|
|
11
|
+
EDIT-FIRST DISCIPLINE. Survey the slice with ONE batched read/grep round,
|
|
12
|
+
then start patching the first bounded piece — broad scope means edit
|
|
13
|
+
incrementally, not read exhaustively. NEVER "one more confirming read": if
|
|
14
|
+
an anchor is plausible, the next call is `apply_patch`. Repeated read-only
|
|
15
|
+
turns without an edit = stalling; any runtime reminder is your cue to patch
|
|
16
|
+
the piece you understand or report blocked — a blocked report is a valid
|
|
17
|
+
completion. Self-check comes AFTER edits; deep verification is Lead's.
|
|
18
|
+
|
|
19
|
+
Minimal checks + how-to-verify. Hand off outcome as fragments anchored to
|
|
20
|
+
`file:line`; no narration, no report bloat.
|
|
21
|
+
|
|
@@ -5,3 +5,7 @@ permission: read-write
|
|
|
5
5
|
# Maintainer
|
|
6
6
|
|
|
7
7
|
Maintenance and cleanup agent.
|
|
8
|
+
|
|
9
|
+
Smallest coherent change; no scope growth. Repeated read-only turns without
|
|
10
|
+
an edit = stalling; patch or return blocked — a blocked report is a valid
|
|
11
|
+
completion. Hand off as fragments (`file:line`); no narration.
|
|
@@ -7,5 +7,6 @@ permission: read
|
|
|
7
7
|
Regression/risk review agent.
|
|
8
8
|
|
|
9
9
|
Find actionable correctness/regression/security/verification risks. Findings
|
|
10
|
-
first, severity-ordered, one line with `file:line`; skip non-risky nits.
|
|
11
|
-
|
|
10
|
+
first, severity-ordered, one line with `file:line`; skip non-risky nits. If
|
|
11
|
+
clean, one line + only material residual risk. Fragments only; no narration,
|
|
12
|
+
no report bloat.
|
|
@@ -1,11 +1,21 @@
|
|
|
1
|
-
---
|
|
2
|
-
permission: read-write
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Worker
|
|
6
|
-
Scoped implementation agent.
|
|
7
|
-
|
|
8
|
-
Smallest scoped change; no drive-by cleanup. Stop when done/blocked.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
---
|
|
2
|
+
permission: read-write
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Worker
|
|
6
|
+
Scoped implementation agent.
|
|
7
|
+
|
|
8
|
+
Smallest scoped change; no drive-by cleanup. Stop when done/blocked.
|
|
9
|
+
|
|
10
|
+
EDIT-FIRST DISCIPLINE. Brief anchors (`file:line`) are pre-verified — trust
|
|
11
|
+
them and patch. No anchor: locate with AT MOST 1-2 reads, then edit. NEVER
|
|
12
|
+
"one more confirming read": if you know the file and the change, the next
|
|
13
|
+
call is `apply_patch`. Repeated read-only turns without an edit = stalling;
|
|
14
|
+
any runtime reminder is your cue to patch now or return blocked with what's
|
|
15
|
+
missing — a blocked report is a valid completion. Confidence threshold is
|
|
16
|
+
"plausible", not "proven"; self-check comes AFTER the edit, and Lead/Reviewer
|
|
17
|
+
own final verification.
|
|
18
|
+
|
|
19
|
+
Hand off outcome as fragments anchored to `file:line`; no narration, no
|
|
20
|
+
report bloat.
|
|
21
|
+
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
* Source files (rules/):
|
|
22
22
|
* - shared/01-tool.md — universal tool policy (Lead + agent BP1, identical full set)
|
|
23
23
|
* - lead/lead-tool.md — Lead-specific control-tower / delegation / ToolSearch guidance
|
|
24
|
+
* - lead/lead-brief.md — Lead brief contract (agent handoff briefs)
|
|
24
25
|
* - lead/01-02 — Lead general / channels
|
|
25
26
|
* - output-styles/<name>.md — Lead output style, selected by config outputStyle
|
|
26
27
|
* - agent/00-common.md — agent common behavior + universal worker contract (BP2)
|
|
@@ -275,6 +276,9 @@ function buildLeadRoleContent({ PLUGIN_ROOT, DATA_DIR }) {
|
|
|
275
276
|
const toolLead = readOptional(path.join(LEAD_DIR, 'lead-tool.md'));
|
|
276
277
|
if (toolLead) parts.push(toolLead);
|
|
277
278
|
|
|
279
|
+
const briefLead = readOptional(path.join(LEAD_DIR, 'lead-brief.md'));
|
|
280
|
+
if (briefLead) parts.push(briefLead);
|
|
281
|
+
|
|
278
282
|
if (generalSplit.role) parts.push(generalSplit.role);
|
|
279
283
|
|
|
280
284
|
const channels = readOptional(path.join(LEAD_DIR, '02-channels.md'));
|