delimit-cli 3.13.3 → 3.14.0
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.
- package/bin/delimit-cli.js +139 -1
- package/bin/delimit-setup.js +10 -4
- package/gateway/ai/inbox_daemon.py +623 -0
- package/gateway/ai/ledger_manager.py +88 -19
- package/gateway/ai/notify.py +975 -0
- package/gateway/ai/server.py +3570 -426
- package/gateway/ai/social.py +504 -0
- package/gateway/ai/tool_metadata.py +201 -0
- package/lib/cross-model-hooks.js +173 -43
- package/package.json +1 -1
- package/scripts/crosspost_devto.py +304 -0
|
@@ -147,8 +147,17 @@ def add_item(
|
|
|
147
147
|
source: str = "session",
|
|
148
148
|
project_path: str = ".",
|
|
149
149
|
tags: Optional[List[str]] = None,
|
|
150
|
+
acceptance_criteria: Optional[List[str]] = None,
|
|
151
|
+
context: str = "",
|
|
152
|
+
tools_needed: Optional[List[str]] = None,
|
|
153
|
+
estimated_complexity: str = "",
|
|
150
154
|
) -> Dict[str, Any]:
|
|
151
|
-
"""Add a new item to the project's strategy or operational ledger.
|
|
155
|
+
"""Add a new item to the project's strategy or operational ledger.
|
|
156
|
+
|
|
157
|
+
LED-189: Items can have acceptance_criteria (testable "done when" conditions).
|
|
158
|
+
LED-190: Items can have context, tools_needed, and estimated_complexity
|
|
159
|
+
for agent-executable task format.
|
|
160
|
+
"""
|
|
152
161
|
_ensure(project_path)
|
|
153
162
|
venture = _detect_venture(project_path)
|
|
154
163
|
ledger_dir = _project_ledger_dir(project_path)
|
|
@@ -173,8 +182,26 @@ def add_item(
|
|
|
173
182
|
"status": "open",
|
|
174
183
|
"tags": tags or [],
|
|
175
184
|
}
|
|
185
|
+
# LED-189: Optional acceptance criteria
|
|
186
|
+
if acceptance_criteria:
|
|
187
|
+
entry["acceptance_criteria"] = acceptance_criteria
|
|
188
|
+
# LED-190: Optional agent-executable fields
|
|
189
|
+
if context:
|
|
190
|
+
entry["context"] = context
|
|
191
|
+
if tools_needed:
|
|
192
|
+
entry["tools_needed"] = tools_needed
|
|
193
|
+
if estimated_complexity:
|
|
194
|
+
entry["estimated_complexity"] = estimated_complexity
|
|
176
195
|
|
|
177
196
|
result = _append(path, entry)
|
|
197
|
+
|
|
198
|
+
# Sync to Supabase for dashboard visibility
|
|
199
|
+
try:
|
|
200
|
+
from ai.supabase_sync import sync_ledger_item
|
|
201
|
+
sync_ledger_item(result)
|
|
202
|
+
except Exception:
|
|
203
|
+
pass # Never let cloud sync break ledger operations
|
|
204
|
+
|
|
178
205
|
return {
|
|
179
206
|
"added": result,
|
|
180
207
|
"ledger": ledger,
|
|
@@ -183,6 +210,17 @@ def add_item(
|
|
|
183
210
|
}
|
|
184
211
|
|
|
185
212
|
|
|
213
|
+
def _find_item_in_ledger_dir(item_id: str, ledger_dir: Path) -> Optional[Dict[str, Any]]:
|
|
214
|
+
"""Search a ledger directory for an item by ID. Returns (ledger_name, path) or None."""
|
|
215
|
+
for ledger_name, filename in [("ops", "operations.jsonl"), ("strategy", "strategy.jsonl")]:
|
|
216
|
+
path = ledger_dir / filename
|
|
217
|
+
items = _read_ledger(path)
|
|
218
|
+
for item in items:
|
|
219
|
+
if item.get("id") == item_id and item.get("type") != "update":
|
|
220
|
+
return {"ledger_name": ledger_name, "path": path}
|
|
221
|
+
return None
|
|
222
|
+
|
|
223
|
+
|
|
186
224
|
def update_item(
|
|
187
225
|
item_id: str,
|
|
188
226
|
status: Optional[str] = None,
|
|
@@ -194,24 +232,55 @@ def update_item(
|
|
|
194
232
|
_ensure(project_path)
|
|
195
233
|
ledger_dir = _project_ledger_dir(project_path)
|
|
196
234
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
235
|
+
# First, search the specified project's ledger
|
|
236
|
+
found = _find_item_in_ledger_dir(item_id, ledger_dir)
|
|
237
|
+
|
|
238
|
+
# If not found, search all registered ventures as a fallback
|
|
239
|
+
if not found:
|
|
240
|
+
try:
|
|
241
|
+
ventures = {}
|
|
242
|
+
if VENTURES_FILE.exists():
|
|
243
|
+
ventures = json.loads(VENTURES_FILE.read_text())
|
|
244
|
+
except Exception:
|
|
245
|
+
ventures = {}
|
|
246
|
+
|
|
247
|
+
searched = {str(ledger_dir)}
|
|
248
|
+
for _name, info in ventures.items():
|
|
249
|
+
vpath = info.get("path", "")
|
|
250
|
+
if not vpath:
|
|
251
|
+
continue
|
|
252
|
+
candidate_dir = Path(vpath) / ".delimit" / "ledger"
|
|
253
|
+
if str(candidate_dir) in searched:
|
|
254
|
+
continue
|
|
255
|
+
searched.add(str(candidate_dir))
|
|
256
|
+
found = _find_item_in_ledger_dir(item_id, candidate_dir)
|
|
257
|
+
if found:
|
|
258
|
+
break
|
|
259
|
+
|
|
260
|
+
if found:
|
|
261
|
+
ledger_name = found["ledger_name"]
|
|
262
|
+
path = found["path"]
|
|
263
|
+
update = {
|
|
264
|
+
"id": item_id,
|
|
265
|
+
"type": "update",
|
|
266
|
+
"updated_at": time.strftime("%Y-%m-%dT%H:%M:%SZ"),
|
|
267
|
+
}
|
|
268
|
+
if status:
|
|
269
|
+
update["status"] = status
|
|
270
|
+
if note:
|
|
271
|
+
update["note"] = note
|
|
272
|
+
if priority:
|
|
273
|
+
update["priority"] = priority
|
|
274
|
+
_append(path, update)
|
|
275
|
+
|
|
276
|
+
# Sync to Supabase for dashboard visibility
|
|
277
|
+
try:
|
|
278
|
+
from ai.supabase_sync import sync_ledger_update
|
|
279
|
+
sync_ledger_update(item_id, status=status or "", note=note or "")
|
|
280
|
+
except Exception:
|
|
281
|
+
pass # Never let cloud sync break ledger operations
|
|
282
|
+
|
|
283
|
+
return {"updated": item_id, "changes": update, "ledger": ledger_name}
|
|
215
284
|
|
|
216
285
|
return {"error": f"Item {item_id} not found in project ledger"}
|
|
217
286
|
|