sqlew 3.2.2 → 3.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -44,31 +44,31 @@ function setDecisionInternal(params, db) {
44
44
  // Insert or update decision based on value type
45
45
  if (isNumeric) {
46
46
  // Numeric decision
47
- const stmt = db.prepare(`
48
- INSERT INTO t_decisions_numeric (key_id, value, agent_id, layer_id, version, status, ts)
49
- VALUES (?, ?, ?, ?, ?, ?, ?)
50
- ON CONFLICT(key_id) DO UPDATE SET
51
- value = excluded.value,
52
- agent_id = excluded.agent_id,
53
- layer_id = excluded.layer_id,
54
- version = excluded.version,
55
- status = excluded.status,
56
- ts = excluded.ts
47
+ const stmt = db.prepare(`
48
+ INSERT INTO t_decisions_numeric (key_id, value, agent_id, layer_id, version, status, ts)
49
+ VALUES (?, ?, ?, ?, ?, ?, ?)
50
+ ON CONFLICT(key_id) DO UPDATE SET
51
+ value = excluded.value,
52
+ agent_id = excluded.agent_id,
53
+ layer_id = excluded.layer_id,
54
+ version = excluded.version,
55
+ status = excluded.status,
56
+ ts = excluded.ts
57
57
  `);
58
58
  stmt.run(keyId, value, agentId, layerId, version, status, ts);
59
59
  }
60
60
  else {
61
61
  // String decision
62
- const stmt = db.prepare(`
63
- INSERT INTO t_decisions (key_id, value, agent_id, layer_id, version, status, ts)
64
- VALUES (?, ?, ?, ?, ?, ?, ?)
65
- ON CONFLICT(key_id) DO UPDATE SET
66
- value = excluded.value,
67
- agent_id = excluded.agent_id,
68
- layer_id = excluded.layer_id,
69
- version = excluded.version,
70
- status = excluded.status,
71
- ts = excluded.ts
62
+ const stmt = db.prepare(`
63
+ INSERT INTO t_decisions (key_id, value, agent_id, layer_id, version, status, ts)
64
+ VALUES (?, ?, ?, ?, ?, ?, ?)
65
+ ON CONFLICT(key_id) DO UPDATE SET
66
+ value = excluded.value,
67
+ agent_id = excluded.agent_id,
68
+ layer_id = excluded.layer_id,
69
+ version = excluded.version,
70
+ status = excluded.status,
71
+ ts = excluded.ts
72
72
  `);
73
73
  stmt.run(keyId, String(value), agentId, layerId, version, status, ts);
74
74
  }
@@ -347,16 +347,16 @@ export function getVersions(params) {
347
347
  }
348
348
  const keyId = keyResult.id;
349
349
  // Query t_decision_history with agent join
350
- const stmt = db.prepare(`
351
- SELECT
352
- dh.version,
353
- dh.value,
354
- a.name as agent_name,
355
- datetime(dh.ts, 'unixepoch') as timestamp
356
- FROM t_decision_history dh
357
- LEFT JOIN m_agents a ON dh.agent_id = a.id
358
- WHERE dh.key_id = ?
359
- ORDER BY dh.ts DESC
350
+ const stmt = db.prepare(`
351
+ SELECT
352
+ dh.version,
353
+ dh.value,
354
+ a.name as agent_name,
355
+ datetime(dh.ts, 'unixepoch') as timestamp
356
+ FROM t_decision_history dh
357
+ LEFT JOIN m_agents a ON dh.agent_id = a.id
358
+ WHERE dh.key_id = ?
359
+ ORDER BY dh.ts DESC
360
360
  `);
361
361
  const rows = stmt.all(keyId);
362
362
  // Transform to response format
@@ -407,58 +407,58 @@ export function searchByLayer(params) {
407
407
  const queryParams = [params.layer, statusValue];
408
408
  if (includeTagsValue) {
409
409
  // Use v_tagged_decisions view for full metadata
410
- query = `
411
- SELECT * FROM v_tagged_decisions
412
- WHERE layer = ? AND status = ?
413
- ORDER BY updated DESC
410
+ query = `
411
+ SELECT * FROM v_tagged_decisions
412
+ WHERE layer = ? AND status = ?
413
+ ORDER BY updated DESC
414
414
  `;
415
415
  }
416
416
  else {
417
417
  // Use base t_decisions table with minimal joins
418
- query = `
419
- SELECT
420
- ck.key,
421
- d.value,
422
- d.version,
423
- CASE d.status
424
- WHEN 1 THEN 'active'
425
- WHEN 2 THEN 'deprecated'
426
- WHEN 3 THEN 'draft'
427
- END as status,
428
- l.name as layer,
429
- NULL as tags,
430
- NULL as scopes,
431
- a.name as decided_by,
432
- datetime(d.ts, 'unixepoch') as updated
433
- FROM t_decisions d
434
- INNER JOIN m_context_keys ck ON d.key_id = ck.id
435
- LEFT JOIN m_layers l ON d.layer_id = l.id
436
- LEFT JOIN m_agents a ON d.agent_id = a.id
437
- WHERE l.name = ? AND d.status = ?
438
-
439
- UNION ALL
440
-
441
- SELECT
442
- ck.key,
443
- CAST(dn.value AS TEXT) as value,
444
- dn.version,
445
- CASE dn.status
446
- WHEN 1 THEN 'active'
447
- WHEN 2 THEN 'deprecated'
448
- WHEN 3 THEN 'draft'
449
- END as status,
450
- l.name as layer,
451
- NULL as tags,
452
- NULL as scopes,
453
- a.name as decided_by,
454
- datetime(dn.ts, 'unixepoch') as updated
455
- FROM t_decisions_numeric dn
456
- INNER JOIN m_context_keys ck ON dn.key_id = ck.id
457
- LEFT JOIN m_layers l ON dn.layer_id = l.id
458
- LEFT JOIN m_agents a ON dn.agent_id = a.id
459
- WHERE l.name = ? AND dn.status = ?
460
-
461
- ORDER BY updated DESC
418
+ query = `
419
+ SELECT
420
+ ck.key,
421
+ d.value,
422
+ d.version,
423
+ CASE d.status
424
+ WHEN 1 THEN 'active'
425
+ WHEN 2 THEN 'deprecated'
426
+ WHEN 3 THEN 'draft'
427
+ END as status,
428
+ l.name as layer,
429
+ NULL as tags,
430
+ NULL as scopes,
431
+ a.name as decided_by,
432
+ datetime(d.ts, 'unixepoch') as updated
433
+ FROM t_decisions d
434
+ INNER JOIN m_context_keys ck ON d.key_id = ck.id
435
+ LEFT JOIN m_layers l ON d.layer_id = l.id
436
+ LEFT JOIN m_agents a ON d.agent_id = a.id
437
+ WHERE l.name = ? AND d.status = ?
438
+
439
+ UNION ALL
440
+
441
+ SELECT
442
+ ck.key,
443
+ CAST(dn.value AS TEXT) as value,
444
+ dn.version,
445
+ CASE dn.status
446
+ WHEN 1 THEN 'active'
447
+ WHEN 2 THEN 'deprecated'
448
+ WHEN 3 THEN 'draft'
449
+ END as status,
450
+ l.name as layer,
451
+ NULL as tags,
452
+ NULL as scopes,
453
+ a.name as decided_by,
454
+ datetime(dn.ts, 'unixepoch') as updated
455
+ FROM t_decisions_numeric dn
456
+ INNER JOIN m_context_keys ck ON dn.key_id = ck.id
457
+ LEFT JOIN m_layers l ON dn.layer_id = l.id
458
+ LEFT JOIN m_agents a ON dn.agent_id = a.id
459
+ WHERE l.name = ? AND dn.status = ?
460
+
461
+ ORDER BY updated DESC
462
462
  `;
463
463
  // Add params for the numeric table part of UNION
464
464
  queryParams.push(params.layer, statusValue);
@@ -815,12 +815,12 @@ export function hasUpdates(params) {
815
815
  }
816
816
  const sinceTs = Math.floor(sinceDate.getTime() / 1000);
817
817
  // Count decisions updated since timestamp (both string and numeric tables)
818
- const decisionCountStmt = db.prepare(`
819
- SELECT COUNT(*) as count FROM (
820
- SELECT ts FROM t_decisions WHERE ts > ?
821
- UNION ALL
822
- SELECT ts FROM t_decisions_numeric WHERE ts > ?
823
- )
818
+ const decisionCountStmt = db.prepare(`
819
+ SELECT COUNT(*) as count FROM (
820
+ SELECT ts FROM t_decisions WHERE ts > ?
821
+ UNION ALL
822
+ SELECT ts FROM t_decisions_numeric WHERE ts > ?
823
+ )
824
824
  `);
825
825
  const decisionResult = decisionCountStmt.get(sinceTs, sinceTs);
826
826
  const decisionsCount = decisionResult.count;
@@ -830,16 +830,16 @@ export function hasUpdates(params) {
830
830
  let messagesCount = 0;
831
831
  if (agentResult) {
832
832
  const agentId = agentResult.id;
833
- const messageCountStmt = db.prepare(`
834
- SELECT COUNT(*) as count FROM t_agent_messages
835
- WHERE ts > ? AND (to_agent_id = ? OR to_agent_id IS NULL)
833
+ const messageCountStmt = db.prepare(`
834
+ SELECT COUNT(*) as count FROM t_agent_messages
835
+ WHERE ts > ? AND (to_agent_id = ? OR to_agent_id IS NULL)
836
836
  `);
837
837
  const messageResult = messageCountStmt.get(sinceTs, agentId);
838
838
  messagesCount = messageResult.count;
839
839
  }
840
840
  // Count file changes since timestamp
841
- const fileCountStmt = db.prepare(`
842
- SELECT COUNT(*) as count FROM t_file_changes WHERE ts > ?
841
+ const fileCountStmt = db.prepare(`
842
+ SELECT COUNT(*) as count FROM t_file_changes WHERE ts > ?
843
843
  `);
844
844
  const fileResult = fileCountStmt.get(sinceTs);
845
845
  const filesCount = fileResult.count;
@@ -974,9 +974,9 @@ export function createTemplate(params) {
974
974
  const defaultsJson = JSON.stringify(params.defaults);
975
975
  const requiredFieldsJson = params.required_fields ? JSON.stringify(params.required_fields) : null;
976
976
  // Insert template
977
- const stmt = db.prepare(`
978
- INSERT INTO t_decision_templates (name, defaults, required_fields, created_by)
979
- VALUES (?, ?, ?, ?)
977
+ const stmt = db.prepare(`
978
+ INSERT INTO t_decision_templates (name, defaults, required_fields, created_by)
979
+ VALUES (?, ?, ?, ?)
980
980
  `);
981
981
  const info = stmt.run(params.name, defaultsJson, requiredFieldsJson, createdById);
982
982
  return {
@@ -1002,17 +1002,17 @@ export function createTemplate(params) {
1002
1002
  export function listTemplates(params = {}) {
1003
1003
  const db = getDatabase();
1004
1004
  try {
1005
- const stmt = db.prepare(`
1006
- SELECT
1007
- t.id,
1008
- t.name,
1009
- t.defaults,
1010
- t.required_fields,
1011
- a.name as created_by,
1012
- datetime(t.ts, 'unixepoch') as created_at
1013
- FROM t_decision_templates t
1014
- LEFT JOIN m_agents a ON t.created_by = a.id
1015
- ORDER BY t.name ASC
1005
+ const stmt = db.prepare(`
1006
+ SELECT
1007
+ t.id,
1008
+ t.name,
1009
+ t.defaults,
1010
+ t.required_fields,
1011
+ a.name as created_by,
1012
+ datetime(t.ts, 'unixepoch') as created_at
1013
+ FROM t_decision_templates t
1014
+ LEFT JOIN m_agents a ON t.created_by = a.id
1015
+ ORDER BY t.name ASC
1016
1016
  `);
1017
1017
  const rows = stmt.all();
1018
1018
  // Parse JSON fields
@@ -1176,4 +1176,233 @@ export function listDecisionContextsAction(params) {
1176
1176
  throw new Error(`Failed to list decision contexts: ${message}`);
1177
1177
  }
1178
1178
  }
1179
+ /**
1180
+ * Help action for decision tool
1181
+ */
1182
+ export function decisionHelp() {
1183
+ return {
1184
+ tool: 'decision',
1185
+ description: 'Manage decisions with metadata (tags, layers, versions, scopes)',
1186
+ note: '💡 TIP: Use action: "example" to see comprehensive usage scenarios and real-world examples for all decision actions.',
1187
+ purpose: {
1188
+ title: '⚠️ CRITICAL: Store WHY and REASON, Not WHAT',
1189
+ principle: 'Decisions table is for ARCHITECTURAL CONTEXT and REASONING, NOT implementation logs or task completion status',
1190
+ what_to_store: {
1191
+ correct: [
1192
+ 'WHY a design choice was made (e.g., "Chose JWT over sessions because stateless auth scales better for our microservice architecture")',
1193
+ 'REASONING behind architecture decisions (e.g., "Moved oscillator_type to MonophonicSynthConfig to separate synthesis methods - FM operators use different config")',
1194
+ 'PROBLEM ANALYSIS and solution rationale (e.g., "Nested transaction bug: setDecision wraps in transaction, batch also wraps → solution: extract internal helper without transaction wrapper")',
1195
+ 'DESIGN TRADE-OFFS and alternatives considered (e.g., "Query builder limited to simple filters, kept domain-specific logic inline for maintainability")',
1196
+ 'CONSTRAINTS and requirements reasoning (e.g., "API response must be <100ms because mobile clients timeout at 200ms")',
1197
+ 'BREAKING CHANGES with migration rationale (e.g., "Removed /v1/users endpoint - clients must use /v2/users with pagination for scalability")'
1198
+ ],
1199
+ incorrect: [
1200
+ '❌ Task completion logs (e.g., "Task 5 completed", "Refactoring done", "Tests passing") → Use tasks tool instead',
1201
+ '❌ Implementation status (e.g., "Added validators.ts", "Fixed bug in batch_create", "Updated README") → These are WHAT, not WHY',
1202
+ '❌ Test results (e.g., "All tests passing", "Integration tests complete", "v3.0.2 testing verified") → Temporary status, not architectural context',
1203
+ '❌ Git commit summaries (e.g., "Released v3.0.2", "Created git commit 2bf55a0") → Belongs in git history',
1204
+ '❌ Documentation updates (e.g., "README reorganized", "Help actions enhanced") → Implementation logs, not decisions',
1205
+ '❌ Build status (e.g., "Build succeeded", "TypeScript compiled with zero errors") → Temporary status'
1206
+ ]
1207
+ },
1208
+ analogy: {
1209
+ git_history: 'WHAT changed (files, lines, commits)',
1210
+ code_comments: 'HOW it works (implementation details, algorithms)',
1211
+ sqlew_decisions: 'WHY it was changed (reasoning, trade-offs, context)',
1212
+ sqlew_tasks: 'WHAT needs to be done (work items, status, completion)'
1213
+ },
1214
+ examples: [
1215
+ {
1216
+ key: 'api/auth/jwt-choice',
1217
+ value: 'Chose JWT over session-based auth because: (1) Stateless design scales horizontally, (2) Mobile clients can cache tokens, (3) Microservice architecture requires distributed auth. Trade-off: Revocation requires token blacklist, but acceptable for 15-min token lifetime.',
1218
+ explanation: 'Explains WHY JWT was chosen, considers trade-offs, provides architectural context'
1219
+ },
1220
+ {
1221
+ key: 'database/postgresql-choice',
1222
+ value: 'Selected PostgreSQL over MongoDB because: (1) Complex relational queries required for reporting, (2) ACID compliance critical for financial data, (3) Team has strong SQL expertise. Trade-off: Less flexible schema, but data integrity more important than schema flexibility for our use case.',
1223
+ explanation: 'Documents database choice with reasoning, alternatives considered, and trade-offs'
1224
+ },
1225
+ {
1226
+ key: 'security/encryption-at-rest',
1227
+ value: 'Implementing AES-256 encryption for all PII in database because: (1) GDPR compliance requires encryption at rest, (2) Recent security audit identified unencrypted sensitive data, (3) Performance impact <5ms per query acceptable. Alternative considered: Database-level encryption rejected due to backup/restore complexity.',
1228
+ explanation: 'Explains security decision with compliance reasoning and performance considerations'
1229
+ }
1230
+ ],
1231
+ cleanup_rule: 'Delete decisions that start with "COMPLETED:", contain task status, test results, or implementation logs. Keep only architectural reasoning and design rationale.'
1232
+ },
1233
+ actions: {
1234
+ set: 'Set/update a decision. Params: key (required), value (required), agent, layer, version, status, tags, scopes',
1235
+ get: 'Get specific decision by key. Params: key (required), include_context (optional, boolean, default: false). When include_context=true, returns decision with attached context (rationale, alternatives, tradeoffs). Backward compatible - omitting flag returns standard decision format.',
1236
+ list: 'List/filter decisions. Params: status, layer, tags, scope, tag_match',
1237
+ search_tags: 'Search decisions by tags. Params: tags (required), match_mode, status, layer',
1238
+ search_layer: 'Search decisions by layer. Params: layer (required), status, include_tags',
1239
+ versions: 'Get version history for a decision. Params: key (required)',
1240
+ quick_set: 'Quick set with smart defaults (FR-002). Params: key (required), value (required), agent, layer, version, status, tags, scopes. Auto-infers layer from key prefix (api/*→presentation, db/*→data, service/*→business, config/*→infrastructure), tags from key hierarchy, scope from parent path. Defaults: status=active, version=1.0.0. All inferred fields can be overridden.',
1241
+ search_advanced: 'Advanced query with complex filtering (FR-004). Params: layers (OR), tags_all (AND), tags_any (OR), exclude_tags, scopes (wildcards), updated_after/before (ISO or relative like "7d"), decided_by, statuses, search_text, sort_by (updated/key/version), sort_order (asc/desc), limit (default:20, max:1000), offset (default:0). Returns decisions with total_count for pagination. All filters use parameterized queries (SQL injection protection).',
1242
+ set_batch: 'Batch set decisions (FR-005). Params: decisions (required, array of SetDecisionParams, max: 50), atomic (optional, boolean, default: true). Returns: {success, inserted, failed, results}. ATOMIC MODE BEHAVIOR (atomic: true): All decisions succeed or all fail as a single transaction. If ANY decision fails, entire batch is rolled back and error is thrown. Use for critical operations requiring consistency. NON-ATOMIC MODE (atomic: false): Each decision is processed independently. If some fail, others still succeed. Returns partial results with per-item success/error status. Use for best-effort batch operations or when individual failures are acceptable. RECOMMENDATION FOR AI AGENTS: Use atomic:false by default to avoid transaction failures from validation errors or malformed data. Only use atomic:true when all-or-nothing guarantee is required. 52% token reduction vs individual calls.',
1243
+ has_updates: 'Check for updates since timestamp (FR-003 Phase A - Lightweight Polling). Params: agent_name (required), since_timestamp (required, ISO 8601 format like "2025-10-14T08:00:00Z"). Returns: {has_updates: boolean, counts: {decisions: N, messages: N, files: N}}. Token cost: ~5-10 tokens per check. Uses COUNT queries on t_decisions, t_agent_messages, t_file_changes with timestamp filtering. Enables efficient polling without full data retrieval.',
1244
+ set_from_template: 'Set decision using template (FR-006). Params: template (required, template name), key (required), value (required), agent, layer (override), version, status (override), tags (override), scopes, plus any template-required fields. Applies template defaults (layer, status, tags) while allowing overrides. Validates required fields if specified by template. Returns: {success, key, key_id, version, template_used, applied_defaults, message}. Built-in templates: breaking_change, security_vulnerability, performance_optimization, deprecation, architecture_decision.',
1245
+ create_template: 'Create new decision template (FR-006). Params: name (required, unique), defaults (required, object with layer/status/tags/priority), required_fields (optional, array of field names), created_by (optional, agent name). Returns: {success, template_id, template_name, message}. Example defaults: {"layer":"business","status":"active","tags":["breaking"]}. Validates layer/status values.',
1246
+ list_templates: 'List all decision templates (FR-006). No params required. Returns: {templates: [{id, name, defaults, required_fields, created_by, created_at}], count}. Shows both built-in and custom templates.',
1247
+ hard_delete: 'Permanently delete a decision (hard delete). Params: key (required). WARNING: IRREVERSIBLE - removes all records including version history, tags, scopes. Use cases: manual cleanup after decision-to-task migration, remove test/debug decisions, purge sensitive data. Unlike soft delete (status=deprecated), this completely removes from database. Idempotent - safe to call even if already deleted. Returns: {success, key, message}.',
1248
+ add_decision_context: 'Add rich context to a decision (v3.2.2). Params: key (required), rationale (required), alternatives_considered (optional, JSON array), tradeoffs (optional, JSON object with pros/cons), decided_by (optional), related_task_id (optional), related_constraint_id (optional). Use to document WHY decisions were made, what alternatives were considered, and trade-offs. Multiple contexts can be attached to the same decision over time. Returns: {success, context_id, decision_key, message}.',
1249
+ list_decision_contexts: 'List decision contexts with filters (v3.2.2). Params: decision_key (optional), related_task_id (optional), related_constraint_id (optional), decided_by (optional), limit (default: 50), offset (default: 0). Returns: {success, contexts: [{id, decision_key, rationale, alternatives_considered, tradeoffs, decided_by, decision_date, related_task_id, related_constraint_id}], count}. JSON fields (alternatives, tradeoffs) are automatically parsed.'
1250
+ },
1251
+ examples: {
1252
+ set: '{ action: "set", key: "auth_method", value: "jwt", tags: ["security"] }',
1253
+ get: '{ action: "get", key: "auth_method" }',
1254
+ list: '{ action: "list", status: "active", layer: "infrastructure" }',
1255
+ search_tags: '{ action: "search_tags", tags: ["security", "api"] }',
1256
+ quick_set: '{ action: "quick_set", key: "api/instruments/oscillator-refactor", value: "Moved oscillator_type to MonophonicSynthConfig" }',
1257
+ search_advanced: '{ action: "search_advanced", layers: ["business", "data"], tags_all: ["breaking", "v0.3.3"], tags_any: ["api", "synthesis"], exclude_tags: ["deprecated"], scopes: ["api/instruments/*"], updated_after: "2025-10-01", statuses: ["active", "draft"], search_text: "oscillator", sort_by: "updated", sort_order: "desc", limit: 20, offset: 0 }',
1258
+ set_batch: '{ action: "set_batch", decisions: [{"key": "feat-1", "value": "...", "layer": "business"}, {"key": "feat-2", "value": "...", "layer": "data"}], atomic: true }',
1259
+ has_updates: '{ action: "has_updates", agent_name: "my-agent", since_timestamp: "2025-10-14T08:00:00Z" }',
1260
+ set_from_template: '{ action: "set_from_template", template: "breaking_change", key: "oscillator-type-moved", value: "oscillator_type moved to MonophonicSynthConfig" }',
1261
+ create_template: '{ action: "create_template", name: "bug_fix", defaults: {"layer":"business","tags":["bug","fix"],"status":"active"}, created_by: "my-agent" }',
1262
+ list_templates: '{ action: "list_templates" }',
1263
+ hard_delete: '{ action: "hard_delete", key: "task_old_authentication_refactor" }'
1264
+ },
1265
+ documentation: {
1266
+ tool_selection: 'docs/TOOL_SELECTION.md - Decision tree, tool comparison, when to use each tool (236 lines, ~12k tokens)',
1267
+ tool_reference: 'docs/TOOL_REFERENCE.md - Parameter requirements, batch operations, templates (471 lines, ~24k tokens)',
1268
+ workflows: 'docs/WORKFLOWS.md - Multi-step workflow examples, multi-agent coordination (602 lines, ~30k tokens)',
1269
+ best_practices: 'docs/BEST_PRACTICES.md - Common errors, best practices, troubleshooting (345 lines, ~17k tokens)',
1270
+ shared_concepts: 'docs/SHARED_CONCEPTS.md - Layer definitions, enum values (status/layer/priority), atomic mode (339 lines, ~17k tokens)'
1271
+ }
1272
+ };
1273
+ }
1274
+ /**
1275
+ * Example action for decision tool
1276
+ */
1277
+ export function decisionExample() {
1278
+ return {
1279
+ tool: 'decision',
1280
+ description: 'Comprehensive decision tool examples without needing WebFetch access',
1281
+ scenarios: {
1282
+ basic_usage: {
1283
+ title: 'Basic Decision Management',
1284
+ examples: [
1285
+ {
1286
+ scenario: 'Record API design decision',
1287
+ request: '{ action: "set", key: "api_auth_method", value: "JWT with refresh tokens", layer: "business", tags: ["api", "security", "authentication"] }',
1288
+ explanation: 'Documents the choice of authentication method for the API'
1289
+ },
1290
+ {
1291
+ scenario: 'Retrieve a decision',
1292
+ request: '{ action: "get", key: "api_auth_method" }',
1293
+ response_structure: '{ key, value, layer, status, version, tags, scopes, decided_by, updated_at }'
1294
+ },
1295
+ {
1296
+ scenario: 'List all active decisions',
1297
+ request: '{ action: "list", status: "active", limit: 20 }',
1298
+ explanation: 'Returns active decisions with metadata for browsing'
1299
+ }
1300
+ ]
1301
+ },
1302
+ advanced_filtering: {
1303
+ title: 'Advanced Search and Filtering',
1304
+ examples: [
1305
+ {
1306
+ scenario: 'Find all security-related decisions in business layer',
1307
+ request: '{ action: "search_advanced", layers: ["business"], tags_any: ["security", "authentication"], status: ["active"], sort_by: "updated", sort_order: "desc" }',
1308
+ explanation: 'Combines layer filtering, tag matching, and sorting'
1309
+ },
1310
+ {
1311
+ scenario: 'Search within API scope with multiple tags',
1312
+ request: '{ action: "search_advanced", scopes: ["api/*"], tags_all: ["breaking", "v2.0"], updated_after: "2025-01-01" }',
1313
+ explanation: 'Uses scope wildcards and timestamp filtering for recent breaking changes'
1314
+ }
1315
+ ]
1316
+ },
1317
+ versioning_workflow: {
1318
+ title: 'Version Management',
1319
+ steps: [
1320
+ {
1321
+ step: 1,
1322
+ action: 'Create initial decision',
1323
+ request: '{ action: "set", key: "database_choice", value: "PostgreSQL", layer: "data", version: "1.0.0", tags: ["database"] }'
1324
+ },
1325
+ {
1326
+ step: 2,
1327
+ action: 'Update decision (creates new version)',
1328
+ request: '{ action: "set", key: "database_choice", value: "PostgreSQL with read replicas", layer: "data", version: "1.1.0", tags: ["database", "scaling"] }'
1329
+ },
1330
+ {
1331
+ step: 3,
1332
+ action: 'View version history',
1333
+ request: '{ action: "versions", key: "database_choice" }',
1334
+ result: 'Returns all versions with timestamps and changes'
1335
+ }
1336
+ ]
1337
+ },
1338
+ batch_operations: {
1339
+ title: 'Batch Decision Management',
1340
+ examples: [
1341
+ {
1342
+ scenario: 'Record multiple related decisions atomically',
1343
+ request: '{ action: "set_batch", decisions: [{"key": "cache_layer", "value": "Redis", "layer": "infrastructure"}, {"key": "cache_ttl", "value": "3600", "layer": "infrastructure"}], atomic: true }',
1344
+ explanation: 'All decisions succeed or all fail together (atomic mode)'
1345
+ },
1346
+ {
1347
+ scenario: 'Best-effort batch insert',
1348
+ request: '{ action: "set_batch", decisions: [{...}, {...}, {...}], atomic: false }',
1349
+ explanation: 'Each decision processed independently - partial success allowed'
1350
+ }
1351
+ ]
1352
+ },
1353
+ templates: {
1354
+ title: 'Using Decision Templates',
1355
+ examples: [
1356
+ {
1357
+ scenario: 'Use built-in breaking_change template',
1358
+ request: '{ action: "set_from_template", template: "breaking_change", key: "api_remove_legacy_endpoint", value: "Removed /v1/users endpoint - migrate to /v2/users" }',
1359
+ explanation: 'Automatically applies layer=business, tags=["breaking"], status=active'
1360
+ },
1361
+ {
1362
+ scenario: 'Create custom template',
1363
+ request: '{ action: "create_template", name: "feature_flag", defaults: {"layer": "presentation", "tags": ["feature-flag"], "status": "draft"}, created_by: "backend-team" }',
1364
+ explanation: 'Define reusable templates for common decision patterns'
1365
+ }
1366
+ ]
1367
+ },
1368
+ quick_set_inference: {
1369
+ title: 'Quick Set with Smart Defaults',
1370
+ examples: [
1371
+ {
1372
+ scenario: 'Auto-infer layer from key prefix',
1373
+ request: '{ action: "quick_set", key: "api/instruments/oscillator-refactor", value: "Moved oscillator_type to MonophonicSynthConfig" }',
1374
+ inferred: 'layer=presentation (from api/*), tags=["instruments", "oscillator-refactor"], scope=api/instruments'
1375
+ },
1376
+ {
1377
+ scenario: 'Database decision with auto-inference',
1378
+ request: '{ action: "quick_set", key: "db/users/add-email-index", value: "Added index on email column" }',
1379
+ inferred: 'layer=data (from db/*), tags=["users", "add-email-index"]'
1380
+ }
1381
+ ]
1382
+ }
1383
+ },
1384
+ best_practices: {
1385
+ key_naming: [
1386
+ 'Use hierarchical keys: "api/users/authentication"',
1387
+ 'Prefix with layer hint: api/* → presentation, db/* → data, service/* → business',
1388
+ 'Use descriptive names that explain the decision context'
1389
+ ],
1390
+ tagging: [
1391
+ 'Tag with relevant categories: security, performance, breaking, etc.',
1392
+ 'Include version tags for release-specific decisions',
1393
+ 'Use consistent tag naming conventions across team'
1394
+ ],
1395
+ versioning: [
1396
+ 'Use semantic versioning: 1.0.0, 1.1.0, 2.0.0',
1397
+ 'Increment major version for breaking changes',
1398
+ 'Document rationale in decision value text'
1399
+ ],
1400
+ cleanup: [
1401
+ 'Mark deprecated decisions with status="deprecated"',
1402
+ 'Use hard_delete only for sensitive data or migration cleanup',
1403
+ 'Link related decisions using scopes'
1404
+ ]
1405
+ }
1406
+ };
1407
+ }
1179
1408
  //# sourceMappingURL=context.js.map