ragtime-cli 0.2.18__py3-none-any.whl → 0.3.1__py3-none-any.whl
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.
- {ragtime_cli-0.2.18.dist-info → ragtime_cli-0.3.1.dist-info}/METADATA +61 -28
- ragtime_cli-0.3.1.dist-info/RECORD +16 -0
- src/cli.py +872 -106
- src/config.py +17 -1
- src/indexers/docs.py +86 -8
- ragtime_cli-0.2.18.dist-info/RECORD +0 -26
- src/commands/audit.md +0 -151
- src/commands/create-pr.md +0 -389
- src/commands/generate-docs.md +0 -325
- src/commands/handoff.md +0 -176
- src/commands/import-docs.md +0 -259
- src/commands/pr-graduate.md +0 -192
- src/commands/recall.md +0 -175
- src/commands/remember.md +0 -168
- src/commands/save.md +0 -10
- src/commands/start.md +0 -206
- {ragtime_cli-0.2.18.dist-info → ragtime_cli-0.3.1.dist-info}/WHEEL +0 -0
- {ragtime_cli-0.2.18.dist-info → ragtime_cli-0.3.1.dist-info}/entry_points.txt +0 -0
- {ragtime_cli-0.2.18.dist-info → ragtime_cli-0.3.1.dist-info}/licenses/LICENSE +0 -0
- {ragtime_cli-0.2.18.dist-info → ragtime_cli-0.3.1.dist-info}/top_level.txt +0 -0
src/config.py
CHANGED
|
@@ -51,9 +51,15 @@ class CodeConfig:
|
|
|
51
51
|
|
|
52
52
|
@dataclass
|
|
53
53
|
class ConventionsConfig:
|
|
54
|
-
"""Configuration for convention checking."""
|
|
54
|
+
"""Configuration for convention checking and storage."""
|
|
55
|
+
# Reading conventions
|
|
55
56
|
files: list[str] = field(default_factory=lambda: [".ragtime/CONVENTIONS.md"])
|
|
56
57
|
also_search_memories: bool = True
|
|
58
|
+
# Writing conventions
|
|
59
|
+
storage: str = "auto" # "auto" | "file" | "memory" | "ask"
|
|
60
|
+
default_file: str = ".ragtime/CONVENTIONS.md"
|
|
61
|
+
folder: str = ".ragtime/conventions/"
|
|
62
|
+
scan_docs_for_sections: list[str] = field(default_factory=lambda: ["docs/"])
|
|
57
63
|
|
|
58
64
|
|
|
59
65
|
@dataclass
|
|
@@ -97,6 +103,12 @@ class RagtimeConfig:
|
|
|
97
103
|
also_search_memories=conventions_data.get(
|
|
98
104
|
"also_search_memories", ConventionsConfig().also_search_memories
|
|
99
105
|
),
|
|
106
|
+
storage=conventions_data.get("storage", ConventionsConfig().storage),
|
|
107
|
+
default_file=conventions_data.get("default_file", ConventionsConfig().default_file),
|
|
108
|
+
folder=conventions_data.get("folder", ConventionsConfig().folder),
|
|
109
|
+
scan_docs_for_sections=conventions_data.get(
|
|
110
|
+
"scan_docs_for_sections", ConventionsConfig().scan_docs_for_sections
|
|
111
|
+
),
|
|
100
112
|
),
|
|
101
113
|
)
|
|
102
114
|
|
|
@@ -120,6 +132,10 @@ class RagtimeConfig:
|
|
|
120
132
|
"conventions": {
|
|
121
133
|
"files": self.conventions.files,
|
|
122
134
|
"also_search_memories": self.conventions.also_search_memories,
|
|
135
|
+
"storage": self.conventions.storage,
|
|
136
|
+
"default_file": self.conventions.default_file,
|
|
137
|
+
"folder": self.conventions.folder,
|
|
138
|
+
"scan_docs_for_sections": self.conventions.scan_docs_for_sections,
|
|
123
139
|
},
|
|
124
140
|
}
|
|
125
141
|
|
src/indexers/docs.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Docs indexer - parses markdown files with YAML frontmatter.
|
|
3
3
|
|
|
4
|
-
Designed for .
|
|
4
|
+
Designed for .ragtime/ style files but works with any markdown.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import os
|
|
@@ -70,12 +70,23 @@ class Section:
|
|
|
70
70
|
content: str
|
|
71
71
|
line_start: int
|
|
72
72
|
parent_path: list[str] # Parent headers for context
|
|
73
|
+
is_convention: bool = False # True if this section contains conventions
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# Headers that indicate convention content
|
|
77
|
+
CONVENTION_HEADERS = {
|
|
78
|
+
"conventions", "convention", "rules", "standards", "guidelines",
|
|
79
|
+
"code conventions", "coding conventions", "code standards",
|
|
80
|
+
"coding standards", "style guide", "code style",
|
|
81
|
+
}
|
|
73
82
|
|
|
74
83
|
|
|
75
84
|
def chunk_by_headers(
|
|
76
85
|
content: str,
|
|
77
86
|
min_chunk_size: int = 100,
|
|
78
87
|
max_chunk_size: int = 2000,
|
|
88
|
+
convention_sections: list[str] | None = None,
|
|
89
|
+
all_conventions: bool = False,
|
|
79
90
|
) -> list[Section]:
|
|
80
91
|
"""
|
|
81
92
|
Split markdown into sections by headers, preserving hierarchy.
|
|
@@ -84,38 +95,69 @@ def chunk_by_headers(
|
|
|
84
95
|
content: Markdown body (without frontmatter)
|
|
85
96
|
min_chunk_size: Minimum chars to make a standalone section
|
|
86
97
|
max_chunk_size: Maximum chars before splitting further
|
|
98
|
+
convention_sections: List of section titles to mark as conventions
|
|
99
|
+
all_conventions: If True, mark ALL sections as conventions
|
|
87
100
|
|
|
88
101
|
Returns:
|
|
89
102
|
List of Section objects with hierarchical context
|
|
90
103
|
"""
|
|
91
104
|
lines = content.split('\n')
|
|
92
105
|
sections: list[Section] = []
|
|
93
|
-
header_stack: list[tuple[int, str]] = [] # (level, title)
|
|
106
|
+
header_stack: list[tuple[int, str, bool]] = [] # (level, title, is_convention)
|
|
94
107
|
|
|
95
108
|
current_section_lines: list[str] = []
|
|
96
109
|
current_section_start = 0
|
|
97
110
|
current_title = ""
|
|
98
111
|
current_level = 0
|
|
112
|
+
current_is_convention = False
|
|
113
|
+
in_convention_marker = False # Track <!-- convention --> blocks
|
|
114
|
+
|
|
115
|
+
def is_convention_header(title: str) -> bool:
|
|
116
|
+
"""Check if header indicates convention content."""
|
|
117
|
+
normalized = title.lower().strip()
|
|
118
|
+
return normalized in CONVENTION_HEADERS or any(
|
|
119
|
+
conv in normalized for conv in ["convention", "rule", "standard", "guideline"]
|
|
120
|
+
)
|
|
99
121
|
|
|
100
122
|
def flush_section():
|
|
101
123
|
"""Save accumulated lines as a section."""
|
|
102
|
-
nonlocal current_section_lines, current_section_start, current_title, current_level
|
|
124
|
+
nonlocal current_section_lines, current_section_start, current_title, current_level, current_is_convention
|
|
103
125
|
|
|
104
126
|
text = '\n'.join(current_section_lines).strip()
|
|
105
127
|
if text:
|
|
106
128
|
# Build parent path from stack (excluding current)
|
|
107
129
|
parent_path = [h[1] for h in header_stack[:-1]] if header_stack else []
|
|
108
130
|
|
|
131
|
+
# Check if any parent is a convention header
|
|
132
|
+
parent_is_convention = any(h[2] for h in header_stack[:-1]) if header_stack else False
|
|
133
|
+
|
|
134
|
+
# Determine if this section is a convention
|
|
135
|
+
is_conv = (
|
|
136
|
+
all_conventions or
|
|
137
|
+
current_is_convention or
|
|
138
|
+
parent_is_convention or
|
|
139
|
+
(convention_sections and current_title in convention_sections)
|
|
140
|
+
)
|
|
141
|
+
|
|
109
142
|
sections.append(Section(
|
|
110
143
|
title=current_title or "Introduction",
|
|
111
144
|
level=current_level,
|
|
112
145
|
content=text,
|
|
113
146
|
line_start=current_section_start,
|
|
114
147
|
parent_path=parent_path,
|
|
148
|
+
is_convention=is_conv,
|
|
115
149
|
))
|
|
116
150
|
current_section_lines = []
|
|
117
151
|
|
|
118
152
|
for i, line in enumerate(lines):
|
|
153
|
+
# Detect convention markers
|
|
154
|
+
if '<!-- convention -->' in line.lower() or '<!-- conventions -->' in line.lower():
|
|
155
|
+
in_convention_marker = True
|
|
156
|
+
continue
|
|
157
|
+
if '<!-- /convention -->' in line.lower() or '<!-- /conventions -->' in line.lower():
|
|
158
|
+
in_convention_marker = False
|
|
159
|
+
continue
|
|
160
|
+
|
|
119
161
|
# Detect markdown headers
|
|
120
162
|
header_match = re.match(r'^(#{1,6})\s+(.+)$', line)
|
|
121
163
|
|
|
@@ -126,16 +168,23 @@ def chunk_by_headers(
|
|
|
126
168
|
level = len(header_match.group(1))
|
|
127
169
|
title = header_match.group(2).strip()
|
|
128
170
|
|
|
171
|
+
# Check if this is a convention header
|
|
172
|
+
is_conv_header = is_convention_header(title)
|
|
173
|
+
|
|
129
174
|
# Update header stack - pop headers at same or lower level
|
|
130
175
|
while header_stack and header_stack[-1][0] >= level:
|
|
131
176
|
header_stack.pop()
|
|
132
|
-
header_stack.append((level, title))
|
|
177
|
+
header_stack.append((level, title, is_conv_header))
|
|
133
178
|
|
|
134
179
|
current_title = title
|
|
135
180
|
current_level = level
|
|
136
181
|
current_section_start = i
|
|
182
|
+
current_is_convention = is_conv_header or in_convention_marker
|
|
137
183
|
current_section_lines = [line] # Include header in content
|
|
138
184
|
else:
|
|
185
|
+
# If inside a convention marker, mark the content
|
|
186
|
+
if in_convention_marker and not current_is_convention:
|
|
187
|
+
current_is_convention = True
|
|
139
188
|
current_section_lines.append(line)
|
|
140
189
|
|
|
141
190
|
# Don't forget the last section
|
|
@@ -145,8 +194,10 @@ def chunk_by_headers(
|
|
|
145
194
|
processed: list[Section] = []
|
|
146
195
|
for section in sections:
|
|
147
196
|
if len(section.content) < min_chunk_size and processed:
|
|
148
|
-
# Merge into previous section
|
|
197
|
+
# Merge into previous section (inherit is_convention if either has it)
|
|
149
198
|
processed[-1].content += '\n\n' + section.content
|
|
199
|
+
if section.is_convention:
|
|
200
|
+
processed[-1].is_convention = True
|
|
150
201
|
elif len(section.content) > max_chunk_size:
|
|
151
202
|
# Split by paragraphs
|
|
152
203
|
paragraphs = re.split(r'\n\n+', section.content)
|
|
@@ -161,6 +212,7 @@ def chunk_by_headers(
|
|
|
161
212
|
content=current_chunk.strip(),
|
|
162
213
|
line_start=section.line_start,
|
|
163
214
|
parent_path=section.parent_path,
|
|
215
|
+
is_convention=section.is_convention,
|
|
164
216
|
))
|
|
165
217
|
current_chunk = para
|
|
166
218
|
chunk_num += 1
|
|
@@ -175,6 +227,7 @@ def chunk_by_headers(
|
|
|
175
227
|
content=current_chunk.strip(),
|
|
176
228
|
line_start=section.line_start,
|
|
177
229
|
parent_path=section.parent_path,
|
|
230
|
+
is_convention=section.is_convention,
|
|
178
231
|
))
|
|
179
232
|
else:
|
|
180
233
|
processed.append(section)
|
|
@@ -213,13 +266,29 @@ def index_file(file_path: Path, hierarchical: bool = True) -> list[DocEntry]:
|
|
|
213
266
|
base_component = metadata.get("component")
|
|
214
267
|
base_title = metadata.get("title") or file_path.stem
|
|
215
268
|
|
|
269
|
+
# Convention detection from frontmatter
|
|
270
|
+
has_conventions = metadata.get("has_conventions", False)
|
|
271
|
+
convention_sections = metadata.get("convention_sections", [])
|
|
272
|
+
|
|
273
|
+
# Check if filename indicates conventions
|
|
274
|
+
filename_lower = file_path.stem.lower()
|
|
275
|
+
is_convention_file = any(
|
|
276
|
+
term in filename_lower
|
|
277
|
+
for term in ["convention", "conventions", "rules", "standards", "guidelines"]
|
|
278
|
+
)
|
|
279
|
+
|
|
216
280
|
# Short docs: return as single entry
|
|
217
281
|
if not hierarchical or len(body) < 500:
|
|
282
|
+
# Determine category - convention file or has_conventions flag
|
|
283
|
+
category = base_category
|
|
284
|
+
if is_convention_file or has_conventions:
|
|
285
|
+
category = "convention"
|
|
286
|
+
|
|
218
287
|
return [DocEntry(
|
|
219
288
|
content=body.strip(),
|
|
220
289
|
file_path=str(file_path),
|
|
221
290
|
namespace=base_namespace,
|
|
222
|
-
category=
|
|
291
|
+
category=category,
|
|
223
292
|
component=base_component,
|
|
224
293
|
title=base_title,
|
|
225
294
|
mtime=mtime,
|
|
@@ -229,7 +298,11 @@ def index_file(file_path: Path, hierarchical: bool = True) -> list[DocEntry]:
|
|
|
229
298
|
)]
|
|
230
299
|
|
|
231
300
|
# Hierarchical chunking for longer docs
|
|
232
|
-
sections = chunk_by_headers(
|
|
301
|
+
sections = chunk_by_headers(
|
|
302
|
+
body,
|
|
303
|
+
convention_sections=convention_sections,
|
|
304
|
+
all_conventions=has_conventions or is_convention_file,
|
|
305
|
+
)
|
|
233
306
|
entries = []
|
|
234
307
|
|
|
235
308
|
for i, section in enumerate(sections):
|
|
@@ -242,11 +315,16 @@ def index_file(file_path: Path, hierarchical: bool = True) -> list[DocEntry]:
|
|
|
242
315
|
if section.parent_path:
|
|
243
316
|
context_prefix += f"Section: {' > '.join(section.parent_path)}\n\n"
|
|
244
317
|
|
|
318
|
+
# Determine category - convention sections get "convention" category
|
|
319
|
+
category = base_category
|
|
320
|
+
if section.is_convention:
|
|
321
|
+
category = "convention"
|
|
322
|
+
|
|
245
323
|
entries.append(DocEntry(
|
|
246
324
|
content=context_prefix + section.content,
|
|
247
325
|
file_path=str(file_path),
|
|
248
326
|
namespace=base_namespace,
|
|
249
|
-
category=
|
|
327
|
+
category=category,
|
|
250
328
|
component=base_component,
|
|
251
329
|
title=section.title,
|
|
252
330
|
mtime=mtime,
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
ragtime_cli-0.2.18.dist-info/licenses/LICENSE,sha256=9A0wJs2PRDciGRH4F8JUJ-aMKYQyq_gVu2ixrXs-l5A,1070
|
|
2
|
-
src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
src/cli.py,sha256=5UTi586H2S_2rplybhzFbfmfDl-E_YP51KEykVUSi2U,83282
|
|
4
|
-
src/config.py,sha256=tQ6gPLr4ksn2bJPIUjtELFr-k01Eg4g-LDo3GNE6P0Q,4600
|
|
5
|
-
src/db.py,sha256=eWqFGrg3O6hve67EzRJGcAsIpYxWJo4JlrAtlZUUA_s,15169
|
|
6
|
-
src/feedback.py,sha256=cPw_lzusZZPvkgUxs_eV67NtV1FoCfTXUulBPnD78lo,6455
|
|
7
|
-
src/mcp_server.py,sha256=ttXBtWPur6D4FWaJyJf80YaYlkF6Ak6tADNB4tD5N7E,27205
|
|
8
|
-
src/memory.py,sha256=UiHyudKbseMMY-sdcaDSfVBMGj6sFXXw1GxBsZ7nuBc,18450
|
|
9
|
-
src/commands/audit.md,sha256=Xkucm-gfBIMalK9wf7NBbyejpsqBTUAGGlb7GxMtMPY,5137
|
|
10
|
-
src/commands/create-pr.md,sha256=u6-jVkDP_6bJQp6ImK039eY9F6B9E2KlAVlvLY-WV6Q,9483
|
|
11
|
-
src/commands/generate-docs.md,sha256=9W2Yy-PDyC3p5k39uEb31z5YAHkSKsQLg6gV3tLgSnQ,7015
|
|
12
|
-
src/commands/handoff.md,sha256=8VxTddtW08jGTW36GW_rS77JdeSn8vHeMfklrWwVUD4,5055
|
|
13
|
-
src/commands/import-docs.md,sha256=ByIdcfbdiF77HoFv5U6zZ_YvZf00-hAs9EMconXssvY,6927
|
|
14
|
-
src/commands/pr-graduate.md,sha256=nXJMuXeOp0SZfjQ567NUO02Rg9zPQHQFbZbJ4Q_His0,6692
|
|
15
|
-
src/commands/recall.md,sha256=unQPWsmocKRoQR7jRtjrj8aVcMHverjGR6u5mYL8TLw,6008
|
|
16
|
-
src/commands/remember.md,sha256=nNewsUhIqF4wtD1jhVDZvmLZjdcmPN6NmUM43SdWepc,5368
|
|
17
|
-
src/commands/save.md,sha256=7gTpW46AU9Y4l8XVZ8f4h1sEdBfVqIRA7hlidUxMAC4,251
|
|
18
|
-
src/commands/start.md,sha256=qoqhkMgET74DBx8YPIT1-wqCiVBUDxlmevigsCinHSY,6506
|
|
19
|
-
src/indexers/__init__.py,sha256=MYoCPZUpHakMX1s2vWnc9shjWfx_X1_0JzUhpKhnKUQ,454
|
|
20
|
-
src/indexers/code.py,sha256=G2TbiKbWj0e7DV5KsU8-Ggw6ziDb4zTuZ4Bu3ryV4g8,18059
|
|
21
|
-
src/indexers/docs.py,sha256=Q8krHYw0bybUyZaq1sJ0r6Fv-I_6BjTufhqI1eg_25s,9992
|
|
22
|
-
ragtime_cli-0.2.18.dist-info/METADATA,sha256=yzNcOmjrR3rL8K5cnwYa1Y6PZeHKpU4CJfTlcSx1A9Q,13354
|
|
23
|
-
ragtime_cli-0.2.18.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
24
|
-
ragtime_cli-0.2.18.dist-info/entry_points.txt,sha256=cWLbeyMxZNbew-THS3bHXTpCRXt1EaUy5QUOXGXLjl4,75
|
|
25
|
-
ragtime_cli-0.2.18.dist-info/top_level.txt,sha256=74rtVfumQlgAPzR5_2CgYN24MB0XARCg0t-gzk6gTrM,4
|
|
26
|
-
ragtime_cli-0.2.18.dist-info/RECORD,,
|
src/commands/audit.md
DELETED
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Audit local memories for duplicates, conflicts, and stale data
|
|
3
|
-
allowed-tools: Bash, mcp__ragtime__search, mcp__ragtime__list_memories, mcp__ragtime__forget, mcp__ragtime__update_status, AskUserQuestion
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Memory Audit
|
|
7
|
-
|
|
8
|
-
Periodic cleanup of local memories. This is a **human-in-the-loop** review - no automatic deletions.
|
|
9
|
-
|
|
10
|
-
<!-- ═══════════════════════════════════════════════════════════════════════════
|
|
11
|
-
CUSTOMIZABLE: Add project-specific audit rules, adjust the report format,
|
|
12
|
-
add custom namespace checks, etc.
|
|
13
|
-
═══════════════════════════════════════════════════════════════════════════ -->
|
|
14
|
-
|
|
15
|
-
## Namespaces to Audit
|
|
16
|
-
|
|
17
|
-
- `app` - Codebase knowledge (architecture, decisions)
|
|
18
|
-
- `team` - Team conventions (standards, processes)
|
|
19
|
-
- `user-*` - Developer preferences
|
|
20
|
-
- `branch-*` - Branch-specific context and decisions
|
|
21
|
-
|
|
22
|
-
## Step 1: Gather All Memories
|
|
23
|
-
|
|
24
|
-
<!-- ═══════════════════════════════════════════════════════════════════════════
|
|
25
|
-
RAGTIME CORE - DO NOT MODIFY
|
|
26
|
-
═══════════════════════════════════════════════════════════════════════════ -->
|
|
27
|
-
|
|
28
|
-
```
|
|
29
|
-
mcp__ragtime__list_memories:
|
|
30
|
-
limit: 100
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
For each namespace:
|
|
34
|
-
```
|
|
35
|
-
mcp__ragtime__list_memories:
|
|
36
|
-
namespace: "{namespace}"
|
|
37
|
-
limit: 50
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
<!-- ═══════════════════════════════════════════════════════════════════════════ -->
|
|
41
|
-
|
|
42
|
-
## Step 2: Identify Issues
|
|
43
|
-
|
|
44
|
-
Group memories by topic and identify:
|
|
45
|
-
|
|
46
|
-
| Issue | Description |
|
|
47
|
-
|-------|-------------|
|
|
48
|
-
| **DUPLICATES** | Memories saying essentially the same thing |
|
|
49
|
-
| **CONFLICTS** | Memories that contradict each other |
|
|
50
|
-
| **STALE** | References to code/features that no longer exist |
|
|
51
|
-
| **ORPHANED** | Branch memories for deleted/merged branches |
|
|
52
|
-
| **LOW_VALUE** | Vague memories that aren't useful |
|
|
53
|
-
|
|
54
|
-
## Step 3: Check for Stale Branches
|
|
55
|
-
|
|
56
|
-
```bash
|
|
57
|
-
# List branch memory folders
|
|
58
|
-
ls -la .claude/memory/branches/
|
|
59
|
-
|
|
60
|
-
# For each, check if branch still exists
|
|
61
|
-
for dir in .claude/memory/branches/*/; do
|
|
62
|
-
branch_slug=$(basename "$dir")
|
|
63
|
-
# Check if branch exists on remote
|
|
64
|
-
if ! git branch -a | grep -q "$branch_slug"; then
|
|
65
|
-
echo "⚠️ Potentially stale: $branch_slug"
|
|
66
|
-
fi
|
|
67
|
-
done
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
Also run:
|
|
71
|
-
```bash
|
|
72
|
-
ragtime prune --dry-run
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
## Step 4: Present Report
|
|
76
|
-
|
|
77
|
-
```
|
|
78
|
-
## Memory Audit Report
|
|
79
|
-
|
|
80
|
-
### App Namespace ({count} memories)
|
|
81
|
-
- Potential duplicates: {n}
|
|
82
|
-
- Potential conflicts: {n}
|
|
83
|
-
- Possibly stale: {n}
|
|
84
|
-
|
|
85
|
-
### Team Namespace ({count} memories)
|
|
86
|
-
- Potential duplicates: {n}
|
|
87
|
-
|
|
88
|
-
### Branch Namespaces
|
|
89
|
-
- Active branches: {n}
|
|
90
|
-
- Stale (unmerged) folders: {n}
|
|
91
|
-
- Ready to prune: {n}
|
|
92
|
-
|
|
93
|
-
───────────────────────────────────────────
|
|
94
|
-
|
|
95
|
-
### Issues Found:
|
|
96
|
-
|
|
97
|
-
**1. Possible Duplicate:**
|
|
98
|
-
- "Auth uses JWT tokens" (app, abc123)
|
|
99
|
-
- "JWT auth with 15-min expiry" (app, def456)
|
|
100
|
-
→ Action: Merge into one?
|
|
101
|
-
|
|
102
|
-
**2. Possible Conflict:**
|
|
103
|
-
- "Use tabs for indentation" (team, ghi789)
|
|
104
|
-
- "Use 2-space indentation" (team, jkl012)
|
|
105
|
-
→ Action: Which is correct?
|
|
106
|
-
|
|
107
|
-
**3. Stale Branch:**
|
|
108
|
-
- branches/old-feature/ (branch deleted)
|
|
109
|
-
→ Action: Prune with `ragtime prune`?
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
## Step 5: Get User Approval
|
|
113
|
-
|
|
114
|
-
For each issue found, ask:
|
|
115
|
-
|
|
116
|
-
- "Should I merge these duplicates?"
|
|
117
|
-
- "Which of these conflicting memories is correct?"
|
|
118
|
-
- "Should I mark this as abandoned?"
|
|
119
|
-
- "Run `ragtime prune` to clean stale branches?"
|
|
120
|
-
|
|
121
|
-
Only make changes the user explicitly approves.
|
|
122
|
-
|
|
123
|
-
## Step 6: Execute Approved Actions
|
|
124
|
-
|
|
125
|
-
<!-- ═══════════════════════════════════════════════════════════════════════════
|
|
126
|
-
RAGTIME CORE - DO NOT MODIFY
|
|
127
|
-
═══════════════════════════════════════════════════════════════════════════ -->
|
|
128
|
-
|
|
129
|
-
**Delete a memory:**
|
|
130
|
-
```
|
|
131
|
-
mcp__ragtime__forget:
|
|
132
|
-
memory_id: "{id}"
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
**Mark as abandoned:**
|
|
136
|
-
```
|
|
137
|
-
mcp__ragtime__update_status:
|
|
138
|
-
memory_id: "{id}"
|
|
139
|
-
status: "abandoned"
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
**Prune stale branches:**
|
|
143
|
-
```bash
|
|
144
|
-
ragtime prune
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
<!-- ═══════════════════════════════════════════════════════════════════════════ -->
|
|
148
|
-
|
|
149
|
-
## Suggested Cadence
|
|
150
|
-
|
|
151
|
-
Run monthly or when memories feel cluttered.
|