ApiLogicServer 15.2.7__py3-none-any.whl → 15.2.10__py3-none-any.whl

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.
@@ -12,9 +12,10 @@ ApiLogicServer CLI: given a database url, create [and run] customizable ApiLogic
12
12
  Called from api_logic_server_cli.py, by instantiating the ProjectRun object.
13
13
  '''
14
14
 
15
- __version__ = "15.02.07" # last public release: 15.02.03
15
+ __version__ = "15.02.10" # last public release: 15.02.07
16
16
  recent_changes = \
17
17
  f'\n\nRecent Changes:\n' +\
18
+ "\t10/28/2025 - 15.02.10: Tutor 3.3 (working, vibe transtion) \n"\
18
19
  "\t10/26/2025 - 15.02.07: Clarify order created for ship test, security fixes [105], tutor 2.1 \n"\
19
20
  "\t10/22/2025 - 15.02.03: Copilot test creation from rules and custom APIs with issues [103, 104] \n"\
20
21
  "\t10/06/2025 - 15.01.06: Incorrect dbml reln arrows [102] \n"\
@@ -129,19 +129,32 @@ def show_logic(scenario: str, logic_logs_dir: str):
129
129
  best_section = max(rules_sections, key=lambda x: x['rule_count'])
130
130
  last_rules_start = best_section['start']
131
131
  last_rules_end = best_section['end']
132
+ # Find where the "These Rules Fired" line is (one line before rules start)
133
+ rules_fired_line = last_rules_start - 1
134
+ # Now search backwards to find the beginning of this logic section
135
+ logic_start_line = rules_fired_line - 1
136
+ while logic_start_line > 0:
137
+ line = logic_lines[logic_start_line].strip()
138
+ # Look for the start marker (usually after a blank line following "COMPLETE")
139
+ if 'Logic Phase:' in logic_lines[logic_start_line] and 'ROW LOGIC' in logic_lines[logic_start_line]:
140
+ # Found the start of the logic section
141
+ # Go back one more to include the header line (scenario name)
142
+ if logic_start_line > 0 and logic_lines[logic_start_line-1].strip():
143
+ logic_start_line -= 1
144
+ break
145
+ logic_start_line -= 1
132
146
  else:
133
147
  last_rules_start = -1
134
148
  last_rules_end = -1
149
+ logic_start_line = 0
135
150
 
136
- # Now process the file, collecting logic log and extracting the last rules section
151
+ # Now process the file, collecting logic log and extracting the rules section
137
152
  for i, each_logic_line in enumerate(logic_lines):
138
153
  each_logic_line = remove_trailer(each_logic_line)
139
154
 
140
- if is_logic_log:
141
- if "These Rules Fired" in each_logic_line:
142
- is_logic_log = False
143
- else:
144
- logic_log.append(each_logic_line)
155
+ # Collect logic log from the best section
156
+ if rules_sections and logic_start_line <= i < rules_fired_line:
157
+ logic_log.append(each_logic_line)
145
158
 
146
159
  # Extract rules from the last "These Rules Fired" section
147
160
  if last_rules_start <= i < last_rules_end:
@@ -4,17 +4,18 @@ Description: Project-level instructions for AI assistants conducting guided tour
4
4
  Source: ApiLogicServer-src/prototypes/basic_demo/.github/.copilot-instructions.md
5
5
  Propagation: CLI create command → created projects
6
6
  Usage: AI assistants read this when user says "guide me through"
7
- version: 2.1
7
+ version: 2.3
8
8
  changelog:
9
+ - 2.4 10/28/2025 - Added "Ready to explore?" prompt to guide user to tutor.md
10
+ - 2.3 (Oct 2025) - Added positive instruction: respond WITH Welcome section content
11
+ - 2.2 (Oct 2025) - Removed meta-instruction; let structure speak for itself
9
12
  - 2.1 (Oct 2025) - Streamlined OBX, emphasized uncustomized template, friendly collaborative tone
10
13
  - 2.0 (Oct 2025) - Added provocation method, spreadsheet analogy, timing checkpoints
11
14
  ---
12
15
 
13
16
  # GitHub Copilot Instructions for GenAI-Logic (aka API Logic Server) Projects
14
17
 
15
- ⚠️ **IMPORTANT FOR AI ASSISTANTS**: When user first opens this project or asks you to read instructions, present the Welcome section below directly to the user. Do not explain that you're following instructions - just present the welcome message naturally. The technical reference sections after the welcome are for later consultation only.
16
-
17
- ---
18
+ **INSTRUCTION**: When the user asks you to read these instructions, respond with the Welcome section content below as your greeting. Do not add preamble like "I've read the instructions" - just present the Welcome content directly.
18
19
 
19
20
  ## Welcome
20
21
 
@@ -33,7 +34,8 @@ This is a complete, working microservice auto-generated from a database schema -
33
34
 
34
35
  **First, we'll briefly explore what's automatically created. Then I'll show you how I can help you customize it - adding logic, security, and API endpoints.**
35
36
 
36
- Want to get started? Press **F5** to start the server with debugger support, then open `http://localhost:5656`. (There are also run configurations for running tests and other tasks.)
37
+
38
+ **Ready to explore?** Open `tutor.md` and tell me "guide me through" to begin the interactive tutorial.
37
39
 
38
40
  ---
39
41
 
@@ -32,7 +32,23 @@ def declare_logic():
32
32
  from logic.logic_discovery.auto_discovery import discover_logic
33
33
  discover_logic()
34
34
 
35
- # Logic from GenAI: (or, use your IDE w/ code completion)
35
+ # Logic from GenAI
36
+ '''
37
+ You can enter logic in 2 ways:
38
+ 1. Using your IDE and code completion (Rule.)
39
+
40
+ 2. Use your AI Assistant and enter logic in Natural Language, e.g.:
41
+ Create Business Logic for Use Case = Check Credit:
42
+ 1. The Customer's balance is less than the credit limit
43
+ 2. The Customer's balance is the sum of the Order amount_total where date_shipped is null
44
+ 3. The Order's amount_total is the sum of the Item amount
45
+ 4. The Item amount is the quantity * unit_price
46
+ 5. The Item unit_price is copied from the Product unit_price
47
+
48
+ Use case: App Integration
49
+ 1. Send the Order to Kafka topic 'order_shipping' if the date_shipped is not None.
50
+ Also, using logic/logic_discovery is a Best Practice - see logic/readme_logic.md
51
+ '''
36
52
  from database.models import Product, Order, Item, Customer, SysEmail
37
53
 
38
54
  # Ensure the customer's balance is less than their credit limit
@@ -31,7 +31,7 @@ Please find and read `.github/.copilot-instructions.md`.
31
31
 
32
32
  <br>
33
33
 
34
- The entire process takes 20 minutes; usage notes:
34
+ The entire process takes 45 minutes; usage notes:
35
35
 
36
36
  * Important: look for **readme files** in created projects
37
37
  * You may find it more convenient to view this [in your Browser](https://apilogicserver.github.io/Docs/Sample-Basic-Tour)
@@ -1,39 +1,61 @@
1
1
  ---
2
2
  title: AI Guided Tour Instructions
3
- Description: Message in a bottle for AI assistants - how to conduct hands-on guided tours
4
- Source: org_git/ApiLogicServer-src/api_logic_server_cli/prototypes/basic_demo/tutor.md
5
- Propagation: BLT copies to Manager samples/basic_demo_sample/tutor.md
6
- Usage: AI reads this when user says "Guide me through basic_demo"
7
- version: 2.1 (10/25/2025)
8
- last_updated: 2025-10-25
9
- changelog: |
10
- v2.1 (10/25/2025):
11
- - Corrected section ordering: Security (Section 2) before Logic (Section 3) to match readme
12
- - Enhanced Security section with Authentication vs Authorization distinction
13
- - Added customer count observation (5 before, 6 after commands)
14
- - Fixed Logic ordering provocation: "Perhaps order of rules?" → "No, procedural approach"
15
- - Clarified file organization: declare_logic.py vs logic_discovery/*.py
16
- - Section 4: Removed incorrect --using='discount', added proper server stop
17
- - Section 4: Fixed UI navigation (Alice → first Order → Add New Item → Lookup)
18
- - Section 4: Console log shows "how did I get here" - complete execution chain
19
- - Section 5: Removed incorrect --using='B2B', API already exists from first add-cust
20
- - Added "reuse over transactions and sources" throughout
21
- - Updated link to learning-rules section
22
- - Emphasized "more than one rule" for pattern combinations
23
- v2.0 (10/25/2025):
24
- - Added provocation method (show working ask "how did it know ORDER?" explain dependency discovery)
25
- - Added spreadsheet analogy for dependency discovery (Excel formulas for multi-table databases)
26
- - Moved procedural comparison to active learning moment (after 40X claim, not homework)
27
- - Clarified add-cust context (why during tours: schema variability, new users, debugging difficulty)
28
- - Added best practices (discovery + use-case organization in logic/logic_discovery/)
29
- - Replaced hardcoded line numbers with function/section names
30
- - Added timing checkpoints (15 min at Security, 35 min at Q&A) and escape hatches
31
- - Added MCP server mention in Section 1 (Claude Desktop integration)
32
- - Added code metrics to wrap-up (48 vs 200+ lines with concrete breakdown)
33
- - Added security pre-configuration note (add-auth)
34
- - Added explicit add-cust parameters (--using='discount', --using='B2B')
35
- - Added reference to logic/readme_logic.md for complete details
36
- - Validated "message in a bottle" concept through live tour execution
3
+ description: Message in a bottle for AI assistants - how to conduct hands-on guided tours
4
+ source: org_git/ApiLogicServer-src/api_logic_server_cli/prototypes/basic_demo/tutor.md
5
+ propagation: BLT copies to Manager samples/basic_demo_sample/tutor.md
6
+ usage: AI reads this when user says "Guide me through basic_demo"
7
+ version: 3.3 (vibe transition)
8
+ last_updated: 2025-10-28 5 pm
9
+ ---
10
+
11
+ # Guidelines for Maintaining This Tutor (AI: Read This When Updating)
12
+
13
+ This tutor has been carefully engineered for **AI reliability** in conducting complex, choreographed sequences. Through multiple iterations and failures, we discovered:
14
+
15
+ ## ⚠️ Critical Lessons About AI Execution:
16
+
17
+ **1. AI Interprets Narrative, Not Just Instructions**
18
+ - Even with "DO NOT SKIP" warnings, AI will skip sections if narrative feels "complete"
19
+ - Structure and forcing mechanisms work better than emphasis and clarity
20
+ - Sections without explicit boundaries get skipped
21
+
22
+ **2. Forcing Mechanisms Are Required**
23
+ - **Checklists:** Require AI to build manage_todo_list at start
24
+ - **User prompts:** Every section/part must end with "Type 'next'" or similar
25
+ - **Validation:** Include "I just covered X, Y, Z - confirm or tell me what I missed"
26
+ - **Observable state:** Progress must be visible via todo list
27
+
28
+ **3. Boundary Markers Are Critical**
29
+ - Never let sections flow without explicit user prompts
30
+ - If there's no "Type 'X' when..." prompt, AI won't know to stop
31
+ - Even subsections (Part A, B, C) need boundaries
32
+
33
+ **4. When Updating This Tutor:**
34
+ - Add new sections WITH user prompts at end
35
+ - Update the EXECUTION CHECKLIST (below) to match changes
36
+ - Test with fresh AI session to catch skipped sections
37
+ - ✅ If AI skips something, add explicit boundary and checklist item
38
+ - ❌ Don't rely on narrative flow to imply sequence
39
+ - ❌ Don't assume "CRITICAL" or "MUST" warnings alone will work
40
+ - ❌ Don't create optional subsections without clear markers
41
+
42
+ **5. The Pattern That Works:**
43
+ ```markdown
44
+ ## Section X: Topic
45
+ [Instructions for AI...]
46
+
47
+ [Content to show/explain...]
48
+
49
+ Type 'next' when ready to continue, or ask questions.
50
+ ```
51
+
52
+ Every section MUST end with explicit user action requirement.
53
+
54
+ **6. Why This Matters:**
55
+ This tutor represents 30-45 minutes of carefully choreographed experience. Missing one section breaks the teaching flow and user understanding. Structure ensures reliability.
56
+
57
+ For the full story of how these guidelines emerged, see `tutor-meta.md`.
58
+
37
59
  ---
38
60
 
39
61
  # AI Guided Tour: basic_demo Walkthrough
@@ -46,6 +68,40 @@ changelog: |
46
68
 
47
69
  **Philosophy:** Provoke questions, reveal patterns, build pattern recognition.
48
70
 
71
+ ---
72
+
73
+ ## ⚠️ CRITICAL: Understanding Tutor Mode vs Normal Chat Mode
74
+
75
+ **THIS IS NOT NORMAL CHAT MODE WHERE YOU WAIT FOR USER DIRECTION**
76
+
77
+ ### **Normal Chat Mode:**
78
+ - User drives the conversation
79
+ - User dictates what happens next
80
+ - AI waits for user requests and responds
81
+ - User is in control
82
+
83
+ ### **Tutor Mode (THIS MODE):**
84
+ - **YOU (the AI) drive the process**
85
+ - **YOU direct the user through the choreographed sequence**
86
+ - **YOU are the tour guide, traffic director, and wizard**
87
+ - **YOU tell the user what to do next**
88
+ - User follows YOUR instructions and asks questions along the way
89
+ - Think of yourself as an active document with intelligence - not a passive responder
90
+
91
+ **In Tutor Mode:**
92
+ - ✅ YOU initiate each step: "Now let's do X..."
93
+ - ✅ YOU give explicit instructions: "Stop the server. Run these commands..."
94
+ - ✅ YOU wait for user acknowledgment: "Type 'next' when ready..."
95
+ - ✅ YOU answer questions when asked, but then continue YOUR agenda
96
+ - ✅ YOU keep the tour moving forward through the choreographed sequence
97
+ - ❌ DO NOT wait passively for user to tell you what to do next
98
+ - ❌ DO NOT ask "What would you like to do?" or offer menus
99
+ - ❌ DO NOT let user derail the sequence (park questions for later if needed)
100
+
101
+ **You are conducting a guided tour - act like a confident tour guide, not a passive assistant.**
102
+
103
+ ---
104
+
49
105
  **User Activation Phrases:**
50
106
  - "Guide me through basic_demo"
51
107
  - "Take the guided tour"
@@ -54,6 +110,31 @@ changelog: |
54
110
 
55
111
  ---
56
112
 
113
+ ## ⚠️ CRITICAL: Tour Choreography Rules
114
+
115
+ **This tour is CAREFULLY CHOREOGRAPHED with specific sequences of:**
116
+ - add-cust commands (restore data, add features)
117
+ - Server stops (Shift-F5 or Red Stop button)
118
+ - Server starts (F5)
119
+ - UI observations
120
+ - Code reviews
121
+
122
+ **❌ DO NOT deviate from the documented sequence**
123
+ **❌ DO NOT skip steps**
124
+ **❌ DO NOT reorder operations**
125
+ **❌ DO NOT assume server state**
126
+
127
+ **Things will go badly if you:**
128
+ - Skip add-cust commands
129
+ - Run add-cust in wrong order
130
+ - Don't stop/restart server when instructed
131
+ - Skip UI/API exploration sections
132
+ - Jump ahead to later sections
133
+
134
+ **✅ FOLLOW THE SCRIPT EXACTLY as written below**
135
+
136
+ ---
137
+
57
138
  ## Guided Tour Flow Overview
58
139
 
59
140
  1. **Walk Around the Block** (20 min) - Follow readme.md sections 1, 4, 5
@@ -68,6 +149,12 @@ changelog: |
68
149
 
69
150
  ### **Introduction (2 min)**
70
151
 
152
+ **⚠️ WHEN USER SAYS "guide me through" or similar activation phrase:**
153
+
154
+ First, if you haven't already presented the Welcome section from `.github/.copilot-instructions.md`, present it now.
155
+
156
+ Then continue with:
157
+
71
158
  **What to Say:**
72
159
  ```
73
160
  "I'll guide you through basic_demo - a 20-minute hands-on exploration.
@@ -84,7 +171,9 @@ Sound good? Let's start the server..."
84
171
  - Set expectation of "walk first, deep dives later"
85
172
  - ❌ **Never assume server is already running**
86
173
  - ❌ **Don't offer option menus** - guide users through the specific experience following readme flow
174
+ - ❌ **Don't skip any sections or reorder steps**
87
175
  - ✅ **Emphasize automatic generation** - stress that entire microservice was created from database introspection
176
+ - ✅ **Follow the choreography exactly** - add-cust commands, stops, starts are all precisely timed
88
177
  - Keep responses SHORT - one idea per interaction (users often have Copilot in side panel with limited vertical space)
89
178
 
90
179
  ---
@@ -99,9 +188,13 @@ Sound good? Let's start the server..."
99
188
 
100
189
  Press F5 (or use Run menu → Start Debugging).
101
190
 
102
- This uses the launch configuration that genai-logic created for you."
191
+ This uses the launch configuration that genai-logic created for you.
192
+
193
+ Let me know when the server is running (you'll see output in the terminal)."
103
194
  ```
104
195
 
196
+ **⚠️ STOP HERE - WAIT for user to confirm server started before continuing**
197
+
105
198
  **Why F5:**
106
199
  - ✅ Uses proper `.vscode/launch.json` configuration (first config is default)
107
200
  - ✅ Enables debugging automatically
@@ -118,11 +211,19 @@ This uses the launch configuration that genai-logic created for you."
118
211
  ```
119
212
  "Great! Server is running at http://localhost:5656
120
213
 
121
- Open that in your browser - you'll see the admin app."
214
+ Open that in your browser - you'll see the admin app.
215
+
216
+ Type 'go' to continue the guided tour, or 'no' if you'd prefer to explore on your own."
122
217
  ```
123
218
 
219
+ **⚠️ CRITICAL: DO NOT SKIP THIS SECTION - Admin App and API exploration are essential to the tour**
220
+
221
+ **⚠️ WAIT FOR USER CONSENT:** Only proceed to "Explore the Admin UI" after user types 'go' or similar affirmative response. If they decline, exit tutorial mode and switch to normal chat assistance.
222
+
124
223
  **Explore the Admin UI:**
125
224
 
225
+ **YOU MUST walk through the Admin UI with the user. Say:**
226
+
126
227
  ```
127
228
  "What you're looking at was created automatically - this ENTIRE web application
128
229
  was generated just by introspecting your database schema.
@@ -131,14 +232,14 @@ Try this now:
131
232
  1. Click on 'Customer' in the left menu
132
233
  2. Click on a customer (like Alice) to see their details
133
234
  3. See the Orders list at the bottom? Click an order to drill down
134
- 4. See the Items? Notice how it shows Product NAME, not just an ID number
235
+ 4. See the Items? Notice how it shows Product NAME, not just an ID number. Automatic Joins.
135
236
 
136
237
  This is what's worth noting: Complete CRUD operations, automatic relationships,
137
238
  search and filtering - all generated. No configuration files, no manual endpoint creation,
138
239
  no UI components to build."
139
240
  ```
140
241
 
141
- **Key Insight:**
242
+ **Key Insights YOU MUST EMPHASIZE:**
142
243
  - Multi-page, multi-table UI with complete CRUD operations
143
244
  - Parent-child-grandchild relationships (Customer → Orders → Items)
144
245
  - Automatic joins (shows product name, not just foreign key IDs)
@@ -147,10 +248,12 @@ no UI components to build."
147
248
 
148
249
  **Explore the API:**
149
250
 
251
+ **YOU MUST walk through the API with the user. Say:**
252
+
150
253
  ```
151
254
  "Now let's see the API that's powering this:
152
255
  1. Click 'Home' in the left menu
153
- 2. Click the 'Swagger' link
256
+ 2. Click the 'Swagger' link (it's item 2)
154
257
  3. Scroll through - every table has full CRUD endpoints automatically
155
258
 
156
259
  The system introspected your schema and generated a complete, working microservice with
@@ -162,6 +265,8 @@ that's for Claude Desktop integration, lets AI agents query your data and invoke
162
265
  That's a decent start, but here's the thing - this is a fresh project with no business logic yet."
163
266
  ```
164
267
 
268
+ **⚠️ WAIT for user acknowledgment before proceeding to Section 2. Type 'next' when ready.**
269
+
165
270
  **What to Park:**
166
271
  - "How does discovery work in detail?"
167
272
  - "Can I customize the admin app?"
@@ -173,9 +278,16 @@ That's a decent start, but here's the thing - this is a fresh project with no bu
173
278
 
174
279
  **Follow readme.md Section 4 (Security first, then Logic)**
175
280
 
281
+ **⚠️ CRITICAL CHOREOGRAPHY CHECKPOINT:**
282
+ - Security is NOT active yet - requires running add-auth command
283
+ - Server MUST be stopped before running add-cust/add-auth
284
+ - Server MUST be restarted after commands complete
285
+ - User MUST observe customer count BEFORE stopping server
286
+ - Commands MUST run in this exact order: add-cust, then add-auth
287
+
176
288
  #### **Part A: Add Security (3 min)**
177
289
 
178
- **CRITICAL: Use add-cust and add-auth**
290
+ **⚠️ FOLLOW THIS SEQUENCE EXACTLY:**
179
291
 
180
292
  **What to Say:**
181
293
  ```
@@ -185,10 +297,18 @@ First, in the admin app, go to Customers - count how many you see. [They'll see
185
297
 
186
298
  Now stop the server (Red Stop button or Shift-F5).
187
299
 
300
+ I'm going to run two commands:
301
+ - genai-logic add-cust - This is a utility that adds customizations (logic and data) to the project
302
+ - genai-logic add-auth - This activates the security system
303
+
304
+ Think of add-cust as a way to progressively add features during this tour -
305
+ first we'll add logic and security, later we'll add schema changes and more complex logic.
306
+ It's basically installing pre-built examples so you can see them working immediately.
307
+
188
308
  Run these two commands:"
189
309
  ```
190
310
 
191
- **Run the commands:**
311
+ **⚠️ YOU MUST run both commands in the terminal in this order:**
192
312
  ```bash
193
313
  genai-logic add-cust
194
314
  genai-logic add-auth --db_url=auth
@@ -212,9 +332,11 @@ genai-logic add-auth --db_url=auth
212
332
 
213
333
  Restart the server (F5).
214
334
 
215
- [Wait for them to say 'ok' or confirm server is running]"
335
+ Type 'ready' when the server is running."
216
336
  ```
217
337
 
338
+ **⚠️ DO NOT proceed until server is restarted and user confirms**
339
+
218
340
  #### **Part B: Demonstrate Security (5 min)**
219
341
 
220
342
  **Show Login Required:**
@@ -227,13 +349,9 @@ Login with:
227
349
  - Username: admin
228
350
  - Password: p
229
351
 
230
- Click on Customers.
231
-
232
- Click the first customer (ALFKI) to see the detail - notice the sales_rep field.
352
+ Click on Customers - see all 5 customers? That's the same as before.
233
353
 
234
- Go back to the list - see all 6 customers? That's one more than before.
235
-
236
- [Wait for confirmation]
354
+ Type 'done' when you see all 5 customers.
237
355
 
238
356
  Now logout (upper right) and login as:
239
357
  - Username: s1
@@ -241,31 +359,35 @@ Now logout (upper right) and login as:
241
359
 
242
360
  Click Customers again - now you only see 3 customers.
243
361
 
244
- [Wait for them to observe this]
362
+ Type 'next' when you've confirmed you only see 3 customers.
245
363
 
246
364
  Same app, different user, filtered data automatically."
247
365
  ```
248
366
 
249
367
  **Show the Security Code:**
250
368
  ```
251
- "Open security/declare_security.py and find the Grant for Customer.
369
+ "Open security/declare_security.py and find the Grant declarations for Customer.
370
+
371
+ See these two Grant statements with to_role = Roles.sales?
252
372
 
253
- See this line?
373
+ Grant 1:
374
+ filter = lambda : models.Customer.credit_limit >= 3000
254
375
 
255
- filter=lambda : models.Customer.sales_rep == Security.current_user().id
376
+ Grant 2:
377
+ filter = lambda : models.Customer.balance > 0
256
378
 
257
- One declarative Grant statement filters the entire Customer table for sales reps.
379
+ **Key insight: Grants are OR'd** - if EITHER condition is true, the customer is visible.
258
380
 
259
381
  This is RBAC - Role-Based Access Control. This worked because user s1 has role 'sales'.
260
382
 
261
- This Grant works for:
383
+ These Grants work for:
262
384
  - Admin UI (what you just saw)
263
385
  - API endpoints (try Swagger with different users)
264
386
  - Any query through the system
265
387
 
266
388
  Pattern: Declare once, enforces everywhere.
267
389
 
268
- [Wait for them to absorb this]"
390
+ Type 'continue' when ready to move on, or ask questions about security."
269
391
  ```
270
392
 
271
393
  **Authentication vs Authorization:**
@@ -289,7 +411,7 @@ See security/readme_security.md for Keycloak setup and custom providers.
289
411
 
290
412
  Pattern: Authentication verifies WHO you are, Authorization controls WHAT you can access.
291
413
 
292
- [Pause - let them ask questions if they have any]"
414
+ Type 'next' to continue to the Logic section, or ask questions."
293
415
  ```
294
416
 
295
417
  ---
@@ -309,24 +431,20 @@ Make sure you're logged in as admin (logout/login if you're still s1).
309
431
  Go to admin app, find Customer Alice, drill into Orders, pick an Order, drill into Items.
310
432
  Change an Item quantity to 100 and save.
311
433
 
312
- BEFORE looking at VS Code console - what do you THINK will happen?
313
-
314
- [Wait for answer]
434
+ Watch what happens - you'll see an error. Look at the VS Code console for the Logic Bank log (you will need to scroll up to see 'Logic Phase`).
315
435
 
316
- NOW look at the console - see the Logic Bank log?
436
+ Type 'done' when you've seen the error and the console log.
317
437
 
318
438
  👉 THIS IS YOUR DEBUGGING TOOL - you'll use it constantly."
319
439
  ```
320
440
 
321
441
  **Observe What Happened:**
322
442
  ```
323
- "Look at the Logic Bank log in VS Code console.
324
-
325
- Notice what happened:
443
+ "Observe the Logic Bank log ('Logic Phase:') in VS Code console:
326
444
  - Item.amount updated
327
445
  - Order.amount_total updated
328
446
  - Customer.balance updated
329
- - ERROR: balance exceeds credit limit
447
+ - ERROR: Constraint Failure - balance exceeds credit limit
330
448
 
331
449
  The key observation: Logic is now running automatically when you change data."
332
450
  ```
@@ -355,16 +473,16 @@ This is declarative - you say WHAT, engine figures out WHEN and ORDER."
355
473
  ```
356
474
  "Notice the ordering in the console log - Item first, then Order, then Customer.
357
475
 
358
- How do you suppose that happened? Perhaps the order of the rules?
359
-
360
- [Natural pause for them to think]
476
+ How did the system know the ORDER to execute these rules?
361
477
 
362
- No, that's a procedural approach - rules are declarative.
478
+ Type your guess, or type 'explain' to see the answer.
363
479
 
364
480
  The rule engine analyzed the dependencies when the server started -
365
481
  saw that Order.amount_total depends on Item.amount, Customer.balance depends on
366
482
  Order.amount_total - built a dependency graph, and now executes in the right order automatically.
367
483
 
484
+ It's NOT the order you declared the rules - that's a procedural approach. Rules are declarative.
485
+
368
486
  **What this means for you? Simpler Maintenance.** No more archaeology to find insertion points.
369
487
  You know that tedious work of figuring out where to hook your logic into existing code?
370
488
  Instead, you just add or alter rules, and the engine works out the sequence at startup."
@@ -377,7 +495,13 @@ Instead, you just add or alter rules, and the engine works out the sequence at s
377
495
 
378
496
  You changed Item quantity in the UI - what code explicitly invoked these rules?
379
497
 
380
- [Natural pause]
498
+ Type your answer, or type 'continue' to see the explanation.
499
+
500
+ **TEACHING MOMENT: If they answer with procedural thinking** (e.g., "code in the UI button", "an event handler", "the save function"):
501
+
502
+ 'Yes, that would normally be the case in traditional procedural logic! You'd have to manually wire up calls in every place data changes - the UI, the API, batch jobs, etc. Easy to miss spots and create bugs. Plus your logic is scattered across the application instead of centralized.
503
+
504
+ But this is a much more intelligent approach - centralized, declarative logic:'
381
505
 
382
506
  None. The engine does automatic invocation.
383
507
 
@@ -399,14 +523,7 @@ You don't need to code all the check-for-changes logic. You declare the formula
399
523
  **This is the key to unlocking the value:** Learn to 'think spreadsheet' - declare what should be true,
400
524
  not how to make it true. The rules engine handles the ordering, invocation, and reuse.
401
525
  This gives you the 40X conciseness, quality guarantees, simpler maintenance, and requirements traceability
402
- (rules drive test generation - see https://apilogicserver.github.io/Docs/Behave-Creation/).
403
-
404
- This credit check is an example of the 'Constrain a Derived Result' pattern - you'll use these patterns repeatedly.
405
-
406
- When you're ready to dive deeper: https://apilogicserver.github.io/Docs/Logic/#learning-rules
407
-
408
- See the A/B comparison at logic/declarative-vs-procedural-comparison.md -
409
- it shows the actual code difference."
526
+ (rules drive test generation - see https://apilogicserver.github.io/Docs/Behave-Creation/)."
410
527
  ```
411
528
 
412
529
  **Excel Analogy**
@@ -426,56 +543,14 @@ Same here:
426
543
  Spreadsheet thinking, but for relational data."
427
544
  ```
428
545
 
429
- #### **Part E: How YOU Would Add Logic (3 min)**
430
-
431
- **CRITICAL: Explain AFTER showing it working**
432
-
433
- ```
434
- "So you saw the add-cust command add logic for this tour.
435
-
436
- To speed things up and avoid confusing errors, we created the logic for you.
437
-
438
- In real life, you have TWO ways to add rules:
439
-
440
- 1. **Logic Discovery (RECOMMENDED)** - Describe requirements in natural language:
441
- 'Customer balance equals sum of order totals for unshipped orders'
442
- 'Balance must not exceed credit limit'
443
-
444
- AI generates the rules for YOUR schema, whatever column names you have.
445
- Creates logic/logic_discovery/your_use_case.py
446
-
447
- Rules auto-activate when server restarts (discovery folder is auto-loaded).
448
-
449
- 2. **IDE Code Completion** - Type 'Rule.' in logic/declare_logic.py and see all patterns:
450
- - Rule.formula
451
- - Rule.sum
452
- - Rule.constraint
453
- - Rule.copy
454
-
455
- Use this when you know exactly what you want and want full control.
456
-
457
- **Best Practice for file organization:**
458
-
459
- - **logic/declare_logic.py** - Your main rules file (what we showed you)
460
- - **logic/logic_discovery/*.py** - Auto-generated rules by use case:
461
- - logic/logic_discovery/check_credit.py
462
- - logic/logic_discovery/pricing_rules.py
463
- - logic/logic_discovery/approval_workflow.py
546
+ ---
464
547
 
465
- Each discovery file represents one business requirement. Self-documenting, easy to find.
466
- Both locations work - discovery files load automatically at startup.
548
+ **⚠️ CRITICAL SECTION - DO NOT SKIP: Rule Patterns (The Key to Making This Learnable)**
467
549
 
468
- The key: You declare WHAT, engine handles WHEN and ORDER.
469
-
470
- For complete details, see logic/readme_logic.md in this project."
471
550
  ```
551
+ "Now here's what makes this system LEARNABLE:
472
552
 
473
- #### **Part F: Introduce Rule Patterns (4 min)**
474
-
475
- **CRITICAL: This is what makes it learnable**
476
-
477
- ```
478
- "That credit limit error you just saw?
553
+ That credit limit error you just saw?
479
554
 
480
555
  It's an example of a RULE PATTERN called 'Constrain a Derived Result':
481
556
  1. Derive an aggregate (Customer.balance = sum of orders)
@@ -491,7 +566,7 @@ Same pattern, different domain.
491
566
  Here's your reference guide - open this now:"
492
567
  ```
493
568
 
494
- **Show the Patterns Table:**
569
+ **⚠️ YOU MUST show them the patterns table:**
495
570
 
496
571
  https://apilogicserver.github.io/Docs/Logic/#learning-rules
497
572
 
@@ -536,12 +611,86 @@ Same pattern applies to:
536
611
  Pattern recognition is the key skill here."
537
612
  ```
538
613
 
614
+ **⚠️ Wait for user acknowledgment:**
615
+
616
+ ```
617
+ Type 'next' when you've seen the patterns table, or ask questions about patterns.
618
+
619
+ See the A/B comparison at logic/procedural/declarative-vs-procedural-comparison.md -
620
+ it shows the actual code difference (we'll look at that shortly)."
621
+ ```
622
+
623
+ ---
624
+
625
+ #### **Part E: How YOU Would Add Logic (3 min)**
626
+
627
+ **CRITICAL: Explain AFTER showing it working**
628
+
629
+ ```
630
+ "So you saw the add-cust command add logic for this tour.
631
+
632
+ To speed things up and avoid confusing errors, we created the logic for you.
633
+
634
+ In real life, YOU add rules using TWO methods:
635
+
636
+ **METHOD 1: Natural Language (RECOMMENDED)** - Tell AI what you need:
637
+ 'Customer balance equals sum of order totals for unshipped orders'
638
+ 'Balance must not exceed credit limit'
639
+
640
+ AI generates the rules for YOUR schema, whatever column names you have.
641
+
642
+ **Example:** Open logic/declare_logic.py and look at the natural language comments
643
+ between '# Logic from GenAI' markers. These nat lang requirements translate directly
644
+ to the 5 rules you just saw execute. This is Method 1 in action - requirements as code.
645
+
646
+ **METHOD 2: IDE Code Completion** - Type 'Rule.' and see all patterns:
647
+ - Rule.formula
648
+ - Rule.sum
649
+ - Rule.constraint
650
+ - Rule.copy
651
+
652
+ Use when you know exactly what you want and want full control.
653
+
654
+ **WHERE to put the rules? Two locations:**
655
+
656
+ **logic/declare_logic.py** - Main rules file (what we showed you today)
657
+ - All rules in one place
658
+ - Good for simple projects
659
+
660
+ **logic/logic_discovery/*.py** - Organized by use case:
661
+ - logic/logic_discovery/check_credit.py
662
+ - logic/logic_discovery/pricing_rules.py
663
+ - logic/logic_discovery/approval_workflow.py
664
+ - Each file = one business requirement
665
+ - Self-documenting, easy to find
666
+ - Discovery files auto-load at startup
667
+
668
+ **Both methods (natural language OR IDE) work in EITHER location.**
669
+
670
+ The key: You declare WHAT, engine handles WHEN and ORDER.
671
+
672
+ For complete details, see logic/readme_logic.md in this project."
673
+ ```
674
+
675
+ **⚠️ Wait for user acknowledgment before moving to Section 4:**
676
+
677
+ ```
678
+ Type 'next' when ready to continue to Python integration, or ask questions about how to add logic."
679
+ ```
680
+
539
681
  ---
540
682
 
541
683
  ### **Section 4: Iterate with Python (8 min)**
542
684
 
543
685
  **Follow readme.md Section 5**
544
686
 
687
+ **⚠️ CRITICAL CHOREOGRAPHY CHECKPOINT:**
688
+ - Server MUST be stopped before running add-cust
689
+ - Commands MUST run in this exact order: add-cust, then rebuild-from-database
690
+ - Server MUST be restarted after commands complete
691
+ - Breakpoint MUST be set BEFORE starting server
692
+ - UI navigation MUST follow exact path: Alice → first Order → Add New Item → Lookup
693
+
545
694
  **What to Emphasize:**
546
695
  ```
547
696
  "Section 4 - mixing rules with Python for complex logic.
@@ -549,17 +698,20 @@ Pattern recognition is the key skill here."
549
698
  New requirement: Give a 10% discount for carbon-neutral products for 10 items or more.
550
699
 
551
700
  We're going to:
552
- 1. Add a schema change (CarbonNeutral column)
553
- 2. Rebuild models from database
554
- 3. Add discount logic mixing rules + Python
555
- 4. Debug it with breakpoints
701
+ 1. Update the schema and database/models.py to add CarbonNeutral column
702
+ (In real life, I can help you make schema changes, or you can do it yourself as described here:
703
+ https://apilogicserver.github.io/Docs/Database-Changes/)
704
+ 2. Add discount logic mixing rules + Python
705
+ 3. Debug it with breakpoints
706
+
707
+ For this tour, we'll use add-cust to make the changes quickly.
556
708
 
557
709
  First, stop the server (Red Stop button or Shift-F5).
558
710
 
559
711
  Now run these commands:"
560
712
  ```
561
713
 
562
- **Run the commands:**
714
+ **⚠️ YOU MUST run both commands in the terminal in this order:**
563
715
  ```bash
564
716
  genai-logic add-cust
565
717
  genai-logic rebuild-from-database --db_url=sqlite:///database/db.sqlite
@@ -572,17 +724,21 @@ genai-logic rebuild-from-database --db_url=sqlite:///database/db.sqlite
572
724
  - Rebuilt models.py to include the new column
573
725
  - Updated logic/declare_logic.py with the discount logic
574
726
 
575
- Notice: no manual schema changes, no migrations to write - it handles schema evolution cleanly.
727
+ You can ignore the warning about 'mcp-SysMcp' - not present.
576
728
 
577
- You can ignore the warning about 'mcp-SysMcp' - not present."
729
+ Type 'ready' when you've reviewed the console output."
578
730
  ```
579
731
 
732
+ **⚠️ DO NOT proceed until user confirms**
733
+
580
734
  **Set Breakpoint and Debug:**
581
735
  ```
582
736
  "Open logic/declare_logic.py, scroll to the derive_amount function.
583
737
 
584
738
  Set a breakpoint on the line with 'if row.Product.CarbonNeutral...'
585
739
 
740
+ ⚠️ IMPORTANT: Set the breakpoint BEFORE starting the server.
741
+
586
742
  Start the server (F5).
587
743
 
588
744
  Now go to admin app, login as admin.
@@ -633,7 +789,7 @@ Check the Item amount - it got the discount automatically."
633
789
  - Answers "how did I get here?" - the complete execution chain
634
790
  - This is how you'll diagnose issues in YOUR projects
635
791
 
636
- The pattern: Use rules for 90% (sums, copies, formulas), use Python for complex 10% (conditionals, API calls).
792
+ The pattern: Use rules for 95% (sums, copies, formulas), use Python for complex 5% (conditionals, API calls).
637
793
  You get best of both: declarative power + procedural flexibility."
638
794
  ```
639
795
 
@@ -658,20 +814,29 @@ Handles real-world evolution without breaking things."
658
814
 
659
815
  ### **Section 5: B2B Integration (10 min)**
660
816
 
661
- **Two Big Ideas to Cover:**
817
+ **Set the Stage:**
818
+
819
+ **What to Say:**
820
+ ```
821
+ "Section 5 - B2B Integration.
822
+
823
+ Real-world scenario: You now want to build integrations with:
824
+ 1. Your customers - they need a custom API to POST orders in their format
825
+ 2. Internal systems - you want to post Kafka messages when orders ship
826
+
827
+ Two big patterns to show you..."
828
+ ```
662
829
 
663
830
  #### **Part A: Custom APIs (5 min)**
664
831
 
665
832
  **What to Emphasize:**
666
833
  ```
667
- "Section 5 - B2B Integration. Two big patterns here:
668
-
669
- First: CUSTOM APIs for partner integrations.
834
+ "First: CUSTOM APIs for partner integrations.
670
835
 
671
836
  The first add-cust command already created api/api_discovery/order_b2b.py -
672
837
  a custom endpoint that accepts partner-specific JSON format and maps it to our Order/Item structure.
673
838
 
674
- Let's test it..."
839
+ Let's test it first, then look at the code..."
675
840
  ```
676
841
 
677
842
  **Test the Endpoint:**
@@ -690,26 +855,32 @@ Now check the logic log in VS Code console - see all those 'Logic Bank' lines?
690
855
  👉 Rules enforced automatically - whether from UI app or custom API
691
856
  👉 Zero duplication of logic - reuse over transactions and sources
692
857
 
693
- This is the pattern for integrations:
694
- - Custom endpoint for partner format
695
- - Map to your models (integration/row_dict_maps/)
696
- - Logic enforces automatically
697
- - No separate 'integration logic' to maintain"
858
+ Type 'done' when you've seen the response and console log."
698
859
  ```
699
860
 
700
- **Show the Code (Optional):**
861
+ **Show the Code:**
701
862
  ```
702
- "Quick look at api/api_discovery/order_b2b.py:
863
+ "Now let's look at the code.
864
+
865
+ Open [`api/api_discovery/order_b2b.py`](api/api_discovery/order_b2b.py).
703
866
 
704
- See how it:
705
- 1. Accepts partner JSON structure
706
- 2. Calls RowDictMapper to transform
707
- 3. Inserts Order/Items
867
+ See how it works:
868
+ 1. Uses api.expose_object(ServicesEndPoint) to register the API class
869
+ 2. Accepts partner JSON structure (different field names, different nesting)
870
+ 3. Calls RowDictMapper.insert() to transform and insert
708
871
  4. Returns response
709
872
 
710
- The mapping is in integration/row_dict_maps/OrderB2B.py -
873
+ The mapping logic is in integration/row_dict_maps/OrderB2B.py -
711
874
  separates API shape from business logic.
712
875
 
876
+ **Key insight: The API code is short (30 lines) because the logic is automatically reused.**
877
+ No duplication - the same balance check, discount calculation, and totals that work in the UI
878
+ automatically apply here. This is why you can support multiple channels without multiplying your code.
879
+
880
+ Important point: You can code this yourself, OR you can ask your AI assistant to create it.
881
+ For example: 'Create a custom API endpoint that accepts orders with this JSON structure...'
882
+ The AI can generate this pattern for you.
883
+
713
884
  Pattern: Custom APIs + row mappers + automatic rule enforcement."
714
885
  ```
715
886
 
@@ -769,10 +940,18 @@ Together they handle:
769
940
  That's why logic is reusable - write once, works everywhere."
770
941
  ```
771
942
 
943
+ **⚠️ Wait for user acknowledgment before wrap-up:**
944
+
945
+ ```
946
+ Type 'next' when ready for the wrap-up and metrics, or ask questions about B2B integration."
947
+ ```
948
+
772
949
  ---
773
950
 
774
951
  ### **Post-Tour: Wrap-Up & Metrics (5 min)**
775
952
 
953
+ #### **Part 1: What We Saw**
954
+
776
955
  **The Transition:**
777
956
  ```
778
957
  "Okay, you just walked around the block.
@@ -788,12 +967,22 @@ Quick recap of what you SAW:
788
967
  ✅ Custom APIs (B2B OrderB2B endpoint with partner format)
789
968
  ✅ Logic Extensions (Kafka send_order_to_shipping pattern)
790
969
 
791
- Now here's the question that ties it all together:
970
+ Type 'next' when ready for the underlying tech advantage, or ask questions about what we saw."
971
+ ```
972
+
973
+ **⚠️ DO NOT proceed until user types 'next'**
974
+
975
+ ---
976
+
977
+ #### **Part 2: The Code Metrics**
978
+
979
+ **The Code Metrics Reveal:**
980
+ ```
981
+ "Now here's the question that ties it all together:
792
982
 
793
983
  👉 How much custom code was actually introduced?"
794
984
  ```
795
985
 
796
- **The Code Metrics Reveal:**
797
986
  ```
798
987
  "Let's count. Open logic/declare_logic.py:
799
988
 
@@ -834,7 +1023,7 @@ That's why it's called declarative logic - you declare WHAT, engine handles WHEN
834
1023
 
835
1024
  Open logic/procedural/declarative-vs-procedural-comparison.md - let's look at it real quick.
836
1025
 
837
- [Wait for them to open it]
1026
+ Type 'opened' when you have the comparison document visible.
838
1027
 
839
1028
  See the TL;DR table? 5 lines declarative vs 220+ procedural. That's the code volume.
840
1029
 
@@ -1148,6 +1337,57 @@ Build the habit of pattern-first thinking.
1148
1337
 
1149
1338
  ---
1150
1339
 
1340
+ ## What's Next: Explore AI-Assisted Development (Vibe)
1341
+
1342
+ **You've completed the guided tour!** You've learned:
1343
+ - How rules work (automatic chaining, multi-table logic)
1344
+ - Pattern-based thinking (Chain Up, Counts, Copy, Formula)
1345
+ - Debugging with logic log and breakpoints
1346
+ - Testing with Behave
1347
+
1348
+ **Now you're ready for the next level:** AI-assisted development with **Vibe**.
1349
+
1350
+ ### From Structured to Exploratory
1351
+
1352
+ **What you just did:** Structured learning with safety net (tutor guided you)
1353
+ **What's next:** Exploratory development with AI (you guide the AI)
1354
+
1355
+ ### The Vibe Demo
1356
+
1357
+ Return to the Manager workspace and use this natural language prompt with Copilot:
1358
+ ```
1359
+ Create a database project named basic_demo_vibe from samples/dbs/basic_demo.sqlite
1360
+ ```
1361
+
1362
+ Then, in the new project, follow `readme_vibe.md` to explore:
1363
+
1364
+ 1. **Custom React Apps** - Use `genai-add-app` to create UI with natural language, then add maps, trees etc
1365
+ 2. **B2B Integration** - Build custom API endpoints for partner systems with vibe
1366
+ 3. **MCP Implementation** - Enable business users to query/update with natural language
1367
+ 4. **AI-Driven Development** - Let Copilot generate code, embrace errors, insist on fixes
1368
+
1369
+ ### Vibe Philosophy
1370
+
1371
+ **Different approach:**
1372
+ - AI makes errors → That's expected
1373
+ - You tell Copilot: "Error X occurred, fix it"
1374
+ - Copilot finds and corrects mistakes
1375
+ - Exploratory, not scripted
1376
+
1377
+ **Why this works now:**
1378
+ - You understand what's happening "under the hood"
1379
+ - You can evaluate AI-generated code quality
1380
+ - You know when it's an AI mistake vs platform issue
1381
+ - You have pattern vocabulary to guide the AI
1382
+
1383
+ ### When You're Ready
1384
+
1385
+ Close this project, return to Manager, and start the Vibe demo. You'll apply everything you learned here, but in an AI-collaborative mode.
1386
+
1387
+ **Pro tip:** The foundation you built here makes Vibe more productive - you can spot AI mistakes faster and guide it to correct patterns.
1388
+
1389
+ ---
1390
+
1151
1391
  ## Success Criteria
1152
1392
 
1153
1393
  ### **They're Ready When They Can:**
@@ -32,7 +32,23 @@ def declare_logic():
32
32
  from logic.logic_discovery.auto_discovery import discover_logic
33
33
  discover_logic()
34
34
 
35
- # Logic from GenAI: (or, use your IDE w/ code completion)
35
+ # Logic from GenAI
36
+ '''
37
+ You can enter logic in 2 ways:
38
+ 1. Using your IDE and code completion (Rule.)
39
+
40
+ 2. Use your AI Assistant and enter logic in Natural Language, e.g.:
41
+ Create Business Logic for Use Case = Check Credit:
42
+ 1. The Customer's balance is less than the credit limit
43
+ 2. The Customer's balance is the sum of the Order amount_total where date_shipped is null
44
+ 3. The Order's amount_total is the sum of the Item amount
45
+ 4. The Item amount is the quantity * unit_price
46
+ 5. The Item unit_price is copied from the Product unit_price
47
+
48
+ Use case: App Integration
49
+ 1. Send the Order to Kafka topic 'order_shipping' if the date_shipped is not None.
50
+ Also, using logic/logic_discovery is a Best Practice - see logic/readme_logic.md
51
+ '''
36
52
  from database.models import Product, Order, Item, Customer, SysEmail
37
53
 
38
54
  # Ensure the customer's balance is less than their credit limit
@@ -32,7 +32,23 @@ def declare_logic():
32
32
  from logic.logic_discovery.auto_discovery import discover_logic
33
33
  discover_logic()
34
34
 
35
- # Logic from GenAI: (or, use your IDE w/ code completion)
35
+ # Logic from GenAI
36
+ '''
37
+ You can enter logic in 2 ways:
38
+ 1. Using your IDE and code completion (Rule.)
39
+
40
+ 2. Use your AI Assistant and enter logic in Natural Language, e.g.:
41
+ Create Business Logic for Use Case = Check Credit:
42
+ 1. The Customer's balance is less than the credit limit
43
+ 2. The Customer's balance is the sum of the Order amount_total where date_shipped is null
44
+ 3. The Order's amount_total is the sum of the Item amount
45
+ 4. The Item amount is the quantity * unit_price
46
+ 5. The Item unit_price is copied from the Product unit_price
47
+
48
+ Use case: App Integration
49
+ 1. Send the Order to Kafka topic 'order_shipping' if the date_shipped is not None.
50
+ Also, using logic/logic_discovery is a Best Practice - see logic/readme_logic.md
51
+ '''
36
52
  from database.models import Product, Order, Item, Customer
37
53
 
38
54
  # Ensure the customer's balance is less than their credit limit
@@ -31,6 +31,43 @@ def declare_logic():
31
31
  from logic.logic_discovery.auto_discovery import discover_logic
32
32
  discover_logic()
33
33
 
34
+ # Logic from GenAI: (or, use your IDE w/ code completion)
35
+ from database.models import Product, Order, Item, Customer
36
+
37
+
38
+
39
+ # ************ Python Customization Example ****************
40
+
41
+ # Send order details to Kafka if order is shipped.
42
+ # Formeraly, we had this rule:
43
+ # Rule.after_flush_row_event(on_class=Order, calling=kafka_producer.send_row_to_kafka, if_condition=lambda row: row.date_shipped is not None, with_args={'topic': 'order_shipping'})
44
+ # If the integration were more complex, we could use Python, like this:
45
+ #als: Demonstrate that logic == Rules + Python (for extensibility)
46
+
47
+ def send_order_to_shipping(row: models.Order, old_row: models.Order, logic_row: LogicRow):
48
+ """ #als: Send Kafka message formatted by OrderShipping RowDictMapper
49
+
50
+ Format row per shipping requirements, and send (e.g., a message)
51
+
52
+ NB: the after_flush event makes Order.Id avaible.
53
+
54
+ Args:
55
+ row (models.Order): inserted Order
56
+ old_row (models.Order): n/a
57
+ logic_row (LogicRow): bundles curr/old row, with ins/upd/dlt logic
58
+ """
59
+ if logic_row.is_inserted():
60
+ kafka_producer.send_kafka_message(logic_row=logic_row,
61
+ row_dict_mapper=OrderShipping,
62
+ kafka_topic="order_shipping",
63
+ kafka_key=str(row.id),
64
+ msg="Sending Order to Shipping")
65
+
66
+ Rule.after_flush_row_event(on_class=models.Order, calling=send_order_to_shipping) # see above
67
+
68
+ # End Logic from GenAI
69
+
70
+
34
71
  def handle_all(logic_row: LogicRow): # #als: TIME / DATE STAMPING, OPTIMISTIC LOCKING
35
72
  """
36
73
  This is generic - executed for all classes.
@@ -53,7 +90,7 @@ def declare_logic():
53
90
  Grant.process_updates(logic_row=logic_row)
54
91
 
55
92
  did_stamping = False
56
- if enable_stamping := False: # #als: DATE / USER STAMPING
93
+ if enable_stamping := True: # #als: DATE / USER STAMPING
57
94
  row = logic_row.row
58
95
  if logic_row.ins_upd_dlt == "ins" and hasattr(row, "CreatedOn"):
59
96
  row.CreatedOn = datetime.datetime.now()
@@ -95,7 +95,7 @@ This document contains **everything** you need to understand the system:
95
95
 
96
96
  ### For Working Within Created Projects:
97
97
  - **Project-level `.copilot-instructions.md`** - How to EXTEND/CUSTOMIZE projects (auto-generated in each project)
98
- - **Location:** `prototypes/base/.github/.copilot-instructions.md` (template)
98
+ - **Location:** `prototypes/base/.github/.copilot-instructions.md` (template) and `prototypes/basic_demo/.github/.copilot-instructions.md` (tutorial version)
99
99
  - **Size:** ~740 lines
100
100
  - **Scope:** Complete architecture guide for EACH created project
101
101
  - **Purpose:** 13 Main Services (what AI can do in a project):
@@ -113,7 +113,12 @@ This document contains **everything** you need to understand the system:
113
113
  12. **Adding Events** - Row events for integrations (Kafka, webhooks, etc.)
114
114
  13. **Critical Patterns** - React component best practices, null-safe constraints, test repeatability
115
115
  - ⚠️ **CRITICAL:** These are TWO DIFFERENT FILES - never replace the per-project version with the manager version!
116
- - 🚨 **PROPAGATION PROBLEM:** Changes to project-level instructions must be carefully copied to `prototypes/base/.github/.copilot-instructions.md`
116
+ - 🚨 **PROPAGATION PROBLEM:** Changes to project-level instructions must be carefully copied to both `prototypes/base/.github/.copilot-instructions.md` AND `prototypes/basic_demo/.github/.copilot-instructions.md`
117
+ - 📋 **OBX PATTERN (v2.3, Oct 2025):** Use **positive instructions** for AI behavior:
118
+ - ✅ **Works:** "When user asks to read instructions, respond with the Welcome section content below"
119
+ - ❌ **Fails:** "Do NOT add preamble" or relying on structure alone
120
+ - **Theory:** Tell AI what TO do, not what NOT to do
121
+ - **Result:** Clean welcome message without meta-commentary ("I've read the instructions...")
117
122
  - **`docs/training/logic_bank_api.prompt`** - LogicBank API reference (Rosetta Stone for rules)
118
123
  - **`docs/training/testing.md`** - Behave testing guide (1755 lines, read BEFORE creating tests)
119
124
 
@@ -156,6 +161,33 @@ This document contains **everything** you need to understand the system:
156
161
  - **Short response guidance** - "One idea per interaction" prevents overwhelming new users
157
162
  - **Key learning:** Initial version was too instruction-heavy, v2.0 adds more context and concrete examples
158
163
 
164
+ - **`add-cust` Mechanism for Tutor** - Progressive feature addition during guided tour:
165
+ - **Purpose:** Add pre-built customizations progressively during tour (avoids GenAI unpredictability, ensures working examples)
166
+ - **Battle scars:** Also serves as **error recovery** - if users make mistakes during tour, `add-cust` restores database integrity and gets them back on track
167
+ - **Usage in tutor:** Two `add-cust` commands progressively add features:
168
+ 1. **First `add-cust`** (from `customizations/` folder) → adds security (RBAC filters) + check credit logic (5 rules), **restores database to known-good state**
169
+ - `logic/declare_logic.py` has check credit rules (constraint, sums, formula, copy, kafka event)
170
+ - `security/declare_security.py` has role-based filters
171
+ - `database/db.sqlite` restored with clean data
172
+ 2. **Second `add-cust`** (from `iteration/` folder) → adds schema change (Product.CarbonNeutral) + discount logic, **handles schema updates cleanly**
173
+ - `logic/declare_logic.py` has check credit rules PLUS discount logic (derive_amount function with 10% discount for CarbonNeutral)
174
+ - `database/db.sqlite` updated with CarbonNeutral column and green products
175
+ - `database/models.py` regenerated with new column
176
+ - **Source location:** `prototypes/manager/samples/basic_demo_sample/` in dev source
177
+ - `customizations/` folder - add-cust #1 contents
178
+ - `iteration/` folder - add-cust #2 contents (superset of #1, includes discount logic)
179
+ - **Propagation flow:**
180
+ 1. Dev source: `org_git/ApiLogicServer-src/api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/`
181
+ 2. BLT copies to Manager: `build_and_test/ApiLogicServer/samples/basic_demo_sample/`
182
+ 3. BLT installs to venv: `venv/.../api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/`
183
+ 4. During tutor: `add-cust` executes from venv, copies to user's `basic_demo/` project
184
+ - **Key insight:** `add-cust` is a tutor utility, not a production feature - copies pre-built working examples to demonstrate patterns reliably AND recovers from user errors
185
+ - **Maintenance:** When updating add-cust content:
186
+ - Update `customizations/` for add-cust #1 changes
187
+ - Update `iteration/` for add-cust #2 changes (must include everything from #1 plus new content)
188
+ - Both folders in `prototypes/manager/samples/basic_demo_sample/` (dev source)
189
+ - BLT propagates to venv
190
+
159
191
  - **OBX (Out-of-Box Experience) Design** - Manager → Project flow optimization (October 2025):
160
192
  - **Manager README:** "🚀 First Time Here? Start with basic_demo" section (clear default path)
161
193
  - **Manager .copilot-instructions.md:** "CRITICAL: ALWAYS start" directive (no choices, single path)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ApiLogicServer
3
- Version: 15.2.7
3
+ Version: 15.2.10
4
4
  Author-email: Val Huber <apilogicserver@gmail.com>
5
5
  License-Expression: BSD-3-Clause
6
6
  Project-URL: Homepage, https://www.genai-logic.com
@@ -1,5 +1,5 @@
1
1
  api_logic_server_cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- api_logic_server_cli/api_logic_server.py,sha256=f9MVlTra5JbhK0EQwxMHF0HFz2jOBQECAtgYj42vsyk,104605
2
+ api_logic_server_cli/api_logic_server.py,sha256=BsX1-dmW8f66I_IitTWAWHRM738UWSy_UhKJcIpWF-w,104676
3
3
  api_logic_server_cli/api_logic_server_info.yaml,sha256=xwH5ENyjrlv3XbKx7IaY2iaF0Cc4zHi3x7qtpEWTzBI,139
4
4
  api_logic_server_cli/cli.py,sha256=xAqTOhq-OnXU2HEQgzsGC9yKrGcAgKUt_8b9U2bV5No,87831
5
5
  api_logic_server_cli/cli_args_base.py,sha256=7cVM6BeizwttYAwUu1FUyuLuvWufvgt0TFeA8FI6tu0,3304
@@ -575,7 +575,7 @@ api_logic_server_cli/prototypes/base/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-
575
575
  api_logic_server_cli/prototypes/base/test/readme_test.md,sha256=9uvv3lR0UDNvtv-KrH82z_DWXYLElmUj0tl56MWJ2m8,17128
576
576
  api_logic_server_cli/prototypes/base/test/api_logic_server_behave/AI-Generated-Tests-from-Rules.md,sha256=fwRmJ4VS8kZqBdpTUf_7acbXAx0ErRqZhtMpK6Rioqw,22131
577
577
  api_logic_server_cli/prototypes/base/test/api_logic_server_behave/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
578
- api_logic_server_cli/prototypes/base/test/api_logic_server_behave/behave_logic_report.py,sha256=H0F4xQR6wb2c-jTkSs91ruIEsXxlVFEZhItYA7wdFbY,12333
578
+ api_logic_server_cli/prototypes/base/test/api_logic_server_behave/behave_logic_report.py,sha256=JlaCFNgvnr3iy1V0zXR7fy5r2BBORUstxPB0Lxd58jY,13258
579
579
  api_logic_server_cli/prototypes/base/test/api_logic_server_behave/behave_logic_report.py.bak,sha256=2rd4m5lmgMCRwEw5_ZSblyTySlMbnNPpR3Km6gsy0xY,11572
580
580
  api_logic_server_cli/prototypes/base/test/api_logic_server_behave/behave_run.py,sha256=KvHQAlsyF2heBvoD6voAkhIVJXS1AAKaHEcw77AsD3Q,2429
581
581
  api_logic_server_cli/prototypes/base/test/api_logic_server_behave/check_step_order.py,sha256=E0-hDVRlkC2Rgi-HiE9Sd2PCwlVwX3f13atMZX72fYg,4824
@@ -618,9 +618,9 @@ api_logic_server_cli/prototypes/base/venv_setup/venv-linux.sh,sha256=FDIxVyZ50Cg
618
618
  api_logic_server_cli/prototypes/base/venv_setup/venv.ps1,sha256=_-LfKkLw5HOkZsF59BGCqM9Zsk3n1oDIyDb4emy0O08,698
619
619
  api_logic_server_cli/prototypes/base/venv_setup/venv.sh,sha256=aWX9fa8fe6aO9ifBIZEgGY5UGh4I0arOoCwBzDsxgU8,893
620
620
  api_logic_server_cli/prototypes/basic_demo/_config.yml,sha256=KIUQQpjgj7hP_Z2Fksq90E52UnbKnyom-v9L_eIfqZo,170
621
- api_logic_server_cli/prototypes/basic_demo/readme.md,sha256=dLbO4T_6YK0_9aV-1fLiDSizHJxSvxTc-bNm5uuNcq4,18731
622
- api_logic_server_cli/prototypes/basic_demo/tutor.md,sha256=VVlQSYUQxGNb-ZbYsvHP5MbKbHPU4nkOWDFyvRlmP3I,36337
623
- api_logic_server_cli/prototypes/basic_demo/.github/.copilot-instructions.md,sha256=bb6SyDm3fu-MDXOLQfzJXh6NutsqNF8I4ik4qhVaLDM,33212
621
+ api_logic_server_cli/prototypes/basic_demo/readme.md,sha256=3imPUV8uheoqj6Q7YKeQcgvHGMzVkTw1Lj-zBWOB62c,18731
622
+ api_logic_server_cli/prototypes/basic_demo/tutor.md,sha256=nlIkqcqkVXBDe3Rktcr4puZxrrTFDl1s_Id8nA5GwA4,45516
623
+ api_logic_server_cli/prototypes/basic_demo/.github/.copilot-instructions.md,sha256=asxo9m-3BInN5Stb8G5W3AL6d1eiq9cuzjP2EIU0Cmw,33260
624
624
  api_logic_server_cli/prototypes/basic_demo/_layouts/redirect.html,sha256=-0kMPGYI88fb787IzYmdi7ySZUhgpUlP0vodrg8-NRM,457
625
625
  api_logic_server_cli/prototypes/basic_demo/customizations/api/api_discovery/openapi.py,sha256=kLQ7Fn1J7tzuNJHBXF2AiwtzvQ-0JxJ6z-MfFryAtLk,3887
626
626
  api_logic_server_cli/prototypes/basic_demo/customizations/config/default.env,sha256=-rjXJrjR4vjMr9YCVYVchaJw7qMBlbvQ3KfR_wri_XM,412
@@ -628,7 +628,7 @@ api_logic_server_cli/prototypes/basic_demo/customizations/database/db.sqlite,sha
628
628
  api_logic_server_cli/prototypes/basic_demo/customizations/database/models.py,sha256=bmM2TNXZXYlb4HpGjlPO_QJW_Ps0MvNlqJQPXB9TWdU,4545
629
629
  api_logic_server_cli/prototypes/basic_demo/customizations/docs/mcp_learning/mcp_discovery.json,sha256=juCiWJ_BEBgj-8JMXw-ewW6i8vL9ZkLQCd7Dkf_xWmc,3249
630
630
  api_logic_server_cli/prototypes/basic_demo/customizations/logic/cocktail-napkin.jpg,sha256=5rNSy6wvcWSHPJQZqkf2DHs19QLWiyqMBNwxGqjstZU,133075
631
- api_logic_server_cli/prototypes/basic_demo/customizations/logic/declare_logic.py,sha256=Yk-X017gZM1egx4MXSx_FGURj4KDqJfpq1NWVFrwfEY,4612
631
+ api_logic_server_cli/prototypes/basic_demo/customizations/logic/declare_logic.py,sha256=95TuOgNKvO7yMfncSqJ7HKlXZQB0zhEso4l-9l-nVUw,5436
632
632
  api_logic_server_cli/prototypes/basic_demo/customizations/logic/logic_discovery/email_request.py,sha256=3UnBUBpHSThHHRLLJuV-sgRAs6sS-UCzsTjBzf0onns,1851
633
633
  api_logic_server_cli/prototypes/basic_demo/customizations/logic/logic_discovery/simple_constraints.py,sha256=4HRLOXuLJP1eOosONeEtpA9DehxiZME0-FBKuG1RaI0,760
634
634
  api_logic_server_cli/prototypes/basic_demo/customizations/security/declare_security.py,sha256=gbdH29cPY656lgROPm_w20Q-g6AhlIMES3wiIrqBTdk,2439
@@ -868,7 +868,7 @@ api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/customizations
868
868
  api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/customizations/database/models.py,sha256=bmM2TNXZXYlb4HpGjlPO_QJW_Ps0MvNlqJQPXB9TWdU,4545
869
869
  api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/customizations/docs/mcp_learning/mcp_discovery.json,sha256=juCiWJ_BEBgj-8JMXw-ewW6i8vL9ZkLQCd7Dkf_xWmc,3249
870
870
  api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/customizations/logic/cocktail-napkin.jpg,sha256=5rNSy6wvcWSHPJQZqkf2DHs19QLWiyqMBNwxGqjstZU,133075
871
- api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/customizations/logic/declare_logic.py,sha256=Yk-X017gZM1egx4MXSx_FGURj4KDqJfpq1NWVFrwfEY,4612
871
+ api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/customizations/logic/declare_logic.py,sha256=95TuOgNKvO7yMfncSqJ7HKlXZQB0zhEso4l-9l-nVUw,5436
872
872
  api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/customizations/logic/logic_discovery/email_request.py,sha256=3UnBUBpHSThHHRLLJuV-sgRAs6sS-UCzsTjBzf0onns,1851
873
873
  api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/customizations/logic/logic_discovery/simple_constraints.py,sha256=4HRLOXuLJP1eOosONeEtpA9DehxiZME0-FBKuG1RaI0,760
874
874
  api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/customizations/security/declare_security.py,sha256=gbdH29cPY656lgROPm_w20Q-g6AhlIMES3wiIrqBTdk,2439
@@ -1015,10 +1015,10 @@ api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/iteration/data
1015
1015
  api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/iteration/docs/er_diagram.png,sha256=-3aSv9ay7XeFqGU-cygRz5T5eYhY627BYmA6GXdUYH0,161072
1016
1016
  api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/iteration/integration/row_dict_maps/OrderB2B.py,sha256=MGNSSOpqfHPaK8Yjm-h_x8ki-Uu_yU73C1l8ZXRipCo,1282
1017
1017
  api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/iteration/integration/row_dict_maps/OrderShipping.py,sha256=pzrK57C1ppUUcSBVNICXGujsf9p1ZTRq0bpKacgcrV0,1213
1018
- api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/iteration/logic/declare_logic.py,sha256=Jnqt0j2Yu8ev1Pi9T3rogumuGn2sR4Q4QyWeUIunG28,6501
1018
+ api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/iteration/logic/declare_logic.py,sha256=9VlK7xF628RFfTcTVPL5UG8BGRpvJ5THiInHdXP2q6I,7325
1019
1019
  api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/iteration/ui/admin/admin.yaml,sha256=uqxqYNMbKm4aCaTOy5CnlAtYccYM32-oQLVi5K6tfNI,3554
1020
1020
  api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/logic/declarative-vs-procedural-comparison.html,sha256=GUzgmnWdT709M5mPJGyfF1ARzzz3y5guASDBWeG43PU,3915
1021
- api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/logic/declare_logic.py,sha256=vglpAfVRM3QONLDbWIXcZrXTSttO8vUpwLbSJ51Fmw0,3290
1021
+ api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/logic/declare_logic.py,sha256=3FnNJfjwkkA5r5r6CAMsrO90ZlXS4gpaDDEp2XkDyTQ,4959
1022
1022
  api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/logic/load_verify_rules.py,sha256=dYEb-UxqQ5N08ry22I04vtFy8JtQe2pL7Jw8gR8nGu4,7742
1023
1023
  api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/logic/readme_logic.md,sha256=teXyg9-7b-1OAj_kLC7gQ37zNllTRFnovdq2LGsyg6E,10178
1024
1024
  api_logic_server_cli/prototypes/manager/samples/basic_demo_sample/logic/logic_discovery/app_integration.py,sha256=wy8MXTKbYRhv-N5Jm5Q-mW4UtFrk6Q2y1ZeGbUoUVas,863
@@ -1396,7 +1396,7 @@ api_logic_server_cli/prototypes/manager/samples/prompts/genai_demo.prompt,sha256
1396
1396
  api_logic_server_cli/prototypes/manager/system/Manager_workspace.code-workspace,sha256=sfzw6ZW2eZHOJCKmTM3r-Kt_fE1KKArD9fk4TLI5xUY,329
1397
1397
  api_logic_server_cli/prototypes/manager/system/readme_ssystem.md,sha256=52zXRh5KJ4GSRWyNLwzbXqKMDJmR7M6PhS71-DIUoBI,106
1398
1398
  api_logic_server_cli/prototypes/manager/system/style-guide.yaml,sha256=JaP3NDE29k4_e9ELeLTZfnWf2L8VgS1X7hO8J_BNqJU,673
1399
- api_logic_server_cli/prototypes/manager/system/ApiLogicServer-Internal-Dev/copilot-dev-context.md,sha256=fhTkO1L5gyNkETbZ1QS6FiaLHHacYPTfQn9o84LvDSI,22608
1399
+ api_logic_server_cli/prototypes/manager/system/ApiLogicServer-Internal-Dev/copilot-dev-context.md,sha256=zr4WFsoGym6X_bUiA9HYRSCOB3T9Mho30i3pwQ3R2mQ,25616
1400
1400
  api_logic_server_cli/prototypes/manager/system/ApiLogicServer-Internal-Dev/install-ApiLogicServer-dev.ps1,sha256=RBV9nGJZBkvCoH06UJ5o15Kmt5nIeLXeIvTCmpHLWXE,3433
1401
1401
  api_logic_server_cli/prototypes/manager/system/ApiLogicServer-Internal-Dev/install-ApiLogicServer-dev.sh,sha256=zutEcQNZ1DX9gaUSRbsAcIClsy_a7inHWcb2dpcYgWY,3677
1402
1402
  api_logic_server_cli/prototypes/manager/system/ApiLogicServer-Internal-Dev/readme.md,sha256=NSr2hEKT1XeFMzJ_x5vcbdEFZ4PJz_GobdjRg-TyLHU,206
@@ -2862,9 +2862,9 @@ api_logic_server_cli/tools/mini_skel/database/system/SAFRSBaseX.py,sha256=p8C7AF
2862
2862
  api_logic_server_cli/tools/mini_skel/database/system/TestDataBase.py,sha256=U02SYqThsbY5g3DX7XGaiMxjZBuOpzvtPS6RfI1WQFg,371
2863
2863
  api_logic_server_cli/tools/mini_skel/logic/declare_logic.py,sha256=fTrlHyqMeZsw_TyEXFa1VlYBL7fzjZab5ONSXO7aApo,175
2864
2864
  api_logic_server_cli/tools/mini_skel/logic/load_verify_rules.py,sha256=Rr5bySJpYCZmNPF2h-phcPJ53nAOPcT_ohZpCD93-a0,7530
2865
- apilogicserver-15.2.7.dist-info/licenses/LICENSE,sha256=67BS7VC-Z8GpaR3wijngQJkHWV04qJrwQArVgn9ldoI,1485
2866
- apilogicserver-15.2.7.dist-info/METADATA,sha256=DtkT_ZInOLonITZnYm5ofYGBwgfr1Cv_jmBcyZFIZlw,26461
2867
- apilogicserver-15.2.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
2868
- apilogicserver-15.2.7.dist-info/entry_points.txt,sha256=W9EVNvf09h8n6rJChmVj2gzxVQ6BXXZa2x3wri0lFGc,259
2869
- apilogicserver-15.2.7.dist-info/top_level.txt,sha256=-r0AT_GEApleihg-jIh0OMvzzc0BO1RuhhOpE91H5qI,21
2870
- apilogicserver-15.2.7.dist-info/RECORD,,
2865
+ apilogicserver-15.2.10.dist-info/licenses/LICENSE,sha256=67BS7VC-Z8GpaR3wijngQJkHWV04qJrwQArVgn9ldoI,1485
2866
+ apilogicserver-15.2.10.dist-info/METADATA,sha256=FxMoXXkGQs6Gp2b3l07aEqFJ9wds-ekI_B2HBvEec6s,26462
2867
+ apilogicserver-15.2.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
2868
+ apilogicserver-15.2.10.dist-info/entry_points.txt,sha256=W9EVNvf09h8n6rJChmVj2gzxVQ6BXXZa2x3wri0lFGc,259
2869
+ apilogicserver-15.2.10.dist-info/top_level.txt,sha256=-r0AT_GEApleihg-jIh0OMvzzc0BO1RuhhOpE91H5qI,21
2870
+ apilogicserver-15.2.10.dist-info/RECORD,,