@blxzer/cursor-trellis 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +124 -5
- package/README.zh-CN.md +170 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +1 -33
- package/dist/cli/index.js.map +1 -1
- package/dist/commands/init.d.ts +0 -13
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +7 -14
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/uninstall.d.ts.map +1 -1
- package/dist/commands/uninstall.js +3 -32
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +7 -84
- package/dist/commands/update.js.map +1 -1
- package/dist/configurators/index.d.ts +7 -8
- package/dist/configurators/index.d.ts.map +1 -1
- package/dist/configurators/index.js +11 -236
- package/dist/configurators/index.js.map +1 -1
- package/dist/configurators/workflow.d.ts.map +1 -1
- package/dist/configurators/workflow.js +5 -1
- package/dist/configurators/workflow.js.map +1 -1
- package/dist/templates/common/bundled-skills/smart-search-cli/SKILL.md +3 -3
- package/dist/templates/common/bundled-skills/trellis-meta/SKILL.md +4 -2
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-agents.md +8 -15
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-hooks.md +7 -7
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-skills-or-commands.md +18 -21
- package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/overview.md +2 -2
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/generated-files.md +10 -7
- package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/overview.md +4 -4
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/agents.md +20 -31
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/hooks-and-settings.md +20 -31
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/overview.md +24 -40
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/platform-map.md +28 -59
- package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/skills-and-commands.md +12 -28
- package/dist/templates/common/bundled-skills/trellis-skill-creator/references/trellis-skill-locations.md +2 -2
- package/dist/templates/cursor/hooks.json +6 -0
- package/dist/templates/cursor/rules/retrieval-routing.mdc +57 -0
- package/dist/templates/extract.d.ts +0 -14
- package/dist/templates/extract.d.ts.map +1 -1
- package/dist/templates/extract.js +0 -34
- package/dist/templates/extract.js.map +1 -1
- package/dist/templates/markdown/agents.md +2 -6
- package/dist/templates/markdown/index.d.ts +1 -0
- package/dist/templates/markdown/index.d.ts.map +1 -1
- package/dist/templates/markdown/index.js +1 -0
- package/dist/templates/markdown/index.js.map +1 -1
- package/dist/templates/markdown/prompts/run-semantic-slice-12.md.txt +41 -0
- package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md.txt +14 -14
- package/dist/templates/markdown/spec/guides/cross-layer-thinking-guide.md.txt +8 -20
- package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +15 -14
- package/dist/templates/markdown/spec/guides/cursor-context-injection-guide.md.txt +2 -1
- package/dist/templates/markdown/spec/guides/cursor-semantic-compliance.md.txt +49 -0
- package/dist/templates/markdown/spec/guides/cursor-subagent-policy.md.txt +2 -2
- package/dist/templates/markdown/spec/guides/retrieval-daily-guide.md.txt +68 -20
- package/dist/templates/shared-hooks/index.d.ts +1 -1
- package/dist/templates/shared-hooks/index.d.ts.map +1 -1
- package/dist/templates/shared-hooks/index.js +1 -0
- package/dist/templates/shared-hooks/index.js.map +1 -1
- package/dist/templates/shared-hooks/inject-retrieval-plan.py +163 -0
- package/dist/templates/shared-hooks/research-end-retrieval-pack.py +2 -11
- package/dist/templates/trellis/index.d.ts +11 -0
- package/dist/templates/trellis/index.d.ts.map +1 -1
- package/dist/templates/trellis/index.js +22 -0
- package/dist/templates/trellis/index.js.map +1 -1
- package/dist/templates/trellis/scripts/aggregate_retrieval_telemetry.py +342 -0
- package/dist/templates/trellis/scripts/batch_plan_envelope.py +105 -0
- package/dist/templates/trellis/scripts/codegraph_session_smoke.py +76 -0
- package/dist/templates/trellis/scripts/common/active_task.py +116 -147
- package/dist/templates/trellis/scripts/common/cli_adapter.py +34 -710
- package/dist/templates/trellis/scripts/common/codebase_retrieval_router.py +49 -106
- package/dist/templates/trellis/scripts/common/git_context.py +17 -2
- package/dist/templates/trellis/scripts/common/project_file_stats.py +91 -0
- package/dist/templates/trellis/scripts/common/retrieval_adapter_metadata.py +9 -11
- package/dist/templates/trellis/scripts/common/retrieval_agent_instructions.py +313 -0
- package/dist/templates/trellis/scripts/common/retrieval_pack.py +0 -6
- package/dist/templates/trellis/scripts/common/retrieval_pack_context.py +0 -4
- package/dist/templates/trellis/scripts/common/retrieval_plan_gate.py +76 -0
- package/dist/templates/trellis/scripts/common/retrieval_result_ranking.py +253 -0
- package/dist/templates/trellis/scripts/common/retrieval_tool_classification.py +157 -0
- package/dist/templates/trellis/scripts/common/semantic_plan_gate.py +52 -0
- package/dist/templates/trellis/scripts/common/workflow_phase.py +3 -24
- package/dist/templates/trellis/scripts/rank_retrieval_candidates.py +80 -0
- package/dist/templates/trellis/scripts/route_codebase_retrieval.py +38 -11
- package/dist/templates/trellis/scripts/score_evidence.py +112 -0
- package/dist/templates/trellis/workflow.md +861 -960
- package/dist/types/ai-tools.d.ts +13 -16
- package/dist/types/ai-tools.d.ts.map +1 -1
- package/dist/types/ai-tools.js +5 -238
- package/dist/types/ai-tools.js.map +1 -1
- package/dist/utils/codebase-retrieval-router.d.ts +1 -8
- package/dist/utils/codebase-retrieval-router.d.ts.map +1 -1
- package/dist/utils/codebase-retrieval-router.js +39 -180
- package/dist/utils/codebase-retrieval-router.js.map +1 -1
- package/dist/utils/project-capabilities.d.ts.map +1 -1
- package/dist/utils/project-capabilities.js +10 -24
- package/dist/utils/project-capabilities.js.map +1 -1
- package/dist/utils/retrieval-agent-instructions.d.ts +14 -0
- package/dist/utils/retrieval-agent-instructions.d.ts.map +1 -0
- package/dist/utils/retrieval-agent-instructions.js +221 -0
- package/dist/utils/retrieval-agent-instructions.js.map +1 -0
- package/dist/utils/retrieval-execution-telemetry.d.ts +43 -85
- package/dist/utils/retrieval-execution-telemetry.d.ts.map +1 -1
- package/dist/utils/retrieval-execution-telemetry.js +289 -22
- package/dist/utils/retrieval-execution-telemetry.js.map +1 -1
- package/dist/utils/retrieval-result-ranking.js +1 -1
- package/dist/utils/retrieval-result-ranking.js.map +1 -1
- package/dist/utils/retrieval-tool-classification.d.ts +32 -0
- package/dist/utils/retrieval-tool-classification.d.ts.map +1 -0
- package/dist/utils/retrieval-tool-classification.js +113 -0
- package/dist/utils/retrieval-tool-classification.js.map +1 -0
- package/dist/utils/uninstall-scrubbers.d.ts +0 -36
- package/dist/utils/uninstall-scrubbers.d.ts.map +1 -1
- package/dist/utils/uninstall-scrubbers.js +0 -184
- package/dist/utils/uninstall-scrubbers.js.map +1 -1
- package/package.json +4 -2
- package/dist/commands/mem.d.ts +0 -30
- package/dist/commands/mem.d.ts.map +0 -1
- package/dist/commands/mem.js +0 -424
- package/dist/commands/mem.js.map +0 -1
- package/dist/configurators/antigravity.d.ts +0 -7
- package/dist/configurators/antigravity.d.ts.map +0 -1
- package/dist/configurators/antigravity.js +0 -19
- package/dist/configurators/antigravity.js.map +0 -1
- package/dist/configurators/claude.d.ts +0 -9
- package/dist/configurators/claude.d.ts.map +0 -1
- package/dist/configurators/claude.js +0 -72
- package/dist/configurators/claude.js.map +0 -1
- package/dist/configurators/codebuddy.d.ts +0 -10
- package/dist/configurators/codebuddy.d.ts.map +0 -1
- package/dist/configurators/codebuddy.js +0 -30
- package/dist/configurators/codebuddy.js.map +0 -1
- package/dist/configurators/codex.d.ts +0 -8
- package/dist/configurators/codex.d.ts.map +0 -1
- package/dist/configurators/codex.js +0 -87
- package/dist/configurators/codex.js.map +0 -1
- package/dist/configurators/copilot.d.ts +0 -10
- package/dist/configurators/copilot.d.ts.map +0 -1
- package/dist/configurators/copilot.js +0 -51
- package/dist/configurators/copilot.js.map +0 -1
- package/dist/configurators/droid.d.ts +0 -10
- package/dist/configurators/droid.d.ts.map +0 -1
- package/dist/configurators/droid.js +0 -30
- package/dist/configurators/droid.js.map +0 -1
- package/dist/configurators/gemini.d.ts +0 -16
- package/dist/configurators/gemini.d.ts.map +0 -1
- package/dist/configurators/gemini.js +0 -38
- package/dist/configurators/gemini.js.map +0 -1
- package/dist/configurators/kilo.d.ts +0 -7
- package/dist/configurators/kilo.d.ts.map +0 -1
- package/dist/configurators/kilo.js +0 -19
- package/dist/configurators/kilo.js.map +0 -1
- package/dist/configurators/kiro.d.ts +0 -8
- package/dist/configurators/kiro.d.ts.map +0 -1
- package/dist/configurators/kiro.js +0 -24
- package/dist/configurators/kiro.js.map +0 -1
- package/dist/configurators/opencode.d.ts +0 -14
- package/dist/configurators/opencode.d.ts.map +0 -1
- package/dist/configurators/opencode.js +0 -96
- package/dist/configurators/opencode.js.map +0 -1
- package/dist/configurators/pi.d.ts +0 -3
- package/dist/configurators/pi.d.ts.map +0 -1
- package/dist/configurators/pi.js +0 -45
- package/dist/configurators/pi.js.map +0 -1
- package/dist/configurators/qoder.d.ts +0 -11
- package/dist/configurators/qoder.d.ts.map +0 -1
- package/dist/configurators/qoder.js +0 -31
- package/dist/configurators/qoder.js.map +0 -1
- package/dist/configurators/windsurf.d.ts +0 -7
- package/dist/configurators/windsurf.d.ts.map +0 -1
- package/dist/configurators/windsurf.js +0 -19
- package/dist/configurators/windsurf.js.map +0 -1
- package/dist/templates/claude/agents/trellis-check.md +0 -124
- package/dist/templates/claude/agents/trellis-implement.md +0 -110
- package/dist/templates/claude/agents/trellis-research.md +0 -137
- package/dist/templates/claude/index.d.ts +0 -22
- package/dist/templates/claude/index.d.ts.map +0 -1
- package/dist/templates/claude/index.js +0 -46
- package/dist/templates/claude/index.js.map +0 -1
- package/dist/templates/claude/settings.json +0 -84
- package/dist/templates/codebuddy/agents/trellis-check.md +0 -115
- package/dist/templates/codebuddy/agents/trellis-implement.md +0 -110
- package/dist/templates/codebuddy/agents/trellis-research.md +0 -137
- package/dist/templates/codebuddy/index.d.ts +0 -15
- package/dist/templates/codebuddy/index.d.ts.map +0 -1
- package/dist/templates/codebuddy/index.js +0 -15
- package/dist/templates/codebuddy/index.js.map +0 -1
- package/dist/templates/codebuddy/settings.json +0 -70
- package/dist/templates/codex/agents/trellis-check.toml +0 -67
- package/dist/templates/codex/agents/trellis-implement.toml +0 -40
- package/dist/templates/codex/agents/trellis-research.toml +0 -73
- package/dist/templates/codex/config.toml +0 -28
- package/dist/templates/codex/hooks/session-start.py +0 -575
- package/dist/templates/codex/hooks.json +0 -15
- package/dist/templates/codex/index.d.ts +0 -39
- package/dist/templates/codex/index.d.ts.map +0 -1
- package/dist/templates/codex/index.js +0 -85
- package/dist/templates/codex/index.js.map +0 -1
- package/dist/templates/codex/skills/before-dev/SKILL.md +0 -40
- package/dist/templates/codex/skills/brainstorm/SKILL.md +0 -112
- package/dist/templates/codex/skills/break-loop/SKILL.md +0 -130
- package/dist/templates/codex/skills/check/SKILL.md +0 -98
- package/dist/templates/codex/skills/check-cross-layer/SKILL.md +0 -158
- package/dist/templates/codex/skills/create-command/SKILL.md +0 -101
- package/dist/templates/codex/skills/finish-work/SKILL.md +0 -90
- package/dist/templates/codex/skills/improve-ut/SKILL.md +0 -69
- package/dist/templates/codex/skills/integrate-skill/SKILL.md +0 -221
- package/dist/templates/codex/skills/onboard/SKILL.md +0 -363
- package/dist/templates/codex/skills/record-session/SKILL.md +0 -67
- package/dist/templates/codex/skills/start/SKILL.md +0 -66
- package/dist/templates/codex/skills/update-spec/SKILL.md +0 -335
- package/dist/templates/copilot/hooks/session-start.py +0 -557
- package/dist/templates/copilot/hooks.json +0 -19
- package/dist/templates/copilot/index.d.ts +0 -23
- package/dist/templates/copilot/index.d.ts.map +0 -1
- package/dist/templates/copilot/index.js +0 -54
- package/dist/templates/copilot/index.js.map +0 -1
- package/dist/templates/copilot/prompts/before-dev.prompt.md +0 -39
- package/dist/templates/copilot/prompts/brainstorm.prompt.md +0 -111
- package/dist/templates/copilot/prompts/break-loop.prompt.md +0 -129
- package/dist/templates/copilot/prompts/check-cross-layer.prompt.md +0 -157
- package/dist/templates/copilot/prompts/check.prompt.md +0 -97
- package/dist/templates/copilot/prompts/create-command.prompt.md +0 -116
- package/dist/templates/copilot/prompts/finish-work.prompt.md +0 -99
- package/dist/templates/copilot/prompts/integrate-skill.prompt.md +0 -223
- package/dist/templates/copilot/prompts/onboard.prompt.md +0 -362
- package/dist/templates/copilot/prompts/parallel.prompt.md +0 -204
- package/dist/templates/copilot/prompts/record-session.prompt.md +0 -66
- package/dist/templates/copilot/prompts/start.prompt.md +0 -63
- package/dist/templates/copilot/prompts/update-spec.prompt.md +0 -358
- package/dist/templates/droid/droids/trellis-check.md +0 -107
- package/dist/templates/droid/droids/trellis-implement.md +0 -102
- package/dist/templates/droid/droids/trellis-research.md +0 -137
- package/dist/templates/droid/index.d.ts +0 -15
- package/dist/templates/droid/index.d.ts.map +0 -1
- package/dist/templates/droid/index.js +0 -15
- package/dist/templates/droid/index.js.map +0 -1
- package/dist/templates/droid/settings.json +0 -70
- package/dist/templates/gemini/agents/trellis-check.md +0 -107
- package/dist/templates/gemini/agents/trellis-implement.md +0 -102
- package/dist/templates/gemini/agents/trellis-research.md +0 -136
- package/dist/templates/gemini/index.d.ts +0 -13
- package/dist/templates/gemini/index.d.ts.map +0 -1
- package/dist/templates/gemini/index.js +0 -13
- package/dist/templates/gemini/index.js.map +0 -1
- package/dist/templates/gemini/settings.json +0 -28
- package/dist/templates/kiro/agents/trellis-check.json +0 -26
- package/dist/templates/kiro/agents/trellis-implement.json +0 -26
- package/dist/templates/kiro/agents/trellis-research.json +0 -30
- package/dist/templates/kiro/index.d.ts +0 -18
- package/dist/templates/kiro/index.d.ts.map +0 -1
- package/dist/templates/kiro/index.js +0 -18
- package/dist/templates/kiro/index.js.map +0 -1
- package/dist/templates/opencode/agents/trellis-check.md +0 -122
- package/dist/templates/opencode/agents/trellis-implement.md +0 -118
- package/dist/templates/opencode/agents/trellis-research.md +0 -145
- package/dist/templates/opencode/lib/session-utils.js +0 -667
- package/dist/templates/opencode/lib/trellis-context.js +0 -336
- package/dist/templates/opencode/package.json +0 -5
- package/dist/templates/opencode/plugins/inject-subagent-context.js +0 -495
- package/dist/templates/opencode/plugins/inject-workflow-state.js +0 -159
- package/dist/templates/opencode/plugins/session-start.js +0 -101
- package/dist/templates/pi/agents/trellis-check.md +0 -37
- package/dist/templates/pi/agents/trellis-implement.md +0 -42
- package/dist/templates/pi/agents/trellis-research.md +0 -25
- package/dist/templates/pi/extensions/trellis/index.ts.txt +0 -1600
- package/dist/templates/pi/index.d.ts +0 -5
- package/dist/templates/pi/index.d.ts.map +0 -1
- package/dist/templates/pi/index.js +0 -12
- package/dist/templates/pi/index.js.map +0 -1
- package/dist/templates/pi/settings.json +0 -12
- package/dist/templates/qoder/agents/trellis-check.md +0 -108
- package/dist/templates/qoder/agents/trellis-implement.md +0 -103
- package/dist/templates/qoder/agents/trellis-research.md +0 -137
- package/dist/templates/qoder/index.d.ts +0 -15
- package/dist/templates/qoder/index.d.ts.map +0 -1
- package/dist/templates/qoder/index.js +0 -15
- package/dist/templates/qoder/index.js.map +0 -1
- package/dist/templates/qoder/settings.json +0 -47
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"""Classify agent tool names for retrieval execution telemetry (Cursor-first)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
|
|
8
|
+
CODEGRAPH_PATTERNS = (
|
|
9
|
+
re.compile(r"^codegraph_", re.I),
|
|
10
|
+
re.compile(r"^project-0-.*-codegraph-", re.I),
|
|
11
|
+
re.compile(r"codegraph_search", re.I),
|
|
12
|
+
re.compile(r"codegraph_explore", re.I),
|
|
13
|
+
re.compile(r"codegraph_callers", re.I),
|
|
14
|
+
re.compile(r"codegraph_node", re.I),
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
PLATFORM_SEMANTIC_PATTERNS = (
|
|
18
|
+
re.compile(r"@codebase", re.I),
|
|
19
|
+
re.compile(r"semantic.?search", re.I),
|
|
20
|
+
re.compile(r"DEEP_SEARCH", re.I),
|
|
21
|
+
re.compile(r"codebase.?search", re.I),
|
|
22
|
+
re.compile(r"SemanticSearch", re.I),
|
|
23
|
+
re.compile(r"Instant Search", re.I),
|
|
24
|
+
re.compile(r"Cursor.*semantic", re.I),
|
|
25
|
+
re.compile(r"built-?in.*codebase", re.I),
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
FAST_CONTEXT_PATTERNS = (
|
|
29
|
+
re.compile(r"fast_context_search", re.I),
|
|
30
|
+
re.compile(r"fast-context", re.I),
|
|
31
|
+
re.compile(r"fast_context", re.I),
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
GREP_PATTERNS = (
|
|
35
|
+
re.compile(r"^grep$", re.I),
|
|
36
|
+
re.compile(r"^Grep$", re.I),
|
|
37
|
+
re.compile(r"^rg$", re.I),
|
|
38
|
+
re.compile(r"ripgrep", re.I),
|
|
39
|
+
re.compile(r"Instant Grep", re.I),
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
READ_PATTERNS = (
|
|
43
|
+
re.compile(r"^read$", re.I),
|
|
44
|
+
re.compile(r"^Read$", re.I),
|
|
45
|
+
re.compile(r"ReadFile", re.I),
|
|
46
|
+
re.compile(r"Get-Content", re.I),
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
ROUTER_CLI_PATTERNS = (
|
|
50
|
+
re.compile(r"route_codebase_retrieval", re.I),
|
|
51
|
+
re.compile(r"retrieval-routing", re.I),
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
STRUCTURAL_ROUTE_IDS = frozenset(
|
|
55
|
+
{
|
|
56
|
+
"caller-chain-ast",
|
|
57
|
+
"trap-demote-codegraph",
|
|
58
|
+
"extension-codegraph",
|
|
59
|
+
"ast-codegraph",
|
|
60
|
+
}
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _matches(name: str, patterns: tuple[re.Pattern[str], ...]) -> bool:
|
|
65
|
+
return any(p.search(name) for p in patterns)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def is_platform_semantic_tool_name(name: str) -> bool:
|
|
69
|
+
return _matches(name.strip(), PLATFORM_SEMANTIC_PATTERNS)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def is_fast_context_tool_name(name: str) -> bool:
|
|
73
|
+
return _matches(name.strip(), FAST_CONTEXT_PATTERNS)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@dataclass(frozen=True)
|
|
77
|
+
class ClassifiedToolCalls:
|
|
78
|
+
tools_called: list[str]
|
|
79
|
+
grep_count: int
|
|
80
|
+
read_count: int
|
|
81
|
+
codegraph_attempted: bool
|
|
82
|
+
codegraph_executed: bool
|
|
83
|
+
semantic_attempted: bool
|
|
84
|
+
semantic_executed: bool
|
|
85
|
+
router_cli_invoked: bool
|
|
86
|
+
platform_semantic_executed: bool = False
|
|
87
|
+
fast_context_count: int = 0
|
|
88
|
+
cursor_fast_context_misuse: bool = False
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def classify_tool_calls(raw: list[str], *, platform: str = "cursor") -> ClassifiedToolCalls:
|
|
92
|
+
tools_called = list(raw)
|
|
93
|
+
grep_count = 0
|
|
94
|
+
read_count = 0
|
|
95
|
+
codegraph_executed = False
|
|
96
|
+
router_cli_invoked = False
|
|
97
|
+
platform_semantic_executed = False
|
|
98
|
+
fast_context_count = 0
|
|
99
|
+
plat = (platform or "cursor").lower()
|
|
100
|
+
|
|
101
|
+
for name in raw:
|
|
102
|
+
trimmed = name.strip()
|
|
103
|
+
if not trimmed:
|
|
104
|
+
continue
|
|
105
|
+
if _matches(trimmed, GREP_PATTERNS):
|
|
106
|
+
grep_count += 1
|
|
107
|
+
if _matches(trimmed, READ_PATTERNS):
|
|
108
|
+
read_count += 1
|
|
109
|
+
if _matches(trimmed, CODEGRAPH_PATTERNS):
|
|
110
|
+
codegraph_executed = True
|
|
111
|
+
if _matches(trimmed, ROUTER_CLI_PATTERNS):
|
|
112
|
+
router_cli_invoked = True
|
|
113
|
+
if is_fast_context_tool_name(trimmed):
|
|
114
|
+
fast_context_count += 1
|
|
115
|
+
if is_platform_semantic_tool_name(trimmed):
|
|
116
|
+
platform_semantic_executed = True
|
|
117
|
+
|
|
118
|
+
if plat == "cursor":
|
|
119
|
+
semantic_executed = platform_semantic_executed
|
|
120
|
+
else:
|
|
121
|
+
semantic_executed = platform_semantic_executed or fast_context_count > 0
|
|
122
|
+
|
|
123
|
+
semantic_attempted = semantic_executed or fast_context_count > 0
|
|
124
|
+
misuse = plat == "cursor" and fast_context_count > 0
|
|
125
|
+
|
|
126
|
+
return ClassifiedToolCalls(
|
|
127
|
+
tools_called=tools_called,
|
|
128
|
+
grep_count=grep_count,
|
|
129
|
+
read_count=read_count,
|
|
130
|
+
codegraph_attempted=codegraph_executed,
|
|
131
|
+
codegraph_executed=codegraph_executed,
|
|
132
|
+
semantic_attempted=semantic_attempted,
|
|
133
|
+
semantic_executed=semantic_executed,
|
|
134
|
+
router_cli_invoked=router_cli_invoked,
|
|
135
|
+
platform_semantic_executed=platform_semantic_executed,
|
|
136
|
+
fast_context_count=fast_context_count,
|
|
137
|
+
cursor_fast_context_misuse=misuse,
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def structural_routes_in_plan(route_ids: list[str]) -> bool:
|
|
142
|
+
return any(
|
|
143
|
+
"codegraph" in rid or rid in STRUCTURAL_ROUTE_IDS for rid in route_ids
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def semantic_routes_in_plan(route_ids: list[str]) -> bool:
|
|
148
|
+
return any(rid in ("platform-semantic", "semantic-fast-context") for rid in route_ids)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def platform_semantic_route_order(routes: list[dict]) -> int | None:
|
|
152
|
+
for route in routes:
|
|
153
|
+
if isinstance(route, dict) and route.get("id") == "platform-semantic":
|
|
154
|
+
order = route.get("order")
|
|
155
|
+
if isinstance(order, int):
|
|
156
|
+
return order
|
|
157
|
+
return None
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""REC-11: post-plan hints when platform-semantic is first-class in the router envelope."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def platform_semantic_order_from_envelope(envelope: dict[str, Any]) -> int | None:
|
|
9
|
+
routes = envelope.get("routes")
|
|
10
|
+
if not isinstance(routes, list):
|
|
11
|
+
return None
|
|
12
|
+
for route in routes:
|
|
13
|
+
if not isinstance(route, dict):
|
|
14
|
+
continue
|
|
15
|
+
if route.get("id") == "platform-semantic":
|
|
16
|
+
order = route.get("order")
|
|
17
|
+
if isinstance(order, int):
|
|
18
|
+
return order
|
|
19
|
+
return None
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def semantic_compliance_gate_hint(
|
|
23
|
+
envelope: dict[str, Any],
|
|
24
|
+
*,
|
|
25
|
+
locale: str = "zh",
|
|
26
|
+
) -> str:
|
|
27
|
+
"""
|
|
28
|
+
When platform-semantic is order 1 (or 2 on policy-first routes), append a
|
|
29
|
+
hard compliance strip for eval / hook-injected plans (REC-06 + REC-11).
|
|
30
|
+
"""
|
|
31
|
+
order = platform_semantic_order_from_envelope(envelope)
|
|
32
|
+
if order is None or order > 2:
|
|
33
|
+
return ""
|
|
34
|
+
routes = envelope.get("routes") or []
|
|
35
|
+
if not isinstance(routes, list):
|
|
36
|
+
return ""
|
|
37
|
+
if not any(isinstance(r, dict) and r.get("id") == "platform-semantic" for r in routes):
|
|
38
|
+
return ""
|
|
39
|
+
|
|
40
|
+
if locale != "zh":
|
|
41
|
+
return (
|
|
42
|
+
"**Plan gate (REC-11):** `platform-semantic` is step "
|
|
43
|
+
f"#{order}. Before Top-1 you MUST run one Cursor built-in codebase "
|
|
44
|
+
"semantic search and log the exact tool name. Do not use fast-context MCP. "
|
|
45
|
+
"If semantic returns paths, corroborate with Read on candidate ranges."
|
|
46
|
+
)
|
|
47
|
+
return (
|
|
48
|
+
"**计划门控(REC-11):** 本问 `platform-semantic` 为第 "
|
|
49
|
+
f"{order} 步。定 Top-1 前 **必须** 执行 1 次 Cursor **内置代码库语义搜索**,"
|
|
50
|
+
"并在记录中写下宿主工具名;**禁止** fast-context MCP。"
|
|
51
|
+
"语义命中路径后须 **Read** 验证候选片段(verified 层)。"
|
|
52
|
+
)
|
|
@@ -132,7 +132,7 @@ def get_step(step_id: str) -> str:
|
|
|
132
132
|
|
|
133
133
|
|
|
134
134
|
def _platform_matches(platform: str, block_names: list[str]) -> bool:
|
|
135
|
-
"""Case-insensitive fuzzy match: accept 'cursor'
|
|
135
|
+
"""Case-insensitive fuzzy match: accept 'cursor' or 'Cursor'."""
|
|
136
136
|
needle = platform.lower().replace("-", "").replace("_", "").replace(" ", "")
|
|
137
137
|
for name in block_names:
|
|
138
138
|
hay = name.lower().replace("-", "").replace("_", "").replace(" ", "")
|
|
@@ -142,29 +142,8 @@ def _platform_matches(platform: str, block_names: list[str]) -> bool:
|
|
|
142
142
|
|
|
143
143
|
|
|
144
144
|
def resolve_effective_platform(platform: str, config: dict) -> str:
|
|
145
|
-
"""
|
|
146
|
-
|
|
147
|
-
When ``--platform codex`` is passed, return ``"codex-inline"`` (default)
|
|
148
|
-
or ``"codex-sub-agent"`` based on ``.trellis/config.yaml`` ``codex.dispatch_mode``.
|
|
149
|
-
``filter_platform`` then surfaces blocks whose marker lists include the
|
|
150
|
-
namespaced name (e.g. ``[codex-sub-agent, ...]`` or ``[codex-inline, Kilo,
|
|
151
|
-
Antigravity, Windsurf]``).
|
|
152
|
-
|
|
153
|
-
Default is ``inline`` because Codex sub-agents run with ``fork_turns="none"``
|
|
154
|
-
isolation and can't inherit the parent session's task context — inline
|
|
155
|
-
keeps the main agent in charge so context isn't lost. Invalid / missing
|
|
156
|
-
values also fall back to inline.
|
|
157
|
-
|
|
158
|
-
Other platforms are returned unchanged.
|
|
159
|
-
"""
|
|
160
|
-
if platform == "codex":
|
|
161
|
-
mode = "inline"
|
|
162
|
-
codex_cfg = config.get("codex") if isinstance(config, dict) else None
|
|
163
|
-
if isinstance(codex_cfg, dict):
|
|
164
|
-
cfg_mode = codex_cfg.get("dispatch_mode")
|
|
165
|
-
if cfg_mode in ("inline", "sub-agent"):
|
|
166
|
-
mode = cfg_mode
|
|
167
|
-
return f"codex-{mode}"
|
|
145
|
+
"""Return the platform name unchanged (Cursor-only fork)."""
|
|
146
|
+
_ = config
|
|
168
147
|
return platform
|
|
169
148
|
|
|
170
149
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""CLI: rank codebase path candidates for B/E/D intents (eval / dogfood)."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import argparse
|
|
7
|
+
import json
|
|
8
|
+
import sys
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
from common.retrieval_result_ranking import rank_retrieval_result_candidates
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
|
15
|
+
parser = argparse.ArgumentParser(
|
|
16
|
+
description="Rank retrieval path candidates (caller / trap / env intents).",
|
|
17
|
+
)
|
|
18
|
+
parser.add_argument(
|
|
19
|
+
"--candidates",
|
|
20
|
+
help="Path to JSON array of candidate objects, or '-' for stdin.",
|
|
21
|
+
)
|
|
22
|
+
parser.add_argument(
|
|
23
|
+
"--intents",
|
|
24
|
+
required=True,
|
|
25
|
+
help="Comma-separated intent ids (e.g. caller-chain,env-config-literal).",
|
|
26
|
+
)
|
|
27
|
+
parser.add_argument("--top-k", type=int, default=5)
|
|
28
|
+
parser.add_argument("--expanded-pool-size", type=int, default=None)
|
|
29
|
+
parser.add_argument(
|
|
30
|
+
"--caller-pool-expansion",
|
|
31
|
+
action="store_true",
|
|
32
|
+
help="Enable caller pool expansion (caller-chain intent).",
|
|
33
|
+
)
|
|
34
|
+
parser.add_argument("--min-concrete-callers", type=int, default=3)
|
|
35
|
+
parser.add_argument("--json", action="store_true", help="Emit JSON (default).")
|
|
36
|
+
parser.add_argument("--pretty", action="store_true")
|
|
37
|
+
return parser.parse_args(argv)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def load_candidates(source: str | None) -> list[dict]:
|
|
41
|
+
if source is None or source == "-":
|
|
42
|
+
raw = sys.stdin.read()
|
|
43
|
+
else:
|
|
44
|
+
raw = Path(source).read_text(encoding="utf-8")
|
|
45
|
+
parsed = json.loads(raw)
|
|
46
|
+
if not isinstance(parsed, list):
|
|
47
|
+
raise ValueError("candidates must be a JSON array")
|
|
48
|
+
return [item for item in parsed if isinstance(item, dict)]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def main(argv: list[str] | None = None) -> int:
|
|
52
|
+
args = parse_args(argv)
|
|
53
|
+
try:
|
|
54
|
+
candidates = load_candidates(args.candidates)
|
|
55
|
+
except (OSError, json.JSONDecodeError, ValueError) as error:
|
|
56
|
+
print(f"rank_retrieval_candidates: {error}", file=sys.stderr)
|
|
57
|
+
return 2
|
|
58
|
+
|
|
59
|
+
intents = [part.strip() for part in args.intents.split(",") if part.strip()]
|
|
60
|
+
expansion = None
|
|
61
|
+
if args.caller_pool_expansion:
|
|
62
|
+
expansion = {
|
|
63
|
+
"enabled": True,
|
|
64
|
+
"minConcreteCallers": args.min_concrete_callers,
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
result = rank_retrieval_result_candidates(
|
|
68
|
+
candidates,
|
|
69
|
+
intents=intents,
|
|
70
|
+
top_k=args.top_k,
|
|
71
|
+
expanded_pool_size=args.expanded_pool_size,
|
|
72
|
+
caller_pool_expansion=expansion,
|
|
73
|
+
)
|
|
74
|
+
indent = 2 if args.pretty else None
|
|
75
|
+
print(json.dumps(result, indent=indent, ensure_ascii=False))
|
|
76
|
+
return 0
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
if __name__ == "__main__":
|
|
80
|
+
raise SystemExit(main())
|
|
@@ -7,12 +7,16 @@ from __future__ import annotations
|
|
|
7
7
|
|
|
8
8
|
import argparse
|
|
9
9
|
import json
|
|
10
|
+
import sys
|
|
10
11
|
from pathlib import Path
|
|
11
12
|
|
|
12
13
|
from common.codebase_retrieval_router import (
|
|
13
14
|
codebase_retrieval_selected_from_capabilities,
|
|
14
15
|
route_codebase_retrieval,
|
|
15
16
|
)
|
|
17
|
+
from common.paths import get_repo_root
|
|
18
|
+
from common.project_file_stats import resolve_project_file_count_arg
|
|
19
|
+
from common.retrieval_agent_instructions import render_agent_instructions
|
|
16
20
|
|
|
17
21
|
|
|
18
22
|
def load_capabilities(path: Path | None) -> dict[str, object] | None:
|
|
@@ -38,16 +42,24 @@ def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
|
|
38
42
|
help="Treat codebase-retrieval as unselected (omit optional adapter routes).",
|
|
39
43
|
)
|
|
40
44
|
parser.add_argument(
|
|
41
|
-
"--
|
|
42
|
-
default="
|
|
43
|
-
|
|
44
|
-
help=
|
|
45
|
+
"--project-file-count",
|
|
46
|
+
default="auto",
|
|
47
|
+
metavar="N|auto",
|
|
48
|
+
help=(
|
|
49
|
+
"File count for large-repo routing (>2000 promotes codegraph). "
|
|
50
|
+
"Default auto: git ls-files or walk from repo root. Example: 5000."
|
|
51
|
+
),
|
|
45
52
|
)
|
|
46
53
|
parser.add_argument(
|
|
47
|
-
"--
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
help="
|
|
54
|
+
"--locale",
|
|
55
|
+
default="zh",
|
|
56
|
+
choices=["zh", "en"],
|
|
57
|
+
help="Language for agent instructions (default: zh).",
|
|
58
|
+
)
|
|
59
|
+
parser.add_argument(
|
|
60
|
+
"--instructions",
|
|
61
|
+
action="store_true",
|
|
62
|
+
help="Print agent-executable instructions only (no JSON).",
|
|
51
63
|
)
|
|
52
64
|
parser.add_argument("--json", action="store_true", help="Emit JSON to stdout (default).")
|
|
53
65
|
parser.add_argument("--pretty", action="store_true", help="Pretty-print JSON.")
|
|
@@ -56,6 +68,14 @@ def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
|
|
|
56
68
|
|
|
57
69
|
def main(argv: list[str] | None = None) -> int:
|
|
58
70
|
args = parse_args(argv)
|
|
71
|
+
try:
|
|
72
|
+
project_file_count = resolve_project_file_count_arg(
|
|
73
|
+
args.project_file_count,
|
|
74
|
+
repo_root=get_repo_root(),
|
|
75
|
+
)
|
|
76
|
+
except ValueError as error:
|
|
77
|
+
print(f"route_codebase_retrieval: {error}", file=sys.stderr)
|
|
78
|
+
return 2
|
|
59
79
|
caps = load_capabilities(Path(args.capabilities) if args.capabilities else None)
|
|
60
80
|
selected = (
|
|
61
81
|
False
|
|
@@ -65,11 +85,18 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
65
85
|
plan = route_codebase_retrieval(
|
|
66
86
|
args.query,
|
|
67
87
|
codebase_retrieval_selected=selected,
|
|
68
|
-
|
|
69
|
-
|
|
88
|
+
project_file_count=project_file_count,
|
|
89
|
+
)
|
|
90
|
+
instructions = render_agent_instructions(
|
|
91
|
+
plan,
|
|
92
|
+
locale=args.locale,
|
|
70
93
|
)
|
|
94
|
+
if args.instructions:
|
|
95
|
+
sys.stdout.write(instructions)
|
|
96
|
+
return 0
|
|
97
|
+
payload: dict[str, object] = {**plan, "agentInstructions": instructions}
|
|
71
98
|
indent = 2 if args.pretty else None
|
|
72
|
-
print(json.dumps(
|
|
99
|
+
print(json.dumps(payload, indent=indent, ensure_ascii=False))
|
|
73
100
|
return 0
|
|
74
101
|
|
|
75
102
|
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""REC-11: derive evidence_score (0-2) from telemetry + optional rubric row."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import argparse
|
|
7
|
+
import json
|
|
8
|
+
import sys
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
_SCRIPT_DIR = Path(__file__).resolve().parent
|
|
13
|
+
if str(_SCRIPT_DIR) not in sys.path:
|
|
14
|
+
sys.path.insert(0, str(_SCRIPT_DIR))
|
|
15
|
+
|
|
16
|
+
from common.retrieval_tool_classification import classify_tool_calls # noqa: E402
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def evidence_score_from_record(record: dict[str, Any]) -> int:
|
|
20
|
+
"""
|
|
21
|
+
Trellis verified layer proxy for eval (R-CR-014):
|
|
22
|
+
0 = no Read on candidates
|
|
23
|
+
1 = Read used but no corroborated_files / weak verify
|
|
24
|
+
2 = read_verification_done and (corroborated_files or read_count >= 1 with top1)
|
|
25
|
+
"""
|
|
26
|
+
if not record.get("read_verification_done") and int(record.get("read_count") or 0) <= 0:
|
|
27
|
+
return 0
|
|
28
|
+
corroborated = record.get("corroborated_files") or []
|
|
29
|
+
if isinstance(corroborated, list) and len(corroborated) > 0:
|
|
30
|
+
return 2
|
|
31
|
+
if record.get("read_verification_done") or int(record.get("read_count") or 0) > 0:
|
|
32
|
+
top1 = str(record.get("top1") or record.get("top_1") or "").strip()
|
|
33
|
+
if top1:
|
|
34
|
+
return 2
|
|
35
|
+
return 1
|
|
36
|
+
return 0
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def enrich_record(raw: dict[str, Any]) -> dict[str, Any]:
|
|
40
|
+
platform = str(raw.get("platform", "cursor"))
|
|
41
|
+
tools = raw.get("tools_called") or []
|
|
42
|
+
if not isinstance(tools, list):
|
|
43
|
+
tools = []
|
|
44
|
+
classified = classify_tool_calls([str(t) for t in tools], platform=platform)
|
|
45
|
+
out = dict(raw)
|
|
46
|
+
out["platform_semantic_executed"] = bool(
|
|
47
|
+
raw.get("platform_semantic_executed", classified.platform_semantic_executed)
|
|
48
|
+
)
|
|
49
|
+
out["semantic_executed"] = bool(raw.get("semantic_executed", classified.semantic_executed))
|
|
50
|
+
out["read_count"] = int(raw.get("read_count", classified.read_count))
|
|
51
|
+
if "read_verification_done" not in out:
|
|
52
|
+
out["read_verification_done"] = classified.read_count > 0
|
|
53
|
+
out["evidence_score"] = evidence_score_from_record(out)
|
|
54
|
+
ans = raw.get("answer_score")
|
|
55
|
+
if isinstance(ans, (int, float)):
|
|
56
|
+
out["combined_score"] = float(ans) + float(out["evidence_score"])
|
|
57
|
+
return out
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def main(argv: list[str] | None = None) -> int:
|
|
61
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
62
|
+
parser.add_argument("jsonl", type=Path, help="Per-query telemetry JSONL")
|
|
63
|
+
parser.add_argument("--pretty", action="store_true")
|
|
64
|
+
parser.add_argument("--markdown", action="store_true")
|
|
65
|
+
args = parser.parse_args(argv)
|
|
66
|
+
|
|
67
|
+
if not args.jsonl.is_file():
|
|
68
|
+
print(f"error: not found: {args.jsonl}", file=sys.stderr)
|
|
69
|
+
return 1
|
|
70
|
+
|
|
71
|
+
rows: list[dict[str, Any]] = []
|
|
72
|
+
for line in args.jsonl.read_text(encoding="utf-8").splitlines():
|
|
73
|
+
stripped = line.strip()
|
|
74
|
+
if not stripped:
|
|
75
|
+
continue
|
|
76
|
+
raw = json.loads(stripped)
|
|
77
|
+
if isinstance(raw, dict):
|
|
78
|
+
rows.append(enrich_record(raw))
|
|
79
|
+
|
|
80
|
+
evidence_total = sum(int(r.get("evidence_score", 0)) for r in rows)
|
|
81
|
+
combined: list[float] = []
|
|
82
|
+
for r in rows:
|
|
83
|
+
c = r.get("combined_score")
|
|
84
|
+
if isinstance(c, (int, float)):
|
|
85
|
+
combined.append(float(c))
|
|
86
|
+
|
|
87
|
+
summary = {
|
|
88
|
+
"n": len(rows),
|
|
89
|
+
"evidence_score_total": evidence_total,
|
|
90
|
+
"evidence_score_max": len(rows) * 2,
|
|
91
|
+
"avg_evidence_score": 0.0 if not rows else evidence_total / len(rows),
|
|
92
|
+
"avg_combined_score": 0.0 if not combined else sum(combined) / len(combined),
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if args.markdown:
|
|
96
|
+
print("## Evidence scores (REC-11)\n")
|
|
97
|
+
print("| query_id | evidence_score | read_verify | semantic_exec |")
|
|
98
|
+
print("| --- | ---: | --- | --- |")
|
|
99
|
+
for r in rows:
|
|
100
|
+
print(
|
|
101
|
+
f"| {r.get('query_id','')} | {r.get('evidence_score',0)} | "
|
|
102
|
+
f"{r.get('read_verification_done')} | {r.get('semantic_executed')} |"
|
|
103
|
+
)
|
|
104
|
+
print(f"\nTotal evidence: **{evidence_total}** / {summary['evidence_score_max']}")
|
|
105
|
+
else:
|
|
106
|
+
payload = {"summary": summary, "records": rows}
|
|
107
|
+
print(json.dumps(payload, ensure_ascii=False, indent=2 if args.pretty else None))
|
|
108
|
+
return 0
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
if __name__ == "__main__":
|
|
112
|
+
raise SystemExit(main())
|