context-mode 1.0.125 → 1.0.127

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 (45) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.openclaw-plugin/openclaw.plugin.json +1 -1
  4. package/.openclaw-plugin/package.json +1 -1
  5. package/build/adapters/claude-code/hooks.d.ts +10 -4
  6. package/build/adapters/claude-code/hooks.js +22 -12
  7. package/build/adapters/claude-code/index.d.ts +24 -1
  8. package/build/adapters/claude-code/index.js +67 -11
  9. package/build/adapters/types.d.ts +57 -0
  10. package/build/adapters/types.js +29 -0
  11. package/build/cli.js +38 -13
  12. package/build/server.js +7 -0
  13. package/build/util/hook-config.d.ts +24 -1
  14. package/build/util/hook-config.js +39 -2
  15. package/build/util/plugin-cache-integrity.d.ts +37 -0
  16. package/build/util/plugin-cache-integrity.js +105 -0
  17. package/build/util/project-dir.d.ts +13 -0
  18. package/build/util/project-dir.js +11 -2
  19. package/cli.bundle.mjs +122 -122
  20. package/hooks/core/routing.mjs +114 -22
  21. package/hooks/gemini-cli/sessionstart.mjs +8 -6
  22. package/hooks/security.bundle.mjs +1 -0
  23. package/hooks/sessionstart.mjs +18 -0
  24. package/openclaw.plugin.json +1 -1
  25. package/package.json +4 -3
  26. package/scripts/plugin-cache-integrity.mjs +248 -0
  27. package/server.bundle.mjs +94 -94
  28. package/start.mjs +37 -0
  29. package/skills/UPSTREAM-CREDITS.md +0 -51
  30. package/skills/diagnose/SKILL.md +0 -122
  31. package/skills/diagnose/scripts/hitl-loop.template.sh +0 -41
  32. package/skills/grill-me/SKILL.md +0 -15
  33. package/skills/grill-with-docs/ADR-FORMAT.md +0 -47
  34. package/skills/grill-with-docs/CONTEXT-FORMAT.md +0 -77
  35. package/skills/grill-with-docs/SKILL.md +0 -93
  36. package/skills/improve-codebase-architecture/DEEPENING.md +0 -37
  37. package/skills/improve-codebase-architecture/INTERFACE-DESIGN.md +0 -44
  38. package/skills/improve-codebase-architecture/LANGUAGE.md +0 -53
  39. package/skills/improve-codebase-architecture/SKILL.md +0 -76
  40. package/skills/tdd/SKILL.md +0 -114
  41. package/skills/tdd/deep-modules.md +0 -33
  42. package/skills/tdd/interface-design.md +0 -31
  43. package/skills/tdd/mocking.md +0 -59
  44. package/skills/tdd/refactoring.md +0 -10
  45. package/skills/tdd/tests.md +0 -61
@@ -0,0 +1,105 @@
1
+ /**
2
+ * TypeScript surface for the start.mjs plugin-cache integrity helper.
3
+ *
4
+ * The actual logic lives in `scripts/plugin-cache-integrity.mjs` (raw
5
+ * `.mjs` so start.mjs can import it without a TS toolchain at boot —
6
+ * #550 fail-fast happens BEFORE any bundle is loaded). This module is
7
+ * the bridge that lets TS consumers (claude-code adapter's
8
+ * getHealthChecks for Algo-D5, the cli doctor surface) call the same
9
+ * function without duplicating the implementation.
10
+ *
11
+ * Single source of truth: scripts/plugin-cache-integrity.mjs. Boot
12
+ * fail-fast (Algo-D4) and doctor diagnostic (Algo-D5) agree
13
+ * byte-for-byte because they call the same exported function.
14
+ *
15
+ * Top-level dynamic import is used (not a static `import` from `.mjs`)
16
+ * because the project is ESM and `import` of a sibling `.mjs` from a
17
+ * `.ts` file relies on the bundler / loader resolving `.mjs`
18
+ * extensions, which esbuild can do but tsc-only typecheck cannot. The
19
+ * dynamic import is resolved by the runtime (Node ESM) regardless of
20
+ * how the consumer was bundled. Errors are caught and surfaced as a
21
+ * FAIL detail — the helper is required to ship in the npm tarball
22
+ * (package.json files[]); a missing helper means the install is
23
+ * fundamentally broken.
24
+ */
25
+ let cached = null;
26
+ let cachedError = null;
27
+ async function loadHelper() {
28
+ if (cached)
29
+ return cached;
30
+ if (cachedError)
31
+ return null;
32
+ try {
33
+ // Resolve relative to this compiled file. After tsc emits to
34
+ // build/util/plugin-cache-integrity.js, the helper sits at
35
+ // ../../scripts/plugin-cache-integrity.mjs. After esbuild bundles
36
+ // src/cli.ts to cli.bundle.mjs at the repo root, the same relative
37
+ // path resolves to ./scripts/plugin-cache-integrity.mjs. Both
38
+ // shapes are walked here.
39
+ const candidates = [
40
+ new URL("../../scripts/plugin-cache-integrity.mjs", import.meta.url),
41
+ new URL("./scripts/plugin-cache-integrity.mjs", import.meta.url),
42
+ ];
43
+ let lastErr = null;
44
+ for (const url of candidates) {
45
+ try {
46
+ const mod = (await import(url.href));
47
+ if (typeof mod?.assertPluginCacheIntegrity === "function") {
48
+ cached = mod;
49
+ return cached;
50
+ }
51
+ }
52
+ catch (err) {
53
+ lastErr = err;
54
+ }
55
+ }
56
+ cachedError =
57
+ lastErr instanceof Error ? lastErr.message : String(lastErr ?? "not found");
58
+ return null;
59
+ }
60
+ catch (err) {
61
+ cachedError = err instanceof Error ? err.message : String(err);
62
+ return null;
63
+ }
64
+ }
65
+ // Eagerly start the load on module init so the first synchronous
66
+ // check() call can hit the cache. The promise is unawaited
67
+ // intentionally — by the time any HealthCheck.check() runs (doctor
68
+ // command, well after MCP server boot), the import has resolved.
69
+ void loadHelper();
70
+ /**
71
+ * Run the integrity check synchronously. If the helper module is
72
+ * still loading (not yet cached) returns a FAIL with detail
73
+ * "integrity helper not yet loaded" — caller should retry once the
74
+ * doctor command's IO is complete. In practice the doctor is invoked
75
+ * many MS after module load so this fallback is defensive only.
76
+ */
77
+ export function checkPluginCacheIntegritySync(pluginRoot) {
78
+ if (cached) {
79
+ const result = cached.assertPluginCacheIntegrity({ pluginRoot });
80
+ if (result.ok) {
81
+ return {
82
+ status: "OK",
83
+ detail: `${pluginRoot} (all required runtime siblings present)`,
84
+ };
85
+ }
86
+ return {
87
+ status: "FAIL",
88
+ detail: `missing: ${result.missing.join(", ")}`,
89
+ };
90
+ }
91
+ if (cachedError) {
92
+ return {
93
+ status: "FAIL",
94
+ detail: `integrity helper unavailable: ${cachedError}`,
95
+ };
96
+ }
97
+ return {
98
+ status: "FAIL",
99
+ detail: "integrity helper not yet loaded",
100
+ };
101
+ }
102
+ /** Force-await the helper load. Tests use this to deflake the eager fire-and-forget. */
103
+ export async function ensurePluginCacheIntegrityLoaded() {
104
+ await loadHelper();
105
+ }
@@ -50,6 +50,15 @@ export declare function isPluginInstallPath(p: string): boolean;
50
50
  */
51
51
  export declare function resolveProjectDirFromTranscript(opts: {
52
52
  projectsRoot: string;
53
+ /**
54
+ * Optional freshness guard. Claude Code updates the active transcript while
55
+ * the session is being used; stale transcripts from previous days must not
56
+ * become a global project-dir signal for other hosts that merely have
57
+ * ~/.claude on disk.
58
+ */
59
+ maxAgeMs?: number;
60
+ /** Test seam for maxAgeMs. Defaults to Date.now(). */
61
+ nowMs?: number;
53
62
  }): string | undefined;
54
63
  /**
55
64
  * Pure project-dir resolver. Mirror of the env-var chain inside
@@ -77,6 +86,10 @@ export declare function resolveProjectDir(opts: {
77
86
  pwd: string | undefined;
78
87
  /** Optional override; production code passes `~/.claude/projects`. */
79
88
  transcriptsRoot?: string;
89
+ /** Optional freshness guard for Claude Code transcript project recovery. */
90
+ transcriptMaxAgeMs?: number;
91
+ /** Test seam for transcriptMaxAgeMs. Defaults to Date.now(). */
92
+ nowMs?: number;
80
93
  /**
81
94
  * Issue #545 — opt-in tightening. When set, the candidate list is built
82
95
  * algorithmically from `workspaceEnvVarsFor(strictPlatform)` plus the
@@ -124,6 +124,11 @@ export function resolveProjectDirFromTranscript(opts) {
124
124
  }
125
125
  if (!bestPath)
126
126
  return undefined;
127
+ if (typeof opts.maxAgeMs === "number") {
128
+ const nowMs = opts.nowMs ?? Date.now();
129
+ if (nowMs - bestMtime > opts.maxAgeMs)
130
+ return undefined;
131
+ }
127
132
  // Read first ~10 lines until we find a cwd field. The jsonl is
128
133
  // append-only and can be huge (60+ MB on long sessions) — never load it
129
134
  // into memory; stream a small head buffer.
@@ -172,7 +177,7 @@ export function resolveProjectDirFromTranscript(opts) {
172
177
  * operation of project-independent tools (sandbox execute, fetch).
173
178
  */
174
179
  export function resolveProjectDir(opts) {
175
- const { env, cwd, pwd, transcriptsRoot, strictPlatform } = opts;
180
+ const { env, cwd, pwd, transcriptsRoot, transcriptMaxAgeMs, nowMs, strictPlatform } = opts;
176
181
  // Build candidate list. Strict path: own workspace vars + universal escape
177
182
  // hatch — NO foreign workspace vars, in any order, can win. Non-strict
178
183
  // path: frozen legacy literal order for backwards compatibility.
@@ -185,7 +190,11 @@ export function resolveProjectDir(opts) {
185
190
  return v;
186
191
  }
187
192
  if (transcriptsRoot) {
188
- const fromTranscript = resolveProjectDirFromTranscript({ projectsRoot: transcriptsRoot });
193
+ const fromTranscript = resolveProjectDirFromTranscript({
194
+ projectsRoot: transcriptsRoot,
195
+ maxAgeMs: transcriptMaxAgeMs,
196
+ nowMs,
197
+ });
189
198
  if (fromTranscript && !isPluginInstallPath(fromTranscript))
190
199
  return fromTranscript;
191
200
  }