context-mode 1.0.111 → 1.0.113

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.
Files changed (153) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.openclaw-plugin/index.ts +3 -2
  4. package/.openclaw-plugin/openclaw.plugin.json +1 -1
  5. package/.openclaw-plugin/package.json +1 -1
  6. package/README.md +152 -34
  7. package/bin/statusline.mjs +144 -127
  8. package/build/adapters/base.d.ts +8 -5
  9. package/build/adapters/base.js +8 -18
  10. package/build/adapters/claude-code/index.d.ts +24 -3
  11. package/build/adapters/claude-code/index.js +44 -11
  12. package/build/adapters/codex/hooks.d.ts +10 -5
  13. package/build/adapters/codex/hooks.js +10 -5
  14. package/build/adapters/codex/index.d.ts +17 -5
  15. package/build/adapters/codex/index.js +337 -37
  16. package/build/adapters/codex/paths.d.ts +1 -0
  17. package/build/adapters/codex/paths.js +12 -0
  18. package/build/adapters/cursor/index.d.ts +6 -0
  19. package/build/adapters/cursor/index.js +83 -2
  20. package/build/adapters/detect.d.ts +1 -1
  21. package/build/adapters/detect.js +29 -6
  22. package/build/adapters/omp/index.d.ts +65 -0
  23. package/build/adapters/omp/index.js +182 -0
  24. package/build/adapters/omp/plugin.d.ts +75 -0
  25. package/build/adapters/omp/plugin.js +220 -0
  26. package/build/adapters/openclaw/mcp-tools.d.ts +54 -0
  27. package/build/adapters/openclaw/mcp-tools.js +198 -0
  28. package/build/adapters/openclaw/plugin.d.ts +130 -0
  29. package/build/adapters/openclaw/plugin.js +629 -0
  30. package/build/adapters/openclaw/workspace-router.d.ts +29 -0
  31. package/build/adapters/openclaw/workspace-router.js +64 -0
  32. package/build/adapters/opencode/plugin.d.ts +145 -0
  33. package/build/adapters/opencode/plugin.js +457 -0
  34. package/build/adapters/pi/extension.d.ts +26 -0
  35. package/build/adapters/pi/extension.js +552 -0
  36. package/build/adapters/pi/index.d.ts +57 -0
  37. package/build/adapters/pi/index.js +173 -0
  38. package/build/adapters/pi/mcp-bridge.d.ts +113 -0
  39. package/build/adapters/pi/mcp-bridge.js +251 -0
  40. package/build/adapters/types.d.ts +11 -6
  41. package/build/cli.js +186 -170
  42. package/build/db-base.d.ts +15 -2
  43. package/build/db-base.js +50 -5
  44. package/build/executor.d.ts +2 -0
  45. package/build/executor.js +15 -2
  46. package/build/runPool.d.ts +36 -0
  47. package/build/runPool.js +51 -0
  48. package/build/runtime.js +64 -5
  49. package/build/search/auto-memory.js +6 -4
  50. package/build/security.js +30 -10
  51. package/build/server.d.ts +23 -1
  52. package/build/server.js +662 -182
  53. package/build/session/analytics.d.ts +404 -1
  54. package/build/session/analytics.js +1347 -42
  55. package/build/session/db.d.ts +114 -5
  56. package/build/session/db.js +275 -27
  57. package/build/session/event-emit.d.ts +48 -0
  58. package/build/session/event-emit.js +101 -0
  59. package/build/session/extract.d.ts +1 -0
  60. package/build/session/extract.js +79 -12
  61. package/build/session/purge.d.ts +111 -0
  62. package/build/session/purge.js +138 -0
  63. package/build/store.d.ts +7 -0
  64. package/build/store.js +69 -6
  65. package/build/util/claude-config.d.ts +26 -0
  66. package/build/util/claude-config.js +91 -0
  67. package/build/util/hook-config.d.ts +4 -0
  68. package/build/util/hook-config.js +39 -0
  69. package/build/util/project-dir.d.ts +49 -0
  70. package/build/util/project-dir.js +67 -0
  71. package/cli.bundle.mjs +411 -208
  72. package/configs/antigravity/GEMINI.md +0 -3
  73. package/configs/claude-code/CLAUDE.md +1 -4
  74. package/configs/codex/AGENTS.md +1 -4
  75. package/configs/codex/config.toml +3 -0
  76. package/configs/codex/hooks.json +8 -0
  77. package/configs/cursor/context-mode.mdc +0 -3
  78. package/configs/gemini-cli/GEMINI.md +0 -3
  79. package/configs/jetbrains-copilot/copilot-instructions.md +0 -3
  80. package/configs/kilo/AGENTS.md +0 -3
  81. package/configs/kiro/KIRO.md +0 -3
  82. package/configs/omp/SYSTEM.md +85 -0
  83. package/configs/omp/mcp.json +7 -0
  84. package/configs/openclaw/AGENTS.md +0 -3
  85. package/configs/opencode/AGENTS.md +0 -3
  86. package/configs/pi/AGENTS.md +0 -3
  87. package/configs/qwen-code/QWEN.md +1 -4
  88. package/configs/vscode-copilot/copilot-instructions.md +0 -3
  89. package/configs/zed/AGENTS.md +0 -3
  90. package/hooks/codex/posttooluse.mjs +9 -2
  91. package/hooks/codex/precompact.mjs +69 -0
  92. package/hooks/codex/sessionstart.mjs +13 -9
  93. package/hooks/codex/stop.mjs +1 -2
  94. package/hooks/codex/userpromptsubmit.mjs +1 -2
  95. package/hooks/core/routing.mjs +237 -18
  96. package/hooks/cursor/afteragentresponse.mjs +1 -1
  97. package/hooks/cursor/hooks.json +31 -0
  98. package/hooks/cursor/posttooluse.mjs +1 -1
  99. package/hooks/cursor/sessionstart.mjs +5 -5
  100. package/hooks/cursor/stop.mjs +1 -1
  101. package/hooks/ensure-deps.mjs +12 -13
  102. package/hooks/gemini-cli/aftertool.mjs +1 -1
  103. package/hooks/gemini-cli/beforeagent.mjs +1 -1
  104. package/hooks/gemini-cli/precompress.mjs +3 -2
  105. package/hooks/gemini-cli/sessionstart.mjs +9 -9
  106. package/hooks/jetbrains-copilot/posttooluse.mjs +1 -1
  107. package/hooks/jetbrains-copilot/precompact.mjs +3 -2
  108. package/hooks/jetbrains-copilot/sessionstart.mjs +9 -9
  109. package/hooks/kiro/agentspawn.mjs +5 -5
  110. package/hooks/kiro/posttooluse.mjs +2 -2
  111. package/hooks/kiro/userpromptsubmit.mjs +1 -1
  112. package/hooks/posttooluse.mjs +45 -0
  113. package/hooks/precompact.mjs +17 -0
  114. package/hooks/pretooluse.mjs +23 -0
  115. package/hooks/routing-block.mjs +0 -12
  116. package/hooks/run-hook.mjs +16 -3
  117. package/hooks/session-db.bundle.mjs +27 -18
  118. package/hooks/session-extract.bundle.mjs +2 -2
  119. package/hooks/session-helpers.mjs +101 -64
  120. package/hooks/sessionstart.mjs +51 -2
  121. package/hooks/vscode-copilot/posttooluse.mjs +1 -1
  122. package/hooks/vscode-copilot/precompact.mjs +3 -2
  123. package/hooks/vscode-copilot/sessionstart.mjs +9 -9
  124. package/openclaw.plugin.json +1 -1
  125. package/package.json +14 -8
  126. package/server.bundle.mjs +349 -147
  127. package/start.mjs +16 -4
  128. package/skills/UPSTREAM-CREDITS.md +0 -51
  129. package/skills/context-mode-ops/SKILL.md +0 -299
  130. package/skills/context-mode-ops/agent-teams.md +0 -198
  131. package/skills/context-mode-ops/communication.md +0 -224
  132. package/skills/context-mode-ops/marketing.md +0 -124
  133. package/skills/context-mode-ops/release.md +0 -214
  134. package/skills/context-mode-ops/review-pr.md +0 -269
  135. package/skills/context-mode-ops/tdd.md +0 -329
  136. package/skills/context-mode-ops/triage-issue.md +0 -266
  137. package/skills/context-mode-ops/validation.md +0 -307
  138. package/skills/diagnose/SKILL.md +0 -122
  139. package/skills/diagnose/scripts/hitl-loop.template.sh +0 -41
  140. package/skills/grill-me/SKILL.md +0 -15
  141. package/skills/grill-with-docs/ADR-FORMAT.md +0 -47
  142. package/skills/grill-with-docs/CONTEXT-FORMAT.md +0 -77
  143. package/skills/grill-with-docs/SKILL.md +0 -93
  144. package/skills/improve-codebase-architecture/DEEPENING.md +0 -37
  145. package/skills/improve-codebase-architecture/INTERFACE-DESIGN.md +0 -44
  146. package/skills/improve-codebase-architecture/LANGUAGE.md +0 -53
  147. package/skills/improve-codebase-architecture/SKILL.md +0 -76
  148. package/skills/tdd/SKILL.md +0 -114
  149. package/skills/tdd/deep-modules.md +0 -33
  150. package/skills/tdd/interface-design.md +0 -31
  151. package/skills/tdd/mocking.md +0 -59
  152. package/skills/tdd/refactoring.md +0 -10
  153. package/skills/tdd/tests.md +0 -61
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Claude Code config directory resolver — single source of truth.
3
+ *
4
+ * Issue #460 follow-up: every Claude-aware reader (adapters, security policy
5
+ * loader, hook helpers) MUST agree on where global settings live. Hardcoding
6
+ * `~/.claude` in any one reader silently breaks `CLAUDE_CONFIG_DIR` for that
7
+ * code path, producing policy drift that is invisible until a user sets the
8
+ * env var and watches their settings get ignored.
9
+ *
10
+ * Mirrors the contract of `hooks/session-helpers.mjs::resolveConfigDir` and
11
+ * `ClaudeCodeAdapter.getConfigDir`:
12
+ * - env unset, empty string, or whitespace-only → ~/.claude
13
+ * - env starts with `~`, `~/`, or `~\` → expanded against homedir()
14
+ * - otherwise → resolved to absolute (relative paths anchor to cwd)
15
+ *
16
+ * Whitespace guard: shells that quote-pad the env value (`CLAUDE_CONFIG_DIR=" "`)
17
+ * would otherwise resolve to `cwd/<spaces>` — silently writing settings into
18
+ * the project tree. Trim before the truthy check so quote-padding falls back
19
+ * to `~/.claude` like a sane default.
20
+ *
21
+ * Cross-platform note: tilde regex strips a single leading `/` OR `\` so
22
+ * `~\Users\foo` works on Windows. `path.resolve` handles drive-letter joining.
23
+ */
24
+ import { resolve } from "node:path";
25
+ import { homedir } from "node:os";
26
+ import { createRequire } from "node:module";
27
+ export function resolveClaudeConfigDir(env = process.env) {
28
+ const envVal = env.CLAUDE_CONFIG_DIR;
29
+ if (envVal && envVal.trim() !== "") {
30
+ if (envVal.startsWith("~")) {
31
+ return resolve(homedir(), envVal.replace(/^~[/\\]?/, ""));
32
+ }
33
+ return resolve(envVal);
34
+ }
35
+ return resolve(homedir(), ".claude");
36
+ }
37
+ /** Resolve the global settings.json path, honoring CLAUDE_CONFIG_DIR. */
38
+ export function resolveClaudeGlobalSettingsPath(env = process.env) {
39
+ return resolve(resolveClaudeConfigDir(env), "settings.json");
40
+ }
41
+ /**
42
+ * Issue #451 round-3: cross-adapter deny-policy parity.
43
+ *
44
+ * `resolveClaudeGlobalSettingsPath` hardcodes the `.claude` segment, so
45
+ * non-Claude adapters (cursor, codex, qwen-code, gemini-cli, jetbrains-copilot,
46
+ * vscode-copilot, etc.) never had their global settings consulted by the
47
+ * security policy reader. This helper returns the union of:
48
+ *
49
+ * 1. The currently-detected adapter's home-rooted settings.json (when the
50
+ * adapter is non-claude — claude is already covered by entry 2).
51
+ * 2. The claude global settings.json (always — defense in depth).
52
+ *
53
+ * Lazy import of `./adapters/detect.js` keeps this file free of any direct
54
+ * adapter dependency: the detect module itself only `import type`s adapter
55
+ * types at the top level (concrete adapters are loaded dynamically inside
56
+ * `getAdapter()`), so a static import is safe — but we use `createRequire`
57
+ * to make the dependency direction crystal clear and to avoid surprising
58
+ * future maintainers who add eager adapter imports to detect.ts.
59
+ *
60
+ * The returned array is deduplicated and order-stable: adapter-specific path
61
+ * first (most specific), claude global second (fallback).
62
+ */
63
+ export function resolveAdapterGlobalSettingsPaths(env = process.env) {
64
+ const paths = [];
65
+ // Lazy-load detect module to avoid any chance of an adapter import cycle.
66
+ // `detect.ts` exports pure functions — `detectPlatform` (env-driven) and
67
+ // `getSessionDirSegments` (sync map). Neither instantiates an adapter.
68
+ let detected = null;
69
+ let segmentsFor = null;
70
+ try {
71
+ const lazyRequire = createRequire(import.meta.url);
72
+ const detect = lazyRequire("../adapters/detect.js");
73
+ detected = detect.detectPlatform();
74
+ segmentsFor = detect.getSessionDirSegments;
75
+ }
76
+ catch {
77
+ // If detection fails for any reason, fall back to claude-only behavior.
78
+ }
79
+ if (detected && segmentsFor && detected.platform !== "claude-code") {
80
+ const segments = segmentsFor(detected.platform);
81
+ if (segments && segments.length > 0) {
82
+ paths.push(resolve(homedir(), ...segments, "settings.json"));
83
+ }
84
+ }
85
+ // Always include claude global as fallback (defense in depth).
86
+ const claudePath = resolveClaudeGlobalSettingsPath(env);
87
+ if (!paths.includes(claudePath)) {
88
+ paths.push(claudePath);
89
+ }
90
+ return paths;
91
+ }
@@ -0,0 +1,4 @@
1
+ import type { HookAdapter } from "../adapters/types.js";
2
+ export declare function getCommandsFromHookEntry(entry: unknown): string[];
3
+ export declare function extractHookScriptPath(command: string): string | null;
4
+ export declare function getHookScriptPaths(adapter: HookAdapter, pluginRoot: string): string[];
@@ -0,0 +1,39 @@
1
+ export function getCommandsFromHookEntry(entry) {
2
+ const commands = [];
3
+ if (entry && typeof entry === "object") {
4
+ const command = entry.command;
5
+ if (typeof command === "string")
6
+ commands.push(command);
7
+ const hooks = entry.hooks;
8
+ if (Array.isArray(hooks)) {
9
+ for (const hook of hooks) {
10
+ if (hook && typeof hook === "object") {
11
+ const nestedCommand = hook.command;
12
+ if (typeof nestedCommand === "string")
13
+ commands.push(nestedCommand);
14
+ }
15
+ }
16
+ }
17
+ }
18
+ return commands;
19
+ }
20
+ export function extractHookScriptPath(command) {
21
+ const match = command.match(/(?:"([^"]+\.mjs)"|'([^']+\.mjs)'|(\S+\.mjs))/);
22
+ return match?.[1] ?? match?.[2] ?? match?.[3] ?? null;
23
+ }
24
+ export function getHookScriptPaths(adapter, pluginRoot) {
25
+ const paths = new Set();
26
+ const hookConfig = adapter.generateHookConfig(pluginRoot);
27
+ for (const entries of Object.values(hookConfig)) {
28
+ if (!Array.isArray(entries))
29
+ continue;
30
+ for (const entry of entries) {
31
+ for (const command of getCommandsFromHookEntry(entry)) {
32
+ const scriptPath = extractHookScriptPath(command);
33
+ if (scriptPath)
34
+ paths.add(scriptPath);
35
+ }
36
+ }
37
+ }
38
+ return [...paths];
39
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Project-dir resolution helpers — shared between `start.mjs` (the MCP entry
3
+ * point) and `src/server.ts getProjectDir()` (the consumer).
4
+ *
5
+ * Background: when Claude Code runs `/ctx-upgrade`, it kills + respawns the
6
+ * MCP server. The respawn happens with `cwd` set to the plugin install
7
+ * directory (`~/.claude/plugins/cache/context-mode/context-mode/<version>/`).
8
+ * The legacy `start.mjs` then set `CLAUDE_PROJECT_DIR = originalCwd`, which
9
+ * poisoned every downstream `ctx_stats` / SessionDB / hash computation —
10
+ * sessions silently re-rooted under the plugin install path.
11
+ *
12
+ * Defense-in-depth fix (v1.0.113):
13
+ * - `start.mjs` calls `isPluginInstallPath(originalCwd)` and skips the env
14
+ * auto-set when true (no poisoning at the source).
15
+ * - `getProjectDir()` calls `resolveProjectDir(...)` which rejects plugin-
16
+ * pathed env vars and the plugin cwd, preferring `process.env.PWD`
17
+ * (shell-set, survives `process.chdir`) before falling back.
18
+ */
19
+ /**
20
+ * Detect whether a path lives inside the Claude Code plugin install tree —
21
+ * specifically `<home>/.claude/plugins/cache/<plugin>/<plugin>/<version>/`
22
+ * or the marketplace mirror `<home>/.claude/plugins/marketplaces/...`.
23
+ *
24
+ * Cross-OS: matches both POSIX (`/`) and Windows (`\`) path separators.
25
+ * Independent of `home` location — we only care about the `.claude/plugins/`
26
+ * suffix pattern.
27
+ */
28
+ export declare function isPluginInstallPath(p: string): boolean;
29
+ /**
30
+ * Pure project-dir resolver. Mirror of the env-var chain inside
31
+ * `src/server.ts getProjectDir()`, but takes its inputs explicitly so the
32
+ * resolver can be exercised under test without process-level mutation.
33
+ *
34
+ * Resolution order:
35
+ * 1. Adapter-priority env vars (CLAUDE / GEMINI / VSCODE / OPENCODE / PI /
36
+ * IDEA / CONTEXT_MODE) — first non-empty AND non-plugin-path wins.
37
+ * 2. `process.env.PWD` — shell-set, NOT updated by `process.chdir()`, so
38
+ * it survives the `start.mjs` chdir into the plugin dir. Skipped if
39
+ * it too points at a plugin install path.
40
+ * 3. `cwd` — last resort. Returned even if it is a plugin path; the
41
+ * caller is responsible for rendering a graceful "no project context"
42
+ * message rather than panicking. Keeping the function total preserves
43
+ * operation of project-independent tools (sandbox execute, fetch).
44
+ */
45
+ export declare function resolveProjectDir(opts: {
46
+ env: Record<string, string | undefined>;
47
+ cwd: string;
48
+ pwd: string | undefined;
49
+ }): string;
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Project-dir resolution helpers — shared between `start.mjs` (the MCP entry
3
+ * point) and `src/server.ts getProjectDir()` (the consumer).
4
+ *
5
+ * Background: when Claude Code runs `/ctx-upgrade`, it kills + respawns the
6
+ * MCP server. The respawn happens with `cwd` set to the plugin install
7
+ * directory (`~/.claude/plugins/cache/context-mode/context-mode/<version>/`).
8
+ * The legacy `start.mjs` then set `CLAUDE_PROJECT_DIR = originalCwd`, which
9
+ * poisoned every downstream `ctx_stats` / SessionDB / hash computation —
10
+ * sessions silently re-rooted under the plugin install path.
11
+ *
12
+ * Defense-in-depth fix (v1.0.113):
13
+ * - `start.mjs` calls `isPluginInstallPath(originalCwd)` and skips the env
14
+ * auto-set when true (no poisoning at the source).
15
+ * - `getProjectDir()` calls `resolveProjectDir(...)` which rejects plugin-
16
+ * pathed env vars and the plugin cwd, preferring `process.env.PWD`
17
+ * (shell-set, survives `process.chdir`) before falling back.
18
+ */
19
+ /**
20
+ * Detect whether a path lives inside the Claude Code plugin install tree —
21
+ * specifically `<home>/.claude/plugins/cache/<plugin>/<plugin>/<version>/`
22
+ * or the marketplace mirror `<home>/.claude/plugins/marketplaces/...`.
23
+ *
24
+ * Cross-OS: matches both POSIX (`/`) and Windows (`\`) path separators.
25
+ * Independent of `home` location — we only care about the `.claude/plugins/`
26
+ * suffix pattern.
27
+ */
28
+ export function isPluginInstallPath(p) {
29
+ if (!p)
30
+ return false;
31
+ return /[/\\]\.claude[/\\]plugins[/\\](cache|marketplaces)[/\\]/.test(p);
32
+ }
33
+ /**
34
+ * Pure project-dir resolver. Mirror of the env-var chain inside
35
+ * `src/server.ts getProjectDir()`, but takes its inputs explicitly so the
36
+ * resolver can be exercised under test without process-level mutation.
37
+ *
38
+ * Resolution order:
39
+ * 1. Adapter-priority env vars (CLAUDE / GEMINI / VSCODE / OPENCODE / PI /
40
+ * IDEA / CONTEXT_MODE) — first non-empty AND non-plugin-path wins.
41
+ * 2. `process.env.PWD` — shell-set, NOT updated by `process.chdir()`, so
42
+ * it survives the `start.mjs` chdir into the plugin dir. Skipped if
43
+ * it too points at a plugin install path.
44
+ * 3. `cwd` — last resort. Returned even if it is a plugin path; the
45
+ * caller is responsible for rendering a graceful "no project context"
46
+ * message rather than panicking. Keeping the function total preserves
47
+ * operation of project-independent tools (sandbox execute, fetch).
48
+ */
49
+ export function resolveProjectDir(opts) {
50
+ const { env, cwd, pwd } = opts;
51
+ const candidates = [
52
+ env.CLAUDE_PROJECT_DIR,
53
+ env.GEMINI_PROJECT_DIR,
54
+ env.VSCODE_CWD,
55
+ env.OPENCODE_PROJECT_DIR,
56
+ env.PI_PROJECT_DIR,
57
+ env.IDEA_INITIAL_DIRECTORY,
58
+ env.CONTEXT_MODE_PROJECT_DIR,
59
+ ];
60
+ for (const c of candidates) {
61
+ if (c && !isPluginInstallPath(c))
62
+ return c;
63
+ }
64
+ if (pwd && !isPluginInstallPath(pwd))
65
+ return pwd;
66
+ return cwd;
67
+ }