dsh-global-todo 0.13.0 → 0.13.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/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ ## [0.13.1] — 2026-10-22
2
+
3
+ The sort orders are total orders now, which is what CI caught.
4
+
5
+ - **Two todos created in the same millisecond could sort in either order.** The comparators
6
+ returned 0 for equal timestamps and leaned on the sort's stability, so a fast machine (the
7
+ packed `npm pack --dry-run` step, where the whole suite runs again) produced a different order
8
+ than the same tests a minute earlier. `seq`, which the service assigns monotonically, is the
9
+ final tiebreaker for all four sorts.
10
+ - **The ordering test uses a stepping clock**, so it asserts the semantics it is named for instead
11
+ of depending on how fast the machine creates three todos; a second test pins the same-millisecond
12
+ case on purpose.
13
+
1
14
  ## [0.13.0] — 2026-10-22
2
15
 
3
16
  Batch capture now scores what it is given, and drops what is not worth a todo.
package/lib/index.js CHANGED
@@ -37,7 +37,7 @@ import { createStore, resolveStorePath } from './store.js'
37
37
  import { createTools } from './tools.js'
38
38
 
39
39
  /** Must equal `package.json`'s version; `npm run check` enforces that. */
40
- export const VERSION = '0.13.0'
40
+ export const VERSION = '0.13.1'
41
41
 
42
42
  /** Plugin id. Also the Loader row id in `cordis.patch.yml`. */
43
43
  export const name = 'dsh-global-todo'
package/lib/service.js CHANGED
@@ -219,20 +219,24 @@ export function createService(options) {
219
219
  if (!SORTS.includes(sort)) {
220
220
  throw new TodoError('invalid-body', `排序只能是 ${SORTS.join(' / ')},收到 ${sort}`)
221
221
  }
222
+ // Every comparator ends on `seq`, which the service assigns monotonically: two todos
223
+ // created in the same millisecond used to tie, and the order then depended on the sort's
224
+ // stability rather than on anything the list guarantees. A CI run caught that.
225
+ const newestFirst = (a, b) => b.createdAt - a.createdAt || (b.seq ?? 0) - (a.seq ?? 0)
222
226
  out = out.slice().sort((a, b) => {
223
- if (sort === 'updated') return b.updatedAt - a.updatedAt
227
+ if (sort === 'updated') return b.updatedAt - a.updatedAt || (b.seq ?? 0) - (a.seq ?? 0)
224
228
  if (sort === 'due') {
225
229
  const left = a.dueAt === null ? Number.POSITIVE_INFINITY : Date.parse(a.dueAt)
226
230
  const right = b.dueAt === null ? Number.POSITIVE_INFINITY : Date.parse(b.dueAt)
227
231
  if (left !== right) return left - right
228
- return b.createdAt - a.createdAt
232
+ return newestFirst(a, b)
229
233
  }
230
234
  if (sort === 'priority') {
231
235
  const rank = PRIORITY_RANK[a.priority] - PRIORITY_RANK[b.priority]
232
236
  if (rank !== 0) return rank
233
- return b.createdAt - a.createdAt
237
+ return newestFirst(a, b)
234
238
  }
235
- return b.createdAt - a.createdAt
239
+ return newestFirst(a, b)
236
240
  })
237
241
 
238
242
  const limit = Number.isInteger(query.limit) && query.limit > 0 ? Math.min(query.limit, 1000) : 200
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-global-todo",
3
- "version": "0.13.0",
3
+ "version": "0.13.1",
4
4
  "icon": "./docs/icon.svg",
5
5
  "description": "Cross-session todo list for DeepSeek Harness: one JSON file a person and an agent both write to, with step plans that ship as a numbered hand-off, session read-back, and a human confirmation before an agent's \"done\" counts.",
6
6
  "type": "module",