muonroi-cli 1.7.2 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +122 -122
- 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 +32 -3
- 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 +12 -12
- 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 +56 -21
- 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/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 +55 -60
- 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 +2 -2
- package/dist/src/lsp/manager.test.js +2 -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/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/oauth-callback.js +2 -2
- package/dist/src/mcp/parse-headers.test.js +14 -14
- package/dist/src/mcp/self-verify-jobs.js +1 -3
- package/dist/src/mcp/setup-guide-text.js +74 -74
- package/dist/src/mcp/smoke.test.js +43 -43
- package/dist/src/models/catalog-gemini.test.js +12 -10
- package/dist/src/models/catalog.json +106 -38
- package/dist/src/ops/doctor.js +7 -7
- 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 +2 -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 +1 -0
- package/dist/src/orchestrator/__tests__/stream-runner.test.js +29 -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 +364 -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 +21 -5
- package/dist/src/orchestrator/message-processor.js +219 -2573
- package/dist/src/orchestrator/orchestrator.d.ts +8 -2
- package/dist/src/orchestrator/orchestrator.js +187 -34
- package/dist/src/orchestrator/preprocessor.d.ts +13 -0
- package/dist/src/orchestrator/preprocessor.js +145 -0
- package/dist/src/orchestrator/prompts.d.ts +8 -0
- package/dist/src/orchestrator/prompts.js +76 -60
- 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-model-tier.js +1 -1
- package/dist/src/orchestrator/subagent-compactor.d.ts +14 -0
- package/dist/src/orchestrator/subagent-compactor.js +83 -10
- package/dist/src/orchestrator/subagent-compactor.spec.js +132 -0
- 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 +151 -0
- package/dist/src/orchestrator/tool-engine.js +3079 -0
- package/dist/src/orchestrator/turn-runner-deps.d.ts +1 -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__/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 +99 -44
- 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.js +3 -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/done-gate.js +3 -3
- package/dist/src/product-loop/gather.js +19 -5
- package/dist/src/product-loop/loop-driver.js +20 -20
- package/dist/src/product-loop/progress-snapshot.js +4 -4
- 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/mcp-vision-bridge.js +48 -48
- 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/reporter/index.js +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/scaffold/bb-ecosystem-apply.js +47 -47
- package/dist/src/scaffold/bb-quality-gate.js +5 -5
- package/dist/src/scaffold/continuation-prompt.js +60 -60
- package/dist/src/scaffold/init-new.js +453 -453
- package/dist/src/self-qa/__tests__/scenario-planner.test.js +3 -3
- package/dist/src/self-qa/agentic-loop.js +19 -19
- 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__/migrations.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/interaction-log.js +5 -5
- package/dist/src/storage/migrations.js +122 -122
- package/dist/src/storage/session-experience-store.js +4 -4
- package/dist/src/storage/sessions.js +43 -43
- package/dist/src/storage/transcript-view.js +7 -1
- package/dist/src/storage/transcript.d.ts +1 -0
- package/dist/src/storage/transcript.js +55 -0
- package/dist/src/storage/ui-interaction-log.d.ts +17 -0
- package/dist/src/storage/usage.js +14 -14
- package/dist/src/storage/workspaces.js +12 -12
- 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 +56 -0
- 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 +5 -0
- package/dist/src/tools/registry.js +185 -11
- package/dist/src/types/index.d.ts +7 -1
- 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/council-inspect.js +4 -4
- 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/clipboard-image.js +23 -23
- package/dist/src/utils/llm-deadline.d.ts +9 -1
- package/dist/src/utils/llm-deadline.js +31 -2
- 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 +27 -31
- package/dist/src/utils/settings.js +100 -109
- package/dist/src/utils/side-question.js +2 -2
- package/dist/src/utils/skills.js +3 -3
- package/dist/src/verify/__tests__/coverage-parsers.test.js +30 -30
- 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)
|
|
@@ -1196,40 +1243,40 @@ export async function layer1Intent(ctx, opts = {}) {
|
|
|
1196
1243
|
// touch existing files.
|
|
1197
1244
|
// 0.7 confidence threshold for Pass 2 keyword override remains
|
|
1198
1245
|
// unchanged (HIGH_CONF_THRESHOLD_PASS2 above).
|
|
1199
|
-
const brainRaw = await classifyViaBrain(`You are a multilingual prompt classifier. The user's prompt may be in English, Vietnamese, or a mix of both.
|
|
1200
|
-
Classify the prompt's INTENT (not its language). Reply with TWO lowercase words separated by a comma: <category>,<style>
|
|
1201
|
-
|
|
1202
|
-
Category — pick ONE (listed in neutral order, no precedence):
|
|
1203
|
-
analyze — explain / inspect / review existing code (giải thích, phân tích, review)
|
|
1204
|
-
debug — fix a bug or investigate failure (sửa lỗi, fix bug, lỗi, traceback)
|
|
1205
|
-
generate — create new code/file or add new behavior (tạo, sinh code, viết function mới, thêm)
|
|
1206
|
-
refactor — restructure existing code (tái cấu trúc, refactor)
|
|
1207
|
-
plan — design / roadmap / architecture (kế hoạch, thiết kế, kiến trúc)
|
|
1208
|
-
documentation — write docs/comments (viết docs, comment, jsdoc)
|
|
1209
|
-
general — chitchat OR unclear / ambiguous coding intent
|
|
1210
|
-
|
|
1211
|
-
Rules (Phase 4 4P-2 disambiguation):
|
|
1212
|
-
- Only return refactor when the user EXPLICITLY uses one of: rename, restructure, reorganize, extract, inline, move, migrate, reshape — applied to EXISTING code WITHOUT adding new behavior.
|
|
1213
|
-
- Feature additions ('add flag', 'thêm', 'create endpoint', 'thêm option'), changing a DEFAULT value, adding tests, or improving coverage are 'generate' — NOT refactor.
|
|
1214
|
-
- 'improve', 'change', 'update', 'modify', 'đổi', 'cải thiện' alone do NOT imply refactor — pick the specific category by what the change actually does.
|
|
1215
|
-
- When the request is ambiguous, prefer 'general' over guessing refactor.
|
|
1216
|
-
|
|
1217
|
-
Negative examples (NOT refactor):
|
|
1218
|
-
- "đổi default --max-tool-rounds 8 sang 12" → generate
|
|
1219
|
-
- "improve test coverage" → generate
|
|
1220
|
-
- "tại sao X trả empty" → analyze
|
|
1221
|
-
- "fix CI failing" → debug
|
|
1222
|
-
|
|
1223
|
-
Style — pick ONE:
|
|
1224
|
-
concise (ngắn gọn) | balanced (cân bằng) | detailed (chi tiết)
|
|
1225
|
-
|
|
1226
|
-
Examples:
|
|
1227
|
-
"Refactor this function" → refactor,balanced
|
|
1228
|
-
"tại sao test fail" → debug,balanced
|
|
1229
|
-
"thiết kế hệ thống auth" → plan,detailed
|
|
1230
|
-
"thêm flag --foo" → generate,concise
|
|
1231
|
-
"hi" → general,concise
|
|
1232
|
-
|
|
1246
|
+
const brainRaw = await classifyViaBrain(`You are a multilingual prompt classifier. The user's prompt may be in English, Vietnamese, or a mix of both.
|
|
1247
|
+
Classify the prompt's INTENT (not its language). Reply with TWO lowercase words separated by a comma: <category>,<style>
|
|
1248
|
+
|
|
1249
|
+
Category — pick ONE (listed in neutral order, no precedence):
|
|
1250
|
+
analyze — explain / inspect / review existing code (giải thích, phân tích, review)
|
|
1251
|
+
debug — fix a bug or investigate failure (sửa lỗi, fix bug, lỗi, traceback)
|
|
1252
|
+
generate — create new code/file or add new behavior (tạo, sinh code, viết function mới, thêm)
|
|
1253
|
+
refactor — restructure existing code (tái cấu trúc, refactor)
|
|
1254
|
+
plan — design / roadmap / architecture (kế hoạch, thiết kế, kiến trúc)
|
|
1255
|
+
documentation — write docs/comments (viết docs, comment, jsdoc)
|
|
1256
|
+
general — chitchat OR unclear / ambiguous coding intent
|
|
1257
|
+
|
|
1258
|
+
Rules (Phase 4 4P-2 disambiguation):
|
|
1259
|
+
- Only return refactor when the user EXPLICITLY uses one of: rename, restructure, reorganize, extract, inline, move, migrate, reshape — applied to EXISTING code WITHOUT adding new behavior.
|
|
1260
|
+
- Feature additions ('add flag', 'thêm', 'create endpoint', 'thêm option'), changing a DEFAULT value, adding tests, or improving coverage are 'generate' — NOT refactor.
|
|
1261
|
+
- 'improve', 'change', 'update', 'modify', 'đổi', 'cải thiện' alone do NOT imply refactor — pick the specific category by what the change actually does.
|
|
1262
|
+
- When the request is ambiguous, prefer 'general' over guessing refactor.
|
|
1263
|
+
|
|
1264
|
+
Negative examples (NOT refactor):
|
|
1265
|
+
- "đổi default --max-tool-rounds 8 sang 12" → generate
|
|
1266
|
+
- "improve test coverage" → generate
|
|
1267
|
+
- "tại sao X trả empty" → analyze
|
|
1268
|
+
- "fix CI failing" → debug
|
|
1269
|
+
|
|
1270
|
+
Style — pick ONE:
|
|
1271
|
+
concise (ngắn gọn) | balanced (cân bằng) | detailed (chi tiết)
|
|
1272
|
+
|
|
1273
|
+
Examples:
|
|
1274
|
+
"Refactor this function" → refactor,balanced
|
|
1275
|
+
"tại sao test fail" → debug,balanced
|
|
1276
|
+
"thiết kế hệ thống auth" → plan,detailed
|
|
1277
|
+
"thêm flag --foo" → generate,concise
|
|
1278
|
+
"hi" → general,concise
|
|
1279
|
+
|
|
1233
1280
|
Prompt: "${ctx.raw.slice(0, 500)}"`, 1500);
|
|
1234
1281
|
if (brainRaw) {
|
|
1235
1282
|
pass3LegacyTaskSucceeded = true;
|
|
@@ -1280,9 +1327,9 @@ Prompt: "${ctx.raw.slice(0, 500)}"`, 1500);
|
|
|
1280
1327
|
if (pass3LegacyTaskAttempted) {
|
|
1281
1328
|
legacyBrainAttempted = true;
|
|
1282
1329
|
pass3LegacyStyleAttempted = true;
|
|
1283
|
-
const brainRawStyle = await classifyViaBrain(`Detect the user's preferred output style. The prompt may be EN or VN.
|
|
1284
|
-
Reply with ONE word: concise (ngắn gọn) | balanced (bình thường) | detailed (chi tiết).
|
|
1285
|
-
|
|
1330
|
+
const brainRawStyle = await classifyViaBrain(`Detect the user's preferred output style. The prompt may be EN or VN.
|
|
1331
|
+
Reply with ONE word: concise (ngắn gọn) | balanced (bình thường) | detailed (chi tiết).
|
|
1332
|
+
|
|
1286
1333
|
Prompt: "${ctx.raw.slice(0, 300)}"`, 800);
|
|
1287
1334
|
if (brainRawStyle) {
|
|
1288
1335
|
pass3LegacyStyleSucceeded = true;
|
|
@@ -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;
|