@skitterbyte/skitterspec-linear 8.0.2 → 8.0.4

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skitterbyte/skitterspec-linear",
3
- "version": "8.0.2",
3
+ "version": "8.0.4",
4
4
  "description": "Spec-driven development for Claude Code, with one-way Linear sync — a superset of @skitterbyte/skitterspec: the base filesystem workflow plus /spec-status · /spec-push and the spec-sync CLI. The repo is canonical; Linear is a generated mirror. Install this OR the base, not both.",
5
5
  "keywords": [
6
6
  "claude",
@@ -15,7 +15,8 @@
15
15
  "author": "Reuben Greaves",
16
16
  "type": "commonjs",
17
17
  "bin": {
18
- "skitterspec-linear": "bin/skitterspec-linear.js"
18
+ "skitterspec-linear": "bin/skitterspec-linear.js",
19
+ "skitterspec": "bin/skitterspec-linear.js"
19
20
  },
20
21
  "files": [
21
22
  "bin",
Binary file
@@ -126,11 +126,13 @@ function joinOpenSpans(text) {
126
126
  const c = text[i]
127
127
  if (c === '\n') {
128
128
  if (!code && (bold || italic || link)) {
129
- // Skip the continuation's indentation, then join. A word wrapped at a
130
- // hyphen (`state-entry-with-`⏎`assignment`) is one compound join TIGHT
131
- // (no space) so we don't corrupt it; otherwise a single space.
129
+ // Skip the continuation's indentation AND any blockquote marker (`>`)
130
+ // a span wrapped across two `> …` lines is one quoted run, so the join
131
+ // must drop the continuation `>` rather than swallow it into the text.
132
+ // Then join: a word wrapped at a hyphen (`state-entry-with-`⏎`assignment`)
133
+ // is one compound — join TIGHT (no space); otherwise a single space.
132
134
  let j = i + 1
133
- while (j < text.length && (text[j] === ' ' || text[j] === '\t')) j++
135
+ while (j < text.length && (text[j] === ' ' || text[j] === '\t' || text[j] === '>')) j++
134
136
  const softHyphen = text[i - 1] === '-' && /\w/.test(text[i - 2] || '') && /\w/.test(text[j] || '')
135
137
  if (!softHyphen) out.push(' ')
136
138
  i = j - 1
@@ -19,6 +19,9 @@ const DEFAULT_WIDTH = 80
19
19
  const TASK_START_RE = /^([ \t]*)-\s*\[([ xX])\]\s*(.*)$/
20
20
  const CONTINUATION_RE = /^[ \t]+\S/
21
21
  const BLOCK_BREAK_RE = /^[ \t]*(?:[-*+]\s|\d+\.\s|#{1,6}\s|>|\||```)/
22
+ // A list-marker line (unordered or ordered). Distinguished from other block
23
+ // breaks because a wrapped continuation can legitimately begin with one.
24
+ const LIST_MARKER_RE = /^[ \t]*(?:[-*+]|\d+\.)\s/
22
25
 
23
26
  // Collapse a wrapped bullet's lines into the single logical line the rest of the
24
27
  // sync engine (and Linear) works in.
@@ -82,12 +85,24 @@ function findTaskBlocks(lines) {
82
85
  const m = TASK_START_RE.exec(lines[i])
83
86
  if (!m) continue
84
87
  const parts = [m[3]]
88
+ // The hanging indent: where the bullet's text starts (marker width). A
89
+ // continuation aligns AT this column; a genuine nested bullet is SHALLOWER.
90
+ const hang = lines[i].length - m[3].length
85
91
  let j = i + 1
86
92
  for (; j < lines.length; j++) {
87
93
  const l = lines[j]
88
94
  if (!l.trim()) break
89
95
  if (!CONTINUATION_RE.test(l)) break
90
- if (BLOCK_BREAK_RE.test(l)) break
96
+ if (BLOCK_BREAK_RE.test(l)) {
97
+ // A list-marker line is a real nested/sibling bullet only when indented
98
+ // shallower than the hanging indent. AT/after it, a line beginning with
99
+ // -/*/+/N. is wrapped continuation text, not a new bullet — keep it (else
100
+ // the task is truncated and its stamped id no longer matches, which makes
101
+ // the next push create a duplicate issue). Headings, quotes, tables and
102
+ // fences always break.
103
+ const indent = l.length - l.trimStart().length
104
+ if (!LIST_MARKER_RE.test(l) || indent < hang) break
105
+ }
91
106
  parts.push(l.trim())
92
107
  }
93
108
  blocks.push({