@lwelliott/cortex-cli 1.0.4 → 1.0.6

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 (42) hide show
  1. package/README.md +2 -2
  2. package/dist/cli/formatters/markdown.js +7 -7
  3. package/dist/cli/formatters/markdown.js.map +1 -1
  4. package/dist/cli/formatters/table.js +10 -10
  5. package/dist/cli/formatters/table.js.map +1 -1
  6. package/dist/cli/index.js +4 -2
  7. package/dist/cli/index.js.map +1 -1
  8. package/dist/cli/task.d.ts.map +1 -1
  9. package/dist/cli/task.js +32 -4
  10. package/dist/cli/task.js.map +1 -1
  11. package/dist/db/generated/schema-types.d.ts +8 -8
  12. package/dist/db/generated/schema-types.js +4 -4
  13. package/dist/db/generated/schema-types.js.map +1 -1
  14. package/dist/db/schema.d.ts +1 -1
  15. package/dist/db/schema.d.ts.map +1 -1
  16. package/dist/db/schema.js +15 -1
  17. package/dist/db/schema.js.map +1 -1
  18. package/dist/models/relation.d.ts.map +1 -1
  19. package/dist/models/relation.js +81 -73
  20. package/dist/models/relation.js.map +1 -1
  21. package/dist/models/task.d.ts +4 -4
  22. package/dist/models/task.d.ts.map +1 -1
  23. package/dist/services/document-service.d.ts +3 -0
  24. package/dist/services/document-service.d.ts.map +1 -1
  25. package/dist/services/document-service.js +77 -76
  26. package/dist/services/document-service.js.map +1 -1
  27. package/dist/services/review-service.d.ts +47 -2
  28. package/dist/services/review-service.d.ts.map +1 -1
  29. package/dist/services/review-service.js +189 -27
  30. package/dist/services/review-service.js.map +1 -1
  31. package/dist/services/schema-migration-service.js +4 -4
  32. package/dist/services/schema-migration-service.js.map +1 -1
  33. package/dist/services/sprint.js +1 -1
  34. package/dist/services/task.d.ts +4 -4
  35. package/dist/services/task.d.ts.map +1 -1
  36. package/dist/services/task.js +18 -27
  37. package/dist/services/task.js.map +1 -1
  38. package/dist/utils/errors.d.ts +13 -1
  39. package/dist/utils/errors.d.ts.map +1 -1
  40. package/dist/utils/errors.js +28 -4
  41. package/dist/utils/errors.js.map +1 -1
  42. package/package.json +1 -1
package/dist/db/schema.js CHANGED
@@ -23,7 +23,7 @@ CREATE TABLE IF NOT EXISTS tasks (
23
23
  id TEXT NOT NULL,
24
24
  sprint_id TEXT NOT NULL REFERENCES sprints(id),
25
25
  parent_id TEXT,
26
- description TEXT NOT NULL,
26
+ content TEXT,
27
27
  task_type TEXT NOT NULL DEFAULT 'Feature'
28
28
  CHECK (task_type IN ('Feature','Bug','Chore')),
29
29
  priority TEXT NOT NULL DEFAULT 'P2'
@@ -786,6 +786,20 @@ exports.MIGRATIONS = [
786
786
  CREATE INDEX IF NOT EXISTS idx_tasks_sprint_id_id ON tasks(sprint_id, id);
787
787
  `,
788
788
  },
789
+ {
790
+ version: 14,
791
+ description: 'SAD-0040: Rename tasks.description→content column (add content, copy data, drop description)',
792
+ sql: `
793
+ -- Step 1: Add content column if it doesn't exist (idempotent via migration runner error handling)
794
+ ALTER TABLE tasks ADD COLUMN content TEXT;
795
+
796
+ -- Step 2: Copy description data to content where content is still null
797
+ UPDATE tasks SET content = description WHERE description IS NOT NULL AND content IS NULL;
798
+
799
+ -- Step 3: Drop description column
800
+ ALTER TABLE tasks DROP COLUMN description;
801
+ `,
802
+ },
789
803
  ];
790
804
  /** Current latest migration version */
791
805
  exports.LATEST_VERSION = exports.MIGRATIONS[exports.MIGRATIONS.length - 1].version;
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"relation.d.ts","sourceRoot":"","sources":["../../src/models/relation.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAe,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAmB1F;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAM7F;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAC5B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,QAAQ,CA6EV;AAsDD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAe9E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,oBAAoB,GAAG,QAAQ,EAAE,CA+B/F;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,YAAY,EAAE,CAEvE"}
1
+ {"version":3,"file":"relation.d.ts","sourceRoot":"","sources":["../../src/models/relation.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAe,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAoB1F;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAM7F;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAC5B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACnC,QAAQ,CAgFV;AAsDD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAkB9E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,oBAAoB,GAAG,QAAQ,EAAE,CA+B/F;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,GAAG,YAAY,EAAE,CAEvE"}
@@ -2,6 +2,7 @@
2
2
  // Relation model: CRUD operations for graph relations
3
3
  // MOD-010: Relations with constraint enforcement (AD-0017)
4
4
  // + MOD-008: Schema dependency
5
+ // AD-0006: Advisory lock wrapping for write operations
5
6
  Object.defineProperty(exports, "__esModule", { value: true });
6
7
  exports.getRelationType = getRelationType;
7
8
  exports.createRelation = createRelation;
@@ -9,6 +10,7 @@ exports.removeRelation = removeRelation;
9
10
  exports.queryRelations = queryRelations;
10
11
  exports.listRelationTypes = listRelationTypes;
11
12
  const retry_1 = require("../db/retry");
13
+ const locks_1 = require("../db/locks");
12
14
  const errors_1 = require("../utils/errors");
13
15
  /** Parse JSON field safely */
14
16
  function parseJson(raw, fallback) {
@@ -46,69 +48,72 @@ function getRelationType(db, name) {
46
48
  * 8. Insert inverse
47
49
  */
48
50
  function createRelation(db, fromId, relType, toId, properties) {
49
- return (0, retry_1.withTransaction)(db, () => {
50
- // 1. Self-relation check
51
- if (fromId === toId) {
52
- throw new errors_1.GraphSelfRelationError(fromId, relType);
53
- }
54
- // 2. Document existence (SAD-0035: entities table dropped, use documents)
55
- const fromDoc = db.prepare('SELECT id, type AS type_name FROM documents WHERE id = ?').get(fromId);
56
- if (!fromDoc)
57
- throw new errors_1.GraphEntityNotFoundError(fromId);
58
- const toDoc = db.prepare('SELECT id, type AS type_name FROM documents WHERE id = ?').get(toId);
59
- if (!toDoc)
60
- throw new errors_1.GraphEntityNotFoundError(toId);
61
- // 3. Relation type existence
62
- const rt = getRelationType(db, relType);
63
- if (!rt)
64
- throw new errors_1.GraphRelationTypeNotFoundError(relType);
65
- // 4. Type constraint check
66
- const fromTypes = parseJson(rt.from_types, []);
67
- const toTypes = parseJson(rt.to_types, []);
68
- if (fromTypes.length > 0 && !fromTypes.includes(fromDoc.type_name)) {
69
- throw new errors_1.GraphTypeConstraintError(relType, 'from', fromDoc.type_name, fromTypes);
70
- }
71
- if (toTypes.length > 0 && !toTypes.includes(toDoc.type_name)) {
72
- throw new errors_1.GraphTypeConstraintError(relType, 'to', toDoc.type_name, toTypes);
73
- }
74
- // 5. Cardinality constraint check
75
- enforceCardinality(db, rt, fromId, toId, relType);
76
- // 6. Duplicate check
77
- const existing = db.prepare('SELECT id FROM relations WHERE from_id = ? AND rel_type = ? AND to_id = ?').get(fromId, relType, toId);
78
- if (existing)
79
- throw new errors_1.GraphDuplicateRelationError(fromId, relType, toId);
80
- const now = new Date().toISOString();
81
- const propsJson = JSON.stringify(properties ?? {});
82
- // 7. Insert primary relation
83
- const result = db.prepare(`
84
- INSERT INTO relations (from_id, rel_type, to_id, properties, created_at, updated_at)
85
- VALUES (?, ?, ?, ?, ?, ?)
86
- `).run(fromId, relType, toId, propsJson, now, now);
87
- const relation = {
88
- id: Number(result.lastInsertRowid),
89
- from_id: fromId,
90
- rel_type: relType,
91
- to_id: toId,
92
- properties: propsJson,
93
- created_at: now,
94
- updated_at: now,
95
- };
96
- // 8. Insert inverse relation if defined
97
- if (rt.inverse_of) {
98
- const inverseRt = getRelationType(db, rt.inverse_of);
99
- if (inverseRt) {
100
- // Check cardinality for inverse too
101
- enforceCardinality(db, inverseRt, toId, fromId, rt.inverse_of);
102
- const existingInverse = db.prepare('SELECT id FROM relations WHERE from_id = ? AND rel_type = ? AND to_id = ?').get(toId, rt.inverse_of, fromId);
103
- if (!existingInverse) {
104
- db.prepare(`
105
- INSERT INTO relations (from_id, rel_type, to_id, properties, created_at, updated_at)
106
- VALUES (?, ?, ?, ?, ?, ?)
107
- `).run(toId, rt.inverse_of, fromId, propsJson, now, now);
51
+ const owner = (0, locks_1.generateLockOwner)();
52
+ return (0, locks_1.withLock)(db, { name: 'graph:mutations', owner }, () => {
53
+ return (0, retry_1.withTransaction)(db, () => {
54
+ // 1. Self-relation check
55
+ if (fromId === toId) {
56
+ throw new errors_1.GraphSelfRelationError(fromId, relType);
57
+ }
58
+ // 2. Document existence (SAD-0035: entities table dropped, use documents)
59
+ const fromDoc = db.prepare('SELECT id, type AS type_name FROM documents WHERE id = ?').get(fromId);
60
+ if (!fromDoc)
61
+ throw new errors_1.GraphEntityNotFoundError(fromId);
62
+ const toDoc = db.prepare('SELECT id, type AS type_name FROM documents WHERE id = ?').get(toId);
63
+ if (!toDoc)
64
+ throw new errors_1.GraphEntityNotFoundError(toId);
65
+ // 3. Relation type existence
66
+ const rt = getRelationType(db, relType);
67
+ if (!rt)
68
+ throw new errors_1.GraphRelationTypeNotFoundError(relType);
69
+ // 4. Type constraint check
70
+ const fromTypes = parseJson(rt.from_types, []);
71
+ const toTypes = parseJson(rt.to_types, []);
72
+ if (fromTypes.length > 0 && !fromTypes.includes(fromDoc.type_name)) {
73
+ throw new errors_1.GraphTypeConstraintError(relType, 'from', fromDoc.type_name, fromTypes);
74
+ }
75
+ if (toTypes.length > 0 && !toTypes.includes(toDoc.type_name)) {
76
+ throw new errors_1.GraphTypeConstraintError(relType, 'to', toDoc.type_name, toTypes);
77
+ }
78
+ // 5. Cardinality constraint check
79
+ enforceCardinality(db, rt, fromId, toId, relType);
80
+ // 6. Duplicate check
81
+ const existing = db.prepare('SELECT id FROM relations WHERE from_id = ? AND rel_type = ? AND to_id = ?').get(fromId, relType, toId);
82
+ if (existing)
83
+ throw new errors_1.GraphDuplicateRelationError(fromId, relType, toId);
84
+ const now = new Date().toISOString();
85
+ const propsJson = JSON.stringify(properties ?? {});
86
+ // 7. Insert primary relation
87
+ const result = db.prepare(`
88
+ INSERT INTO relations (from_id, rel_type, to_id, properties, created_at, updated_at)
89
+ VALUES (?, ?, ?, ?, ?, ?)
90
+ `).run(fromId, relType, toId, propsJson, now, now);
91
+ const relation = {
92
+ id: Number(result.lastInsertRowid),
93
+ from_id: fromId,
94
+ rel_type: relType,
95
+ to_id: toId,
96
+ properties: propsJson,
97
+ created_at: now,
98
+ updated_at: now,
99
+ };
100
+ // 8. Insert inverse relation if defined
101
+ if (rt.inverse_of) {
102
+ const inverseRt = getRelationType(db, rt.inverse_of);
103
+ if (inverseRt) {
104
+ // Check cardinality for inverse too
105
+ enforceCardinality(db, inverseRt, toId, fromId, rt.inverse_of);
106
+ const existingInverse = db.prepare('SELECT id FROM relations WHERE from_id = ? AND rel_type = ? AND to_id = ?').get(toId, rt.inverse_of, fromId);
107
+ if (!existingInverse) {
108
+ db.prepare(`
109
+ INSERT INTO relations (from_id, rel_type, to_id, properties, created_at, updated_at)
110
+ VALUES (?, ?, ?, ?, ?, ?)
111
+ `).run(toId, rt.inverse_of, fromId, propsJson, now, now);
112
+ }
108
113
  }
109
114
  }
110
- }
111
- return relation;
115
+ return relation;
116
+ });
112
117
  });
113
118
  }
114
119
  /**
@@ -152,18 +157,21 @@ function enforceCardinality(db, rt, fromId, toId, relType) {
152
157
  * Also removes any inverse relation.
153
158
  */
154
159
  function removeRelation(db, relationId) {
155
- (0, retry_1.withTransaction)(db, () => {
156
- const rel = db.prepare('SELECT from_id, rel_type, to_id FROM relations WHERE id = ?')
157
- .get(relationId);
158
- if (!rel)
159
- throw new errors_1.GraphRelationNotFoundError(relationId);
160
- db.prepare('DELETE FROM relations WHERE id = ?').run(relationId);
161
- // Remove inverse if defined
162
- const rt = getRelationType(db, rel.rel_type);
163
- if (rt?.inverse_of) {
164
- db.prepare('DELETE FROM relations WHERE from_id = ? AND rel_type = ? AND to_id = ?')
165
- .run(rel.to_id, rt.inverse_of, rel.from_id);
166
- }
160
+ const owner = (0, locks_1.generateLockOwner)();
161
+ (0, locks_1.withLock)(db, { name: 'graph:mutations', owner }, () => {
162
+ (0, retry_1.withTransaction)(db, () => {
163
+ const rel = db.prepare('SELECT from_id, rel_type, to_id FROM relations WHERE id = ?')
164
+ .get(relationId);
165
+ if (!rel)
166
+ throw new errors_1.GraphRelationNotFoundError(relationId);
167
+ db.prepare('DELETE FROM relations WHERE id = ?').run(relationId);
168
+ // Remove inverse if defined
169
+ const rt = getRelationType(db, rel.rel_type);
170
+ if (rt?.inverse_of) {
171
+ db.prepare('DELETE FROM relations WHERE from_id = ? AND rel_type = ? AND to_id = ?')
172
+ .run(rel.to_id, rt.inverse_of, rel.from_id);
173
+ }
174
+ });
167
175
  });
168
176
  }
169
177
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"relation.js","sourceRoot":"","sources":["../../src/models/relation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"relation.js","sourceRoot":"","sources":["../../src/models/relation.ts"],"names":[],"mappings":"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"}
@@ -4,7 +4,7 @@ export interface Task {
4
4
  id: string;
5
5
  sprint_id: string;
6
6
  parent_id: string | null;
7
- description: string;
7
+ content: string | null;
8
8
  task_type: TaskType;
9
9
  priority: TaskPriority;
10
10
  owner: RoleName;
@@ -28,7 +28,7 @@ export interface TaskResult {
28
28
  id: string;
29
29
  sprint_id: string;
30
30
  parent_id: string | null;
31
- description: string;
31
+ content: string | null;
32
32
  task_type: TaskType;
33
33
  priority: TaskPriority;
34
34
  owner: RoleName;
@@ -40,7 +40,7 @@ export interface TaskResult {
40
40
  /** Detailed task information for `task show` */
41
41
  export interface TaskDetail extends Task {
42
42
  sprint_name: string | null;
43
- parent_description: string | null;
43
+ parent_content: string | null;
44
44
  }
45
45
  /** Options for task creation */
46
46
  export interface TaskAddOptions {
@@ -60,7 +60,7 @@ export interface TaskMoveContext {
60
60
  }
61
61
  /** Fields that can be updated on a task (metadata only — no stage/owner/sprint) */
62
62
  export interface TaskUpdateFields {
63
- description?: string;
63
+ content?: string;
64
64
  task_type?: TaskType;
65
65
  priority?: TaskPriority;
66
66
  points?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../../src/models/task.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAExF,gCAAgC;AAChC,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,QAAQ,CAAC;IACpB,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,QAAQ,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,8BAA8B;AAC9B,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,QAAQ,CAAC;IACpB,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,QAAQ,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,gDAAgD;AAChD,MAAM,WAAW,UAAW,SAAQ,IAAI;IACtC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,gCAAgC;AAChC,MAAM,WAAW,cAAc;IAC7B,oFAAoF;IACpF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,QAAQ,CAAC;IACrB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED,4BAA4B;AAC5B,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,mFAAmF;AACnF,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,QAAQ,CAAC;IACrB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kFAAkF;IAClF,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B"}
1
+ {"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../../src/models/task.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAExF,gCAAgC;AAChC,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,QAAQ,CAAC;IACpB,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,QAAQ,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,8BAA8B;AAC9B,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,EAAE,QAAQ,CAAC;IACpB,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,QAAQ,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,gDAAgD;AAChD,MAAM,WAAW,UAAW,SAAQ,IAAI;IACtC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,gCAAgC;AAChC,MAAM,WAAW,cAAc;IAC7B,oFAAoF;IACpF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,QAAQ,CAAC;IACrB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED,4BAA4B;AAC5B,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,mFAAmF;AACnF,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,QAAQ,CAAC;IACrB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kFAAkF;IAClF,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B"}
@@ -2,6 +2,7 @@ import type Database from 'better-sqlite3';
2
2
  import type { Document, DocumentDetail, DocumentRegisterOptions, DocumentUpdateFields, SearchResult, ListOptions, SearchOptions } from '../models/document';
3
3
  /**
4
4
  * Register a new document.
5
+ * Wrapped with doc:global advisory lock (AD-0006) for multi-process coordination.
5
6
  */
6
7
  export declare function registerDocument(db: Database.Database, id: string, type: string, title: string, opts?: DocumentRegisterOptions): Document;
7
8
  /**
@@ -25,6 +26,7 @@ export declare function getDocument(db: Database.Database, id: string): Document
25
26
  export declare function showDocument(db: Database.Database, id: string): DocumentDetail;
26
27
  /**
27
28
  * Update document metadata.
29
+ * Wrapped with doc:global advisory lock (AD-0006) for multi-process coordination.
28
30
  * --meta replaces entirely (not merge), per spec.
29
31
  *
30
32
  * MOD-021: When fields.type changes the document type, the old entity is deleted
@@ -35,6 +37,7 @@ export declare function showDocument(db: Database.Database, id: string): Documen
35
37
  export declare function updateDocument(db: Database.Database, id: string, fields: DocumentUpdateFields): Document;
36
38
  /**
37
39
  * Remove a document registration.
40
+ * Wrapped with doc:global advisory lock (AD-0006) for multi-process coordination.
38
41
  *
39
42
  * Deletion ordering per SAD-0035 (3-step sequence after entities table drop):
40
43
  * Step 1: Delete relations (outgoing and incoming) referencing the document
@@ -1 +1 @@
1
- {"version":3,"file":"document-service.d.ts","sourceRoot":"","sources":["../../src/services/document-service.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAG3C,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAmC5J;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,uBAAuB,GAC7B,QAAQ,CAmEV;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,IAAI,CAAC,EAAE,WAAW,GACjB,QAAQ,EAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAkDhC;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,QAAQ,CAIvE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,cAAc,CAkB9E;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,oBAAoB,GAC3B,QAAQ,CAmEV;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAetE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,aAAa,GACnB,YAAY,EAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAgIpC"}
1
+ {"version":3,"file":"document-service.d.ts","sourceRoot":"","sources":["../../src/services/document-service.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAG3C,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAoC5J;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,uBAAuB,GAC7B,QAAQ,CA8DV;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,IAAI,CAAC,EAAE,WAAW,GACjB,QAAQ,EAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAkDhC;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,QAAQ,CAIvE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,cAAc,CAkB9E;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,oBAAoB,GAC3B,QAAQ,CAiEV;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAgBtE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,aAAa,GACnB,YAAY,EAAE,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAgIpC"}
@@ -3,6 +3,7 @@
3
3
  // SAD-0003: MOD-012 Document Registry & Content
4
4
  // AD-0018: FTS5 with trigger-based index
5
5
  // AD-0019: Dual-mode document storage
6
+ // AD-0006: Advisory lock wrapping for multi-step write operations
6
7
  // SAD-0035: Entity auto-sync removed — entities table dropped
7
8
  Object.defineProperty(exports, "__esModule", { value: true });
8
9
  exports.registerDocument = registerDocument;
@@ -16,6 +17,7 @@ const crypto_1 = require("crypto");
16
17
  const fs_1 = require("fs");
17
18
  const errors_1 = require("../utils/errors");
18
19
  const retry_1 = require("../db/retry");
20
+ const locks_1 = require("../db/locks");
19
21
  // ─── Order-by validation ───
20
22
  const VALID_ORDER_FIELDS = ['id', 'type', 'title', 'created', 'updated'];
21
23
  function parseOrderBy(raw) {
@@ -41,6 +43,7 @@ function sha256(content) {
41
43
  // ─── Public API ───
42
44
  /**
43
45
  * Register a new document.
46
+ * Wrapped with doc:global advisory lock (AD-0006) for multi-process coordination.
44
47
  */
45
48
  function registerDocument(db, id, type, title, opts) {
46
49
  if (!id || !id.trim())
@@ -49,25 +52,13 @@ function registerDocument(db, id, type, title, opts) {
49
52
  throw new errors_1.DocumentMissingFieldError('type');
50
53
  if (!title || !title.trim())
51
54
  throw new errors_1.DocumentMissingFieldError('title');
52
- // Check duplicate
53
- const existing = db.prepare('SELECT id FROM documents WHERE id = ?').get(id);
54
- if (existing)
55
- throw new errors_1.DocumentDuplicateError(id);
56
- // Pre-transaction doc type validation gate (FS-SS-012-0011, SAD-0027 §5)
57
- // builtin:3.0: doc type IS entity type name (no mapping needed)
58
55
  // Pre-transaction SRC storage enforcement (FS-SS-029-0001 v2 VR-001/VR-002)
59
56
  // SRC documents must use filesystem storage; DB storage via --content-file is rejected
60
57
  if (type === 'SRC' && (opts?.content || opts?.contentFile)) {
61
58
  throw new errors_1.DocSrcStorageError();
62
59
  }
63
- // FS-SS-012-0001 v4 VR-004: When content is provided (via --content-file),
64
- // content_storage defaults to 'db'. Otherwise defaults to 'filesystem'.
65
- const storage = opts?.contentStorage ?? ((opts?.content || opts?.contentFile) ? 'db' : 'filesystem');
66
- const metadata = opts?.metadata ? JSON.stringify(opts.metadata) : '{}';
67
- const now = new Date().toISOString();
60
+ // Pre-transaction file read (fail fast before lock acquisition)
68
61
  // Handle content: compute hash and load content from file or direct input
69
- // Content is ALWAYS stored in document_contents to enable FTS5 indexing,
70
- // regardless of whether content_storage is 'db' or 'filesystem'.
71
62
  let contentHash = null;
72
63
  let contentValue = null;
73
64
  let contentFilePath = null;
@@ -87,19 +78,27 @@ function registerDocument(db, id, type, title, opts) {
87
78
  throw new errors_1.DocumentFileError(opts.contentFile, msg);
88
79
  }
89
80
  }
90
- // Determine the filesystem path to store in the documents table.
91
- // Prefer the explicit --path option; fall back to --content-file path.
81
+ const storage = opts?.contentStorage ?? ((opts?.content || opts?.contentFile) ? 'db' : 'filesystem');
82
+ const metadata = opts?.metadata ? JSON.stringify(opts.metadata) : '{}';
92
83
  const storedPath = opts?.path ?? contentFilePath ?? null;
93
- // Insert document and content (FK: document_contents → documents)
94
- // SAD-0035: Entity auto-creation removed entities table dropped
95
- (0, retry_1.withTransaction)(db, () => {
96
- db.prepare(`INSERT INTO documents (id, type, title, path, content_hash, content_storage, metadata, created_at, updated_at)
97
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, type, title, storedPath, contentHash, storage, metadata, now, now);
98
- if (contentValue !== null) {
99
- db.prepare(`INSERT INTO document_contents (document_id, content, content_hash, updated_at) VALUES (?, ?, ?, ?)`).run(id, contentValue, contentHash, now);
100
- }
84
+ const owner = (0, locks_1.generateLockOwner)();
85
+ return (0, locks_1.withLock)(db, { name: 'doc:global', owner }, () => {
86
+ // Check duplicate inside lock to prevent TOCTOU races
87
+ const existing = db.prepare('SELECT id FROM documents WHERE id = ?').get(id);
88
+ if (existing)
89
+ throw new errors_1.DocumentDuplicateError(id);
90
+ const now = new Date().toISOString();
91
+ // Insert document and content (FK: document_contents → documents)
92
+ // SAD-0035: Entity auto-creation removed — entities table dropped
93
+ (0, retry_1.withTransaction)(db, () => {
94
+ db.prepare(`INSERT INTO documents (id, type, title, path, content_hash, content_storage, metadata, created_at, updated_at)
95
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, type, title, storedPath, contentHash, storage, metadata, now, now);
96
+ if (contentValue !== null) {
97
+ db.prepare(`INSERT INTO document_contents (document_id, content, content_hash, updated_at) VALUES (?, ?, ?, ?)`).run(id, contentValue, contentHash, now);
98
+ }
99
+ });
100
+ return getDocument(db, id);
101
101
  });
102
- return getDocument(db, id);
103
102
  }
104
103
  /**
105
104
  * List documents with optional filters, pagination, sorting, and count-only support.
@@ -190,6 +189,7 @@ function showDocument(db, id) {
190
189
  }
191
190
  /**
192
191
  * Update document metadata.
192
+ * Wrapped with doc:global advisory lock (AD-0006) for multi-process coordination.
193
193
  * --meta replaces entirely (not merge), per spec.
194
194
  *
195
195
  * MOD-021: When fields.type changes the document type, the old entity is deleted
@@ -198,29 +198,10 @@ function showDocument(db, id) {
198
198
  * atomic transaction per FS-SS-021-0004.
199
199
  */
200
200
  function updateDocument(db, id, fields) {
201
+ // Pre-lock validation
201
202
  const doc = getDocument(db, id);
202
- const now = new Date().toISOString();
203
- const sets = ['updated_at = ?'];
204
- const params = [now];
205
- if (fields.title !== undefined) {
206
- sets.push('title = ?');
207
- params.push(fields.title);
208
- }
209
- if (fields.type !== undefined) {
210
- sets.push('type = ?');
211
- params.push(fields.type);
212
- }
213
- if (fields.metadata !== undefined) {
214
- sets.push('metadata = ?');
215
- params.push(JSON.stringify(fields.metadata));
216
- }
217
- if (fields.content_storage !== undefined) {
218
- sets.push('content_storage = ?');
219
- params.push(fields.content_storage);
220
- }
221
- // Handle content update
203
+ // Handle content file read before lock acquisition (fail fast)
222
204
  let newContent;
223
- let contentHash;
224
205
  if (fields.contentFile) {
225
206
  try {
226
207
  newContent = (0, fs_1.readFileSync)(fields.contentFile, 'utf-8');
@@ -233,39 +214,58 @@ function updateDocument(db, id, fields) {
233
214
  else if (fields.content !== undefined) {
234
215
  newContent = fields.content;
235
216
  }
236
- if (newContent !== undefined) {
237
- contentHash = sha256(newContent);
238
- sets.push('content_hash = ?');
239
- params.push(contentHash);
240
- }
241
- // SAD-0035: Entity sync on type change removed — entities table dropped
242
217
  // content_storage switch validation (FR-URD-G001-0001 M6)
243
- // Switching from filesystem to db without providing content creates an
244
- // inconsistency: the document_contents table has no authoritative copy.
245
218
  if (fields.content_storage !== undefined && fields.content_storage !== doc.content_storage) {
246
219
  if (fields.content_storage === 'db' && doc.content_storage === 'filesystem' && newContent === undefined && !fields.contentFile) {
247
220
  throw new errors_1.DocumentMissingFieldError('content');
248
221
  }
249
222
  }
250
- params.push(id);
251
- // Single atomic transaction: content upsert + document update
252
- // SAD-0035: Entity sync removed — entities table dropped
253
- (0, retry_1.withTransaction)(db, () => {
254
- // Step 1: Content upsert
255
- // Content is ALWAYS written to document_contents to enable FTS5 indexing
256
- // and maintain content_hash consistency, regardless of storage type.
223
+ const owner = (0, locks_1.generateLockOwner)();
224
+ return (0, locks_1.withLock)(db, { name: 'doc:global', owner }, () => {
225
+ const now = new Date().toISOString();
226
+ const sets = ['updated_at = ?'];
227
+ const params = [now];
228
+ if (fields.title !== undefined) {
229
+ sets.push('title = ?');
230
+ params.push(fields.title);
231
+ }
232
+ if (fields.type !== undefined) {
233
+ sets.push('type = ?');
234
+ params.push(fields.type);
235
+ }
236
+ if (fields.metadata !== undefined) {
237
+ sets.push('metadata = ?');
238
+ params.push(JSON.stringify(fields.metadata));
239
+ }
240
+ if (fields.content_storage !== undefined) {
241
+ sets.push('content_storage = ?');
242
+ params.push(fields.content_storage);
243
+ }
244
+ let contentHash;
257
245
  if (newContent !== undefined) {
258
- db.prepare(`INSERT INTO document_contents (document_id, content, content_hash, updated_at)
259
- VALUES (?, ?, ?, ?)
260
- ON CONFLICT(document_id) DO UPDATE SET content = excluded.content, content_hash = excluded.content_hash, updated_at = excluded.updated_at`).run(id, newContent, contentHash, now);
246
+ contentHash = sha256(newContent);
247
+ sets.push('content_hash = ?');
248
+ params.push(contentHash);
261
249
  }
262
- // Step 2: Document row UPDATE
263
- db.prepare(`UPDATE documents SET ${sets.join(', ')} WHERE id = ?`).run(...params);
250
+ params.push(id);
251
+ // Single atomic transaction: content upsert + document update
252
+ // SAD-0035: Entity sync removed — entities table dropped
253
+ (0, retry_1.withTransaction)(db, () => {
254
+ // Step 1: Content upsert
255
+ if (newContent !== undefined) {
256
+ db.prepare(`INSERT INTO document_contents (document_id, content, content_hash, updated_at)
257
+ VALUES (?, ?, ?, ?)
258
+ ON CONFLICT(document_id) DO UPDATE SET content = excluded.content, content_hash = excluded.content_hash, updated_at = excluded.updated_at`).run(id, newContent, contentHash, now);
259
+ }
260
+ // Step 2: Document row UPDATE
261
+ db.prepare(`UPDATE documents SET ${sets.join(', ')} WHERE id = ?`).run(...params);
262
+ });
263
+ return getDocument(db, id);
264
264
  });
265
- return getDocument(db, id);
266
265
  }
267
266
  /**
268
267
  * Remove a document registration.
268
+ * Wrapped with doc:global advisory lock (AD-0006) for multi-process coordination.
269
269
  *
270
270
  * Deletion ordering per SAD-0035 (3-step sequence after entities table drop):
271
271
  * Step 1: Delete relations (outgoing and incoming) referencing the document
@@ -276,16 +276,17 @@ function updateDocument(db, id, fields) {
276
276
  * Content is always deleted unconditionally per AD-0028 — there is no soft-delete option.
277
277
  */
278
278
  function removeDocument(db, id) {
279
- getDocument(db, id); // verify exists
280
- (0, retry_1.withTransaction)(db, () => {
281
- // Step 1: Delete all relations referencing this document (from_id OR to_id)
282
- db.prepare('DELETE FROM relations WHERE from_id = ? OR to_id = ?').run(id, id);
283
- // Step 2: Delete document_contents unconditionally per AD-0028
284
- // FK constraint (document_contents.document_id documents.id) requires
285
- // content deletion before the document row is removed.
286
- db.prepare('DELETE FROM document_contents WHERE document_id = ?').run(id);
287
- // Step 3: Delete document row
288
- db.prepare('DELETE FROM documents WHERE id = ?').run(id);
279
+ getDocument(db, id); // verify exists before lock
280
+ const owner = (0, locks_1.generateLockOwner)();
281
+ (0, locks_1.withLock)(db, { name: 'doc:global', owner }, () => {
282
+ (0, retry_1.withTransaction)(db, () => {
283
+ // Step 1: Delete all relations referencing this document (from_id OR to_id)
284
+ db.prepare('DELETE FROM relations WHERE from_id = ? OR to_id = ?').run(id, id);
285
+ // Step 2: Delete document_contents unconditionally per AD-0028
286
+ db.prepare('DELETE FROM document_contents WHERE document_id = ?').run(id);
287
+ // Step 3: Delete document row
288
+ db.prepare('DELETE FROM documents WHERE id = ?').run(id);
289
+ });
289
290
  });
290
291
  }
291
292
  /**