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
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, test, vi } from "vitest";
|
|
2
|
+
import { sessionRecallLedger } from "../../ee/recall-ledger.js";
|
|
2
3
|
import { layer3EeInjection, RECALL_FEEDBACK_NUDGE } from "../layer3-ee-injection.js";
|
|
3
4
|
vi.mock("../../ee/bridge.js", () => ({
|
|
4
5
|
searchByText: vi.fn().mockResolvedValue([]),
|
|
@@ -22,6 +23,9 @@ describe("layer3EeInjection (bridge-based)", () => {
|
|
|
22
23
|
beforeEach(() => {
|
|
23
24
|
vi.mocked(searchByText).mockReset();
|
|
24
25
|
vi.mocked(searchByText).mockResolvedValue([]);
|
|
26
|
+
// The recall-feedback ledger is a process singleton; reset so passive-injection
|
|
27
|
+
// debt recorded by one test does not lengthen the pending reminder in the next.
|
|
28
|
+
sessionRecallLedger.reset();
|
|
25
29
|
});
|
|
26
30
|
test("Test 1: returns enriched context with hints when searchByText returns points with payload.text", async () => {
|
|
27
31
|
vi.mocked(searchByText).mockResolvedValue([
|
|
@@ -93,10 +97,10 @@ describe("layer3EeInjection (bridge-based)", () => {
|
|
|
93
97
|
const chars = parseInt(charsMatch[1], 10);
|
|
94
98
|
// Two parallel collections, each at 15% of budget: 15% of 100 tokens * 4 chars/token
|
|
95
99
|
// = 60 chars per block + 3 for "..." suffix, joined with newline. Allow generous
|
|
96
|
-
// ceiling for header text + 2 blocks, PLUS the
|
|
97
|
-
//
|
|
98
|
-
// regression would blow well past this bound regardless.
|
|
99
|
-
expect(chars).toBeLessThanOrEqual(
|
|
100
|
+
// ceiling for header text + 2 blocks, PLUS the dynamic pending-feedback reminder
|
|
101
|
+
// (≤5 [id collection] lines) that replaced the fixed nudge. The 2000-char input
|
|
102
|
+
// means a truncation regression would blow well past this bound regardless.
|
|
103
|
+
expect(chars).toBeLessThanOrEqual(600);
|
|
100
104
|
}
|
|
101
105
|
}
|
|
102
106
|
});
|
|
@@ -137,6 +141,65 @@ describe("Layer 3 formatter mode (ctx._brainData populated)", () => {
|
|
|
137
141
|
expect(result.enriched).toContain("mock fs in unit tests");
|
|
138
142
|
expect(result.t1Rules).toEqual(["never skip tests"]);
|
|
139
143
|
});
|
|
144
|
+
test("unified path: records rateable points (with id) into the ledger + names [id collection] in the reminder", async () => {
|
|
145
|
+
// Symmetric with the legacy-path recall-loop closure. When the server (PIL
|
|
146
|
+
// schema_version 1.1+) attributes points with id/collection, the unified
|
|
147
|
+
// formatter must record them as pending debt and surface an actionable reminder.
|
|
148
|
+
sessionRecallLedger.reset();
|
|
149
|
+
const { layer3EeInjection } = await import("../layer3-ee-injection.js");
|
|
150
|
+
const ctx = {
|
|
151
|
+
raw: "x",
|
|
152
|
+
enriched: "x",
|
|
153
|
+
taskType: "debug",
|
|
154
|
+
domain: null,
|
|
155
|
+
confidence: 0.85,
|
|
156
|
+
outputStyle: "balanced",
|
|
157
|
+
tokenBudget: 2000,
|
|
158
|
+
metrics: null,
|
|
159
|
+
layers: [],
|
|
160
|
+
_brainData: {
|
|
161
|
+
t0_principles: [{ text: "always run tests", score: 0.9, id: "pr1", collection: "experience-principles" }],
|
|
162
|
+
t1_rules: [],
|
|
163
|
+
t2_patterns: [{ text: "mock fs in unit tests", score: 0.7, id: "be1", collection: "experience-behavioral" }],
|
|
164
|
+
retrieval_skipped_reason: null,
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
const result = await layer3EeInjection(ctx);
|
|
168
|
+
// Inline [id:..] handle rendered so the reminder refers to something visible.
|
|
169
|
+
expect(result.enriched).toContain("[id:pr1]");
|
|
170
|
+
// Dynamic reminder names the actual [id collection] so ee_feedback is actionable.
|
|
171
|
+
expect(result.enriched).toMatch(/ee_feedback\(id, collection, followed\|ignored\|noise\)/);
|
|
172
|
+
expect(result.enriched).toContain("[pr1 experience-principles]");
|
|
173
|
+
expect(result.enriched).toContain("[be1 experience-behavioral]");
|
|
174
|
+
// Both points recorded as rateable pending debt.
|
|
175
|
+
expect(sessionRecallLedger.pendingCount()).toBe(2);
|
|
176
|
+
});
|
|
177
|
+
test("unified path: no id (older server) renders text but stays unrateable (static nudge)", async () => {
|
|
178
|
+
sessionRecallLedger.reset();
|
|
179
|
+
const { layer3EeInjection } = await import("../layer3-ee-injection.js");
|
|
180
|
+
const ctx = {
|
|
181
|
+
raw: "x",
|
|
182
|
+
enriched: "x",
|
|
183
|
+
taskType: "debug",
|
|
184
|
+
domain: null,
|
|
185
|
+
confidence: 0.85,
|
|
186
|
+
outputStyle: "balanced",
|
|
187
|
+
tokenBudget: 2000,
|
|
188
|
+
metrics: null,
|
|
189
|
+
layers: [],
|
|
190
|
+
_brainData: {
|
|
191
|
+
t0_principles: [{ text: "always run tests", score: 0.9 }],
|
|
192
|
+
t1_rules: [],
|
|
193
|
+
t2_patterns: [{ text: "mock fs in unit tests", score: 0.7 }],
|
|
194
|
+
retrieval_skipped_reason: null,
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
const result = await layer3EeInjection(ctx);
|
|
198
|
+
expect(result.enriched).toContain("always run tests");
|
|
199
|
+
// No ids → nothing recorded; the static nudge is the fallback.
|
|
200
|
+
expect(sessionRecallLedger.pendingCount()).toBe(0);
|
|
201
|
+
expect(result.enriched).toContain(RECALL_FEEDBACK_NUDGE);
|
|
202
|
+
});
|
|
140
203
|
test("emits no block when ctx._brainData is null AND legacy disabled by flag", async () => {
|
|
141
204
|
const { layer3EeInjection } = await import("../layer3-ee-injection.js");
|
|
142
205
|
const ctx = {
|
|
@@ -24,6 +24,7 @@ vi.mock("../../storage/interaction-log.js", () => ({
|
|
|
24
24
|
vi.mock("../../ee/intercept.js", () => ({
|
|
25
25
|
updateLastSurfacedState: vi.fn(),
|
|
26
26
|
}));
|
|
27
|
+
import { sessionRecallLedger } from "../../ee/recall-ledger.js";
|
|
27
28
|
import { layer3EeInjection } from "../layer3-ee-injection.js";
|
|
28
29
|
const BASE_CTX = {
|
|
29
30
|
raw: "test prompt for experience injection",
|
|
@@ -41,6 +42,9 @@ describe("layer3 experience_injected chunk emission (CQ-16b)", () => {
|
|
|
41
42
|
beforeEach(() => {
|
|
42
43
|
capturedSinkCalls.length = 0;
|
|
43
44
|
mockSearchByText.mockResolvedValue([]);
|
|
45
|
+
// Reset the process-singleton recall ledger so pending debt from a prior test
|
|
46
|
+
// does not change the dynamic feedback reminder content of the next.
|
|
47
|
+
sessionRecallLedger.reset();
|
|
44
48
|
});
|
|
45
49
|
it("emits experience_injected chunk when searchByText returns high-score point", async () => {
|
|
46
50
|
mockSearchByText.mockResolvedValue([
|
|
@@ -103,8 +107,16 @@ describe("layer3 experience_injected chunk emission (CQ-16b)", () => {
|
|
|
103
107
|
collection: "experience-behavioral",
|
|
104
108
|
},
|
|
105
109
|
]);
|
|
106
|
-
const result = await layer3EeInjection(BASE_CTX);
|
|
107
|
-
|
|
110
|
+
const result = await layer3EeInjection({ ...BASE_CTX, sessionId: "test-session-nudge" });
|
|
111
|
+
// The dynamic pending-feedback reminder replaced the fixed nudge when the ledger
|
|
112
|
+
// is enabled (default soft); it names the actual [id collection] so ee_feedback is
|
|
113
|
+
// actionable. Accept either form (reminder when the ledger recorded debt, or the
|
|
114
|
+
// static fallback when disabled).
|
|
115
|
+
expect(result.enriched).toMatch(/ee_feedback\(id, (collection, )?followed\|ignored\|noise\)/);
|
|
116
|
+
// Reminder names the actual [id collection]; the mock returns the same point in
|
|
117
|
+
// both search arms so the principles arm wins first-sighting (real searches return
|
|
118
|
+
// distinct points per collection) — assert id-named, collection-agnostic.
|
|
119
|
+
expect(result.enriched).toMatch(/\[p1 experience-(principles|behavioral)\]/);
|
|
108
120
|
});
|
|
109
121
|
it("does NOT emit experience_injected when searchByText returns empty array", async () => {
|
|
110
122
|
mockSearchByText.mockResolvedValue([]);
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from "vitest";
|
|
2
2
|
vi.mock("../../ee/bridge.js", () => ({
|
|
3
3
|
routeTask: vi.fn().mockResolvedValue(null),
|
|
4
|
+
// WhoAmI v4.0: L4 reads delegation_style to bias a 'discuss' phase. Default null
|
|
5
|
+
// = fail-open, so every pre-existing test below behaves exactly as before.
|
|
6
|
+
getWhoAmIProfile: vi.fn(() => null),
|
|
4
7
|
}));
|
|
8
|
+
import { getWhoAmIProfile } from "../../ee/bridge.js";
|
|
5
9
|
import { layer4Gsd } from "../layer4-gsd.js";
|
|
6
10
|
function makeCtx(overrides = {}) {
|
|
7
11
|
return {
|
|
@@ -139,6 +143,32 @@ describe("layer4Gsd (playbook)", () => {
|
|
|
139
143
|
const result = await layer4Gsd(makeCtx({ raw, enriched: raw, taskType: "refactor", intentKind: "task", deliverableKind: "code" }));
|
|
140
144
|
expect(result.enriched).not.toContain("QUESTION / explanatory");
|
|
141
145
|
});
|
|
146
|
+
it("autonomous delegation drops a 'discuss' phase (WhoAmI v4.0 bias toward direct)", async () => {
|
|
147
|
+
vi.mocked(getWhoAmIProfile).mockReturnValueOnce({
|
|
148
|
+
level: "standard",
|
|
149
|
+
dims: { "work_patterns.delegation_style": { value: "autonomous", confidence: 0.68, samples: 19 } },
|
|
150
|
+
});
|
|
151
|
+
const result = await layer4Gsd(makeCtx({ gsdPhase: "discuss", raw: "do the thing" }));
|
|
152
|
+
expect(result.gsdPhase ?? null).toBeNull();
|
|
153
|
+
const layer = result.layers.find((l) => l.name === "gsd-workflow-structuring");
|
|
154
|
+
expect(layer.delta).toContain("phase=none");
|
|
155
|
+
expect(layer.delta).toContain("autonomous:skip-discuss");
|
|
156
|
+
});
|
|
157
|
+
it("collaborative delegation keeps the 'discuss' phase", async () => {
|
|
158
|
+
vi.mocked(getWhoAmIProfile).mockReturnValueOnce({
|
|
159
|
+
level: "standard",
|
|
160
|
+
dims: { "work_patterns.delegation_style": { value: "collaborative", confidence: 0.7, samples: 20 } },
|
|
161
|
+
});
|
|
162
|
+
const result = await layer4Gsd(makeCtx({ gsdPhase: "discuss", raw: "do the thing" }));
|
|
163
|
+
expect(result.gsdPhase).toBe("discuss");
|
|
164
|
+
const layer = result.layers.find((l) => l.name === "gsd-workflow-structuring");
|
|
165
|
+
expect(layer.delta).toContain("phase=discuss");
|
|
166
|
+
});
|
|
167
|
+
it("absent profile leaves 'discuss' untouched (fail-open default)", async () => {
|
|
168
|
+
// getWhoAmIProfile defaults to null in the mock — the phase must be unchanged.
|
|
169
|
+
const result = await layer4Gsd(makeCtx({ gsdPhase: "discuss", raw: "do the thing" }));
|
|
170
|
+
expect(result.gsdPhase).toBe("discuss");
|
|
171
|
+
});
|
|
142
172
|
it("uses ctx.gsdPhase from L1 (unified path) without calling routeTask", async () => {
|
|
143
173
|
const { routeTask } = await import("../../ee/bridge.js");
|
|
144
174
|
vi.mocked(routeTask).mockClear();
|
|
@@ -3,6 +3,9 @@ vi.mock("../../ee/bridge.js", () => ({
|
|
|
3
3
|
getEmbeddingRaw: vi.fn().mockResolvedValue(null),
|
|
4
4
|
searchCollection: vi.fn().mockResolvedValue([]),
|
|
5
5
|
searchByText: vi.fn().mockResolvedValue([]),
|
|
6
|
+
// WhoAmI v4.0: L5 reads session_length to tune the resume-digest stale window.
|
|
7
|
+
// Default null = fail-open → 30m default, so the pre-v4.0 assertions below hold.
|
|
8
|
+
getWhoAmIProfile: vi.fn(() => null),
|
|
6
9
|
}));
|
|
7
10
|
vi.mock("node:fs", async (importOriginal) => {
|
|
8
11
|
const actual = await importOriginal();
|
|
@@ -16,7 +19,8 @@ vi.mock("node:fs", async (importOriginal) => {
|
|
|
16
19
|
},
|
|
17
20
|
};
|
|
18
21
|
});
|
|
19
|
-
import {
|
|
22
|
+
import { getWhoAmIProfile } from "../../ee/bridge.js";
|
|
23
|
+
import { layer5Context, staleThresholdMsForSessionLength } from "../layer5-context.js";
|
|
20
24
|
function makeCtx(overrides = {}) {
|
|
21
25
|
return {
|
|
22
26
|
raw: "continue working on the auth module",
|
|
@@ -133,5 +137,39 @@ describe("layer5Context", () => {
|
|
|
133
137
|
expect(result.enriched).toContain("already enriched prompt");
|
|
134
138
|
expect(result.enriched).toContain("[flow-context:");
|
|
135
139
|
});
|
|
140
|
+
// WhoAmI v4.0: session_length tunes the resume-digest stale window. A 45-minute-old
|
|
141
|
+
// digest is stale at the 30m default but FRESH for a long-session user (window→60m).
|
|
142
|
+
// This proves the profile actually flows through layer5Context, not just the helper.
|
|
143
|
+
it("long session_length relaxes the stale window — 45m digest is not stale", async () => {
|
|
144
|
+
vi.mocked(getWhoAmIProfile).mockReturnValueOnce({
|
|
145
|
+
level: "minimal",
|
|
146
|
+
dims: { "work_patterns.session_length": { value: "long", confidence: 0.5, samples: 16 } },
|
|
147
|
+
});
|
|
148
|
+
const result = await layer5Context(makeCtx({ resumeDigest: "Deep-work session context", digestAgeMs: 45 * 60 * 1000 }));
|
|
149
|
+
expect(result.enriched).not.toContain("stale");
|
|
150
|
+
const layer = result.layers.find((l) => l.name === "context-enrichment");
|
|
151
|
+
expect(layer.delta).toContain("window=60m");
|
|
152
|
+
expect(layer.delta).not.toContain(",stale");
|
|
153
|
+
});
|
|
154
|
+
it("short session_length tightens the stale window — 20m digest is stale", async () => {
|
|
155
|
+
vi.mocked(getWhoAmIProfile).mockReturnValueOnce({
|
|
156
|
+
level: "minimal",
|
|
157
|
+
dims: { "work_patterns.session_length": { value: "short", confidence: 0.5, samples: 16 } },
|
|
158
|
+
});
|
|
159
|
+
const result = await layer5Context(makeCtx({ resumeDigest: "Quick-burst session context", digestAgeMs: 20 * 60 * 1000 }));
|
|
160
|
+
expect(result.enriched).toContain("stale");
|
|
161
|
+
const layer = result.layers.find((l) => l.name === "context-enrichment");
|
|
162
|
+
expect(layer.delta).toContain("window=15m");
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
describe("staleThresholdMsForSessionLength — pure session_length → stale window mapping", () => {
|
|
166
|
+
it("long → 60m, short → 15m, medium/absent/unknown → 30m default (fail-open)", () => {
|
|
167
|
+
expect(staleThresholdMsForSessionLength("long")).toBe(60 * 60 * 1000);
|
|
168
|
+
expect(staleThresholdMsForSessionLength("short")).toBe(15 * 60 * 1000);
|
|
169
|
+
expect(staleThresholdMsForSessionLength("medium")).toBe(30 * 60 * 1000);
|
|
170
|
+
expect(staleThresholdMsForSessionLength(undefined)).toBe(30 * 60 * 1000);
|
|
171
|
+
expect(staleThresholdMsForSessionLength(null)).toBe(30 * 60 * 1000);
|
|
172
|
+
expect(staleThresholdMsForSessionLength("telegraphic")).toBe(30 * 60 * 1000);
|
|
173
|
+
});
|
|
136
174
|
});
|
|
137
175
|
//# sourceMappingURL=layer5-context.test.js.map
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { getWhoAmIProfile } from "../../ee/bridge.js";
|
|
2
3
|
import { applyPilSuffix, getResponseToolSet, isImplementationIntent, isQuestionLike, layer6Output, } from "../layer6-output.js";
|
|
3
|
-
// Mock bridge for PIL-03 classifyViaBrain tests
|
|
4
|
+
// Mock bridge for PIL-03 classifyViaBrain tests. getWhoAmIProfile defaults to null
|
|
5
|
+
// (fail-open) so applyPilSuffix never reads the real on-device profile during tests.
|
|
4
6
|
vi.mock("../../ee/bridge.js", () => ({
|
|
5
7
|
classifyViaBrain: vi.fn().mockResolvedValue(null),
|
|
8
|
+
getWhoAmIProfile: vi.fn(() => null),
|
|
6
9
|
}));
|
|
7
10
|
async function getMockBrain() {
|
|
8
11
|
const { classifyViaBrain } = await import("../../ee/bridge.js");
|
|
@@ -434,4 +437,29 @@ describe("isImplementationIntent — improve / cải thiện (regression: sessio
|
|
|
434
437
|
expect(isImplementationIntent("why does the suite fail — break it down")).toBe(false);
|
|
435
438
|
});
|
|
436
439
|
});
|
|
440
|
+
describe("applyPilSuffix — WhoAmI feedback_style correction-affordance", () => {
|
|
441
|
+
const withFeedback = (value) => ({
|
|
442
|
+
level: "standard",
|
|
443
|
+
dims: { "communication.feedback_style": { value, confidence: 0.7, samples: 20 } },
|
|
444
|
+
});
|
|
445
|
+
// Reset around each test so a mockReturnValue never leaks into (or out of) this
|
|
446
|
+
// block — clearAllMocks elsewhere only clears history, not the return override.
|
|
447
|
+
beforeEach(() => vi.mocked(getWhoAmIProfile).mockReturnValue(null));
|
|
448
|
+
afterEach(() => vi.mocked(getWhoAmIProfile).mockReturnValue(null));
|
|
449
|
+
it("precise-correction + action task (refactor) → AUDITABLE CHANGES rule", () => {
|
|
450
|
+
vi.mocked(getWhoAmIProfile).mockReturnValue(withFeedback("precise-correction"));
|
|
451
|
+
expect(applyPilSuffix("SYS", makeCtx("refactor"))).toContain("AUDITABLE CHANGES");
|
|
452
|
+
});
|
|
453
|
+
it("precise-correction + non-action task (analyze) → no rule (diffs don't apply)", () => {
|
|
454
|
+
vi.mocked(getWhoAmIProfile).mockReturnValue(withFeedback("precise-correction"));
|
|
455
|
+
expect(applyPilSuffix("SYS", makeCtx("analyze"))).not.toContain("AUDITABLE CHANGES");
|
|
456
|
+
});
|
|
457
|
+
it("implicit feedback → no rule (intentionally unwired — covered by brevity/delegation)", () => {
|
|
458
|
+
vi.mocked(getWhoAmIProfile).mockReturnValue(withFeedback("implicit"));
|
|
459
|
+
expect(applyPilSuffix("SYS", makeCtx("debug"))).not.toContain("AUDITABLE CHANGES");
|
|
460
|
+
});
|
|
461
|
+
it("absent profile → no rule (fail-open)", () => {
|
|
462
|
+
expect(applyPilSuffix("SYS", makeCtx("generate"))).not.toContain("AUDITABLE CHANGES");
|
|
463
|
+
});
|
|
464
|
+
});
|
|
437
465
|
//# sourceMappingURL=layer6-output.test.js.map
|
|
@@ -17,6 +17,8 @@ vi.mock("../../ee/bridge.js", () => ({
|
|
|
17
17
|
searchCollection: vi.fn().mockResolvedValue([]),
|
|
18
18
|
getEmbeddingRaw: vi.fn().mockResolvedValue(null),
|
|
19
19
|
routeTask: vi.fn().mockResolvedValue(null),
|
|
20
|
+
getWhoAmIProfile: vi.fn(() => null),
|
|
21
|
+
outputStyleFromProfile: vi.fn(() => null),
|
|
20
22
|
}));
|
|
21
23
|
import { applyPilSuffix, runPipeline } from "../index.js";
|
|
22
24
|
beforeEach(() => {
|
|
@@ -27,7 +29,7 @@ describe("PIL orchestrator contract", () => {
|
|
|
27
29
|
const ctx = await runPipeline("refactor this function");
|
|
28
30
|
// Layer 2 personality now appends hints, so enriched starts with raw
|
|
29
31
|
expect(ctx.enriched.startsWith("refactor this function")).toBe(true);
|
|
30
|
-
expect(ctx.layers).toHaveLength(
|
|
32
|
+
expect(ctx.layers).toHaveLength(7);
|
|
31
33
|
});
|
|
32
34
|
it("applyPilSuffix appends OUTPUT RULES suffix for coding taskType (non-null)", () => {
|
|
33
35
|
const codingCtx = {
|
|
@@ -8,6 +8,8 @@ vi.mock("../../ee/bridge.js", () => ({
|
|
|
8
8
|
searchCollection: vi.fn().mockResolvedValue([]),
|
|
9
9
|
getEmbeddingRaw: vi.fn().mockResolvedValue(null),
|
|
10
10
|
routeTask: vi.fn().mockResolvedValue(null),
|
|
11
|
+
getWhoAmIProfile: vi.fn(() => null),
|
|
12
|
+
outputStyleFromProfile: vi.fn(() => null),
|
|
11
13
|
}));
|
|
12
14
|
import { classify } from "../../router/classifier/index.js";
|
|
13
15
|
import { runPipeline } from "../pipeline.js";
|
|
@@ -18,10 +20,10 @@ beforeEach(() => {
|
|
|
18
20
|
mockClassify.mockReturnValue({ tier: "hot", confidence: 0.85, reason: "regex:refactor" });
|
|
19
21
|
});
|
|
20
22
|
describe("runPipeline()", () => {
|
|
21
|
-
it("returns PipelineContext with
|
|
23
|
+
it("returns PipelineContext with 7 LayerResults for normal input", async () => {
|
|
22
24
|
const ctx = await runPipeline("refactor this function");
|
|
23
25
|
expect(ctx.raw).toBe("refactor this function");
|
|
24
|
-
expect(ctx.layers).toHaveLength(
|
|
26
|
+
expect(ctx.layers).toHaveLength(7);
|
|
25
27
|
});
|
|
26
28
|
it("returns enriched that starts with raw (layers may append hints)", async () => {
|
|
27
29
|
const ctx = await runPipeline("some prompt");
|
|
@@ -44,24 +46,25 @@ describe("runPipeline()", () => {
|
|
|
44
46
|
const ctx = await runPipeline("");
|
|
45
47
|
expect(ctx.raw).toBe("");
|
|
46
48
|
expect(ctx.enriched.startsWith(ctx.raw)).toBe(true);
|
|
47
|
-
expect(ctx.layers).toHaveLength(
|
|
49
|
+
expect(ctx.layers).toHaveLength(7);
|
|
48
50
|
});
|
|
49
51
|
it("conversational turn (taskType=null) skips layers 2-5 with delta=skipped:null-taskType", async () => {
|
|
50
52
|
mockClassify.mockReturnValue({ tier: "abstain", confidence: 0.2, reason: "low-confidence" });
|
|
51
53
|
const ctx = await runPipeline("hello how are you");
|
|
52
|
-
expect(ctx.layers).toHaveLength(
|
|
54
|
+
expect(ctx.layers).toHaveLength(7);
|
|
53
55
|
expect(ctx.layers[1].delta).toBe("skipped:null-taskType");
|
|
54
56
|
expect(ctx.layers[2].delta).toBe("skipped:null-taskType");
|
|
55
57
|
expect(ctx.layers[3].delta).toBe("skipped:null-taskType");
|
|
56
58
|
expect(ctx.layers[4].delta).toBe("skipped:null-taskType");
|
|
59
|
+
expect(ctx.layers[5].delta).toBe("skipped:null-taskType");
|
|
57
60
|
expect(ctx.taskType).toBeNull();
|
|
58
61
|
});
|
|
59
|
-
it("coding task runs all
|
|
62
|
+
it("coding task runs all 7 layers normally (no skip)", async () => {
|
|
60
63
|
const ctx = await runPipeline("refactor this function");
|
|
61
|
-
expect(ctx.layers).toHaveLength(
|
|
64
|
+
expect(ctx.layers).toHaveLength(7);
|
|
62
65
|
expect(ctx.taskType).toBe("refactor");
|
|
63
|
-
// layers 2-5 should NOT have skipped delta
|
|
64
|
-
for (let i = 1; i <=
|
|
66
|
+
// layers 2-5 (which include indices 1 to 5) should NOT have skipped delta
|
|
67
|
+
for (let i = 1; i <= 5; i++) {
|
|
65
68
|
expect(ctx.layers[i].delta).not.toBe("skipped:null-taskType");
|
|
66
69
|
}
|
|
67
70
|
});
|
|
@@ -172,6 +172,7 @@ describe("schemas validate correct input", () => {
|
|
|
172
172
|
expect(result.success).toBe(false);
|
|
173
173
|
});
|
|
174
174
|
});
|
|
175
|
+
import { normalizeStructuredResponseTaskType } from "../response-tools.js";
|
|
175
176
|
describe("respond_general catch-all tool", () => {
|
|
176
177
|
it("respond_general tool exists with correct schema", () => {
|
|
177
178
|
const tools = buildResponseTools("general");
|
|
@@ -187,4 +188,55 @@ describe("respond_general catch-all tool", () => {
|
|
|
187
188
|
expect(isResponseTool("respond_general")).toBe(true);
|
|
188
189
|
});
|
|
189
190
|
});
|
|
191
|
+
describe("normalizeStructuredResponseTaskType", () => {
|
|
192
|
+
// Regression: session 48d22fe436f6 — model called respond_analyze but sent
|
|
193
|
+
// { response: "..." } (general shape). TUI rendered empty findings box.
|
|
194
|
+
it("normalizes 'analyze' → 'general' when findings missing but response present", () => {
|
|
195
|
+
expect(normalizeStructuredResponseTaskType("analyze", { response: "Some analysis text" })).toBe("general");
|
|
196
|
+
});
|
|
197
|
+
it("keeps 'analyze' when findings array is present", () => {
|
|
198
|
+
expect(normalizeStructuredResponseTaskType("analyze", {
|
|
199
|
+
findings: [{ text: "issue", evidence: "file:1", severity: "high" }],
|
|
200
|
+
})).toBe("analyze");
|
|
201
|
+
});
|
|
202
|
+
it("normalizes 'debug' → 'general' when root_cause missing but response present", () => {
|
|
203
|
+
expect(normalizeStructuredResponseTaskType("debug", { response: "Bug is in the store" })).toBe("general");
|
|
204
|
+
});
|
|
205
|
+
it("keeps 'debug' when root_cause is present", () => {
|
|
206
|
+
expect(normalizeStructuredResponseTaskType("debug", {
|
|
207
|
+
hypothesis: "race condition",
|
|
208
|
+
root_cause: "shared mutable state",
|
|
209
|
+
fix: { file: "src/a.ts", diff: "+x" },
|
|
210
|
+
verify_command: "bun test",
|
|
211
|
+
})).toBe("debug");
|
|
212
|
+
});
|
|
213
|
+
it("normalizes 'plan' → 'general' when steps missing but response present", () => {
|
|
214
|
+
expect(normalizeStructuredResponseTaskType("plan", { response: "Step 1: do A" })).toBe("general");
|
|
215
|
+
});
|
|
216
|
+
it("normalizes 'refactor' → 'general' when changes missing but response present", () => {
|
|
217
|
+
expect(normalizeStructuredResponseTaskType("refactor", { response: "Refactored X" })).toBe("general");
|
|
218
|
+
});
|
|
219
|
+
it("normalizes 'documentation' → 'general' when content missing but response present", () => {
|
|
220
|
+
expect(normalizeStructuredResponseTaskType("documentation", { response: "Docs here" })).toBe("general");
|
|
221
|
+
});
|
|
222
|
+
it("normalizes 'generate' → 'general' when files missing but response present", () => {
|
|
223
|
+
expect(normalizeStructuredResponseTaskType("generate", { response: "Generated code" })).toBe("general");
|
|
224
|
+
});
|
|
225
|
+
it("keeps 'general' unchanged always", () => {
|
|
226
|
+
expect(normalizeStructuredResponseTaskType("general", { response: "hello" })).toBe("general");
|
|
227
|
+
expect(normalizeStructuredResponseTaskType("general", {})).toBe("general");
|
|
228
|
+
});
|
|
229
|
+
it("does NOT normalize when response field is empty string", () => {
|
|
230
|
+
expect(normalizeStructuredResponseTaskType("analyze", { response: "" })).toBe("analyze");
|
|
231
|
+
});
|
|
232
|
+
it("does NOT normalize when response field is whitespace-only", () => {
|
|
233
|
+
expect(normalizeStructuredResponseTaskType("analyze", { response: " " })).toBe("analyze");
|
|
234
|
+
});
|
|
235
|
+
it("does NOT normalize when response field is missing entirely", () => {
|
|
236
|
+
expect(normalizeStructuredResponseTaskType("analyze", { summary: "Some summary" })).toBe("analyze");
|
|
237
|
+
});
|
|
238
|
+
it("keeps unknown taskType unchanged", () => {
|
|
239
|
+
expect(normalizeStructuredResponseTaskType("unknown_type", { response: "hello" })).toBe("unknown_type");
|
|
240
|
+
});
|
|
241
|
+
});
|
|
190
242
|
//# sourceMappingURL=response-tools.test.js.map
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
* one imperative line targeting that phase's most damaging failure mode. Kept
|
|
38
38
|
* tight (primacy matters more than detail; tokens are the cost).
|
|
39
39
|
*/
|
|
40
|
-
export declare const AGENT_OPERATING_CONTRACT = "[AGENT OPERATING CONTRACT \u2014 read first; applies to every step]\n\n1. BEFORE ACTING: do only what was asked. Never assume scope or facts \u2014 if ambiguous, ask or use defaults; never invent requirements.\n2. READING: base statements on what you read/ran THIS turn. Do not infer contents of files you did not open.\n3. EXECUTING: smallest correct change; never widen scope or mask failures (no `|| true`, skipped tests, or swallowed catch).\n4. WHEN UNSURE: verify and cross-check BEFORE concluding.
|
|
40
|
+
export declare const AGENT_OPERATING_CONTRACT = "[AGENT OPERATING CONTRACT \u2014 read first; applies to every step]\n\n1. BEFORE ACTING: do only what was asked. Never assume scope or facts \u2014 if ambiguous, ask or use defaults; never invent requirements. RESEARCH FIRST: explore code (read/grep) and recall EE brain before editing. RECALL FIRST: ee.query in unfamiliar areas to surface past lessons.\n2. READING: base statements on what you read/ran THIS turn. Do not infer contents of files you did not open.\n3. EXECUTING: smallest correct change; never widen scope or mask failures (no `|| true`, skipped tests, or swallowed catch).\n4. WHEN UNSURE: verify and cross-check BEFORE concluding. Reading code is not proof \u2014 reproduce the bug.\n5. REPORTING: answer ONLY what was asked. Every fact or file:line MUST come from this turn; else label \"unverified\"; do not guess. Synthesize evidence gracefully \u2014 do NOT dump massive verbatim tool outputs into the final answer. Cite concise file:line references. Never claim a build/test ran, or describe edits, you did not actually do this turn; if a check can't run, fix it or say so \u2014 don't imply success.\n\n6. LANGUAGE: Reply in user's detected language for final output. Internal reasoning, tools, and code remain in English.\n\n7. ANTI-M\u00D9 / COMPACTION: On compaction, emit PRESERVE_FULL_CONTEXT (veto) or KEEP_TOOL_IDS (from stub id=) to protect results. Use ee_query with \"tool-artifact id=XXX\" to re-hydrate. Self-check via EE checkpoints. Suggest /compact near tool limits.\n\n8. GIT SAFETY: never push on red \u2014 run the check, await its result in a SEPARATE step, confirm 0 failures, then push. Never `git add -A`/`commit -a`; stage explicitly so secrets (.env, .muonroi-cli/, keys) aren't committed. Never `--no-verify`.\n\n9. VERIFICATION: when finishing a task, ALWAYS self-verify your work. Use the `selfverify_*` native tools (start/status/result) to run the QA harness which drives the live TUI like a real user to catch regressions that unit tests can't.\n\n[END CONTRACT \u2014 instructions follow]";
|
|
41
41
|
export interface ContractSectionOptions {
|
|
42
42
|
/** Chitchat turns carry no tools and make no factual claims — skip the contract. */
|
|
43
43
|
chitchat?: boolean;
|
|
@@ -39,18 +39,20 @@
|
|
|
39
39
|
*/
|
|
40
40
|
export const AGENT_OPERATING_CONTRACT = `[AGENT OPERATING CONTRACT — read first; applies to every step]
|
|
41
41
|
|
|
42
|
-
1. BEFORE ACTING: do only what was asked. Never assume scope or facts — if ambiguous, ask or use defaults; never invent requirements.
|
|
42
|
+
1. BEFORE ACTING: do only what was asked. Never assume scope or facts — if ambiguous, ask or use defaults; never invent requirements. RESEARCH FIRST: explore code (read/grep) and recall EE brain before editing. RECALL FIRST: ee.query in unfamiliar areas to surface past lessons.
|
|
43
43
|
2. READING: base statements on what you read/ran THIS turn. Do not infer contents of files you did not open.
|
|
44
44
|
3. EXECUTING: smallest correct change; never widen scope or mask failures (no \`|| true\`, skipped tests, or swallowed catch).
|
|
45
|
-
4. WHEN UNSURE: verify and cross-check BEFORE concluding.
|
|
45
|
+
4. WHEN UNSURE: verify and cross-check BEFORE concluding. Reading code is not proof — reproduce the bug.
|
|
46
46
|
5. REPORTING: answer ONLY what was asked. Every fact or file:line MUST come from this turn; else label "unverified"; do not guess. Synthesize evidence gracefully — do NOT dump massive verbatim tool outputs into the final answer. Cite concise file:line references. Never claim a build/test ran, or describe edits, you did not actually do this turn; if a check can't run, fix it or say so — don't imply success.
|
|
47
47
|
|
|
48
48
|
6. LANGUAGE: Reply in user's detected language for final output. Internal reasoning, tools, and code remain in English.
|
|
49
49
|
|
|
50
|
-
7. ANTI-MÙ / COMPACTION:
|
|
50
|
+
7. ANTI-MÙ / COMPACTION: On compaction, emit PRESERVE_FULL_CONTEXT (veto) or KEEP_TOOL_IDS (from stub id=) to protect results. Use ee_query with "tool-artifact id=XXX" to re-hydrate. Self-check via EE checkpoints. Suggest /compact near tool limits.
|
|
51
51
|
|
|
52
52
|
8. GIT SAFETY: never push on red — run the check, await its result in a SEPARATE step, confirm 0 failures, then push. Never \`git add -A\`/\`commit -a\`; stage explicitly so secrets (.env, .muonroi-cli/, keys) aren't committed. Never \`--no-verify\`.
|
|
53
53
|
|
|
54
|
+
9. VERIFICATION: when finishing a task, ALWAYS self-verify your work. Use the \`selfverify_*\` native tools (start/status/result) to run the QA harness which drives the live TUI like a real user to catch regressions that unit tests can't.
|
|
55
|
+
|
|
54
56
|
[END CONTRACT — instructions follow]`;
|
|
55
57
|
/**
|
|
56
58
|
* Build the contract block for insertion at the front of the system prompt.
|
|
@@ -47,8 +47,8 @@ describe("AGENT_OPERATING_CONTRACT", () => {
|
|
|
47
47
|
expect(AGENT_OPERATING_CONTRACT).toMatch(/push on red|never push/i);
|
|
48
48
|
expect(AGENT_OPERATING_CONTRACT).toMatch(/git add -A|stage explicitly/i);
|
|
49
49
|
});
|
|
50
|
-
it("stays compact (under
|
|
51
|
-
expect(AGENT_OPERATING_CONTRACT.length).toBeLessThan(
|
|
50
|
+
it("stays compact (under 2000 chars) to preserve attention budget on every turn (git-safety rule added)", () => {
|
|
51
|
+
expect(AGENT_OPERATING_CONTRACT.length).toBeLessThan(2000);
|
|
52
52
|
});
|
|
53
53
|
});
|
|
54
54
|
describe("buildContractSection", () => {
|
|
@@ -27,7 +27,7 @@ import type { ShellKind } from "../utils/shell.js";
|
|
|
27
27
|
* Wrapped with the `[CRITICAL TOOL-USE RULES ...]` marker so the model knows
|
|
28
28
|
* to treat these as overrides to anything that follows.
|
|
29
29
|
*/
|
|
30
|
-
export declare const CHEAP_MODEL_PLAYBOOK = "[CRITICAL TOOL-USE RULES \u2014 read before invoking any tool; these override defaults that follow]\n\n1. Bash output is AUTOMATICALLY cached. Every `bash` call returns a `run_id`\n (e.g. `bash-1`) you can re-query via `bash_output_get(run_id, mode=tail|head|grep|lines)`.\n - When you want only the last N lines: do NOT pipe `| tail -N`. Run the\n bare command, then call `bash_output_get(run_id, mode=tail, lines=N)`.\n - Same for `| head`, `| grep PATTERN`, `> file`. Pipes/redirects HIDE\n the full output from the cache; `bash_output_get` reads from the cache\n without re-running.\n - This applies to EVERY bash call, not just retries.\n - To VIEW a file use `read_file` (start_line/end_line) \u2014 never sed/cat a\n file. `bash_output_get` is for COMMAND output, not files.\n\n2. Before reading more than 3 files to understand a topic, delegate to\n `task(agent=\"explore\")`. The sub-agent returns a compressed summary;\n you save reading tokens.\n\n3. Use the `grep` tool (ripgrep) for content search \u2014 NOT `bash` with\n `grep` / `find` piped.\n\n4. When a tool returns `ERROR: ...`, do NOT retry the identical call.\n Pick a different tool, change inputs meaningfully, or stop and report.\n\n5. Fix the ROOT CAUSE, never mask a failure to make it \"pass\"\n (`continue-on-error`, swallowed try/catch, skipped/deleted test, `|| true`).\n If a step fails from a missing secret/config, make it CONDITIONAL (skip when\n absent) so it still runs when present \u2014 do NOT blanket-ignore it.\n\n6. For a build / CI / test failure, read the ACTUAL failure log or stack trace\n BEFORE hypothesizing \u2014 fix the real error, not a guess from source alone.\n\n7. ANTI-M\u00D9 / COMPACTION (for long sessions): On pre-warn or \"[context compacted at step...\", emit PRESERVE_FULL_CONTEXT (full veto) or lighter KEEP_TOOL_IDS: id1,id2 (from stub id=) to protect specific high-value results. read_file/grep/lsp/bash on src/PLAN/error are auto-kept (idea 1). Use ee.query tool with \"tool-artifact id=XXX\" for on-demand full. Self-check \"task finished?\" / \"compacted yet?\". Use EE checkpoints.\n\n[END CRITICAL TOOL-USE RULES \u2014 your regular instructions begin below]\n\n";
|
|
30
|
+
export declare const CHEAP_MODEL_PLAYBOOK = "[CRITICAL TOOL-USE RULES \u2014 read before invoking any tool; these override defaults that follow]\n\n1. Bash output is AUTOMATICALLY cached. Every `bash` call returns a `run_id`\n (e.g. `bash-1`) you can re-query via `bash_output_get(run_id, mode=tail|head|grep|lines)`.\n - When you want only the last N lines: do NOT pipe `| tail -N`. Run the\n bare command, then call `bash_output_get(run_id, mode=tail, lines=N)`.\n - Same for `| head`, `| grep PATTERN`, `> file`. Pipes/redirects HIDE\n the full output from the cache; `bash_output_get` reads from the cache\n without re-running.\n - This applies to EVERY bash call, not just retries.\n - To VIEW a file use `read_file` (start_line/end_line) \u2014 never sed/cat a\n file. `bash_output_get` is for COMMAND output, not files.\n\n2. Before reading more than 3 files to understand a topic, delegate to\n `task(agent=\"explore\")`. The sub-agent returns a compressed summary;\n you save reading tokens.\n\n3. Use the `grep` tool (ripgrep) for content search \u2014 NOT `bash` with\n `grep` / `find` piped.\n\n4. When a tool returns `ERROR: ...`, do NOT retry the identical call.\n Pick a different tool, change inputs meaningfully, or stop and report.\n\n5. Fix the ROOT CAUSE, never mask a failure to make it \"pass\"\n (`continue-on-error`, swallowed try/catch, skipped/deleted test, `|| true`).\n If a step fails from a missing secret/config, make it CONDITIONAL (skip when\n absent) so it still runs when present \u2014 do NOT blanket-ignore it.\n\n6. For a build / CI / test failure, read the ACTUAL failure log or stack trace\n BEFORE hypothesizing \u2014 fix the real error, not a guess from source alone.\n\n7. ANTI-M\u00D9 / COMPACTION (for long sessions): On pre-warn or \"[context compacted at step...\", emit PRESERVE_FULL_CONTEXT (full veto) or lighter KEEP_TOOL_IDS: id1,id2 (from stub id=) to protect specific high-value results. read_file/grep/lsp/bash on src/PLAN/error are auto-kept (idea 1). Use ee.query tool with \"tool-artifact id=XXX\" for on-demand full. Self-check \"task finished?\" / \"compacted yet?\". Use EE checkpoints. If you are reaching tool/step limits in a long session, suggest the user run \"/compact\" in the chat to compress this session's history.\n\n[END CRITICAL TOOL-USE RULES \u2014 your regular instructions begin below]\n\n";
|
|
31
31
|
/**
|
|
32
32
|
* Predicate gating playbook injection.
|
|
33
33
|
*
|
|
@@ -56,7 +56,7 @@ export const CHEAP_MODEL_PLAYBOOK = `[CRITICAL TOOL-USE RULES — read before in
|
|
|
56
56
|
6. For a build / CI / test failure, read the ACTUAL failure log or stack trace
|
|
57
57
|
BEFORE hypothesizing — fix the real error, not a guess from source alone.
|
|
58
58
|
|
|
59
|
-
7. ANTI-MÙ / COMPACTION (for long sessions): On pre-warn or "[context compacted at step...", emit PRESERVE_FULL_CONTEXT (full veto) or lighter KEEP_TOOL_IDS: id1,id2 (from stub id=) to protect specific high-value results. read_file/grep/lsp/bash on src/PLAN/error are auto-kept (idea 1). Use ee.query tool with "tool-artifact id=XXX" for on-demand full. Self-check "task finished?" / "compacted yet?". Use EE checkpoints.
|
|
59
|
+
7. ANTI-MÙ / COMPACTION (for long sessions): On pre-warn or "[context compacted at step...", emit PRESERVE_FULL_CONTEXT (full veto) or lighter KEEP_TOOL_IDS: id1,id2 (from stub id=) to protect specific high-value results. read_file/grep/lsp/bash on src/PLAN/error are auto-kept (idea 1). Use ee.query tool with "tool-artifact id=XXX" for on-demand full. Self-check "task finished?" / "compacted yet?". Use EE checkpoints. If you are reaching tool/step limits in a long session, suggest the user run "/compact" in the chat to compress this session's history.
|
|
60
60
|
|
|
61
61
|
[END CRITICAL TOOL-USE RULES — your regular instructions begin below]
|
|
62
62
|
|
|
@@ -25,7 +25,7 @@ import type { TaskType } from "./types.js";
|
|
|
25
25
|
* Universal anti-ramble convergence block — applies to every task type.
|
|
26
26
|
* Kept tight; the per-task addendum below specialises it.
|
|
27
27
|
*/
|
|
28
|
-
export declare const CHEAP_MODEL_CONVERGENCE = "[CONVERGENCE \u2014 minimise tool calls; the system prompt + tools are re-sent every call, so each extra step is expensive]\n\n- Plan the FEWEST reads you need, then read the specific file/section directly.\n Do NOT broad-grep, re-read a file you already read, or explore \"just in case\".\n- The moment you have enough to act, STOP investigating and make the change.\n- Make the SMALLEST correct change for the request; do not widen scope.\n- Finish the action before you answer \u2014 never stop mid-step (e.g. \"I'm verifying\u2026\").\n When done, state completion in ONE line (what changed + that it's verified);\n no recap, no next-steps padding.\n- GROUND every claim in what you actually read or ran THIS turn: cite real\n file:line, and never invent counts, line numbers, names, or bugs. If a number\n (test/file count) is not verified by a command you ran, run the check or mark\n it \"unverified\" \u2014 do NOT guess a value or assert a finding you did not observe.\n- ANTI-M\u00D9: After compaction note or pre-warn, emit PRESERVE_FULL_CONTEXT (full) or KEEP_TOOL_IDS: id1,id2 to protect high-value (auto for read_file/grep on src/PLAN/error). Use the ee_query tool with \"tool-artifact id=XXX\" for on-demand full re-hydrate. Recall checkpoints. ";
|
|
28
|
+
export declare const CHEAP_MODEL_CONVERGENCE = "[CONVERGENCE \u2014 minimise tool calls; the system prompt + tools are re-sent every call, so each extra step is expensive]\n\n- Plan the FEWEST reads you need, then read the specific file/section directly.\n Do NOT broad-grep, re-read a file you already read, or explore \"just in case\".\n- The moment you have enough to act, STOP investigating and make the change.\n- Make the SMALLEST correct change for the request; do not widen scope.\n- Finish the action before you answer \u2014 never stop mid-step (e.g. \"I'm verifying\u2026\").\n When done, state completion in ONE line (what changed + that it's verified);\n no recap, no next-steps padding.\n- GROUND every claim in what you actually read or ran THIS turn: cite real\n file:line, and never invent counts, line numbers, names, or bugs. If a number\n (test/file count) is not verified by a command you ran, run the check or mark\n it \"unverified\" \u2014 do NOT guess a value or assert a finding you did not observe.\n- ANTI-M\u00D9: After compaction note or pre-warn, emit PRESERVE_FULL_CONTEXT (full) or KEEP_TOOL_IDS: id1,id2 to protect high-value (auto for read_file/grep on src/PLAN/error). Use the ee_query tool with \"tool-artifact id=XXX\" for on-demand full re-hydrate. Recall checkpoints. If you are reaching tool/step limits in a long session, suggest the user run \"/compact\" to compress history. ";
|
|
29
29
|
/**
|
|
30
30
|
* Map a sub-agent role (agentKey) to the workbook TaskType that best matches
|
|
31
31
|
* its job. Sub-agents never run PIL Layer 1, so they have no classifier-derived
|
|
@@ -36,7 +36,7 @@ export const CHEAP_MODEL_CONVERGENCE = `[CONVERGENCE — minimise tool calls; th
|
|
|
36
36
|
file:line, and never invent counts, line numbers, names, or bugs. If a number
|
|
37
37
|
(test/file count) is not verified by a command you ran, run the check or mark
|
|
38
38
|
it "unverified" — do NOT guess a value or assert a finding you did not observe.
|
|
39
|
-
- ANTI-MÙ: After compaction note or pre-warn, emit PRESERVE_FULL_CONTEXT (full) or KEEP_TOOL_IDS: id1,id2 to protect high-value (auto for read_file/grep on src/PLAN/error). Use the ee_query tool with "tool-artifact id=XXX" for on-demand full re-hydrate. Recall checkpoints. `;
|
|
39
|
+
- ANTI-MÙ: After compaction note or pre-warn, emit PRESERVE_FULL_CONTEXT (full) or KEEP_TOOL_IDS: id1,id2 to protect high-value (auto for read_file/grep on src/PLAN/error). Use the ee_query tool with "tool-artifact id=XXX" for on-demand full re-hydrate. Recall checkpoints. If you are reaching tool/step limits in a long session, suggest the user run "/compact" to compress history. `;
|
|
40
40
|
/**
|
|
41
41
|
* Per-task-type addenda. Each is 1–2 tight lines targeting that type's most
|
|
42
42
|
* common budget-model failure mode. Types not listed fall back to the
|
package/dist/src/pil/config.d.ts
CHANGED
|
@@ -5,6 +5,16 @@
|
|
|
5
5
|
* Default OFF during rollout; flip to ON after dual-run validation.
|
|
6
6
|
*/
|
|
7
7
|
export declare function isUnifiedPilEnabled(): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* MUONROI_PIL_UNIFIED_BUDGET_MS: client-side timeout for the unified
|
|
10
|
+
* /api/pil-context call in Layer 1 Pass 3. The server's uncached path is
|
|
11
|
+
* classifier-bound (~1.5-3s; its own classifier timeout is 3500ms), so the
|
|
12
|
+
* legacy 1500ms budget aborted before the server could ever answer — the
|
|
13
|
+
* unified path then ALWAYS fell back to legacy, making MUONROI_PIL_UNIFIED=1 a
|
|
14
|
+
* no-op. Default 3500ms clears realistic uncached latency; cache hits return in
|
|
15
|
+
* ~1ms regardless. Clamped to [1000, 8000].
|
|
16
|
+
*/
|
|
17
|
+
export declare function getUnifiedPilBudgetMs(): number;
|
|
8
18
|
/**
|
|
9
19
|
* MUONROI_LLM_FIRST_CLASSIFY: model-first Layer-1 classification. When enabled
|
|
10
20
|
* (default), the configured model classifies taskType/intentKind/style at the
|
|
@@ -14,5 +24,15 @@ export declare function isUnifiedPilEnabled(): boolean;
|
|
|
14
24
|
* (the orchestrator does this on the main path); without it, the cascade runs.
|
|
15
25
|
*/
|
|
16
26
|
export declare function isLlmFirstClassifyEnabled(): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* G3 (b1): on the model-first classify path, also fetch the unified pil-context
|
|
29
|
+
* brain so layer3 renders the rich source="unified" injection (server-attributed
|
|
30
|
+
* t0/t2 + t1_rules + the rateable ledger) instead of falling through to its
|
|
31
|
+
* legacy dense-only /api/search round-trip. Default ON; set "0" to revert to
|
|
32
|
+
* the legacy layer3 injection on the default path. Independent of
|
|
33
|
+
* MUONROI_PIL_UNIFIED (which gates the OFFLINE cascade's unified pass).
|
|
34
|
+
*/
|
|
35
|
+
export declare function isLlmFirstBrainEnabled(): boolean;
|
|
17
36
|
export declare function isDiscoveryEnabled(): boolean;
|
|
18
37
|
export declare function getMaxInterviewQuestions(): number;
|
|
38
|
+
export declare function isPonytailModeEnabled(): boolean;
|
package/dist/src/pil/config.js
CHANGED
|
@@ -11,6 +11,21 @@ export function isUnifiedPilEnabled() {
|
|
|
11
11
|
return true;
|
|
12
12
|
return false;
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* MUONROI_PIL_UNIFIED_BUDGET_MS: client-side timeout for the unified
|
|
16
|
+
* /api/pil-context call in Layer 1 Pass 3. The server's uncached path is
|
|
17
|
+
* classifier-bound (~1.5-3s; its own classifier timeout is 3500ms), so the
|
|
18
|
+
* legacy 1500ms budget aborted before the server could ever answer — the
|
|
19
|
+
* unified path then ALWAYS fell back to legacy, making MUONROI_PIL_UNIFIED=1 a
|
|
20
|
+
* no-op. Default 3500ms clears realistic uncached latency; cache hits return in
|
|
21
|
+
* ~1ms regardless. Clamped to [1000, 8000].
|
|
22
|
+
*/
|
|
23
|
+
export function getUnifiedPilBudgetMs() {
|
|
24
|
+
const raw = Number(process.env.MUONROI_PIL_UNIFIED_BUDGET_MS);
|
|
25
|
+
if (!Number.isFinite(raw))
|
|
26
|
+
return 3500;
|
|
27
|
+
return Math.max(1000, Math.min(8000, Math.trunc(raw)));
|
|
28
|
+
}
|
|
14
29
|
/**
|
|
15
30
|
* MUONROI_LLM_FIRST_CLASSIFY: model-first Layer-1 classification. When enabled
|
|
16
31
|
* (default), the configured model classifies taskType/intentKind/style at the
|
|
@@ -22,6 +37,17 @@ export function isUnifiedPilEnabled() {
|
|
|
22
37
|
export function isLlmFirstClassifyEnabled() {
|
|
23
38
|
return process.env.MUONROI_LLM_FIRST_CLASSIFY !== "0";
|
|
24
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* G3 (b1): on the model-first classify path, also fetch the unified pil-context
|
|
42
|
+
* brain so layer3 renders the rich source="unified" injection (server-attributed
|
|
43
|
+
* t0/t2 + t1_rules + the rateable ledger) instead of falling through to its
|
|
44
|
+
* legacy dense-only /api/search round-trip. Default ON; set "0" to revert to
|
|
45
|
+
* the legacy layer3 injection on the default path. Independent of
|
|
46
|
+
* MUONROI_PIL_UNIFIED (which gates the OFFLINE cascade's unified pass).
|
|
47
|
+
*/
|
|
48
|
+
export function isLlmFirstBrainEnabled() {
|
|
49
|
+
return process.env.MUONROI_LLM_FIRST_BRAIN !== "0";
|
|
50
|
+
}
|
|
25
51
|
export function isDiscoveryEnabled() {
|
|
26
52
|
return process.env.MUONROI_PIL_DISCOVERY !== "0";
|
|
27
53
|
}
|
|
@@ -33,4 +59,13 @@ export function getMaxInterviewQuestions() {
|
|
|
33
59
|
const v = Number(process.env.MUONROI_PIL_MAX_QUESTIONS);
|
|
34
60
|
return Number.isFinite(v) && v >= 1 && v <= 5 ? v : 3;
|
|
35
61
|
}
|
|
62
|
+
export function isPonytailModeEnabled() {
|
|
63
|
+
if (process.env.MUONROI_PONYTAIL_DISABLE === "1")
|
|
64
|
+
return false;
|
|
65
|
+
if (process.env.MUONROI_PONYTAIL_DISABLE === "0")
|
|
66
|
+
return true;
|
|
67
|
+
if (process.env.VITEST === "true" || process.env.NODE_ENV === "test")
|
|
68
|
+
return false;
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
36
71
|
//# sourceMappingURL=config.js.map
|