sqlew 4.1.2 → 4.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +59 -0
- package/README.md +268 -409
- package/assets/claude-md-snippets/plan-mode-integration.md +36 -10
- package/assets/config.example.toml +120 -282
- package/assets/sample-skills/sqlew-decision-format/SKILL.md +73 -0
- package/dist/cli/hooks/check-completion.d.ts.map +1 -1
- package/dist/cli/hooks/check-completion.js +90 -2
- package/dist/cli/hooks/check-completion.js.map +1 -1
- package/dist/cli/hooks/init-hooks.d.ts.map +1 -1
- package/dist/cli/hooks/init-hooks.js +97 -5
- package/dist/cli/hooks/init-hooks.js.map +1 -1
- package/dist/cli/hooks/on-enter-plan.d.ts +22 -0
- package/dist/cli/hooks/on-enter-plan.d.ts.map +1 -0
- package/dist/cli/hooks/on-enter-plan.js +51 -0
- package/dist/cli/hooks/on-enter-plan.js.map +1 -0
- package/dist/cli/hooks/on-exit-plan.d.ts +20 -0
- package/dist/cli/hooks/on-exit-plan.d.ts.map +1 -0
- package/dist/cli/hooks/on-exit-plan.js +66 -0
- package/dist/cli/hooks/on-exit-plan.js.map +1 -0
- package/dist/cli/hooks/on-stop.d.ts +19 -0
- package/dist/cli/hooks/on-stop.d.ts.map +1 -0
- package/dist/cli/hooks/on-stop.js +152 -0
- package/dist/cli/hooks/on-stop.js.map +1 -0
- package/dist/cli/hooks/on-subagent-stop.d.ts +20 -0
- package/dist/cli/hooks/on-subagent-stop.d.ts.map +1 -0
- package/dist/cli/hooks/on-subagent-stop.js +94 -0
- package/dist/cli/hooks/on-subagent-stop.js.map +1 -0
- package/dist/cli/hooks/plan-pattern-extractor.d.ts +87 -0
- package/dist/cli/hooks/plan-pattern-extractor.d.ts.map +1 -0
- package/dist/cli/hooks/plan-pattern-extractor.js +218 -0
- package/dist/cli/hooks/plan-pattern-extractor.js.map +1 -0
- package/dist/cli/hooks/plan-processor.d.ts +43 -0
- package/dist/cli/hooks/plan-processor.d.ts.map +1 -0
- package/dist/cli/hooks/plan-processor.js +115 -0
- package/dist/cli/hooks/plan-processor.js.map +1 -0
- package/dist/cli/hooks/plan-toml-parser.d.ts +42 -0
- package/dist/cli/hooks/plan-toml-parser.d.ts.map +1 -0
- package/dist/cli/hooks/plan-toml-parser.js +178 -0
- package/dist/cli/hooks/plan-toml-parser.js.map +1 -0
- package/dist/cli/hooks/save.d.ts +7 -9
- package/dist/cli/hooks/save.d.ts.map +1 -1
- package/dist/cli/hooks/save.js +50 -25
- package/dist/cli/hooks/save.js.map +1 -1
- package/dist/cli/hooks/stdin-parser.d.ts +66 -2
- package/dist/cli/hooks/stdin-parser.d.ts.map +1 -1
- package/dist/cli/hooks/stdin-parser.js +57 -2
- package/dist/cli/hooks/stdin-parser.js.map +1 -1
- package/dist/cli/hooks/suggest.d.ts +8 -4
- package/dist/cli/hooks/suggest.d.ts.map +1 -1
- package/dist/cli/hooks/suggest.js +21 -123
- package/dist/cli/hooks/suggest.js.map +1 -1
- package/dist/cli/hooks/track-plan.d.ts +8 -1
- package/dist/cli/hooks/track-plan.d.ts.map +1 -1
- package/dist/cli/hooks/track-plan.js +64 -66
- package/dist/cli/hooks/track-plan.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +107 -6
- package/dist/cli.js.map +1 -1
- package/dist/config/global-config.d.ts +90 -0
- package/dist/config/global-config.d.ts.map +1 -1
- package/dist/config/global-config.js +86 -1
- package/dist/config/global-config.js.map +1 -1
- package/dist/database/initialization/init.js +3 -3
- package/dist/database/initialization/init.js.map +1 -1
- package/dist/database/migrations/v4/20260102204000_v4_fix_decision_set_example.d.ts +15 -0
- package/dist/database/migrations/v4/20260102204000_v4_fix_decision_set_example.d.ts.map +1 -0
- package/dist/database/migrations/v4/20260102204000_v4_fix_decision_set_example.js +74 -0
- package/dist/database/migrations/v4/20260102204000_v4_fix_decision_set_example.js.map +1 -0
- package/dist/index.js +8 -4
- package/dist/index.js.map +1 -1
- package/dist/init-skills.d.ts +12 -3
- package/dist/init-skills.d.ts.map +1 -1
- package/dist/init-skills.js +96 -24
- package/dist/init-skills.js.map +1 -1
- package/dist/knexfile.d.ts.map +1 -1
- package/dist/knexfile.js +16 -12
- package/dist/knexfile.js.map +1 -1
- package/dist/server/setup.js +5 -5
- package/dist/server/setup.js.map +1 -1
- package/dist/server/tool-handlers.d.ts.map +1 -1
- package/dist/server/tool-handlers.js +7 -1
- package/dist/server/tool-handlers.js.map +1 -1
- package/dist/server/tool-registry.js +1 -1
- package/dist/server/tool-registry.js.map +1 -1
- package/dist/tests/feature/decision/truncate.test.d.ts +8 -0
- package/dist/tests/feature/decision/truncate.test.d.ts.map +1 -0
- package/dist/tests/feature/decision/truncate.test.js +192 -0
- package/dist/tests/feature/decision/truncate.test.js.map +1 -0
- package/dist/tests/unit/config/plan-toml-cache.test.d.ts +9 -0
- package/dist/tests/unit/config/plan-toml-cache.test.d.ts.map +1 -0
- package/dist/tests/unit/config/plan-toml-cache.test.js +230 -0
- package/dist/tests/unit/config/plan-toml-cache.test.js.map +1 -0
- package/dist/tests/unit/hooks/plan-toml-parser.test.d.ts +10 -0
- package/dist/tests/unit/hooks/plan-toml-parser.test.d.ts.map +1 -0
- package/dist/tests/unit/hooks/plan-toml-parser.test.js +316 -0
- package/dist/tests/unit/hooks/plan-toml-parser.test.js.map +1 -0
- package/dist/tools/constraints/actions/activate.d.ts +46 -0
- package/dist/tools/constraints/actions/activate.d.ts.map +1 -0
- package/dist/tools/constraints/actions/activate.js +105 -0
- package/dist/tools/constraints/actions/activate.js.map +1 -0
- package/dist/tools/constraints/actions/add.d.ts.map +1 -1
- package/dist/tools/constraints/actions/add.js +30 -13
- package/dist/tools/constraints/actions/add.js.map +1 -1
- package/dist/tools/constraints/actions/deactivate.d.ts.map +1 -1
- package/dist/tools/constraints/actions/deactivate.js +7 -4
- package/dist/tools/constraints/actions/deactivate.js.map +1 -1
- package/dist/tools/constraints/actions/get.d.ts.map +1 -1
- package/dist/tools/constraints/actions/get.js +10 -7
- package/dist/tools/constraints/actions/get.js.map +1 -1
- package/dist/tools/constraints/actions/suggest-pending.d.ts +41 -0
- package/dist/tools/constraints/actions/suggest-pending.d.ts.map +1 -0
- package/dist/tools/constraints/actions/suggest-pending.js +71 -0
- package/dist/tools/constraints/actions/suggest-pending.js.map +1 -0
- package/dist/tools/constraints/help/example.d.ts.map +1 -1
- package/dist/tools/constraints/help/example.js +65 -1
- package/dist/tools/constraints/help/example.js.map +1 -1
- package/dist/tools/constraints/help/help.d.ts.map +1 -1
- package/dist/tools/constraints/help/help.js +10 -5
- package/dist/tools/constraints/help/help.js.map +1 -1
- package/dist/tools/constraints/index.d.ts +2 -0
- package/dist/tools/constraints/index.d.ts.map +1 -1
- package/dist/tools/constraints/index.js +2 -0
- package/dist/tools/constraints/index.js.map +1 -1
- package/dist/tools/context/actions/add-context.d.ts.map +1 -1
- package/dist/tools/context/actions/add-context.js +13 -6
- package/dist/tools/context/actions/add-context.js.map +1 -1
- package/dist/tools/context/actions/has-updates.d.ts.map +1 -1
- package/dist/tools/context/actions/has-updates.js +0 -4
- package/dist/tools/context/actions/has-updates.js.map +1 -1
- package/dist/tools/context/actions/list-contexts.d.ts.map +1 -1
- package/dist/tools/context/actions/list-contexts.js +12 -7
- package/dist/tools/context/actions/list-contexts.js.map +1 -1
- package/dist/tools/context/actions/list.d.ts.map +1 -1
- package/dist/tools/context/actions/list.js +8 -0
- package/dist/tools/context/actions/list.js.map +1 -1
- package/dist/tools/context/actions/search-advanced.d.ts.map +1 -1
- package/dist/tools/context/actions/search-advanced.js +41 -27
- package/dist/tools/context/actions/search-advanced.js.map +1 -1
- package/dist/tools/context/actions/search-layer.d.ts.map +1 -1
- package/dist/tools/context/actions/search-layer.js +8 -0
- package/dist/tools/context/actions/search-layer.js.map +1 -1
- package/dist/tools/context/actions/search-tags.d.ts.map +1 -1
- package/dist/tools/context/actions/search-tags.js +8 -0
- package/dist/tools/context/actions/search-tags.js.map +1 -1
- package/dist/tools/files/actions/check-lock.d.ts.map +1 -1
- package/dist/tools/files/actions/check-lock.js +9 -3
- package/dist/tools/files/actions/check-lock.js.map +1 -1
- package/dist/tools/files/actions/get.d.ts.map +1 -1
- package/dist/tools/files/actions/get.js +18 -13
- package/dist/tools/files/actions/get.js.map +1 -1
- package/dist/tools/files/actions/record-batch.d.ts.map +1 -1
- package/dist/tools/files/actions/record-batch.js +11 -6
- package/dist/tools/files/actions/record-batch.js.map +1 -1
- package/dist/tools/files/actions/record.d.ts.map +1 -1
- package/dist/tools/files/actions/record.js +8 -2
- package/dist/tools/files/actions/record.js.map +1 -1
- package/dist/tools/files/help/example.d.ts.map +1 -1
- package/dist/tools/files/help/example.js +11 -0
- package/dist/tools/files/help/example.js.map +1 -1
- package/dist/tools/files/help/help.d.ts.map +1 -1
- package/dist/tools/files/help/help.js +11 -0
- package/dist/tools/files/help/help.js.map +1 -1
- package/dist/tools/suggest/actions/by-context.d.ts.map +1 -1
- package/dist/tools/suggest/actions/by-context.js +5 -15
- package/dist/tools/suggest/actions/by-context.js.map +1 -1
- package/dist/tools/suggest/actions/by-key.d.ts.map +1 -1
- package/dist/tools/suggest/actions/by-key.js +5 -15
- package/dist/tools/suggest/actions/by-key.js.map +1 -1
- package/dist/tools/suggest/actions/by-tags.d.ts.map +1 -1
- package/dist/tools/suggest/actions/by-tags.js +5 -15
- package/dist/tools/suggest/actions/by-tags.js.map +1 -1
- package/dist/tools/suggest/actions/constraint-by-context.d.ts +1 -1
- package/dist/tools/suggest/actions/constraint-by-context.d.ts.map +1 -1
- package/dist/tools/suggest/actions/constraint-by-context.js +9 -16
- package/dist/tools/suggest/actions/constraint-by-context.js.map +1 -1
- package/dist/tools/suggest/actions/constraint-by-tags.d.ts +1 -1
- package/dist/tools/suggest/actions/constraint-by-tags.d.ts.map +1 -1
- package/dist/tools/suggest/actions/constraint-by-tags.js +11 -17
- package/dist/tools/suggest/actions/constraint-by-tags.js.map +1 -1
- package/dist/tools/suggest/actions/constraint-by-text.d.ts +1 -1
- package/dist/tools/suggest/actions/constraint-by-text.d.ts.map +1 -1
- package/dist/tools/suggest/actions/constraint-by-text.js +6 -15
- package/dist/tools/suggest/actions/constraint-by-text.js.map +1 -1
- package/dist/types/actions.d.ts +1 -1
- package/dist/types/actions.d.ts.map +1 -1
- package/dist/types.d.ts +9 -230
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/action-specs/constraint-specs.d.ts +1 -1
- package/dist/utils/action-specs/constraint-specs.d.ts.map +1 -1
- package/dist/utils/action-specs/constraint-specs.js +22 -5
- package/dist/utils/action-specs/constraint-specs.js.map +1 -1
- package/dist/utils/action-specs/decision-specs.d.ts.map +1 -1
- package/dist/utils/action-specs/decision-specs.js +11 -10
- package/dist/utils/action-specs/decision-specs.js.map +1 -1
- package/dist/utils/action-specs/file-specs.js +4 -4
- package/dist/utils/action-specs/file-specs.js.map +1 -1
- package/dist/utils/hook-queue.d.ts +43 -3
- package/dist/utils/hook-queue.d.ts.map +1 -1
- package/dist/utils/hook-queue.js +326 -32
- package/dist/utils/hook-queue.js.map +1 -1
- package/dist/utils/param-normalizer.d.ts +52 -0
- package/dist/utils/param-normalizer.d.ts.map +1 -0
- package/dist/utils/param-normalizer.js +70 -0
- package/dist/utils/param-normalizer.js.map +1 -0
- package/dist/utils/parameter-validator.d.ts.map +1 -1
- package/dist/utils/parameter-validator.js +2 -0
- package/dist/utils/parameter-validator.js.map +1 -1
- package/dist/utils/suggest-helpers.d.ts +82 -0
- package/dist/utils/suggest-helpers.d.ts.map +1 -0
- package/dist/utils/suggest-helpers.js +93 -0
- package/dist/utils/suggest-helpers.js.map +1 -0
- package/dist/utils/text-truncate.d.ts +13 -0
- package/dist/utils/text-truncate.d.ts.map +1 -0
- package/dist/utils/text-truncate.js +18 -0
- package/dist/utils/text-truncate.js.map +1 -0
- package/dist/utils/validators.d.ts +1 -1
- package/dist/utils/validators.d.ts.map +1 -1
- package/dist/utils/validators.js +1 -1
- package/dist/utils/validators.js.map +1 -1
- package/dist/watcher/base-watcher.d.ts.map +1 -1
- package/dist/watcher/base-watcher.js +4 -3
- package/dist/watcher/base-watcher.js.map +1 -1
- package/dist/watcher/file-watcher.d.ts.map +1 -1
- package/dist/watcher/file-watcher.js +5 -1
- package/dist/watcher/file-watcher.js.map +1 -1
- package/dist/watcher/queue-watcher.d.ts +12 -1
- package/dist/watcher/queue-watcher.d.ts.map +1 -1
- package/dist/watcher/queue-watcher.js +92 -12
- package/dist/watcher/queue-watcher.js.map +1 -1
- package/docs/ADR_CONCEPTS.md +4 -0
- package/docs/HOOKS_GUIDE.md +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan TOML Parser Unit Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for extracting and parsing [[decision]] and [[constraint]]
|
|
5
|
+
* from ```toml blocks in plan markdown files.
|
|
6
|
+
*
|
|
7
|
+
* @since v4.2.0
|
|
8
|
+
*/
|
|
9
|
+
import { describe, it } from 'node:test';
|
|
10
|
+
import assert from 'node:assert';
|
|
11
|
+
import { extractTomlBlocks, parseTomlBlock, parsePlanToml, } from '../../../cli/hooks/plan-toml-parser.js';
|
|
12
|
+
describe('plan-toml-parser', () => {
|
|
13
|
+
describe('extractTomlBlocks', () => {
|
|
14
|
+
it('should extract single toml block', () => {
|
|
15
|
+
const content = `
|
|
16
|
+
# Plan
|
|
17
|
+
|
|
18
|
+
Some text here.
|
|
19
|
+
|
|
20
|
+
\`\`\`toml
|
|
21
|
+
[[decision]]
|
|
22
|
+
key = "test"
|
|
23
|
+
value = "value"
|
|
24
|
+
\`\`\`
|
|
25
|
+
|
|
26
|
+
More text.
|
|
27
|
+
`;
|
|
28
|
+
const blocks = extractTomlBlocks(content);
|
|
29
|
+
assert.strictEqual(blocks.length, 1);
|
|
30
|
+
assert.ok(blocks[0].includes('[[decision]]'));
|
|
31
|
+
});
|
|
32
|
+
it('should extract multiple toml blocks', () => {
|
|
33
|
+
const content = `
|
|
34
|
+
\`\`\`toml
|
|
35
|
+
[[decision]]
|
|
36
|
+
key = "first"
|
|
37
|
+
value = "one"
|
|
38
|
+
\`\`\`
|
|
39
|
+
|
|
40
|
+
Some text between.
|
|
41
|
+
|
|
42
|
+
\`\`\`toml
|
|
43
|
+
[[decision]]
|
|
44
|
+
key = "second"
|
|
45
|
+
value = "two"
|
|
46
|
+
\`\`\`
|
|
47
|
+
`;
|
|
48
|
+
const blocks = extractTomlBlocks(content);
|
|
49
|
+
assert.strictEqual(blocks.length, 2);
|
|
50
|
+
});
|
|
51
|
+
it('should handle empty content', () => {
|
|
52
|
+
const blocks = extractTomlBlocks('');
|
|
53
|
+
assert.strictEqual(blocks.length, 0);
|
|
54
|
+
});
|
|
55
|
+
it('should ignore non-toml code blocks', () => {
|
|
56
|
+
const content = `
|
|
57
|
+
\`\`\`javascript
|
|
58
|
+
const x = 1;
|
|
59
|
+
\`\`\`
|
|
60
|
+
|
|
61
|
+
\`\`\`toml
|
|
62
|
+
[[decision]]
|
|
63
|
+
key = "test"
|
|
64
|
+
value = "value"
|
|
65
|
+
\`\`\`
|
|
66
|
+
|
|
67
|
+
\`\`\`python
|
|
68
|
+
print("hello")
|
|
69
|
+
\`\`\`
|
|
70
|
+
`;
|
|
71
|
+
const blocks = extractTomlBlocks(content);
|
|
72
|
+
assert.strictEqual(blocks.length, 1);
|
|
73
|
+
});
|
|
74
|
+
it('should be case-insensitive for toml tag', () => {
|
|
75
|
+
const content = `
|
|
76
|
+
\`\`\`TOML
|
|
77
|
+
[[decision]]
|
|
78
|
+
key = "upper"
|
|
79
|
+
value = "case"
|
|
80
|
+
\`\`\`
|
|
81
|
+
`;
|
|
82
|
+
const blocks = extractTomlBlocks(content);
|
|
83
|
+
assert.strictEqual(blocks.length, 1);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
describe('parseTomlBlock - decisions', () => {
|
|
87
|
+
it('should parse decision with required fields only', () => {
|
|
88
|
+
const toml = `
|
|
89
|
+
[[decision]]
|
|
90
|
+
key = "api/auth"
|
|
91
|
+
value = "Use JWT tokens"
|
|
92
|
+
`;
|
|
93
|
+
const result = parseTomlBlock(toml);
|
|
94
|
+
assert.strictEqual(result.decisions.length, 1);
|
|
95
|
+
assert.strictEqual(result.decisions[0].key, 'api/auth');
|
|
96
|
+
assert.strictEqual(result.decisions[0].value, 'Use JWT tokens');
|
|
97
|
+
});
|
|
98
|
+
it('should parse decision with all optional fields', () => {
|
|
99
|
+
const toml = `
|
|
100
|
+
[[decision]]
|
|
101
|
+
key = "database/orm"
|
|
102
|
+
value = "Knex query builder"
|
|
103
|
+
status = "active"
|
|
104
|
+
layer = "data"
|
|
105
|
+
tags = ["database", "architecture"]
|
|
106
|
+
rationale = "Explicit SQL control"
|
|
107
|
+
alternatives = ["TypeORM", "Prisma"]
|
|
108
|
+
tradeoffs = "Learning curve vs flexibility"
|
|
109
|
+
`;
|
|
110
|
+
const result = parseTomlBlock(toml);
|
|
111
|
+
assert.strictEqual(result.decisions.length, 1);
|
|
112
|
+
const d = result.decisions[0];
|
|
113
|
+
assert.strictEqual(d.key, 'database/orm');
|
|
114
|
+
assert.strictEqual(d.value, 'Knex query builder');
|
|
115
|
+
assert.strictEqual(d.status, 'active');
|
|
116
|
+
assert.strictEqual(d.layer, 'data');
|
|
117
|
+
assert.deepStrictEqual(d.tags, ['database', 'architecture']);
|
|
118
|
+
assert.strictEqual(d.rationale, 'Explicit SQL control');
|
|
119
|
+
assert.deepStrictEqual(d.alternatives, ['TypeORM', 'Prisma']);
|
|
120
|
+
assert.strictEqual(d.tradeoffs, 'Learning curve vs flexibility');
|
|
121
|
+
});
|
|
122
|
+
it('should parse multiple decisions', () => {
|
|
123
|
+
const toml = `
|
|
124
|
+
[[decision]]
|
|
125
|
+
key = "first"
|
|
126
|
+
value = "First decision"
|
|
127
|
+
|
|
128
|
+
[[decision]]
|
|
129
|
+
key = "second"
|
|
130
|
+
value = "Second decision"
|
|
131
|
+
|
|
132
|
+
[[decision]]
|
|
133
|
+
key = "third"
|
|
134
|
+
value = "Third decision"
|
|
135
|
+
`;
|
|
136
|
+
const result = parseTomlBlock(toml);
|
|
137
|
+
assert.strictEqual(result.decisions.length, 3);
|
|
138
|
+
});
|
|
139
|
+
it('should skip invalid decisions (missing required fields)', () => {
|
|
140
|
+
const toml = `
|
|
141
|
+
[[decision]]
|
|
142
|
+
key = "valid"
|
|
143
|
+
value = "This is valid"
|
|
144
|
+
|
|
145
|
+
[[decision]]
|
|
146
|
+
key = "missing-value"
|
|
147
|
+
|
|
148
|
+
[[decision]]
|
|
149
|
+
value = "missing-key"
|
|
150
|
+
`;
|
|
151
|
+
const result = parseTomlBlock(toml);
|
|
152
|
+
assert.strictEqual(result.decisions.length, 1);
|
|
153
|
+
assert.strictEqual(result.decisions[0].key, 'valid');
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
describe('parseTomlBlock - constraints', () => {
|
|
157
|
+
it('should parse constraint with required fields only', () => {
|
|
158
|
+
const toml = `
|
|
159
|
+
[[constraint]]
|
|
160
|
+
text = "All API endpoints must validate JWT"
|
|
161
|
+
category = "security"
|
|
162
|
+
`;
|
|
163
|
+
const result = parseTomlBlock(toml);
|
|
164
|
+
assert.strictEqual(result.constraints.length, 1);
|
|
165
|
+
assert.strictEqual(result.constraints[0].text, 'All API endpoints must validate JWT');
|
|
166
|
+
assert.strictEqual(result.constraints[0].category, 'security');
|
|
167
|
+
});
|
|
168
|
+
it('should parse constraint with all optional fields', () => {
|
|
169
|
+
const toml = `
|
|
170
|
+
[[constraint]]
|
|
171
|
+
text = "No raw SQL strings"
|
|
172
|
+
category = "code-style"
|
|
173
|
+
priority = "high"
|
|
174
|
+
layer = "data"
|
|
175
|
+
tags = ["database", "security"]
|
|
176
|
+
rationale = "Prevent SQL injection"
|
|
177
|
+
`;
|
|
178
|
+
const result = parseTomlBlock(toml);
|
|
179
|
+
assert.strictEqual(result.constraints.length, 1);
|
|
180
|
+
const c = result.constraints[0];
|
|
181
|
+
assert.strictEqual(c.text, 'No raw SQL strings');
|
|
182
|
+
assert.strictEqual(c.category, 'code-style');
|
|
183
|
+
assert.strictEqual(c.priority, 'high');
|
|
184
|
+
assert.strictEqual(c.layer, 'data');
|
|
185
|
+
assert.deepStrictEqual(c.tags, ['database', 'security']);
|
|
186
|
+
assert.strictEqual(c.rationale, 'Prevent SQL injection');
|
|
187
|
+
});
|
|
188
|
+
it('should parse multiple constraints', () => {
|
|
189
|
+
const toml = `
|
|
190
|
+
[[constraint]]
|
|
191
|
+
text = "First rule"
|
|
192
|
+
category = "security"
|
|
193
|
+
|
|
194
|
+
[[constraint]]
|
|
195
|
+
text = "Second rule"
|
|
196
|
+
category = "performance"
|
|
197
|
+
`;
|
|
198
|
+
const result = parseTomlBlock(toml);
|
|
199
|
+
assert.strictEqual(result.constraints.length, 2);
|
|
200
|
+
});
|
|
201
|
+
it('should skip invalid constraints (missing required fields)', () => {
|
|
202
|
+
const toml = `
|
|
203
|
+
[[constraint]]
|
|
204
|
+
text = "Valid constraint"
|
|
205
|
+
category = "security"
|
|
206
|
+
|
|
207
|
+
[[constraint]]
|
|
208
|
+
text = "Missing category"
|
|
209
|
+
|
|
210
|
+
[[constraint]]
|
|
211
|
+
category = "missing-text"
|
|
212
|
+
`;
|
|
213
|
+
const result = parseTomlBlock(toml);
|
|
214
|
+
assert.strictEqual(result.constraints.length, 1);
|
|
215
|
+
assert.strictEqual(result.constraints[0].text, 'Valid constraint');
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
describe('parseTomlBlock - mixed decisions and constraints', () => {
|
|
219
|
+
it('should parse both decisions and constraints from same block', () => {
|
|
220
|
+
const toml = `
|
|
221
|
+
[[decision]]
|
|
222
|
+
key = "auth/method"
|
|
223
|
+
value = "JWT with refresh tokens"
|
|
224
|
+
layer = "business"
|
|
225
|
+
|
|
226
|
+
[[constraint]]
|
|
227
|
+
text = "All endpoints must validate JWT"
|
|
228
|
+
category = "security"
|
|
229
|
+
priority = "critical"
|
|
230
|
+
|
|
231
|
+
[[decision]]
|
|
232
|
+
key = "database/engine"
|
|
233
|
+
value = "PostgreSQL 15"
|
|
234
|
+
layer = "data"
|
|
235
|
+
|
|
236
|
+
[[constraint]]
|
|
237
|
+
text = "Use parameterized queries only"
|
|
238
|
+
category = "security"
|
|
239
|
+
`;
|
|
240
|
+
const result = parseTomlBlock(toml);
|
|
241
|
+
assert.strictEqual(result.decisions.length, 2);
|
|
242
|
+
assert.strictEqual(result.constraints.length, 2);
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
describe('parsePlanToml - end-to-end', () => {
|
|
246
|
+
it('should parse complete plan markdown with toml blocks', () => {
|
|
247
|
+
const content = `
|
|
248
|
+
# Implementation Plan
|
|
249
|
+
|
|
250
|
+
## Overview
|
|
251
|
+
This is a plan for implementing authentication.
|
|
252
|
+
|
|
253
|
+
## Architectural Decisions & Constraints
|
|
254
|
+
|
|
255
|
+
\`\`\`toml
|
|
256
|
+
[[decision]]
|
|
257
|
+
key = "auth/provider"
|
|
258
|
+
value = "Custom JWT implementation"
|
|
259
|
+
status = "active"
|
|
260
|
+
layer = "business"
|
|
261
|
+
tags = ["auth", "security"]
|
|
262
|
+
rationale = "Full control over token lifecycle"
|
|
263
|
+
|
|
264
|
+
[[constraint]]
|
|
265
|
+
text = "JWT tokens must expire within 15 minutes"
|
|
266
|
+
category = "security"
|
|
267
|
+
priority = "critical"
|
|
268
|
+
layer = "business"
|
|
269
|
+
\`\`\`
|
|
270
|
+
|
|
271
|
+
## Implementation Steps
|
|
272
|
+
|
|
273
|
+
1. Create token service
|
|
274
|
+
2. Add middleware
|
|
275
|
+
|
|
276
|
+
## Additional Constraints
|
|
277
|
+
|
|
278
|
+
\`\`\`toml
|
|
279
|
+
[[constraint]]
|
|
280
|
+
text = "Store refresh tokens in HTTP-only cookies"
|
|
281
|
+
category = "security"
|
|
282
|
+
priority = "high"
|
|
283
|
+
\`\`\`
|
|
284
|
+
`;
|
|
285
|
+
const result = parsePlanToml(content);
|
|
286
|
+
assert.strictEqual(result.decisions.length, 1);
|
|
287
|
+
assert.strictEqual(result.constraints.length, 2);
|
|
288
|
+
assert.strictEqual(result.decisions[0].key, 'auth/provider');
|
|
289
|
+
assert.strictEqual(result.constraints[0].text, 'JWT tokens must expire within 15 minutes');
|
|
290
|
+
assert.strictEqual(result.constraints[1].text, 'Store refresh tokens in HTTP-only cookies');
|
|
291
|
+
});
|
|
292
|
+
it('should handle plan with no toml blocks', () => {
|
|
293
|
+
const content = `
|
|
294
|
+
# Simple Plan
|
|
295
|
+
|
|
296
|
+
Just some text without any TOML.
|
|
297
|
+
`;
|
|
298
|
+
const result = parsePlanToml(content);
|
|
299
|
+
assert.strictEqual(result.decisions.length, 0);
|
|
300
|
+
assert.strictEqual(result.constraints.length, 0);
|
|
301
|
+
});
|
|
302
|
+
it('should handle malformed toml gracefully', () => {
|
|
303
|
+
const content = `
|
|
304
|
+
\`\`\`toml
|
|
305
|
+
this is not valid toml
|
|
306
|
+
{ broken json
|
|
307
|
+
\`\`\`
|
|
308
|
+
`;
|
|
309
|
+
// Should not throw, just return empty
|
|
310
|
+
const result = parsePlanToml(content);
|
|
311
|
+
assert.strictEqual(result.decisions.length, 0);
|
|
312
|
+
assert.strictEqual(result.constraints.length, 0);
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
//# sourceMappingURL=plan-toml-parser.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-toml-parser.test.js","sourceRoot":"","sources":["../../../../src/tests/unit/hooks/plan-toml-parser.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,aAAa,GACd,MAAM,wCAAwC,CAAC;AAEhD,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,MAAM,OAAO,GAAG;;;;;;;;;;;;CAYrB,CAAC;YACI,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;YAC1C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACrC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;YAC7C,MAAM,OAAO,GAAG;;;;;;;;;;;;;;CAcrB,CAAC;YACI,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;YAC1C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;YACrC,MAAM,MAAM,GAAG,iBAAiB,CAAC,EAAE,CAAC,CAAC;YACrC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;YAC5C,MAAM,OAAO,GAAG;;;;;;;;;;;;;;CAcrB,CAAC;YACI,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;YAC1C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;YACjD,MAAM,OAAO,GAAG;;;;;;CAMrB,CAAC;YACI,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;YAC1C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;QAC1C,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;YACzD,MAAM,IAAI,GAAG;;;;CAIlB,CAAC;YACI,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;YACxD,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;YACxD,MAAM,IAAI,GAAG;;;;;;;;;;CAUlB,CAAC;YACI,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YAC9B,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;YAC1C,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,EAAE,oBAAoB,CAAC,CAAC;YAClD,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YACvC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YACpC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC,CAAC;YAC7D,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,EAAE,sBAAsB,CAAC,CAAC;YACxD,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;YAC9D,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,EAAE,+BAA+B,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,IAAI,GAAG;;;;;;;;;;;;CAYlB,CAAC;YACI,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;YACjE,MAAM,IAAI,GAAG;;;;;;;;;;CAUlB,CAAC;YACI,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;QAC5C,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;YAC3D,MAAM,IAAI,GAAG;;;;CAIlB,CAAC;YACI,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACjD,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,qCAAqC,CAAC,CAAC;YACtF,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACjE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;YAC1D,MAAM,IAAI,GAAG;;;;;;;;CAQlB,CAAC;YACI,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACjD,MAAM,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;YAChC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;YACjD,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;YAC7C,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YACvC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YACpC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;YACzD,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,EAAE,uBAAuB,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;YAC3C,MAAM,IAAI,GAAG;;;;;;;;CAQlB,CAAC;YACI,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;YACnE,MAAM,IAAI,GAAG;;;;;;;;;;CAUlB,CAAC;YACI,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACjD,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;QACrE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAChE,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;YACrE,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;CAmBlB,CAAC;YACI,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;QAC1C,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;YAC9D,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqCrB,CAAC;YACI,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;YACtC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACjD,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;YAC7D,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,0CAA0C,CAAC,CAAC;YAC3F,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,2CAA2C,CAAC,CAAC;QAC9F,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;YAChD,MAAM,OAAO,GAAG;;;;CAIrB,CAAC;YACI,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;YACtC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;YACjD,MAAM,OAAO,GAAG;;;;;CAKrB,CAAC;YACI,sCAAsC;YACtC,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;YACtC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Activate constraints (by tag or by ID)
|
|
3
|
+
*
|
|
4
|
+
* - activateConstraintsByTag: Bulk activate by tag (for plan-based workflow)
|
|
5
|
+
* - activateConstraint: Single constraint by ID (MCP action)
|
|
6
|
+
*
|
|
7
|
+
* @since v4.2.1
|
|
8
|
+
*/
|
|
9
|
+
import { DatabaseAdapter } from '../../../adapters/index.js';
|
|
10
|
+
/**
|
|
11
|
+
* Activate constraints by tag response
|
|
12
|
+
*/
|
|
13
|
+
export interface ActivateConstraintsResponse {
|
|
14
|
+
success: boolean;
|
|
15
|
+
activated_count: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Activate constraint by ID response
|
|
19
|
+
*/
|
|
20
|
+
export interface ActivateConstraintByIdResponse {
|
|
21
|
+
success: boolean;
|
|
22
|
+
constraint_id: number;
|
|
23
|
+
message: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Activate all constraints matching a specific tag
|
|
27
|
+
*
|
|
28
|
+
* Used by queue-watcher to activate constraints when implementation starts.
|
|
29
|
+
* The tag typically contains the plan_id short form (8 chars).
|
|
30
|
+
*
|
|
31
|
+
* @param tag - Tag to match (e.g., plan_id short form)
|
|
32
|
+
* @param adapter - Optional database adapter (for testing)
|
|
33
|
+
* @returns Number of constraints activated
|
|
34
|
+
*/
|
|
35
|
+
export declare function activateConstraintsByTag(tag: string, adapter?: DatabaseAdapter): Promise<ActivateConstraintsResponse>;
|
|
36
|
+
/**
|
|
37
|
+
* Activate a single constraint by ID
|
|
38
|
+
*
|
|
39
|
+
* @param params - Parameters containing constraint_id
|
|
40
|
+
* @param adapter - Optional database adapter (for testing)
|
|
41
|
+
* @returns Success response with constraint ID
|
|
42
|
+
*/
|
|
43
|
+
export declare function activateConstraint(params: {
|
|
44
|
+
constraint_id: number;
|
|
45
|
+
}, adapter?: DatabaseAdapter): Promise<ActivateConstraintByIdResponse>;
|
|
46
|
+
//# sourceMappingURL=activate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activate.d.ts","sourceRoot":"","sources":["../../../../src/tools/constraints/actions/activate.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAO7D;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC7C,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;GASG;AACH,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,2BAA2B,CAAC,CAqCtC;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,EACjC,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,8BAA8B,CAAC,CA6CzC"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Activate constraints (by tag or by ID)
|
|
3
|
+
*
|
|
4
|
+
* - activateConstraintsByTag: Bulk activate by tag (for plan-based workflow)
|
|
5
|
+
* - activateConstraint: Single constraint by ID (MCP action)
|
|
6
|
+
*
|
|
7
|
+
* @since v4.2.1
|
|
8
|
+
*/
|
|
9
|
+
import { getAdapter } from '../../../database.js';
|
|
10
|
+
import { getProjectContext } from '../../../utils/project-context.js';
|
|
11
|
+
import { normalizeParams, CONSTRAINT_ALIASES } from '../../../utils/param-normalizer.js';
|
|
12
|
+
import connectionManager from '../../../utils/connection-manager.js';
|
|
13
|
+
import { SQLITE_TRUE } from '../../../constants.js';
|
|
14
|
+
/**
|
|
15
|
+
* Activate all constraints matching a specific tag
|
|
16
|
+
*
|
|
17
|
+
* Used by queue-watcher to activate constraints when implementation starts.
|
|
18
|
+
* The tag typically contains the plan_id short form (8 chars).
|
|
19
|
+
*
|
|
20
|
+
* @param tag - Tag to match (e.g., plan_id short form)
|
|
21
|
+
* @param adapter - Optional database adapter (for testing)
|
|
22
|
+
* @returns Number of constraints activated
|
|
23
|
+
*/
|
|
24
|
+
export async function activateConstraintsByTag(tag, adapter) {
|
|
25
|
+
const actualAdapter = adapter ?? getAdapter();
|
|
26
|
+
const knex = actualAdapter.getKnex();
|
|
27
|
+
try {
|
|
28
|
+
return await connectionManager.executeWithRetry(async () => {
|
|
29
|
+
const projectId = getProjectContext().getProjectId();
|
|
30
|
+
// Find constraints with matching tag that are inactive
|
|
31
|
+
const constraintIds = await knex('v4_constraints as c')
|
|
32
|
+
.join('v4_constraint_tags as ct', 'c.id', 'ct.constraint_id')
|
|
33
|
+
.join('v4_tags as t', 'ct.tag_id', 't.id')
|
|
34
|
+
.where('c.project_id', projectId)
|
|
35
|
+
.where('c.active', 0)
|
|
36
|
+
.where('t.name', tag)
|
|
37
|
+
.select('c.id')
|
|
38
|
+
.then(rows => rows.map(r => r.id));
|
|
39
|
+
if (constraintIds.length === 0) {
|
|
40
|
+
return { success: true, activated_count: 0 };
|
|
41
|
+
}
|
|
42
|
+
// Activate all matching constraints
|
|
43
|
+
await knex('v4_constraints')
|
|
44
|
+
.whereIn('id', constraintIds)
|
|
45
|
+
.where('project_id', projectId)
|
|
46
|
+
.update({ active: SQLITE_TRUE });
|
|
47
|
+
return {
|
|
48
|
+
success: true,
|
|
49
|
+
activated_count: constraintIds.length,
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
55
|
+
throw new Error(`Failed to activate constraints: ${message}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Activate a single constraint by ID
|
|
60
|
+
*
|
|
61
|
+
* @param params - Parameters containing constraint_id
|
|
62
|
+
* @param adapter - Optional database adapter (for testing)
|
|
63
|
+
* @returns Success response with constraint ID
|
|
64
|
+
*/
|
|
65
|
+
export async function activateConstraint(params, adapter) {
|
|
66
|
+
const actualAdapter = adapter ?? getAdapter();
|
|
67
|
+
const knex = actualAdapter.getKnex();
|
|
68
|
+
// Normalize aliases: id → constraint_id
|
|
69
|
+
const normalizedParams = normalizeParams(params, CONSTRAINT_ALIASES);
|
|
70
|
+
try {
|
|
71
|
+
return await connectionManager.executeWithRetry(async () => {
|
|
72
|
+
const projectId = getProjectContext().getProjectId();
|
|
73
|
+
// Check if constraint exists
|
|
74
|
+
const constraint = await knex('v4_constraints')
|
|
75
|
+
.where('id', normalizedParams.constraint_id)
|
|
76
|
+
.where('project_id', projectId)
|
|
77
|
+
.first();
|
|
78
|
+
if (!constraint) {
|
|
79
|
+
throw new Error(`Constraint not found: ${normalizedParams.constraint_id}`);
|
|
80
|
+
}
|
|
81
|
+
if (constraint.active === 1) {
|
|
82
|
+
return {
|
|
83
|
+
success: true,
|
|
84
|
+
constraint_id: normalizedParams.constraint_id,
|
|
85
|
+
message: 'Constraint already active',
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
// Activate the constraint
|
|
89
|
+
await knex('v4_constraints')
|
|
90
|
+
.where('id', normalizedParams.constraint_id)
|
|
91
|
+
.where('project_id', projectId)
|
|
92
|
+
.update({ active: SQLITE_TRUE });
|
|
93
|
+
return {
|
|
94
|
+
success: true,
|
|
95
|
+
constraint_id: normalizedParams.constraint_id,
|
|
96
|
+
message: 'Constraint activated',
|
|
97
|
+
};
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
102
|
+
throw new Error(`Failed to activate constraint: ${message}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=activate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activate.js","sourceRoot":"","sources":["../../../../src/tools/constraints/actions/activate.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../../../src/tools/constraints/actions/add.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../../../src/tools/constraints/actions/add.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAmB7D,OAAO,KAAK,EACV,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,aAAa,CAAC;AAErB;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,mBAAmB,EAC3B,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,qBAAqB,CAAC,CA+FhC"}
|
|
@@ -6,6 +6,7 @@ import { getAdapter, getLayerId, getOrCreateTag, getOrCreateCategoryId } from '.
|
|
|
6
6
|
import { STRING_TO_PRIORITY, DEFAULT_PRIORITY, SQLITE_TRUE, STANDARD_LAYERS } from '../../../constants.js';
|
|
7
7
|
import { validateCategory, validatePriority } from '../../../utils/validators.js';
|
|
8
8
|
import { validateActionParams } from '../../../utils/parameter-validator.js';
|
|
9
|
+
import { normalizeParams, CONSTRAINT_ALIASES } from '../../../utils/param-normalizer.js';
|
|
9
10
|
import { parseStringArray } from '../../../utils/param-parser.js';
|
|
10
11
|
import { getProjectContext } from '../../../utils/project-context.js';
|
|
11
12
|
import connectionManager from '../../../utils/connection-manager.js';
|
|
@@ -18,50 +19,65 @@ import connectionManager from '../../../utils/connection-manager.js';
|
|
|
18
19
|
*/
|
|
19
20
|
export async function addConstraint(params, adapter) {
|
|
20
21
|
const actualAdapter = adapter ?? getAdapter();
|
|
22
|
+
// Normalize aliases: text → constraint_text
|
|
23
|
+
const normalizedParams = normalizeParams(params, CONSTRAINT_ALIASES);
|
|
21
24
|
try {
|
|
22
25
|
return await connectionManager.executeWithRetry(async () => {
|
|
23
26
|
// Fail-fast project_id validation (Constraint #29)
|
|
24
27
|
const projectId = getProjectContext().getProjectId();
|
|
25
28
|
// Validate parameters
|
|
26
|
-
validateActionParams('constraint', 'add',
|
|
29
|
+
validateActionParams('constraint', 'add', normalizedParams);
|
|
27
30
|
// Validate category
|
|
28
|
-
validateCategory(
|
|
31
|
+
validateCategory(normalizedParams.category);
|
|
29
32
|
// Validate priority if provided
|
|
30
|
-
const priorityStr =
|
|
33
|
+
const priorityStr = normalizedParams.priority || 'medium';
|
|
31
34
|
validatePriority(priorityStr);
|
|
32
35
|
const priority = STRING_TO_PRIORITY[priorityStr] || DEFAULT_PRIORITY;
|
|
33
36
|
// Validate and get layer ID if provided
|
|
34
37
|
let layerId = null;
|
|
35
|
-
if (
|
|
36
|
-
if (!STANDARD_LAYERS.includes(
|
|
38
|
+
if (normalizedParams.layer) {
|
|
39
|
+
if (!STANDARD_LAYERS.includes(normalizedParams.layer)) {
|
|
37
40
|
throw new Error(`Invalid layer. Must be one of: ${STANDARD_LAYERS.join(', ')}`);
|
|
38
41
|
}
|
|
39
|
-
layerId = await getLayerId(actualAdapter,
|
|
42
|
+
layerId = await getLayerId(actualAdapter, normalizedParams.layer);
|
|
40
43
|
if (!layerId) {
|
|
41
|
-
throw new Error(`Layer not found: ${
|
|
44
|
+
throw new Error(`Layer not found: ${normalizedParams.layer}`);
|
|
42
45
|
}
|
|
43
46
|
}
|
|
44
47
|
// Use transaction for multi-table insert
|
|
45
48
|
const result = await actualAdapter.transaction(async (trx) => {
|
|
46
49
|
// Get or create category
|
|
47
|
-
const categoryId = await getOrCreateCategoryId(actualAdapter,
|
|
50
|
+
const categoryId = await getOrCreateCategoryId(actualAdapter, normalizedParams.category, trx);
|
|
51
|
+
// Duplicate check: skip if same text + category already exists
|
|
52
|
+
const existing = await trx('v4_constraints')
|
|
53
|
+
.where({
|
|
54
|
+
constraint_text: normalizedParams.constraint_text,
|
|
55
|
+
category_id: categoryId,
|
|
56
|
+
project_id: projectId
|
|
57
|
+
})
|
|
58
|
+
.first();
|
|
59
|
+
if (existing) {
|
|
60
|
+
return { constraintId: existing.id, alreadyExists: true };
|
|
61
|
+
}
|
|
48
62
|
// Note: Agent tracking removed in v4.0 (created_by param kept for API compatibility but not stored)
|
|
49
63
|
// Calculate timestamp
|
|
50
64
|
const ts = Math.floor(Date.now() / 1000);
|
|
51
65
|
// Insert constraint with project_id (agent_id removed in v4.0)
|
|
66
|
+
// v4.2.1: Support active parameter for plan-based workflow
|
|
67
|
+
const activeValue = normalizedParams.active === false ? 0 : SQLITE_TRUE;
|
|
52
68
|
const [constraintId] = await trx('v4_constraints').insert({
|
|
53
69
|
category_id: categoryId,
|
|
54
70
|
layer_id: layerId,
|
|
55
|
-
constraint_text:
|
|
71
|
+
constraint_text: normalizedParams.constraint_text,
|
|
56
72
|
priority: priority,
|
|
57
|
-
active:
|
|
73
|
+
active: activeValue,
|
|
58
74
|
ts: ts,
|
|
59
75
|
project_id: projectId
|
|
60
76
|
});
|
|
61
77
|
// Insert m_tags if provided
|
|
62
|
-
if (
|
|
78
|
+
if (normalizedParams.tags && normalizedParams.tags.length > 0) {
|
|
63
79
|
// Parse tags (handles both arrays and JSON strings from MCP)
|
|
64
|
-
const tags = parseStringArray(
|
|
80
|
+
const tags = parseStringArray(normalizedParams.tags);
|
|
65
81
|
for (const tagName of tags) {
|
|
66
82
|
const tagId = await getOrCreateTag(actualAdapter, projectId, tagName, trx); // v3.7.3: pass projectId
|
|
67
83
|
await trx('v4_constraint_tags').insert({
|
|
@@ -70,11 +86,12 @@ export async function addConstraint(params, adapter) {
|
|
|
70
86
|
});
|
|
71
87
|
}
|
|
72
88
|
}
|
|
73
|
-
return { constraintId: Number(constraintId) };
|
|
89
|
+
return { constraintId: Number(constraintId), alreadyExists: false };
|
|
74
90
|
});
|
|
75
91
|
return {
|
|
76
92
|
success: true,
|
|
77
93
|
constraint_id: result.constraintId,
|
|
94
|
+
already_exists: result.alreadyExists,
|
|
78
95
|
};
|
|
79
96
|
});
|
|
80
97
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add.js","sourceRoot":"","sources":["../../../../src/tools/constraints/actions/add.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACL,UAAU,EACV,UAAU,EACV,cAAc,EACd,qBAAqB,EACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,WAAW,EACX,eAAe,EAChB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAClF,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,iBAAiB,MAAM,sCAAsC,CAAC;AAMrE;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAA2B,EAC3B,OAAyB;IAEzB,MAAM,aAAa,GAAG,OAAO,IAAI,UAAU,EAAE,CAAC;IAE9C,IAAI,CAAC;QACH,OAAO,MAAM,iBAAiB,CAAC,gBAAgB,CAAC,KAAK,IAAI,EAAE;YACzD,mDAAmD;YACnD,MAAM,SAAS,GAAG,iBAAiB,EAAE,CAAC,YAAY,EAAE,CAAC;YAErD,sBAAsB;YACtB,oBAAoB,CAAC,YAAY,EAAE,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"add.js","sourceRoot":"","sources":["../../../../src/tools/constraints/actions/add.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deactivate.d.ts","sourceRoot":"","sources":["../../../../src/tools/constraints/actions/deactivate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"deactivate.d.ts","sourceRoot":"","sources":["../../../../src/tools/constraints/actions/deactivate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAO7D,OAAO,KAAK,EACV,0BAA0B,EAC1B,4BAA4B,EAC7B,MAAM,aAAa,CAAC;AAErB;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,0BAA0B,EAClC,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,4BAA4B,CAAC,CAsCvC"}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { getAdapter } from '../../../database.js';
|
|
6
6
|
import { validateActionParams } from '../../../utils/parameter-validator.js';
|
|
7
|
+
import { normalizeParams, CONSTRAINT_ALIASES } from '../../../utils/param-normalizer.js';
|
|
7
8
|
import { getProjectContext } from '../../../utils/project-context.js';
|
|
8
9
|
import connectionManager from '../../../utils/connection-manager.js';
|
|
9
10
|
import { SQLITE_FALSE } from '../../../constants.js';
|
|
@@ -18,23 +19,25 @@ import { SQLITE_FALSE } from '../../../constants.js';
|
|
|
18
19
|
export async function deactivateConstraint(params, adapter) {
|
|
19
20
|
const actualAdapter = adapter ?? getAdapter();
|
|
20
21
|
const knex = actualAdapter.getKnex();
|
|
22
|
+
// Normalize aliases: id → constraint_id
|
|
23
|
+
const normalizedParams = normalizeParams(params, CONSTRAINT_ALIASES);
|
|
21
24
|
try {
|
|
22
25
|
return await connectionManager.executeWithRetry(async () => {
|
|
23
26
|
// Fail-fast project_id validation (Constraint #29)
|
|
24
27
|
const projectId = getProjectContext().getProjectId();
|
|
25
28
|
// Validate parameters
|
|
26
|
-
validateActionParams('constraint', 'deactivate',
|
|
29
|
+
validateActionParams('constraint', 'deactivate', normalizedParams);
|
|
27
30
|
// Check if constraint exists in current project
|
|
28
31
|
const constraint = await knex('v4_constraints')
|
|
29
|
-
.where({ id:
|
|
32
|
+
.where({ id: normalizedParams.constraint_id, project_id: projectId })
|
|
30
33
|
.select('id', 'active')
|
|
31
34
|
.first();
|
|
32
35
|
if (!constraint) {
|
|
33
|
-
throw new Error(`Constraint not found: ${
|
|
36
|
+
throw new Error(`Constraint not found: ${normalizedParams.constraint_id}`);
|
|
34
37
|
}
|
|
35
38
|
// Update constraint to inactive (idempotent) with project_id filter
|
|
36
39
|
await knex('v4_constraints')
|
|
37
|
-
.where({ id:
|
|
40
|
+
.where({ id: normalizedParams.constraint_id, project_id: projectId })
|
|
38
41
|
.update({ active: SQLITE_FALSE });
|
|
39
42
|
return {
|
|
40
43
|
success: true,
|