@neikyun/ciel 6.9.2 → 6.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -33,6 +33,11 @@ declare -a SOURCES=(
33
33
  # .claude/rules/*.md detected separately (variable count)
34
34
  RULES_DIR="$PROJECT_DIR/.claude/rules"
35
35
 
36
+ # Claude Code's per-project auto-memory dir. Lives OUTSIDE the repo, derived
37
+ # from cwd with `/` replaced by `-`. Tests override via CIEL_AUTO_MEMORY_DIR.
38
+ # Pattern: ~/.claude/projects/-Users-foo-Projects-Bar/memory/
39
+ AUTO_MEMORY_DIR="${CIEL_AUTO_MEMORY_DIR:-$HOME/.claude/projects/$(echo "$PROJECT_DIR" | sed 's|/|-|g')/memory}"
40
+
36
41
  # ─── Helpers ─────────────────────────────────────────────────────────────────
37
42
 
38
43
  scan_sources() {
@@ -58,6 +63,17 @@ scan_sources() {
58
63
  fi
59
64
  fi
60
65
 
66
+ # Claude Code auto-memory — excludes the MEMORY.md index file (just a TOC,
67
+ # not memory content). Each *.md sibling is a discrete entry to migrate.
68
+ if [[ -d "$AUTO_MEMORY_DIR" ]]; then
69
+ local auto_count
70
+ auto_count=$(find "$AUTO_MEMORY_DIR" -maxdepth 1 -name "*.md" -type f -not -name "MEMORY.md" 2>/dev/null | wc -l | tr -d ' ')
71
+ if [[ "$auto_count" -gt 0 ]]; then
72
+ echo " ✓ $AUTO_MEMORY_DIR/ ($auto_count Claude Code auto-memory entries — to migrate to .ciel/memory/)"
73
+ found=$((found + auto_count))
74
+ fi
75
+ fi
76
+
61
77
  echo ""
62
78
  if [[ "$found" -eq 0 ]]; then
63
79
  echo "No ingestable sources found. The cued-recall memory will populate"
@@ -233,8 +233,16 @@ def match_path_pattern(pattern: str, paths) -> bool:
233
233
  return False
234
234
 
235
235
 
236
- def score_memory(mem, paths, symbols, intents, langs) -> int:
237
- """Score a memory's relevance. 0 = exclude. Positive = include, higher first."""
236
+ def score_memory(mem, paths, symbols, intents, langs, prompt_lower="") -> int:
237
+ """Score a memory's relevance. 0 = exclude. Positive = include, higher first.
238
+
239
+ Symbol and intent matching are case-insensitive and fall back to a
240
+ word-boundary search against the raw prompt. This lets a memory tagged
241
+ `symbols: [OkHttp]` fire on a prompt that mentions "okhttp" in prose,
242
+ and lets free-form intent tags (e.g. `intents: [okhttp, diagnostics]`)
243
+ match without being members of the fixed INTENT_KEYWORDS vocabulary.
244
+ Word boundaries prevent "test" intent from firing on "contest".
245
+ """
238
246
  # Hard language gate: if memory is language-specific AND prompt has language
239
247
  # cues AND no overlap → exclude. Avoids Kotlin memories firing on TS edits.
240
248
  mem_langs = mem.get('languages') or []
@@ -245,11 +253,23 @@ def score_memory(mem, paths, symbols, intents, langs) -> int:
245
253
  for pattern in mem.get('path_patterns') or []:
246
254
  if match_path_pattern(pattern, paths):
247
255
  score += 10
256
+
257
+ # Case-insensitive comparison sets — built once per memory call.
258
+ symbols_lower = {s.lower() for s in symbols}
259
+ intents_lower = {i.lower() for i in intents}
260
+
248
261
  for sym in mem.get('symbols') or []:
249
- if sym in symbols:
262
+ sym_lower = sym.lower()
263
+ if sym_lower in symbols_lower or (
264
+ prompt_lower and re.search(r'\b' + re.escape(sym_lower) + r'\b', prompt_lower)
265
+ ):
250
266
  score += 8
267
+
251
268
  for intent in mem.get('intents') or []:
252
- if intent in intents:
269
+ intent_lower = intent.lower()
270
+ if intent_lower in intents_lower or (
271
+ prompt_lower and re.search(r'\b' + re.escape(intent_lower) + r'\b', prompt_lower)
272
+ ):
253
273
  score += 5
254
274
 
255
275
  # No cue match at all → don't include (cued recall, not free recall)
@@ -399,6 +419,7 @@ def cmd_query(args):
399
419
  symbols = extract_symbol_cues(prompt)
400
420
  intents = extract_intent_cues(prompt)
401
421
  langs = extract_language_cues(prompt)
422
+ prompt_lower = prompt.lower()
402
423
  now = datetime.now(timezone.utc)
403
424
  iso_now = now.isoformat().replace('+00:00', 'Z')
404
425
 
@@ -418,7 +439,7 @@ def cmd_query(args):
418
439
  for mid, m in mems.items():
419
440
  if m.get('stale'):
420
441
  continue
421
- s = score_memory(m, paths, symbols, intents, langs)
442
+ s = score_memory(m, paths, symbols, intents, langs, prompt_lower=prompt_lower)
422
443
  if s > 0:
423
444
  scored.append((s, mid, m))
424
445
 
@@ -1,10 +1,10 @@
1
1
  ---
2
- description: Scan project for ingestable tribal docs (lessons.md, ciel-overlay.md, .claude/rules/, etc.) and propose ingestion into the cued-recall memory under .ciel/memory/. Reports findings if no sources found. Always confirms each candidate with the user before writing.
2
+ description: Scan project for ingestable tribal docs (lessons.md, ciel-overlay.md, .claude/rules/, Claude Code auto-memory at ~/.claude/projects/<slug>/memory/, etc.) and propose ingestion into the cued-recall memory under .ciel/memory/. Reports findings if no sources found. Always confirms each candidate with the user before writing.
3
3
  ---
4
4
 
5
5
  # /ciel-memory-bootstrap — Initialize Cued-Recall Memory
6
6
 
7
- **Purpose:** First-run scan of an existing project to convert tribal knowledge already documented in `lessons.md`, `ciel-overlay.md`, `.claude/rules/`, and similar files into the structured cued-recall memory at `.ciel/memory/`.
7
+ **Purpose:** First-run scan of an existing project to convert tribal knowledge already documented in `lessons.md`, `ciel-overlay.md`, `.claude/rules/`, Claude Code's per-project auto-memory (`~/.claude/projects/<slug>/memory/`), and similar files into the structured cued-recall memory at `.ciel/memory/`.
8
8
 
9
9
  **Usage:** `/ciel-memory-bootstrap` (no args)
10
10
 
@@ -60,6 +60,39 @@ For each source found in Step 1, `Read` the file fully. Identify candidate memor
60
60
  | `## Heading\n\n- rule\n- rule` (rules.md style) | One memory per rule. |
61
61
  | Numbered lessons in `ciel-overlay.md` "Key Lessons" | One memory per lesson. |
62
62
  | `## section` in CLAUDE.md/AGENTS.md describing a non-obvious convention | One memory per section. |
63
+ | **Claude Code auto-memory** entries (`~/.claude/projects/<slug>/memory/*.md`, excluding `MEMORY.md`) | One memory per file. Title = frontmatter `description`. Cues derived per "Auto-memory mapping" below. |
64
+
65
+ #### Auto-memory mapping (special parser)
66
+
67
+ Claude Code auto-memory uses a different frontmatter than Ciel's cued-recall. Each source file looks like:
68
+
69
+ ```yaml
70
+ ---
71
+ name: feedback-okhttp-cookiejar-override
72
+ description: Neiyomi shared PersistentCookieJar overrides manual Cookie headers via OkHttp BridgeInterceptor
73
+ metadata:
74
+ type: feedback
75
+ ---
76
+
77
+ (body markdown — Context / Why / How to apply sections)
78
+ ```
79
+
80
+ When you encounter a file under `$AUTO_MEMORY_DIR`, map it to a Ciel episode as follows:
81
+
82
+ | Auto-memory field | Ciel frontmatter field | Notes |
83
+ |---|---|---|
84
+ | `description:` | `title:` | one-line summary |
85
+ | `name:` | base of slug for filename | already kebab-case |
86
+ | `metadata.type:` (`user`/`feedback`/`project`/`reference`) | `intents:` `[<type>]` plus topic-specific intents inferred from body | e.g. `feedback` + `okhttp` + `cookie` |
87
+ | body markdown | Ciel episode body, verbatim | preserve Context/Why/How to apply structure |
88
+ | paths cited in body (e.g. `src/`, `*.kt`, `Caddyfile`) | `path_patterns:` | infer from grep — narrow patterns preferred |
89
+ | symbols cited in body (class/function/table names) | `symbols:` | infer from grep |
90
+ | language hint (file extensions in body) | `languages:` | `kotlin`/`typescript`/`python`/`sql`/etc. |
91
+ | `captured_from:` (NEW) | `auto-memory-migration` | distinguishes from user-intervention captures |
92
+
93
+ **Skip `MEMORY.md`** — it's a table-of-contents index, not memory content. The scan already excludes it.
94
+
95
+ **Backup before delete.** After successfully writing an episode file for an auto-memory entry, MOVE (not delete) the source to `$AUTO_MEMORY_DIR/.migrated-to-ciel/<filename>` so the user can audit migration. The MEMORY.md index file itself stays in place — Claude Code may regenerate it on next session.
63
96
 
64
97
  Skip:
65
98
  - The pipeline / workflow descriptions (those belong in CLAUDE.md, not memory)
@@ -152,6 +185,8 @@ Report:
152
185
  | Nothing scanned | No tribal docs in this project | Working as intended; report and end |
153
186
  | Memories all tagged with broad paths | Source content didn't include path hints | Ask user to refine tags after listing |
154
187
  | index.json malformed after rebuild | python3 parse error | Recreate empty index, re-run rebuild step |
188
+ | Auto-memory not detected | Slug derivation mismatch (cwd has unexpected characters) | Override via `CIEL_AUTO_MEMORY_DIR=<absolute-path> bash hooks/memory-bootstrap.sh scan` |
189
+ | Auto-memory file has `name:` but no `description:` | Older auto-memory format | Use first heading or filename as title; ask user to confirm before writing |
155
190
 
156
191
  ## See also
157
192
 
@@ -15,7 +15,7 @@ Usage: `/ciel-status [--check]`
15
15
  ```
16
16
  ## CIEL STATUS
17
17
 
18
- Version: v6.9.2
18
+ Version: v6.10.1
19
19
  Platform: Claude Code
20
20
  Config: .claude/settings.json — OK (4 hooks registered)
21
21
  Skills directory: skills/ — 43 skills loaded
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neikyun/ciel",
3
- "version": "6.9.2",
3
+ "version": "6.10.1",
4
4
  "description": "Ciel — Deep-reasoning pipeline for LLM-assisted development. OpenCode plugin + multi-platform CLI (OpenCode, Claude Code, more).",
5
5
  "main": "./dist/plugin/index.js",
6
6
  "types": "./dist/plugin/index.d.ts",