@fanchao8609/agent_brain_sync 1.2.0 → 1.2.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.
- package/package.json +1 -1
- package/src/store.js +3 -2
- package/src/todo.js +19 -4
package/package.json
CHANGED
package/src/store.js
CHANGED
|
@@ -4,7 +4,7 @@ import { promises as fs } from 'node:fs';
|
|
|
4
4
|
import { join, resolve, dirname } from 'node:path';
|
|
5
5
|
import { homedir } from 'node:os';
|
|
6
6
|
import { requireBrain, findBrainRoot, brainPath } from './index.js';
|
|
7
|
-
import { addTask, upsertTask, boardText, readTodo, ensureTodo, todoTemplate, today, localStamp, setBreakpoint, moveBlocked, insertDoneGrouped } from './todo.js';
|
|
7
|
+
import { addTask, upsertTask, boardText, readTodo, ensureTodo, todoTemplate, today, localStamp, setBreakpoint, moveBlocked, insertDoneGrouped, idOfTaskLine } from './todo.js';
|
|
8
8
|
import { editFile, SKIP } from './lock.js';
|
|
9
9
|
import { appendWrapup, strandedFor, wrapupLogPath } from './wrapup.js';
|
|
10
10
|
|
|
@@ -320,9 +320,10 @@ async function markDone(file, id) {
|
|
|
320
320
|
let changed = false;
|
|
321
321
|
let moved = null;
|
|
322
322
|
const kept = [];
|
|
323
|
+
const wantId = String(id).replace(/\u200b/g, '');
|
|
323
324
|
for (let i = 0; i < lines.length; i++) {
|
|
324
325
|
const l = lines[i];
|
|
325
|
-
if (!moved && l
|
|
326
|
+
if (!moved && idOfTaskLine(l) === wantId) {
|
|
326
327
|
changed = true;
|
|
327
328
|
const head = l.replace('- [ ]', '- [x]').replace(/\(认领[^)]*\)/, '') + ` (完成 ${today()})`;
|
|
328
329
|
const bp = [];
|
package/src/todo.js
CHANGED
|
@@ -215,8 +215,8 @@ export async function upsertTask(brainRoot, { section, text }) {
|
|
|
215
215
|
const out = await editFile(p, (orig) => {
|
|
216
216
|
const base = normalizeTodo(orig);
|
|
217
217
|
const lines = base.split('\n');
|
|
218
|
-
//
|
|
219
|
-
const idx = lines
|
|
218
|
+
// 在所有分区中找该 id 对应的未完成任务行(Done 的已完成行不重复动);全等比对
|
|
219
|
+
const idx = findTaskLine(lines, id);
|
|
220
220
|
if (idx !== -1) {
|
|
221
221
|
// 原位更新:保留断点附属行,只换任务行本体
|
|
222
222
|
const oldNote = extractNote(lines[idx].replace(/^- \[ \] /, ''));
|
|
@@ -244,10 +244,25 @@ export function extractNote(text) {
|
|
|
244
244
|
return i === -1 ? '' : String(text).slice(i + 3).replace(/\s*\(认领[^)]*\)\s*$/, '');
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
-
/**
|
|
247
|
+
/**
|
|
248
|
+
* 从任务行取出行首 id token(`- [ ] <id> …` 里的 <id>)。
|
|
249
|
+
* 坑: 不能用 l.includes(id) 定位任务 —— 那是子串匹配,`T1` 会命中 `T11`(同理
|
|
250
|
+
* TASK-1/TASK-10、fix-hook/fix-hook-2),导致 upsert 误判"已存在"而原地改写别的任务、
|
|
251
|
+
* 新任务静默消失。必须取出 id token 做全等比对。
|
|
252
|
+
* id 里可能混入零宽字符(历史瑕疵),比对前先剥掉。
|
|
253
|
+
*/
|
|
254
|
+
export function idOfTaskLine(line) {
|
|
255
|
+
if (!line || !line.startsWith('- [ ]')) return null;
|
|
256
|
+
const m = line.match(/^- \[ \] (\S+)/);
|
|
257
|
+
return m ? m[1].replace(/\u200b/g, '') : null;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/** 定位 id 对应的未完成任务行下标;附属断点行(↳ 开头)不算任务行。
|
|
261
|
+
* 全等比对,不用 includes(否则 T1 会误命中 T11)。 */
|
|
248
262
|
export function findTaskLine(lines, id) {
|
|
249
263
|
if (!id) return -1;
|
|
250
|
-
|
|
264
|
+
const want = String(id).replace(/\u200b/g, '');
|
|
265
|
+
return lines.findIndex((l) => idOfTaskLine(l) === want);
|
|
251
266
|
}
|
|
252
267
|
|
|
253
268
|
/** 实时断点: 在 id 任务行下原位补/换 `↳ 断点:` 附属行(不挪任务位置)。 */
|