@sudocode-ai/cli 0.1.0 → 0.1.2

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.
Files changed (112) hide show
  1. package/dist/cli/feedback-commands.d.ts.map +1 -0
  2. package/dist/cli/feedback-commands.js +274 -0
  3. package/dist/cli/feedback-commands.js.map +1 -0
  4. package/dist/cli/init-commands.d.ts.map +1 -0
  5. package/dist/cli/init-commands.js +148 -0
  6. package/dist/cli/init-commands.js.map +1 -0
  7. package/dist/cli/issue-commands.d.ts.map +1 -0
  8. package/dist/cli/issue-commands.js +310 -0
  9. package/dist/cli/issue-commands.js.map +1 -0
  10. package/dist/cli/query-commands.d.ts.map +1 -0
  11. package/dist/cli/query-commands.js +61 -0
  12. package/dist/cli/query-commands.js.map +1 -0
  13. package/dist/cli/reference-commands.d.ts.map +1 -0
  14. package/dist/cli/reference-commands.js +136 -0
  15. package/dist/cli/reference-commands.js.map +1 -0
  16. package/dist/cli/relationship-commands.d.ts.map +1 -0
  17. package/dist/cli/relationship-commands.js +76 -0
  18. package/dist/cli/relationship-commands.js.map +1 -0
  19. package/dist/cli/server-commands.d.ts.map +1 -0
  20. package/dist/cli/server-commands.js +99 -0
  21. package/dist/cli/server-commands.js.map +1 -0
  22. package/dist/cli/spec-commands.d.ts.map +1 -0
  23. package/dist/cli/spec-commands.js +321 -0
  24. package/dist/cli/spec-commands.js.map +1 -0
  25. package/dist/cli/status-commands.d.ts.map +1 -0
  26. package/dist/cli/status-commands.js +131 -0
  27. package/dist/cli/status-commands.js.map +1 -0
  28. package/dist/cli/sync-commands.d.ts.map +1 -0
  29. package/dist/cli/sync-commands.js +416 -0
  30. package/dist/cli/sync-commands.js.map +1 -0
  31. package/dist/cli/update-commands.d.ts.map +1 -0
  32. package/dist/cli/update-commands.js +78 -0
  33. package/dist/cli/update-commands.js.map +1 -0
  34. package/dist/cli.d.ts.map +1 -0
  35. package/dist/cli.js +425 -195
  36. package/dist/cli.js.map +1 -0
  37. package/dist/db.d.ts.map +1 -0
  38. package/dist/db.js +54 -0
  39. package/dist/db.js.map +1 -0
  40. package/dist/export.d.ts.map +1 -0
  41. package/dist/export.js +195 -0
  42. package/dist/export.js.map +1 -0
  43. package/dist/filename-generator.d.ts.map +1 -0
  44. package/dist/filename-generator.js +93 -0
  45. package/dist/filename-generator.js.map +1 -0
  46. package/dist/id-generator.d.ts.map +1 -0
  47. package/dist/id-generator.js +123 -0
  48. package/dist/id-generator.js.map +1 -0
  49. package/dist/import.d.ts.map +1 -0
  50. package/dist/import.js +608 -0
  51. package/dist/import.js.map +1 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +13 -189
  54. package/dist/index.js.map +1 -0
  55. package/dist/jsonl.d.ts.map +1 -0
  56. package/dist/jsonl.js +333 -0
  57. package/dist/jsonl.js.map +1 -0
  58. package/dist/markdown.d.ts.map +1 -0
  59. package/dist/markdown.js +357 -0
  60. package/dist/markdown.js.map +1 -0
  61. package/dist/migrations.d.ts.map +1 -0
  62. package/dist/migrations.js +57 -0
  63. package/dist/migrations.js.map +1 -0
  64. package/dist/operations/events.d.ts.map +1 -0
  65. package/dist/operations/events.js +108 -0
  66. package/dist/operations/events.js.map +1 -0
  67. package/dist/operations/feedback-anchors.d.ts.map +1 -0
  68. package/dist/operations/feedback-anchors.js +444 -0
  69. package/dist/operations/feedback-anchors.js.map +1 -0
  70. package/dist/operations/feedback.d.ts.map +1 -0
  71. package/dist/operations/feedback.js +234 -0
  72. package/dist/operations/feedback.js.map +1 -0
  73. package/dist/operations/index.d.ts.map +1 -0
  74. package/dist/operations/index.js +10 -0
  75. package/dist/operations/index.js.map +1 -0
  76. package/dist/operations/issues.d.ts.map +1 -0
  77. package/dist/operations/issues.js +411 -0
  78. package/dist/operations/issues.js.map +1 -0
  79. package/dist/operations/references.d.ts.map +1 -0
  80. package/dist/operations/references.js +117 -0
  81. package/dist/operations/references.js.map +1 -0
  82. package/dist/operations/relationships.d.ts.map +1 -0
  83. package/dist/operations/relationships.js +236 -0
  84. package/dist/operations/relationships.js.map +1 -0
  85. package/dist/operations/specs.d.ts.map +1 -0
  86. package/dist/operations/specs.js +290 -0
  87. package/dist/operations/specs.js.map +1 -0
  88. package/dist/operations/tags.d.ts.map +1 -0
  89. package/dist/operations/tags.js +127 -0
  90. package/dist/operations/tags.js.map +1 -0
  91. package/dist/operations/transactions.d.ts.map +1 -0
  92. package/dist/operations/transactions.js +111 -0
  93. package/dist/operations/transactions.js.map +1 -0
  94. package/dist/sync.d.ts.map +1 -0
  95. package/dist/sync.js +442 -0
  96. package/dist/sync.js.map +1 -0
  97. package/dist/test-schema.d.ts.map +1 -0
  98. package/dist/test-schema.js +46 -0
  99. package/dist/test-schema.js.map +1 -0
  100. package/dist/types.d.ts.map +1 -0
  101. package/dist/types.js +7 -0
  102. package/dist/types.js.map +1 -0
  103. package/dist/update-checker.d.ts.map +1 -0
  104. package/dist/update-checker.js +151 -0
  105. package/dist/update-checker.js.map +1 -0
  106. package/dist/version.d.ts.map +1 -0
  107. package/dist/version.js +23 -0
  108. package/dist/version.js.map +1 -0
  109. package/dist/watcher.d.ts.map +1 -0
  110. package/dist/watcher.js +438 -0
  111. package/dist/watcher.js.map +1 -0
  112. package/package.json +4 -7
package/dist/index.js CHANGED
@@ -1,189 +1,13 @@
1
- var Ye=Object.defineProperty;var K=(n,e)=>()=>(n&&(e=n(n=0)),e);var ze=(n,e)=>{for(var t in e)Ye(n,t,{get:e[t],enumerable:!0})};import*as _e from"fs";import*as Z from"path";import{fileURLToPath as Xe}from"url";function nt(){let n=Z.join(tt,"..","package.json");return JSON.parse(_e.readFileSync(n,"utf8")).version}var et,tt,he,ye=K(()=>{"use strict";et=Xe(import.meta.url),tt=Z.dirname(et);he=nt()});import*as C from"fs";import*as se from"path";import*as Ee from"crypto";function be(n,e){let t=ie(e),s=st(n);return`${t.id_prefix.spec}-${String(s).padStart(3,"0")}`}function Se(n,e){let t=ie(e),s=it(n);return`${t.id_prefix.issue}-${String(s).padStart(3,"0")}`}function st(n){let t=n.prepare(`
2
- SELECT id FROM specs
3
- ORDER BY created_at DESC
4
- LIMIT 1
5
- `).get();if(t){let r=t.id.match(/(\d+)$/);if(r)return parseInt(r[1],10)+1}return n.prepare("SELECT COUNT(*) as count FROM specs").get().count+1}function it(n){let t=n.prepare(`
6
- SELECT id FROM issues
7
- ORDER BY created_at DESC
8
- LIMIT 1
9
- `).get();if(t){let r=t.id.match(/(\d+)$/);if(r)return parseInt(r[1],10)+1}return n.prepare("SELECT COUNT(*) as count FROM issues").get().count+1}function ie(n){let e=se.join(n,"config.json");if(!C.existsSync(e)){let s={version:he,id_prefix:{spec:"SPEC",issue:"ISSUE"}};return rt(n,s),s}let t=C.readFileSync(e,"utf8");return JSON.parse(t)}function rt(n,e){let t=se.join(n,"config.json");C.writeFileSync(t,JSON.stringify(e,null,2),"utf8")}function De(n){return ie(n)}function G(){return Ee.randomUUID()}var B=K(()=>{"use strict";ye()});var re={};ze(re,{addRelationship:()=>I,getAllRelationships:()=>lt,getDependencies:()=>ut,getDependents:()=>pt,getIncomingRelationships:()=>H,getOutgoingRelationships:()=>k,getRelationship:()=>ee,relationshipExists:()=>ft,removeAllRelationships:()=>A,removeRelationship:()=>ot});function I(n,e){let t=e.from_type==="spec"?"specs":"issues",s=n.prepare(`SELECT id, uuid FROM ${t} WHERE id = ?`).get(e.from_id);if(!s)throw new Error(`${e.from_type==="spec"?"Spec":"Issue"} not found: ${e.from_id}`);let i=e.to_type==="spec"?"specs":"issues",r=n.prepare(`SELECT id, uuid FROM ${i} WHERE id = ?`).get(e.to_id);if(!r)throw new Error(`${e.to_type==="spec"?"Spec":"Issue"} not found: ${e.to_id}`);let c=ee(n,e.from_id,e.from_type,e.to_id,e.to_type,e.relationship_type);if(c)return c;let o=n.prepare(`
10
- INSERT INTO relationships (
11
- from_id, from_uuid, from_type, to_id, to_uuid, to_type, relationship_type, metadata
12
- ) VALUES (
13
- @from_id, @from_uuid, @from_type, @to_id, @to_uuid, @to_type, @relationship_type, @metadata
14
- )
15
- `);try{o.run({from_id:e.from_id,from_uuid:s.uuid,from_type:e.from_type,to_id:e.to_id,to_uuid:r.uuid,to_type:e.to_type,relationship_type:e.relationship_type,metadata:e.metadata??null});let d=ee(n,e.from_id,e.from_type,e.to_id,e.to_type,e.relationship_type);if(!d)throw new Error("Failed to create relationship");return e.relationship_type==="blocks"&&e.from_type==="issue"&&e.to_type==="issue"&&at(n,e.from_id,e.to_id),d}catch(d){throw d.code&&d.code.startsWith("SQLITE_CONSTRAINT")?new Error(`Relationship already exists: ${e.from_id} (${e.from_type}) --[${e.relationship_type}]--> ${e.to_id} (${e.to_type})`):d}}function at(n,e,t){let s=E(n,t);if(s&&s.status!=="closed"){let i=E(n,e);i&&(i.status==="open"||i.status==="in_progress")&&n.prepare(`
16
- UPDATE issues
17
- SET status = 'blocked', updated_at = CURRENT_TIMESTAMP
18
- WHERE id = ?
19
- `).run(e)}}function ee(n,e,t,s,i,r){return n.prepare(`
20
- SELECT * FROM relationships
21
- WHERE from_id = ? AND from_type = ?
22
- AND to_id = ? AND to_type = ?
23
- AND relationship_type = ?
24
- `).get(e,t,s,i,r)??null}function ot(n,e,t,s,i,r){let d=n.prepare(`
25
- DELETE FROM relationships
26
- WHERE from_id = ? AND from_type = ?
27
- AND to_id = ? AND to_type = ?
28
- AND relationship_type = ?
29
- `).run(e,t,s,i,r).changes>0;return d&&r==="blocks"&&t==="issue"&&i==="issue"&&ct(n,e),d}function ct(n,e){let t=E(n,e);t&&t.status==="blocked"&&(dt(n,e)||n.prepare(`
30
- UPDATE issues
31
- SET status = 'open', updated_at = CURRENT_TIMESTAMP
32
- WHERE id = ?
33
- `).run(e))}function dt(n,e){return n.prepare(`
34
- SELECT COUNT(*) as count
35
- FROM relationships r
36
- JOIN issues blocker ON r.to_id = blocker.id AND r.to_type = 'issue'
37
- WHERE r.from_id = ?
38
- AND r.from_type = 'issue'
39
- AND r.relationship_type = 'blocks'
40
- AND blocker.status IN ('open', 'in_progress', 'blocked')
41
- `).get(e).count>0}function k(n,e,t,s){let i=`
42
- SELECT * FROM relationships
43
- WHERE from_id = @entity_id AND from_type = @entity_type
44
- `,r={entity_id:e,entity_type:t};return s!==void 0&&(i+=" AND relationship_type = @relationship_type",r.relationship_type=s),i+=" ORDER BY created_at DESC",n.prepare(i).all(r)}function H(n,e,t,s){let i=`
45
- SELECT * FROM relationships
46
- WHERE to_id = @entity_id AND to_type = @entity_type
47
- `,r={entity_id:e,entity_type:t};return s!==void 0&&(i+=" AND relationship_type = @relationship_type",r.relationship_type=s),i+=" ORDER BY created_at DESC",n.prepare(i).all(r)}function ut(n,e,t){return k(n,e,t,"blocks")}function pt(n,e,t){return H(n,e,t,"blocks")}function lt(n,e,t){return{outgoing:k(n,e,t),incoming:H(n,e,t)}}function ft(n,e,t,s,i,r){return ee(n,e,t,s,i,r)!==null}function A(n,e,t){return n.prepare(`
48
- DELETE FROM relationships
49
- WHERE (from_id = ? AND from_type = ?)
50
- OR (to_id = ? AND to_type = ?)
51
- `).run(e,t,e,t).changes}var v=K(()=>{"use strict";w()});function te(n,e){let t=null;if(e.parent_id){let o=E(n,e.parent_id);if(!o)throw new Error(`Parent issue not found: ${e.parent_id}`);t=o.uuid}let s=e.uuid||G(),i=["id","uuid","title","content","status","priority","assignee","parent_id","parent_uuid","archived"],r=["@id","@uuid","@title","@content","@status","@priority","@assignee","@parent_id","@parent_uuid","@archived"];e.created_at&&(i.push("created_at"),r.push("@created_at")),e.updated_at&&(i.push("updated_at"),r.push("@updated_at")),e.closed_at!==void 0&&(i.push("closed_at"),r.push("@closed_at")),e.archived_at!==void 0&&(i.push("archived_at"),r.push("@archived_at"));let c=n.prepare(`
52
- INSERT INTO issues (
53
- ${i.join(", ")}
54
- ) VALUES (
55
- ${r.join(", ")}
56
- )
57
- ON CONFLICT(id) DO UPDATE SET
58
- uuid = excluded.uuid,
59
- title = excluded.title,
60
- content = excluded.content,
61
- status = excluded.status,
62
- priority = excluded.priority,
63
- assignee = excluded.assignee,
64
- parent_id = excluded.parent_id,
65
- parent_uuid = excluded.parent_uuid,
66
- archived = excluded.archived,
67
- archived_at = excluded.archived_at,
68
- ${e.created_at?"created_at = excluded.created_at,":""}
69
- ${e.updated_at?"updated_at = excluded.updated_at":"updated_at = CURRENT_TIMESTAMP"}
70
- `);try{let o={id:e.id,uuid:s,title:e.title,content:e.content||"",status:e.status||"open",priority:e.priority??2,assignee:e.assignee??null,parent_id:e.parent_id??null,parent_uuid:t,archived:e.archived?1:0};e.created_at&&(o.created_at=e.created_at),e.updated_at&&(o.updated_at=e.updated_at),e.closed_at!==void 0&&(o.closed_at=e.closed_at),e.archived_at!==void 0&&(o.archived_at=e.archived_at),c.run(o);let d=E(n,e.id);if(!d)throw new Error(`Failed to create issue ${e.id}`);return d}catch(o){throw o.code&&o.code.startsWith("SQLITE_CONSTRAINT")?new Error(`Constraint violation: ${o.message}`):o}}function E(n,e){return n.prepare(`
71
- SELECT * FROM issues WHERE id = ?
72
- `).get(e)??null}function L(n,e,t){let s=E(n,e);if(!s)throw new Error(`Issue not found: ${e}`);if(t.parent_id&&!E(n,t.parent_id))throw new Error(`Parent issue not found: ${t.parent_id}`);let i=[],r={id:e};if(t.title!==void 0&&t.title!==s.title&&(i.push("title = @title"),r.title=t.title),t.content!==void 0&&t.content!==s.content&&(i.push("content = @content"),r.content=t.content),t.status!==void 0&&t.status!==s.status?(i.push("status = @status"),r.status=t.status,t.closed_at!==void 0?(i.push("closed_at = @closed_at"),r.closed_at=t.closed_at):t.status==="closed"&&s.status!=="closed"?i.push("closed_at = CURRENT_TIMESTAMP"):t.status!=="closed"&&s.status==="closed"&&i.push("closed_at = NULL")):t.closed_at!==void 0&&t.closed_at!==s.closed_at&&(i.push("closed_at = @closed_at"),r.closed_at=t.closed_at),t.priority!==void 0&&t.priority!==s.priority&&(i.push("priority = @priority"),r.priority=t.priority),t.assignee!==void 0&&t.assignee!==s.assignee&&(i.push("assignee = @assignee"),r.assignee=t.assignee),t.parent_id!==void 0&&t.parent_id!==s.parent_id&&(i.push("parent_id = @parent_id"),r.parent_id=t.parent_id),t.archived!==void 0&&(t.archived?1:0)!==s.archived?(i.push("archived = @archived"),r.archived=t.archived?1:0,t.archived_at!==void 0?(i.push("archived_at = @archived_at"),r.archived_at=t.archived_at):t.archived&&!s.archived?i.push("archived_at = CURRENT_TIMESTAMP"):!t.archived&&s.archived&&i.push("archived_at = NULL")):t.archived_at!==void 0&&t.archived_at!==s.archived_at&&(i.push("archived_at = @archived_at"),r.archived_at=t.archived_at),t.updated_at!==void 0?(i.push("updated_at = @updated_at"),r.updated_at=t.updated_at):i.length>0&&i.push("updated_at = CURRENT_TIMESTAMP"),i.length===0)return s;let c=n.prepare(`
73
- UPDATE issues SET ${i.join(", ")} WHERE id = @id
74
- `);try{c.run(r);let o=E(n,e);if(!o)throw new Error(`Failed to update issue ${e}`);return t.status==="closed"&&s.status!=="closed"&&gt(n,e),o}catch(o){throw o.code&&o.code.startsWith("SQLITE_CONSTRAINT")?new Error(`Constraint violation: ${o.message}`):o}}function gt(n,e){let t=H(n,e,"issue","blocks");for(let s of t){let i=s.from_id,r=E(n,i);if(!r||r.status!=="blocked")continue;mt(n,i,e)||n.prepare(`
75
- UPDATE issues
76
- SET status = 'open', updated_at = CURRENT_TIMESTAMP
77
- WHERE id = ?
78
- `).run(i)}}function mt(n,e,t){let s=n.prepare(`
79
- SELECT COUNT(*) as count
80
- FROM relationships r
81
- JOIN issues blocker ON r.to_id = blocker.id AND r.to_type = 'issue'
82
- WHERE r.from_id = ?
83
- AND r.from_type = 'issue'
84
- AND r.relationship_type = 'blocks'
85
- AND blocker.status IN ('open', 'in_progress', 'blocked')
86
- ${t?"AND blocker.id != ?":""}
87
- `),i=t?[e,t]:[e];return s.get(...i).count>0}function Ie(n,e){return n.prepare("DELETE FROM issues WHERE id = ?").run(e).changes>0}function gn(n,e){return L(n,e,{status:"closed"})}function mn(n,e){return L(n,e,{status:"open"})}function $(n,e={}){let t=[],s={};e.status!==void 0&&(t.push("status = @status"),s.status=e.status),e.priority!==void 0&&(t.push("priority = @priority"),s.priority=e.priority),e.assignee!==void 0&&(t.push("assignee = @assignee"),s.assignee=e.assignee),e.parent_id!==void 0&&(t.push("parent_id = @parent_id"),s.parent_id=e.parent_id),e.archived!==void 0&&(t.push("archived = @archived"),s.archived=e.archived?1:0);let i="SELECT * FROM issues";return t.length>0&&(i+=" WHERE "+t.join(" AND ")),i+=" ORDER BY priority DESC, created_at DESC",e.limit!==void 0&&(i+=" LIMIT @limit",s.limit=e.limit),e.offset!==void 0&&(i+=" OFFSET @offset",s.offset=e.offset),n.prepare(i).all(s)}function _n(n){return n.prepare("SELECT * FROM ready_issues ORDER BY priority DESC, created_at DESC").all()}function hn(n){return n.prepare("SELECT * FROM blocked_issues ORDER BY priority DESC, created_at DESC").all()}function yn(n,e,t={}){let s=["(title LIKE @query OR content LIKE @query)"],i={query:`%${e}%`};t.status!==void 0&&(s.push("status = @status"),i.status=t.status),t.priority!==void 0&&(s.push("priority = @priority"),i.priority=t.priority),t.assignee!==void 0&&(s.push("assignee = @assignee"),i.assignee=t.assignee),t.parent_id!==void 0&&(s.push("parent_id = @parent_id"),i.parent_id=t.parent_id),t.archived!==void 0&&(s.push("archived = @archived"),i.archived=t.archived?1:0);let r=`SELECT * FROM issues WHERE ${s.join(" AND ")} ORDER BY priority DESC, created_at DESC`;return t.limit!==void 0?(r+=" LIMIT @limit",i.limit=t.limit):r+=" LIMIT 50",n.prepare(r).all(i)}var w=K(()=>{"use strict";B();v()});export*from"@sudocode-ai/types";import Ze from"better-sqlite3";import*as R from"@sudocode-ai/types/schema";var Ve=[];function Qe(n){return n.exec(`
88
- CREATE TABLE IF NOT EXISTS migrations (
89
- version INTEGER PRIMARY KEY,
90
- name TEXT NOT NULL,
91
- applied_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
92
- )
93
- `),n.prepare("SELECT MAX(version) as version FROM migrations").get().version??0}function Ke(n,e){n.prepare(`
94
- INSERT OR REPLACE INTO migrations (version, name)
95
- VALUES (?, ?)
96
- `).run(e.version,e.name)}function me(n){let e=Qe(n),t=Ve.filter(s=>s.version>e);if(t.length!==0){console.log(`Running ${t.length} pending migration(s)...`);for(let s of t){console.log(` Applying migration ${s.version}: ${s.name}`);try{s.up(n),Ke(n,s),console.log(` \u2713 Migration ${s.version} applied successfully`)}catch(i){throw console.error(` \u2717 Migration ${s.version} failed:`,i),i}}}}function Ge(n){let e=new Ze(n.path,{verbose:n.verbose?console.log:void 0});e.exec(R.DB_CONFIG);for(let t of R.ALL_TABLES)e.exec(t);for(let t of R.ALL_INDEXES)e.exec(t);for(let t of R.ALL_VIEWS)e.exec(t);return me(e),e}function en(n){return Ge({path:n})}function tn(n,e){let t=`sp_${Date.now()}`;try{n.exec(`SAVEPOINT ${t}`);let s=e(n);return n.exec(`RELEASE ${t}`),s}catch(s){throw n.exec(`ROLLBACK TO ${t}`),s}}B();function X(n,e){let t=null;if(e.parent_id){let o=T(n,e.parent_id);if(!o)throw new Error(`Parent spec not found: ${e.parent_id}`);t=o.uuid}let s=e.uuid||G(),i=["id","uuid","title","file_path","content","priority","parent_id","parent_uuid","archived"],r=["@id","@uuid","@title","@file_path","@content","@priority","@parent_id","@parent_uuid","@archived"];e.created_at&&(i.push("created_at"),r.push("@created_at")),e.updated_at&&(i.push("updated_at"),r.push("@updated_at")),e.archived_at!==void 0&&(i.push("archived_at"),r.push("@archived_at"));let c=n.prepare(`
97
- INSERT INTO specs (
98
- ${i.join(", ")}
99
- ) VALUES (
100
- ${r.join(", ")}
101
- )
102
- ON CONFLICT(id) DO UPDATE SET
103
- uuid = excluded.uuid,
104
- title = excluded.title,
105
- file_path = excluded.file_path,
106
- content = excluded.content,
107
- priority = excluded.priority,
108
- parent_id = excluded.parent_id,
109
- parent_uuid = excluded.parent_uuid,
110
- archived = excluded.archived,
111
- archived_at = excluded.archived_at,
112
- ${e.created_at?"created_at = excluded.created_at,":""}
113
- ${e.updated_at?"updated_at = excluded.updated_at":"updated_at = CURRENT_TIMESTAMP"}
114
- `);try{let o={id:e.id,uuid:s,title:e.title,file_path:e.file_path,content:e.content||"",priority:e.priority??2,parent_id:e.parent_id??null,parent_uuid:t,archived:e.archived?1:0};e.created_at&&(o.created_at=e.created_at),e.updated_at&&(o.updated_at=e.updated_at),e.archived_at!==void 0&&(o.archived_at=e.archived_at),c.run(o);let d=T(n,e.id);if(!d)throw new Error(`Failed to create spec ${e.id}`);return d}catch(o){throw o.code&&o.code.startsWith("SQLITE_CONSTRAINT")?new Error(`Constraint violation: ${o.message}`):o}}function T(n,e){return n.prepare(`
115
- SELECT * FROM specs WHERE id = ?
116
- `).get(e)??null}function xe(n,e){return n.prepare(`
117
- SELECT * FROM specs WHERE file_path = ?
118
- `).get(e)??null}function P(n,e,t){let s=T(n,e);if(!s)throw new Error(`Spec not found: ${e}`);if(t.parent_id&&!T(n,t.parent_id))throw new Error(`Parent spec not found: ${t.parent_id}`);let i=[],r={id:e};if(t.title!==void 0&&t.title!==s.title&&(i.push("title = @title"),r.title=t.title),t.file_path!==void 0&&t.file_path!==s.file_path&&(i.push("file_path = @file_path"),r.file_path=t.file_path),t.content!==void 0&&t.content!==s.content&&(i.push("content = @content"),r.content=t.content),t.priority!==void 0&&t.priority!==s.priority&&(i.push("priority = @priority"),r.priority=t.priority),t.parent_id!==void 0&&t.parent_id!==s.parent_id&&(i.push("parent_id = @parent_id"),r.parent_id=t.parent_id),t.archived!==void 0&&t.archived!==s.archived?(i.push("archived = @archived"),r.archived=t.archived?1:0,t.archived_at!==void 0?(i.push("archived_at = @archived_at"),r.archived_at=t.archived_at):t.archived&&!s.archived?i.push("archived_at = CURRENT_TIMESTAMP"):!t.archived&&s.archived&&i.push("archived_at = NULL")):t.archived_at!==void 0&&t.archived_at!==s.archived_at&&(i.push("archived_at = @archived_at"),r.archived_at=t.archived_at),t.updated_at!==void 0?(i.push("updated_at = @updated_at"),r.updated_at=t.updated_at):i.length>0&&i.push("updated_at = CURRENT_TIMESTAMP"),i.length===0)return s;let c=n.prepare(`
119
- UPDATE specs SET ${i.join(", ")} WHERE id = @id
120
- `);try{c.run(r);let o=T(n,e);if(!o)throw new Error(`Failed to update spec ${e}`);return o}catch(o){throw o.code&&o.code.startsWith("SQLITE_CONSTRAINT")?new Error(`Constraint violation: ${o.message}`):o}}function Te(n,e){return n.prepare("DELETE FROM specs WHERE id = ?").run(e).changes>0}function F(n,e={}){let t=[],s={};e.priority!==void 0&&(t.push("priority = @priority"),s.priority=e.priority),e.parent_id!==void 0&&(t.push("parent_id = @parent_id"),s.parent_id=e.parent_id),e.archived!==void 0&&(t.push("archived = @archived"),s.archived=e.archived?1:0);let i="SELECT * FROM specs";return t.length>0&&(i+=" WHERE "+t.join(" AND ")),i+=" ORDER BY priority DESC, created_at DESC",e.limit!==void 0&&(i+=" LIMIT @limit",s.limit=e.limit),e.offset!==void 0&&(i+=" OFFSET @offset",s.offset=e.offset),n.prepare(i).all(s)}function dn(n,e,t={}){let s=["(title LIKE @query OR content LIKE @query)"],i={query:`%${e}%`};t.priority!==void 0&&(s.push("priority = @priority"),i.priority=t.priority),t.parent_id!==void 0&&(s.push("parent_id = @parent_id"),i.parent_id=t.parent_id),t.archived!==void 0&&(s.push("archived = @archived"),i.archived=t.archived?1:0);let r=`SELECT * FROM specs WHERE ${s.join(" AND ")} ORDER BY priority DESC, created_at DESC`;return t.limit!==void 0?(r+=" LIMIT @limit",i.limit=t.limit):r+=" LIMIT 50",n.prepare(r).all(i)}w();v();function _t(n,e,t,s){let i=t==="spec"?"specs":"issues",r=n.prepare(`SELECT uuid FROM ${i} WHERE id = ?`).get(e);if(!r)throw new Error(`${t==="spec"?"Spec":"Issue"} not found: ${e}`);let c=n.prepare(`
121
- INSERT INTO tags (entity_id, entity_uuid, entity_type, tag)
122
- VALUES (@entity_id, @entity_uuid, @entity_type, @tag)
123
- `);try{return c.run({entity_id:e,entity_uuid:r.uuid,entity_type:t,tag:s}),{entity_id:e,entity_uuid:r.uuid,entity_type:t,tag:s}}catch(o){if(o.code&&o.code.startsWith("SQLITE_CONSTRAINT"))return{entity_id:e,entity_uuid:r.uuid,entity_type:t,tag:s};throw o}}function ht(n,e,t,s){let i=[];for(let r of s)i.push(_t(n,e,t,r));return i}function bn(n,e,t,s){return n.prepare(`
124
- DELETE FROM tags
125
- WHERE entity_id = ? AND entity_type = ? AND tag = ?
126
- `).run(e,t,s).changes>0}function q(n,e,t){return n.prepare(`
127
- SELECT tag FROM tags
128
- WHERE entity_id = ? AND entity_type = ?
129
- ORDER BY tag
130
- `).all(e,t).map(r=>r.tag)}function Sn(n,e,t){let s="SELECT * FROM tags WHERE tag = @tag",i={tag:e};return t!==void 0&&(s+=" AND entity_type = @entity_type",i.entity_type=t),s+=" ORDER BY entity_id",n.prepare(s).all(i)}function yt(n,e,t){return n.prepare(`
131
- DELETE FROM tags
132
- WHERE entity_id = ? AND entity_type = ?
133
- `).run(e,t).changes}function Dn(n,e,t,s){return n.prepare(`
134
- SELECT 1 FROM tags
135
- WHERE entity_id = ? AND entity_type = ? AND tag = ?
136
- `).get(e,t,s)!==void 0}function xn(n,e){let t="SELECT DISTINCT tag FROM tags",s={};return e!==void 0&&(t+=" WHERE entity_type = @entity_type",s.entity_type=e),t+=" ORDER BY tag",n.prepare(t).all(s).map(c=>c.tag)}function O(n,e,t,s){return yt(n,e,t),s.length>0&&ht(n,e,t,s),s}function In(n,e){let s=n.prepare(`
137
- INSERT INTO events (
138
- entity_id, entity_type, event_type, actor,
139
- old_value, new_value, comment, git_commit_sha, source
140
- ) VALUES (
141
- @entity_id, @entity_type, @event_type, @actor,
142
- @old_value, @new_value, @comment, @git_commit_sha, @source
143
- )
144
- `).run({entity_id:e.entity_id,entity_type:e.entity_type,event_type:e.event_type,actor:e.actor,old_value:e.old_value||null,new_value:e.new_value||null,comment:e.comment||null,git_commit_sha:e.git_commit_sha||null,source:e.source||null}),i=Et(n,Number(s.lastInsertRowid));if(!i)throw new Error("Failed to create event");return i}function Et(n,e){return n.prepare("SELECT * FROM events WHERE id = ?").get(e)??null}function ae(n,e={}){let t=[],s={};e.entity_id!==void 0&&(t.push("entity_id = @entity_id"),s.entity_id=e.entity_id),e.entity_type!==void 0&&(t.push("entity_type = @entity_type"),s.entity_type=e.entity_type),e.event_type!==void 0&&(t.push("event_type = @event_type"),s.event_type=e.event_type),e.actor!==void 0&&(t.push("actor = @actor"),s.actor=e.actor);let i="SELECT * FROM events";return t.length>0&&(i+=" WHERE "+t.join(" AND ")),i+=" ORDER BY created_at DESC",e.limit!==void 0&&(i+=" LIMIT @limit",s.limit=e.limit),e.offset!==void 0&&(i+=" OFFSET @offset",s.offset=e.offset),n.prepare(i).all(s)}function Rn(n,e,t,s){return ae(n,{entity_id:e,entity_type:t,limit:s})}function vn(n,e=50){return ae(n,{limit:e})}function On(n,e,t){return ae(n,{actor:e,limit:t})}function wn(n,e,t){return n.prepare(`
145
- DELETE FROM events
146
- WHERE entity_id = ? AND entity_type = ?
147
- `).run(e,t).changes}function bt(n,e,t){let s=`[[${n}`;return e&&(s+=`|${e}`),s+="]]",t&&(s+=`{ ${t} }`),s}function St(n,e){let t=n.split(`
148
- `);if(e<1||e>t.length)throw new Error(`Line number ${e} is out of bounds (content has ${t.length} lines)`);let s=0;for(let i=0;i<e-1;i++)s+=t[i].length+1;return s}function Dt(n,e){let t=n.indexOf(e);if(t===-1)throw new Error(`Text not found: "${e}"`);return t}function Nn(n,e,t){let{referenceId:s,displayText:i,relationshipType:r,format:c="inline",position:o="after"}=t;if(!e.line&&!e.text)throw new Error("Either line or text must be specified");if(e.line&&e.text)throw new Error("Cannot specify both line and text");let d=bt(s,i,r),a;if(e.line){if(a=St(n,e.line),o==="after"){let f=n.indexOf(`
149
- `,a);a=f===-1?n.length:f}}else if(e.text)a=Dt(n,e.text),o==="after"&&(a+=e.text.length);else throw new Error("Location must specify line or text");let u;return c==="newline"?o==="before"?u=`${d}
150
- `:u=`
151
- ${d}`:o==="before"?u=`${d} `:u=` ${d}`,n.slice(0,a)+u+n.slice(a)}function oe(n,e){return n.inTransaction?e(n):n.transaction(e)(n)}function Wn(n,e){return oe(n,()=>{let t=[];for(let s of e)t.push(s());return t})}function jn(n,e,t=3,s=100){let i=null;for(let r=0;r<=t;r++)try{return e(n)}catch(c){if(i=c,(c.code==="SQLITE_BUSY"||c.code==="SQLITE_LOCKED")&&r<t){let o=s*Math.pow(2,r);new Promise(a=>setTimeout(a,o)).then(()=>{});continue}throw c}throw i||new Error("Transaction failed after retries")}var Re=class n{constructor(e,t){this.db=e;this.savepointId=t||`sp_${Date.now()}_${Math.random().toString().replace(".","")}`,this.db.prepare(`SAVEPOINT ${this.savepointId}`).run()}savepointId;released=!1;commit(){if(this.released)throw new Error("Savepoint already released");this.db.prepare(`RELEASE ${this.savepointId}`).run(),this.released=!0}rollback(){if(this.released)throw new Error("Savepoint already released");this.db.prepare(`ROLLBACK TO ${this.savepointId}`).run(),this.db.prepare(`RELEASE ${this.savepointId}`).run(),this.released=!0}static execute(e,t){let s=new n(e);try{let i=t(s);return s.released||s.commit(),i}catch(i){throw s.released||s.rollback(),i}}};import*as h from"fs";import*as ve from"readline";import*as ce from"path";async function M(n,e={}){let{skipErrors:t=!1,onError:s}=e;if(!h.existsSync(n))return[];let i=[],r=h.createReadStream(n,{encoding:"utf8"}),c=ve.createInterface({input:r,crlfDelay:1/0}),o=0;for await(let d of c)if(o++,d.trim()!=="")try{let a=JSON.parse(d);i.push(a)}catch(a){let u=a;if(s&&s(o,d,u),!t)throw new Error(`Failed to parse JSON at line ${o}: ${u.message}`)}return i}function de(n,e={}){let{skipErrors:t=!1,onError:s}=e;if(!h.existsSync(n))return[];let i=[],c=h.readFileSync(n,"utf8").split(`
152
- `);for(let o=0;o<c.length;o++){let d=c[o].trim(),a=o+1;if(d!=="")try{let u=JSON.parse(d);i.push(u)}catch(u){let p=u;if(s&&s(a,d,p),!t)throw new Error(`Failed to parse JSON at line ${a}: ${p.message}`)}}return i}async function Y(n,e,t={}){let{atomic:s=!0}=t,i=ce.dirname(n);h.existsSync(i)||h.mkdirSync(i,{recursive:!0});let r=s?`${n}.tmp`:n,c=[...e].sort((a,u)=>{let p=a.created_at,f=u.created_at;if(!p&&!f){let b=a.id||"",y=u.id||"";return b<y?-1:b>y?1:0}if(!p)return 1;if(!f||p<f)return-1;if(p>f)return 1;let g=a.id||"",S=u.id||"";return g<S?-1:g>S?1:0}),d=c.map(a=>JSON.stringify(a)).join(`
153
- `)+`
154
- `;if(!(h.existsSync(n)&&h.readFileSync(n,"utf8")===d)&&(h.writeFileSync(r,d,"utf8"),s&&h.renameSync(r,n),c.length>0)){let a=c.map(u=>u.updated_at).filter(u=>u!=null).map(u=>{let p=String(u),g=p.endsWith("Z")||p.includes("+")||/[+-]\d{2}:\d{2}$/.test(p)?p:p.replace(" ","T")+"Z";return new Date(g).getTime()});if(a.length>0){let u=Math.max(...a),p=new Date(u);h.utimesSync(n,p,p)}}}function Oe(n,e,t={}){let{atomic:s=!0}=t,i=ce.dirname(n);h.existsSync(i)||h.mkdirSync(i,{recursive:!0});let r=s?`${n}.tmp`:n,c=[...e].sort((a,u)=>{let p=a.created_at,f=u.created_at;if(!p&&!f){let b=a.id||"",y=u.id||"";return b<y?-1:b>y?1:0}if(!p)return 1;if(!f||p<f)return-1;if(p>f)return 1;let g=a.id||"",S=u.id||"";return g<S?-1:g>S?1:0}),d=c.map(a=>JSON.stringify(a)).join(`
155
- `)+`
156
- `;if(!(h.existsSync(n)&&h.readFileSync(n,"utf8")===d)&&(h.writeFileSync(r,d,"utf8"),s&&h.renameSync(r,n),c.length>0)){let a=c.map(u=>u.updated_at).filter(u=>u!=null).map(u=>{let p=String(u),g=p.endsWith("Z")||p.includes("+")||/[+-]\d{2}:\d{2}$/.test(p)?p:p.replace(" ","T")+"Z";return new Date(g).getTime()});if(a.length>0){let u=Math.max(...a),p=new Date(u);h.utimesSync(n,p,p)}}}async function Pn(n,e,t="id"){let s=e[t];if(!s)throw new Error(`Entity missing ${t} field`);let i=await M(n,{skipErrors:!0}),r=i.findIndex(c=>c[t]===s);r>=0?i[r]=e:i.push(e),await Y(n,i)}function Hn(n,e,t="id"){let s=e[t];if(!s)throw new Error(`Entity missing ${t} field`);let i=de(n,{skipErrors:!0}),r=i.findIndex(c=>c[t]===s);r>=0?i[r]=e:i.push(e),Oe(n,i)}async function qn(n,e,t="id"){let s=await M(n,{skipErrors:!0}),i=s.length,r=s.filter(c=>c[t]!==e);return r.length===i?!1:(await Y(n,r),!0)}function Yn(n,e,t="id"){let s=de(n,{skipErrors:!0}),i=s.length,r=s.filter(c=>c[t]!==e);return r.length===i?!1:(Oe(n,r),!0)}async function zn(n,e,t="id"){return(await M(n,{skipErrors:!0})).find(i=>i[t]===e)??null}function Vn(n,e,t="id"){return de(n,{skipErrors:!0}).find(i=>i[t]===e)??null}w();v();function we(n){return{...n,dismissed:n.dismissed===1}}function xt(n){let t=n.prepare(`
157
- SELECT id FROM issue_feedback ORDER BY id DESC LIMIT 1
158
- `).get();if(!t)return"FB-001";let s=t.id.match(/^FB-(\d+)$/);if(!s)return"FB-001";let i=parseInt(s[1],10)+1;return`FB-${String(i).padStart(3,"0")}`}function Le(n,e){let t=e.id||xt(n),s=e.anchor?JSON.stringify(e.anchor):null,i=e.agent||"user",r=n.prepare("SELECT uuid FROM issues WHERE id = ?").get(e.issue_id);if(!r)throw new Error(`Issue not found: ${e.issue_id}`);let c=n.prepare("SELECT uuid FROM specs WHERE id = ?").get(e.spec_id);if(!c)throw new Error(`Spec not found: ${e.spec_id}`);let o=n.prepare(`
159
- INSERT INTO issue_feedback (
160
- id, issue_id, issue_uuid, spec_id, spec_uuid, feedback_type, content, agent, anchor, dismissed
161
- ) VALUES (
162
- @id, @issue_id, @issue_uuid, @spec_id, @spec_uuid, @feedback_type, @content, @agent, @anchor, @dismissed
163
- )
164
- `);try{o.run({id:t,issue_id:e.issue_id,issue_uuid:r.uuid,spec_id:e.spec_id,spec_uuid:c.uuid,feedback_type:e.feedback_type,content:e.content,agent:i,anchor:s,dismissed:e.dismissed!==void 0&&e.dismissed?1:0});let d=ue(n,t);if(!d)throw new Error(`Failed to create feedback ${t}`);return d}catch(d){throw d.code&&d.code.startsWith("SQLITE_CONSTRAINT")?new Error(`Constraint violation: ${d.message}`):d}}function ue(n,e){let s=n.prepare(`
165
- SELECT * FROM issue_feedback WHERE id = ?
166
- `).get(e);return s?we(s):null}function Ne(n,e,t){let s=ue(n,e);if(!s)throw new Error(`Feedback not found: ${e}`);let i=[],r={id:e};if(t.content!==void 0&&(i.push("content = @content"),r.content=t.content),t.dismissed!==void 0&&(i.push("dismissed = @dismissed"),r.dismissed=t.dismissed?1:0),t.anchor!==void 0&&(i.push("anchor = @anchor"),r.anchor=JSON.stringify(t.anchor)),i.push("updated_at = CURRENT_TIMESTAMP"),i.length===1)return s;let c=n.prepare(`
167
- UPDATE issue_feedback SET ${i.join(", ")} WHERE id = @id
168
- `);try{c.run(r);let o=ue(n,e);if(!o)throw new Error(`Failed to update feedback ${e}`);return o}catch(o){throw o.code&&o.code.startsWith("SQLITE_CONSTRAINT")?new Error(`Constraint violation: ${o.message}`):o}}function Ce(n,e){return n.prepare("DELETE FROM issue_feedback WHERE id = ?").run(e).changes>0}function J(n,e={}){let t=[],s={};e.issue_id!==void 0&&(t.push("issue_id = @issue_id"),s.issue_id=e.issue_id),e.spec_id!==void 0&&(t.push("spec_id = @spec_id"),s.spec_id=e.spec_id),e.feedback_type!==void 0&&(t.push("feedback_type = @feedback_type"),s.feedback_type=e.feedback_type),e.dismissed!==void 0&&(t.push("dismissed = @dismissed"),s.dismissed=e.dismissed?1:0);let i="SELECT * FROM issue_feedback";return t.length>0&&(i+=" WHERE "+t.join(" AND ")),i+=" ORDER BY created_at DESC",e.limit!==void 0&&(i+=" LIMIT @limit",s.limit=e.limit),e.offset!==void 0&&(i+=" OFFSET @offset",s.offset=e.offset),n.prepare(i).all(s).map(we)}function Tt(n,e){let s=k(n,e.id,"spec").map(r=>({from:r.from_id,from_type:r.from_type,to:r.to_id,to_type:r.to_type,type:r.relationship_type})),i=q(n,e.id,"spec");return{...e,relationships:s,tags:i}}function It(n,e){let s=k(n,e.id,"issue").map(o=>({from:o.from_id,from_type:o.from_type,to:o.to_id,to_type:o.to_type,type:o.relationship_type})),i=q(n,e.id,"issue"),c=J(n,{issue_id:e.id}).map(o=>({id:o.id,issue_id:o.issue_id,spec_id:o.spec_id,feedback_type:o.feedback_type,content:o.content,agent:o.agent,anchor:o.anchor&&typeof o.anchor=="string"?JSON.parse(o.anchor):o.anchor,dismissed:o.dismissed,created_at:o.created_at,updated_at:o.updated_at}));return{...e,relationships:s,tags:i,feedback:c.length>0?c:void 0}}function Rt(n,e={}){let{since:t}=e,s=F(n);return(t?s.filter(r=>new Date(r.updated_at)>t):s).map(r=>Tt(n,r))}function vt(n,e={}){let{since:t}=e,s=$(n);return(t?s.filter(r=>new Date(r.updated_at)>t):s).map(r=>It(n,r))}async function le(n,e={}){let{outputDir:t=".sudocode",specsFile:s="specs.jsonl",issuesFile:i="issues.jsonl"}=e,r=`${t}/${s}`,c=`${t}/${i}`,o=Rt(n,e);await Y(r,o);let d=vt(n,e);return await Y(c,d),{specsCount:o.length,issuesCount:d.length}}var pe=class{constructor(e,t=5e3,s={}){this.db=e;this.delayMs=t;this.options=s}timeoutId=null;pending=!1;trigger(){this.pending=!0,this.timeoutId&&clearTimeout(this.timeoutId),this.timeoutId=setTimeout(()=>{this.execute()},this.delayMs)}async execute(){if(this.pending){this.pending=!1,this.timeoutId=null;try{await le(this.db,this.options)}catch(e){throw console.error("Export failed:",e),e}}}cancel(){this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=null),this.pending=!1}isPending(){return this.pending}async flush(){this.pending&&(this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=null),await this.execute())}};function ss(n,e=5e3,t={}){return new pe(n,e,t)}w();v();import*as fe from"path";function Fe(n,e){let t=new Map(n.map(d=>[d.uuid,d])),s=new Set(e.map(d=>d.uuid)),i=e.filter(d=>!t.has(d.uuid)).map(d=>d.id),r=n.filter(d=>!s.has(d.uuid)).map(d=>d.id),c=[],o=[];for(let d of e){let a=t.get(d.uuid);a&&(Ot(a,d)?c.push(d.id):o.push(d.id))}return{added:i,updated:c,deleted:r,unchanged:o}}function Ot(n,e){return n.updated_at!==e.updated_at}function ke(n,e){let t=[],s=new Map(n.map(r=>[r.id,r]));for(let r of e){let c=s.get(r.id);c&&c.uuid!==r.uuid&&t.push({id:r.id,uuid:r.uuid,type:"spec",reason:"Same ID but different UUID (different entities)",localContent:c.title,incomingContent:r.title,localCreatedAt:c.created_at,incomingCreatedAt:r.created_at})}let i=new Map;for(let r of e){let c=i.get(r.id)||[];c.push(r),i.set(r.id,c)}for(let[r,c]of i.entries())if(c.length>1&&new Set(c.map(d=>d.uuid)).size>1)for(let d=1;d<c.length;d++)t.push({id:c[d].id,uuid:c[d].uuid,type:"spec",reason:"Duplicate ID in incoming data with different UUID",localContent:c[0].title,incomingContent:c[d].title,localCreatedAt:c[0].created_at,incomingCreatedAt:c[d].created_at});return t}function ls(n,e,t){let s=0,i=F(n);for(let c of i){let o=new RegExp(`\\b${e}\\b`,"g"),d=c.content.match(o);d&&(s+=d.length)}let r=$(n);for(let c of r){let o=new RegExp(`\\b${e}\\b`,"g"),d=c.content.match(o);d&&(s+=d.length)}return s}function wt(n,e){let t=[],s=new Map;for(let i of e){let r=!0;if(i.localCreatedAt){let o=new Date(i.localCreatedAt).getTime(),d=new Date(i.incomingCreatedAt).getTime();d>o?r=!0:o>d?r=!1:r=i.uuid>i.localContent}let c=s.get(i.uuid);c||(c=Lt(n,i.id,i.type),s.set(i.uuid,c)),t.push({...i,resolution:"renumber",newId:c,...r&&{note:"incoming is newer - correctly renumbered"},...!r&&{note:"local is newer - incoming (older) being renumbered"}})}return t}function Lt(n,e,t){let s=e.match(/^([a-z]+-)?(\d+)$/i);if(!s)return`${t}-${Date.now()}`;let i=s[1]||`${t}-`,r=parseInt(s[2],10),c=`${i}${r+1e3}`,o=0;for(;o<1e3;){if(!(t==="spec"?T(n,c)!==null:E(n,c)!==null))return c;r++,c=`${i}${r+1e3}`,o++}return`${i}${Date.now()}`}function fs(n,e,t){let s=0,i=F(n);for(let c of i){let o=new RegExp(`\\b${e}\\b`,"g");if(o.test(c.content)){let d=c.content.replace(o,t);P(n,c.id,{content:d}),s++}}let r=$(n);for(let c of r){let o=new RegExp(`\\b${e}\\b`,"g"),d=!1,a=c.content;o.test(c.content)&&(a=c.content.replace(o,t),d=!0),d&&(L(n,c.id,{content:a}),s++)}return s}function Ae(n,e,t,s=!1,i=!1){if(s)return{added:t.added.length,updated:t.updated.length,deleted:t.deleted.length};let r=0,c=0,o=0;for(let d of t.added){let a=e.find(u=>u.id===d);a&&(X(n,{id:a.id,uuid:a.uuid,title:a.title,file_path:a.file_path,content:a.content,priority:a.priority,parent_id:a.parent_id,archived:a.archived,archived_at:a.archived_at,created_at:a.created_at,updated_at:a.updated_at}),O(n,a.id,"spec",a.tags||[]),r++)}if(!i)for(let d of t.added){let a=e.find(u=>u.id===d);if(a&&a.relationships&&a.relationships.length>0)for(let u of a.relationships)I(n,{from_id:u.from,from_type:u.from_type,to_id:u.to,to_type:u.to_type,relationship_type:u.type})}for(let d of t.updated){let a=e.find(u=>u.id===d);a&&(P(n,a.id,{title:a.title,file_path:a.file_path,content:a.content,priority:a.priority,parent_id:a.parent_id,archived:a.archived,archived_at:a.archived_at,updated_at:a.updated_at}),O(n,a.id,"spec",a.tags||[]),c++)}if(!i)for(let d of t.updated){let a=e.find(u=>u.id===d);if(a){A(n,a.id,"spec");for(let u of a.relationships||[])I(n,{from_id:u.from,from_type:u.from_type,to_id:u.to,to_type:u.to_type,relationship_type:u.type})}}for(let d of t.deleted)Te(n,d),o++;return{added:r,updated:c,deleted:o}}function $e(n,e,t){let s=J(n,{issue_id:e});for(let i of s)Ce(n,i.id);if(t&&t.length>0)for(let i of t)Le(n,{id:i.id,issue_id:i.issue_id,spec_id:i.spec_id,feedback_type:i.feedback_type,content:i.content,agent:i.agent,anchor:i.anchor,dismissed:i.dismissed})}function Me(n,e,t,s=!1,i=!1){if(s)return{added:t.added.length,updated:t.updated.length,deleted:t.deleted.length};let r=0,c=0,o=0;for(let d of t.added){let a=e.find(u=>u.id===d);a&&(te(n,{id:a.id,uuid:a.uuid,title:a.title,content:a.content,status:a.status,priority:a.priority,assignee:a.assignee,parent_id:a.parent_id,archived:a.archived,archived_at:a.archived_at,created_at:a.created_at,updated_at:a.updated_at,closed_at:a.closed_at}),O(n,a.id,"issue",a.tags||[]),$e(n,a.id,a.feedback),r++)}if(!i)for(let d of t.added){let a=e.find(u=>u.id===d);if(a)for(let u of a.relationships||[])I(n,{from_id:u.from,from_type:u.from_type,to_id:u.to,to_type:u.to_type,relationship_type:u.type})}for(let d of t.updated){let a=e.find(u=>u.id===d);a&&(L(n,a.id,{title:a.title,content:a.content,status:a.status,priority:a.priority,assignee:a.assignee,parent_id:a.parent_id,archived:a.archived,archived_at:a.archived_at,updated_at:a.updated_at,closed_at:a.closed_at}),O(n,a.id,"issue",a.tags||[]),$e(n,a.id,a.feedback),c++)}if(!i)for(let d of t.updated){let a=e.find(u=>u.id===d);if(a){A(n,a.id,"issue");for(let u of a.relationships||[])I(n,{from_id:u.from,from_type:u.from_type,to_id:u.to,to_type:u.to_type,relationship_type:u.type})}}for(let d of t.deleted)Ie(n,d),o++;return{added:r,updated:c,deleted:o}}async function gs(n,e={}){let{inputDir:t=".sudocode",specsFile:s="specs.jsonl",issuesFile:i="issues.jsonl",dryRun:r=!1,resolveCollisions:c=!0}=e,o=fe.join(t,s),d=fe.join(t,i),a=await M(o,{skipErrors:!0}),u=await M(d,{skipErrors:!0}),p=F(n),f=$(n),g=ke(p,a),S=ke(f,u),b=[...g.map(m=>({...m,type:"spec"})),...S.map(m=>({...m,type:"issue"}))],y=[];if(c&&b.length>0){y=wt(n,b);for(let m of y)if(m.resolution==="renumber"&&m.newId){if(m.type==="spec"){let _=a.find(l=>l.id===m.id&&l.uuid===m.uuid);_&&(_.id=m.newId)}else if(m.type==="issue"){let _=u.find(l=>l.id===m.id&&l.uuid===m.uuid);_&&(_.id=m.newId)}}}let D=Fe(p,a),x=Fe(f,u),N={specs:{added:0,updated:0,deleted:0},issues:{added:0,updated:0,deleted:0},collisions:y.length>0?y:b};return r?(N.specs=Ae(n,a,D,r),N.issues=Me(n,u,x,r)):oe(n,()=>{N.specs=Ae(n,a,D,r,!0),N.issues=Me(n,u,x,r,!0);for(let m of D.added){let _=a.find(l=>l.id===m);if(_&&_.relationships&&_.relationships.length>0)for(let l of _.relationships)I(n,{from_id:l.from,from_type:l.from_type,to_id:l.to,to_type:l.to_type,relationship_type:l.type})}for(let m of D.updated){let _=a.find(l=>l.id===m);if(_){A(n,_.id,"spec");for(let l of _.relationships||[])I(n,{from_id:l.from,from_type:l.from_type,to_id:l.to,to_type:l.to_type,relationship_type:l.type})}}for(let m of x.added){let _=u.find(l=>l.id===m);if(_&&_.relationships&&_.relationships.length>0)for(let l of _.relationships)I(n,{from_id:l.from,from_type:l.from_type,to_id:l.to,to_type:l.to_type,relationship_type:l.type})}for(let m of x.updated){let _=u.find(l=>l.id===m);if(_){A(n,_.id,"issue");for(let l of _.relationships||[])I(n,{from_id:l.from,from_type:l.from_type,to_id:l.to,to_type:l.to_type,relationship_type:l.type})}}}),N}import U from"gray-matter";import*as W from"fs";w();B();import*as Je from"crypto";function z(n,e,t){let s=n.split(`
169
- `);if(e<1||e>s.length)throw new Error(`Line number ${e} is out of range (1-${s.length})`);let i=s[e-1],r=Nt(s,e),c=Ue(i,t,50),o=ne(s,e,-50),d=ne(s,e,50),a=r?e-r.startLine:void 0,u=We(c);return{section_heading:r?.heading,section_level:r?.level,line_number:e,line_offset:a,text_snippet:c,context_before:o,context_after:d,content_hash:u,anchor_status:"valid",last_verified_at:new Date().toISOString(),original_location:{line_number:e,section_heading:r?.heading}}}function Nt(n,e){for(let t=e-1;t>=0;t--){let i=n[t].match(/^(#{1,6})\s+(.+?)(\r)?$/);if(i){let r=i[1].length;return{heading:i[2].trim(),level:r,startLine:t+1}}}return null}function Ue(n,e,t=50){if(!n||n.trim()==="")return"";let s=n.trim(),i=0,r=s.length;if(e!==void 0){let o=n.length-n.trimStart().length,d=Math.max(0,e-o),a=Math.floor(t/2);i=Math.max(0,d-a),r=Math.min(s.length,d+a)}else r=Math.min(s.length,t);let c=s.substring(i,r);return i>0&&(c="..."+c),r<s.length&&(c=c+"..."),c}function ne(n,e,t){if(t===0)return"";let s=t>0?1:-1,i=Math.abs(t),r="",c=e-1;for(s>0?c+=1:c-=1;c>=0&&c<n.length&&r.length<i;){let o=n[c],d=i-r.length;if(s>0)r.length>0&&(r+=" "),r+=o.substring(0,d);else{let a=Math.max(0,o.length-d),u=o.substring(a);r.length>0?r=u+" "+r:r=u}c+=s}return r.trim()}function We(n){return Je.createHash("sha256").update(n).digest("hex").substring(0,16)}function Ct(n,e){if(!e.line_number)return!1;let t=n.split(`
170
- `);if(e.line_number<1||e.line_number>t.length)return!1;let s=t[e.line_number-1];if(e.text_snippet&&e.text_snippet.trim()){let i=e.text_snippet.replace(/\.\.\./g,"").trim();if(i&&!s.includes(i))return!1}if(e.content_hash&&e.text_snippet&&e.text_snippet.trim()){let i=Ue(s,void 0,50);if(i&&We(i)!==e.content_hash)return!1}return!0}function je(n){let e=n.split(`
171
- `),t=[];for(let s=0;s<e.length;s++){let r=e[s].match(/^(#{1,6})\s+(.+?)(\r)?$/);r&&t.push({heading:r[2].trim(),level:r[1].length,startLine:s+1})}return t}function Ft(n,e,t,s){if(!e)return[];let i=n.split(`
172
- `),r=[],c=e.replace(/\.\.\./g,"").trim();for(let o=0;o<i.length;o++)if(i[o].includes(c)){let a=.5;t&&ne(i,o+1,-50).includes(t.substring(0,20))&&(a+=.25),s&&ne(i,o+1,50).includes(s.substring(0,20))&&(a+=.25),r.push({lineNumber:o+1,confidence:Math.min(a,1)})}return r.sort((o,d)=>d.confidence-o.confidence)}function kt(n,e){let t=n.length,s=e.length,i=Array(t+1).fill(null).map(()=>Array(s+1).fill(0));for(let r=0;r<=t;r++)i[r][0]=r;for(let r=0;r<=s;r++)i[0][r]=r;for(let r=1;r<=t;r++)for(let c=1;c<=s;c++){let o=n[r-1]===e[c-1]?0:1;i[r][c]=Math.min(i[r-1][c]+1,i[r][c-1]+1,i[r-1][c-1]+o)}return i[t][s]}function At(n,e,t=5){let s=je(n);if(s.length===0)return null;let i=e.toLowerCase().trim(),r=null,c=1/0;for(let o of s){let d=o.heading.toLowerCase().trim(),a=kt(i,d);a<c&&a<=t&&(c=a,r=o)}return r}function Be(n,e,t){if(Ct(e,t))return{...t,anchor_status:"valid",last_verified_at:new Date().toISOString()};if(t.section_heading&&t.line_offset!==void 0){let i=je(e).find(r=>r.heading===t.section_heading);if(i){let r=i.startLine+t.line_offset,c=e.split(`
173
- `);if(r>0&&r<=c.length){let o=c[r-1];if(t.text_snippet){let d=t.text_snippet.replace(/\.\.\./g,"").trim();if(d&&o.includes(d))return{...z(e,r),anchor_status:"relocated",last_verified_at:new Date().toISOString(),original_location:t.original_location||{line_number:t.line_number||0,section_heading:t.section_heading}}}}}}if(t.text_snippet){let s=Ft(e,t.text_snippet,t.context_before,t.context_after);if(s.length>0&&s[0].confidence>=.7)return{...z(e,s[0].lineNumber),anchor_status:"relocated",last_verified_at:new Date().toISOString(),original_location:t.original_location||{line_number:t.line_number||0,section_heading:t.section_heading}}}if(t.section_heading&&t.line_offset!==void 0){let s=At(e,t.section_heading,5);if(s){let i=s.startLine+t.line_offset,r=e.split(`
174
- `);if(i>0&&i<=r.length)return{...z(e,i),anchor_status:"relocated",last_verified_at:new Date().toISOString(),original_location:t.original_location||{line_number:t.line_number||0,section_heading:t.section_heading}}}}return{...t,anchor_status:"stale",last_verified_at:new Date().toISOString(),original_location:t.original_location||{line_number:t.line_number||0,section_heading:t.section_heading}}}function $t(n,e,t){let s=U(n),i;if(t&&e)try{i=De(t)}catch{}let r=Ut(s.content,e,i);return{data:s.data,content:s.content,raw:n,references:r}}function Pe(n,e,t){let s=W.readFileSync(n,"utf8");return $t(s,e,t)}function Mt(n,e){return n.substring(0,e).split(`
175
- `).length}function Jt(n){return{section_heading:n.section_heading,section_level:n.section_level,line_number:n.line_number,line_offset:n.line_offset,text_snippet:n.text_snippet,context_before:n.context_before,context_after:n.context_after,content_hash:n.content_hash}}function Ut(n,e,t){let s=[],i=/\[\[(@)?([a-z]+-\d+)(?:\|([^\]]+))?\]\](?:\{\s*(?:type:\s*)?([a-z-]+)\s*\})?/gi,r;for(;(r=i.exec(n))!==null;){let c=r[1]==="@",o=r[2],d=r[3]?.trim(),a=r[4]?.trim(),u;try{let p=Mt(n,r.index),f=z(n,p,r.index);u=Jt(f)}catch{u=void 0}if(e){let p=null;try{T(e,o)&&(p="spec")}catch{}if(!p)try{E(e,o)&&(p="issue")}catch{}p&&s.push({match:r[0],id:o,type:p,index:r.index,displayText:d,relationshipType:a,anchor:u})}else{let p;if(t){let f=t.id_prefix.spec.toLowerCase(),g=t.id_prefix.issue.toLowerCase();c||o.toLowerCase().startsWith(g+"-")?p="issue":(o.toLowerCase().startsWith(f+"-"),p="spec")}else p=c||o.startsWith("issue-")?"issue":"spec";s.push({match:r[0],id:o,type:p,index:r.index,displayText:d,relationshipType:a,anchor:u})}}return s}function Wt(n,e){return U.stringify(e,n)}function jt(n,e){let t=U(n),s={...t.data,...e},i=Object.fromEntries(Object.entries(s).filter(([r,c])=>c!==void 0));return U.stringify(t.content,i)}function ge(n,e){let t=W.readFileSync(n,"utf8"),s=jt(t,e);W.writeFileSync(n,s,"utf8")}function Ds(n){return n.trimStart().startsWith("---")}function Bt(n,e){return Wt(n,e)}function He(n,e,t){let s=Bt(e,t);W.writeFileSync(n,s,"utf8")}function xs(n){return U(n).content}function Ts(n){return U(n).data}function Is(n){let e=[],t=n.match(/^## Spec Feedback Provided\s*$/m);if(!t)return e;let s=t.index+t[0].length,i=n.slice(s),r=i.match(/^## /m),c=r?i.slice(0,r.index):i,o=/^### (FB-\d+) → ([a-z]+-\d+)(?: \((.*?)\))?\s*\n\*\*Type:\*\* (.+?)\s*\n\*\*Location:\*\* (.*?)\s*\n\*\*Status:\*\* (.+?)\s*\n\n([\s\S]*?)(?=\n###|$)/gm,d;for(;(d=o.exec(c))!==null;){let[,a,u,p,f,g,S,b]=d,y=g.match(/(?:(.+?),\s+)?line (\d+)\s*([✓⚠✗])/),D={id:a,specId:u,specTitle:p||void 0,type:f.trim(),location:{section:y?.[1]?.trim(),line:y?.[2]?parseInt(y[2]):void 0,status:y?.[3]==="\u2713"?"valid":y?.[3]==="\u26A0"?"relocated":"stale"},status:S.trim(),content:b.trim(),createdAt:""},x=b.match(/\*\*Resolution:\*\* (.+)/);x&&(D.resolution=x[1].trim()),e.push(D)}return e}function Pt(n){if(n.length===0)return"";let e=`
176
- ## Spec Feedback Provided
177
-
178
- `;for(let t of n){let s=t.location.status==="valid"?"\u2713":t.location.status==="relocated"?"\u26A0":"\u2717",i="";t.location.section&&t.location.line?i=`${t.location.section}, line ${t.location.line} ${s}`:t.location.line?i=`line ${t.location.line} ${s}`:i=`Unknown ${s}`;let r=t.specTitle?` (${t.specTitle})`:"";e+=`### ${t.id} \u2192 ${t.specId}${r}
179
- `,e+=`**Type:** ${t.type}
180
- `,e+=`**Location:** ${i}
181
- `,e+=`**Status:** ${t.status}
182
-
183
- `,e+=`${t.content}
184
- `,t.resolution&&(e+=`
185
- **Resolution:** ${t.resolution}
186
- `),e+=`
187
- `}return e}function Rs(n,e){let t=n.match(/^## Spec Feedback Provided\s*$/m);if(t){let i=t.index,c=n.slice(i).match(/^## /m);if(c&&c.index>0){let o=i+c.index;n=n.slice(0,i)+n.slice(o)}else n=n.slice(0,i)}let s=Pt(e);return s&&(n=n.trimEnd()+`
188
- `+s),n}import*as j from"fs";import*as V from"path";w();v();B();function Ht(n){let{file_path:e,entity_type:t,...s}=n;return s}function qt(n,e,t,s,i,r){let c=new Date().toISOString(),o={...e};if(o.id||(o.id=t==="spec"?be(n,i):Se(n,i)),!o.title){let a=j.readFileSync(s,"utf8").match(/^#\s+(.+)$/m);o.title=a?a[1]:V.basename(s,".md")}return o.created_at||(o.created_at=c),o.updated_at||(o.updated_at=c),t==="spec"||o.status||(o.status="open"),!o.priority&&o.priority!==0&&(o.priority=2),o}async function Ms(n,e,t={}){let{outputDir:s=".sudocode",autoExport:i=!0,user:r="system",autoInitialize:c=!0,writeBackFrontmatter:o=!0}=t;try{let d=Pe(e,n,s),{data:a,content:u,references:p}=d,f=Yt(a,e),g=a.id,S=g,b=V.relative(s,e),y=b.startsWith("..")?V.relative(process.cwd(),e):b,D=null,x=null;if(f==="spec"){if(a.file_path=y,S&&(x=T(n,S)),D=xe(n,y),x)g=x.id,x.file_path!==y&&(console.log(`[sync] File renamed: ${x.file_path} \u2192 ${y}`),D&&D.id!==x.id&&console.warn(`[sync] Warning: File path conflict! Spec ${D.id} already exists at ${y}. Keeping ${x.id} and updating path.`));else if(D)g=D.id,a.id=g;else if(S&&D){let Q=D.id;console.warn(`[sync] Warning: ID in frontmatter (${S}) differs from existing spec ID (${Q}) for ${y}. Using existing ID.`),g=Q,a.id=g}}if(!g)if(c){if(a=qt(n,a,f,e,s,r),g=a.id,o){let Q=Ht(a);ge(e,Q)}}else return{success:!1,action:"no-change",entityId:"",entityType:f,error:"Missing id in frontmatter (auto-initialization disabled)"};let m=!(f==="spec"?T(n,g):E(n,g)),_=j.statSync(e),l=new Date(_.mtimeMs).toISOString();return f==="spec"?await zt(n,g,a,u,p,m,r,l):await Vt(n,g,a,u,p,m,r,l),i&&await le(n,{outputDir:s}),{success:!0,action:m?"created":"updated",entityId:g,entityType:f}}catch(d){return{success:!1,action:"no-change",entityId:"",entityType:"spec",error:d instanceof Error?d.message:String(d)}}}async function Js(n,e,t,s){try{let i=t==="spec"?T(n,e):E(n,e);if(!i)return{success:!1,action:"no-change",entityId:e,entityType:t,error:`${t} not found: ${e}`};let{getOutgoingRelationships:r}=await Promise.resolve().then(()=>(v(),re)),c=r(n,e,t),o=q(n,e,t),d=Qt(i,t,c,o),a=j.existsSync(s);if(a)ge(s,d);else{let u=i.content||"";He(s,d,u)}return{success:!0,action:a?"updated":"created",entityId:e,entityType:t}}catch(i){return{success:!1,action:"no-change",entityId:e,entityType:t,error:i instanceof Error?i.message:String(i)}}}function Yt(n,e){return n.entity_type==="issue"?"issue":n.entity_type==="spec"?"spec":e.includes("/issues/")||e.includes("/issue-")?"issue":(e.includes("/specs/")||e.includes("/spec-"),"spec")}async function zt(n,e,t,s,i,r,c,o){let d=r?null:T(n,e),a=d?.content||"",u={id:e,title:t.title||"Untitled",file_path:t.file_path||"",content:s,priority:t.priority??2,parent_id:t.parent_id||void 0};if(r)X(n,{...u,updated_at:o});else{let p=d?.title!==u.title||d?.content!==u.content||d?.priority!==u.priority||d?.parent_id!==u.parent_id||d?.file_path!==u.file_path;if(P(n,e,{...u,...p&&o?{updated_at:o}:{}}),a!==s){let f=J(n,{spec_id:e});if(f.length>0)for(let g of f){let S=typeof g.anchor=="string"?JSON.parse(g.anchor):g.anchor,b=Be(a,s,S);Ne(n,g.id,{anchor:b})}}}t.tags&&Array.isArray(t.tags)&&O(n,e,"spec",t.tags),await qe(n,e,"spec",i,t.relationships,c)}async function Vt(n,e,t,s,i,r,c,o){let d=r?null:E(n,e),a={id:e,title:t.title||"Untitled",content:s,status:t.status||"open",priority:t.priority??2,assignee:t.assignee||void 0,parent_id:t.parent_id||void 0};if(r)te(n,{...a,updated_at:o});else{let u=d?.title!==a.title||d?.content!==a.content||d?.status!==a.status||d?.priority!==a.priority||d?.assignee!==a.assignee||d?.parent_id!==a.parent_id;L(n,e,{...a,...u&&o?{updated_at:o}:{}})}t.tags&&Array.isArray(t.tags)&&O(n,e,"issue",t.tags),await qe(n,e,"issue",i,t.relationships,c)}async function qe(n,e,t,s,i,r="system"){let{getOutgoingRelationships:c}=await Promise.resolve().then(()=>(v(),re)),o=c(n,e,t),d=new Set(o.map(a=>`${a.relationship_type}:${a.to_type}:${a.to_id}`));for(let a of s){let u=a.relationshipType||"references",p=`${u}:${a.type}:${a.id}`;if(!d.has(p))try{I(n,{from_id:e,from_type:t,to_id:a.id,to_type:a.type,relationship_type:u,metadata:a.anchor?JSON.stringify({anchor:a.anchor}):void 0})}catch{}}if(i&&Array.isArray(i))for(let a of i){let u=`${a.relationship_type}:${a.target_type}:${a.target_id}`;if(!d.has(u))try{I(n,{from_id:e,from_type:t,to_id:a.target_id,to_type:a.target_type,relationship_type:a.relationship_type})}catch{}}}function Qt(n,e,t,s){let i={id:n.id,title:n.title,priority:n.priority,created_at:n.created_at};if(n.parent_id&&(i.parent_id=n.parent_id),s.length>0&&(i.tags=s),t.length>0&&(i.relationships=t),e==="spec")return i;{let r=n,c={...i,status:r.status};return r.assignee&&(c.assignee=r.assignee),r.closed_at&&(c.closed_at=r.closed_at),c}}export{pe as ExportDebouncer,Re as SavepointTransaction,Nn as addReferenceToContent,I as addRelationship,_t as addTag,ht as addTags,Wn as batchTransaction,gn as closeIssue,ls as countReferences,ss as createDebouncedExport,te as createIssue,Bt as createMarkdown,X as createSpec,wn as deleteEntityEvents,Ie as deleteIssue,qn as deleteJSONLLine,Yn as deleteJSONLLineSync,Te as deleteSpec,Fe as detectChanges,ke as detectCollisions,vt as exportIssuesToJSONL,Rt as exportSpecsToJSONL,le as exportToJSONL,Ut as extractCrossReferences,Pt as formatFeedbackForIssue,bt as formatReference,lt as getAllRelationships,xn as getAllTags,hn as getBlockedIssues,en as getDatabase,ut as getDependencies,pt as getDependents,Sn as getEntitiesByTag,Rn as getEntityEvents,Et as getEvent,On as getEventsByActor,Ts as getFrontmatter,H as getIncomingRelationships,E as getIssue,zn as getJSONLEntity,Vn as getJSONLEntitySync,k as getOutgoingRelationships,_n as getReadyIssues,vn as getRecentEvents,ee as getRelationship,T as getSpec,xe as getSpecByFilePath,q as getTags,Ds as hasFrontmatter,Dn as hasTag,gs as importFromJSONL,Me as importIssues,Ae as importSpecs,Ge as initDatabase,In as insertEvent,It as issueToJSONL,$ as listIssues,F as listSpecs,Is as parseFeedbackSection,$t as parseMarkdown,Pe as parseMarkdownFile,ae as queryEvents,M as readJSONL,de as readJSONLSync,ft as relationshipExists,A as removeAllRelationships,yt as removeAllTags,xs as removeFrontmatter,ot as removeRelationship,bn as removeTag,mn as reopenIssue,wt as resolveCollisions,yn as searchIssues,dn as searchSpecs,O as setTags,Tt as specToJSONL,Wt as stringifyMarkdown,Js as syncJSONLToMarkdown,Ms as syncMarkdownToJSONL,oe as transaction,Rs as updateFeedbackInIssue,jt as updateFrontmatter,ge as updateFrontmatterFile,L as updateIssue,Pn as updateJSONLLine,Hn as updateJSONLLineSync,P as updateSpec,fs as updateTextReferences,jn as withRetry,tn as withTransaction,Y as writeJSONL,Oe as writeJSONLSync,He as writeMarkdownFile};
189
- //# sourceMappingURL=index.js.map
1
+ /**
2
+ * Main entry point for sudocode
3
+ */
4
+ export * from "@sudocode-ai/types";
5
+ export * from "./db.js";
6
+ export * from "./operations/index.js";
7
+ export * from "./operations/transactions.js";
8
+ export * from "./jsonl.js";
9
+ export * from "./export.js";
10
+ export * from "./import.js";
11
+ export * from "./markdown.js";
12
+ export * from "./sync.js";
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,oBAAoB,CAAC;AACnC,cAAc,SAAS,CAAC;AACxB,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonl.d.ts","sourceRoot":"","sources":["../src/jsonl.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExD,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAEvE,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACpE;AAED,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EACjE,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,CAAC,EAAE,CAAC,CA4Cd;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EAC/D,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,gBAAqB,GAC7B,CAAC,EAAE,CAwCL;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EAClE,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,CAAC,EAAE,EACb,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAkFf;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EAChE,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,CAAC,EAAE,EACb,OAAO,GAAE,iBAAsB,GAC9B,IAAI,CAkFN;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EACvE,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,CAAC,EACT,OAAO,GAAE,MAAa,GACrB,OAAO,CAAC,IAAI,CAAC,CAuBf;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EACrE,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,CAAC,EACT,OAAO,GAAE,MAAa,GACrB,IAAI,CAuBN;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EACvE,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,MAAa,GACrB,OAAO,CAAC,OAAO,CAAC,CAelB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EACrE,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,MAAa,GACrB,OAAO,CAeT;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EACtE,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,MAAa,GACrB,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAGnB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,EACpE,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,MAAa,GACrB,CAAC,GAAG,IAAI,CAGV"}
package/dist/jsonl.js ADDED
@@ -0,0 +1,333 @@
1
+ /**
2
+ * JSONL (JSON Lines) reader and writer
3
+ * Supports reading and writing .jsonl files for specs and issues
4
+ */
5
+ import * as fs from "fs";
6
+ import * as readline from "readline";
7
+ import * as path from "path";
8
+ /**
9
+ * Read a JSONL file and parse all lines
10
+ * Uses streaming for memory efficiency with large files
11
+ */
12
+ export async function readJSONL(filePath, options = {}) {
13
+ const { skipErrors = false, onError } = options;
14
+ // Check if file exists
15
+ if (!fs.existsSync(filePath)) {
16
+ return [];
17
+ }
18
+ const entities = [];
19
+ const fileStream = fs.createReadStream(filePath, { encoding: "utf8" });
20
+ const rl = readline.createInterface({
21
+ input: fileStream,
22
+ crlfDelay: Infinity,
23
+ });
24
+ let lineNumber = 0;
25
+ for await (const line of rl) {
26
+ lineNumber++;
27
+ // Skip empty lines
28
+ if (line.trim() === "") {
29
+ continue;
30
+ }
31
+ try {
32
+ const entity = JSON.parse(line);
33
+ entities.push(entity);
34
+ }
35
+ catch (error) {
36
+ const parseError = error;
37
+ if (onError) {
38
+ onError(lineNumber, line, parseError);
39
+ }
40
+ if (!skipErrors) {
41
+ throw new Error(`Failed to parse JSON at line ${lineNumber}: ${parseError.message}`);
42
+ }
43
+ }
44
+ }
45
+ return entities;
46
+ }
47
+ /**
48
+ * Read a JSONL file synchronously (for smaller files)
49
+ */
50
+ export function readJSONLSync(filePath, options = {}) {
51
+ const { skipErrors = false, onError } = options;
52
+ // Check if file exists
53
+ if (!fs.existsSync(filePath)) {
54
+ return [];
55
+ }
56
+ const entities = [];
57
+ const content = fs.readFileSync(filePath, "utf8");
58
+ const lines = content.split("\n");
59
+ for (let i = 0; i < lines.length; i++) {
60
+ const line = lines[i].trim();
61
+ const lineNumber = i + 1;
62
+ // Skip empty lines
63
+ if (line === "") {
64
+ continue;
65
+ }
66
+ try {
67
+ const entity = JSON.parse(line);
68
+ entities.push(entity);
69
+ }
70
+ catch (error) {
71
+ const parseError = error;
72
+ if (onError) {
73
+ onError(lineNumber, line, parseError);
74
+ }
75
+ if (!skipErrors) {
76
+ throw new Error(`Failed to parse JSON at line ${lineNumber}: ${parseError.message}`);
77
+ }
78
+ }
79
+ }
80
+ return entities;
81
+ }
82
+ /**
83
+ * Write entities to a JSONL file
84
+ * Each entity is written as a single line of JSON
85
+ * Entities are sorted by created_at date to minimize merge conflicts
86
+ */
87
+ export async function writeJSONL(filePath, entities, options = {}) {
88
+ const { atomic = true } = options;
89
+ // Ensure directory exists
90
+ const dir = path.dirname(filePath);
91
+ if (!fs.existsSync(dir)) {
92
+ fs.mkdirSync(dir, { recursive: true });
93
+ }
94
+ const targetPath = atomic ? `${filePath}.tmp` : filePath;
95
+ // Sort entities by created_at date to minimize merge conflicts
96
+ const sortedEntities = [...entities].sort((a, b) => {
97
+ const aDate = a.created_at;
98
+ const bDate = b.created_at;
99
+ // Handle missing created_at fields - put them at the end
100
+ if (!aDate && !bDate) {
101
+ // Both missing dates, sort by ID
102
+ const aId = a.id || "";
103
+ const bId = b.id || "";
104
+ return aId < bId ? -1 : aId > bId ? 1 : 0;
105
+ }
106
+ if (!aDate)
107
+ return 1;
108
+ if (!bDate)
109
+ return -1;
110
+ // Compare dates as strings (ISO 8601 format sorts lexicographically)
111
+ if (aDate < bDate)
112
+ return -1;
113
+ if (aDate > bDate)
114
+ return 1;
115
+ // If dates are equal, fall back to ID comparison
116
+ const aId = a.id || "";
117
+ const bId = b.id || "";
118
+ return aId < bId ? -1 : aId > bId ? 1 : 0;
119
+ });
120
+ // Write each entity as a line
121
+ const lines = sortedEntities.map((entity) => JSON.stringify(entity));
122
+ const content = lines.join("\n") + "\n";
123
+ // Check if content has actually changed before writing
124
+ // This prevents unnecessary file writes that trigger watcher events
125
+ if (fs.existsSync(filePath)) {
126
+ const existingContent = fs.readFileSync(filePath, "utf8");
127
+ if (existingContent === content) {
128
+ // Content unchanged, skip write
129
+ return;
130
+ }
131
+ }
132
+ fs.writeFileSync(targetPath, content, "utf8");
133
+ // Atomic rename if requested
134
+ if (atomic) {
135
+ fs.renameSync(targetPath, filePath);
136
+ }
137
+ // Set file modification time to match the newest updated_at timestamp
138
+ // This ensures filesystem mtime reflects content timestamps for accurate sync direction detection
139
+ if (sortedEntities.length > 0) {
140
+ const timestamps = sortedEntities
141
+ .map((e) => e.updated_at)
142
+ .filter((t) => t != null)
143
+ .map((t) => {
144
+ // Append 'Z' if not present to force UTC interpretation
145
+ const timestamp = String(t);
146
+ const hasZone = timestamp.endsWith("Z") ||
147
+ timestamp.includes("+") ||
148
+ /[+-]\d{2}:\d{2}$/.test(timestamp);
149
+ const utcTimestamp = hasZone
150
+ ? timestamp
151
+ : timestamp.replace(" ", "T") + "Z";
152
+ return new Date(utcTimestamp).getTime();
153
+ });
154
+ if (timestamps.length > 0) {
155
+ const newestTimestamp = Math.max(...timestamps);
156
+ const mtimeDate = new Date(newestTimestamp);
157
+ fs.utimesSync(filePath, mtimeDate, mtimeDate);
158
+ }
159
+ }
160
+ }
161
+ /**
162
+ * Write entities to a JSONL file synchronously
163
+ * Entities are sorted by created_at date to minimize merge conflicts
164
+ */
165
+ export function writeJSONLSync(filePath, entities, options = {}) {
166
+ const { atomic = true } = options;
167
+ // Ensure directory exists
168
+ const dir = path.dirname(filePath);
169
+ if (!fs.existsSync(dir)) {
170
+ fs.mkdirSync(dir, { recursive: true });
171
+ }
172
+ const targetPath = atomic ? `${filePath}.tmp` : filePath;
173
+ // Sort entities by created_at date to minimize merge conflicts
174
+ const sortedEntities = [...entities].sort((a, b) => {
175
+ const aDate = a.created_at;
176
+ const bDate = b.created_at;
177
+ // Handle missing created_at fields - put them at the end
178
+ if (!aDate && !bDate) {
179
+ // Both missing dates, sort by ID
180
+ const aId = a.id || "";
181
+ const bId = b.id || "";
182
+ return aId < bId ? -1 : aId > bId ? 1 : 0;
183
+ }
184
+ if (!aDate)
185
+ return 1;
186
+ if (!bDate)
187
+ return -1;
188
+ // Compare dates as strings (ISO 8601 format sorts lexicographically)
189
+ if (aDate < bDate)
190
+ return -1;
191
+ if (aDate > bDate)
192
+ return 1;
193
+ // If dates are equal, fall back to ID comparison
194
+ const aId = a.id || "";
195
+ const bId = b.id || "";
196
+ return aId < bId ? -1 : aId > bId ? 1 : 0;
197
+ });
198
+ // Write each entity as a line
199
+ const lines = sortedEntities.map((entity) => JSON.stringify(entity));
200
+ const content = lines.join("\n") + "\n";
201
+ // Check if content has actually changed before writing
202
+ // This prevents unnecessary file writes that trigger watcher events
203
+ if (fs.existsSync(filePath)) {
204
+ const existingContent = fs.readFileSync(filePath, "utf8");
205
+ if (existingContent === content) {
206
+ // Content unchanged, skip write
207
+ return;
208
+ }
209
+ }
210
+ fs.writeFileSync(targetPath, content, "utf8");
211
+ // Atomic rename if requested
212
+ if (atomic) {
213
+ fs.renameSync(targetPath, filePath);
214
+ }
215
+ // Set file modification time to match the newest updated_at timestamp
216
+ // This ensures filesystem mtime reflects content timestamps for accurate sync direction detection
217
+ if (sortedEntities.length > 0) {
218
+ const timestamps = sortedEntities
219
+ .map((e) => e.updated_at)
220
+ .filter((t) => t != null)
221
+ .map((t) => {
222
+ // Append 'Z' if not present to force UTC interpretation
223
+ const timestamp = String(t);
224
+ const hasZone = timestamp.endsWith("Z") ||
225
+ timestamp.includes("+") ||
226
+ /[+-]\d{2}:\d{2}$/.test(timestamp);
227
+ const utcTimestamp = hasZone
228
+ ? timestamp
229
+ : timestamp.replace(" ", "T") + "Z";
230
+ return new Date(utcTimestamp).getTime();
231
+ });
232
+ if (timestamps.length > 0) {
233
+ const newestTimestamp = Math.max(...timestamps);
234
+ const mtimeDate = new Date(newestTimestamp);
235
+ fs.utimesSync(filePath, mtimeDate, mtimeDate);
236
+ }
237
+ }
238
+ }
239
+ /**
240
+ * Update a single line in a JSONL file by entity ID
241
+ * If the entity doesn't exist, append it
242
+ * If it exists, replace the line
243
+ */
244
+ export async function updateJSONLLine(filePath, entity, idField = "id") {
245
+ const entityId = entity[idField];
246
+ if (!entityId) {
247
+ throw new Error(`Entity missing ${idField} field`);
248
+ }
249
+ // Read existing entities
250
+ const entities = await readJSONL(filePath, { skipErrors: true });
251
+ // Find and update or append
252
+ const index = entities.findIndex((e) => e[idField] === entityId);
253
+ if (index >= 0) {
254
+ // Replace existing
255
+ entities[index] = entity;
256
+ }
257
+ else {
258
+ // Append new
259
+ entities.push(entity);
260
+ }
261
+ // Write back
262
+ await writeJSONL(filePath, entities);
263
+ }
264
+ /**
265
+ * Update a single line in a JSONL file synchronously
266
+ */
267
+ export function updateJSONLLineSync(filePath, entity, idField = "id") {
268
+ const entityId = entity[idField];
269
+ if (!entityId) {
270
+ throw new Error(`Entity missing ${idField} field`);
271
+ }
272
+ // Read existing entities
273
+ const entities = readJSONLSync(filePath, { skipErrors: true });
274
+ // Find and update or append
275
+ const index = entities.findIndex((e) => e[idField] === entityId);
276
+ if (index >= 0) {
277
+ // Replace existing
278
+ entities[index] = entity;
279
+ }
280
+ else {
281
+ // Append new
282
+ entities.push(entity);
283
+ }
284
+ // Write back
285
+ writeJSONLSync(filePath, entities);
286
+ }
287
+ /**
288
+ * Delete an entity from a JSONL file by ID
289
+ */
290
+ export async function deleteJSONLLine(filePath, entityId, idField = "id") {
291
+ // Read existing entities
292
+ const entities = await readJSONL(filePath, { skipErrors: true });
293
+ // Filter out the entity
294
+ const initialLength = entities.length;
295
+ const filtered = entities.filter((e) => e[idField] !== entityId);
296
+ if (filtered.length === initialLength) {
297
+ return false; // Nothing deleted
298
+ }
299
+ // Write back
300
+ await writeJSONL(filePath, filtered);
301
+ return true;
302
+ }
303
+ /**
304
+ * Delete an entity from a JSONL file synchronously
305
+ */
306
+ export function deleteJSONLLineSync(filePath, entityId, idField = "id") {
307
+ // Read existing entities
308
+ const entities = readJSONLSync(filePath, { skipErrors: true });
309
+ // Filter out the entity
310
+ const initialLength = entities.length;
311
+ const filtered = entities.filter((e) => e[idField] !== entityId);
312
+ if (filtered.length === initialLength) {
313
+ return false; // Nothing deleted
314
+ }
315
+ // Write back
316
+ writeJSONLSync(filePath, filtered);
317
+ return true;
318
+ }
319
+ /**
320
+ * Get a single entity from a JSONL file by ID
321
+ */
322
+ export async function getJSONLEntity(filePath, entityId, idField = "id") {
323
+ const entities = await readJSONL(filePath, { skipErrors: true });
324
+ return entities.find((e) => e[idField] === entityId) ?? null;
325
+ }
326
+ /**
327
+ * Get a single entity from a JSONL file synchronously
328
+ */
329
+ export function getJSONLEntitySync(filePath, entityId, idField = "id") {
330
+ const entities = readJSONLSync(filePath, { skipErrors: true });
331
+ return entities.find((e) => e[idField] === entityId) ?? null;
332
+ }
333
+ //# sourceMappingURL=jsonl.js.map