Skip to content

feat: add project context recovery skill for v0.0.50#197

Merged
ymkiux merged 7 commits into
mainfrom
feat/cross-session-search-skill
Jun 14, 2026
Merged

feat: add project context recovery skill for v0.0.50#197
ymkiux merged 7 commits into
mainfrom
feat/cross-session-search-skill

Conversation

@awsl233777

@awsl233777 awsl233777 commented Jun 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • bump package version from 0.0.49 to 0.0.50 in package.json and package-lock.json without creating a git tag
  • add codexmate-project-context-recovery, a project handoff/context recovery AgentSkill for local agent session history
  • bundle a dependency-free scripts/search_sessions.py helper with two modes:
    • --mode search: raw local session evidence search
    • --mode brief: structured project context brief with confidence, timeline, repo/branch/PR/file signals, commands, validations, risks, and handoff guidance
  • search local Codex, Claude Code, codexmate-derived, Gemini, and CodeBuddy session stores
  • support --path-filter, --source codexmate-derived, stricter hyphen/slash matching, and positive integer validation for numeric CLI options
  • replace the old codexmate-cross-session-search skill/test with the project context recovery skill/test
  • keep the scope honest: this recovers historical session evidence and does not replace live GitHub/current-file verification

Validation

  • npm run lint
  • npm run test:unit
  • python3 ~/.npm-global/lib/node_modules/openclaw/skills/skill-creator/scripts/package_skill.py skills/codexmate-project-context-recovery /tmp/codexmate-skill-dist
  • npm pack --dry-run --json
  • python3 skills/codexmate-project-context-recovery/scripts/search_sessions.py 'feat/task-orchestration-tab' --mode brief --source all --path-filter codexmate --match all --limit 2 --format text
  • python3 skills/codexmate-project-context-recovery/scripts/search_sessions.py 'completely-nonexistent-token-zzq-197' --source all --path-filter codexmate --match all --limit 2 --format text

Validation Results

  • lint passed for 220 files
  • unit passed: 656 tests
  • skill package validation passed
  • npm dry-run includes:
    • skills/codexmate-project-context-recovery/SKILL.md
    • skills/codexmate-project-context-recovery/scripts/search_sessions.py
  • false-positive regression returns no matching sessions
  • --source codexmate-derived and negative numeric argument validation are covered by unit tests

Notes

  • Version text is updated in this PR commit using npm version 0.0.50 --no-git-tag-version; no local or remote git tag was created.
  • Claude Code was invoked with the project skill installed and detected project skills, but this local Claude Code runtime is not logged in (Not logged in · Please run /login), so model-level end-to-end behavior could not be completed here.
  • The context brief extraction is heuristic. It improves handoff value beyond raw grep, but it is not semantic memory/indexing; mutable facts still require live checks.

Summary by CodeRabbit

  • New Features

    • Introduced project context recovery skill enabling users to search and restore context information from prior local agent sessions with confidence scoring and validation guidance.
  • Tests

    • Added comprehensive test coverage for the project context recovery skill including search and brief generation scenarios.

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5f83672f-1cb9-478f-9ccf-8387f5abd3f1

📥 Commits

Reviewing files that changed from the base of the PR and between 1360b00 and c1d4a4d.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (2)
  • package.json
  • skills/codexmate-project-context-recovery/SKILL.md
✅ Files skipped from review due to trivial changes (1)
  • skills/codexmate-project-context-recovery/SKILL.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json

📝 Walkthrough

Walkthrough

A new codexmate-project-context-recovery skill is introduced, consisting of a SKILL.md specification and a dependency-free Python CLI (search_sessions.py) that scans local agent session files, scores and ranks matches against a query, and emits either a ranked hit list or a structured project context brief. The skills/ directory is added to the npm package files and the version is bumped to 0.0.50. End-to-end unit tests and test runner registration are added.

Changes

Project Context Recovery Skill

Layer / File(s) Summary
Skill specification and npm publishing
skills/codexmate-project-context-recovery/SKILL.md, package.json
SKILL.md describes the evidence-first recovery workflow including target confirmation, brief generation, confidence assessment, live verification, MCP fallback path, and privacy rules. package.json adds skills/ to the published files array and bumps the version from 0.0.49 to 0.0.50.
Search script constants, Hit dataclass, and file/query utilities
skills/codexmate-project-context-recovery/scripts/search_sessions.py
Defines filtering constants and evidence term lists, the Hit dataclass, session root selection (candidate_roots), file iteration (iter_files), safe tail reading (read_tail), and query token processing utilities (token_groups, flatten_groups, contains_token, group_matches_all).
Text extraction, filtering, scoring, and metadata discovery
skills/codexmate-project-context-recovery/scripts/search_sessions.py
Implements noisy-string detection and JSON-aware text collection, JSONL/JSON record classification and filtering, searchable text extraction from session files, snippet generation, match scoring, result deduplication, GitHub-oriented metadata extraction via regex (extract_metadata), and sentence selection for categorized evidence.
Core search pipeline, brief construction, output renderers, and CLI
skills/codexmate-project-context-recovery/scripts/search_sessions.py
Implements search() iterating candidate files with match-mode enforcement, scoring, metadata extraction, and top-N sorting. Implements build_brief() aggregating evidence and computing confidence labels. Adds emit_json, emit_text, and emit_brief_text renderers and wires the main() CLI entrypoint with full argument parsing and dispatch.
Project context recovery skill tests
tests/unit/codexmate-project-context-recovery-skill.test.mjs
End-to-end tests using a temp HOME with fixture JSONL session files. Covers normal search (single codex hit with PR 197 snippet), --mode brief (confidence, hit count, repo/branch/file lists, evidence and timeline content), --source codexmate-derived, negative limit error path, and nonexistent-token miss case. Cleans up temp directory in a finally block.
Test runner integration
tests/unit/run.mjs
Adds a dynamic import of the new test module to the runner's aggregation sequence so its tests are collected and reported.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 Hopping through sessions of old,
A Python script searches, brave and bold.
SKILL.md charts the path so clear,
Briefs and confidence appear!
With snippets and hits ranked just right,
Context recovered — what a delight! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat: add project context recovery skill for v0.0.50' directly and clearly summarizes the main changeset: introduction of the codexmate-project-context-recovery skill and version bump to 0.0.50.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/cross-session-search-skill

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@awsl233777

Copy link
Copy Markdown
Collaborator Author

Updated this PR to follow Claude Agent Skills authoring guidance more closely:

  • Kept SKILL.md concise with only name/description frontmatter and trigger-focused workflow guidance.
  • Added a bundled executable script: scripts/search_sessions.py.
  • The script provides actual utility even when codexmate MCP is unavailable: it searches local Codex, Claude Code, codexmate-derived, Gemini, and CodeBuddy session stores; supports --path-filter, --match all, text/JSON output, and snippets.
  • Added a unit test with temporary fake session stores to verify project-specific evidence search.

Validation run locally:

python3 skills/codexmate-cross-session-search/scripts/search_sessions.py 'cross-session search skill' --source all --path-filter codexmate-cross-session-search --limit 3 --format text
python3 ~/.npm-global/lib/node_modules/openclaw/skills/skill-creator/scripts/package_skill.py skills/codexmate-cross-session-search /tmp/codexmate-skill-dist
npm run lint
npm run test:unit
npm pack --dry-run --json

Results:

  • skill packaging passed
  • lint passed for 220 files
  • unit passed: 657 tests
  • npm dry-run includes both the skill SKILL.md and executable script

Claude Code smoke note: Claude Code detected the project skill, but this local runtime is not logged in (Not logged in · Please run /login), so I validated the practical search behavior directly through the bundled script and unit fixture instead.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@skills/codexmate-cross-session-search/scripts/search_sessions.py`:
- Around line 39-52: The candidate_roots function supports prefix-based grouping
where selecting "codexmate-derived" would match both "codexmate-derived-codex"
and "codexmate-derived-claude" (via the startswith check), but the CLI argument
parser has hard-coded choices that only include the full specific names, making
the prefix matching logic unreachable. Add the grouped selector options
(umbrella prefixes like "codexmate-derived") to the CLI argument choices
alongside the existing individual source names. This will align the CLI choices
with the prefix-matching behavior already implemented in candidate_roots and
make all code paths reachable. Check both the candidate_roots function
definition and the CLI argument parser setup (referenced at line 217) to ensure
the grouped options are consistently exposed.
- Around line 220-223: The numeric CLI arguments (--limit, --snippets,
--max-bytes, and --max-files-per-root) in the parser.add_argument calls lack
bounds validation, allowing negative values that cause unexpected behavior.
Define a custom type validation function that ensures these arguments are
positive integers (greater than 0), then apply this validation function via the
type parameter in each of these add_argument calls. This will reject invalid
negative values at parse time rather than allowing them to produce surprising
results during execution.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 00ee102d-8a92-46a8-b0d3-c94b16bcf83a

📥 Commits

Reviewing files that changed from the base of the PR and between cc75bcd and 08ec4d1.

📒 Files selected for processing (4)
  • skills/codexmate-cross-session-search/SKILL.md
  • skills/codexmate-cross-session-search/scripts/search_sessions.py
  • tests/unit/codexmate-cross-session-search-skill.test.mjs
  • tests/unit/run.mjs
✅ Files skipped from review due to trivial changes (1)
  • skills/codexmate-cross-session-search/SKILL.md
📜 Review details
🧰 Additional context used
🪛 ast-grep (0.43.0)
skills/codexmate-cross-session-search/scripts/search_sessions.py

[info] 195-195: use jsonify instead of json.dumps for JSON output
Context: json.dumps({"hits": [hit.dict for hit in hits]}, ensure_ascii=False, indent=2)
Note: Security best practice.

(use-jsonify)

🪛 Ruff (0.15.15)
skills/codexmate-cross-session-search/scripts/search_sessions.py

[warning] 113-113: Do not catch blind exception: Exception

(BLE001)

🔇 Additional comments (2)
tests/unit/codexmate-cross-session-search-skill.test.mjs (1)

1-62: LGTM!

tests/unit/run.mjs (1)

23-23: LGTM!

Comment on lines +39 to +52
def candidate_roots(selected: str) -> list[tuple[str, Path]]:
h = home()
roots = [
("codex", h / ".codex" / "sessions"),
("claude", h / ".claude" / "projects"),
("codexmate-derived-codex", h / ".codexmate" / "sessions" / "derived" / "codex"),
("codexmate-derived-claude", h / ".codexmate" / "sessions" / "derived" / "claude"),
("gemini", h / ".gemini"),
("codebuddy", h / ".codebuddy"),
]
if selected == "all":
return roots
return [(name, path) for name, path in roots if name == selected or name.startswith(f"{selected}-")]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Align --source choices with candidate_roots prefix behavior.

candidate_roots supports grouped prefix selection, but current CLI choices prevent using umbrella selectors (making part of that logic unreachable). Either expose grouped source choices or remove the prefix branch.

Suggested fix (expose grouped selectors)
-    parser.add_argument("--source", default="all", choices=["all", "codex", "claude", "gemini", "codebuddy", "codexmate-derived-codex", "codexmate-derived-claude"], help="Session source to search")
+    parser.add_argument(
+        "--source",
+        default="all",
+        choices=[
+            "all",
+            "codex",
+            "claude",
+            "gemini",
+            "codebuddy",
+            "codexmate",
+            "codexmate-derived",
+            "codexmate-derived-codex",
+            "codexmate-derived-claude",
+        ],
+        help="Session source to search",
+    )

Also applies to: 217-217

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/codexmate-cross-session-search/scripts/search_sessions.py` around
lines 39 - 52, The candidate_roots function supports prefix-based grouping where
selecting "codexmate-derived" would match both "codexmate-derived-codex" and
"codexmate-derived-claude" (via the startswith check), but the CLI argument
parser has hard-coded choices that only include the full specific names, making
the prefix matching logic unreachable. Add the grouped selector options
(umbrella prefixes like "codexmate-derived") to the CLI argument choices
alongside the existing individual source names. This will align the CLI choices
with the prefix-matching behavior already implemented in candidate_roots and
make all code paths reachable. Check both the candidate_roots function
definition and the CLI argument parser setup (referenced at line 217) to ensure
the grouped options are consistently exposed.

Comment on lines +220 to +223
parser.add_argument("--limit", type=int, default=DEFAULT_LIMIT, help="Maximum hits to print")
parser.add_argument("--snippets", type=int, default=2, help="Maximum snippets per hit")
parser.add_argument("--max-bytes", type=int, default=DEFAULT_MAX_BYTES, help="Tail bytes to scan per session file")
parser.add_argument("--max-files-per-root", type=int, default=5000, help="Maximum files to scan per root")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Validate numeric CLI bounds at parse time.

Negative values currently produce surprising behavior (for example, --limit -1 slices results unexpectedly, and negative scan limits can short-circuit traversal). Add explicit integer bounds in argument parsing.

Suggested fix
+def positive_int(value: str) -> int:
+    ivalue = int(value)
+    if ivalue <= 0:
+        raise argparse.ArgumentTypeError("must be > 0")
+    return ivalue
+
 def main() -> int:
@@
-    parser.add_argument("--limit", type=int, default=DEFAULT_LIMIT, help="Maximum hits to print")
-    parser.add_argument("--snippets", type=int, default=2, help="Maximum snippets per hit")
-    parser.add_argument("--max-bytes", type=int, default=DEFAULT_MAX_BYTES, help="Tail bytes to scan per session file")
-    parser.add_argument("--max-files-per-root", type=int, default=5000, help="Maximum files to scan per root")
+    parser.add_argument("--limit", type=positive_int, default=DEFAULT_LIMIT, help="Maximum hits to print")
+    parser.add_argument("--snippets", type=positive_int, default=2, help="Maximum snippets per hit")
+    parser.add_argument("--max-bytes", type=positive_int, default=DEFAULT_MAX_BYTES, help="Tail bytes to scan per session file")
+    parser.add_argument("--max-files-per-root", type=positive_int, default=5000, help="Maximum files to scan per root")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/codexmate-cross-session-search/scripts/search_sessions.py` around
lines 220 - 223, The numeric CLI arguments (--limit, --snippets, --max-bytes,
and --max-files-per-root) in the parser.add_argument calls lack bounds
validation, allowing negative values that cause unexpected behavior. Define a
custom type validation function that ensures these arguments are positive
integers (greater than 0), then apply this validation function via the type
parameter in each of these add_argument calls. This will reject invalid negative
values at parse time rather than allowing them to produce surprising results
during execution.

@awsl233777

Copy link
Copy Markdown
Collaborator Author

Follow-up after skepticism/negative testing:

This skill should be described as a best-effort local session evidence locator, not a semantic memory system.

I found and fixed a false-positive case in the search script: a hyphenated unknown query such as completely-nonexistent-token-zzq-197 could previously match just because one split fragment (for example 197) appeared in a session. --match all now requires a hyphen/slash token to match as the raw token or for all split parts to match.

Additional validation:

python3 skills/codexmate-cross-session-search/scripts/search_sessions.py 'completely-nonexistent-token-zzq-197' --source all --path-filter codexmate --match all --limit 2 --format text
# No matching sessions found.

python3 skills/codexmate-cross-session-search/scripts/search_sessions.py 'feat/task-orchestration-tab' --source all --path-filter codexmate --match all --limit 2 --format text
# Finds real codexmate Codex sessions with matching branch metadata.

npm run lint
npm run test:unit
python3 ~/.npm-global/lib/node_modules/openclaw/skills/skill-creator/scripts/package_skill.py skills/codexmate-cross-session-search /tmp/codexmate-skill-dist

Results:

  • lint passed
  • unit passed: 657 tests
  • skill packaging passed
  • added a regression test for the false-positive case

Scope clarified in SKILL.md: use hard identifiers such as repo names, branches, file paths, commit hashes, exact errors, and PR/issue numbers with project filters; treat generic language and short tokens skeptically.

@awsl233777 awsl233777 changed the title feat: add cross-session search skill feat: add project context recovery skill Jun 14, 2026
@awsl233777

Copy link
Copy Markdown
Collaborator Author

Implemented the proposed “方案 B” direction.

The PR no longer positions this as a strong semantic search/memory feature. It is now a project context recovery / handoff brief skill:

  • renamed skill frontmatter to codexmate-project-context-recovery
  • renamed bundled skill directory to skills/codexmate-project-context-recovery
  • added --mode brief on top of raw --mode search
  • brief output includes confidence, timeline, repo/branch/PR/file signals, commands, validations, risks, and handoff reminders
  • tightened hyphen/slash matching so unknown compound queries cannot match just because one fragment appears
  • added tests for both search and brief generation
  • clarified limits in SKILL.md: this is historical session evidence, not semantic memory and not live GitHub/current-state truth

Validation run locally:

python3 skills/codexmate-project-context-recovery/scripts/search_sessions.py 'feat/task-orchestration-tab' --mode brief --source all --path-filter codexmate --match all --limit 2 --format text
python3 skills/codexmate-project-context-recovery/scripts/search_sessions.py 'completely-nonexistent-token-zzq-197' --source all --path-filter codexmate --match all --limit 2 --format text
npm run lint
npm run test:unit
python3 ~/.npm-global/lib/node_modules/openclaw/skills/skill-creator/scripts/package_skill.py skills/codexmate-project-context-recovery /tmp/codexmate-skill-dist
npm pack --dry-run --json

Results:

  • lint passed for 220 files
  • unit passed: 656 tests
  • skill package validation passed
  • npm dry-run includes the new skill SKILL.md and bundled script
  • false-positive regression now returns no matching sessions

Remaining honest limitation: the brief extraction is still heuristic. It improves the handoff value beyond raw grep, but it is not a full semantic memory/indexing system. Mutable facts still require live checks.

@awsl233777

Copy link
Copy Markdown
Collaborator Author

Addressed the two actionable CodeRabbit findings on the current implementation:

  1. Exposed the grouped --source codexmate-derived selector so the candidate_roots() prefix behavior is reachable from the CLI.
  2. Added positive_int argument validation for numeric CLI options: --limit, --brief-items, --snippets, --max-bytes, and --max-files-per-root.

Regression coverage added:

  • fixture verifies --source codexmate-derived finds derived codexmate sessions
  • fixture verifies --limit -1 is rejected at parse time

Validation after the fix:

npm run lint
npm run test:unit
python3 ~/.npm-global/lib/node_modules/openclaw/skills/skill-creator/scripts/package_skill.py skills/codexmate-project-context-recovery /tmp/codexmate-skill-dist
npm pack --dry-run --json

Results:

  • lint passed for 220 files
  • unit passed: 656 tests
  • skill package validation passed
  • npm dry-run includes the new skill files

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (3)
skills/codexmate-project-context-recovery/scripts/search_sessions.py (1)

254-258: 💤 Low value

Consider catching a more specific exception type.

The bare except Exception catch is overly broad. Since json.loads raises json.JSONDecodeError (subclass of ValueError), catching that specifically would be more precise. However, given this is a defensive parser for unknown session formats, the broad catch is acceptable if intentional.

♻️ Optional fix for more specific exception handling
         if m:
             try:
                 return json.loads('"' + m.group(1) + '"')
-            except Exception:
+            except (json.JSONDecodeError, UnicodeDecodeError):
                 return m.group(1)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skills/codexmate-project-context-recovery/scripts/search_sessions.py` around
lines 254 - 258, Replace the overly broad `except Exception` clause in the
json.loads error handling block with a more specific exception type. Since
json.loads raises json.JSONDecodeError when it fails to parse the JSON string,
change the except clause to catch json.JSONDecodeError specifically instead of
the generic Exception class. This makes the error handling more precise and
clearly documents what exceptions are actually expected from the json.loads
call.

Source: Linters/SAST tools

tests/unit/codexmate-project-context-recovery-skill.test.mjs (2)

31-32: ⚡ Quick win

Consider emitting a skip message when python3 is unavailable.

The test silently returns when python3 is not found. While this prevents spurious failures, it also hides that the test didn't run.

💡 Suggested enhancement
 test('project context recovery skill script finds evidence and builds a handoff brief', () => {
-    if (!hasPython3()) return;
+    if (!hasPython3()) {
+        console.log('⊘ Skipping project-context-recovery skill test: python3 not found');
+        return;
+    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/codexmate-project-context-recovery-skill.test.mjs` around lines 31
- 32, The test for "project context recovery skill script finds evidence and
builds a handoff brief" silently returns when python3 is unavailable via the
hasPython3() check, making it unclear that the test was skipped rather than
passed. Replace the silent return with the test framework's skip mechanism (such
as test.skip()) to emit a skip message that makes it visible when the test is
not executed due to missing python3.

82-89: Brief mode assertions depend on internal script scoring and term matching.

Lines 83 and 88 assert specific confidence levels and evidence content that depend on:

  • The script's internal score calculation reaching >= 20 for confidence='high' (Line 83)
  • The script's VALIDATION_TERMS matching "npm run lint" text (Line 88)

These assertions are valid for the current implementation but may be fragile if the script's scoring logic or term lists change. Consider this when maintaining the test.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/codexmate-project-context-recovery-skill.test.mjs` around lines 82
- 89, The test assertions at lines 83 and 88 are fragile because they depend on
internal implementation details of the script: the confidence level assertion
depends on the script's internal score calculation logic, and the validation
term assertion depends on specific strings in the script's VALIDATION_TERMS. To
make the test more maintainable, either refactor these assertions to test the
behavior rather than specific implementation values, or add explanatory comments
documenting exactly which internal script components these assertions depend on
and under what conditions they might need updating.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@skills/codexmate-project-context-recovery/SKILL.md`:
- Around line 18-26: The quick-start command examples in SKILL.md reference
`python3 scripts/search_sessions.py` without clarifying the actual location of
this script after npm installation. Add a clarification note in the
documentation that explains either the full path to the script within the
installed node_modules directory
(node_modules/codexmate/skills/codexmate-project-context-recovery/scripts/search_sessions.py)
or documents an alternative invocation pattern (such as a CLI entrypoint if
available). This will help users understand how to properly locate and invoke
the script after installation rather than assuming they are running from within
the skills directory.
- Around line 39-43: The SKILL.md file contains mixed-language section headers
with Chinese characters (`当前对象`, `历史证据`, `接手简报`, `实时核查`) that are inconsistent
with the rest of the document which is written in English. Replace each of these
four Chinese headers with their English equivalents to maintain language
consistency throughout the document. Ensure all section headers in the file use
the same language to improve readability for all audiences.
- Line 33: The confidence level guidance at line 33 in the SKILL.md file is
incomplete. Currently it documents `high` and `medium/weak` confidence levels,
but omits the `none` confidence level that the brief builder can emit when no
search hits are found. Update the documentation to include all three confidence
levels by adding a case for `none` confidence, explaining that it indicates no
hits were found and guidance on how to proceed when encountering this level.

In `@tests/unit/run.mjs`:
- Line 23: Add a missing import statement for the cross-session search skill
test file in the test runner. In run.mjs, after the existing import statement
for codexmate-project-context-recovery-skill.test.mjs, add a new import
statement that follows the same pattern to dynamically import
codexmate-cross-session-search-skill.test.mjs using pathToFileURL and path.join
with __dirname. This ensures both skill test files are registered in the
runner's dynamic import sequence.

---

Nitpick comments:
In `@skills/codexmate-project-context-recovery/scripts/search_sessions.py`:
- Around line 254-258: Replace the overly broad `except Exception` clause in the
json.loads error handling block with a more specific exception type. Since
json.loads raises json.JSONDecodeError when it fails to parse the JSON string,
change the except clause to catch json.JSONDecodeError specifically instead of
the generic Exception class. This makes the error handling more precise and
clearly documents what exceptions are actually expected from the json.loads
call.

In `@tests/unit/codexmate-project-context-recovery-skill.test.mjs`:
- Around line 31-32: The test for "project context recovery skill script finds
evidence and builds a handoff brief" silently returns when python3 is
unavailable via the hasPython3() check, making it unclear that the test was
skipped rather than passed. Replace the silent return with the test framework's
skip mechanism (such as test.skip()) to emit a skip message that makes it
visible when the test is not executed due to missing python3.
- Around line 82-89: The test assertions at lines 83 and 88 are fragile because
they depend on internal implementation details of the script: the confidence
level assertion depends on the script's internal score calculation logic, and
the validation term assertion depends on specific strings in the script's
VALIDATION_TERMS. To make the test more maintainable, either refactor these
assertions to test the behavior rather than specific implementation values, or
add explanatory comments documenting exactly which internal script components
these assertions depend on and under what conditions they might need updating.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8ba8cf07-63df-427c-9437-654659e9bf16

📥 Commits

Reviewing files that changed from the base of the PR and between 08ec4d1 and ab003e7.

📒 Files selected for processing (5)
  • skills/codexmate-project-context-recovery/SKILL.md
  • skills/codexmate-project-context-recovery/scripts/search_sessions.py
  • tests/unit/codexmate-cross-session-search-skill.test.mjs
  • tests/unit/codexmate-project-context-recovery-skill.test.mjs
  • tests/unit/run.mjs
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/unit/codexmate-cross-session-search-skill.test.mjs
📜 Review details
🧰 Additional context used
🪛 ast-grep (0.43.0)
skills/codexmate-project-context-recovery/scripts/search_sessions.py

[info] 455-455: use jsonify instead of json.dumps for JSON output
Context: json.dumps({"hits": [hit.dict for hit in hits]}, ensure_ascii=False, indent=2)
Note: Security best practice.

(use-jsonify)


[info] 528-528: use jsonify instead of json.dumps for JSON output
Context: json.dumps(brief, ensure_ascii=False, indent=2)
Note: Security best practice.

(use-jsonify)

🪛 Ruff (0.15.15)
skills/codexmate-project-context-recovery/scripts/search_sessions.py

[warning] 256-256: Do not catch blind exception: Exception

(BLE001)


[warning] 335-335: String contains ambiguous (FULLWIDTH EXCLAMATION MARK). Did you mean ! (EXCLAMATION MARK)?

(RUF001)


[warning] 335-335: String contains ambiguous (FULLWIDTH QUESTION MARK). Did you mean ? (QUESTION MARK)?

(RUF001)

🔇 Additional comments (10)
skills/codexmate-project-context-recovery/scripts/search_sessions.py (7)

1-56: LGTM!


58-68: LGTM!


71-115: LGTM!


118-155: LGTM!


261-346: LGTM!


349-391: LGTM!


394-539: LGTM!

tests/unit/codexmate-project-context-recovery-skill.test.mjs (3)

1-21: LGTM!


23-29: LGTM!


91-100: LGTM!

Comment thread skills/codexmate-project-context-recovery/SKILL.md
Comment thread skills/codexmate-project-context-recovery/SKILL.md Outdated
Comment thread skills/codexmate-project-context-recovery/SKILL.md Outdated
Comment thread tests/unit/run.mjs
await import(pathToFileURL(path.join(__dirname, 'task-codex-exec-windows.test.mjs')));
await import(pathToFileURL(path.join(__dirname, 'skills-modal-ui.test.mjs')));
await import(pathToFileURL(path.join(__dirname, 'skills-market-runtime.test.mjs')));
await import(pathToFileURL(path.join(__dirname, 'codexmate-project-context-recovery-skill.test.mjs')));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if cross-session-search skill test exists and is registered in runner

echo "=== Checking if test file exists ==="
fd -t f 'codexmate-cross-session-search-skill.test.mjs' tests/

echo ""
echo "=== Checking if it's imported in run.mjs ==="
rg -n 'codexmate-cross-session-search-skill' tests/unit/run.mjs

Repository: SakuraByteCore/codexmate

Length of output: 208


Add import for codexmate-cross-session-search-skill.test.mjs to the test runner.

The test file codexmate-cross-session-search-skill.test.mjs exists but is not imported in run.mjs. The layer description indicates both the cross-session search skill test and the project-context recovery skill test should be registered in the runner's dynamic import sequence. Add the missing import alongside the existing codexmate-project-context-recovery-skill.test.mjs import.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/run.mjs` at line 23, Add a missing import statement for the
cross-session search skill test file in the test runner. In run.mjs, after the
existing import statement for codexmate-project-context-recovery-skill.test.mjs,
add a new import statement that follows the same pattern to dynamically import
codexmate-cross-session-search-skill.test.mjs using pathToFileURL and path.join
with __dirname. This ensures both skill test files are registered in the
runner's dynamic import sequence.

@awsl233777

Copy link
Copy Markdown
Collaborator Author

Addressed the current SKILL.md CodeRabbit comments:

  • clarified how to resolve scripts/search_sessions.py relative to the skill directory and documented the npm package path: node_modules/codexmate/skills/codexmate-project-context-recovery/scripts/search_sessions.py
  • documented the none confidence level for no-hit briefs
  • replaced mixed Chinese/English output labels with English labels

I did not re-add codexmate-cross-session-search-skill.test.mjs: that comment is stale after the skill rename. The old test file was intentionally deleted and replaced by codexmate-project-context-recovery-skill.test.mjs, which is imported from tests/unit/run.mjs.

Validation:

npm run lint
npm run test:unit
python3 ~/.npm-global/lib/node_modules/openclaw/skills/skill-creator/scripts/package_skill.py skills/codexmate-project-context-recovery /tmp/codexmate-skill-dist

Results:

  • lint passed for 220 files
  • unit passed: 656 tests
  • skill package validation passed

@awsl233777

Copy link
Copy Markdown
Collaborator Author

Updated this PR to bump the package version to 0.0.50 / v0.0.50 semantics in the PR commit.

Changes:

  • package.json: 0.0.490.0.50
  • package-lock.json: root package version entries updated to 0.0.50
  • removed stale tests/unit/codexmate-cross-session-search-skill.test.mjs, now replaced by tests/unit/codexmate-project-context-recovery-skill.test.mjs

Validation before committing:

npm run lint
npm run test:unit
python3 ~/.npm-global/lib/node_modules/openclaw/skills/skill-creator/scripts/package_skill.py skills/codexmate-project-context-recovery /tmp/codexmate-skill-dist
npm pack --dry-run --json

Results:

  • lint passed for 220 files
  • unit passed: 656 tests
  • skill package validation passed
  • npm dry-run includes the project context recovery skill files

Note: I used npm version 0.0.50 --no-git-tag-version, so the version/tag text is represented in the PR commit without creating a local or remote git tag.

@awsl233777 awsl233777 changed the title feat: add project context recovery skill feat: add project context recovery skill for v0.0.50 Jun 14, 2026
@ymkiux ymkiux merged commit 4566066 into main Jun 14, 2026
9 checks passed
@ymkiux ymkiux deleted the feat/cross-session-search-skill branch June 14, 2026 15:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants