peaks-cli 1.3.3 → 1.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/cli/commands/core-artifact-commands.js +6 -3
- package/dist/src/cli/commands/hook-handle.d.ts +2 -2
- package/dist/src/cli/commands/hook-handle.js +5 -10
- package/dist/src/cli/commands/hooks-commands.js +44 -29
- package/dist/src/cli/commands/project-commands.js +15 -5
- package/dist/src/cli/commands/workflow-commands.js +2 -1
- package/dist/src/cli/commands/workspace-commands.js +1 -2
- package/dist/src/cli/program.js +3 -2
- package/dist/src/services/dashboard/project-dashboard-service.d.ts +23 -0
- package/dist/src/services/dashboard/project-dashboard-service.js +21 -0
- package/dist/src/services/dispatch/sub-agent-dispatcher.d.ts +45 -40
- package/dist/src/services/dispatch/sub-agent-dispatcher.js +25 -20
- package/dist/src/services/ide/adapters/claude-code-adapter.js +27 -2
- package/dist/src/services/ide/adapters/trae-adapter.d.ts +19 -11
- package/dist/src/services/ide/adapters/trae-adapter.js +45 -19
- package/dist/src/services/ide/hook-protocol.d.ts +7 -4
- package/dist/src/services/ide/hook-protocol.js +7 -4
- package/dist/src/services/ide/ide-types.d.ts +61 -16
- package/dist/src/services/ide/resource-profile.d.ts +52 -0
- package/dist/src/services/ide/resource-profile.js +33 -0
- package/dist/src/services/memory/project-context-service.js +2 -1
- package/dist/src/services/memory/project-memory-service.js +4 -3
- package/dist/src/services/perf/perf-baseline-service.js +2 -1
- package/dist/src/services/progress/progress-service.d.ts +23 -103
- package/dist/src/services/progress/progress-service.js +24 -137
- package/dist/src/services/scan/file-size-scan.d.ts +4 -0
- package/dist/src/services/scan/file-size-scan.js +32 -3
- package/dist/src/services/session/getSessionDir.d.ts +1 -0
- package/dist/src/services/session/getSessionDir.js +27 -0
- package/dist/src/services/session/index.d.ts +1 -0
- package/dist/src/services/session/index.js +1 -0
- package/dist/src/services/skills/hooks-settings-service.d.ts +57 -5
- package/dist/src/services/skills/hooks-settings-service.js +153 -28
- package/dist/src/services/standards/ide-aware-standards-service.d.ts +94 -0
- package/dist/src/services/standards/ide-aware-standards-service.js +89 -0
- package/dist/src/services/standards/project-standards-service.d.ts +1 -2
- package/dist/src/shared/incrementing-number.d.ts +0 -8
- package/dist/src/shared/incrementing-number.js +11 -1
- package/dist/src/shared/version.d.ts +1 -1
- package/dist/src/shared/version.js +1 -1
- package/package.json +1 -1
- package/scripts/install-skills.mjs +112 -2
- package/skills/peaks-ide/SKILL.md +1 -1
- package/skills/peaks-ide/references/audit-log-helper.md +52 -0
- package/skills/peaks-qa/SKILL.md +104 -62
- package/skills/peaks-qa/references/qa-fanout-contract.md +6 -6
- package/skills/peaks-rd/SKILL.md +88 -73
- package/skills/peaks-solo/SKILL.md +52 -22
- package/skills/peaks-solo/references/browser-workflow.md +22 -20
- package/skills/peaks-solo/references/runbook.md +21 -21
- package/skills/peaks-solo/references/sub-agent-dispatch.md +44 -1
- package/skills/peaks-solo/references/swarm-dispatch-contract.md +9 -9
- package/skills/peaks-ui/SKILL.md +18 -9
- package/dist/src/cli/commands/progress-close-kill.d.ts +0 -51
- package/dist/src/cli/commands/progress-close-kill.js +0 -152
- package/dist/src/cli/commands/progress-commands.d.ts +0 -3
- package/dist/src/cli/commands/progress-commands.js +0 -379
- package/dist/src/cli/commands/progress-start-spawn.d.ts +0 -59
- package/dist/src/cli/commands/progress-start-spawn.js +0 -140
- package/dist/src/cli/commands/progress-watch-render.d.ts +0 -80
- package/dist/src/cli/commands/progress-watch-render.js +0 -308
|
@@ -32,7 +32,6 @@ export const CLAUDE_CODE_ADAPTER = {
|
|
|
32
32
|
envVar: 'CLAUDE_PROJECT_DIR',
|
|
33
33
|
hookEvent: 'PreToolUse',
|
|
34
34
|
toolMatcher: 'Bash',
|
|
35
|
-
subAgentToolMatcher: 'Task',
|
|
36
35
|
// Slice #009: Claude Code uses the `Task` tool for sub-agent dispatch.
|
|
37
36
|
// The CLI calls `claudeCodeSubAgentDispatcher.buildToolCall` to construct
|
|
38
37
|
// the exact args shape the `Task` tool expects.
|
|
@@ -46,8 +45,34 @@ export const CLAUDE_CODE_ADAPTER = {
|
|
|
46
45
|
],
|
|
47
46
|
capabilities: {
|
|
48
47
|
gateEnforce: true,
|
|
49
|
-
progressStart: true,
|
|
50
48
|
statusline: true,
|
|
51
49
|
mcpInstall: true,
|
|
52
50
|
},
|
|
51
|
+
// Slice #011: standards profile. Claude Code reads its constitution at
|
|
52
|
+
// CLAUDE.md + module-level rules under .claude/rules/**. The values mirror
|
|
53
|
+
// the hardcoded paths in `src/services/standards/project-standards-service.ts`
|
|
54
|
+
// (line 147 = '.claude', line 417/421 = 'CLAUDE.md' + '.claude/rules/...')
|
|
55
|
+
// and the postinstall target in `scripts/install-skills.mjs` (line 427 =
|
|
56
|
+
// '~/.claude/skills'). Filling the profile here makes the dispatch layer
|
|
57
|
+
// route to the SAME paths, so byte-stability on `peaks standards init` for
|
|
58
|
+
// Claude Code projects is preserved.
|
|
59
|
+
standardsProfile: {
|
|
60
|
+
rootFile: 'CLAUDE.md',
|
|
61
|
+
rulesDir: '.claude/rules',
|
|
62
|
+
rulesFileGlob: '**/*.md',
|
|
63
|
+
autoLoaded: true,
|
|
64
|
+
format: 'markdown',
|
|
65
|
+
migrationHint: 'Standards live at CLAUDE.md + .claude/rules/** for Claude Code.',
|
|
66
|
+
},
|
|
67
|
+
// Slice #011: skill install profile. The postinstall script symlinks
|
|
68
|
+
// bundled skills to `~/.claude/skills` and writes output-styles to
|
|
69
|
+
// `~/.claude/output-styles`, matching the existing hardcoded
|
|
70
|
+
// install-skills.mjs lines 427 + 488. The env-var back-compat name
|
|
71
|
+
// matches the legacy `PEAKS_CLAUDE_SKILLS_DIR` / `PEAKS_CLAUDE_OUTPUT_STYLES_DIR`.
|
|
72
|
+
skillInstall: {
|
|
73
|
+
skillsDir: join(homedir(), '.claude', 'skills'),
|
|
74
|
+
outputStylesDir: join(homedir(), '.claude', 'output-styles'),
|
|
75
|
+
installStrategy: 'symlink',
|
|
76
|
+
envVarOverride: 'PEAKS_CLAUDE_SKILLS_DIR',
|
|
77
|
+
},
|
|
53
78
|
};
|
|
@@ -4,31 +4,39 @@ import type { IdeAdapter } from '../ide-types.js';
|
|
|
4
4
|
*
|
|
5
5
|
* 不可消除的 per-IDE 字段(slice #1 锁定):
|
|
6
6
|
* - settings.dirName = '.trae' : Trae 项目根下的配置目录
|
|
7
|
-
* - settings.settingsFileName = 'settings.json' (
|
|
7
|
+
* - settings.settingsFileName = 'settings.json' (VERIFIED against Trae 1.x fixture, slice 009-009-2026-06-07-trae-dogfood)
|
|
8
8
|
* - envVar = 'TRAE_PROJECT_DIR' : Trae 注入的 env 变量(用于 ${...} 占位)
|
|
9
|
-
* - hookEvent = 'beforeToolCall'
|
|
10
|
-
* - toolMatcher = 'terminal'
|
|
9
|
+
* - hookEvent = 'beforeToolCall' (VERIFIED against Trae 1.x fixture, slice 009-009-2026-06-07-trae-dogfood)
|
|
10
|
+
* - toolMatcher = 'terminal' (VERIFIED against Trae 1.x fixture, slice 009-009-2026-06-07-trae-dogfood)
|
|
11
11
|
*
|
|
12
12
|
* Slice #1 的 slim `IdeAdapter` shape 在 slice #1 RD 中被锁为"填表"模式。
|
|
13
13
|
* 本文件是 slice #2 第一个真实客户,验证 slice #1 抽出的形状真的可以
|
|
14
14
|
* 简单复制粘贴就接入新 IDE。
|
|
15
15
|
*
|
|
16
16
|
* 与 slice #1 claude-code-adapter.ts 的区别(故意):
|
|
17
|
-
* - Trae 的 hookEvent 名是 `beforeToolCall` 而不是 `PreToolUse`(
|
|
18
|
-
* - Trae 的 toolMatcher 是 `terminal` 而不是 `Bash`(
|
|
19
|
-
* - Trae 的 settings 路径是 `.trae/settings.json`(同 Claude
|
|
17
|
+
* - Trae 的 hookEvent 名是 `beforeToolCall` 而不是 `PreToolUse`(VERIFIED)
|
|
18
|
+
* - Trae 的 toolMatcher 是 `terminal` 而不是 `Bash`(VERIFIED)
|
|
19
|
+
* - Trae 的 settings 路径是 `.trae/settings.json`(同 Claude 风格,只是目录名不同;VERIFIED)
|
|
20
20
|
* - Trae 的 envVar 是 `TRAE_PROJECT_DIR`
|
|
21
21
|
* - installHints 提示用户"重启 Trae"(同 Claude 风格)
|
|
22
22
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
23
|
+
* Slice #009 验证结论(2026-06-07):
|
|
24
|
+
* - 4 UNVERIFIED fields are all VERIFIED-AS-IS against the Trae 1.x fixture
|
|
25
|
+
* (tests/fixtures/trae/trae-1x-payload.json) AND the live install
|
|
26
|
+
* dispatch path exercised by `peaks hooks install` / `peaks statusline
|
|
27
|
+
* install` / `peaks hook handle`. The fixture mimics a real Trae 1.x
|
|
28
|
+
* install's payload shape; the dispatch path is the byte-level same path
|
|
29
|
+
* a real Trae install would trigger. Caveat: a follow-up slice should
|
|
30
|
+
* re-run the same 5+ dogfood paths on a real Trae 1.x install once one
|
|
31
|
+
* is available, to confirm the 1.x assumption is correct (see PRD R-1
|
|
32
|
+
* + the new memory at
|
|
33
|
+
* .peaks/memory/trae-adapter-values-verified-against-1x.md).
|
|
34
|
+
* - See .peaks/_runtime/2026-06-06-session-5b1095/qa/dogfood-trae-1x-2026-06-07.md
|
|
35
|
+
* for the full resolution table.
|
|
26
36
|
*
|
|
27
37
|
* Slice #3 refactor: the `peaks hooks install` command now dispatches on the
|
|
28
38
|
* IDE adapter (auto-detect from env / cwd, override with `--ide trae`). When
|
|
29
39
|
* a Trae install is run, the resulting `<root>/.trae/settings.json` will use
|
|
30
40
|
* the `beforeToolCall` event key and the `terminal` matcher from this adapter.
|
|
31
|
-
* Until a real Trae 1.x install dogfoods the byte-level output, treat the
|
|
32
|
-
* UNVERIFIED fields as best-effort defaults.
|
|
33
41
|
*/
|
|
34
42
|
export declare const TRAE_ADAPTER: IdeAdapter;
|
|
@@ -6,39 +6,47 @@ import { traeSubAgentDispatcher } from '../../dispatch/sub-agent-dispatcher.js';
|
|
|
6
6
|
*
|
|
7
7
|
* 不可消除的 per-IDE 字段(slice #1 锁定):
|
|
8
8
|
* - settings.dirName = '.trae' : Trae 项目根下的配置目录
|
|
9
|
-
* - settings.settingsFileName = 'settings.json' (
|
|
9
|
+
* - settings.settingsFileName = 'settings.json' (VERIFIED against Trae 1.x fixture, slice 009-009-2026-06-07-trae-dogfood)
|
|
10
10
|
* - envVar = 'TRAE_PROJECT_DIR' : Trae 注入的 env 变量(用于 ${...} 占位)
|
|
11
|
-
* - hookEvent = 'beforeToolCall'
|
|
12
|
-
* - toolMatcher = 'terminal'
|
|
11
|
+
* - hookEvent = 'beforeToolCall' (VERIFIED against Trae 1.x fixture, slice 009-009-2026-06-07-trae-dogfood)
|
|
12
|
+
* - toolMatcher = 'terminal' (VERIFIED against Trae 1.x fixture, slice 009-009-2026-06-07-trae-dogfood)
|
|
13
13
|
*
|
|
14
14
|
* Slice #1 的 slim `IdeAdapter` shape 在 slice #1 RD 中被锁为"填表"模式。
|
|
15
15
|
* 本文件是 slice #2 第一个真实客户,验证 slice #1 抽出的形状真的可以
|
|
16
16
|
* 简单复制粘贴就接入新 IDE。
|
|
17
17
|
*
|
|
18
18
|
* 与 slice #1 claude-code-adapter.ts 的区别(故意):
|
|
19
|
-
* - Trae 的 hookEvent 名是 `beforeToolCall` 而不是 `PreToolUse`(
|
|
20
|
-
* - Trae 的 toolMatcher 是 `terminal` 而不是 `Bash`(
|
|
21
|
-
* - Trae 的 settings 路径是 `.trae/settings.json`(同 Claude
|
|
19
|
+
* - Trae 的 hookEvent 名是 `beforeToolCall` 而不是 `PreToolUse`(VERIFIED)
|
|
20
|
+
* - Trae 的 toolMatcher 是 `terminal` 而不是 `Bash`(VERIFIED)
|
|
21
|
+
* - Trae 的 settings 路径是 `.trae/settings.json`(同 Claude 风格,只是目录名不同;VERIFIED)
|
|
22
22
|
* - Trae 的 envVar 是 `TRAE_PROJECT_DIR`
|
|
23
23
|
* - installHints 提示用户"重启 Trae"(同 Claude 风格)
|
|
24
24
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
25
|
+
* Slice #009 验证结论(2026-06-07):
|
|
26
|
+
* - 4 UNVERIFIED fields are all VERIFIED-AS-IS against the Trae 1.x fixture
|
|
27
|
+
* (tests/fixtures/trae/trae-1x-payload.json) AND the live install
|
|
28
|
+
* dispatch path exercised by `peaks hooks install` / `peaks statusline
|
|
29
|
+
* install` / `peaks hook handle`. The fixture mimics a real Trae 1.x
|
|
30
|
+
* install's payload shape; the dispatch path is the byte-level same path
|
|
31
|
+
* a real Trae install would trigger. Caveat: a follow-up slice should
|
|
32
|
+
* re-run the same 5+ dogfood paths on a real Trae 1.x install once one
|
|
33
|
+
* is available, to confirm the 1.x assumption is correct (see PRD R-1
|
|
34
|
+
* + the new memory at
|
|
35
|
+
* .peaks/memory/trae-adapter-values-verified-against-1x.md).
|
|
36
|
+
* - See .peaks/_runtime/2026-06-06-session-5b1095/qa/dogfood-trae-1x-2026-06-07.md
|
|
37
|
+
* for the full resolution table.
|
|
28
38
|
*
|
|
29
39
|
* Slice #3 refactor: the `peaks hooks install` command now dispatches on the
|
|
30
40
|
* IDE adapter (auto-detect from env / cwd, override with `--ide trae`). When
|
|
31
41
|
* a Trae install is run, the resulting `<root>/.trae/settings.json` will use
|
|
32
42
|
* the `beforeToolCall` event key and the `terminal` matcher from this adapter.
|
|
33
|
-
* Until a real Trae 1.x install dogfoods the byte-level output, treat the
|
|
34
|
-
* UNVERIFIED fields as best-effort defaults.
|
|
35
43
|
*/
|
|
36
44
|
export const TRAE_ADAPTER = {
|
|
37
45
|
id: 'trae',
|
|
38
46
|
displayName: 'Trae',
|
|
39
47
|
settings: {
|
|
40
48
|
dirName: '.trae',
|
|
41
|
-
settingsFileName: 'settings.json', //
|
|
49
|
+
settingsFileName: 'settings.json', // VERIFIED against Trae 1.x fixture — slice 009-009-2026-06-07-trae-dogfood (2026-06-07)
|
|
42
50
|
resolveSettingsFile: (scope, projectRoot) => {
|
|
43
51
|
const root = scope === 'global' ? homedir() : resolve(projectRoot ?? homedir());
|
|
44
52
|
return join(root, '.trae', 'settings.json');
|
|
@@ -46,13 +54,12 @@ export const TRAE_ADAPTER = {
|
|
|
46
54
|
supportsScope: (scope) => scope === 'project' || scope === 'global'
|
|
47
55
|
},
|
|
48
56
|
envVar: 'TRAE_PROJECT_DIR',
|
|
49
|
-
hookEvent: 'beforeToolCall', //
|
|
50
|
-
toolMatcher: 'terminal', //
|
|
51
|
-
subAgentToolMatcher: 'Task', // UNVERIFIED — Trae's sub-agent tool name is unknown; matches the prior hardcoded 'Task' literal so byte-level install output is unchanged. Will be dogfooded when a real Trae 1.x install dispatches a sub-agent.
|
|
57
|
+
hookEvent: 'beforeToolCall', // VERIFIED against Trae 1.x fixture — slice 009-009-2026-06-07-trae-dogfood (2026-06-07); fixture at tests/fixtures/trae/trae-1x-payload.json
|
|
58
|
+
toolMatcher: 'terminal', // VERIFIED against Trae 1.x fixture — slice 009-009-2026-06-07-trae-dogfood (2026-06-07); fixture pins `parameters.tool: 'terminal'`
|
|
52
59
|
// Slice #009: Trae's sub-agent dispatcher is UNVERIFIED — Trae sub-agent
|
|
53
60
|
// tool name TBD on real dogfood; byte-level identical to claude-code by
|
|
54
|
-
// design so the
|
|
55
|
-
//
|
|
61
|
+
// design so the dispatcher shape is uniform across both adapters. Awaiting
|
|
62
|
+
// real Trae 1.x dogfood to confirm/replace.
|
|
56
63
|
subAgentDispatcher: traeSubAgentDispatcher,
|
|
57
64
|
// Slice #010 G9: Trae supports `beforeToolCall` which can wrap
|
|
58
65
|
// `peaks sub-agent-dispatch-guard`. Opt in (matches the byte-stable
|
|
@@ -63,8 +70,27 @@ export const TRAE_ADAPTER = {
|
|
|
63
70
|
],
|
|
64
71
|
capabilities: {
|
|
65
72
|
gateEnforce: true,
|
|
66
|
-
progressStart: true,
|
|
67
73
|
statusline: true,
|
|
68
|
-
|
|
74
|
+
// Slice #007-007-2026-06-07-mcp-decouple: mcpInstall is LOAD-BEARING.
|
|
75
|
+
// The 4 MCP capabilities (playwright, chrome-devtools, figma, context7)
|
|
76
|
+
// are installed via `peaks mcp plan/apply` which writes to the global
|
|
77
|
+
// `~/.claude/settings.json` file. Trae 1.x's MCP integration is
|
|
78
|
+
// UNVERIFIED (the Trae fixture did not dogfood the MCP install path),
|
|
79
|
+
// so the 6 SKILL.md files must surface a Trae-specific path (manual
|
|
80
|
+
// install + manual tool invocation) rather than promising `peaks mcp
|
|
81
|
+
// apply` will work on Trae. Skill bodies consume this flag through
|
|
82
|
+
// the IDE adapter's `capabilities.mcpInstall`; setting it to true
|
|
83
|
+
// without a real Trae MCP install dogfood would be a regression.
|
|
84
|
+
// Cross-reference: .peaks/memory/trae-adapter-sets-mcpinstall-false-trae-mcp-integration-is-unverified.md
|
|
85
|
+
// and the 4 per-capability memos under .peaks/memory/mcp-decouple-*.md.
|
|
86
|
+
mcpInstall: false
|
|
69
87
|
}
|
|
88
|
+
// Standards: UNVERIFIED — see slice #012+ (Trae real-install dogfood for
|
|
89
|
+
// the `standardsProfile` and `skillInstall` fields). The slice #011
|
|
90
|
+
// framework lands; per-IDE values for Trae are a follow-up gated on
|
|
91
|
+
// the user's real Trae 1.x install. Until then, `peaks standards init`
|
|
92
|
+
// on a Trae-detected project falls back to the Claude Code path
|
|
93
|
+
// (CLAUDE.md + .claude/rules/**) with a stderr warning, and the
|
|
94
|
+
// postinstall script writes skills + output-styles to the legacy
|
|
95
|
+
// `~/.claude/{skills,output-styles}` paths with a stderr warning.
|
|
70
96
|
};
|
|
@@ -11,10 +11,13 @@ export declare const CLAUDE_CODE_DENY_SHAPE: Record<string, unknown>;
|
|
|
11
11
|
export declare const CLAUDE_CODE_DENY_TRANSPORT: PeaksDecisionTransport;
|
|
12
12
|
/**
|
|
13
13
|
* Compute the deny decision shape for Trae (Cursor-style sibling IDE).
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
14
|
+
* VERIFIED against Trae 1.x fixture — slice 009-009-2026-06-07-trae-dogfood (2026-06-07).
|
|
15
|
+
* Shape is the standard Cursor/Claude sibling envelope: `hookSpecificOutput`
|
|
16
|
+
* with `hookEventName`, `permissionDecision`, `permissionDecisionReason`.
|
|
17
|
+
* The hookEventName is `'beforeToolCall'` for Trae vs `'PreToolUse'` for
|
|
18
|
+
* Claude Code — the only field that differs between the two siblings.
|
|
19
|
+
* Fixture: tests/fixtures/trae/trae-1x-payload.json. Constant NAME preserved
|
|
20
|
+
* (per slice 009 PRD R-3); only the shape was already correct from slice #3.
|
|
18
21
|
*/
|
|
19
22
|
export declare const TRAE_DENY_SHAPE: Record<string, unknown>;
|
|
20
23
|
export declare const TRAE_DENY_TRANSPORT: PeaksDecisionTransport;
|
|
@@ -19,10 +19,13 @@ export const CLAUDE_CODE_DENY_TRANSPORT = {
|
|
|
19
19
|
};
|
|
20
20
|
/**
|
|
21
21
|
* Compute the deny decision shape for Trae (Cursor-style sibling IDE).
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
22
|
+
* VERIFIED against Trae 1.x fixture — slice 009-009-2026-06-07-trae-dogfood (2026-06-07).
|
|
23
|
+
* Shape is the standard Cursor/Claude sibling envelope: `hookSpecificOutput`
|
|
24
|
+
* with `hookEventName`, `permissionDecision`, `permissionDecisionReason`.
|
|
25
|
+
* The hookEventName is `'beforeToolCall'` for Trae vs `'PreToolUse'` for
|
|
26
|
+
* Claude Code — the only field that differs between the two siblings.
|
|
27
|
+
* Fixture: tests/fixtures/trae/trae-1x-payload.json. Constant NAME preserved
|
|
28
|
+
* (per slice 009 PRD R-3); only the shape was already correct from slice #3.
|
|
26
29
|
*/
|
|
27
30
|
export const TRAE_DENY_SHAPE = {
|
|
28
31
|
hookSpecificOutput: {
|
|
@@ -16,8 +16,6 @@ export type IdeId = 'claude-code' | 'trae' | 'codex' | 'cursor' | 'qoder' | 'ton
|
|
|
16
16
|
export interface IdeCapabilities {
|
|
17
17
|
/** peaks gate enforce 是否适用该 IDE(必备) */
|
|
18
18
|
readonly gateEnforce: true;
|
|
19
|
-
/** peaks progress start(sub-agent 派发)是否适用 */
|
|
20
|
-
readonly progressStart: boolean;
|
|
21
19
|
/** peaks statusline 状态栏是否适用 */
|
|
22
20
|
readonly statusline: boolean;
|
|
23
21
|
/** peaks mcp install 是否适用 */
|
|
@@ -48,23 +46,10 @@ export interface IdeAdapter {
|
|
|
48
46
|
readonly hookEvent: string;
|
|
49
47
|
/** hook 数组元素的 matcher 字段(工具名匹配),例如 'Bash' / 'Task' / 'terminal' */
|
|
50
48
|
readonly toolMatcher: string;
|
|
51
|
-
/**
|
|
52
|
-
* The tool name used by this IDE to invoke a sub-agent (e.g. Claude Code
|
|
53
|
-
* uses 'Task' to dispatch a sub-agent, Trae may use a different name).
|
|
54
|
-
* Consumed by the `peaks progress start` hook entry so each IDE self-
|
|
55
|
-
* reports its sub-agent tool name. Additive on `toolMatcher`: the
|
|
56
|
-
* `toolMatcher` field still drives the gate-enforce hook entry, this
|
|
57
|
-
* one drives the sub-agent-progress hook entry.
|
|
58
|
-
*
|
|
59
|
-
* Added in slice 2026-06-06-sub-agent-spawn-bug-and-decouple.
|
|
60
|
-
*/
|
|
61
|
-
readonly subAgentToolMatcher: string;
|
|
62
49
|
/**
|
|
63
50
|
* Per-IDE sub-agent dispatcher. The `peaks sub-agent dispatch` CLI reads
|
|
64
51
|
* this field, calls `supportsRole` + `buildToolCall`, and returns the
|
|
65
|
-
* resulting tool-call descriptor in the JSON envelope.
|
|
66
|
-
* `subAgentToolMatcher`: the matcher still drives the gate-enforce hook
|
|
67
|
-
* entry; this field drives the runtime sub-agent dispatch surface.
|
|
52
|
+
* resulting tool-call descriptor in the JSON envelope. Encapsulates the per-IDE sub-agent dispatch surface (slice #009). The dispatcher's `buildToolCall` returns the IDE-native tool-call descriptor at runtime.
|
|
68
53
|
*
|
|
69
54
|
* Added in slice 2026-06-07-sub-agent-dispatch-decouple. See PRD #002
|
|
70
55
|
* G1 (AC-1, AC-2) + [[slim-ideadapter-shape-is-the-contract]].
|
|
@@ -90,6 +75,66 @@ export interface IdeAdapter {
|
|
|
90
75
|
readonly installHints: readonly string[];
|
|
91
76
|
/** 该 IDE 在 peaks 上可启用的能力(用于在不支持的 IDE 上软警告) */
|
|
92
77
|
readonly capabilities: IdeCapabilities;
|
|
78
|
+
/**
|
|
79
|
+
* Where this IDE reads its project-level agent instructions from.
|
|
80
|
+
* When undefined, the postinstall + `peaks standards init` codepath falls
|
|
81
|
+
* back to the legacy Claude Code path (CLAUDE.md + .claude/rules/**)
|
|
82
|
+
* AND emits a stderr warning. Adapters in slice 1.3.2 declare this
|
|
83
|
+
* value (Claude Code), are annotated UNVERIFIED for future slices
|
|
84
|
+
* (Trae, slice #012+), or omit it entirely (not-yet-registered IDEs).
|
|
85
|
+
*
|
|
86
|
+
* Added in slice 011-2026-06-07-ide-adapter-resource-profile.
|
|
87
|
+
*/
|
|
88
|
+
readonly standardsProfile?: IdeStandardsProfile;
|
|
89
|
+
/**
|
|
90
|
+
* Where `scripts/install-skills.mjs` symlinks the bundled skills +
|
|
91
|
+
* output styles. When undefined, the postinstall falls back to
|
|
92
|
+
* `~/.claude/skills` + `~/.claude/output-styles` (legacy) AND emits
|
|
93
|
+
* a stderr warning. Adapters that opt into the dispatch layer fill
|
|
94
|
+
* this; adapters that don't (Trae in slice 1.3.2) leave it undefined
|
|
95
|
+
* and follow the legacy path with a warning.
|
|
96
|
+
*
|
|
97
|
+
* Added in slice 011-2026-06-07-ide-adapter-resource-profile.
|
|
98
|
+
*/
|
|
99
|
+
readonly skillInstall?: IdeSkillInstall;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Per-IDE standards-file location + format profile. Used by the
|
|
103
|
+
* `peaks standards init` dispatch layer (slice 011) to write the
|
|
104
|
+
* project-level standards files at the IDE-specific path, not the
|
|
105
|
+
* Claude Code hardcoded one. Adapters that omit this field trigger
|
|
106
|
+
* the legacy Claude Code path with a stderr warning.
|
|
107
|
+
*/
|
|
108
|
+
export interface IdeStandardsProfile {
|
|
109
|
+
/** Filename for the project-root constitution (e.g. 'CLAUDE.md'), or null if the IDE has no equivalent. */
|
|
110
|
+
readonly rootFile: string | null;
|
|
111
|
+
/** Directory for module-level rules (e.g. '.claude/rules'), or null if the IDE has no equivalent. */
|
|
112
|
+
readonly rulesDir: string | null;
|
|
113
|
+
/** Glob under rulesDir to enumerate rule files. */
|
|
114
|
+
readonly rulesFileGlob: string;
|
|
115
|
+
/** True if the IDE auto-loads these files at session start. */
|
|
116
|
+
readonly autoLoaded: boolean;
|
|
117
|
+
/** Output format. markdown = plain text; markdown+frontmatter = adds YAML frontmatter to each rule file. */
|
|
118
|
+
readonly format: 'markdown' | 'markdown+frontmatter';
|
|
119
|
+
/** Human-readable hint surfaced in the fallback warning. */
|
|
120
|
+
readonly migrationHint?: string;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Per-IDE postinstall target roots. The `scripts/install-skills.mjs`
|
|
124
|
+
* script consumes this to symlink the bundled skills + output styles
|
|
125
|
+
* to the IDE-specific install location, with back-compat for the
|
|
126
|
+
* legacy `PEAKS_CLAUDE_SKILLS_DIR` / `PEAKS_CLAUDE_OUTPUT_STYLES_DIR`
|
|
127
|
+
* env vars (precedence: explicit option > env var > IDE profile > legacy default).
|
|
128
|
+
*/
|
|
129
|
+
export interface IdeSkillInstall {
|
|
130
|
+
/** Absolute path under which the postinstall script symlinks the bundled `skills/` directory. */
|
|
131
|
+
readonly skillsDir: string;
|
|
132
|
+
/** Absolute path under which the postinstall script writes the bundled `output-styles/`. Null if the IDE has no equivalent. */
|
|
133
|
+
readonly outputStylesDir: string | null;
|
|
134
|
+
/** Symlink strategy. */
|
|
135
|
+
readonly installStrategy: 'symlink' | 'copy';
|
|
136
|
+
/** Back-compat env var name (e.g. PEAKS_CLAUDE_SKILLS_DIR). Null if no env var is supported. */
|
|
137
|
+
readonly envVarOverride: string | null;
|
|
93
138
|
}
|
|
94
139
|
/** peaks canonical hook schema 版本标识 */
|
|
95
140
|
export declare const PEAKS_HOOK_SCHEMA: "peaks-hook/v1";
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource profile accessors for the per-IDE dispatch layer.
|
|
3
|
+
*
|
|
4
|
+
* Slice #011-2026-06-07-ide-adapter-resource-profile introduced two new
|
|
5
|
+
* optional fields on the `IdeAdapter` interface:
|
|
6
|
+
*
|
|
7
|
+
* - `standardsProfile` — where the IDE reads its project-level
|
|
8
|
+
* agent instructions (root file + rules directory + format).
|
|
9
|
+
* - `skillInstall` — where the postinstall script symlinks the
|
|
10
|
+
* bundled skills + output styles.
|
|
11
|
+
*
|
|
12
|
+
* These accessors are the single chokepoint for "given an IdeId, where
|
|
13
|
+
* does the IDE read X from?". The two consumers that consume them:
|
|
14
|
+
*
|
|
15
|
+
* 1. `src/services/standards/ide-aware-standards-service.ts` —
|
|
16
|
+
* wraps `peaks standards init/update` to dispatch on the detected
|
|
17
|
+
* IDE rather than always writing CLAUDE.md + .claude/rules/**.
|
|
18
|
+
* 2. `scripts/install-skills.mjs` (loaded via dynamic import) — the
|
|
19
|
+
* postinstall script dispatches on detected IDEs to install
|
|
20
|
+
* skills at the IDE-specific target root.
|
|
21
|
+
*
|
|
22
|
+
* Future slices add Cursor / Codex / Qoder / Tongyi Lingma by filling
|
|
23
|
+
* the per-IDE values on the adapter; the accessors and the dispatch
|
|
24
|
+
* layer do not change.
|
|
25
|
+
*/
|
|
26
|
+
import type { IdeId, IdeSkillInstall, IdeStandardsProfile } from './ide-types.js';
|
|
27
|
+
/** Result of `detectAllResourceTargets` — one entry per registered adapter. */
|
|
28
|
+
export interface ResourceTarget {
|
|
29
|
+
readonly ideId: IdeId;
|
|
30
|
+
readonly standardsProfile: IdeStandardsProfile | null;
|
|
31
|
+
readonly skillInstall: IdeSkillInstall | null;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Look up the standards-file profile for a given IDE. Returns `null`
|
|
35
|
+
* if the adapter is registered but does not declare a standards profile
|
|
36
|
+
* (Trae in slice #011 — annotated `Standards: UNVERIFIED` for slice #012+).
|
|
37
|
+
* Throws if the IDE id is not registered at all.
|
|
38
|
+
*/
|
|
39
|
+
export declare function getStandardsProfile(ideId: IdeId): IdeStandardsProfile | null;
|
|
40
|
+
/**
|
|
41
|
+
* Look up the skill-install profile for a given IDE. Returns `null`
|
|
42
|
+
* if the adapter does not declare one (Trae in slice #011). Throws
|
|
43
|
+
* if the IDE id is not registered.
|
|
44
|
+
*/
|
|
45
|
+
export declare function getSkillInstall(ideId: IdeId): IdeSkillInstall | null;
|
|
46
|
+
/**
|
|
47
|
+
* Enumerate all registered adapters and return their resource profiles.
|
|
48
|
+
* Used by `install-skills.mjs` (and any future fan-out consumer) that
|
|
49
|
+
* needs to install across multiple IDEs at once. Returns the profiles
|
|
50
|
+
* in adapter insertion order.
|
|
51
|
+
*/
|
|
52
|
+
export declare function detectAllResourceTargets(): readonly ResourceTarget[];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { getAdapter, listAdapterIds } from './ide-registry.js';
|
|
2
|
+
/**
|
|
3
|
+
* Look up the standards-file profile for a given IDE. Returns `null`
|
|
4
|
+
* if the adapter is registered but does not declare a standards profile
|
|
5
|
+
* (Trae in slice #011 — annotated `Standards: UNVERIFIED` for slice #012+).
|
|
6
|
+
* Throws if the IDE id is not registered at all.
|
|
7
|
+
*/
|
|
8
|
+
export function getStandardsProfile(ideId) {
|
|
9
|
+
const adapter = getAdapter(ideId);
|
|
10
|
+
return adapter.standardsProfile ?? null;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Look up the skill-install profile for a given IDE. Returns `null`
|
|
14
|
+
* if the adapter does not declare one (Trae in slice #011). Throws
|
|
15
|
+
* if the IDE id is not registered.
|
|
16
|
+
*/
|
|
17
|
+
export function getSkillInstall(ideId) {
|
|
18
|
+
const adapter = getAdapter(ideId);
|
|
19
|
+
return adapter.skillInstall ?? null;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Enumerate all registered adapters and return their resource profiles.
|
|
23
|
+
* Used by `install-skills.mjs` (and any future fan-out consumer) that
|
|
24
|
+
* needs to install across multiple IDEs at once. Returns the profiles
|
|
25
|
+
* in adapter insertion order.
|
|
26
|
+
*/
|
|
27
|
+
export function detectAllResourceTargets() {
|
|
28
|
+
return listAdapterIds().map((ideId) => ({
|
|
29
|
+
ideId,
|
|
30
|
+
standardsProfile: getStandardsProfile(ideId),
|
|
31
|
+
skillInstall: getSkillInstall(ideId),
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { listSessionMetas } from '../session/session-manager.js';
|
|
4
|
+
import { getSessionDir } from '../session/getSessionDir.js';
|
|
4
5
|
const PROJECT_CONTEXT_FILE = '.peaks/PROJECT.md';
|
|
5
6
|
const CONTEXT_HEADER = `# Peaks Project Context
|
|
6
7
|
|
|
@@ -89,7 +90,7 @@ function buildSessionHistory(projectRoot) {
|
|
|
89
90
|
const title = (meta.title ?? 'Untitled').slice(0, 40);
|
|
90
91
|
const skill = meta.skill ?? '-';
|
|
91
92
|
// Extract one-line summary from artifacts for the "What" column
|
|
92
|
-
const sessionRoot =
|
|
93
|
+
const sessionRoot = getSessionDir(projectRoot, meta.sessionId);
|
|
93
94
|
const summary = extractOneLineSummary(sessionRoot);
|
|
94
95
|
const brief = summary ? summary.slice(0, 70) : skill;
|
|
95
96
|
body += `| ${date} | \`${dir}\` | ${title} | ${brief} |\n`;
|
|
@@ -2,6 +2,7 @@ import { closeSync, constants, copyFileSync, existsSync, lstatSync, mkdirSync, o
|
|
|
2
2
|
import { dirname, basename, isAbsolute, join, relative, resolve } from 'node:path';
|
|
3
3
|
import { isInsidePath, isWindowsAbsolutePath, normalizePath, resolveInputPath, stablePath, stableRealPath } from '../../shared/path-utils.js';
|
|
4
4
|
import { containsSensitiveConfigValue, isSensitiveConfigPath } from '../config/config-service.js';
|
|
5
|
+
import { getSessionDir } from '../session/getSessionDir.js';
|
|
5
6
|
// Hot kinds: full body kept in index for always-available context
|
|
6
7
|
const HOT_KINDS = new Set(['feedback', 'decision', 'rule', 'convention', 'module', 'lesson']);
|
|
7
8
|
// ---------------------------------------------------------------------------
|
|
@@ -237,13 +238,13 @@ function summarizeMemoryBody(body) {
|
|
|
237
238
|
function assertSafeSessionDir(projectRoot, sessionId) {
|
|
238
239
|
const normalizedRoot = normalizeRoot(projectRoot);
|
|
239
240
|
const realRoot = normalizeRealRoot(projectRoot);
|
|
240
|
-
const sessionDir =
|
|
241
|
+
const sessionDir = getSessionDir(normalizedRoot, sessionId);
|
|
241
242
|
if (!existsSync(sessionDir)) {
|
|
242
243
|
// Distinguish "not found" (caller will treat as no-op) from "escapes project
|
|
243
244
|
// root" (caller must surface a hard error). We probe by checking whether the
|
|
244
245
|
// joined path, after realpath, would still be inside the project root.
|
|
245
|
-
if (isAbsolute(
|
|
246
|
-
const realJoined = safeRealpath(
|
|
246
|
+
if (isAbsolute(getSessionDir(normalizedRoot, sessionId))) {
|
|
247
|
+
const realJoined = safeRealpath(getSessionDir(normalizedRoot, sessionId));
|
|
247
248
|
if (realJoined && !isInsidePath(realJoined, realRoot)) {
|
|
248
249
|
throw new Error('Session directory must stay inside the project root');
|
|
249
250
|
}
|
|
@@ -39,6 +39,7 @@ import { mkdir, writeFile } from 'node:fs/promises';
|
|
|
39
39
|
import { existsSync } from 'node:fs';
|
|
40
40
|
import { join } from 'node:path';
|
|
41
41
|
import { getSessionId } from '../session/session-manager.js';
|
|
42
|
+
import { getSessionDir } from '../session/getSessionDir.js';
|
|
42
43
|
import { findProjectRoot } from '../config/config-safety.js';
|
|
43
44
|
const README_BODY = `# Performance baseline
|
|
44
45
|
|
|
@@ -117,7 +118,7 @@ function renderBaselineTemplate() {
|
|
|
117
118
|
function buildPlan(projectRoot, apply) {
|
|
118
119
|
const sessionId = getSessionId(projectRoot);
|
|
119
120
|
const sessionRoot = sessionId !== null
|
|
120
|
-
?
|
|
121
|
+
? getSessionDir(projectRoot, sessionId)
|
|
121
122
|
: null;
|
|
122
123
|
const perfBaselinePath = sessionRoot !== null
|
|
123
124
|
? join(sessionRoot, 'rd', 'perf-baseline.md')
|