muonroi-cli 1.7.2 → 1.8.1
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/dist/packages/agent-harness-core/src/event-filter.js +1 -0
- package/dist/packages/agent-harness-core/src/event-redact.js +8 -0
- package/dist/packages/agent-harness-core/src/mcp-server.d.ts +16 -0
- package/dist/packages/agent-harness-core/src/mcp-server.js +88 -10
- package/dist/packages/agent-harness-core/src/protocol.d.ts +15 -0
- package/dist/packages/agent-harness-core/src/selector.js +2 -2
- package/dist/packages/agent-harness-core/src/transports/sidechannel.js +1 -1
- package/dist/packages/agent-harness-opentui/src/agent-mode.js +1 -1
- package/dist/packages/agent-harness-opentui/src/install.js +1 -1
- package/dist/src/__test-stubs__/vitest-setup.js +4 -0
- package/dist/src/agent-harness/__tests__/mock-model.spec.js +54 -0
- package/dist/src/agent-harness/mock-model.d.ts +1 -1
- package/dist/src/agent-harness/mock-model.js +143 -6
- package/dist/src/agent-harness/test-spawn.js +3 -1
- package/dist/src/chat/chat-keychain.js +9 -1
- package/dist/src/cli/cost-forensics.js +7 -4
- package/dist/src/cli/keys.d.ts +2 -2
- package/dist/src/cli/keys.js +107 -28
- package/dist/src/cli/usage-report.js +2 -2
- package/dist/src/council/__tests__/abort-threading.test.d.ts +1 -0
- package/dist/src/council/__tests__/abort-threading.test.js +193 -0
- package/dist/src/council/__tests__/clarification-prompt.test.js +21 -1
- package/dist/src/council/__tests__/council-turn-length-emit.test.d.ts +1 -0
- package/dist/src/council/__tests__/council-turn-length-emit.test.js +130 -0
- package/dist/src/council/__tests__/debate-round-budget.test.d.ts +1 -0
- package/dist/src/council/__tests__/debate-round-budget.test.js +45 -0
- package/dist/src/council/__tests__/evaluator-metrics.test.js +3 -0
- package/dist/src/council/__tests__/post-debate-recommendation.test.d.ts +1 -0
- package/dist/src/council/__tests__/post-debate-recommendation.test.js +58 -0
- package/dist/src/council/__tests__/research-tools.test.js +4 -0
- package/dist/src/council/__tests__/round-tools.test.js +6 -0
- package/dist/src/council/clarifier-question-cap.test.d.ts +12 -0
- package/dist/src/council/clarifier-question-cap.test.js +73 -0
- package/dist/src/council/clarifier.d.ts +29 -1
- package/dist/src/council/clarifier.js +64 -1
- package/dist/src/council/debate-planner.d.ts +2 -1
- package/dist/src/council/debate-planner.js +5 -3
- package/dist/src/council/debate.d.ts +9 -0
- package/dist/src/council/debate.js +88 -8
- package/dist/src/council/index.d.ts +46 -1
- package/dist/src/council/index.js +125 -19
- package/dist/src/council/llm.js +41 -13
- package/dist/src/council/prompts.js +36 -1
- package/dist/src/council/types.d.ts +14 -1
- package/dist/src/ee/__tests__/export-transcripts.test.js +1 -1
- package/dist/src/ee/bridge.d.ts +3 -1
- package/dist/src/ee/bridge.js +9 -3
- package/dist/src/ee/bridge.test.js +1 -2
- package/dist/src/ee/client.js +15 -2
- package/dist/src/ee/recall-ledger.d.ts +20 -0
- package/dist/src/ee/recall-ledger.js +40 -1
- package/dist/src/ee/search.d.ts +25 -0
- package/dist/src/ee/search.js +73 -0
- package/dist/src/ee/types.d.ts +15 -1
- package/dist/src/ee/who-am-i.d.ts +41 -0
- package/dist/src/ee/who-am-i.js +143 -0
- package/dist/src/ee/who-am-i.test.d.ts +1 -0
- package/dist/src/ee/who-am-i.test.js +101 -0
- package/dist/src/flow/compaction/index.d.ts +1 -0
- package/dist/src/flow/compaction/index.js +4 -0
- package/dist/src/generated/version.d.ts +1 -1
- package/dist/src/generated/version.js +1 -1
- package/dist/src/headless/council-answers.js +1 -0
- package/dist/src/headless/output.d.ts +30 -1
- package/dist/src/headless/output.js +180 -0
- package/dist/src/headless/output.test.js +61 -1
- package/dist/src/hooks/index.js +48 -2
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +59 -62
- package/dist/src/lsp/client-normalize.test.d.ts +12 -0
- package/dist/src/lsp/client-normalize.test.js +34 -0
- package/dist/src/lsp/client.d.ts +1 -0
- package/dist/src/lsp/client.js +10 -2
- package/dist/src/lsp/manager.d.ts +1 -1
- package/dist/src/lsp/manager.js +13 -5
- package/dist/src/lsp/manager.test.js +41 -2
- package/dist/src/lsp/runtime.d.ts +1 -1
- package/dist/src/lsp/runtime.js +2 -2
- package/dist/src/maintain/__tests__/gh-create-pr.test.js +7 -3
- package/dist/src/maintain/__tests__/pr-builder.test.js +7 -3
- package/dist/src/mcp/__tests__/client-pool.spec.js +3 -3
- package/dist/src/mcp/__tests__/ee-tools.test.js +42 -14
- package/dist/src/mcp/__tests__/forensics-tools.test.js +3 -3
- package/dist/src/mcp/__tests__/lsp-tools.test.js +4 -4
- package/dist/src/mcp/auto-setup.js +0 -8
- package/dist/src/mcp/client-pool.d.ts +1 -1
- package/dist/src/mcp/client-pool.js +25 -9
- package/dist/src/mcp/ee-tools.d.ts +10 -0
- package/dist/src/mcp/ee-tools.js +34 -0
- package/dist/src/mcp/self-verify-jobs.d.ts +1 -0
- package/dist/src/mcp/self-verify-jobs.js +1 -3
- package/dist/src/mcp/self-verify-runner.js +1 -1
- package/dist/src/models/catalog-gemini.test.js +12 -10
- package/dist/src/models/catalog.json +106 -38
- package/dist/src/orchestrator/__tests__/auto-commit.test.d.ts +1 -0
- package/dist/src/orchestrator/__tests__/auto-commit.test.js +142 -0
- package/dist/src/orchestrator/__tests__/batch-turn-runner.test.js +3 -0
- package/dist/src/orchestrator/__tests__/delegations.test.d.ts +1 -0
- package/dist/src/orchestrator/__tests__/delegations.test.js +96 -0
- package/dist/src/orchestrator/__tests__/message-processor.test.js +2 -0
- package/dist/src/orchestrator/__tests__/prompts.test.d.ts +1 -0
- package/dist/src/orchestrator/__tests__/prompts.test.js +88 -0
- package/dist/src/orchestrator/__tests__/stream-runner.test.js +29 -0
- package/dist/src/orchestrator/__tests__/sub-session-delegation.test.d.ts +1 -0
- package/dist/src/orchestrator/__tests__/sub-session-delegation.test.js +507 -0
- package/dist/src/orchestrator/agent.test.js +5 -2
- package/dist/src/orchestrator/auto-commit.d.ts +110 -0
- package/dist/src/orchestrator/auto-commit.js +366 -0
- package/dist/src/orchestrator/batch-turn-runner.d.ts +3 -2
- package/dist/src/orchestrator/batch-turn-runner.js +2 -1
- package/dist/src/orchestrator/compaction-proposer-prompt.d.ts +8 -0
- package/dist/src/orchestrator/compaction-proposer-prompt.js +43 -0
- package/dist/src/orchestrator/compaction.d.ts +22 -0
- package/dist/src/orchestrator/compaction.js +42 -0
- package/dist/src/orchestrator/delegations.d.ts +1 -0
- package/dist/src/orchestrator/delegations.js +41 -0
- package/dist/src/orchestrator/error-utils.js +27 -2
- package/dist/src/orchestrator/message-processor.d.ts +23 -5
- package/dist/src/orchestrator/message-processor.js +226 -2573
- package/dist/src/orchestrator/orchestrator.d.ts +11 -2
- package/dist/src/orchestrator/orchestrator.js +530 -43
- package/dist/src/orchestrator/pending-calls.js +2 -1
- package/dist/src/orchestrator/preprocessor.d.ts +13 -0
- package/dist/src/orchestrator/preprocessor.js +146 -0
- package/dist/src/orchestrator/prompts.d.ts +16 -0
- package/dist/src/orchestrator/prompts.js +130 -67
- package/dist/src/orchestrator/safety-askcard.d.ts +66 -0
- package/dist/src/orchestrator/safety-askcard.js +74 -0
- package/dist/src/orchestrator/sandbox.test.js +8 -5
- package/dist/src/orchestrator/scope-ceiling.js +1 -1
- package/dist/src/orchestrator/stall-watchdog.d.ts +47 -0
- package/dist/src/orchestrator/stall-watchdog.js +23 -0
- package/dist/src/orchestrator/stall-watchdog.test.js +36 -1
- package/dist/src/orchestrator/stream-runner.js +52 -30
- package/dist/src/orchestrator/sub-agent-cap.d.ts +2 -0
- package/dist/src/orchestrator/sub-agent-cap.js +12 -4
- package/dist/src/orchestrator/sub-agent-model-tier.js +1 -1
- package/dist/src/orchestrator/subagent-compactor.d.ts +21 -0
- package/dist/src/orchestrator/subagent-compactor.js +148 -24
- package/dist/src/orchestrator/subagent-compactor.spec.js +249 -1
- package/dist/src/orchestrator/text-tool-call-detector.d.ts +9 -5
- package/dist/src/orchestrator/text-tool-call-detector.js +16 -12
- package/dist/src/orchestrator/text-tool-call-detector.test.js +66 -8
- package/dist/src/orchestrator/tool-args-repair.js +1 -1
- package/dist/src/orchestrator/tool-engine.d.ts +153 -0
- package/dist/src/orchestrator/tool-engine.js +3138 -0
- package/dist/src/orchestrator/turn-runner-deps.d.ts +3 -0
- package/dist/src/pil/__tests__/discovery-types.test.js +15 -4
- package/dist/src/pil/__tests__/discovery.test.js +89 -145
- package/dist/src/pil/__tests__/dual-run.test.js +2 -0
- package/dist/src/pil/__tests__/layer1-intent-trace.test.js +3 -0
- package/dist/src/pil/__tests__/layer1-intent.test.js +3 -0
- package/dist/src/pil/__tests__/layer16-clarity.test.js +35 -32
- package/dist/src/pil/__tests__/layer18-acceptance.test.js +1 -78
- package/dist/src/pil/__tests__/layer2_5-ponytail.test.d.ts +1 -0
- package/dist/src/pil/__tests__/layer2_5-ponytail.test.js +53 -0
- package/dist/src/pil/__tests__/layer3-ee-injection.test.js +67 -4
- package/dist/src/pil/__tests__/layer3-injected-chunk.test.js +14 -2
- package/dist/src/pil/__tests__/layer4-gsd.test.js +30 -0
- package/dist/src/pil/__tests__/layer5-context.test.js +39 -1
- package/dist/src/pil/__tests__/layer6-output.test.js +30 -2
- package/dist/src/pil/__tests__/llm-classify.test.js +79 -1
- package/dist/src/pil/__tests__/orchestrator-integration.test.js +3 -1
- package/dist/src/pil/__tests__/pipeline.test.js +11 -8
- package/dist/src/pil/__tests__/response-tools.test.js +52 -0
- package/dist/src/pil/agent-operating-contract.d.ts +1 -1
- package/dist/src/pil/agent-operating-contract.js +5 -3
- package/dist/src/pil/agent-operating-contract.test.js +2 -2
- package/dist/src/pil/cheap-model-playbook.d.ts +1 -1
- package/dist/src/pil/cheap-model-playbook.js +1 -1
- package/dist/src/pil/cheap-model-workbooks.d.ts +1 -1
- package/dist/src/pil/cheap-model-workbooks.js +1 -1
- package/dist/src/pil/config.d.ts +20 -0
- package/dist/src/pil/config.js +35 -0
- package/dist/src/pil/discovery-types.d.ts +32 -9
- package/dist/src/pil/discovery.d.ts +3 -3
- package/dist/src/pil/discovery.js +138 -244
- package/dist/src/pil/index.d.ts +1 -1
- package/dist/src/pil/index.js +1 -1
- package/dist/src/pil/layer1-intent.d.ts +9 -1
- package/dist/src/pil/layer1-intent.js +62 -7
- package/dist/src/pil/layer1-intent.test.js +112 -2
- package/dist/src/pil/layer15-context-scan.js +1 -1
- package/dist/src/pil/layer16-clarity.d.ts +21 -25
- package/dist/src/pil/layer16-clarity.js +52 -88
- package/dist/src/pil/layer18-acceptance.d.ts +13 -3
- package/dist/src/pil/layer18-acceptance.js +1 -75
- package/dist/src/pil/layer2-personality.js +7 -8
- package/dist/src/pil/layer2_5-ponytail.d.ts +2 -0
- package/dist/src/pil/layer2_5-ponytail.js +41 -0
- package/dist/src/pil/layer3-ee-injection.js +180 -14
- package/dist/src/pil/layer4-gsd.js +22 -8
- package/dist/src/pil/layer5-context.d.ts +1 -0
- package/dist/src/pil/layer5-context.js +26 -11
- package/dist/src/pil/layer6-output.js +23 -5
- package/dist/src/pil/llm-classify.d.ts +11 -0
- package/dist/src/pil/llm-classify.js +196 -3
- package/dist/src/pil/native-capabilities-workbook.d.ts +1 -1
- package/dist/src/pil/native-capabilities-workbook.js +4 -3
- package/dist/src/pil/pipeline.js +15 -1
- package/dist/src/pil/response-tools.d.ts +16 -0
- package/dist/src/pil/response-tools.js +41 -0
- package/dist/src/pil/schema.d.ts +8 -0
- package/dist/src/pil/schema.js +24 -3
- package/dist/src/pil/task-tier-map.js +7 -7
- package/dist/src/pil/types.d.ts +9 -3
- package/dist/src/product-loop/__tests__/discovery-interview.test.js +103 -1
- package/dist/src/product-loop/__tests__/gather-selectable-alts.test.js +34 -0
- package/dist/src/product-loop/__tests__/sprint-self-verify.test.js +12 -12
- package/dist/src/product-loop/discovery-interview.d.ts +20 -0
- package/dist/src/product-loop/discovery-interview.js +121 -7
- package/dist/src/product-loop/gather.js +19 -5
- package/dist/src/product-loop/loop-driver.js +2 -2
- package/dist/src/product-loop/sprint-self-verify.js +2 -2
- package/dist/src/providers/__tests__/reasoning-roundtrip.test.js +12 -0
- package/dist/src/providers/auth/__tests__/gemini-oauth.test.d.ts +1 -5
- package/dist/src/providers/auth/__tests__/gemini-oauth.test.js +1 -5
- package/dist/src/providers/auth/gcloud.d.ts +28 -0
- package/dist/src/providers/auth/gcloud.js +102 -0
- package/dist/src/providers/auth/gemini-oauth.d.ts +46 -19
- package/dist/src/providers/auth/gemini-oauth.js +292 -105
- package/dist/src/providers/auth/grok-oauth.d.ts +1 -1
- package/dist/src/providers/auth/grok-oauth.js +1 -1
- package/dist/src/providers/auth/registry.js +28 -6
- package/dist/src/providers/gemini.d.ts +1 -1
- package/dist/src/providers/gemini.js +10 -3
- package/dist/src/providers/keychain.d.ts +2 -2
- package/dist/src/providers/keychain.js +20 -2
- package/dist/src/providers/openai.js +5 -1
- package/dist/src/providers/runtime.d.ts +1 -1
- package/dist/src/providers/runtime.js +11 -2
- package/dist/src/providers/siliconflow-sse-repair.js +1 -1
- package/dist/src/providers/strategies/google.strategy.d.ts +9 -2
- package/dist/src/providers/strategies/google.strategy.js +159 -9
- package/dist/src/providers/strategies/thinking-mode.js +19 -6
- package/dist/src/providers/types.d.ts +1 -1
- package/dist/src/router/decide.test.js +40 -8
- package/dist/src/router/step-router.d.ts +20 -0
- package/dist/src/router/step-router.js +73 -0
- package/dist/src/self-qa/agentic-loop.js +30 -21
- package/dist/src/self-qa/orchestrator.js +5 -5
- package/dist/src/self-qa/scenario-planner.js +1 -1
- package/dist/src/self-qa/spec-emitter.js +4 -4
- package/dist/src/storage/__tests__/hierarchical-session.test.d.ts +1 -0
- package/dist/src/storage/__tests__/hierarchical-session.test.js +161 -0
- package/dist/src/storage/__tests__/sweep-stale-pending.test.js +2 -2
- package/dist/src/storage/index.d.ts +1 -1
- package/dist/src/storage/index.js +1 -1
- package/dist/src/storage/migrations.js +13 -1
- package/dist/src/storage/transcript-response-entry.test.js +18 -5
- package/dist/src/storage/transcript-view.js +7 -1
- package/dist/src/storage/transcript.d.ts +3 -0
- package/dist/src/storage/transcript.js +254 -73
- package/dist/src/storage/ui-interaction-log.d.ts +17 -0
- package/dist/src/storage/usage.js +22 -5
- package/dist/src/tools/__tests__/native-tools.test.js +6 -0
- package/dist/src/tools/bash.d.ts +36 -23
- package/dist/src/tools/bash.js +59 -301
- package/dist/src/tools/bash.test.js +2 -257
- package/dist/src/tools/file-tracker.d.ts +5 -0
- package/dist/src/tools/file-tracker.js +14 -0
- package/dist/src/tools/file.js +2 -0
- package/dist/src/tools/git-safety.d.ts +38 -1
- package/dist/src/tools/git-safety.js +94 -4
- package/dist/src/tools/git-safety.test.js +45 -1
- package/dist/src/tools/native-tools.d.ts +1 -1
- package/dist/src/tools/native-tools.js +66 -1
- package/dist/src/tools/registry-bash-empty-command.test.js +4 -3
- package/dist/src/tools/registry-git-safety.test.js +17 -6
- package/dist/src/tools/registry.d.ts +6 -0
- package/dist/src/tools/registry.js +215 -13
- package/dist/src/types/index.d.ts +8 -2
- package/dist/src/ui/app.d.ts +1 -0
- package/dist/src/ui/app.js +0 -0
- package/dist/src/ui/components/council-question-card.js +1 -0
- package/dist/src/ui/components/message-view.js +37 -3
- package/dist/src/ui/components/structured-response-view.js +7 -0
- package/dist/src/ui/components/task-list-panel.js +3 -12
- package/dist/src/ui/containers/chat-feed.d.ts +40 -0
- package/dist/src/ui/containers/chat-feed.js +66 -0
- package/dist/src/ui/containers/modals-layer.d.ts +87 -0
- package/dist/src/ui/containers/modals-layer.js +18 -0
- package/dist/src/ui/slash/__tests__/menu-parity.test.d.ts +1 -0
- package/dist/src/ui/slash/__tests__/menu-parity.test.js +1 -0
- package/dist/src/ui/slash/__tests__/ponytail.test.d.ts +1 -0
- package/dist/src/ui/slash/__tests__/ponytail.test.js +37 -0
- package/dist/src/ui/slash/expand.js +14 -1
- package/dist/src/ui/slash/export.js +16 -1
- package/dist/src/ui/slash/menu-items.js +1 -0
- package/dist/src/ui/slash/ponytail.d.ts +2 -0
- package/dist/src/ui/slash/ponytail.js +19 -0
- package/dist/src/ui/status-bar/store.js +0 -1
- package/dist/src/ui/status-bar/store.test.js +2 -2
- package/dist/src/ui/use-app-logic.d.ts +26 -0
- package/dist/src/ui/use-app-logic.js +0 -0
- package/dist/src/ui/utils/relaunch.js +1 -1
- package/dist/src/ui/utils/text.d.ts +11 -0
- package/dist/src/ui/utils/text.js +21 -1
- package/dist/src/ui/utils/text.test.js +25 -1
- package/dist/src/ui/utils/tools.js +3 -1
- package/dist/src/usage/cost-log.js +2 -2
- package/dist/src/usage/estimator.d.ts +14 -0
- package/dist/src/usage/estimator.js +22 -0
- package/dist/src/utils/__tests__/compaction-caps.test.d.ts +21 -0
- package/dist/src/utils/__tests__/compaction-caps.test.js +187 -0
- package/dist/src/utils/__tests__/llm-deadline-abort.test.d.ts +1 -0
- package/dist/src/utils/__tests__/llm-deadline-abort.test.js +33 -0
- package/dist/src/utils/__tests__/llm-deadline.test.js +16 -4
- package/dist/src/utils/__tests__/logger.test.d.ts +1 -0
- package/dist/src/utils/__tests__/logger.test.js +115 -0
- package/dist/src/utils/__tests__/settings-agent-first.test.d.ts +1 -0
- package/dist/src/utils/__tests__/settings-agent-first.test.js +48 -0
- package/dist/src/utils/install-manager.d.ts +1 -0
- package/dist/src/utils/install-manager.js +76 -7
- package/dist/src/utils/install-manager.test.js +43 -1
- package/dist/src/utils/llm-deadline.d.ts +9 -1
- package/dist/src/utils/llm-deadline.js +31 -2
- package/dist/src/utils/logger.d.ts +28 -0
- package/dist/src/utils/logger.js +171 -0
- package/dist/src/utils/permission-mode.d.ts +33 -0
- package/dist/src/utils/permission-mode.js +164 -3
- package/dist/src/utils/permission-mode.test.js +92 -1
- package/dist/src/utils/settings.d.ts +36 -32
- package/dist/src/utils/settings.js +151 -123
- package/dist/src/utils/update-checker.test.js +5 -1
- package/package.json +1 -1
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { classifyViaBrain, pilContext } from "../ee/bridge.js";
|
|
13
13
|
import { classify } from "../router/classifier/index.js";
|
|
14
|
-
import { isLlmFirstClassifyEnabled, isUnifiedPilEnabled } from "./config.js";
|
|
14
|
+
import { getUnifiedPilBudgetMs, isLlmFirstBrainEnabled, isLlmFirstClassifyEnabled, isUnifiedPilEnabled, } from "./config.js";
|
|
15
15
|
/** File/path reference regex — matches common source-file extensions. */
|
|
16
16
|
const FILE_REF_RE = /[\w./-]+\.(ts|tsx|js|jsx|json|md|py|rs|go|cs)\b/gi;
|
|
17
17
|
/** Keywords that force a "low" complexity signal (additive score -3). */
|
|
@@ -645,6 +645,49 @@ export async function layer1Intent(ctx, opts = {}) {
|
|
|
645
645
|
complexity,
|
|
646
646
|
complexityScore,
|
|
647
647
|
};
|
|
648
|
+
// G3 (b1): reach the unified injection on the default (model-first)
|
|
649
|
+
// path. Without this, _brainData stays null and layer3 falls back to a
|
|
650
|
+
// legacy dense-only /api/search round-trip with divergent source
|
|
651
|
+
// attribution. Populate _brainData from the SAME server-side unified
|
|
652
|
+
// retrieval the offline cascade uses (one round-trip, bounded by budget)
|
|
653
|
+
// so layer3 renders the richer source="unified" block AND records the
|
|
654
|
+
// rateable ledger consistently. On chitchat / null / failure, _brainData
|
|
655
|
+
// stays null → layer3 legacy path (behaviour unchanged). Gate:
|
|
656
|
+
// MUONROI_LLM_FIRST_BRAIN=0 reverts.
|
|
657
|
+
let llmFirstBrainData = null;
|
|
658
|
+
if (isLlmFirstBrainEnabled() && intentKind !== "chitchat") {
|
|
659
|
+
let brainRaw = ctx.raw;
|
|
660
|
+
if (ctx.sessionId) {
|
|
661
|
+
brainRaw =
|
|
662
|
+
ctx.raw +
|
|
663
|
+
' [EE task checkpoints ("Context checkpoint summary" with ✔ DONE) from prior compactions are available via the ee.query tool. ' +
|
|
664
|
+
"To keep full tool history this turn when you see pre-warn or compaction note, emit exact literal PRESERVE_FULL_CONTEXT in reasoning or assistant note. " +
|
|
665
|
+
'Self-check "task finished?" or "compacted yet this turn?" using the checkpoints.]';
|
|
666
|
+
}
|
|
667
|
+
intentTrace.pass3UnifiedAttempted = true;
|
|
668
|
+
// try/catch (not .catch) so a SYNC throw from pilContext (e.g. no EE
|
|
669
|
+
// client configured, as in unit tests) is also swallowed — it must
|
|
670
|
+
// never break the model-first return; _brainData just stays null.
|
|
671
|
+
let resp = null;
|
|
672
|
+
try {
|
|
673
|
+
resp = await pilContext(brainRaw, {
|
|
674
|
+
projectCtx: domain ? { domain } : undefined,
|
|
675
|
+
budgetMs: getUnifiedPilBudgetMs(),
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
catch (err) {
|
|
679
|
+
console.error(`[pil/layer1] llm-first unified brain fetch failed: ${err?.message}`);
|
|
680
|
+
}
|
|
681
|
+
if (resp) {
|
|
682
|
+
llmFirstBrainData = {
|
|
683
|
+
t0_principles: resp.t0_principles,
|
|
684
|
+
t1_rules: resp.t1_rules,
|
|
685
|
+
t2_patterns: resp.t2_patterns,
|
|
686
|
+
retrieval_skipped_reason: resp.retrieval_skipped_reason,
|
|
687
|
+
};
|
|
688
|
+
intentTrace.pass3UnifiedSucceeded = true;
|
|
689
|
+
}
|
|
690
|
+
}
|
|
648
691
|
return {
|
|
649
692
|
...ctx,
|
|
650
693
|
taskType: llmRes.taskType,
|
|
@@ -665,9 +708,10 @@ export async function layer1Intent(ctx, opts = {}) {
|
|
|
665
708
|
// the raw prompt.
|
|
666
709
|
ecosystemScope: llmRes.ecosystemScope,
|
|
667
710
|
replyLanguage: llmRes.replyLanguage,
|
|
668
|
-
//
|
|
669
|
-
//
|
|
670
|
-
|
|
711
|
+
// G3 (b1): populated from the unified pil-context fetch above so
|
|
712
|
+
// layer3 renders source="unified" instead of its legacy dense-only
|
|
713
|
+
// round-trip. null (chitchat / fetch failed) → layer3 legacy path.
|
|
714
|
+
_brainData: llmFirstBrainData,
|
|
671
715
|
_intentTrace: intentTrace,
|
|
672
716
|
layers: [
|
|
673
717
|
...ctx.layers,
|
|
@@ -1040,8 +1084,11 @@ export async function layer1Intent(ctx, opts = {}) {
|
|
|
1040
1084
|
// accidentally swallow phrases like "refactor this" or "fix the bug" that
|
|
1041
1085
|
// happen to be short.
|
|
1042
1086
|
//
|
|
1043
|
-
//
|
|
1044
|
-
//
|
|
1087
|
+
// WhoAmI v4.0: the outputStyle baseline from communication.brevity +
|
|
1088
|
+
// decision_speed is now wired below (getWhoAmIProfile/outputStyleFromProfile
|
|
1089
|
+
// at the classifier-default branch — it replaces "balanced" when no per-turn
|
|
1090
|
+
// signal resolves the style). Not applied at this chitchat hot-path: greetings
|
|
1091
|
+
// already force "concise" regardless of profile.
|
|
1045
1092
|
const trimmed = ctx.raw.trim();
|
|
1046
1093
|
const wordCount = trimmed.split(/\s+/).filter(Boolean).length;
|
|
1047
1094
|
const noTaskSignal = taskType === null || (taskType === "general" && result.reason === "regex:short-message");
|
|
@@ -1096,7 +1143,7 @@ export async function layer1Intent(ctx, opts = {}) {
|
|
|
1096
1143
|
}
|
|
1097
1144
|
const resp = await pilContext(brainRaw, {
|
|
1098
1145
|
projectCtx: domain ? { domain } : undefined,
|
|
1099
|
-
budgetMs:
|
|
1146
|
+
budgetMs: getUnifiedPilBudgetMs(),
|
|
1100
1147
|
});
|
|
1101
1148
|
if (resp) {
|
|
1102
1149
|
if (resp.taskType)
|
|
@@ -1293,6 +1340,14 @@ Prompt: "${ctx.raw.slice(0, 300)}"`, 800);
|
|
|
1293
1340
|
}
|
|
1294
1341
|
}
|
|
1295
1342
|
}
|
|
1343
|
+
else if (opts.profileStyleBaseline) {
|
|
1344
|
+
// WhoAmI v4.0 baseline: a standing communication.brevity/decision_speed
|
|
1345
|
+
// preference (computed once in the pipeline from the on-device profile)
|
|
1346
|
+
// fills in when no per-turn signal resolved the style. Per-turn detection
|
|
1347
|
+
// above still wins (override); this only replaces the generic "balanced".
|
|
1348
|
+
outputStyle = opts.profileStyleBaseline;
|
|
1349
|
+
styleSource = "whoami-profile";
|
|
1350
|
+
}
|
|
1296
1351
|
else {
|
|
1297
1352
|
outputStyle = "balanced";
|
|
1298
1353
|
styleSource = "classifier-default";
|
|
@@ -12,14 +12,23 @@ vi.mock("./config.js", () => ({
|
|
|
12
12
|
// Default OFF so the existing cascade tests below exercise the regex passes.
|
|
13
13
|
// The model-first gate has its own describe block that flips this to true.
|
|
14
14
|
isLlmFirstClassifyEnabled: vi.fn(() => false),
|
|
15
|
+
// G3 (b1): default OFF so the existing model-first classification tests don't
|
|
16
|
+
// trigger the unified brain fetch; the brain-path test flips it true.
|
|
17
|
+
isLlmFirstBrainEnabled: vi.fn(() => false),
|
|
18
|
+
// Pass-3 unified reads the client-side budget; provided so the whole-module
|
|
19
|
+
// mock does not drop the export (the model-first tests never hit it, but the
|
|
20
|
+
// cascade tests can).
|
|
21
|
+
getUnifiedPilBudgetMs: vi.fn(() => 3500),
|
|
15
22
|
}));
|
|
16
|
-
import { classifyViaBrain } from "../ee/bridge.js";
|
|
23
|
+
import { classifyViaBrain, pilContext } from "../ee/bridge.js";
|
|
17
24
|
import { classify } from "../router/classifier/index.js";
|
|
18
|
-
import { isLlmFirstClassifyEnabled } from "./config.js";
|
|
25
|
+
import { isLlmFirstBrainEnabled, isLlmFirstClassifyEnabled } from "./config.js";
|
|
19
26
|
import { hasActionableToolIntent, isGreenfieldBuildTask, isSocialPleasantry, isStatusCheckQuestion, layer1Intent, } from "./layer1-intent.js";
|
|
20
27
|
const mockedClassify = vi.mocked(classify);
|
|
21
28
|
const mockedClassifyViaBrain = vi.mocked(classifyViaBrain);
|
|
22
29
|
const mockedLlmFirst = vi.mocked(isLlmFirstClassifyEnabled);
|
|
30
|
+
const mockedLlmFirstBrain = vi.mocked(isLlmFirstBrainEnabled);
|
|
31
|
+
const mockedPilContext = vi.mocked(pilContext);
|
|
23
32
|
function makeCtx(raw) {
|
|
24
33
|
return {
|
|
25
34
|
raw,
|
|
@@ -560,6 +569,10 @@ describe("Pass 2.6 — social pleasantries route to chitchat (drop the tool-sche
|
|
|
560
569
|
describe("layer1Intent — model-first gate (MUONROI_LLM_FIRST_CLASSIFY)", () => {
|
|
561
570
|
beforeEach(() => {
|
|
562
571
|
mockedLlmFirst.mockReturnValue(true);
|
|
572
|
+
// G3 (b1): brain fetch OFF by default so the classification tests don't
|
|
573
|
+
// trigger pilContext; the brain-path tests flip it on explicitly.
|
|
574
|
+
mockedLlmFirstBrain.mockReturnValue(false);
|
|
575
|
+
mockedPilContext.mockReset();
|
|
563
576
|
// Make the regex cascade obviously WRONG so passing tests prove the model won.
|
|
564
577
|
mockedClassify.mockReturnValue({ tier: "hot", reason: "regex:create-file", confidence: 0.9 });
|
|
565
578
|
});
|
|
@@ -582,6 +595,75 @@ describe("layer1Intent — model-first gate (MUONROI_LLM_FIRST_CLASSIFY)", () =>
|
|
|
582
595
|
expect(result._intentTrace?.pass1Reason).toBe("llm-first");
|
|
583
596
|
expect(mockedClassify).not.toHaveBeenCalled();
|
|
584
597
|
});
|
|
598
|
+
it("G3 (b1): populates _brainData from pilContext on the model-first path (→ layer3 unified)", async () => {
|
|
599
|
+
mockedLlmFirstBrain.mockReturnValue(true);
|
|
600
|
+
// biome-ignore lint/suspicious/noExplicitAny: partial pil-context shape for the test
|
|
601
|
+
mockedPilContext.mockResolvedValue({
|
|
602
|
+
taskType: "general",
|
|
603
|
+
intentKind: "task",
|
|
604
|
+
outputStyle: "concise",
|
|
605
|
+
confidence: 0.9,
|
|
606
|
+
t0_principles: [{ text: "principle-1", score: 0.9 }],
|
|
607
|
+
t1_rules: [{ text: "rule-1", score: 0.8 }],
|
|
608
|
+
t2_patterns: [],
|
|
609
|
+
retrieval_skipped_reason: null,
|
|
610
|
+
});
|
|
611
|
+
const result = await layer1Intent(makeCtx("explain the auth flow"), {
|
|
612
|
+
llmFallback: async () => ({
|
|
613
|
+
taskType: "general",
|
|
614
|
+
outputStyle: "concise",
|
|
615
|
+
confidence: 0.9,
|
|
616
|
+
intentKind: "task",
|
|
617
|
+
deliverableKind: "answer",
|
|
618
|
+
depthTier: null,
|
|
619
|
+
ecosystemScope: null,
|
|
620
|
+
replyLanguage: null,
|
|
621
|
+
}),
|
|
622
|
+
});
|
|
623
|
+
// _brainData now carries the unified brain → layer3 renders source="unified"
|
|
624
|
+
// instead of its legacy dense-only /api/search round-trip.
|
|
625
|
+
expect(result._brainData?.t0_principles).toHaveLength(1);
|
|
626
|
+
expect(result._brainData?.t1_rules).toHaveLength(1);
|
|
627
|
+
expect(result._intentTrace?.pass3UnifiedAttempted).toBe(true);
|
|
628
|
+
expect(result._intentTrace?.pass3UnifiedSucceeded).toBe(true);
|
|
629
|
+
expect(mockedPilContext).toHaveBeenCalledTimes(1);
|
|
630
|
+
});
|
|
631
|
+
it("G3 (b1): chitchat skips the brain fetch (no pilContext round-trip)", async () => {
|
|
632
|
+
mockedLlmFirstBrain.mockReturnValue(true);
|
|
633
|
+
const result = await layer1Intent(makeCtx("cảm ơn nhé"), {
|
|
634
|
+
llmFallback: async () => ({
|
|
635
|
+
taskType: "general",
|
|
636
|
+
outputStyle: "concise",
|
|
637
|
+
confidence: 0.9,
|
|
638
|
+
intentKind: "chitchat",
|
|
639
|
+
deliverableKind: "answer",
|
|
640
|
+
depthTier: null,
|
|
641
|
+
ecosystemScope: null,
|
|
642
|
+
replyLanguage: null,
|
|
643
|
+
}),
|
|
644
|
+
});
|
|
645
|
+
expect(result._brainData).toBeNull();
|
|
646
|
+
expect(mockedPilContext).not.toHaveBeenCalled();
|
|
647
|
+
});
|
|
648
|
+
it("G3 (b1): a failed/empty pilContext leaves _brainData null (layer3 legacy path)", async () => {
|
|
649
|
+
mockedLlmFirstBrain.mockReturnValue(true);
|
|
650
|
+
mockedPilContext.mockResolvedValue(null);
|
|
651
|
+
const result = await layer1Intent(makeCtx("explain the auth flow"), {
|
|
652
|
+
llmFallback: async () => ({
|
|
653
|
+
taskType: "general",
|
|
654
|
+
outputStyle: "concise",
|
|
655
|
+
confidence: 0.9,
|
|
656
|
+
intentKind: "task",
|
|
657
|
+
deliverableKind: "answer",
|
|
658
|
+
depthTier: null,
|
|
659
|
+
ecosystemScope: null,
|
|
660
|
+
replyLanguage: null,
|
|
661
|
+
}),
|
|
662
|
+
});
|
|
663
|
+
expect(result._brainData).toBeNull();
|
|
664
|
+
expect(result.taskType).toBe("general"); // classification still intact
|
|
665
|
+
expect(mockedPilContext).toHaveBeenCalledTimes(1);
|
|
666
|
+
});
|
|
585
667
|
it("marks chitchat from the model for a pure greeting", async () => {
|
|
586
668
|
const result = await layer1Intent(makeCtx("cảm ơn bạn nhé"), {
|
|
587
669
|
llmFallback: async () => ({
|
|
@@ -651,4 +733,32 @@ describe("layer1Intent — model-first gate (MUONROI_LLM_FIRST_CLASSIFY)", () =>
|
|
|
651
733
|
expect(result.taskType).toBe("debug");
|
|
652
734
|
});
|
|
653
735
|
});
|
|
736
|
+
describe("layer1Intent — WhoAmI v4.0 output-style baseline (opts.profileStyleBaseline)", () => {
|
|
737
|
+
// A cheap regex task hit (high conf, unified PIL mocked off) skips the brain and
|
|
738
|
+
// lands on the classifier-default branch — exactly where the profile baseline now
|
|
739
|
+
// applies. The pipeline derives the baseline from the profile; layer1 just consumes
|
|
740
|
+
// the option. The prompt carries no explicit style cue.
|
|
741
|
+
const REFACTOR_PROMPT = "refactor the authentication module to use the new provider";
|
|
742
|
+
it("uses the profile-derived style baseline when no per-turn signal resolves it", async () => {
|
|
743
|
+
mockedClassify.mockReturnValue({ tier: "hot", reason: "regex:refactor", confidence: 0.9 });
|
|
744
|
+
const result = await layer1Intent(makeCtx(REFACTOR_PROMPT), { profileStyleBaseline: "concise" });
|
|
745
|
+
expect(result.taskType).toBe("refactor");
|
|
746
|
+
expect(result.outputStyle).toBe("concise");
|
|
747
|
+
expect(result._intentTrace?.styleSource).toBe("whoami-profile");
|
|
748
|
+
});
|
|
749
|
+
it("falls back to balanced when there is no profile baseline (behaviour unchanged)", async () => {
|
|
750
|
+
mockedClassify.mockReturnValue({ tier: "hot", reason: "regex:refactor", confidence: 0.9 });
|
|
751
|
+
const result = await layer1Intent(makeCtx(REFACTOR_PROMPT), { profileStyleBaseline: null });
|
|
752
|
+
expect(result.outputStyle).toBe("balanced");
|
|
753
|
+
expect(result._intentTrace?.styleSource).toBe("classifier-default");
|
|
754
|
+
});
|
|
755
|
+
it("an explicit per-turn style request still overrides the profile baseline", async () => {
|
|
756
|
+
mockedClassify.mockReturnValue({ tier: "hot", reason: "regex:refactor", confidence: 0.9 });
|
|
757
|
+
const result = await layer1Intent(makeCtx("refactor the auth module and explain step by step"), {
|
|
758
|
+
profileStyleBaseline: "concise",
|
|
759
|
+
});
|
|
760
|
+
expect(result.outputStyle).toBe("detailed");
|
|
761
|
+
expect(result._intentTrace?.styleSource).toBe("explicit-regex");
|
|
762
|
+
});
|
|
763
|
+
});
|
|
654
764
|
//# sourceMappingURL=layer1-intent.test.js.map
|
|
@@ -76,7 +76,7 @@ export function scanBoundedContexts(cwd) {
|
|
|
76
76
|
const entryNames = ["index.ts", "index.tsx", "index.js", "mod.rs", "__init__.py"];
|
|
77
77
|
const entryFiles = entryNames.map((e) => join(dirPath, e)).filter((e) => existsSync(join(cwd, e)));
|
|
78
78
|
const exportedSymbols = extractExports(cwd, entryFiles).slice(0, 20);
|
|
79
|
-
return { path: dirPath
|
|
79
|
+
return { path: `${dirPath}/`, name: d, entryFiles, exportedSymbols };
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
82
|
function extractExports(cwd, entryFiles) {
|
|
@@ -1,33 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* src/pil/layer16-clarity.ts
|
|
3
3
|
*
|
|
4
|
-
* Phase
|
|
5
|
-
* (
|
|
6
|
-
*
|
|
7
|
-
* its questions, options, recommended default, and reason — in
|
|
8
|
-
* `proposeModelGaps` (`discovery.ts`). There is no regex gap synthesis.
|
|
4
|
+
* Phase 3 (2026-06-23): the model now generates full ModelCard[] directly
|
|
5
|
+
* (questions, options, kinds, cancel/adjust markers) — no ClarityGap
|
|
6
|
+
* intermediate, no sentinel strings, no hardcoded "Type something" option.
|
|
9
7
|
*
|
|
10
|
-
* What remains here is
|
|
11
|
-
* -
|
|
12
|
-
* - `
|
|
13
|
-
* - `resolveGapsNonInteractive` (default-answer resolution when headless),
|
|
14
|
-
* - `getAutofilledOutcome` / `getDefaultOutcome` (outcome-label polish).
|
|
8
|
+
* What remains here is thin RENDERING + HEADLESS RESOLUTION:
|
|
9
|
+
* - `modelCardToQuestion` (ModelCard → CouncilQuestionData)
|
|
10
|
+
* - `resolveGapsNonInteractive` (default-answer resolution when headless)
|
|
15
11
|
*/
|
|
16
12
|
import type { CouncilQuestionData } from "../types/index.js";
|
|
17
|
-
import type { ClarifiedIntent,
|
|
18
|
-
import type { TaskType } from "./types.js";
|
|
13
|
+
import type { ClarifiedIntent, ModelCard, ProjectContext } from "./discovery-types.js";
|
|
19
14
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* sentinel, NOT a real outcome, so it must never surface verbatim as the
|
|
24
|
-
* resolved outcome. Centralised here so discovery.ts (which presents the
|
|
25
|
-
* option) and the outcome-resolution paths agree on the exact strings.
|
|
15
|
+
* Map a model-designed card into a CouncilQuestionData for TUI rendering.
|
|
16
|
+
* The model controls every field; the CLI only assigns questionId and maps
|
|
17
|
+
* the card options 1:1 into CouncilQuestionOptions (keeping isCancel/isAdjust).
|
|
26
18
|
*/
|
|
27
|
-
export declare
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
export declare function resolveGapsNonInteractive(
|
|
33
|
-
|
|
19
|
+
export declare function modelCardToQuestion(card: ModelCard, questionId: string): CouncilQuestionData;
|
|
20
|
+
/**
|
|
21
|
+
* Resolve model cards with best-effort defaults when there is no interactive
|
|
22
|
+
* handler (headless mode). Picks the default option for each card.
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveGapsNonInteractive(cards: ModelCard[], projectContext: ProjectContext, raw: string): ClarifiedIntent;
|
|
25
|
+
/**
|
|
26
|
+
* Get a default outcome label for well-known task types when no outcome
|
|
27
|
+
* was voiced by the user and no card provided one.
|
|
28
|
+
*/
|
|
29
|
+
export declare function getDefaultOutcome(taskType: string | null, raw?: string): string;
|
|
@@ -1,107 +1,71 @@
|
|
|
1
|
-
import { hasOperationalScope } from "./clarity-gate.js";
|
|
2
1
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* sentinel, NOT a real outcome, so it must never surface verbatim as the
|
|
7
|
-
* resolved outcome. Centralised here so discovery.ts (which presents the
|
|
8
|
-
* option) and the outcome-resolution paths agree on the exact strings.
|
|
2
|
+
* Map a model-designed card into a CouncilQuestionData for TUI rendering.
|
|
3
|
+
* The model controls every field; the CLI only assigns questionId and maps
|
|
4
|
+
* the card options 1:1 into CouncilQuestionOptions (keeping isCancel/isAdjust).
|
|
9
5
|
*/
|
|
10
|
-
export
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
export function buildInterviewQuestion(gap, questionId) {
|
|
20
|
-
const options = gap.options.map((label) => ({
|
|
21
|
-
label,
|
|
22
|
-
value: label,
|
|
23
|
-
kind: "choice",
|
|
6
|
+
export function modelCardToQuestion(card, questionId) {
|
|
7
|
+
const options = card.options.map((o) => ({
|
|
8
|
+
label: o.label,
|
|
9
|
+
value: o.label,
|
|
10
|
+
kind: o.kind,
|
|
11
|
+
description: o.description,
|
|
12
|
+
isCancel: o.isCancel,
|
|
13
|
+
isAdjust: o.isAdjust,
|
|
24
14
|
}));
|
|
25
|
-
options.push({
|
|
26
|
-
label: "Type something",
|
|
27
|
-
description: "Enter a custom answer",
|
|
28
|
-
value: "",
|
|
29
|
-
kind: "freetext",
|
|
30
|
-
});
|
|
31
15
|
return {
|
|
32
16
|
questionId,
|
|
33
|
-
question:
|
|
34
|
-
context:
|
|
35
|
-
isRequired:
|
|
17
|
+
question: card.question,
|
|
18
|
+
context: card.context,
|
|
19
|
+
isRequired: true,
|
|
36
20
|
phase: "pil-interview",
|
|
37
21
|
options,
|
|
38
|
-
defaultIndex:
|
|
22
|
+
defaultIndex: card.defaultIndex ?? 0,
|
|
39
23
|
};
|
|
40
24
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
break;
|
|
57
|
-
}
|
|
58
|
-
case "constraint":
|
|
59
|
-
constraints.push(defaultAnswer);
|
|
60
|
-
break;
|
|
25
|
+
/**
|
|
26
|
+
* Resolve model cards with best-effort defaults when there is no interactive
|
|
27
|
+
* handler (headless mode). Picks the default option for each card.
|
|
28
|
+
*/
|
|
29
|
+
export function resolveGapsNonInteractive(cards, projectContext, raw) {
|
|
30
|
+
const answers = [];
|
|
31
|
+
for (const card of cards) {
|
|
32
|
+
const defaultIdx = card.defaultIndex ?? 0;
|
|
33
|
+
const opt = card.options[defaultIdx];
|
|
34
|
+
if (opt?.kind === "freetext") {
|
|
35
|
+
// Freetext can't be auto-answered; fall back to raw-derived outcome
|
|
36
|
+
answers.push("");
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
answers.push(opt?.label ?? "");
|
|
61
40
|
}
|
|
62
41
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (scope.length === 0) {
|
|
66
|
-
scope = projectContext.relevantModules.map((m) => m.path);
|
|
67
|
-
if (scope.length === 0)
|
|
68
|
-
scope = ["project root"];
|
|
69
|
-
}
|
|
42
|
+
const outcome = answers.find((a) => a.length > 0) ?? `Complete: ${raw.slice(0, 80)}`;
|
|
43
|
+
const scope = projectContext.relevantModules.length > 0 ? projectContext.relevantModules.map((m) => m.path) : ["project root"];
|
|
70
44
|
return {
|
|
71
45
|
outcome,
|
|
72
46
|
scope,
|
|
73
|
-
constraints,
|
|
74
|
-
gaps:
|
|
47
|
+
constraints: [],
|
|
48
|
+
gaps: [],
|
|
75
49
|
};
|
|
76
50
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (isNativeMeta) {
|
|
89
|
-
// Force good outcome for self-review / native meta prompts regardless of L1 taskType (analyze/debug)
|
|
90
|
-
// Prevents generic "Local path...", "In prompts/ directory...", "Complete the task..." in [Discovery]
|
|
91
|
-
return "Native self-assessment of the CLI with specific, actionable code fixes proposed and verified";
|
|
92
|
-
}
|
|
93
|
-
// Operational debug tasks (CI/build/deploy) have a stronger default outcome.
|
|
94
|
-
if (taskType === "debug" && hasOperationalScope(raw)) {
|
|
95
|
-
return "Pipeline green, all checks passing";
|
|
96
|
-
}
|
|
97
|
-
return DEFAULT_OUTCOMES[taskType] ?? null;
|
|
98
|
-
}
|
|
99
|
-
function getDefaultOutcome(raw) {
|
|
100
|
-
const lower = raw.toLowerCase();
|
|
101
|
-
const isNativeMeta = /đánh giá|phân tích|cải thiện|fix|native|agent.*inside|cli.*bên trong|phỏng vấn|discovery/i.test(lower);
|
|
102
|
-
if (isNativeMeta) {
|
|
103
|
-
return "Native self-assessment of muonroi-cli with concrete improvements identified and implemented";
|
|
51
|
+
/**
|
|
52
|
+
* Get a default outcome label for well-known task types when no outcome
|
|
53
|
+
* was voiced by the user and no card provided one.
|
|
54
|
+
*/
|
|
55
|
+
export function getDefaultOutcome(taskType, raw) {
|
|
56
|
+
if (raw) {
|
|
57
|
+
const lower = raw.toLowerCase();
|
|
58
|
+
const isNativeMeta = /đánh giá|phân tích|cải thiện|fix|native|agent.*inside|cli.*bên trong|phỏng vấn|discovery/i.test(lower);
|
|
59
|
+
if (isNativeMeta) {
|
|
60
|
+
return "Native self-assessment of the CLI with specific, actionable improvements";
|
|
61
|
+
}
|
|
104
62
|
}
|
|
105
|
-
|
|
63
|
+
const map = {
|
|
64
|
+
analyze: "Detailed analysis with concrete improvement recommendations",
|
|
65
|
+
plan: "Step-by-step plan",
|
|
66
|
+
documentation: "Docs updated",
|
|
67
|
+
debug: "Error resolved, expected behavior restored",
|
|
68
|
+
};
|
|
69
|
+
return map[taskType ?? ""] ?? `Complete: ${(raw ?? "").slice(0, 80)}`;
|
|
106
70
|
}
|
|
107
71
|
//# sourceMappingURL=layer16-clarity.js.map
|
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* src/pil/layer18-acceptance.ts
|
|
3
|
+
*
|
|
4
|
+
* Phase 3 (2026-06-23): acceptance is now model-driven — the model includes
|
|
5
|
+
* acceptance/rejection options in its own ModelCard[]. The CLI no longer
|
|
6
|
+
* builds hardcoded Accept/Adjust/Cancel buttons.
|
|
7
|
+
*
|
|
8
|
+
* What remains here is a simplified summary card builder used by the
|
|
9
|
+
* `showAcceptance` replacement: when feasibility warnings exist, the CLI
|
|
10
|
+
* appends them as context to the model's last card rather than creating a
|
|
11
|
+
* separate acceptance ceremony.
|
|
12
|
+
*/
|
|
2
13
|
import type { AcceptanceCardData, ClarifiedIntent, FeasibilityResult } from "./discovery-types.js";
|
|
3
|
-
export declare function buildAcceptanceCard(intentStatement: string, intent: ClarifiedIntent, feasibility: FeasibilityResult,
|
|
4
|
-
export declare function buildAcceptanceQuestion(card: AcceptanceCardData, questionId: string): CouncilQuestionData;
|
|
14
|
+
export declare function buildAcceptanceCard(intentStatement: string, intent: ClarifiedIntent, feasibility: FeasibilityResult, _raw?: string): AcceptanceCardData;
|
|
@@ -1,14 +1,5 @@
|
|
|
1
|
-
export function buildAcceptanceCard(intentStatement, intent, feasibility,
|
|
1
|
+
export function buildAcceptanceCard(intentStatement, intent, feasibility, _raw) {
|
|
2
2
|
const warnings = [...feasibility.warnings];
|
|
3
|
-
// PIL-L6 fix — detect mismatch between user's raw words and the reframed
|
|
4
|
-
// intent statement. If raw says "ci fail / fix" but statement says
|
|
5
|
-
// "generate / feature implemented", add a loud warning AND surface a hint
|
|
6
|
-
// in the card so the user notices before accepting.
|
|
7
|
-
if (raw) {
|
|
8
|
-
const mismatch = detectIntentMismatch(raw, intentStatement);
|
|
9
|
-
if (mismatch)
|
|
10
|
-
warnings.unshift(mismatch);
|
|
11
|
-
}
|
|
12
3
|
return {
|
|
13
4
|
intentStatement,
|
|
14
5
|
outcome: intent.outcome,
|
|
@@ -16,69 +7,4 @@ export function buildAcceptanceCard(intentStatement, intent, feasibility, raw) {
|
|
|
16
7
|
warnings,
|
|
17
8
|
};
|
|
18
9
|
}
|
|
19
|
-
/**
|
|
20
|
-
* PIL-L6 fix — heuristic mismatch detector. Returns a human-readable warning
|
|
21
|
-
* string when the reframed intent looks wrong relative to the raw prompt.
|
|
22
|
-
* Returns null when no mismatch is detected. Cheap regex-based — no LLM.
|
|
23
|
-
*/
|
|
24
|
-
function detectIntentMismatch(raw, intentStatement) {
|
|
25
|
-
const r = raw.toLowerCase();
|
|
26
|
-
const s = intentStatement.toLowerCase();
|
|
27
|
-
// Debug signals in raw vs. non-debug intent
|
|
28
|
-
const debugSignals = /\b(fail(?:s|ed|ing)?|error|exception|crash|broken|bug|fix\s+(?:the\s+)?(?:ci|build|test|action|workflow|deploy)|sửa\s+lỗi|lỗi|hỏng)\b/i;
|
|
29
|
-
if (debugSignals.test(raw) && !/^debug:/.test(s) && !/(fix|debug|repair|resolve|error|fail)/.test(s)) {
|
|
30
|
-
return `Detected debug/bug-fix signals in your prompt ("${matchedWord(r, debugSignals)}") but intent reframed as "${intentStatement}". Verify before accepting.`;
|
|
31
|
-
}
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
function matchedWord(haystack, re) {
|
|
35
|
-
const m = re.exec(haystack);
|
|
36
|
-
return m?.[0] ?? "";
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Classify a card warning as blocking (should force Adjust default) or
|
|
40
|
-
* informational (Accept default is fine). Intent-mismatch detector output
|
|
41
|
-
* is informational — the card body already surfaces it so the user can see
|
|
42
|
-
* the hint without being routed back into another interview round.
|
|
43
|
-
*/
|
|
44
|
-
function isBlockingWarning(warning) {
|
|
45
|
-
const w = warning.toLowerCase();
|
|
46
|
-
if (w.includes("detected") && (w.includes("signals") || w.includes("verify before accepting"))) {
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
|
-
return true;
|
|
50
|
-
}
|
|
51
|
-
export function buildAcceptanceQuestion(card, questionId) {
|
|
52
|
-
const contextLines = [];
|
|
53
|
-
contextLines.push(`Outcome: ${card.outcome}`);
|
|
54
|
-
contextLines.push(`Scope: ${card.scope.join(", ")}`);
|
|
55
|
-
if (card.warnings.length > 0) {
|
|
56
|
-
contextLines.push(`⚠ ${card.warnings.join("; ")}`);
|
|
57
|
-
}
|
|
58
|
-
const options = [
|
|
59
|
-
{ label: "Accept", value: "accept", kind: "choice", description: "Proceed with this understanding" },
|
|
60
|
-
{ label: "Adjust", value: "adjust", kind: "choice", description: "Let me clarify further" },
|
|
61
|
-
{ label: "Cancel", value: "cancel", kind: "choice", description: "Never mind" },
|
|
62
|
-
];
|
|
63
|
-
// Default-index policy:
|
|
64
|
-
// - No warnings → Accept (0).
|
|
65
|
-
// - Any blocking warning (feasibility text like "infeasible", "blocked by",
|
|
66
|
-
// "cannot") → Adjust (1).
|
|
67
|
-
// - Only informational warnings (intent-mismatch detector output —
|
|
68
|
-
// "Detected ... signals" / "Verify before accepting") → Accept (0).
|
|
69
|
-
// Evidence (session 1f29e238a816): intent-mismatch detector fired on a
|
|
70
|
-
// 4-word follow-up ("Can you fix it?"), forcing Adjust default and a
|
|
71
|
-
// PIL chain that burned 35s on questions the user had already answered.
|
|
72
|
-
const hasBlockingWarning = card.warnings.some((w) => isBlockingWarning(w));
|
|
73
|
-
const defaultIndex = hasBlockingWarning ? 1 : 0;
|
|
74
|
-
return {
|
|
75
|
-
questionId,
|
|
76
|
-
question: `I understand you want to: ${card.intentStatement}`,
|
|
77
|
-
context: contextLines.join("\n"),
|
|
78
|
-
isRequired: true,
|
|
79
|
-
phase: "pil-acceptance",
|
|
80
|
-
options,
|
|
81
|
-
defaultIndex,
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
10
|
//# sourceMappingURL=layer18-acceptance.js.map
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { truncateToBudget } from "./budget.js";
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
// Until WhoAmI ships, L2 relies entirely on L1's per-turn detection.
|
|
2
|
+
// WhoAmI v4.0 (partly wired): ctx.outputStyle now carries the profile baseline
|
|
3
|
+
// from communication.brevity / decision_speed (resolved in layer1-intent.ts via
|
|
4
|
+
// ../ee/who-am-i.ts), so the concise/detailed bias below is already profile-aware
|
|
5
|
+
// without changing this layer — L1's per-turn detection overrides it. Still future:
|
|
6
|
+
// a richer hint built directly from feedback_style (EE emits implicit |
|
|
7
|
+
// precise-correction). NOTE: `work_patterns.delegation_style` is NOT emitted by EE
|
|
8
|
+
// slice-1 — do not wire it until a later EE slice adds it.
|
|
10
9
|
const DEFAULT_PERSONALITY = "balanced";
|
|
11
10
|
const PERSONALITY_HINTS = {
|
|
12
11
|
concise: "[personality: concise — Be direct and terse. Lead with the answer. Skip preamble. " +
|