@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.
- package/dist/cli/feedback-commands.d.ts.map +1 -0
- package/dist/cli/feedback-commands.js +274 -0
- package/dist/cli/feedback-commands.js.map +1 -0
- package/dist/cli/init-commands.d.ts.map +1 -0
- package/dist/cli/init-commands.js +148 -0
- package/dist/cli/init-commands.js.map +1 -0
- package/dist/cli/issue-commands.d.ts.map +1 -0
- package/dist/cli/issue-commands.js +310 -0
- package/dist/cli/issue-commands.js.map +1 -0
- package/dist/cli/query-commands.d.ts.map +1 -0
- package/dist/cli/query-commands.js +61 -0
- package/dist/cli/query-commands.js.map +1 -0
- package/dist/cli/reference-commands.d.ts.map +1 -0
- package/dist/cli/reference-commands.js +136 -0
- package/dist/cli/reference-commands.js.map +1 -0
- package/dist/cli/relationship-commands.d.ts.map +1 -0
- package/dist/cli/relationship-commands.js +76 -0
- package/dist/cli/relationship-commands.js.map +1 -0
- package/dist/cli/server-commands.d.ts.map +1 -0
- package/dist/cli/server-commands.js +99 -0
- package/dist/cli/server-commands.js.map +1 -0
- package/dist/cli/spec-commands.d.ts.map +1 -0
- package/dist/cli/spec-commands.js +321 -0
- package/dist/cli/spec-commands.js.map +1 -0
- package/dist/cli/status-commands.d.ts.map +1 -0
- package/dist/cli/status-commands.js +131 -0
- package/dist/cli/status-commands.js.map +1 -0
- package/dist/cli/sync-commands.d.ts.map +1 -0
- package/dist/cli/sync-commands.js +416 -0
- package/dist/cli/sync-commands.js.map +1 -0
- package/dist/cli/update-commands.d.ts.map +1 -0
- package/dist/cli/update-commands.js +78 -0
- package/dist/cli/update-commands.js.map +1 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +425 -195
- package/dist/cli.js.map +1 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +54 -0
- package/dist/db.js.map +1 -0
- package/dist/export.d.ts.map +1 -0
- package/dist/export.js +195 -0
- package/dist/export.js.map +1 -0
- package/dist/filename-generator.d.ts.map +1 -0
- package/dist/filename-generator.js +93 -0
- package/dist/filename-generator.js.map +1 -0
- package/dist/id-generator.d.ts.map +1 -0
- package/dist/id-generator.js +123 -0
- package/dist/id-generator.js.map +1 -0
- package/dist/import.d.ts.map +1 -0
- package/dist/import.js +608 -0
- package/dist/import.js.map +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -189
- package/dist/index.js.map +1 -0
- package/dist/jsonl.d.ts.map +1 -0
- package/dist/jsonl.js +333 -0
- package/dist/jsonl.js.map +1 -0
- package/dist/markdown.d.ts.map +1 -0
- package/dist/markdown.js +357 -0
- package/dist/markdown.js.map +1 -0
- package/dist/migrations.d.ts.map +1 -0
- package/dist/migrations.js +57 -0
- package/dist/migrations.js.map +1 -0
- package/dist/operations/events.d.ts.map +1 -0
- package/dist/operations/events.js +108 -0
- package/dist/operations/events.js.map +1 -0
- package/dist/operations/feedback-anchors.d.ts.map +1 -0
- package/dist/operations/feedback-anchors.js +444 -0
- package/dist/operations/feedback-anchors.js.map +1 -0
- package/dist/operations/feedback.d.ts.map +1 -0
- package/dist/operations/feedback.js +234 -0
- package/dist/operations/feedback.js.map +1 -0
- package/dist/operations/index.d.ts.map +1 -0
- package/dist/operations/index.js +10 -0
- package/dist/operations/index.js.map +1 -0
- package/dist/operations/issues.d.ts.map +1 -0
- package/dist/operations/issues.js +411 -0
- package/dist/operations/issues.js.map +1 -0
- package/dist/operations/references.d.ts.map +1 -0
- package/dist/operations/references.js +117 -0
- package/dist/operations/references.js.map +1 -0
- package/dist/operations/relationships.d.ts.map +1 -0
- package/dist/operations/relationships.js +236 -0
- package/dist/operations/relationships.js.map +1 -0
- package/dist/operations/specs.d.ts.map +1 -0
- package/dist/operations/specs.js +290 -0
- package/dist/operations/specs.js.map +1 -0
- package/dist/operations/tags.d.ts.map +1 -0
- package/dist/operations/tags.js +127 -0
- package/dist/operations/tags.js.map +1 -0
- package/dist/operations/transactions.d.ts.map +1 -0
- package/dist/operations/transactions.js +111 -0
- package/dist/operations/transactions.js.map +1 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +442 -0
- package/dist/sync.js.map +1 -0
- package/dist/test-schema.d.ts.map +1 -0
- package/dist/test-schema.js +46 -0
- package/dist/test-schema.js.map +1 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/update-checker.d.ts.map +1 -0
- package/dist/update-checker.js +151 -0
- package/dist/update-checker.js.map +1 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +23 -0
- package/dist/version.js.map +1 -0
- package/dist/watcher.d.ts.map +1 -0
- package/dist/watcher.js +438 -0
- package/dist/watcher.js.map +1 -0
- package/package.json +4 -7
package/dist/index.js
CHANGED
|
@@ -1,189 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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"&>(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
|