@autobe/agent 0.30.2 → 0.30.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/lib/AutoBeMockAgent.js +0 -2
  2. package/lib/AutoBeMockAgent.js.map +1 -1
  3. package/lib/constants/AutoBeConfigConstant.d.ts +1 -1
  4. package/lib/constants/AutoBeSystemPromptConstant.d.ts +12 -11
  5. package/lib/constants/AutoBeSystemPromptConstant.js.map +1 -1
  6. package/lib/index.mjs +498 -55
  7. package/lib/index.mjs.map +1 -1
  8. package/lib/orchestrate/analyze/histories/transformAnalyzeExtractDecisionsHistory.d.ts +18 -0
  9. package/lib/orchestrate/analyze/histories/transformAnalyzeExtractDecisionsHistory.js +51 -0
  10. package/lib/orchestrate/analyze/histories/transformAnalyzeExtractDecisionsHistory.js.map +1 -0
  11. package/lib/orchestrate/analyze/histories/transformAnalyzeScenarioHistory.js +1 -1
  12. package/lib/orchestrate/analyze/histories/transformAnalyzeScenarioHistory.js.map +1 -1
  13. package/lib/orchestrate/analyze/histories/transformAnalyzeScenarioReviewHistory.js +1 -1
  14. package/lib/orchestrate/analyze/histories/transformAnalyzeScenarioReviewHistory.js.map +1 -1
  15. package/lib/orchestrate/analyze/histories/transformAnalyzeSectionCrossFileReviewHistory.d.ts +1 -0
  16. package/lib/orchestrate/analyze/histories/transformAnalyzeSectionCrossFileReviewHistory.js +15 -1
  17. package/lib/orchestrate/analyze/histories/transformAnalyzeSectionCrossFileReviewHistory.js.map +1 -1
  18. package/lib/orchestrate/analyze/histories/transformAnalyzeSectionReviewHistory.js +1 -1
  19. package/lib/orchestrate/analyze/histories/transformAnalyzeSectionReviewHistory.js.map +1 -1
  20. package/lib/orchestrate/analyze/orchestrateAnalyze.js +48 -13
  21. package/lib/orchestrate/analyze/orchestrateAnalyze.js.map +1 -1
  22. package/lib/orchestrate/analyze/orchestrateAnalyzeExtractDecisions.d.ts +17 -0
  23. package/lib/orchestrate/analyze/orchestrateAnalyzeExtractDecisions.js +345 -0
  24. package/lib/orchestrate/analyze/orchestrateAnalyzeExtractDecisions.js.map +1 -0
  25. package/lib/orchestrate/analyze/orchestrateAnalyzeScenario.js +2 -2
  26. package/lib/orchestrate/analyze/orchestrateAnalyzeSectionCrossFileReview.d.ts +1 -0
  27. package/lib/orchestrate/analyze/orchestrateAnalyzeSectionCrossFileReview.js +1 -0
  28. package/lib/orchestrate/analyze/orchestrateAnalyzeSectionCrossFileReview.js.map +1 -1
  29. package/lib/orchestrate/analyze/structures/IAutoBeAnalyzeExtractDecisionsApplication.d.ts +91 -0
  30. package/lib/orchestrate/analyze/structures/IAutoBeAnalyzeExtractDecisionsApplication.js +3 -0
  31. package/lib/orchestrate/analyze/structures/IAutoBeAnalyzeExtractDecisionsApplication.js.map +1 -0
  32. package/lib/orchestrate/analyze/structures/IAutoBeAnalyzeScenarioApplication.d.ts +15 -5
  33. package/lib/orchestrate/analyze/utils/buildErrorCodeRegistry.d.ts +0 -9
  34. package/lib/orchestrate/analyze/utils/buildErrorCodeRegistry.js +1 -13
  35. package/lib/orchestrate/analyze/utils/buildErrorCodeRegistry.js.map +1 -1
  36. package/lib/orchestrate/analyze/utils/detectDecisionConflicts.d.ts +63 -0
  37. package/lib/orchestrate/analyze/utils/detectDecisionConflicts.js +105 -0
  38. package/lib/orchestrate/analyze/utils/detectDecisionConflicts.js.map +1 -0
  39. package/lib/orchestrate/common/histories/transformPreliminaryHistory.js +1 -1
  40. package/lib/orchestrate/common/histories/transformPreliminaryHistory.js.map +1 -1
  41. package/lib/orchestrate/interface/histories/transformInterfaceActionEndpointReviewHistory.js +1 -1
  42. package/lib/orchestrate/interface/histories/transformInterfaceActionEndpointReviewHistory.js.map +1 -1
  43. package/lib/orchestrate/interface/histories/transformInterfaceBaseEndpointReviewHistory.js +1 -1
  44. package/lib/orchestrate/interface/histories/transformInterfaceBaseEndpointReviewHistory.js.map +1 -1
  45. package/lib/orchestrate/interface/histories/transformInterfaceSchemaRefineHistory.js +1 -1
  46. package/lib/orchestrate/interface/histories/transformInterfaceSchemaRefineHistory.js.map +1 -1
  47. package/lib/orchestrate/interface/orchestrateInterfaceSchemaRefine.js +1 -2
  48. package/lib/orchestrate/interface/orchestrateInterfaceSchemaRefine.js.map +1 -1
  49. package/lib/orchestrate/interface/orchestrateInterfaceSchemaReview.js +1 -2
  50. package/lib/orchestrate/interface/orchestrateInterfaceSchemaReview.js.map +1 -1
  51. package/lib/orchestrate/interface/utils/AutoBeJsonSchemaValidator.js +36 -0
  52. package/lib/orchestrate/interface/utils/AutoBeJsonSchemaValidator.js.map +1 -1
  53. package/lib/orchestrate/prisma/histories/transformPrismaComponentReviewHistory.js +2 -2
  54. package/lib/orchestrate/prisma/histories/transformPrismaComponentReviewHistory.js.map +1 -1
  55. package/lib/orchestrate/prisma/histories/transformPrismaComponentsHistory.js +1 -1
  56. package/lib/orchestrate/prisma/histories/transformPrismaComponentsHistory.js.map +1 -1
  57. package/lib/orchestrate/prisma/histories/transformPrismaGroupHistory.js +1 -1
  58. package/lib/orchestrate/prisma/histories/transformPrismaGroupHistory.js.map +1 -1
  59. package/lib/orchestrate/prisma/histories/transformPrismaGroupReviewHistory.js +1 -1
  60. package/lib/orchestrate/prisma/histories/transformPrismaGroupReviewHistory.js.map +1 -1
  61. package/lib/orchestrate/prisma/histories/transformPrismaSchemaHistory.js +1 -1
  62. package/lib/orchestrate/prisma/histories/transformPrismaSchemaHistory.js.map +1 -1
  63. package/lib/orchestrate/prisma/histories/transformPrismaSchemaReviewHistory.js +1 -1
  64. package/lib/orchestrate/prisma/histories/transformPrismaSchemaReviewHistory.js.map +1 -1
  65. package/lib/orchestrate/prisma/orchestratePrismaCorrect.js +1 -1
  66. package/package.json +5 -5
  67. package/src/AutoBeMockAgent.ts +0 -2
  68. package/src/constants/AutoBeConfigConstant.ts +1 -1
  69. package/src/constants/AutoBeSystemPromptConstant.ts +12 -11
  70. package/src/orchestrate/analyze/histories/transformAnalyzeExtractDecisionsHistory.ts +69 -0
  71. package/src/orchestrate/analyze/histories/transformAnalyzeSectionCrossFileReviewHistory.ts +20 -0
  72. package/src/orchestrate/analyze/orchestrateAnalyze.ts +58 -1
  73. package/src/orchestrate/analyze/orchestrateAnalyzeExtractDecisions.ts +97 -0
  74. package/src/orchestrate/analyze/orchestrateAnalyzeSectionCrossFileReview.ts +2 -0
  75. package/src/orchestrate/analyze/structures/IAutoBeAnalyzeExtractDecisionsApplication.ts +99 -0
  76. package/src/orchestrate/analyze/structures/IAutoBeAnalyzeScenarioApplication.ts +15 -5
  77. package/src/orchestrate/analyze/utils/buildErrorCodeRegistry.ts +0 -20
  78. package/src/orchestrate/analyze/utils/detectDecisionConflicts.ts +172 -0
  79. package/src/orchestrate/interface/orchestrateInterfaceSchemaRefine.ts +1 -2
  80. package/src/orchestrate/interface/orchestrateInterfaceSchemaReview.ts +1 -2
  81. package/src/orchestrate/interface/utils/AutoBeJsonSchemaValidator.ts +38 -0
package/lib/index.mjs CHANGED
@@ -421,7 +421,7 @@ async function process$u(ctx, props) {
421
421
  retry: ctx.retry
422
422
  },
423
423
  histories: transformImageDescribeDraftHistories(),
424
- controllers: [ createController$H({
424
+ controllers: [ createController$I({
425
425
  build: next => {
426
426
  pointer.value = next;
427
427
  }
@@ -467,7 +467,7 @@ async function process$u(ctx, props) {
467
467
  return event;
468
468
  }
469
469
 
470
- function createController$H(props) {
470
+ function createController$I(props) {
471
471
  const validate = next => {
472
472
  const result = (() => {
473
473
  const _io0 = input => "string" === typeof input.observation && "string" === typeof input.analysis && (Array.isArray(input.topics) && input.topics.every(elem => "string" === typeof elem)) && "string" === typeof input.summary && "string" === typeof input.description;
@@ -2129,6 +2129,350 @@ function buildTocContent(scenario, expandedTemplate, otherFileStates) {
2129
2129
  return lines.join("\n");
2130
2130
  }
2131
2131
 
2132
+ const transformAnalyzeExtractDecisionsHistory = (_ctx, props) => {
2133
+ const fileContent = props.sectionEvents.map((sectionsForModule, moduleIndex) => sectionsForModule.map((sectionEvent, unitIndex) => sectionEvent.sectionSections.map(section => `### [M${moduleIndex + 1}.U${unitIndex + 1}] ${section.title}\n\n${section.content}`).join("\n\n")).join("\n\n")).join("\n\n---\n\n");
2134
+ return {
2135
+ histories: [ {
2136
+ id: v7(),
2137
+ created_at: (new Date).toISOString(),
2138
+ type: "systemMessage",
2139
+ text: '\x3c!--\nfilename: ANALYZE_EXTRACT_DECISIONS.md\n--\x3e\n# Key Decision Extractor\n\nYou are the **Key Decision Extractor** for hierarchical requirements documentation.\nYour role is to extract **binary and discrete decisions** from a single file\'s section content as structured data, enabling programmatic cross-file contradiction detection.\n\nThis agent achieves its goal through function calling. **Function calling is MANDATORY**.\n\n---\n\n## 1. What to Extract\n\nExtract every **binary or discrete decision** embedded in the prose. A "decision" is a specific behavioral choice the document makes about how the system works.\n\n### 1.1. Binary Decisions (yes/no)\n\nStatements that assert or deny a capability, requirement, or behavior.\n\n**Examples:**\n- "Users must provide their current password to change it" → `topic: "password_change", decision: "requires_current_password", value: "yes"`\n- "The system does not require the old password" → `topic: "password_change", decision: "requires_current_password", value: "no"`\n- "Deleted emails can be reused for new accounts" → `topic: "deleted_email", decision: "can_be_reused", value: "yes"`\n- "An email from a deleted account is permanently blocked" → `topic: "deleted_email", decision: "can_be_reused", value: "no"`\n\n### 1.2. Discrete Decisions (multiple options)\n\nStatements that choose one option among several possibilities.\n\n**Examples:**\n- "Deleted todos are removed via soft delete" → `topic: "todo_deletion", decision: "deletion_method", value: "soft_delete"`\n- "Deleted todos are immediately and permanently removed" → `topic: "todo_deletion", decision: "deletion_method", value: "hard_delete"`\n- "Edit history records the new values of changed fields" → `topic: "edit_history", decision: "recorded_values", value: "new_values"`\n- "Edit history records the previous values of changed fields" → `topic: "edit_history", decision: "recorded_values", value: "previous_values"`\n\n### 1.3. Behavioral Decisions\n\nStatements about system behavior in specific scenarios.\n\n**Examples:**\n- "Users are automatically logged in after registration" → `topic: "registration", decision: "auto_login_after_signup", value: "yes"`\n- "Users must log in separately after registration" → `topic: "registration", decision: "auto_login_after_signup", value: "no"`\n- "Display name is required during account creation" → `topic: "display_name", decision: "required_at_signup", value: "yes"`\n- "Display name can be set later after account creation" → `topic: "display_name", decision: "required_at_signup", value: "no"`\n\n---\n\n## 2. How to Extract\n\n### 2.1. Topic Normalization\n\nUse consistent, lowercase, underscore-separated topic names:\n- `password_change`, NOT `PasswordChange` or `changing password`\n- `todo_deletion`, NOT `TodoDeletion` or `deleting todos`\n- `edit_history`, NOT `EditHistory` or `history of edits`\n\n### 2.2. Decision Normalization\n\nUse consistent, descriptive decision names:\n- `requires_current_password`, NOT `needsOldPassword` or `old password needed`\n- `deletion_method`, NOT `howToDelete` or `delete approach`\n\n### 2.3. Value Normalization\n\nUse short, consistent values:\n- Binary: `"yes"` or `"no"`\n- Discrete: short descriptive strings like `"soft_delete"`, `"hard_delete"`, `"new_values"`, `"previous_values"`\n\n### 2.4. Evidence\n\nInclude a short quote (1-2 sentences) from the source text that supports the extracted decision. This helps identify contradictions later.\n\n---\n\n## 3. What NOT to Extract\n\n- **Obvious facts**: "Users can create todos" — this is a feature, not a decision\n- **Vague statements**: "The system should be secure" — not specific enough\n- **Quantities or numbers**: "Maximum 300 characters" — handled by other validators\n- **Lists of features**: "Users can filter by status" — not a binary/discrete choice\n- **Implementation details**: "Uses JWT tokens" — technical, not behavioral\n\nFocus ONLY on decisions where **two files could reasonably disagree** about the correct answer.\n\n---\n\n## 4. Output Format\n\nCall `process()` with ALL extracted decisions:\n\n```typescript\nprocess({\n thinking: "This file defines password change as requiring current password, soft delete for todos, and edit history recording previous values.",\n request: {\n type: "complete",\n decisions: [\n {\n topic: "password_change",\n decision: "requires_current_password",\n value: "yes",\n evidence: "A user may change their password only by providing their current password."\n },\n {\n topic: "todo_deletion",\n decision: "deletion_method",\n value: "soft_delete",\n evidence: "When a user deletes a todo, it is removed from their main todo list but remains accessible in their trash."\n },\n {\n topic: "edit_history",\n decision: "recorded_values",\n value: "previous_values",\n evidence: "Each history entry must record the previous value of each field that was modified."\n }\n ]\n }\n});\n```\n\nIf the file contains no extractable decisions (e.g., 00-toc.md):\n\n```typescript\nprocess({\n thinking: "This file is a table of contents with no behavioral decisions.",\n request: {\n type: "complete",\n decisions: []\n }\n});\n```\n\n---\n\n## 5. Common Decision Topics\n\nThese are common topics where contradictions frequently occur between files. Extract these whenever you see them:\n\n- **Authentication**: `requires_current_password`, `auto_login_after_signup`, `session_mechanism`\n- **Account lifecycle**: `deleted_email_reusable`, `account_deletion_method`, `data_retention_after_deletion`\n- **Data deletion**: `deletion_method` (soft/hard), `retention_period`, `cascade_behavior`\n- **Edit history**: `recorded_values` (new/previous/both), `immutable`, `survives_soft_delete`\n- **Profile**: `display_name_required_at_signup`, `email_immutable`\n- **Authorization**: `owner_only_access`, `cross_user_visibility`\n- **Dates**: `date_validation_rules`, `null_date_sort_position`\n\n---\n\n## 6. Quality Rules\n\n- **Be exhaustive**: Extract ALL decisions, not just obvious ones\n- **Be consistent**: Same topic name for the same concept across calls\n- **Be precise**: Values should be unambiguous and distinct\n- **Be faithful**: Only extract what the text actually says, do not infer or assume\n- **One decision per statement**: If a sentence contains two decisions, extract both separately'
2140
+ }, {
2141
+ id: v7(),
2142
+ created_at: (new Date).toISOString(),
2143
+ type: "assistantMessage",
2144
+ text: StringUtil.trim`
2145
+ ## File: ${props.file.filename}
2146
+
2147
+ ## Full Section Content
2148
+
2149
+ ${fileContent}
2150
+ `
2151
+ } ],
2152
+ userMessage: `Extract all binary and discrete decisions from the file "${props.file.filename}". Return structured decisions for cross-file contradiction detection.`
2153
+ };
2154
+ };
2155
+
2156
+ const parseLooseStructuredString$1 = input => {
2157
+ const text = input.trim();
2158
+ if (text.length === 0) return undefined;
2159
+ if (text.startsWith("[") === false && text.startsWith("{") === false || text.endsWith("]") === false && text.endsWith("}") === false) return undefined;
2160
+ try {
2161
+ return JSON.parse(text);
2162
+ } catch {
2163
+ const normalized = text.replace(/'/g, '"').replace(/\bNone\b/g, "null").replace(/\bTrue\b/g, "true").replace(/\bFalse\b/g, "false");
2164
+ try {
2165
+ return JSON.parse(normalized);
2166
+ } catch {
2167
+ return undefined;
2168
+ }
2169
+ }
2170
+ };
2171
+
2172
+ const isRecord$1 = input => typeof input === "object" && input !== null && Array.isArray(input) === false;
2173
+
2174
+ const tryParseStringAsRecord = value => {
2175
+ if (typeof value !== "string") return value;
2176
+ const parsed = parseLooseStructuredString$1(value);
2177
+ return isRecord$1(parsed) ? parsed : value;
2178
+ };
2179
+
2180
+ const orchestrateAnalyzeExtractDecisions = async (ctx, props) => {
2181
+ const pointer = {
2182
+ value: null
2183
+ };
2184
+ await ctx.conversate({
2185
+ source: SOURCE$D,
2186
+ controller: createController$H({
2187
+ pointer
2188
+ }),
2189
+ enforceFunctionCall: true,
2190
+ ...transformAnalyzeExtractDecisionsHistory(ctx, {
2191
+ file: props.file,
2192
+ sectionEvents: props.sectionEvents
2193
+ })
2194
+ });
2195
+ return {
2196
+ filename: props.file.filename,
2197
+ decisions: (pointer.value?.decisions ?? []).map(d => ({
2198
+ topic: d.topic,
2199
+ decision: d.decision,
2200
+ value: d.value,
2201
+ evidence: d.evidence
2202
+ }))
2203
+ };
2204
+ };
2205
+
2206
+ function createController$H(props) {
2207
+ const application = __typia_transform__llmApplicationFinalize._llmApplicationFinalize({
2208
+ functions: [ {
2209
+ name: "process",
2210
+ parameters: {
2211
+ description: "Current Type: {@link IAutoBeAnalyzeExtractDecisionsApplicationProps}",
2212
+ type: "object",
2213
+ properties: {
2214
+ thinking: {
2215
+ description: "Think before you act.\n\nBefore completing extraction, reflect on what decisions this file makes:\n\n- What binary (yes/no) choices does this file assert?\n- What discrete behavioral choices does this file make?\n- Are there decisions where another file could reasonably disagree?",
2216
+ anyOf: [ {
2217
+ type: "null"
2218
+ }, {
2219
+ type: "string"
2220
+ } ]
2221
+ },
2222
+ request: {
2223
+ description: "Extraction result.",
2224
+ $ref: "#/$defs/IAutoBeAnalyzeExtractDecisionsApplicationComplete"
2225
+ }
2226
+ },
2227
+ required: [ "request" ],
2228
+ additionalProperties: false,
2229
+ $defs: {
2230
+ IAutoBeAnalyzeExtractDecisionsApplicationComplete: {
2231
+ description: "Request to complete the decision extraction.",
2232
+ type: "object",
2233
+ properties: {
2234
+ type: {
2235
+ description: "Type discriminator for the request.",
2236
+ type: "string",
2237
+ enum: [ "complete" ]
2238
+ },
2239
+ decisions: {
2240
+ description: "All binary/discrete decisions extracted from this file.\n\nEach decision represents a specific behavioral choice that the file makes.\nUse normalized topic names, decision names, and values.\n\nReturn an empty array if the file has no extractable decisions (e.g., table\nof contents).",
2241
+ type: "array",
2242
+ items: {
2243
+ $ref: "#/$defs/IAutoBeAnalyzeExtractedDecision"
2244
+ }
2245
+ }
2246
+ },
2247
+ required: [ "type", "decisions" ]
2248
+ },
2249
+ IAutoBeAnalyzeExtractedDecision: {
2250
+ description: "A single extracted decision from the file's content.",
2251
+ type: "object",
2252
+ properties: {
2253
+ topic: {
2254
+ description: "Normalized topic grouping.\n\nUse lowercase, underscore-separated names.",
2255
+ type: "string"
2256
+ },
2257
+ decision: {
2258
+ description: "Specific decision within the topic.\n\nUse lowercase, underscore-separated, descriptive names.",
2259
+ type: "string"
2260
+ },
2261
+ value: {
2262
+ description: 'The value of the decision.\n\nFor binary decisions: "yes" or "no". For discrete decisions: short\ndescriptive string.',
2263
+ type: "string"
2264
+ },
2265
+ evidence: {
2266
+ description: "Short quote (1-2 sentences) from the source text supporting this decision.",
2267
+ type: "string"
2268
+ }
2269
+ },
2270
+ required: [ "topic", "decision", "value", "evidence" ]
2271
+ }
2272
+ }
2273
+ },
2274
+ description: "Process decision extraction from a single file's sections.\n\nReads the file content and extracts all binary/discrete decisions as\nstructured data for cross-file contradiction detection.",
2275
+ validate: (() => {
2276
+ const _io0 = input => (null === input.thinking || undefined === input.thinking || "string" === typeof input.thinking) && ("object" === typeof input.request && null !== input.request && _io1(input.request));
2277
+ const _io1 = input => "complete" === input.type && (Array.isArray(input.decisions) && input.decisions.every(elem => "object" === typeof elem && null !== elem && _io2(elem)));
2278
+ const _io2 = input => "string" === typeof input.topic && "string" === typeof input.decision && "string" === typeof input.value && "string" === typeof input.evidence;
2279
+ const _vo0 = (input, _path, _exceptionable = true) => [ null === input.thinking || undefined === input.thinking || "string" === typeof input.thinking || _report(_exceptionable, {
2280
+ path: _path + ".thinking",
2281
+ expected: "(null | string | undefined)",
2282
+ value: input.thinking
2283
+ }), ("object" === typeof input.request && null !== input.request || _report(_exceptionable, {
2284
+ path: _path + ".request",
2285
+ expected: "IAutoBeAnalyzeExtractDecisionsApplicationComplete",
2286
+ value: input.request
2287
+ })) && _vo1(input.request, _path + ".request", _exceptionable) || _report(_exceptionable, {
2288
+ path: _path + ".request",
2289
+ expected: "IAutoBeAnalyzeExtractDecisionsApplicationComplete",
2290
+ value: input.request
2291
+ }) ].every(flag => flag);
2292
+ const _vo1 = (input, _path, _exceptionable = true) => [ "complete" === input.type || _report(_exceptionable, {
2293
+ path: _path + ".type",
2294
+ expected: '"complete"',
2295
+ value: input.type
2296
+ }), (Array.isArray(input.decisions) || _report(_exceptionable, {
2297
+ path: _path + ".decisions",
2298
+ expected: "Array<IAutoBeAnalyzeExtractedDecision>",
2299
+ value: input.decisions
2300
+ })) && input.decisions.map((elem, _index2) => ("object" === typeof elem && null !== elem || _report(_exceptionable, {
2301
+ path: _path + ".decisions[" + _index2 + "]",
2302
+ expected: "IAutoBeAnalyzeExtractedDecision",
2303
+ value: elem
2304
+ })) && _vo2(elem, _path + ".decisions[" + _index2 + "]", _exceptionable) || _report(_exceptionable, {
2305
+ path: _path + ".decisions[" + _index2 + "]",
2306
+ expected: "IAutoBeAnalyzeExtractedDecision",
2307
+ value: elem
2308
+ })).every(flag => flag) || _report(_exceptionable, {
2309
+ path: _path + ".decisions",
2310
+ expected: "Array<IAutoBeAnalyzeExtractedDecision>",
2311
+ value: input.decisions
2312
+ }) ].every(flag => flag);
2313
+ const _vo2 = (input, _path, _exceptionable = true) => [ "string" === typeof input.topic || _report(_exceptionable, {
2314
+ path: _path + ".topic",
2315
+ expected: "string",
2316
+ value: input.topic
2317
+ }), "string" === typeof input.decision || _report(_exceptionable, {
2318
+ path: _path + ".decision",
2319
+ expected: "string",
2320
+ value: input.decision
2321
+ }), "string" === typeof input.value || _report(_exceptionable, {
2322
+ path: _path + ".value",
2323
+ expected: "string",
2324
+ value: input.value
2325
+ }), "string" === typeof input.evidence || _report(_exceptionable, {
2326
+ path: _path + ".evidence",
2327
+ expected: "string",
2328
+ value: input.evidence
2329
+ }) ].every(flag => flag);
2330
+ const __is = input => "object" === typeof input && null !== input && _io0(input);
2331
+ let errors;
2332
+ let _report;
2333
+ return input => {
2334
+ if (false === __is(input)) {
2335
+ errors = [];
2336
+ _report = __typia_transform__validateReport._validateReport(errors);
2337
+ ((input, _path, _exceptionable = true) => ("object" === typeof input && null !== input || _report(true, {
2338
+ path: _path + "",
2339
+ expected: "IAutoBeAnalyzeExtractDecisionsApplicationProps",
2340
+ value: input
2341
+ })) && _vo0(input, _path + "", true) || _report(true, {
2342
+ path: _path + "",
2343
+ expected: "IAutoBeAnalyzeExtractDecisionsApplicationProps",
2344
+ value: input
2345
+ }))(input, "$input", true);
2346
+ const success = 0 === errors.length;
2347
+ return success ? {
2348
+ success,
2349
+ data: input
2350
+ } : {
2351
+ success,
2352
+ errors,
2353
+ data: input
2354
+ };
2355
+ }
2356
+ return {
2357
+ success: true,
2358
+ data: input
2359
+ };
2360
+ };
2361
+ })()
2362
+ } ]
2363
+ }, {
2364
+ validate: {
2365
+ process: input => {
2366
+ if (isRecord$1(input) && typeof input.request === "string") {
2367
+ input = {
2368
+ ...input,
2369
+ request: tryParseStringAsRecord(input.request)
2370
+ };
2371
+ }
2372
+ return (() => {
2373
+ const _io0 = input => (null === input.thinking || undefined === input.thinking || "string" === typeof input.thinking) && ("object" === typeof input.request && null !== input.request && _io1(input.request));
2374
+ const _io1 = input => "complete" === input.type && (Array.isArray(input.decisions) && input.decisions.every(elem => "object" === typeof elem && null !== elem && _io2(elem)));
2375
+ const _io2 = input => "string" === typeof input.topic && "string" === typeof input.decision && "string" === typeof input.value && "string" === typeof input.evidence;
2376
+ const _vo0 = (input, _path, _exceptionable = true) => [ null === input.thinking || undefined === input.thinking || "string" === typeof input.thinking || _report(_exceptionable, {
2377
+ path: _path + ".thinking",
2378
+ expected: "(null | string | undefined)",
2379
+ value: input.thinking
2380
+ }), ("object" === typeof input.request && null !== input.request || _report(_exceptionable, {
2381
+ path: _path + ".request",
2382
+ expected: "IAutoBeAnalyzeExtractDecisionsApplicationComplete",
2383
+ value: input.request
2384
+ })) && _vo1(input.request, _path + ".request", _exceptionable) || _report(_exceptionable, {
2385
+ path: _path + ".request",
2386
+ expected: "IAutoBeAnalyzeExtractDecisionsApplicationComplete",
2387
+ value: input.request
2388
+ }) ].every(flag => flag);
2389
+ const _vo1 = (input, _path, _exceptionable = true) => [ "complete" === input.type || _report(_exceptionable, {
2390
+ path: _path + ".type",
2391
+ expected: '"complete"',
2392
+ value: input.type
2393
+ }), (Array.isArray(input.decisions) || _report(_exceptionable, {
2394
+ path: _path + ".decisions",
2395
+ expected: "Array<IAutoBeAnalyzeExtractedDecision>",
2396
+ value: input.decisions
2397
+ })) && input.decisions.map((elem, _index2) => ("object" === typeof elem && null !== elem || _report(_exceptionable, {
2398
+ path: _path + ".decisions[" + _index2 + "]",
2399
+ expected: "IAutoBeAnalyzeExtractedDecision",
2400
+ value: elem
2401
+ })) && _vo2(elem, _path + ".decisions[" + _index2 + "]", _exceptionable) || _report(_exceptionable, {
2402
+ path: _path + ".decisions[" + _index2 + "]",
2403
+ expected: "IAutoBeAnalyzeExtractedDecision",
2404
+ value: elem
2405
+ })).every(flag => flag) || _report(_exceptionable, {
2406
+ path: _path + ".decisions",
2407
+ expected: "Array<IAutoBeAnalyzeExtractedDecision>",
2408
+ value: input.decisions
2409
+ }) ].every(flag => flag);
2410
+ const _vo2 = (input, _path, _exceptionable = true) => [ "string" === typeof input.topic || _report(_exceptionable, {
2411
+ path: _path + ".topic",
2412
+ expected: "string",
2413
+ value: input.topic
2414
+ }), "string" === typeof input.decision || _report(_exceptionable, {
2415
+ path: _path + ".decision",
2416
+ expected: "string",
2417
+ value: input.decision
2418
+ }), "string" === typeof input.value || _report(_exceptionable, {
2419
+ path: _path + ".value",
2420
+ expected: "string",
2421
+ value: input.value
2422
+ }), "string" === typeof input.evidence || _report(_exceptionable, {
2423
+ path: _path + ".evidence",
2424
+ expected: "string",
2425
+ value: input.evidence
2426
+ }) ].every(flag => flag);
2427
+ const __is = input => "object" === typeof input && null !== input && _io0(input);
2428
+ let errors;
2429
+ let _report;
2430
+ return input => {
2431
+ if (false === __is(input)) {
2432
+ errors = [];
2433
+ _report = __typia_transform__validateReport._validateReport(errors);
2434
+ ((input, _path, _exceptionable = true) => ("object" === typeof input && null !== input || _report(true, {
2435
+ path: _path + "",
2436
+ expected: "IAutoBeAnalyzeExtractDecisionsApplicationProps",
2437
+ value: input
2438
+ })) && _vo0(input, _path + "", true) || _report(true, {
2439
+ path: _path + "",
2440
+ expected: "IAutoBeAnalyzeExtractDecisionsApplicationProps",
2441
+ value: input
2442
+ }))(input, "$input", true);
2443
+ const success = 0 === errors.length;
2444
+ return success ? {
2445
+ success,
2446
+ data: input
2447
+ } : {
2448
+ success,
2449
+ errors,
2450
+ data: input
2451
+ };
2452
+ }
2453
+ return {
2454
+ success: true,
2455
+ data: input
2456
+ };
2457
+ };
2458
+ })()(input);
2459
+ }
2460
+ }
2461
+ });
2462
+ return {
2463
+ protocol: "class",
2464
+ name: SOURCE$D,
2465
+ application,
2466
+ execute: {
2467
+ process: input => {
2468
+ if (input.request.type === "complete") props.pointer.value = input.request;
2469
+ }
2470
+ }
2471
+ };
2472
+ }
2473
+
2474
+ const SOURCE$D = "analyzeSectionReview";
2475
+
2132
2476
  var AutoBeDatabaseModelProgrammer;
2133
2477
 
2134
2478
  (function(AutoBeDatabaseModelProgrammer) {
@@ -2572,6 +2916,7 @@ var AutoBeJsonSchemaValidator;
2572
2916
  validateReferenceId(props);
2573
2917
  validatePropertyNames(props);
2574
2918
  validateNumericRanges(props);
2919
+ validateEmptyProperties(props);
2575
2920
  vo(props.typeName, props.schema);
2576
2921
  AutoBeOpenApiTypeChecker.skim({
2577
2922
  schema: props.schema,
@@ -3070,6 +3415,38 @@ var AutoBeJsonSchemaValidator;
3070
3415
  }
3071
3416
  });
3072
3417
  };
3418
+ const validateEmptyProperties = props => {
3419
+ if (AutoBeOpenApiTypeChecker.isObject(props.schema) === false) return;
3420
+ if (Object.keys(props.schema.properties).length !== 0) return;
3421
+ if (AutoBeJsonSchemaValidator.isObjectType({
3422
+ operations: props.operations,
3423
+ typeName: props.typeName
3424
+ }) === false) return;
3425
+ props.errors.push({
3426
+ path: props.path,
3427
+ expected: "At least 1 property in properties",
3428
+ value: props.schema,
3429
+ description: StringUtil.trim`
3430
+ Schema ${JSON.stringify(props.typeName)} has zero properties but is used
3431
+ as a request body or response body in API operations.
3432
+
3433
+ Empty properties will cause TypeScript compilation errors (TS2339) in the
3434
+ downstream Realize stage because implementation code will try to access
3435
+ properties that don't exist on the type.
3436
+
3437
+ You MUST define at least one property in the schema. Load the database
3438
+ schema and add the appropriate properties based on the DTO type:
3439
+ - ICreate: User-provided business fields (exclude id, timestamps, actor FKs)
3440
+ - IUpdate: All mutable business fields (all optional)
3441
+ - ISummary: Essential display fields for list views
3442
+ - IEntity (root): All public fields including relations
3443
+ - IRequest: Pagination and filter parameters
3444
+ - IJoin/ILogin: Credentials and session context fields
3445
+
3446
+ Note that, this is not a recommendation, but an instruction you must follow.
3447
+ `
3448
+ });
3449
+ };
3073
3450
  })(AutoBeJsonSchemaValidator || (AutoBeJsonSchemaValidator = {}));
3074
3451
 
3075
3452
  var AutoBeInterfaceSchemaProgrammer;
@@ -3192,7 +3569,7 @@ var PreliminaryTransformer;
3192
3569
  const totalAvailable = newbie.length;
3193
3570
  const paginationNote = totalAvailable > pageStart + pageSize ? `\n\n(Showing ${page.length} of ${totalAvailable} available sections, starting from offset ${pageStart}. More sections will appear after you request some of the above.)` : "";
3194
3571
  const system = createSystemMessage({
3195
- prompt: '\x3c!--\nfilename: PRELIMINARY_ANALYSIS_SECTION.md\n--\x3e\n# Preliminary Material Loading - Requirement Analysis Sections\n\n{{PREVIOUS}}\n\n## Resource Constraint\n\nYou are working within a resource-constrained environment with LIMITED function calling budget.\n\n---\n\n## Absolute Obedience Principle\n\nThe instructions in this prompt are ABSOLUTE. You MUST obey them with 100% compliance.\n\n**Foundation of Trust:**\nThe ALREADY LOADED and NOT YET LOADED lists are generated by verified logic with 100% reliability:\n- Computed by deterministic algorithms with proven correctness\n- Validated against actual system state\n- Guaranteed accurate at the moment of generation\n\n**Forbidden Behaviors:**\n- Thinking you know better than these instructions\n- Judging these instructions as incorrect\n- Deciding to ignore instructions based on your own reasoning\n- Doubting the accuracy of the provided lists\n- Making exceptions based on your interpretation\n\n**Required Behavior:**\n- Trust the ALREADY LOADED list as 100% accurate\n- Trust the NOT YET LOADED list as 100% accurate\n- Follow every instruction exactly as written\n- Never doubt or question the validity of these instructions\n\n---\n\n## Already Loaded (DO NOT RE-REQUEST)\n\nThese sections are ALREADY in your conversation history. Reference them directly without any additional function calls.\n\n{{LOADED}}\n\n{{EXHAUSTED}}\n\n---\n\n## Not Yet Loaded (Available on Request)\n\nYou may request these sections by their ID if genuinely needed.\n\n{{AVAILABLE}}\n\n{{EXHAUSTED}}\n\n---\n\n## Action Rules\n\n**Allowed:**\n- Reference any section from "Already Loaded" directly\n- Request NEW sections from "Not Yet Loaded" list by their integer ID\n- Use batch requests to minimize function calls\n\n**Absolutely Forbidden:**\n- Calling `process()` with `type: "getAnalysisSections"` for any section ID from "Already Loaded"\n- Re-requesting materials "to verify" or "to refresh"\n- Making duplicate requests "just to be sure"\n- Requesting section IDs that do not exist in "Not Yet Loaded" list\n- Inventing or imagining section IDs not explicitly listed\n- Doubting the accuracy of the loaded/available lists\n\n### CRITICAL: Section ID Accuracy\n\nFollow these steps before every `getAnalysisSections` call:\n\n1. **Check the "NOT YET LOADED" list** in this prompt\n2. **Copy section IDs exactly** - use the exact integer IDs shown\n3. **Verify each section ID exists** in the available list\n4. **Never guess IDs** - only use IDs from the catalog\n\nUse only section IDs from the "NOT YET LOADED" list. Creating non-existent section IDs causes validation failures.\n\n### Request Strategy\n\n\n### Example\n```typescript\n// Correct - request only new, needed sections by ID\nprocess({\n request: {\n type: "getAnalysisSections",\n sectionIds: [3, 7, 12]\n }\n})\n\n// Wrong - re-requesting loaded sections\nprocess({\n request: {\n type: "getAnalysisSections",\n sectionIds: [1] // Already in your context!\n }\n})\n```\n\n---\n\n## Never Work from Imagination\n\nYou MUST NEVER proceed based on assumptions about section contents. ALWAYS load actual data first.\n\n**Forbidden:**\n- Guessing requirements based on "typical patterns" or section titles\n- Assuming validation rules without reading actual sections\n- Imagining specifications based on "common sense"\n\n**Required:**\n- Need business requirements? -> Call `getAnalysisSections` for the specific section IDs\n- Need validation rules? -> Load the actual sections first\n- ALWAYS: Check "Not Yet Loaded" -> Request by ID -> Wait for data -> Then work\n\n**Zero Tolerance:** If you think "this probably has X, Y, Z" -> STOP and request the actual section.\n\n---\n\n## Evidence-First Strategy\n\nDo NOT wait until you are stuck to load analysis sections. Load them EARLY in your workflow.\n\n**When to Load:**\n- BEFORE making any business logic decision\n- BEFORE calling `complete`\n- When any domain-specific question arises\n\n**How to Load:**\n1. Review the "Not Yet Loaded" catalog\n2. Identify sections relevant to your current task by their titles and keywords\n3. Request them in a SINGLE batched call using their IDs\n4. Use the loaded evidence to ground your decisions\n\n**Critical:** Having analysis sections available but NOT loaded is almost as bad as imagining requirements. If relevant sections exist, load them BEFORE proceeding.\n\n---\n\n## Enforcement\n\nThis constraint has SYSTEM PROMPT AUTHORITY. Treating it as optional will cause:\n- Wasted function call budget\n- Performance degradation\n- Potential infinite loops\n- Pipeline failures\n\n**Zero Tolerance:** You MUST NOT call `process()` with `type: "getAnalysisSections"` for any section ID in the "Already Loaded" section. No exceptions, no special cases, no "verification" requests.',
3572
+ prompt: '\x3c!--\nfilename: PRELIMINARY_ANALYSIS_SECTION.md\n--\x3e\n# Preliminary Material Loading - Requirement Analysis Sections\n\n{{PREVIOUS}}\n\n## What Are Analysis Sections?\n\nAnalysis sections are the **requirements specification documents** for the system you are building. Each section describes a specific part of the business domain:\n\n- **Business rules**: How entities behave, what constraints apply, what workflows exist\n- **Entity definitions**: What data models exist, their properties, and relationships\n- **Validation constraints**: Required fields, format rules, value ranges, business invariants\n- **User stories & workflows**: How users interact with the system, step-by-step processes\n- **Authorization rules**: Who can access what, role-based permissions\n- **Edge cases**: Special conditions, error handling, boundary scenarios\n\nThese documents were written during the analysis phase and represent the **source of truth** for all downstream design and implementation. They contain details that cannot be inferred from titles alone — you must load the actual content to know the specific rules.\n\n**The catalog below shows section titles and keywords.** Use these to judge which sections are relevant to your current task. If a section\'s title or keywords overlap with the entities or features you are working on, loading it will give you the actual requirements.\n\n---\n\n## Already Loaded (DO NOT RE-REQUEST)\n\nThese sections are ALREADY in your conversation history. Reference them directly without any additional function calls.\n\n{{LOADED}}\n\n{{EXHAUSTED}}\n\n---\n\n## Not Yet Loaded (Available on Request)\n\n{{AVAILABLE}}\n\n{{EXHAUSTED}}\n\n---\n\n## How to Request\n\nCall `getAnalysisSections` with section IDs from the "Not Yet Loaded" list. Each call can load up to 100 sections. You can call **multiple times** until you have enough context to understand the project do not hesitate to make additional calls if needed.\n\n```typescript\n// First call - load initial batch\nprocess({\n request: {\n type: "getAnalysisSections",\n sectionIds: [1, 2, 3, ..., 80]\n }\n})\n\n// Second call - load more sections\nprocess({\n request: {\n type: "getAnalysisSections",\n sectionIds: [81, 82, 83, ..., 150]\n }\n})\n```\n\n**Rules:**\n- Only use section IDs from the "Not Yet Loaded" list never invent IDs\n- Never re-request sections from "Already Loaded"\n- Batch related sections into one call when possible\n\nInvalid or duplicate IDs cause validation failures.\n\n---\n\n## Never Work from Imagination\n\nDo not guess what requirements say based on section titles. If you need the actual business rules, validation constraints, or entity specifications load the section.\n\n- Thinking "this probably requires X, Y, Z"? Load the section and check.\n- Unsure about a business rule or constraint? The answer is in the analysis sections.\n\n---\n\n## Duplicate Prevention\n\nThis rule has SYSTEM PROMPT AUTHORITY:\n- Do NOT re-request items from "Already Loaded"\n- Do NOT request items that don\'t exist in "Not Yet Loaded"\n\nViolations cause validation failures and wasted iterations.',
3196
3573
  previous: "\x3c!--\nfilename: PRELIMINARY_ANALYSIS_SECTION_PREVIOUS.md\n--\x3e\n> These sections describe requirements for **ALREADY IMPLEMENTED** features from previous iterations.\n>\n> Reference them to:\n> - Maintain consistency with existing implementations\n> - Understand related business logic and dependencies\n> - Verify prerequisite features or constraints\n> - Cross-reference with current iteration requirements\n>\n> **DO NOT** use these to design new features. They describe what has **ALREADY BEEN BUILT**.\n>\n> **IMPORTANT**: Use `getPreviousAnalysisSections` to load these sections, NOT `getAnalysisSections` (which is for NEW requirements you need to analyze in current iteration).",
3197
3574
  available: formatCompactSectionIndex(page) + paginationNote,
3198
3575
  loaded: Array.from(oldbie.values()).map(s => `- [${s.id}] ${s.sectionTitle}`).join("\n"),
@@ -5149,7 +5526,7 @@ const transformAnalyzeScenarioHistory = (ctx, preliminary, feedback) => ({
5149
5526
  histories: [ {
5150
5527
  id: v7(),
5151
5528
  type: "systemMessage",
5152
- text: '\x3c!--\nfilename: ANALYZE_SCENARIO.md\n--\x3e\n# Scenario Analyst\n\nYou are the **Scenario Analyst** — the agent that extracts business concepts from user conversations.\n\n**Your Job**: Identify `prefix`, `actors`, `concepts`, `features`, and `language` from user requirements.\n\n**Your Mindset**: Think like a business analyst. Capture WHAT the business needs, not HOW to implement it.\n\n**Boundary**: Do not define database schemas or API endpoints. Those belong to later phases.\n\n---\n\n## 1. Workflow\n\n1. **Clarify** — Ask questions if business type, actors, scope, or core policies are unclear\n2. **Close** — Stop asking when: user says proceed, all key questions resolved, or 8 questions reached\n3. **Output** — Call `process({ request: { type: "complete", ... } })` with extracted scenario\n\n---\n\n## 2. 6-File SRS Structure\n\n| File | Focus | Downstream |\n|------|-------|-----------|\n| 00-toc.md | Summary, scope, glossary | Project setup |\n| 01-actors-and-auth.md | Who can do what | Auth middleware |\n| 02-domain-model.md | Business concepts and relationships | Database design |\n| 03-functional-requirements.md | What operations users can perform | Interface design |\n| 04-business-rules.md | Validation rules, error conditions | Service logic |\n| 05-non-functional.md | Performance, security | Infrastructure |\n\n---\n\n## 3. Output Format\n\n```typescript\nprocess({\n thinking: "Identified 3 actors and 5 domain concepts from user requirements.",\n request: {\n type: "complete",\n reason: "User described a todo app with user authentication",\n prefix: "todoApp",\n language: "en",\n actors: [\n { name: "guest", kind: "guest", description: "Unauthenticated visitors" },\n { name: "member", kind: "member", description: "Registered users managing todos" }\n ],\n concepts: [\n { name: "User", description: "Registered user of the system", relationships: [] },\n { name: "Todo", description: "Task item that users create and track", relationships: ["owned by User"] }\n ],\n features: []\n }\n});\n```\n\n---\n\n## 4. Actors\n\n**Default to minimal set**: `guest`, `member`\n\nOnly add actors when the user explicitly describes a distinct identity type (e.g., "sellers" vs "buyers" in a marketplace). If someone can be represented as a role attribute on an existing actor, don\'t create a new actor.\n\n**Test**: "Does this require a separate login and account lifecycle?" YES → actor. NO → attribute.\n\n---\n\n## 5. Concepts\n\nDescribe **business concepts** — the nouns users talk about when describing their business.\n\n**Good**: `{ name: "Todo", description: "A task item users create and manage", relationships: ["owned by User"] }`\n\n**Bad**: `{ name: "Todo", attributes: ["title: text(1-500)", "completed: boolean"] }` — attributes belong in Database phase.\n\n---\n\n## 6. Features (Optional)\n\nOnly include if user mentions specific capabilities:\n\n| Feature | Trigger Keywords |\n|---------|-----------------|\n| `real-time` | live updates, WebSocket, chat |\n| `external-integration` | payment, OAuth, email service |\n| `file-storage` | file upload, attachments, S3 |\n\n---\n\n## 7. User Input Preservation\n\nThe user\'s stated requirements are authoritative:\n- "multi-user" → design as multi-user\n- "email/password login" → use email/password auth\n- "soft delete" → implement soft delete\n- 8 features mentioned → include all 8\n\n---\n\n## 8. Document Sections (Post-Closure)\n\nAfter closing clarification, the requirements document must include:\n\n### 8.1. Interpretation & Assumptions\n- Original user input (verbatim)\n- Your interpretation\n- At least 8 assumptions (business type, users, scope, policies, etc.)\n\n### 8.2. Scope Definition\n- In-scope (v1 features)\n- Out-of-scope (deferred to v2)\n\n### 8.3. Domain Concepts\n- Business description of each concept\n- How concepts relate to each other\n\n### 8.4. Core Workflows\n- User journeys in natural language\n- Exception scenarios\n\n---\n\n## 9. Diagrams\n\nUse business language in flowcharts:\n\n```mermaid\ngraph LR\n A["Browse Products"] --\x3e B["Add to Cart"]\n B --\x3e C{"Checkout?"}\n C --\x3e|Yes| D["Complete Order"]\n C --\x3e|No| E["Continue Shopping"]\n```\n\n---\n\n## 10. Final Checklist\n\n**Scenario Extraction:**\n- [ ] `prefix` is a valid camelCase identifier\n- [ ] All actors have `name`, `kind`, and `description`\n- [ ] All concepts have `name`, `description`, and `relationships`\n- [ ] Features only from fixed catalog: `real-time`, `external-integration`, `file-storage`\n\n**Prohibited Content (REJECT if present):**\n- [ ] NO database schemas or table definitions\n- [ ] NO API endpoints or HTTP methods\n- [ ] NO field types or column definitions\n- [ ] NO technical implementation details\n\n**Business Language Only:**\n- [ ] Concepts describe WHAT exists, not HOW it\'s stored\n- [ ] Relationships describe business connections, not foreign keys\n- [ ] All descriptions use user-facing language',
5529
+ text: '\x3c!--\nfilename: ANALYZE_SCENARIO.md\n--\x3e\n# Scenario Analyst\n\nYou are the **Scenario Analyst** — the agent that extracts business concepts from user conversations.\n\n**Your Job**: Identify `prefix`, `actors`, `concepts`, `features`, and `language` from user requirements.\n\n**Your Mindset**: Think like a business analyst. Capture WHAT the business needs, not HOW to implement it.\n\n**Boundary**: Do not define database schemas or API endpoints. Those belong to later phases.\n\n---\n\n## 1. Workflow\n\n1. **Clarify** — Ask questions if business type, actors, scope, or core policies are unclear\n2. **Close** — Stop asking when: user says proceed, all key questions resolved, or 8 questions reached\n3. **Output** — Call `process({ request: { type: "complete", ... } })` with extracted scenario\n\n---\n\n## 2. 6-File SRS Structure\n\n| File | Focus | Downstream |\n|------|-------|-----------|\n| 00-toc.md | Summary, scope, glossary | Project setup |\n| 01-actors-and-auth.md | Who can do what | Auth middleware |\n| 02-domain-model.md | Business concepts and relationships | Database design |\n| 03-functional-requirements.md | What operations users can perform | Interface design |\n| 04-business-rules.md | Validation rules, error conditions | Service logic |\n| 05-non-functional.md | Performance, security | Infrastructure |\n\n---\n\n## 3. Output Format\n\n```typescript\nprocess({\n thinking: "Identified 3 actors and 5 domain concepts from user requirements.",\n request: {\n type: "complete",\n reason: "User described a todo app with user authentication",\n prefix: "todoApp",\n language: "en",\n actors: [\n { name: "guest", kind: "guest", description: "Unauthenticated visitors" },\n { name: "member", kind: "member", description: "Registered users managing todos" }\n ],\n concepts: [\n { name: "User", description: "Registered user of the system", relationships: [] },\n { name: "Todo", description: "Task item that users create and track", relationships: ["owned by User"] }\n ],\n features: []\n }\n});\n```\n\n---\n\n## 4. Actors\n\n**Default to minimal set**: `guest`, `member`\n\nOnly add actors when the user explicitly describes a distinct identity type (e.g., "sellers" vs "buyers" in a marketplace). If someone can be represented as a role attribute on an existing actor, don\'t create a new actor.\n\n**Test**: "Does this require a separate login and account lifecycle?" YES → actor. NO → attribute.\n\n---\n\n## 5. Concepts\n\nDescribe **business concepts** — the nouns users talk about when describing their business.\n\n**Good**: `{ name: "Todo", description: "A task item users create and manage", relationships: ["owned by User"] }`\n\n**Bad**: `{ name: "Todo", attributes: ["title: text(1-500)", "completed: boolean"] }` — attributes belong in Database phase.\n\n---\n\n## 6. Features (STRICT — Default is EMPTY)\n\nFeatures activate conditional modules across ALL 6 SRS files. Wrong activation causes massive hallucination downstream. **Default: empty array `[]`**.\n\n**Activation Rule**: Include a feature ONLY if the user used one of its exact trigger keywords. Do NOT infer features from general context.\n\n| Feature | Activate ONLY if user said | Do NOT activate if |\n|---------|---------------------------|-------------------|\n| `real-time` | "live updates", "WebSocket", "real-time", "chat", "push notifications" | User just described a standard CRUD app |\n| `external-integration` | "payment", "Stripe", "OAuth", "email service", "SMS", "third-party API" | User just mentioned login/signup (that\'s built-in auth, not external integration) |\n| `file-storage` | "file upload", "image upload", "attachments", "S3", "media" | User described text-only data (title, description, dates) |\n\n**Examples**:\n- "Todo app with user auth, CRUD, soft delete" → `features: []` (no trigger keywords)\n- "Shopping mall with Stripe payment" → `features: [{ id: "external-integration", providers: ["stripe"] }]`\n- "Chat app with real-time messaging and file sharing" → `features: [{ id: "real-time" }, { id: "file-storage" }]`\n\n**Self-check**: For each feature you want to activate, quote the exact user words that triggered it. No quote → remove feature.\n\n---\n\n## 7. User Input Preservation\n\nThe user\'s stated requirements are authoritative:\n- "multi-user" → design as multi-user\n- "email/password login" → use email/password auth\n- "soft delete" → implement soft delete\n- 8 features mentioned → include all 8\n\n---\n\n## 8. Document Sections (Post-Closure)\n\nAfter closing clarification, the requirements document must include:\n\n### 8.1. Interpretation & Assumptions\n- Original user input (verbatim)\n- Your interpretation\n- At least 8 assumptions (business type, users, scope, policies, etc.)\n\n### 8.2. Scope Definition\n- In-scope (v1 features)\n- Out-of-scope (deferred to v2)\n\n### 8.3. Domain Concepts\n- Business description of each concept\n- How concepts relate to each other\n\n### 8.4. Core Workflows\n- User journeys in natural language\n- Exception scenarios\n\n---\n\n## 9. Diagrams\n\nUse business language in flowcharts:\n\n```mermaid\ngraph LR\n A["Browse Products"] --\x3e B["Add to Cart"]\n B --\x3e C{"Checkout?"}\n C --\x3e|Yes| D["Complete Order"]\n C --\x3e|No| E["Continue Shopping"]\n```\n\n---\n\n## 10. Final Checklist\n\n**Scenario Extraction:**\n- [ ] `prefix` is a valid camelCase identifier\n- [ ] All actors have `name`, `kind`, and `description`\n- [ ] All concepts have `name`, `description`, and `relationships`\n- [ ] Features default to empty array — only activated by EXACT trigger keywords from user\n- [ ] For each activated feature, you can quote the user\'s exact words that triggered it\n- [ ] A standard CRUD app with auth has NO features — features: []\n\n**Prohibited Content (REJECT if present):**\n- [ ] NO database schemas or table definitions\n- [ ] NO API endpoints or HTTP methods\n- [ ] NO field types or column definitions\n- [ ] NO technical implementation details\n\n**Business Language Only:**\n- [ ] Concepts describe WHAT exists, not HOW it\'s stored\n- [ ] Relationships describe business connections, not foreign keys\n- [ ] All descriptions use user-facing language',
5153
5530
  created_at: (new Date).toISOString()
5154
5531
  }, ...ctx.histories().filter(h => h.type === "userMessage" || h.type === "assistantMessage"), ...preliminary.getHistories(), ...feedback ? [ {
5155
5532
  id: v7(),
@@ -5178,30 +5555,6 @@ const transformAnalyzeScenarioHistory = (ctx, preliminary, feedback) => ({
5178
5555
  `
5179
5556
  });
5180
5557
 
5181
- const parseLooseStructuredString$1 = input => {
5182
- const text = input.trim();
5183
- if (text.length === 0) return undefined;
5184
- if (text.startsWith("[") === false && text.startsWith("{") === false || text.endsWith("]") === false && text.endsWith("}") === false) return undefined;
5185
- try {
5186
- return JSON.parse(text);
5187
- } catch {
5188
- const normalized = text.replace(/'/g, '"').replace(/\bNone\b/g, "null").replace(/\bTrue\b/g, "true").replace(/\bFalse\b/g, "false");
5189
- try {
5190
- return JSON.parse(normalized);
5191
- } catch {
5192
- return undefined;
5193
- }
5194
- }
5195
- };
5196
-
5197
- const isRecord$1 = input => typeof input === "object" && input !== null && Array.isArray(input) === false;
5198
-
5199
- const tryParseStringAsRecord = value => {
5200
- if (typeof value !== "string") return value;
5201
- const parsed = parseLooseStructuredString$1(value);
5202
- return isRecord$1(parsed) ? parsed : value;
5203
- };
5204
-
5205
5558
  const orchestrateAnalyzeScenario = async (ctx, props) => {
5206
5559
  const start = new Date;
5207
5560
  const preliminary = new AutoBePreliminaryController({
@@ -5301,7 +5654,7 @@ const orchestrateAnalyzeScenario = async (ctx, props) => {
5301
5654
  items: {
5302
5655
  $ref: "#/components/schemas/FixedAnalyzeTemplateFeature"
5303
5656
  },
5304
- description: "High-level project features that activate conditional modules.\n\nSelected from a FIXED catalog — the LLM must NOT invent features outside\nthe predefined list. Each feature activates additional modules in the\nappropriate SRS files.\n\nIf the project has no special features beyond REST CRUD, return an empty\narray."
5657
+ description: 'High-level project features that activate conditional modules.\n\nWARNING: Wrong activation causes cascading hallucination across ALL SRS\nfiles. Each feature adds 2-3 conditional modules that downstream LLMs\nMUST fill with content if the user never requested the feature, those\nmodules get filled with hallucinated requirements.\n\nDEFAULT IS EMPTY ARRAY []. Most projects need no features.\n\nActivation rule: Include ONLY if the user used exact trigger keywords:\n\n- "file-storage": user said "file upload", "attachment", "image upload"\n- "real-time": user said "real-time", "WebSocket", "live updates", "chat"\n- "external-integration": user said "payment", "Stripe", "OAuth", "email\n service"\n\nStandard CRUD with auth = features: []. Do NOT activate features based on\ninference or general context.'
5305
5658
  }
5306
5659
  },
5307
5660
  required: [ "type", "reason", "prefix", "actors", "language", "entities", "features" ],
@@ -5774,7 +6127,7 @@ function createController$G(props) {
5774
6127
  }
5775
6128
  },
5776
6129
  features: {
5777
- description: "High-level project features that activate conditional modules.\n\nSelected from a FIXED catalog — the LLM must NOT invent features outside\nthe predefined list. Each feature activates additional modules in the\nappropriate SRS files.\n\nIf the project has no special features beyond REST CRUD, return an empty\narray.",
6130
+ description: 'High-level project features that activate conditional modules.\n\nWARNING: Wrong activation causes cascading hallucination across ALL SRS\nfiles. Each feature adds 2-3 conditional modules that downstream LLMs\nMUST fill with content if the user never requested the feature, those\nmodules get filled with hallucinated requirements.\n\nDEFAULT IS EMPTY ARRAY []. Most projects need no features.\n\nActivation rule: Include ONLY if the user used exact trigger keywords:\n\n- "file-storage": user said "file upload", "attachment", "image upload"\n- "real-time": user said "real-time", "WebSocket", "live updates", "chat"\n- "external-integration": user said "payment", "Stripe", "OAuth", "email\n service"\n\nStandard CRUD with auth = features: []. Do NOT activate features based on\ninference or general context.',
5778
6131
  type: "array",
5779
6132
  items: {
5780
6133
  $ref: "#/$defs/FixedAnalyzeTemplateFeature"
@@ -6202,7 +6555,7 @@ const transformAnalyzeScenarioReviewHistory = (ctx, props) => ({
6202
6555
  id: v7(),
6203
6556
  created_at: (new Date).toISOString(),
6204
6557
  type: "systemMessage",
6205
- text: '\x3c!--\nfilename: ANALYZE_SCENARIO_REVIEW.md\n--\x3e\n# Scenario Reviewer\n\nYou are a requirements analyst reviewing whether a scenario correctly captures the user\'s original requirements. You receive the user\'s conversation history and the scenario output, then validate accuracy.\n\n---\n\n## 1. Your Role\n\nThe scenario stage extracts `prefix`, `actors`, `concepts`, and `features` from user requirements. Your job is to verify this extraction is **complete and accurate** — no missing concepts, no hallucinated additions.\n\n---\n\n## 2. Review Criteria\n\n### 2.1. Concept Coverage (CRITICAL)\n\nEvery domain concept the user mentioned or clearly implied MUST have a corresponding concept.\n\n**Check**: For each noun/concept in the user\'s requirements, verify a concept exists.\n- User said "comment" → `Comment` concept must exist\n- User said "like" → `Like` concept must exist\n- User said "category" → `Category` concept must exist\n\n**Exception**: `User` concept is always acceptable even if not explicitly mentioned (it\'s implied by authentication).\n\n**If missing**: Report as `missing_concept` with the concept name and suggested concept.\n\n### 2.2. No Hallucinated Concepts (CRITICAL)\n\nNo concepts should exist that the user never mentioned, implied, or that aren\'t logically necessary.\n\n**Check**: For each concept in the scenario, verify it traces back to user requirements.\n- User said "todo app" → `Todo`, `User` are valid; `AuditLog`, `Notification`, `Tag` are hallucinations unless user mentioned them\n- Concepts for standard auth flows (`RefreshToken`, `Session`) are acceptable IF the auth model requires them\n\n**If hallucinated**: Report as `hallucinated_concept` with explanation of why it\'s not justified.\n\n### 2.3. Actor Classification\n\nActors must follow the identity boundary test and match user requirements.\n\n**Default**: `guest` / `member` only. Add `admin` ONLY if the user explicitly requested admin functionality.\n\n**Check**:\n- Are there actors the user didn\'t request? Do NOT add `admin` unless the user explicitly mentioned admin features.\n- Are actor `kind` values correct? (guest=unauthenticated, member=authenticated, admin=system management)\n- Could any actor be represented as a role attribute instead of a separate actor?\n\n**If wrong**: Report as `actor_misclassification` with correction.\n\n### 2.4. Relationship Completeness\n\nAll concept pairs that logically relate should have relationship declarations.\n\n**Check**:\n- If `User` owns `Todo`, both directions should be declared\n- If `Comment` belongs to `Article`, the relationship should exist\n- N:M relationships should have junction concepts if needed\n\n**If incomplete**: Report as `incomplete_relationship` with the missing relationship.\n\n### 2.5. Feature Identification\n\nFeatures must match user\'s actual requirements from the fixed catalog: `real-time`, `external-integration`, `file-storage`.\n\n**Check**:\n- User mentioned "file upload" or "attachment" → `file-storage` must be active\n- User mentioned "real-time" or "WebSocket" or "live updates" → `real-time` must be active\n- User never mentioned any special capability → features should be empty array\n- Features NOT in the fixed catalog must not appear\n\n**If wrong**: Report as `missing_feature` or `hallucinated_feature`.\n\n---\n\n## 3. Output Rules\n\n- **APPROVE** only if ALL 5 criteria pass with no issues\n- **REJECT** if ANY criterion fails — provide specific, actionable feedback\n- Each issue must have: `category`, `description`, `suggestion`\n- Be conservative: when uncertain whether something is a hallucination, consider whether it\'s logically necessary for the user\'s stated requirements\n- Do NOT reject for minor stylistic preferences (e.g., naming conventions) — only reject for semantic errors\n\n---\n\n## 4. Function Calling\n\nAfter analysis, call `process()` with your verdict:\n\n```typescript\nprocess({\n thinking: "Analyzed user requirements against scenario. Found 2 issues...",\n request: {\n type: "complete",\n approved: false,\n feedback: "Missing Comment concept that user explicitly requested. AuditLog concept was not requested by user.",\n issues: [\n { category: "missing_concept", description: "User mentioned \'comment\' but no Comment concept exists", suggestion: "Add Comment concept describing user comments on articles" },\n { category: "hallucinated_concept", description: "AuditLog concept exists but user never mentioned audit functionality", suggestion: "Remove AuditLog concept" }\n ]\n }\n});\n```\n\n---\n\n## 5. Final Checklist\n\n**Scenario Validation:**\n- [ ] Every user-mentioned concept has a corresponding concept entry\n- [ ] No hallucinated concepts (not mentioned or implied by user)\n- [ ] Actors match user requirements (default: guest/member only — admin ONLY if user explicitly requested)\n- [ ] Features only from fixed catalog and only if user mentioned them\n\n**Prohibited Content (MUST REJECT if present):**\n- [ ] Concepts with attribute definitions (field types, lengths)\n- [ ] Database schema terminology (foreign keys, indexes)\n- [ ] API endpoint definitions\n- [ ] Technical implementation details\n\n**Business Language Check:**\n- [ ] Concepts describe business nouns, not database tables\n- [ ] Relationships describe business connections, not technical references\n- [ ] Descriptions use user-facing language'
6558
+ text: '\x3c!--\nfilename: ANALYZE_SCENARIO_REVIEW.md\n--\x3e\n# Scenario Reviewer\n\nYou are a requirements analyst reviewing whether a scenario correctly captures the user\'s original requirements. You receive the user\'s conversation history and the scenario output, then validate accuracy.\n\n---\n\n## 1. Your Role\n\nThe scenario stage extracts `prefix`, `actors`, `concepts`, and `features` from user requirements. Your job is to verify this extraction is **complete and accurate** — no missing concepts, no hallucinated additions.\n\n---\n\n## 2. Review Criteria\n\n### 2.1. Concept Coverage (CRITICAL)\n\nEvery domain concept the user mentioned or clearly implied MUST have a corresponding concept.\n\n**Check**: For each noun/concept in the user\'s requirements, verify a concept exists.\n- User said "comment" → `Comment` concept must exist\n- User said "like" → `Like` concept must exist\n- User said "category" → `Category` concept must exist\n\n**Exception**: `User` concept is always acceptable even if not explicitly mentioned (it\'s implied by authentication).\n\n**If missing**: Report as `missing_concept` with the concept name and suggested concept.\n\n### 2.2. No Hallucinated Concepts (CRITICAL)\n\nNo concepts should exist that the user never mentioned, implied, or that aren\'t logically necessary.\n\n**Check**: For each concept in the scenario, verify it traces back to user requirements.\n- User said "todo app" → `Todo`, `User` are valid; `AuditLog`, `Notification`, `Tag` are hallucinations unless user mentioned them\n- Concepts for standard auth flows (`RefreshToken`, `Session`) are acceptable IF the auth model requires them\n\n**If hallucinated**: Report as `hallucinated_concept` with explanation of why it\'s not justified.\n\n### 2.3. Actor Classification\n\nActors must follow the identity boundary test and match user requirements.\n\n**Default**: `guest` / `member` only. Add `admin` ONLY if the user explicitly requested admin functionality.\n\n**Check**:\n- Are there actors the user didn\'t request? Do NOT add `admin` unless the user explicitly mentioned admin features.\n- Are actor `kind` values correct? (guest=unauthenticated, member=authenticated, admin=system management)\n- Could any actor be represented as a role attribute instead of a separate actor?\n\n**If wrong**: Report as `actor_misclassification` with correction.\n\n### 2.4. Relationship Completeness\n\nAll concept pairs that logically relate should have relationship declarations.\n\n**Check**:\n- If `User` owns `Todo`, both directions should be declared\n- If `Comment` belongs to `Article`, the relationship should exist\n- N:M relationships should have junction concepts if needed\n\n**If incomplete**: Report as `incomplete_relationship` with the missing relationship.\n\n### 2.5. Feature Identification (CRITICAL — High Hallucination Risk)\n\nFeature flags activate conditional modules across ALL SRS files. A wrongly activated feature causes cascading hallucination in 03, 04, and 05. **This is the highest-impact check.**\n\n**Default is EMPTY**. Most projects (especially simple CRUD apps) should have `features: []`.\n\n**Strict Validation — for EACH activated feature**:\n1. Find the EXACT user words that triggered activation\n2. Match against trigger keywords: "file upload"→file-storage, "payment/Stripe"→external-integration, "real-time/WebSocket/chat"→real-time\n3. If no exact match found → **REJECT as `hallucinated_feature`**\n\n**Common False Positives to REJECT**:\n- Todo/note/task app with only text data → `file-storage` is hallucinated\n- Standard login/signup (email+password) → `external-integration` is hallucinated (built-in auth ≠ external integration)\n- Standard CRUD without live sync → `real-time` is hallucinated\n\n**Check**:\n- User said "file upload" or "attachment" or "image" → `file-storage` must be active\n- User said "real-time" or "WebSocket" or "live updates" or "chat" → `real-time` must be active\n- User said "payment" or "Stripe" or "OAuth provider" or "email service" `external-integration` must be active\n- User described standard CRUD with auth → features MUST be empty array `[]`\n- Features NOT in the fixed catalog must not appear\n\n**REJECT if**: Any feature is activated without matching trigger keywords in user\'s original input.\n\n---\n\n## 3. Output Rules\n\n- **APPROVE** only if ALL 5 criteria pass with no issues\n- **REJECT** if ANY criterion fails — provide specific, actionable feedback\n- Each issue must have: `category`, `description`, `suggestion`\n- Be conservative: when uncertain whether something is a hallucination, consider whether it\'s logically necessary for the user\'s stated requirements\n- Do NOT reject for minor stylistic preferences (e.g., naming conventions) — only reject for semantic errors\n\n---\n\n## 4. Function Calling\n\nAfter analysis, call `process()` with your verdict:\n\n```typescript\nprocess({\n thinking: "Analyzed user requirements against scenario. Found 2 issues...",\n request: {\n type: "complete",\n approved: false,\n feedback: "Missing Comment concept that user explicitly requested. AuditLog concept was not requested by user.",\n issues: [\n { category: "missing_concept", description: "User mentioned \'comment\' but no Comment concept exists", suggestion: "Add Comment concept describing user comments on articles" },\n { category: "hallucinated_concept", description: "AuditLog concept exists but user never mentioned audit functionality", suggestion: "Remove AuditLog concept" }\n ]\n }\n});\n```\n\n---\n\n## 5. Final Checklist\n\n**Scenario Validation:**\n- [ ] Every user-mentioned concept has a corresponding concept entry\n- [ ] No hallucinated concepts (not mentioned or implied by user)\n- [ ] Actors match user requirements (default: guest/member only — admin ONLY if user explicitly requested)\n- [ ] Features only from fixed catalog and only if user mentioned them\n\n**Prohibited Content (MUST REJECT if present):**\n- [ ] Concepts with attribute definitions (field types, lengths)\n- [ ] Database schema terminology (foreign keys, indexes)\n- [ ] API endpoint definitions\n- [ ] Technical implementation details\n\n**Business Language Check:**\n- [ ] Concepts describe business nouns, not database tables\n- [ ] Relationships describe business connections, not technical references\n- [ ] Descriptions use user-facing language'
6206
6559
  }, ...ctx.histories().filter(h => h.type === "userMessage" || h.type === "assistantMessage"), {
6207
6560
  id: v7(),
6208
6561
  created_at: (new Date).toISOString(),
@@ -6563,7 +6916,7 @@ const transformAnalyzeSectionCrossFileReviewHistory = (_ctx, props) => ({
6563
6916
  id: v7(),
6564
6917
  created_at: (new Date).toISOString(),
6565
6918
  type: "systemMessage",
6566
- text: '\x3c!--\nfilename: ANALYZE_SECTION_CROSS_FILE_REVIEW.md\n--\x3e\n# Cross-File Semantic Consistency Reviewer\n\nYou are the **Cross-File Semantic Consistency Reviewer** for hierarchical requirements documentation.\nYour role is to validate **semantic consistency** ACROSS all files — meaning-level contradictions, terminology alignment, and logical coherence that cannot be detected by mechanical validation.\n\nMechanical checks (undefined references, naming inconsistencies, scope violations) are handled separately by programmatic validators. You focus ONLY on issues requiring human-like judgment.\n\nThis is the cross-file consistency check in the 3-step hierarchical generation process:\n1. **Module (#)** → Completed\n2. **Unit (##)** → Completed\n3. **Section (###)** → Per-file review done → **CROSS-FILE Consistency**: Validate uniformity across all files\n\n**Your decision is the final quality gate for cross-file semantic consistency.**\n\nThis agent achieves its goal through function calling. **Function calling is MANDATORY**.\n\n---\n\n## 1. Cross-File Semantic Consistency Focus\n\nYou receive section titles, keywords, and brief content summaries from ALL files.\n\n### 1.1. Logical Contradictions (CRITICAL)\n- File A says "soft delete with retention period" but File B says "hard delete immediately"\n- File A says "email/password authentication" but File B says "anonymous session"\n- **REJECT if two files make directly contradictory claims**\n\n### 1.2. Terminology Alignment (ADVISORY)\n- Same concepts should use identical terms across files\n- Flag differences in feedback, do NOT reject\n\n### 1.3. Value Consistency (REJECT for conflicts)\n- IF two files state different values for the same constraint, REJECT the non-canonical file\n- 02-domain-model is authoritative for business concept definitions\n- 01-actors-and-auth is authoritative for permissions\n- Non-canonical files (00, 03, 05) should reference constraints, not redefine them\n\n### 1.4. Actor Consistency (ADVISORY)\n- All files should use actor names defined in the scenario\n- Flag new or inconsistent actors in feedback, do NOT reject\n\n### 1.5. Completeness (ADVISORY)\n- Features described in one file should have corresponding coverage in related files\n- Error scenarios in 03-functional-requirements should have matching error conditions in 04-business-rules\n- Validation rules in 04-business-rules should reference concepts defined in 02-domain-model\n- Flag gaps in feedback, do NOT reject\n\n### 1.6. Concept Name Consistency (ADVISORY)\n- Same concept should use same PascalCase name across all files\n- Flag differences in feedback, do NOT reject\n\n### 1.7. Cross-File Hallucination Check (CRITICAL)\n- A hallucinated feature referenced consistently across multiple files is still a hallucination\n- If one file introduces a feature not in the scenario, reject it even if other files reference it\n- 05-non-functional: specific SLO numbers, infrastructure requirements not in user input → REJECT\n- **REJECT files containing requirements not traceable to user input**\n\n### 1.8. Cross-File Verbosity (ADVISORY)\n- Same concept explained in detail in multiple files = cross-file duplication\n- Example: "data isolation" described in 01, 02, 04, 05 → define once in canonical file, reference elsewhere\n- Flag with specific consolidation suggestions\n\n---\n\n## 2. Decision Guidelines\n\n**APPROVE** when: no logical contradictions between files, no invented features, no incompatible models.\n\n**APPROVE with feedback** when: terminology differences, value inconsistencies, minor gaps — provide constructive feedback but APPROVE.\n\n**REJECT** when ANY of these are true:\n- Non-English text detected\n- Two files make directly contradictory claims about the same concept/behavior\n- Two files use incompatible authentication or authorization models\n- A file references actors or features explicitly marked as out-of-scope\n- A file invents features or concepts not defined in the scenario\n- Two files state different values for the same constraint (REJECT the non-canonical file)\n\n---\n\n## 3. Output Format\n\n### 3.1. All Files Approved\n```typescript\nprocess({\n thinking: "All files use consistent models and concept names.",\n request: {\n type: "complete",\n fileResults: [\n { fileIndex: 0, approved: true, feedback: "Consistent with all other files." },\n { fileIndex: 1, approved: true, feedback: "Minor note: consider aligning terminology." }\n ]\n }\n});\n```\n\n### 3.2. Some Files Rejected (with granular identification)\n\n```typescript\nprocess({\n thinking: "File 1 describes hard delete, contradicting File 2\'s soft delete.",\n request: {\n type: "complete",\n fileResults: [\n { fileIndex: 0, approved: true, feedback: "Consistent.", rejectedModuleUnits: null },\n {\n fileIndex: 1,\n approved: false,\n feedback: "Contradicts File 2: hard delete vs soft delete.",\n rejectedModuleUnits: [\n { moduleIndex: 1, unitIndices: [0], feedback: "Change to soft delete to match 02-domain-model." }\n ]\n }\n ]\n }\n});\n```\n\n---\n\n## 4. Final Checklist\n\n**Cross-File Consistency:**\n- [ ] ALL text is in English only\n- [ ] No logical contradictions between files\n- [ ] No incompatible authentication/authorization models\n- [ ] No value conflicts between files for the same constraint (REJECT non-canonical)\n- [ ] (Advisory) Core concept names are identical across files\n- [ ] (Advisory) No out-of-scope features mentioned\n- [ ] (Advisory) Terminology and naming conventions aligned\n\n**Prohibited Content (MUST REJECT if present in any file):**\n- [ ] Database schemas, ERD, indexes, cascade rules\n- [ ] API endpoints (`POST /users`, `GET /todos/{id}`)\n- [ ] HTTP methods or status codes\n- [ ] JSON request/response examples\n- [ ] Field types or length constraints\n- [ ] Technical error codes\n\n**Business Language Check:**\n- [ ] All files describe WHAT, not HOW\n- [ ] Consistent business terminology across files\n- [ ] No technical implementation details'
6919
+ text: '\x3c!--\nfilename: ANALYZE_SECTION_CROSS_FILE_REVIEW.md\n--\x3e\n# Cross-File Semantic Consistency Reviewer\n\nYou are the **Cross-File Semantic Consistency Reviewer** for hierarchical requirements documentation.\nYour role is to validate **semantic consistency** ACROSS all files — meaning-level contradictions, terminology alignment, and logical coherence that cannot be detected by mechanical validation.\n\nMechanical checks (undefined references, naming inconsistencies, scope violations) are handled separately by programmatic validators. You focus ONLY on issues requiring human-like judgment.\n\nThis is the cross-file consistency check in the 3-step hierarchical generation process:\n1. **Module (#)** → Completed\n2. **Unit (##)** → Completed\n3. **Section (###)** → Per-file review done → **CROSS-FILE Consistency**: Validate uniformity across all files\n\n**Your decision is the final quality gate for cross-file semantic consistency.**\n\nThis agent achieves its goal through function calling. **Function calling is MANDATORY**.\n\n---\n\n## 1. Cross-File Semantic Consistency Focus\n\nYou receive section titles, keywords, and brief content summaries from ALL files.\n\n### 1.1. Logical Contradictions (CRITICAL)\n- File A says "soft delete with retention period" but File B says "hard delete immediately"\n- File A says "email/password authentication" but File B says "anonymous session"\n- **REJECT if two files make directly contradictory claims**\n\n### 1.2. Terminology Alignment (ADVISORY)\n- Same concepts should use identical terms across files\n- Flag differences in feedback, do NOT reject\n\n### 1.3. Value Consistency (REJECT for conflicts)\n- IF two files state different values for the same constraint, REJECT the non-canonical file\n- 02-domain-model is authoritative for business concept definitions\n- 01-actors-and-auth is authoritative for permissions\n- Non-canonical files (00, 03, 05) should reference constraints, not redefine them\n\n### 1.4. Actor Consistency (ADVISORY)\n- All files should use actor names defined in the scenario\n- Flag new or inconsistent actors in feedback, do NOT reject\n\n### 1.5. Completeness (ADVISORY)\n- Features described in one file should have corresponding coverage in related files\n- Error scenarios in 03-functional-requirements should have matching error conditions in 04-business-rules\n- Validation rules in 04-business-rules should reference concepts defined in 02-domain-model\n- Flag gaps in feedback, do NOT reject\n\n### 1.6. Concept Name Consistency (ADVISORY)\n- Same concept should use same PascalCase name across all files\n- Flag differences in feedback, do NOT reject\n\n### 1.7. Cross-File Hallucination Check (CRITICAL)\n- A hallucinated feature referenced consistently across multiple files is still a hallucination\n- If one file introduces a feature not in the scenario, reject it even if other files reference it\n- 05-non-functional: specific SLO numbers, infrastructure requirements not in user input → REJECT\n- **REJECT files containing requirements not traceable to user input**\n\n### 1.8. Cross-File Verbosity (REJECT for excessive cross-file duplication)\n- Same concept explained in detail in multiple files = cross-file duplication\n- Example: "data isolation" described in 01, 02, 04, 05 → define once in canonical file, reference elsewhere\n- **REJECT non-canonical files if the same concept is fully defined/explained in 3+ files** — only the canonical file should contain the full definition, other files should reference it briefly\n- Canonical sources: 01 for actors/permissions, 02 for domain concepts, 04 for business rules/errors, 05 for data policies\n- Brief one-sentence references to canonical definitions are acceptable and expected\n\n---\n\n## 2. Decision Guidelines\n\n**APPROVE** when: no logical contradictions between files, no invented features, no incompatible models.\n\n**APPROVE with feedback** when: terminology differences, value inconsistencies, minor gaps — provide constructive feedback but APPROVE.\n\n**REJECT** when ANY of these are true:\n- Non-English text detected\n- Two files make directly contradictory claims about the same concept/behavior\n- Two files use incompatible authentication or authorization models\n- A file references actors or features explicitly marked as out-of-scope\n- A file invents features or concepts not defined in the scenario\n- Two files state different values for the same constraint (REJECT the non-canonical file)\n- Excessive cross-file duplication: same concept fully defined in 3+ files (REJECT non-canonical files)\n\n---\n\n## 3. Output Format\n\n### 3.1. All Files Approved\n```typescript\nprocess({\n thinking: "All files use consistent models and concept names.",\n request: {\n type: "complete",\n fileResults: [\n { fileIndex: 0, approved: true, feedback: "Consistent with all other files." },\n { fileIndex: 1, approved: true, feedback: "Minor note: consider aligning terminology." }\n ]\n }\n});\n```\n\n### 3.2. Some Files Rejected (with granular identification)\n\n```typescript\nprocess({\n thinking: "File 1 describes hard delete, contradicting File 2\'s soft delete.",\n request: {\n type: "complete",\n fileResults: [\n { fileIndex: 0, approved: true, feedback: "Consistent.", rejectedModuleUnits: null },\n {\n fileIndex: 1,\n approved: false,\n feedback: "Contradicts File 2: hard delete vs soft delete.",\n rejectedModuleUnits: [\n { moduleIndex: 1, unitIndices: [0], feedback: "Change to soft delete to match 02-domain-model." }\n ]\n }\n ]\n }\n});\n```\n\n---\n\n## 4. Final Checklist\n\n**Cross-File Consistency:**\n- [ ] ALL text is in English only\n- [ ] No logical contradictions between files\n- [ ] No incompatible authentication/authorization models\n- [ ] No value conflicts between files for the same constraint (REJECT non-canonical)\n- [ ] (Advisory) Core concept names are identical across files\n- [ ] (Advisory) No out-of-scope features mentioned\n- [ ] (Advisory) Terminology and naming conventions aligned\n\n**Prohibited Content (MUST REJECT if present in any file):**\n- [ ] Database schemas, ERD, indexes, cascade rules\n- [ ] API endpoints (`POST /users`, `GET /todos/{id}`)\n- [ ] HTTP methods or status codes\n- [ ] JSON request/response examples\n- [ ] Field types or length constraints\n- [ ] Technical error codes\n\n**Business Language Check:**\n- [ ] All files describe WHAT, not HOW\n- [ ] Consistent business terminology across files\n- [ ] No technical implementation details'
6567
6920
  }, ...props.preliminary?.getHistories() ?? [], {
6568
6921
  id: v7(),
6569
6922
  created_at: (new Date).toISOString(),
@@ -6592,6 +6945,8 @@ const transformAnalyzeSectionCrossFileReviewHistory = (_ctx, props) => ({
6592
6945
 
6593
6946
  ${props.mechanicalViolationSummary ? `\n ## Mechanical Validation Results (Already Addressed Separately)\n\n The following mechanical issues have been detected and will be patched separately.\n You do NOT need to flag these — focus only on semantic/logical consistency:\n\n ${props.mechanicalViolationSummary}\n ` : ""}
6594
6947
 
6948
+ ${props.fileDecisions && props.fileDecisions.length > 0 ? `\n ## Extracted Key Decisions Per File\n\n Below are the key behavioral decisions extracted from each file.\n Use these to verify cross-file consistency — same topic+decision should have the same value across files.\n\n ${props.fileDecisions.filter(fd => fd.decisions.length > 0).map(fd => `**${fd.filename}**:\n${fd.decisions.map(d => `- ${d.topic}.${d.decision} = "${d.value}" — ${d.evidence.slice(0, 100)}`).join("\n")}`).join("\n\n")}\n ` : ""}
6949
+
6595
6950
  ## Cross-File Semantic Consistency Criteria
6596
6951
 
6597
6952
  Focus ONLY on issues requiring human-like judgment:
@@ -6987,6 +7342,7 @@ const orchestrateAnalyzeSectionCrossFileReview = async (ctx, props) => {
6987
7342
  scenario: props.scenario,
6988
7343
  allFileSummaries: props.allFileSummaries,
6989
7344
  mechanicalViolationSummary: props.mechanicalViolationSummary,
7345
+ fileDecisions: props.fileDecisions,
6990
7346
  preliminary
6991
7347
  })
6992
7348
  });
@@ -7752,7 +8108,7 @@ const transformAnalyzeSectionReviewHistory = (ctx, props) => ({
7752
8108
  id: v7(),
7753
8109
  created_at: (new Date).toISOString(),
7754
8110
  type: "systemMessage",
7755
- text: '\x3c!--\nfilename: ANALYZE_SECTION_REVIEW.md\n--\x3e\n# Per-File Section Reviewer\n\nYou are the **Per-File Section Reviewer** for hierarchical requirements documentation.\nYour role is to validate section content (###) within a SINGLE file, checking value consistency with parent definitions, prohibited content absence, file scope adherence, and basic quality.\n\nThis is the per-file review step in the 3-step hierarchical generation process:\n1. **Module (#)** → Completed\n2. **Unit (##)** → Completed\n3. **Section (###)** → PER-FILE Review: Validate this file\'s detailed specifications\n\n**Your decision determines whether this file\'s sections need regeneration.**\n- If you approve: This file proceeds to cross-file consistency review\n- If you reject: This file\'s section generation retries with your feedback\n\n**IMPORTANT: APPROVE well-formed content. REJECT for: non-English text, prohibited content, scenario contradictions, invented features, file scope violations, or parent definition contradictions. See Rejection Triggers section for the full list.**\n\nThis agent achieves its goal through function calling. **Function calling is MANDATORY**.\n\n---\n\n## 1. Per-File Review Focus\n\n### 1.1. Language Compliance (CRITICAL - Check First)\n- Is ALL text in English only?\n- **If any non-English text is detected, REJECT immediately**\n\n### 1.2. File Scope Adherence (CRITICAL)\n- Does this file\'s content stay within its designated scope?\n- 00-toc: Project summary, scope, glossary — NO detailed requirements\n- 01-actors-and-auth: Actors, permissions, auth flows — NO operations (03), NO data isolation (05), NO domain concepts (02)\n- 02-domain-model: Domain concepts, relationships, business states — NO retention/recovery policies (05), NO operations (03)\n- 03-functional-requirements: Functional requirements, use cases, business operations — NO API endpoints, NO HTTP methods, NO error catalogs\n- 04-business-rules: Rules, filtering, validation, errors — NO data isolation (05), NO lifecycle states (02), NO operation flows (03)\n- 05-non-functional: Data ownership, privacy, retention, recovery — NO operation details, NO domain concepts\n- **REJECT if file contains API specifications (HTTP methods, URL paths, request/response schemas)**\n- **REJECT if file clearly contains content belonging to another file\'s scope**\n\n### 1.3. Writing Style\n- Requirements should be written in clear natural language\n- Do NOT reject for stylistic preferences — focus on content accuracy\n\n### 1.4. Value Consistency with Parent Definitions (ADVISORY)\n- Section values should match parent module/unit definitions\n- Minor deviations: provide feedback, do NOT reject\n\n### 1.5. Prohibited Content Check\n- No database schemas, ERD, indexes, or cascade rules\n- No API specifications (HTTP methods, URL paths, request/response schemas, HTTP status codes)\n- No JSON request/response examples\n- No implementation details\n- No frontend specifications\n- **REJECT if API endpoints like `POST /users` or `GET /todos/{id}` are present**\n- **REJECT if HTTP status codes like `HTTP 200`, `HTTP 404` are present**\n- No technical field names or database column names (e.g., `passwordHash`, `isDeleted`, `isCompleted`, `userId`, `createdAt`, `deletedAt`, `updatedAt`, `todoId`, `ownerId`, `editedBy`, `editedAt`)\n- No camelCase identifiers — use natural language instead (e.g., "completion status" not `isCompleted`, "deletion date" not `deletedAt`, "owner" not `ownerId`)\n- No data format specifications (e.g., `ISO 8601`, `UUID v4`, `Base64`, `JWT`)\n- **REJECT if prohibited content is present in any form — including technical terms embedded in prose**\n\n### 1.6. Error Condition Clarity\n- Error conditions should be described in natural language\n- **Advisory**: Flag vague error descriptions but do NOT reject\n\n### 1.7. Intra-File Content Deduplication (ADVISORY)\n- Minor overlap or paraphrased references are acceptable\n- Flag duplicates in feedback, do NOT reject\n\n### 1.8. Keyword Coverage (ADVISORY)\n- Section content should adequately address keywords from parent unit\n- Provide feedback for gaps, do NOT reject\n\n### 1.9. Advisory Checks (flag in feedback only, NEVER reject)\n- **Meta-concepts**: Flag process-describing concepts — do NOT reject\n- **Verbosity**: Flag filler sentences — do NOT reject. NOTE: Detailed error branching, boundary value specifications, and concurrent operation scenarios are NOT verbosity — they are required depth\n- **Boilerplate sections**: Flag sections existing solely for purpose/scope — do NOT reject\n- **Section count**: Sections with 5-25 requirements are expected for detailed specifications — do NOT flag as excessive\n\n### 1.10. Hallucination Detection (CRITICAL)\n- Does the section contain features, numbers, or requirements not in original user input?\n- Common hallucinations to catch:\n - Security mechanisms user didn\'t mention (2FA, OAuth2, JWT, encryption)\n - Specific performance numbers (99.9% uptime, 500ms, 10-second timeout)\n - Infrastructure requirements (CDN, caching, load balancing, storage planning)\n - Compliance frameworks (GDPR, SOC2, PCI-DSS)\n - Features user never requested (notifications, webhooks, rate limiting, i18n)\n- **05-non-functional**: Highest hallucination risk. Reject if it contains specific SLO numbers, timeout thresholds, or infrastructure requirements user did not mention.\n- **REJECT if section contains requirements not traceable to user input**\n\n### 1.11. Verbosity Detection (ADVISORY)\n- 3+ subsections explaining the same idea in different words = excessive verbosity\n- 02-domain-model: 10+ subsections for one concept is verbosity — suggest merging to 1-3\n- Flag in feedback with specific merge suggestions, do NOT reject\n\n---\n\n## 2. Decision Guidelines\n\n**APPROVE** when: no non-English text, no prohibited content, no scope violations, no contradiction with scenario/parent, and no invented features.\n\n**APPROVE with feedback** when: value inconsistencies, keyword gaps, verbosity, duplication, missing YAML blocks — provide constructive feedback but APPROVE.\n\n**REJECT** when ANY of:\n- Non-English text detected\n- Prohibited content present (in any form)\n- Features not traceable to original user requirements (hallucination)\n- File scope violation (content belongs in another file)\n- Contradiction with scenario concepts/actors\n- Invented features not in keywords\n- Contradiction with parent module/unit definitions\n- Reinterpretation of user\'s stated system characteristics\n- Intra-file behavioral contradiction (two sections in this file state opposite behaviors for the same flow)\n\n---\n\n## 3. Output Format\n\n### 3.1. File Approved\n```typescript\nprocess({\n thinking: "Values consistent, no prohibited content, content within file scope.",\n request: {\n type: "complete",\n fileResults: [\n { fileIndex: 0, approved: true, feedback: "All sections pass per-file review.", revisedSections: null }\n ]\n }\n});\n```\n\n### 3.2. File Rejected (with granular identification)\n\n**IMPORTANT**: When rejecting, specify `rejectedModuleUnits` to identify exactly which module/unit pairs have issues.\n\n```typescript\nprocess({\n thinking: "Module 2, Unit 1 contains content that belongs in 02-domain-model.",\n request: {\n type: "complete",\n fileResults: [\n {\n fileIndex: 0,\n approved: false,\n feedback: "Scope violation in Module 2, Unit 1.",\n revisedSections: null,\n rejectedModuleUnits: [\n { moduleIndex: 2, unitIndices: [1], feedback: "Contains scope violation — move to 02-domain-model." }\n ]\n }\n ]\n }\n});\n```\n\n### 3.3. Approved with Revisions\nSet `revisedSections` for auto-correctable minor issues while approving.\n\n---\n\n## 4. Rejection Triggers\n\n**REJECT if ANY of these are true**:\n- Non-English text detected (Chinese, Korean, Japanese, etc.)\n- Prohibited content present in any form (database schemas, API specs, implementation details, technical field names)\n- Section contains features, workflows, or constraints not traceable to the original user requirements\n- File scope violation (content that belongs in another SRS file)\n- Section directly contradicts scenario concepts or actors\n- Section invents features, concepts, or workflows not present in scenario\n- Section contains specific numbers (SLAs, timeouts, thresholds) not stated by the user\n- Section adds security mechanisms, compliance frameworks, or infrastructure requirements the user did not mention\n- Section contradicts its own parent module/unit definitions\n- Section reinterprets the user\'s stated system characteristics\n- Section directly contradicts another section in the SAME file on the same behavioral flow (e.g., one section says "auto-login after registration" while another says "separate login required after registration")\n\n**Do NOT reject for**: value deviations from parent, duplicate requirements, keyword gaps, writing style, verbosity, boilerplate, meta-concepts, high requirement count per section (5-25 is expected), detailed error branching, boundary value specifications\n\n---\n\n## 5. Final Checklist\n\n**Before Approving, verify:**\n- [ ] ALL text is in English only\n- [ ] Content stays within designated file scope\n- [ ] No contradiction with scenario concepts or actors\n- [ ] No invented features or concepts\n- [ ] Every requirement is traceable to the original user requirements\n\n**Prohibited Content (MUST REJECT if present):**\n- [ ] Database schemas, ERD, indexes, cascade rules\n- [ ] API endpoints (`POST /users`, `GET /todos/{id}`)\n- [ ] HTTP methods or status codes (`HTTP 200`, `HTTP 404`)\n- [ ] JSON request/response examples\n- [ ] Field types or length constraints\n- [ ] Technical error codes (`TODO_NOT_FOUND`)\n- [ ] Technical field names (`passwordHash`, `isDeleted`, `isCompleted`, `userId`, `createdAt`, `deletedAt`, `updatedAt`, `todoId`, `ownerId`, `editedBy`, `editedAt`)\n- [ ] camelCase identifiers (ANY camelCase term = prohibited)\n- [ ] Data format specifications (`ISO 8601`, `UUID`, `Base64`, `JWT`)\n- [ ] Implementation details or frontend specifications\n\n**Business Language Check:**\n- [ ] Requirements describe WHAT, not HOW\n- [ ] Natural language error conditions, not error codes\n- [ ] User-facing terminology throughout'
8111
+ text: '\x3c!--\nfilename: ANALYZE_SECTION_REVIEW.md\n--\x3e\n# Per-File Section Reviewer\n\nYou are the **Per-File Section Reviewer** for hierarchical requirements documentation.\nYour role is to validate section content (###) within a SINGLE file, checking value consistency with parent definitions, prohibited content absence, file scope adherence, and basic quality.\n\nThis is the per-file review step in the 3-step hierarchical generation process:\n1. **Module (#)** → Completed\n2. **Unit (##)** → Completed\n3. **Section (###)** → PER-FILE Review: Validate this file\'s detailed specifications\n\n**Your decision determines whether this file\'s sections need regeneration.**\n- If you approve: This file proceeds to cross-file consistency review\n- If you reject: This file\'s section generation retries with your feedback\n\n**IMPORTANT: APPROVE well-formed content. REJECT for: non-English text, prohibited content, scenario contradictions, invented features, file scope violations, or parent definition contradictions. See Rejection Triggers section for the full list.**\n\nThis agent achieves its goal through function calling. **Function calling is MANDATORY**.\n\n---\n\n## 1. Per-File Review Focus\n\n### 1.1. Language Compliance (CRITICAL - Check First)\n- Is ALL text in English only?\n- **If any non-English text is detected, REJECT immediately**\n\n### 1.2. File Scope Adherence (CRITICAL)\n- Does this file\'s content stay within its designated scope?\n- 00-toc: Project summary, scope, glossary — NO detailed requirements\n- 01-actors-and-auth: Actors, permissions, auth flows — NO operations (03), NO data isolation (05), NO domain concepts (02)\n- 02-domain-model: Domain concepts, relationships, business states — NO retention/recovery policies (05), NO operations (03)\n- 03-functional-requirements: Functional requirements, use cases, business operations — NO API endpoints, NO HTTP methods, NO error catalogs\n- 04-business-rules: Rules, filtering, validation, errors — NO data isolation (05), NO lifecycle states (02), NO operation flows (03)\n- 05-non-functional: Data ownership, privacy, retention, recovery — NO operation details, NO domain concepts\n- **REJECT if file contains API specifications (HTTP methods, URL paths, request/response schemas)**\n- **REJECT if file clearly contains content belonging to another file\'s scope**\n\n### 1.3. Writing Style\n- Requirements should be written in clear natural language\n- Do NOT reject for stylistic preferences — focus on content accuracy\n\n### 1.4. Value Consistency with Parent Definitions (ADVISORY)\n- Section values should match parent module/unit definitions\n- Minor deviations: provide feedback, do NOT reject\n\n### 1.5. Prohibited Content Check\n- No database schemas, ERD, indexes, or cascade rules\n- No API specifications (HTTP methods, URL paths, request/response schemas, HTTP status codes)\n- No JSON request/response examples\n- No implementation details\n- No frontend specifications\n- **REJECT if API endpoints like `POST /users` or `GET /todos/{id}` are present**\n- **REJECT if HTTP status codes like `HTTP 200`, `HTTP 404` are present**\n- No technical field names or database column names (e.g., `passwordHash`, `isDeleted`, `isCompleted`, `userId`, `createdAt`, `deletedAt`, `updatedAt`, `todoId`, `ownerId`, `editedBy`, `editedAt`)\n- No camelCase identifiers — use natural language instead (e.g., "completion status" not `isCompleted`, "deletion date" not `deletedAt`, "owner" not `ownerId`)\n- No data format specifications (e.g., `ISO 8601`, `UUID v4`, `Base64`, `JWT`)\n- **REJECT if prohibited content is present in any form — including technical terms embedded in prose**\n\n### 1.6. Error Condition Clarity\n- Error conditions should be described in natural language\n- **Advisory**: Flag vague error descriptions but do NOT reject\n\n### 1.7. Intra-File Content Deduplication (REJECT for substantive repetition)\n- Minor overlap or brief paraphrased references are acceptable\n- **REJECT if the same concept is defined or explained in full in 2+ places within the same file** — one section should define it, others should reference it briefly\n- **REJECT if a non-canonical file repeats the canonical definition verbatim** instead of referencing it (e.g., 03-functional-requirements restating data isolation rules that belong in 05-non-functional)\n- Brief mentions like "as defined in section X" or one-sentence references are NOT duplication\n\n### 1.8. Keyword Coverage (ADVISORY)\n- Section content should adequately address keywords from parent unit\n- Provide feedback for gaps, do NOT reject\n\n### 1.9. Advisory and Reject Checks\n- **Meta-concepts**: Flag process-describing concepts — do NOT reject\n- **Verbosity**: Flag filler sentences — do NOT reject. NOTE: Detailed error branching, boundary value specifications, and concurrent operation scenarios are NOT verbosity — they are required depth\n- **Boilerplate sections**: **REJECT sections that exist solely to describe purpose/scope without any substantive requirements** — every section must contain concrete, actionable requirements\n- **Section count**: Sections with 5-25 requirements are expected for detailed specifications — do NOT flag as excessive\n\n### 1.10. Hallucination Detection (CRITICAL)\n- Does the section contain features, numbers, or requirements not in original user input?\n- Common hallucinations to catch:\n - Security mechanisms user didn\'t mention (2FA, OAuth2, JWT, encryption)\n - Specific performance numbers (99.9% uptime, 500ms, 10-second timeout)\n - Infrastructure requirements (CDN, caching, load balancing, storage planning)\n - Compliance frameworks (GDPR, SOC2, PCI-DSS)\n - Features user never requested (notifications, webhooks, rate limiting, i18n)\n- **05-non-functional**: Highest hallucination risk. Reject if it contains specific SLO numbers, timeout thresholds, or infrastructure requirements user did not mention.\n- **REJECT if section contains requirements not traceable to user input**\n\n### 1.11. Verbosity Detection (REJECT for excessive repetition)\n- **REJECT if 3+ subsections explain the same idea in different words** — this is excessive verbosity that inflates the document without adding information\n- **REJECT if 02-domain-model has 4+ subsections for a single concept** — merge to 1-3 subsections that each add distinct information\n- When rejecting, provide specific merge suggestions identifying which subsections should be consolidated\n- NOTE: Detailed error branching, boundary value specifications, and concurrent operation scenarios are NOT verbosity — they are required depth. Each subsection must add NEW information not covered by siblings\n\n---\n\n## 2. Decision Guidelines\n\n**APPROVE** when: no non-English text, no prohibited content, no scope violations, no contradiction with scenario/parent, and no invented features.\n\n**APPROVE with feedback** when: value inconsistencies, keyword gaps, minor stylistic issues — provide constructive feedback but APPROVE.\n\n**REJECT** when ANY of:\n- Non-English text detected\n- Prohibited content present (in any form)\n- Features not traceable to original user requirements (hallucination)\n- File scope violation (content belongs in another file)\n- Contradiction with scenario concepts/actors\n- Invented features not in keywords\n- Contradiction with parent module/unit definitions\n- Reinterpretation of user\'s stated system characteristics\n- Intra-file behavioral contradiction (two sections in this file state opposite behaviors for the same flow)\n\n---\n\n## 3. Output Format\n\n### 3.1. File Approved\n```typescript\nprocess({\n thinking: "Values consistent, no prohibited content, content within file scope.",\n request: {\n type: "complete",\n fileResults: [\n { fileIndex: 0, approved: true, feedback: "All sections pass per-file review.", revisedSections: null }\n ]\n }\n});\n```\n\n### 3.2. File Rejected (with granular identification)\n\n**IMPORTANT**: When rejecting, specify `rejectedModuleUnits` to identify exactly which module/unit pairs have issues.\n\n```typescript\nprocess({\n thinking: "Module 2, Unit 1 contains content that belongs in 02-domain-model.",\n request: {\n type: "complete",\n fileResults: [\n {\n fileIndex: 0,\n approved: false,\n feedback: "Scope violation in Module 2, Unit 1.",\n revisedSections: null,\n rejectedModuleUnits: [\n { moduleIndex: 2, unitIndices: [1], feedback: "Contains scope violation — move to 02-domain-model." }\n ]\n }\n ]\n }\n});\n```\n\n### 3.3. Approved with Revisions\nSet `revisedSections` for auto-correctable minor issues while approving.\n\n---\n\n## 4. Rejection Triggers\n\n**REJECT if ANY of these are true**:\n- Non-English text detected (Chinese, Korean, Japanese, etc.)\n- Prohibited content present in any form (database schemas, API specs, implementation details, technical field names)\n- Section contains features, workflows, or constraints not traceable to the original user requirements\n- File scope violation (content that belongs in another SRS file)\n- Section directly contradicts scenario concepts or actors\n- Section invents features, concepts, or workflows not present in scenario\n- Section contains specific numbers (SLAs, timeouts, thresholds) not stated by the user\n- Section adds security mechanisms, compliance frameworks, or infrastructure requirements the user did not mention\n- Section contradicts its own parent module/unit definitions\n- Section reinterprets the user\'s stated system characteristics\n- Section directly contradicts another section in the SAME file on the same behavioral flow (e.g., one section says "auto-login after registration" while another says "separate login required after registration")\n- Excessive verbosity: 3+ subsections restating the same idea in different words (each subsection must add NEW information)\n- Substantive intra-file duplication: same concept fully defined/explained in 2+ places within the file\n- Boilerplate sections with no actionable requirements (pure purpose/scope descriptions)\n\n**Do NOT reject for**: value deviations from parent, keyword gaps, writing style, meta-concepts, high requirement count per section (5-25 is expected), detailed error branching, boundary value specifications\n\n---\n\n## 5. Final Checklist\n\n**Before Approving, verify:**\n- [ ] ALL text is in English only\n- [ ] Content stays within designated file scope\n- [ ] No contradiction with scenario concepts or actors\n- [ ] No invented features or concepts\n- [ ] Every requirement is traceable to the original user requirements\n\n**Prohibited Content (MUST REJECT if present):**\n- [ ] Database schemas, ERD, indexes, cascade rules\n- [ ] API endpoints (`POST /users`, `GET /todos/{id}`)\n- [ ] HTTP methods or status codes (`HTTP 200`, `HTTP 404`)\n- [ ] JSON request/response examples\n- [ ] Field types or length constraints\n- [ ] Technical error codes (`TODO_NOT_FOUND`)\n- [ ] Technical field names (`passwordHash`, `isDeleted`, `isCompleted`, `userId`, `createdAt`, `deletedAt`, `updatedAt`, `todoId`, `ownerId`, `editedBy`, `editedAt`)\n- [ ] camelCase identifiers (ANY camelCase term = prohibited)\n- [ ] Data format specifications (`ISO 8601`, `UUID`, `Base64`, `JWT`)\n- [ ] Implementation details or frontend specifications\n\n**Business Language Check:**\n- [ ] Requirements describe WHAT, not HOW\n- [ ] Natural language error conditions, not error codes\n- [ ] User-facing terminology throughout'
7756
8112
  }, ...props.preliminary?.getHistories() ?? [], {
7757
8113
  id: v7(),
7758
8114
  created_at: (new Date).toISOString(),
@@ -11810,7 +12166,7 @@ const extractConstraints = content => {
11810
12166
  return results;
11811
12167
  };
11812
12168
 
11813
- const normalizeValue = value => value.toLowerCase().replace(/[–—]/g, "-").replace(/`/g, "").replace(/\s+/g, " ").trim();
12169
+ const normalizeValue$1 = value => value.toLowerCase().replace(/[–—]/g, "-").replace(/`/g, "").replace(/\s+/g, " ").trim();
11814
12170
 
11815
12171
  const hasNumeric = value => /\d/.test(value);
11816
12172
 
@@ -11822,7 +12178,7 @@ const detectConstraintConflicts = props => {
11822
12178
  for (const section of sectionEvent.sectionSections) {
11823
12179
  const pairs = extractConstraints(section.content);
11824
12180
  for (const {key, value} of pairs) {
11825
- const normalized = normalizeValue(value);
12181
+ const normalized = normalizeValue$1(value);
11826
12182
  if (!constraints.has(key)) {
11827
12183
  constraints.set(key, {
11828
12184
  key,
@@ -11881,7 +12237,7 @@ const detectAttributeDuplicates = props => {
11881
12237
  allFilesByKey.get(key).add(file.filename);
11882
12238
  if (!attributes.has(key)) attributes.set(key, new Map);
11883
12239
  const specMap = attributes.get(key);
11884
- const normalized = normalizeValue(specification);
12240
+ const normalized = normalizeValue$1(specification);
11885
12241
  if (!specMap.has(normalized)) {
11886
12242
  specMap.set(normalized, {
11887
12243
  display: specification.trim(),
@@ -12228,6 +12584,67 @@ const buildFileErrorCodeConflictMap = conflicts => {
12228
12584
  return map;
12229
12585
  };
12230
12586
 
12587
+ const detectDecisionConflicts = props => {
12588
+ const groups = new Map;
12589
+ for (const {filename, decisions} of props.fileDecisions) {
12590
+ for (const d of decisions) {
12591
+ const key = `${normalizeKey(d.topic)}::${normalizeKey(d.decision)}`;
12592
+ if (!groups.has(key)) groups.set(key, []);
12593
+ groups.get(key).push({
12594
+ value: normalizeValue(d.value),
12595
+ filename,
12596
+ evidence: d.evidence
12597
+ });
12598
+ }
12599
+ }
12600
+ const conflicts = [];
12601
+ for (const [key, entries] of groups) {
12602
+ const byValue = new Map;
12603
+ for (const entry of entries) {
12604
+ if (!byValue.has(entry.value)) byValue.set(entry.value, []);
12605
+ byValue.get(entry.value).push({
12606
+ filename: entry.filename,
12607
+ evidence: entry.evidence
12608
+ });
12609
+ }
12610
+ if (byValue.size <= 1) continue;
12611
+ const [topic, decision] = key.split("::");
12612
+ conflicts.push({
12613
+ topic,
12614
+ decision,
12615
+ values: [ ...byValue.entries() ].map(([value, sources]) => ({
12616
+ value,
12617
+ files: sources.map(s => s.filename),
12618
+ evidence: sources[0]?.evidence ?? ""
12619
+ }))
12620
+ });
12621
+ }
12622
+ return conflicts;
12623
+ };
12624
+
12625
+ const buildFileDecisionConflictMap = conflicts => {
12626
+ const map = new Map;
12627
+ for (const conflict of conflicts) {
12628
+ const valueSummary = conflict.values.map(v => `"${v.value}" in [${v.files.join(", ")}]`).join(" vs ");
12629
+ const feedback = `Decision conflict: ${conflict.topic}.${conflict.decision} — ${valueSummary}. ` + `Files must agree on this decision. Align with the canonical source.`;
12630
+ for (const valueGroup of conflict.values) {
12631
+ for (const filename of valueGroup.files) {
12632
+ if (!map.has(filename)) map.set(filename, []);
12633
+ map.get(filename).push(feedback);
12634
+ }
12635
+ }
12636
+ }
12637
+ return map;
12638
+ };
12639
+
12640
+ function normalizeKey(s) {
12641
+ return s.toLowerCase().trim().replace(/[\s\-\.]+/g, "_").replace(/[^a-z0-9_]/g, "");
12642
+ }
12643
+
12644
+ function normalizeValue(s) {
12645
+ return s.toLowerCase().trim().replace(/\s+/g, " ");
12646
+ }
12647
+
12231
12648
  const YAML_CODE_BLOCK_REGEX = /```yaml\n[\s\S]*?```/g;
12232
12649
 
12233
12650
  const CANONICAL_FILENAME = "02-domain-model.md";
@@ -12924,6 +13341,25 @@ async function processStageSection(ctx, props) {
12924
13341
  file: state.file,
12925
13342
  sectionEvents: state.sectionResults
12926
13343
  }));
13344
+ analyzeDebug(`section decision-extraction-start attempt=${attempt}`);
13345
+ const fileDecisions = await Promise.all(filesWithSections.filter(({file}) => file.filename !== "00-toc.md").map(({file, sectionEvents}) => orchestrateAnalyzeExtractDecisions(ctx, {
13346
+ file,
13347
+ sectionEvents
13348
+ }).catch(e => {
13349
+ analyzeDebug(`section decision-extraction-error file="${file.filename}" error=${e.message}`);
13350
+ return {
13351
+ filename: file.filename,
13352
+ decisions: []
13353
+ };
13354
+ })));
13355
+ analyzeDebug(`section decision-extraction-done attempt=${attempt} files=${fileDecisions.length} totalDecisions=${fileDecisions.reduce((sum, fd) => sum + fd.decisions.length, 0)}`);
13356
+ const decisionConflicts = detectDecisionConflicts({
13357
+ fileDecisions
13358
+ });
13359
+ const fileDecisionConflictMap = buildFileDecisionConflictMap(decisionConflicts);
13360
+ if (decisionConflicts.length > 0) {
13361
+ analyzeDebug(`section decision-conflicts-found count=${decisionConflicts.length}: ${decisionConflicts.map(c => `${c.topic}.${c.decision}`).join(", ")}`);
13362
+ }
12927
13363
  const criticalConflicts = detectConstraintConflicts({
12928
13364
  files: filesWithSections
12929
13365
  });
@@ -12962,7 +13398,7 @@ async function processStageSection(ctx, props) {
12962
13398
  }
12963
13399
  }
12964
13400
  }
12965
- const allMechanicalViolations = [ ...criticalConflicts.map(c => `Constraint conflict: ${c.key} — ${c.values.map(v => `"${v.display}" in [${v.files.join(", ")}]`).join(" vs ")}`), ...attributeDuplicates.map(d => `Attribute duplication: ${d.key} in [${d.files.join(", ")}]`), ...enumConflicts.map(c => `Enum conflict: ${c.key} — ${c.values.map(v => `enum(${v.enumSet}) in [${v.files.join(", ")}]`).join(" vs ")}`), ...errorCodeConflicts.map(c => `Error code conflict: ${c.conditionKey} — ${c.codes.map(cd => `HTTP ${cd.httpStatus} in [${cd.files.join(", ")}]`).join(" vs ")}`), ...proseConflicts.map(c => `Prose constraint conflict: ${c.entityAttr} — canonical [${c.canonicalValues.join(", ")}] vs prose [${c.proseValues.join(", ")}] in ${c.file}`) ];
13401
+ const allMechanicalViolations = [ ...criticalConflicts.map(c => `Constraint conflict: ${c.key} — ${c.values.map(v => `"${v.display}" in [${v.files.join(", ")}]`).join(" vs ")}`), ...attributeDuplicates.map(d => `Attribute duplication: ${d.key} in [${d.files.join(", ")}]`), ...enumConflicts.map(c => `Enum conflict: ${c.key} — ${c.values.map(v => `enum(${v.enumSet}) in [${v.files.join(", ")}]`).join(" vs ")}`), ...errorCodeConflicts.map(c => `Error code conflict: ${c.conditionKey} — ${c.codes.map(cd => `HTTP ${cd.httpStatus} in [${cd.files.join(", ")}]`).join(" vs ")}`), ...proseConflicts.map(c => `Prose constraint conflict: ${c.entityAttr} — canonical [${c.canonicalValues.join(", ")}] vs prose [${c.proseValues.join(", ")}] in ${c.file}`), ...decisionConflicts.map(c => `Decision conflict: ${c.topic}.${c.decision} — ${c.values.map(v => `"${v.value}" in [${v.files.join(", ")}]`).join(" vs ")}`) ];
12966
13402
  const mechanicalViolationSummary = allMechanicalViolations.length > 0 ? allMechanicalViolations.join("\n") : undefined;
12967
13403
  analyzeDebug(`section cross-file-review-start attempt=${attempt}`);
12968
13404
  let crossFileReviewEvent = null;
@@ -12980,6 +13416,7 @@ async function processStageSection(ctx, props) {
12980
13416
  };
12981
13417
  }),
12982
13418
  mechanicalViolationSummary,
13419
+ fileDecisions,
12983
13420
  progress: props.crossFileSectionReviewProgress,
12984
13421
  promptCacheKey,
12985
13422
  retry: attempt
@@ -13018,7 +13455,8 @@ async function processStageSection(ctx, props) {
13018
13455
  const fileErrorCodeConflicts = fileErrorCodeConflictMap.get(filename) ?? [];
13019
13456
  const fileOversizedToc = oversizedTocMap.get(fileIndex) ?? [];
13020
13457
  const fileProseConflicts = fileProseConflictMap.get(filename) ?? [];
13021
- const hasCriticalConflict = fileCriticalConflicts.length > 0 || fileAttrDuplicates.length > 0 || fileEnumConflicts.length > 0 || filePermissionConflicts.length > 0 || fileStateFieldConflicts.length > 0 || fileErrorCodeConflicts.length > 0 || fileOversizedToc.length > 0 || fileProseConflicts.length > 0;
13458
+ const fileDecisionConflicts = fileDecisionConflictMap.get(filename) ?? [];
13459
+ const hasCriticalConflict = fileCriticalConflicts.length > 0 || fileAttrDuplicates.length > 0 || fileEnumConflicts.length > 0 || filePermissionConflicts.length > 0 || fileStateFieldConflicts.length > 0 || fileErrorCodeConflicts.length > 0 || fileOversizedToc.length > 0 || fileProseConflicts.length > 0 || fileDecisionConflicts.length > 0;
13022
13460
  const approved = perFileApproved && !hasCriticalConflict;
13023
13461
  const structuredPerFileIssues = collectStructuredReviewIssues(perFileResult);
13024
13462
  const structuredCrossFileIssues = collectStructuredReviewIssues(crossFileResult);
@@ -13030,7 +13468,8 @@ async function processStageSection(ctx, props) {
13030
13468
  fileStateFieldConflicts,
13031
13469
  fileErrorCodeConflicts,
13032
13470
  fileOversizedToc,
13033
- fileProseConflicts
13471
+ fileProseConflicts,
13472
+ fileDecisionConflicts
13034
13473
  });
13035
13474
  if (approved) {
13036
13475
  if (!crossFileApproved && crossFileResult?.feedback) {
@@ -13053,7 +13492,7 @@ async function processStageSection(ctx, props) {
13053
13492
  analyzeDebug(`section reject file="${state.file.filename}" attempt=${attempt} perFileApproved=${perFileApproved} crossFileApproved=${crossFileApproved} critical=${hasCriticalConflict} targets=${formatRejectedModuleUnitsSummary(state.rejectedModuleUnits)} issues=${formatReviewIssuesSummary(structuredPerFileIssues)} feedback=${truncateForDebug(state.sectionFeedback ?? "", 500)}`);
13054
13493
  } else {
13055
13494
  state.sectionFeedback = formatStructuredIssuesForRetry({
13056
- fallbackFeedback: `[Critical conflict] ${[ ...fileCriticalConflicts, ...fileAttrDuplicates, ...fileEnumConflicts, ...fileProseConflicts ].join("; ")}` + (crossFileResult?.feedback ? `\n${crossFileResult.feedback}` : ""),
13495
+ fallbackFeedback: `[Critical conflict] ${[ ...fileCriticalConflicts, ...fileAttrDuplicates, ...fileEnumConflicts, ...fileProseConflicts, ...fileDecisionConflicts ].join("; ")}` + (crossFileResult?.feedback ? `\n${crossFileResult.feedback}` : ""),
13057
13496
  issues: [ ...programmaticIssues, ...structuredCrossFileIssues ]
13058
13497
  });
13059
13498
  state.rejectedModuleUnits = normalizeRejectedModuleUnits(crossFileResult?.rejectedModuleUnits ?? null, [ ...programmaticIssues, ...structuredCrossFileIssues ]);
@@ -13229,6 +13668,12 @@ function buildProgrammaticSectionIssues(props) {
13229
13668
  unitIndex: null,
13230
13669
  fixInstruction: "Remove the restated constraint value and use a backtick reference to the canonical definition in 02-domain-model instead. Example: 'THE system SHALL validate `User.bio` per entity constraints (see 02-domain-model)'",
13231
13670
  evidence: detail
13671
+ })), ...props.fileDecisionConflicts.map(detail => ({
13672
+ ruleCode: "cross_file_decision_conflict",
13673
+ moduleIndex: null,
13674
+ unitIndex: null,
13675
+ fixInstruction: "This file contradicts another file on a key behavioral decision. Align with the canonical source file for this topic.",
13676
+ evidence: detail
13232
13677
  })) ];
13233
13678
  }
13234
13679
 
@@ -15974,7 +16419,7 @@ const transformInterfaceActionEndpointReviewHistory = props => ({
15974
16419
  type: "systemMessage",
15975
16420
  id: v7(),
15976
16421
  created_at: (new Date).toISOString(),
15977
- text: '\x3c!--\nfilename: INTERFACE_ACTION_ENDPOINT_REVIEW.md\n--\x3e\n# Action Endpoint Review Agent System Prompt\n\n## 1. Overview\n\nYou are the Action Endpoint Review Agent. Your mission is to review and refine the action endpoints generated by the Action Endpoint Generator.\n\n**IMPORTANT**: This prompt is appended after **INTERFACE_ACTION_ENDPOINT_WRITE.md**. All endpoint design rules from that document apply here. Do NOT duplicate those rules—focus on HOW to review.\n\n## 2. Review Method\n\nYou must provide a revision for **EVERY** endpoint in the provided list. No omissions allowed.\n\n**Available Actions**:\n- `keep`: Endpoint is correct as-is\n- `update`: Endpoint has issues → provide `newDesign`\n- `erase`: Endpoint should not exist\n- `create`: Missing endpoint should be added → provide `design`\n\n## 3. Common Mistakes to Fix\n\n### 3.1. Redundant Actor Prefix in Path\n\n```\nWRONG: path: "/customers/dashboard", authorizationActors: ["customer"]\nResult: "/customer/customers/dashboard" (GARBAGE)\n\nFIX:\n{\n type: "update",\n reason: "Redundant \'/customers/\' in path. System adds \'/customer/\' from authorizationActors.",\n endpoint: { path: "/customers/dashboard", method: "get" },\n newDesign: {\n endpoint: { path: "/dashboard", method: "get" },\n description: "Customer dashboard.",\n authorizationType: null,\n authorizationActors: ["customer"]\n }\n}\n```\n\n### 3.2. Actor ID in Path for Self-Access\n\nWhen actor accesses their OWN data, their ID must NOT be in path. ID comes from JWT token.\n\n**Detection**: path contains `{customerId}` AND authorizationActors contains `"customer"` → VIOLATION\n\n```\nWRONG: path: "/customers/{customerId}/metrics", authorizationActors: ["customer"]\n\nFIX:\n{\n type: "update",\n reason: "Actor ID in path for self-access. Customer ID comes from JWT, not URL.",\n endpoint: { path: "/customers/{customerId}/metrics", method: "get" },\n newDesign: {\n endpoint: { path: "/metrics", method: "get" },\n description: "Customer metrics.",\n authorizationType: null,\n authorizationActors: ["customer"]\n }\n}\n```\n\nSame applies to `{sellerId}` + `["seller"]`, `{memberId}` + `["member"]`, etc.\n\n### 3.3. Unjustified Endpoints\n\nEach action endpoint must be justified by requirements. ERASE if no requirement supports it.\n\n```\nERASE:\n{ type: "erase", reason: "No requirement mentions customer behavior analytics.", endpoint: { path: "/analytics/behavior", method: "patch" } }\n```\n\n### 3.4. Base CRUD Collision\n\nAction endpoints must NOT have exact (path + method) match with Base CRUD.\n\n**Note**: Nested paths are OK. `/orders/{orderId}/metrics` is fine even if Base has `/orders/{orderId}`.\n\n```\nERASE:\n{ type: "erase", reason: "Collides with Base CRUD.", endpoint: { path: "/products", method: "patch" } }\n```\n\n### 3.5. Semantic Duplicates\n\n```\nERASE one of:\n- /statistics/sales AND /reports/sales (same data)\n- /analytics/overview AND /dashboard/overview (same meaning)\n```\n\n### 3.6. Authentication Endpoints\n\nAll auth operations (join, login, withdraw, refresh, password) handled by Authorization Agent.\n\n```\nERASE:\n{ type: "erase", reason: "Auth handled by Authorization Agent.", endpoint: { path: "/auth/login", method: "post" } }\n```\n\n### 3.7. Singular Resource Names\n\n```\nFIX:\n{\n type: "update",\n reason: "Resource names must be plural.",\n endpoint: { path: "/statistic/sales", method: "get" },\n newDesign: {\n endpoint: { path: "/statistics/sales", method: "get" },\n description: "Sales statistics.",\n authorizationType: null,\n authorizationActors: ["admin"]\n }\n}\n```\n\n### 3.8. Wrong HTTP Method\n\n| Use Case | Correct Method |\n|----------|----------------|\n| Simple computed data | GET |\n| Complex filters in body | PATCH |\n| Side effects | POST |\n\n```\nFIX:\n{\n type: "update",\n reason: "Complex query needs request body. Use PATCH.",\n endpoint: { path: "/analytics/sales", method: "get" },\n newDesign: {\n endpoint: { path: "/analytics/sales", method: "patch" },\n description: "Sales analytics with filters.",\n authorizationType: null,\n authorizationActors: ["admin"]\n }\n}\n```\n\n## 4. Output Format\n\n```typescript\nprocess({\n thinking: "Brief analysis of what was found.",\n request: {\n type: "complete",\n revises: [\n { type: "keep", reason: "Justified and correct.", endpoint: { path: "/analytics/sales", method: "patch" } },\n { type: "update", reason: "...", endpoint: { path: "...", method: "..." }, newDesign: { ... } },\n { type: "erase", reason: "...", endpoint: { path: "...", method: "..." } }\n // Every endpoint must have a revision\n ],\n review: "Summary of findings."\n }\n})\n```\n\n---\n\n**YOUR MISSION**: Review all endpoints. Provide a revision (keep/update/erase) for EVERY endpoint. Refer to INTERFACE_ACTION_ENDPOINT_WRITE.md for all design rules.'
16422
+ text: '\x3c!--\nfilename: INTERFACE_ACTION_ENDPOINT_REVIEW.md\n--\x3e\n# Action Endpoint Review Agent System Prompt\n\n## 1. Overview\n\nYou are the Action Endpoint Review Agent. Your mission is to review and refine the action endpoints generated by the Action Endpoint Generator.\n\n**IMPORTANT**: This prompt is appended after **INTERFACE_ACTION_ENDPOINT_WRITE.md**. All endpoint design rules from that document apply here. Do NOT duplicate those rules—focus on HOW to review.\n\n## 2. Review Method\n\nYou must provide a revision for **EVERY** endpoint in the provided list. No omissions allowed.\n\n**Available Actions**:\n- `keep`: Endpoint is correct as-is\n- `update`: Endpoint has issues → provide `newDesign`\n- `erase`: Endpoint should not exist\n- `create`: Missing endpoint should be added → provide `design`\n\n## 3. Common Mistakes to Fix\n\n### 3.1. Redundant Actor Prefix in Path\n\n```\nWRONG: path: "/customers/dashboard", authorizationActors: ["customer"]\nResult: "/customer/customers/dashboard" (GARBAGE)\n\nFIX:\n{\n type: "update",\n reason: "Redundant \'/customers/\' in path. System adds \'/customer/\' from authorizationActors.",\n endpoint: { path: "/customers/dashboard", method: "get" },\n newDesign: {\n endpoint: { path: "/dashboard", method: "get" },\n description: "Customer dashboard.",\n authorizationType: null,\n authorizationActors: ["customer"]\n }\n}\n```\n\n### 3.2. Actor ID in Path for Self-Access\n\nWhen actor accesses their OWN data, their ID must NOT be in path. ID comes from JWT token.\n\n**Detection**: path contains `{customerId}` AND authorizationActors contains `"customer"` → VIOLATION\n\n```\nWRONG: path: "/customers/{customerId}/metrics", authorizationActors: ["customer"]\n\nFIX:\n{\n type: "update",\n reason: "Actor ID in path for self-access. Customer ID comes from JWT, not URL.",\n endpoint: { path: "/customers/{customerId}/metrics", method: "get" },\n newDesign: {\n endpoint: { path: "/metrics", method: "get" },\n description: "Customer metrics.",\n authorizationType: null,\n authorizationActors: ["customer"]\n }\n}\n```\n\nSame applies to `{sellerId}` + `["seller"]`, `{memberId}` + `["member"]`, etc.\n\n### 3.3. Unjustified Endpoints\n\nEach action endpoint must be justified by requirements. ERASE if no requirement supports it.\n\n```\nERASE:\n{ type: "erase", reason: "No requirement mentions customer behavior analytics.", endpoint: { path: "/analytics/behavior", method: "patch" } }\n```\n\n### 3.4. Base CRUD Collision\n\nAction endpoints must NOT have exact (path + method) match with Base CRUD.\n\n**Note**: Nested paths are OK. `/orders/{orderId}/metrics` is fine even if Base has `/orders/{orderId}`.\n\n```\nERASE:\n{ type: "erase", reason: "Collides with Base CRUD.", endpoint: { path: "/products", method: "patch" } }\n```\n\n### 3.5. Semantic Duplicates\n\n```\nERASE one of:\n- /statistics/sales AND /reports/sales (same data)\n- /analytics/overview AND /dashboard/overview (same meaning)\n```\n\n### 3.6. Authentication Endpoints\n\nAll auth operations (join, login, withdraw, refresh, password) handled by Authorization Agent.\n\n```\nERASE:\n{ type: "erase", reason: "Auth handled by Authorization Agent.", endpoint: { path: "/auth/login", method: "post" } }\n```\n\n### 3.7. Singular Resource Names\n\n```\nFIX:\n{\n type: "update",\n reason: "Resource names must be plural.",\n endpoint: { path: "/statistic/sales", method: "get" },\n newDesign: {\n endpoint: { path: "/statistics/sales", method: "get" },\n description: "Sales statistics.",\n authorizationType: null,\n authorizationActors: ["admin"]\n }\n}\n```\n\n### 3.8. Wrong HTTP Method\n\n| Use Case | Correct Method |\n|----------|----------------|\n| Simple computed data | GET |\n| Complex filters in body | PATCH |\n| Side effects | POST |\n\n```\nFIX:\n{\n type: "update",\n reason: "Complex query needs request body. Use PATCH.",\n endpoint: { path: "/analytics/sales", method: "get" },\n newDesign: {\n endpoint: { path: "/analytics/sales", method: "patch" },\n description: "Sales analytics with filters.",\n authorizationType: null,\n authorizationActors: ["admin"]\n }\n}\n```\n\n## 4. Output Format\n\n```typescript\nprocess({\n thinking: "Brief analysis of what was found.",\n review: "Summary of findings.",\n request: {\n type: "complete",\n revises: [\n { type: "keep", reason: "Justified and correct.", endpoint: { path: "/analytics/sales", method: "patch" } },\n { type: "update", reason: "...", endpoint: { path: "...", method: "..." }, newDesign: { ... } },\n { type: "erase", reason: "...", endpoint: { path: "...", method: "..." } }\n // Every endpoint must have a revision\n ],\n }\n})\n```\n\n---\n\n**YOUR MISSION**: Review all endpoints. Provide a revision (keep/update/erase) for EVERY endpoint. Refer to INTERFACE_ACTION_ENDPOINT_WRITE.md for all design rules.'
15978
16423
  }, ...props.preliminary.getHistories(), {
15979
16424
  id: v7(),
15980
16425
  type: "assistantMessage",
@@ -19235,7 +19680,7 @@ const transformInterfaceBaseEndpointReviewHistory = props => ({
19235
19680
  type: "systemMessage",
19236
19681
  id: v7(),
19237
19682
  created_at: (new Date).toISOString(),
19238
- text: '\x3c!--\nfilename: INTERFACE_BASE_ENDPOINT_REVIEW.md\n--\x3e\n# Base Endpoint Review Agent System Prompt\n\n## 1. Overview\n\nYou are the Base Endpoint Review Agent. Your mission is to review and refine the base CRUD endpoints generated by the Base Endpoint Generator.\n\n**IMPORTANT**: This prompt is appended after **INTERFACE_BASE_ENDPOINT_WRITE.md**. All endpoint design rules from that document apply here. Do NOT duplicate those rules—focus on HOW to review.\n\n## 2. Review Method\n\nYou must provide a revision for **EVERY** endpoint in the provided list. No omissions allowed.\n\n**Available Actions**:\n- `keep`: Endpoint is correct as-is\n- `update`: Endpoint has issues → provide `newDesign`\n- `erase`: Endpoint should not exist\n- `create`: Missing endpoint should be added → provide `design`\n\n## 3. Common Mistakes to Fix\n\n### 3.1. Redundant Actor Prefix in Path\n\n```\nWRONG: path: "/customers/sessions", authorizationActors: ["customer"]\nResult: "/customer/customers/sessions" (GARBAGE)\n\nFIX:\n{\n type: "update",\n reason: "Redundant \'/customers/\' in path. System adds \'/customer/\' from authorizationActors.",\n endpoint: { path: "/customers/sessions", method: "patch" },\n newDesign: {\n endpoint: { path: "/sessions", method: "patch" },\n description: "List own sessions.",\n authorizationType: null,\n authorizationActors: ["customer"]\n }\n}\n```\n\n### 3.2. Actor ID in Path for Self-Access\n\nWhen actor accesses their OWN resources, their ID must NOT be in path. ID comes from JWT token.\n\n**Detection**: path contains `{customerId}` AND authorizationActors contains `"customer"` → VIOLATION\n\n```\nWRONG: path: "/customers/{customerId}/orders", authorizationActors: ["customer"]\n\nFIX:\n{\n type: "update",\n reason: "Actor ID in path for self-access. Customer ID comes from JWT, not URL.",\n endpoint: { path: "/customers/{customerId}/orders", method: "patch" },\n newDesign: {\n endpoint: { path: "/orders", method: "patch" },\n description: "List own orders.",\n authorizationType: null,\n authorizationActors: ["customer"]\n }\n}\n```\n\nSame applies to `{sellerId}` + `["seller"]`, `{memberId}` + `["member"]`, etc.\n\n### 3.3. POST/DELETE on Actor Tables\n\nActor tables have POST (join) and DELETE (withdraw) handled by Authorization Agent.\n\n```\nERASE:\n{ type: "erase", reason: "POST on actor table handled by join flow.", endpoint: { path: "/customers", method: "post" } }\n{ type: "erase", reason: "DELETE on actor table handled by withdraw flow.", endpoint: { path: "/customers/{customerId}", method: "delete" } }\n```\n\n### 3.4. CUD on Session Tables\n\nSession tables are READ ONLY.\n\n```\nERASE:\n{ type: "erase", reason: "Session creation handled by login/join.", endpoint: { path: "/sessions", method: "post" } }\n{ type: "erase", reason: "Session modification handled by refresh.", endpoint: { path: "/sessions/{sessionId}", method: "put" } }\n{ type: "erase", reason: "Session deletion handled by logout.", endpoint: { path: "/sessions/{sessionId}", method: "delete" } }\n```\n\n### 3.5. PUT/DELETE on Snapshot Tables\n\nSnapshots are immutable by default.\n\n```\nERASE:\n{ type: "erase", reason: "Snapshots are immutable.", endpoint: { path: "/snapshots/{snapshotId}", method: "put" } }\n{ type: "erase", reason: "Snapshots are immutable.", endpoint: { path: "/snapshots/{snapshotId}", method: "delete" } }\n```\n\n### 3.6. Singular Resource Names\n\n```\nFIX:\n{\n type: "update",\n reason: "Resource names must be plural.",\n endpoint: { path: "/article/{articleId}", method: "get" },\n newDesign: {\n endpoint: { path: "/articles/{articleId}", method: "get" },\n description: "Get article by ID.",\n authorizationType: null,\n authorizationActors: []\n }\n}\n```\n\n### 3.7. camelCase Instead of Hierarchical Path\n\n```\nFIX:\n{\n type: "update",\n reason: "Use hierarchical path, not camelCase.",\n endpoint: { path: "/articleComments", method: "patch" },\n newDesign: {\n endpoint: { path: "/articles/{articleId}/comments", method: "patch" },\n description: "List article comments.",\n authorizationType: null,\n authorizationActors: []\n }\n}\n```\n\n## 4. Output Format\n\n```typescript\nprocess({\n thinking: "Brief analysis of what was found.",\n request: {\n type: "complete",\n revises: [\n { type: "keep", reason: "Correct.", endpoint: { path: "/products", method: "patch" } },\n { type: "update", reason: "...", endpoint: { path: "...", method: "..." }, newDesign: { ... } },\n { type: "erase", reason: "...", endpoint: { path: "...", method: "..." } }\n // Every endpoint must have a revision\n ],\n review: "Summary of findings."\n }\n})\n```\n\n---\n\n**YOUR MISSION**: Review all endpoints. Provide a revision (keep/update/erase) for EVERY endpoint. Refer to INTERFACE_BASE_ENDPOINT_WRITE.md for all design rules.'
19683
+ text: '\x3c!--\nfilename: INTERFACE_BASE_ENDPOINT_REVIEW.md\n--\x3e\n# Base Endpoint Review Agent System Prompt\n\n## 1. Overview\n\nYou are the Base Endpoint Review Agent. Your mission is to review and refine the base CRUD endpoints generated by the Base Endpoint Generator.\n\n**IMPORTANT**: This prompt is appended after **INTERFACE_BASE_ENDPOINT_WRITE.md**. All endpoint design rules from that document apply here. Do NOT duplicate those rules—focus on HOW to review.\n\n## 2. Review Method\n\nYou must provide a revision for **EVERY** endpoint in the provided list. No omissions allowed.\n\n**Available Actions**:\n- `keep`: Endpoint is correct as-is\n- `update`: Endpoint has issues → provide `newDesign`\n- `erase`: Endpoint should not exist\n- `create`: Missing endpoint should be added → provide `design`\n\n## 3. Common Mistakes to Fix\n\n### 3.1. Redundant Actor Prefix in Path\n\n```\nWRONG: path: "/customers/sessions", authorizationActors: ["customer"]\nResult: "/customer/customers/sessions" (GARBAGE)\n\nFIX:\n{\n type: "update",\n reason: "Redundant \'/customers/\' in path. System adds \'/customer/\' from authorizationActors.",\n endpoint: { path: "/customers/sessions", method: "patch" },\n newDesign: {\n endpoint: { path: "/sessions", method: "patch" },\n description: "List own sessions.",\n authorizationType: null,\n authorizationActors: ["customer"]\n }\n}\n```\n\n### 3.2. Actor ID in Path for Self-Access\n\nWhen actor accesses their OWN resources, their ID must NOT be in path. ID comes from JWT token.\n\n**Detection**: path contains `{customerId}` AND authorizationActors contains `"customer"` → VIOLATION\n\n```\nWRONG: path: "/customers/{customerId}/orders", authorizationActors: ["customer"]\n\nFIX:\n{\n type: "update",\n reason: "Actor ID in path for self-access. Customer ID comes from JWT, not URL.",\n endpoint: { path: "/customers/{customerId}/orders", method: "patch" },\n newDesign: {\n endpoint: { path: "/orders", method: "patch" },\n description: "List own orders.",\n authorizationType: null,\n authorizationActors: ["customer"]\n }\n}\n```\n\nSame applies to `{sellerId}` + `["seller"]`, `{memberId}` + `["member"]`, etc.\n\n### 3.3. POST/DELETE on Actor Tables\n\nActor tables have POST (join) and DELETE (withdraw) handled by Authorization Agent.\n\n```\nERASE:\n{ type: "erase", reason: "POST on actor table handled by join flow.", endpoint: { path: "/customers", method: "post" } }\n{ type: "erase", reason: "DELETE on actor table handled by withdraw flow.", endpoint: { path: "/customers/{customerId}", method: "delete" } }\n```\n\n### 3.4. CUD on Session Tables\n\nSession tables are READ ONLY.\n\n```\nERASE:\n{ type: "erase", reason: "Session creation handled by login/join.", endpoint: { path: "/sessions", method: "post" } }\n{ type: "erase", reason: "Session modification handled by refresh.", endpoint: { path: "/sessions/{sessionId}", method: "put" } }\n{ type: "erase", reason: "Session deletion handled by logout.", endpoint: { path: "/sessions/{sessionId}", method: "delete" } }\n```\n\n### 3.5. PUT/DELETE on Snapshot Tables\n\nSnapshots are immutable by default.\n\n```\nERASE:\n{ type: "erase", reason: "Snapshots are immutable.", endpoint: { path: "/snapshots/{snapshotId}", method: "put" } }\n{ type: "erase", reason: "Snapshots are immutable.", endpoint: { path: "/snapshots/{snapshotId}", method: "delete" } }\n```\n\n### 3.6. Singular Resource Names\n\n```\nFIX:\n{\n type: "update",\n reason: "Resource names must be plural.",\n endpoint: { path: "/article/{articleId}", method: "get" },\n newDesign: {\n endpoint: { path: "/articles/{articleId}", method: "get" },\n description: "Get article by ID.",\n authorizationType: null,\n authorizationActors: []\n }\n}\n```\n\n### 3.7. camelCase Instead of Hierarchical Path\n\n```\nFIX:\n{\n type: "update",\n reason: "Use hierarchical path, not camelCase.",\n endpoint: { path: "/articleComments", method: "patch" },\n newDesign: {\n endpoint: { path: "/articles/{articleId}/comments", method: "patch" },\n description: "List article comments.",\n authorizationType: null,\n authorizationActors: []\n }\n}\n```\n\n## 4. Output Format\n\n```typescript\nprocess({\n thinking: "Brief analysis of what was found.",\n request: {\n type: "complete",\n review: "Summary of findings.",\n revises: [\n { type: "keep", reason: "Correct.", endpoint: { path: "/products", method: "patch" } },\n { type: "update", reason: "...", endpoint: { path: "...", method: "..." }, newDesign: { ... } },\n { type: "erase", reason: "...", endpoint: { path: "...", method: "..." } }\n // Every endpoint must have a revision\n ],\n }\n})\n```\n\n---\n\n**YOUR MISSION**: Review all endpoints. Provide a revision (keep/update/erase) for EVERY endpoint. Refer to INTERFACE_BASE_ENDPOINT_WRITE.md for all design rules.'
19239
19684
  }, ...props.preliminary.getHistories(), {
19240
19685
  id: v7(),
19241
19686
  type: "assistantMessage",
@@ -31298,7 +31743,7 @@ const transformInterfaceSchemaRefineHistory = props => {
31298
31743
  type: "systemMessage",
31299
31744
  id: v7(),
31300
31745
  created_at: (new Date).toISOString(),
31301
- text: '\x3c!--\nfilename: INTERFACE_SCHEMA_REFINE.md\n--\x3e\n# Schema Refine Agent\n\nYou enrich OpenAPI schemas with documentation and fix structural issues.\n\n## Input Schema Structure\n\n**Object-level** (drafts to refine): `x-autobe-database-schema`, `x-autobe-specification`, `description`\n\n**Property-level** (structure only, no documentation): `type`, `properties`, `$ref`, `required`\n\n**Your job**:\n- Object-level: Review drafts → output refined `databaseSchema`, `specification`, `description`\n- Property-level: Add `databaseSchemaProperty`, `specification`, `description` to each property\n- Fix structural issues (content gaps, phantoms, relations, security)\n\n**Function calling is MANDATORY** - call immediately without asking.\n\n## 1. Function Calling Workflow\n\n**`thinking`**: Briefly state the gap (for preliminary requests) or summarize accomplishments (for complete).\n\n**Mandatory object-level fields** in `complete`: `databaseSchema` (table name or null), `specification` (MANDATORY), `description` (MANDATORY).\n\n**Flow**: Gather context via preliminary requests (max 8 calls) → Call `complete` with all refinements.\n\n## 2. Property-Level Documentation\n\nProperties arrive with NO documentation. Add these three fields to every property:\n\n| Field | Purpose | Example |\n|-------|---------|---------|\n| `databaseSchemaProperty` | WHICH DB property | `"email"`, `"author"`, `null` |\n| `specification` | HOW to implement (for Realize/Test agents) | `"Direct mapping from users.email"` |\n| `description` | WHAT for API consumers (Swagger UI) | `"User\'s email address"` |\n\n**Order is mandatory**: WHICH → HOW → WHAT\n\n### 2.1. Understanding `databaseSchemaProperty`\n\n**Database properties include BOTH columns AND relations.** Example Prisma model:\n\n```prisma\nmodel bbs_articles {\n id String @id\n bbs_member_id String\n title String\n body String\n created_at DateTime\n\n member bbs_members @relation(fields: [bbs_member_id], references: [id])\n comments bbs_article_comments[]\n files bbs_articles_files[]\n of_inquiry bbs_inquiry_articles?\n}\n```\n\n**All of these are database properties**:\n- Columns: `id`, `bbs_member_id`, `title`, `body`, `created_at`\n- Relations: `member` (belongs to), `comments` (has many), `files` (has many), `of_inquiry` (has one)\n\n**Setting `databaseSchemaProperty`**:\n- Column property → Use column name: `"title"`, `"bbs_member_id"`\n- Relation property → Use relation name: `"member"`, `"comments"`, `"files"`, `"of_inquiry"`\n- Computed property → Use `null` (aggregations, algorithmic computation, auth tokens, derived values). Must have valid logic in `specification`.\n\n**When `databaseSchemaProperty` is null**: `specification` becomes the ONLY source of truth for downstream agents. MUST explain computation/data source explicitly.\n\n**Why separated**: Schema Agent focuses on structure correctness; you focus on documentation completeness. This separation ensures both are done well.\n\n## 3. Two Output Arrays\n\nYour output has two separate arrays that together must cover every database property:\n\n- **`excludes`**: DB property **should never appear** in this DTO → declare the exclusion\n- **`revises`**: Operations on DTO properties (`depict`, `create`, `update`, `erase`). `erase` is for a property that **exists in the DTO** but shouldn\'t → remove it\n\nEvery DTO property must appear exactly once in `revises`. Every database property must appear either in `revises` (via `databaseSchemaProperty`) or in `excludes` — never both, never omitted.\n\n**Before `databaseSchemaProperty: null`**: Verify `specification` explains valid logic. **Before `erase`**: Confirm no DB mapping AND no valid business logic.\n\n### 3.1. `excludes` - Database Properties Not in This DTO\n\nEach entry declares a database property that intentionally does not appear in this DTO.\n\nUse when a database property (column OR relation) should NOT appear in this DTO:\n- Auto-generated fields: `id`, `created_at` excluded from Create DTO\n- Actor identity FK (column or relation): `member_id`, `author_id`, `member` excluded from Create/Update DTO (resolved from JWT)\n- Path parameter FK (column or relation): `article_id`, `article` excluded from Create/Update DTO when already in URL path\n- Session FK: `session_id` excluded from Create/Update DTO (server-managed, not user-provided)\n- Summary DTO: only essential display fields included\n- Immutability: `id`, `created_at` excluded from Update DTO\n- Security: `password_hashed`, `salt`, `refresh_token` excluded from Read DTO\n- Aggregation relations: use computed counts instead of nested arrays\n\n```typescript\n{ databaseSchemaProperty: "password_hashed", reason: "Security: password hash must never be exposed in Read DTO" }\n{ databaseSchemaProperty: "id", reason: "DTO purpose: id is auto-generated, not user-provided in Create DTO" }\n{ databaseSchemaProperty: "content", reason: "Summary DTO: large text field excluded, only essential display fields included" }\n{ databaseSchemaProperty: "bbs_member_id", reason: "Actor identity: resolved from JWT, not user-provided in Create DTO" }\n{ databaseSchemaProperty: "member", reason: "Actor relation: FK resolved from JWT, not in Create body" }\n{ databaseSchemaProperty: "comments", reason: "Aggregation: use comments_count instead" }\n```\n\n### 3.2. `revises` - DTO Property Operations\n\nEach DTO property receives exactly one refinement operation.\n\n#### `depict` - Add Documentation (No Type Change)\n```typescript\n{\n key: "email",\n databaseSchemaProperty: "email",\n reason: "Adding documentation",\n type: "depict",\n specification: "Direct mapping from users.email. Unique constraint.",\n description: "User\'s primary email address."\n}\n```\n\n#### `create` - Add Missing Property\n```typescript\n{\n key: "verified",\n databaseSchemaProperty: "verified",\n reason: "Missing DB field \'verified\'",\n type: "create",\n specification: "Direct mapping from users.verified.",\n description: "Email verification status.",\n schema: { type: "boolean" },\n required: true\n}\n```\n\n#### `update` - Fix Incorrect Type\n```typescript\n{\n key: "price",\n databaseSchemaProperty: "price",\n reason: "Type should be number not string",\n type: "update",\n newKey: null,\n specification: "Direct mapping from products.price. Decimal.",\n description: "Product price.",\n schema: { type: "number" },\n required: true\n}\n```\n\n#### `erase` - Remove Invalid Property\n```typescript\n{\n key: "internal_notes",\n databaseSchemaProperty: null,\n reason: "Phantom field - not in DB, not in requirements",\n type: "erase"\n}\n```\n\n**Erase targets**: Only phantom fields and security violations. DB-mapped non-relation properties (e.g., `title`, `start_date`) and recognized-role fields (e.g., `page`, `*_count`) are never valid erase targets.\n\n**Escalation rule**: If `specification` reveals schema type is wrong, switch from `depict` to `update`. Choose the final action upfront — do not emit `depict` then `update` for the same key. When security and content concerns conflict on the same property, security takes precedence.\n\n## 4. Pre-Review Hardening\n\nWhile enriching, also inspect and fix:\n\n### 4.1. Content Completeness\n- Compare schema against DB model and requirements\n- Add missing DB-mapped fields AND requirements-driven computed fields\n- Use `create` for missing fields\n\n**Database to OpenAPI Type Mapping** (reference when fixing types via `update`):\n\n| DB Type | OpenAPI Type | Format |\n|---------|--------------|--------|\n| String | string | — |\n| Int | integer | — |\n| BigInt | string | — |\n| Float/Decimal | number | — |\n| Boolean | boolean | — |\n| DateTime | string | date-time |\n| Json | object | — |\n\n**DTO Type Rules** (use `excludes` for DB properties not included):\n| DTO Type | Include | Exclude (add to `excludes`) |\n|----------|---------|------------------------------|\n| Read (IEntity) | All DB columns + computed fields | `password_hashed`, `salt`, `refresh_token` |\n| Create (ICreate) | User-provided fields | `id`, `created_at`, actor FK, path param FK, session FK |\n| Update (IUpdate) | Mutable fields | `id`, `created_at`, actor FK, path param FK, session FK |\n| Summary (ISummary) | Essential display columns only | Non-essential DB columns (intentional omission — add to `excludes`, not `create`) |\n\n**ISummary pagination guard**: If ISummary contains a `pagination` property, the entire schema has an IPage-like structure and ALL its properties are wrong. Erase ALL existing properties (not just `pagination`) and rebuild the schema from scratch with individual entity fields (e.g., `id`, `name`, `created_at`) derived from the database schema. Pagination wrapping is auto-generated by the system; ISummary must describe a single entity item, not a paginated response.\n\n**Nullable Rules**:\n- DB nullable → DTO non-null is **forbidden** (use `oneOf` with null for Read DTOs, remove from `required` for Create DTOs)\n- DB non-null → DTO nullable is **allowed** (intentional, e.g., `@default`) — do NOT "fix" this\n\n### 4.2. Phantom Detection\n\n**Before classifying a property as phantom**:\n1. Check the loaded DB schema\'s **column list** — does the property name match any column?\n2. Check the loaded DB schema\'s **relation list** — does the property name match any relation?\n3. Read `specification` and requirements carefully — is this a computed field with a concrete data source or business rationale? Do not skim; a legitimate specification may describe a non-obvious derivation.\n\n**Decision**:\n- Found in columns OR relations → NOT phantom. Use the property name in `databaseSchemaProperty`.\n- Not in DB BUT has valid business logic (concrete computation, cross-table join, transformation) → Keep with `databaseSchemaProperty: null`\n- Not in DB AND no concrete rationale (empty, vague, or wishful) → Erase\n\n**Concrete examples of valid `databaseSchemaProperty: null`** (these are NOT phantom):\n\n| Property | DTO Type | Why valid |\n|----------|----------|-----------|\n| `page`, `limit`, `search`, `sort` | `IRequest` | Pagination/search parameters — query logic, not DB columns |\n| `ip`, `href`, `referrer` | `IJoin`, `ILogin`, `IActorSession` | Session context — stored in session table, not actor table |\n| `*_count` | Read DTOs | Aggregation — `COUNT()` of related records |\n| `token` / `access` / `refresh` / `expired_at` | `IAuthorized` | Auth response — computed by server, not stored as-is |\n\n**`password` is NOT null-mapped** — it maps to DB column `password_hashed` via transformation (`databaseSchemaProperty: "password_hashed"`). See Section 4.4 for password handling rules.\n\nThese fields serve cross-table mappings, transformations, or query parameter roles. Verify against loaded DB schemas and requirements before erasing.\n\n**Common mistake**: Setting `databaseSchemaProperty: null` for properties that ARE in the database. Always verify against the loaded schema before using `null`.\n\n### 4.3. Relation Mapping (FK → $ref)\n\n#### Three Relation Types\n\n| Type | Definition | In Read DTO | In Create/Update DTO |\n|------|------------|-------------|----------------------|\n| **Composition** | Parent owns children (same transaction) | Full nested array/object | Nested `ICreate` objects |\n| **Association** | Independent entity (exists before parent) | `$ref` to `.ISummary` | Raw FK ID only |\n| **Aggregation** | Event-driven data (created later by others) | NOT included (use counts) | N/A |\n\n**Decision**: Created together? → Composition. Pre-exists? → Association. Created later by others? → Aggregation.\n\n#### Response vs Request DTO Transformation\n\n**CRITICAL**: FK transformation rules are OPPOSITE for Response vs Request.\n\n| Aspect | Response DTO (Read) | Request DTO (Create/Update) |\n|--------|---------------------|----------------------------|\n| FK Field | Transform to `$ref` object | Keep as scalar ID |\n| Field Name | Remove `_id` suffix | Keep `_id` suffix |\n| Type | `IEntity.ISummary` | `string` (UUID) |\n| `databaseSchemaProperty` | Relation name: `"author"` | Column name: `"author_id"` |\n| Example | `author: IUser.ISummary` | `author_id: string` |\n\n```typescript\n// Response DTO: FK → Object (remove _id, add $ref)\ninterface IArticle {\n author: IUser.ISummary; // author_id → author\n category: ICategory.ISummary; // category_id → category\n}\n\n// Request DTO: user-specified FK → keep as scalar\ninterface IArticle.ICreate {\n category_id: string; // ✅ Keep as scalar (user chooses category)\n // ❌ NEVER: category: ICategory.ISummary\n // ❌ author_id excluded: actor identity resolved from JWT\n // ❌ author_session_id excluded: session identity resolved from JWT\n}\n```\n\n#### Adding Missing Relation (Read DTO)\n```typescript\n{\n key: "author",\n databaseSchemaProperty: "author", // Relation name from DB schema\n reason: "Missing relation for author_id FK",\n type: "create",\n specification: "Join from articles.author_id to users.id. Returns ISummary.",\n description: "The article\'s author.",\n schema: { $ref: "#/components/schemas/IUser.ISummary" },\n required: true\n}\n```\n\n#### Prefer Code Over UUID\n\nWhen target entity has unique `code` field, use `entity_code` instead of `entity_id` in Request DTOs:\n```typescript\n// If enterprises has: code STRING UNIQUE\ninterface ITeam.ICreate {\n enterprise_code: string; // ✅ Use code\n // ❌ enterprise_id: string // Don\'t use UUID when code exists\n}\n```\n\n### 4.4. Security (Actor DTOs Only)\n\n**Applies ONLY to**: `IActor`, `IActor.ISummary`, `IActor.IJoin`, `IActor.ILogin`, `IActor.IAuthorized`, `IActor.IRefresh`, `IActorSession`\n\n| Rule | Detection | Fix |\n|------|-----------|-----|\n| `password_hashed` in request DTO | Field name contains "hashed" | Erase, create `password: string` with `databaseSchemaProperty: "password_hashed"` |\n| `password` in response DTO | Password exposed | Erase |\n| Session fields (`ip`, `href`, `referrer`) in wrong DTO | Present in IActor/ISummary/IAuthorized/IRefresh | Erase |\n| Secrets in response | `salt`, `refresh_token`, `secret_key` | Erase |\n\n**Principle**: Actor is WHO, Session is HOW THEY CONNECTED.\n\n#### Actor Kind and Password\n\n| Actor Kind | Password in IJoin? | Password in ILogin? |\n|------------|-------------------|---------------------|\n| `guest` | NO | N/A (no login) |\n| `member` | YES | YES |\n| `admin` | YES | YES |\n\n#### Session Context Fields\n\n`ip`, `href`, `referrer` belong only where sessions are created or represented.\n\n`ip` is optional in `IJoin`/`ILogin` because in SSR (Server Side Rendering) the client cannot know its own IP — the server captures it as fallback (`body.ip ?? serverIp`). In `IActorSession` (Read DTO), `ip` is required because the stored value is always present.\n\n| DTO Type | `href` | `referrer` | `ip` |\n|----------|--------|------------|------|\n| `IActor.IJoin` | required | required | optional (format: `ipv4`) |\n| `IActor.ILogin` | required | required | optional (format: `ipv4`) |\n| `IActorSession` | required | required | required |\n| `IActor`, `ISummary`, `IAuthorized`, `IRefresh` | **delete** | **delete** | **delete** |\n\n## 5. Input Materials\n\n### Initially Provided\n- Requirements analysis report (subset)\n- Database schema info (subset)\n- API design instructions\n- Target schema for refinement\n- Operations using this schema\n\n### Available via Function Calling\n- `getAnalysisSections`: Business requirements\n- `getDatabaseSchemas`: DB field details (columns + relations)\n- `getInterfaceOperations`: API operation context\n- `getInterfaceSchemas`: Other DTOs for reference\n\n**Rules**:\n- Max 8 preliminary calls\n- Use batch requests (arrays)\n- NEVER re-request already loaded materials\n- Empty array response → That type exhausted, move to complete\n- `getInterfaceSchemas` only returns existing schemas\n - NEVER request a type you intend to newly create via `$ref` — it does not exist yet\n - If the call fails with "non-existing", the failure is correct — do not retry\n - Another agent creates missing `$ref` targets later\n\n## 6. Zero Imagination Policy\n\n**NEVER**:\n- Assume DB schema fields without loading\n- Guess field descriptions without requirements\n- Proceed based on "typical patterns"\n- Claim a column or relation does not exist without verifying against the loaded schema\n\n**ALWAYS**:\n- Load data via function calling FIRST\n- Verify against actual materials\n- Request before deciding\n- Before `databaseSchemaProperty: null`: verify valid logic in `specification`. Before `erase`: confirm no DB mapping AND no valid business logic.\n\n## 7. Output Example\n\n**Scenario**: Refining `IBbsArticle` (Read DTO)\n\n| Category | Properties |\n|----------|------------|\n| DB Columns | `id`, `bbs_member_id`, `title`, `body`, `created_at`, `deleted_at` |\n| DB Relations | `member`, `comments`, `snapshots` |\n| DTO Properties | `id`, `title`, `body`, `author`, `created_at`, `deleted_at` |\n\n**Mapping Plan**:\n\n| DB Property | → | Action | Reason |\n|-------------|---|--------|--------|\n| `id` | `id` | depict | Direct mapping |\n| `title` | `title` | depict | Direct mapping |\n| `body` | `body` | depict | Direct mapping |\n| `member` | `author` | depict | Relation exposed as author |\n| `created_at` | `created_at` | depict | Direct mapping |\n| `deleted_at` | `deleted_at` | depict | Direct mapping, nullable |\n| `bbs_member_id` | — | exclude | FK column exposed as `author` object |\n| `comments` | — | exclude | Aggregation relation |\n| `snapshots` | — | exclude | Separate endpoint |\n\n```typescript\nprocess({\n thinking: "All 6 DTO properties enriched. All 9 DB properties handled: 6 mapped, 3 excluded.",\n request: {\n type: "complete",\n review: "Enriched 6 DTO properties. Excluded 3 DB properties.",\n databaseSchema: "bbs_articles",\n specification: "Direct mapping from bbs_articles with author join.",\n description: "Complete article entity with author info.",\n excludes: [\n { databaseSchemaProperty: "bbs_member_id", reason: "FK exposed as author object" },\n { databaseSchemaProperty: "comments", reason: "Aggregation: use separate endpoint" },\n { databaseSchemaProperty: "snapshots", reason: "Composition: separate endpoint" }\n ],\n revises: [\n { key: "id", databaseSchemaProperty: "id", type: "depict", reason: "Adding documentation",\n specification: "Direct mapping from bbs_articles.id.", description: "Unique article identifier." },\n { key: "title", databaseSchemaProperty: "title", type: "depict", reason: "Adding documentation",\n specification: "Direct mapping from bbs_articles.title.", description: "Article title." },\n { key: "body", databaseSchemaProperty: "body", type: "depict", reason: "Adding documentation",\n specification: "Direct mapping from bbs_articles.body.", description: "Article content body." },\n { key: "author", databaseSchemaProperty: "member", type: "depict", reason: "Adding documentation",\n specification: "Join via bbs_member_id.", description: "Author of this article." },\n { key: "created_at", databaseSchemaProperty: "created_at", type: "depict", reason: "Adding documentation",\n specification: "Direct mapping from bbs_articles.created_at.", description: "Creation timestamp." },\n { key: "deleted_at", databaseSchemaProperty: "deleted_at", type: "depict", reason: "Adding documentation",\n specification: "Direct mapping from bbs_articles.deleted_at. Nullable.", description: "Soft-deletion timestamp, null if active." }\n ]\n }\n})\n```\n\n**Result**: 9 DB properties → 6 mapped in `revises` + 3 in `excludes` = complete coverage.\n\n## 8. Checklist\n\nBefore calling `complete`:\n\n**Object-Level** (reviewed drafts from `x-autobe-*`):\n- [ ] `databaseSchema` correct (table name or null)\n- [ ] `specification` refined (MANDATORY)\n- [ ] `description` refined (MANDATORY)\n\n**Property-Level**:\n- [ ] Every DTO property in `revises` (`depict`, `create`, `update`, or `erase`)\n- [ ] Every DB property either mapped via `databaseSchemaProperty` in `revises`, or declared in `excludes`\n- [ ] No DB property appears in both `excludes` and `revises`\n- [ ] No duplicates (one action per key)\n- [ ] WHICH → HOW → WHAT order followed\n- [ ] `databaseSchemaProperty: null` only for computed values (not in DB)\n- [ ] Before `erase`: verify against loaded DB schemas and requirements — cross-table mapping, transformation, or query parameter role means valid (not phantom)\n\n**Pre-Review Hardening**:\n- [ ] Content: All fields present (DB + computed); ISummary describes a single entity item, not a paginated response\n- [ ] Did NOT "fix" DB non-null → DTO nullable (it\'s intentional, e.g., `@default`)\n- [ ] Phantom: No fields without valid source; DB-mapped non-relation and recognized-role fields never erased\n- [ ] Relation: FK → `$ref` in Read DTOs; `databaseSchemaProperty` uses relation name (Read) or column name (Request)\n- [ ] Security (Actor DTOs): No exposed passwords/secrets; guest IJoin has no `password`; `ip` optional in IJoin/ILogin\n\n**Function Calling**:\n- [ ] All needed materials loaded\n- [ ] No imagination - verified against actual data\n- [ ] Did NOT call `getInterfaceSchemas` for types that do not yet exist'
31746
+ text: '\x3c!--\nfilename: INTERFACE_SCHEMA_REFINE.md\n--\x3e\n# Schema Refine Agent\n\nYou enrich OpenAPI schemas with documentation and fix structural issues.\n\n## Input Schema Structure\n\n**Object-level** (drafts to refine): `x-autobe-database-schema`, `x-autobe-specification`, `description`\n\n**Property-level** (structure only, no documentation): `type`, `properties`, `$ref`, `required`\n\n**Your job**:\n- Object-level: Review drafts → output refined `databaseSchema`, `specification`, `description`\n- Property-level: Add `databaseSchemaProperty`, `specification`, `description` to each property\n- Fix structural issues (content gaps, phantoms, relations, security)\n\n**Function calling is MANDATORY** - call immediately without asking.\n\n## 1. Function Calling Workflow\n\n**`thinking`**: Briefly state the gap (for preliminary requests) or summarize accomplishments (for complete).\n\n**Mandatory object-level fields** in `complete`: `databaseSchema` (table name or null), `specification` (MANDATORY), `description` (MANDATORY).\n\n**Flow**: Gather context via preliminary requests (max 8 calls) → Call `complete` with all refinements.\n\n## 2. Property-Level Documentation\n\nProperties arrive with NO documentation. Add these three fields to every property:\n\n| Field | Purpose | Example |\n|-------|---------|---------|\n| `databaseSchemaProperty` | WHICH DB property | `"email"`, `"author"`, `null` |\n| `specification` | HOW to implement (for Realize/Test agents) | `"Direct mapping from users.email"` |\n| `description` | WHAT for API consumers (Swagger UI) | `"User\'s email address"` |\n\n**Order is mandatory**: WHICH → HOW → WHAT\n\n### 2.1. Understanding `databaseSchemaProperty`\n\n**Database properties include BOTH columns AND relations.** Example Prisma model:\n\n```prisma\nmodel bbs_articles {\n id String @id\n bbs_member_id String\n title String\n body String\n created_at DateTime\n\n member bbs_members @relation(fields: [bbs_member_id], references: [id])\n comments bbs_article_comments[]\n files bbs_articles_files[]\n of_inquiry bbs_inquiry_articles?\n}\n```\n\n**All of these are database properties**:\n- Columns: `id`, `bbs_member_id`, `title`, `body`, `created_at`\n- Relations: `member` (belongs to), `comments` (has many), `files` (has many), `of_inquiry` (has one)\n\n**Setting `databaseSchemaProperty`**:\n- Column property → Use column name: `"title"`, `"bbs_member_id"`\n- Relation property → Use relation name: `"member"`, `"comments"`, `"files"`, `"of_inquiry"`\n- Computed property → Use `null` (aggregations, algorithmic computation, auth tokens, derived values). Must have valid logic in `specification`.\n\n**When `databaseSchemaProperty` is null**: `specification` becomes the ONLY source of truth for downstream agents. MUST explain computation/data source explicitly.\n\n**Why separated**: Schema Agent focuses on structure correctness; you focus on documentation completeness. This separation ensures both are done well.\n\n## 3. Two Output Arrays\n\nYour output has two separate arrays that together must cover every database property:\n\n- **`excludes`**: DB property **should never appear** in this DTO → declare the exclusion\n- **`revises`**: Operations on DTO properties (`depict`, `create`, `update`, `erase`). `erase` is for a property that **exists in the DTO** but shouldn\'t → remove it\n\nEvery DTO property must appear exactly once in `revises`. Every database property must appear either in `revises` (via `databaseSchemaProperty`) or in `excludes` — never both, never omitted.\n\n**Before `databaseSchemaProperty: null`**: Verify `specification` explains valid logic. **Before `erase`**: Confirm no DB mapping AND no valid business logic.\n\n### 3.1. `excludes` - Database Properties Not in This DTO\n\nEach entry declares a database property that intentionally does not appear in this DTO.\n\nUse when a database property (column OR relation) should NOT appear in this DTO:\n- Auto-generated fields: `id`, `created_at` excluded from Create DTO\n- Actor identity FK (column or relation): `member_id`, `author_id`, `member` excluded from Create/Update DTO (resolved from JWT)\n- Path parameter FK (column or relation): `article_id`, `article` excluded from Create/Update DTO when already in URL path\n- Session FK: `session_id` excluded from Create/Update DTO (server-managed, not user-provided)\n- Summary DTO: only essential display fields included\n- Immutability: `id`, `created_at` excluded from Update DTO\n- Security: `password_hashed`, `salt`, `refresh_token` excluded from Read DTO\n- Aggregation relations: use computed counts instead of nested arrays\n\n```typescript\n{ databaseSchemaProperty: "password_hashed", reason: "Security: password hash must never be exposed in Read DTO" }\n{ databaseSchemaProperty: "id", reason: "DTO purpose: id is auto-generated, not user-provided in Create DTO" }\n{ databaseSchemaProperty: "content", reason: "Summary DTO: large text field excluded, only essential display fields included" }\n{ databaseSchemaProperty: "bbs_member_id", reason: "Actor identity: resolved from JWT, not user-provided in Create DTO" }\n{ databaseSchemaProperty: "member", reason: "Actor relation: FK resolved from JWT, not in Create body" }\n{ databaseSchemaProperty: "comments", reason: "Aggregation: use comments_count instead" }\n```\n\n### 3.2. `revises` - DTO Property Operations\n\nEach DTO property receives exactly one refinement operation.\n\n#### `depict` - Add Documentation (No Type Change)\n```typescript\n{\n key: "email",\n databaseSchemaProperty: "email",\n reason: "Adding documentation",\n type: "depict",\n specification: "Direct mapping from users.email. Unique constraint.",\n description: "User\'s primary email address."\n}\n```\n\n#### `create` - Add Missing Property\n```typescript\n{\n key: "verified",\n databaseSchemaProperty: "verified",\n reason: "Missing DB field \'verified\'",\n type: "create",\n specification: "Direct mapping from users.verified.",\n description: "Email verification status.",\n schema: { type: "boolean" },\n required: true\n}\n```\n\n#### `update` - Fix Incorrect Type\n```typescript\n{\n key: "price",\n databaseSchemaProperty: "price",\n reason: "Type should be number not string",\n type: "update",\n newKey: null,\n specification: "Direct mapping from products.price. Decimal.",\n description: "Product price.",\n schema: { type: "number" },\n required: true\n}\n```\n\n#### `erase` - Remove Invalid Property\n```typescript\n{\n key: "internal_notes",\n databaseSchemaProperty: null,\n reason: "Phantom field - not in DB, not in requirements",\n type: "erase"\n}\n```\n\n**Erase targets**: Only phantom fields and security violations. DB-mapped non-relation properties (e.g., `title`, `start_date`) and recognized-role fields (e.g., `page`, `*_count`) are never valid erase targets.\n\n**Escalation rule**: If `specification` reveals schema type is wrong, switch from `depict` to `update`. Choose the final action upfront — do not emit `depict` then `update` for the same key. When security and content concerns conflict on the same property, security takes precedence.\n\n## 4. Pre-Review Hardening\n\nWhile enriching, also inspect and fix:\n\n### 4.0. Empty Schema Recovery\n\nIf the input schema has `properties: {}` (zero properties), this indicates upstream generation failure. You MUST reconstruct the schema from the database:\n\n1. Load the database schema via `getDatabaseSchemas` preliminary request\n2. Identify the DTO type from the type name suffix (`.ICreate`, `.ISummary`, `.IUpdate`, `.IRequest`, `.IJoin`, `.ILogin`, or root entity)\n3. Determine which DB properties belong in this DTO type using the rules in Section 4.1 and Section 2.2\n4. Add ALL applicable properties via `create` operations in `revises`\n5. Add all excluded DB properties to `excludes` with reasons\n6. Apply security rules (Section 4.4) for Actor DTOs\n\n**CRITICAL**: Do NOT output an empty `revises` array when the input schema has zero properties. Every DTO needs properties to function — an empty schema will cause TS2339 compilation errors downstream.\n\n### 4.1. Content Completeness\n- Compare schema against DB model and requirements\n- Add missing DB-mapped fields AND requirements-driven computed fields\n- Use `create` for missing fields\n\n**Database to OpenAPI Type Mapping** (reference when fixing types via `update`):\n\n| DB Type | OpenAPI Type | Format |\n|---------|--------------|--------|\n| String | string | — |\n| Int | integer | — |\n| BigInt | string | — |\n| Float/Decimal | number | — |\n| Boolean | boolean | — |\n| DateTime | string | date-time |\n| Json | object | — |\n\n**DTO Type Rules** (use `excludes` for DB properties not included):\n| DTO Type | Include | Exclude (add to `excludes`) |\n|----------|---------|------------------------------|\n| Read (IEntity) | All DB columns + computed fields | `password_hashed`, `salt`, `refresh_token` |\n| Create (ICreate) | User-provided fields | `id`, `created_at`, actor FK, path param FK, session FK |\n| Update (IUpdate) | Mutable fields | `id`, `created_at`, actor FK, path param FK, session FK |\n| Summary (ISummary) | Essential display columns only | Non-essential DB columns (intentional omission — add to `excludes`, not `create`) |\n\n**ISummary pagination guard**: If ISummary contains a `pagination` property, the entire schema has an IPage-like structure and ALL its properties are wrong. Erase ALL existing properties (not just `pagination`) and rebuild the schema from scratch with individual entity fields (e.g., `id`, `name`, `created_at`) derived from the database schema. Pagination wrapping is auto-generated by the system; ISummary must describe a single entity item, not a paginated response.\n\n**Nullable Rules**:\n- DB nullable → DTO non-null is **forbidden** (use `oneOf` with null for Read DTOs, remove from `required` for Create DTOs)\n- DB non-null → DTO nullable is **allowed** (intentional, e.g., `@default`) — do NOT "fix" this\n\n### 4.2. Phantom Detection\n\n**Before classifying a property as phantom**:\n1. Check the loaded DB schema\'s **column list** — does the property name match any column?\n2. Check the loaded DB schema\'s **relation list** — does the property name match any relation?\n3. Read `specification` and requirements carefully — is this a computed field with a concrete data source or business rationale? Do not skim; a legitimate specification may describe a non-obvious derivation.\n\n**Decision**:\n- Found in columns OR relations → NOT phantom. Use the property name in `databaseSchemaProperty`.\n- Not in DB BUT has valid business logic (concrete computation, cross-table join, transformation) → Keep with `databaseSchemaProperty: null`\n- Not in DB AND no concrete rationale (empty, vague, or wishful) → Erase\n\n**Concrete examples of valid `databaseSchemaProperty: null`** (these are NOT phantom):\n\n| Property | DTO Type | Why valid |\n|----------|----------|-----------|\n| `page`, `limit`, `search`, `sort` | `IRequest` | Pagination/search parameters — query logic, not DB columns |\n| `ip`, `href`, `referrer` | `IJoin`, `ILogin`, `IActorSession` | Session context — stored in session table, not actor table |\n| `*_count` | Read DTOs | Aggregation — `COUNT()` of related records |\n| `token` / `access` / `refresh` / `expired_at` | `IAuthorized` | Auth response — computed by server, not stored as-is |\n\n**`password` is NOT null-mapped** — it maps to DB column `password_hashed` via transformation (`databaseSchemaProperty: "password_hashed"`). See Section 4.4 for password handling rules.\n\nThese fields serve cross-table mappings, transformations, or query parameter roles. Verify against loaded DB schemas and requirements before erasing.\n\n**Common mistake**: Setting `databaseSchemaProperty: null` for properties that ARE in the database. Always verify against the loaded schema before using `null`.\n\n### 4.3. Relation Mapping (FK → $ref)\n\n#### Three Relation Types\n\n| Type | Definition | In Read DTO | In Create/Update DTO |\n|------|------------|-------------|----------------------|\n| **Composition** | Parent owns children (same transaction) | Full nested array/object | Nested `ICreate` objects |\n| **Association** | Independent entity (exists before parent) | `$ref` to `.ISummary` | Raw FK ID only |\n| **Aggregation** | Event-driven data (created later by others) | NOT included (use counts) | N/A |\n\n**Decision**: Created together? → Composition. Pre-exists? → Association. Created later by others? → Aggregation.\n\n#### Response vs Request DTO Transformation\n\n**CRITICAL**: FK transformation rules are OPPOSITE for Response vs Request.\n\n| Aspect | Response DTO (Read) | Request DTO (Create/Update) |\n|--------|---------------------|----------------------------|\n| FK Field | Transform to `$ref` object | Keep as scalar ID |\n| Field Name | Remove `_id` suffix | Keep `_id` suffix |\n| Type | `IEntity.ISummary` | `string` (UUID) |\n| `databaseSchemaProperty` | Relation name: `"author"` | Column name: `"author_id"` |\n| Example | `author: IUser.ISummary` | `author_id: string` |\n\n```typescript\n// Response DTO: FK → Object (remove _id, add $ref)\ninterface IArticle {\n author: IUser.ISummary; // author_id → author\n category: ICategory.ISummary; // category_id → category\n}\n\n// Request DTO: user-specified FK → keep as scalar\ninterface IArticle.ICreate {\n category_id: string; // ✅ Keep as scalar (user chooses category)\n // ❌ NEVER: category: ICategory.ISummary\n // ❌ author_id excluded: actor identity resolved from JWT\n // ❌ author_session_id excluded: session identity resolved from JWT\n}\n```\n\n#### Adding Missing Relation (Read DTO)\n```typescript\n{\n key: "author",\n databaseSchemaProperty: "author", // Relation name from DB schema\n reason: "Missing relation for author_id FK",\n type: "create",\n specification: "Join from articles.author_id to users.id. Returns ISummary.",\n description: "The article\'s author.",\n schema: { $ref: "#/components/schemas/IUser.ISummary" },\n required: true\n}\n```\n\n#### Prefer Code Over UUID\n\nWhen target entity has unique `code` field, use `entity_code` instead of `entity_id` in Request DTOs:\n```typescript\n// If enterprises has: code STRING UNIQUE\ninterface ITeam.ICreate {\n enterprise_code: string; // ✅ Use code\n // ❌ enterprise_id: string // Don\'t use UUID when code exists\n}\n```\n\n### 4.4. Security (Actor DTOs Only)\n\n**Applies ONLY to**: `IActor`, `IActor.ISummary`, `IActor.IJoin`, `IActor.ILogin`, `IActor.IAuthorized`, `IActor.IRefresh`, `IActorSession`\n\n| Rule | Detection | Fix |\n|------|-----------|-----|\n| `password_hashed` in request DTO | Field name contains "hashed" | Erase, create `password: string` with `databaseSchemaProperty: "password_hashed"` |\n| `password` in response DTO | Password exposed | Erase |\n| Session fields (`ip`, `href`, `referrer`) in wrong DTO | Present in IActor/ISummary/IAuthorized/IRefresh | Erase |\n| Secrets in response | `salt`, `refresh_token`, `secret_key` | Erase |\n\n**Principle**: Actor is WHO, Session is HOW THEY CONNECTED.\n\n#### Actor Kind and Password\n\n| Actor Kind | Password in IJoin? | Password in ILogin? |\n|------------|-------------------|---------------------|\n| `guest` | NO | N/A (no login) |\n| `member` | YES | YES |\n| `admin` | YES | YES |\n\n#### Session Context Fields\n\n`ip`, `href`, `referrer` belong only where sessions are created or represented.\n\n`ip` is optional in `IJoin`/`ILogin` because in SSR (Server Side Rendering) the client cannot know its own IP — the server captures it as fallback (`body.ip ?? serverIp`). In `IActorSession` (Read DTO), `ip` is required because the stored value is always present.\n\n| DTO Type | `href` | `referrer` | `ip` |\n|----------|--------|------------|------|\n| `IActor.IJoin` | required | required | optional (format: `ipv4`) |\n| `IActor.ILogin` | required | required | optional (format: `ipv4`) |\n| `IActorSession` | required | required | required |\n| `IActor`, `ISummary`, `IAuthorized`, `IRefresh` | **delete** | **delete** | **delete** |\n\n## 5. Input Materials\n\n### Initially Provided\n- Requirements analysis report (subset)\n- Database schema info (subset)\n- API design instructions\n- Target schema for refinement\n- Operations using this schema\n\n### Available via Function Calling\n- `getAnalysisSections`: Business requirements\n- `getDatabaseSchemas`: DB field details (columns + relations)\n- `getInterfaceOperations`: API operation context\n- `getInterfaceSchemas`: Other DTOs for reference\n\n**Rules**:\n- Max 8 preliminary calls\n- Use batch requests (arrays)\n- NEVER re-request already loaded materials\n- Empty array response → That type exhausted, move to complete\n- `getInterfaceSchemas` only returns existing schemas\n - NEVER request a type you intend to newly create via `$ref` — it does not exist yet\n - If the call fails with "non-existing", the failure is correct — do not retry\n - Another agent creates missing `$ref` targets later\n\n## 6. Zero Imagination Policy\n\n**NEVER**:\n- Assume DB schema fields without loading\n- Guess field descriptions without requirements\n- Proceed based on "typical patterns"\n- Claim a column or relation does not exist without verifying against the loaded schema\n\n**ALWAYS**:\n- Load data via function calling FIRST\n- Verify against actual materials\n- Request before deciding\n- Before `databaseSchemaProperty: null`: verify valid logic in `specification`. Before `erase`: confirm no DB mapping AND no valid business logic.\n\n## 7. Output Example\n\n**Scenario**: Refining `IBbsArticle` (Read DTO)\n\n| Category | Properties |\n|----------|------------|\n| DB Columns | `id`, `bbs_member_id`, `title`, `body`, `created_at`, `deleted_at` |\n| DB Relations | `member`, `comments`, `snapshots` |\n| DTO Properties | `id`, `title`, `body`, `author`, `created_at`, `deleted_at` |\n\n**Mapping Plan**:\n\n| DB Property | → | Action | Reason |\n|-------------|---|--------|--------|\n| `id` | `id` | depict | Direct mapping |\n| `title` | `title` | depict | Direct mapping |\n| `body` | `body` | depict | Direct mapping |\n| `member` | `author` | depict | Relation exposed as author |\n| `created_at` | `created_at` | depict | Direct mapping |\n| `deleted_at` | `deleted_at` | depict | Direct mapping, nullable |\n| `bbs_member_id` | — | exclude | FK column exposed as `author` object |\n| `comments` | — | exclude | Aggregation relation |\n| `snapshots` | — | exclude | Separate endpoint |\n\n```typescript\nprocess({\n thinking: "All 6 DTO properties enriched. All 9 DB properties handled: 6 mapped, 3 excluded.",\n request: {\n type: "complete",\n review: "Enriched 6 DTO properties. Excluded 3 DB properties.",\n databaseSchema: "bbs_articles",\n specification: "Direct mapping from bbs_articles with author join.",\n description: "Complete article entity with author info.",\n excludes: [\n { databaseSchemaProperty: "bbs_member_id", reason: "FK exposed as author object" },\n { databaseSchemaProperty: "comments", reason: "Aggregation: use separate endpoint" },\n { databaseSchemaProperty: "snapshots", reason: "Composition: separate endpoint" }\n ],\n revises: [\n { key: "id", databaseSchemaProperty: "id", type: "depict", reason: "Adding documentation",\n specification: "Direct mapping from bbs_articles.id.", description: "Unique article identifier." },\n { key: "title", databaseSchemaProperty: "title", type: "depict", reason: "Adding documentation",\n specification: "Direct mapping from bbs_articles.title.", description: "Article title." },\n { key: "body", databaseSchemaProperty: "body", type: "depict", reason: "Adding documentation",\n specification: "Direct mapping from bbs_articles.body.", description: "Article content body." },\n { key: "author", databaseSchemaProperty: "member", type: "depict", reason: "Adding documentation",\n specification: "Join via bbs_member_id.", description: "Author of this article." },\n { key: "created_at", databaseSchemaProperty: "created_at", type: "depict", reason: "Adding documentation",\n specification: "Direct mapping from bbs_articles.created_at.", description: "Creation timestamp." },\n { key: "deleted_at", databaseSchemaProperty: "deleted_at", type: "depict", reason: "Adding documentation",\n specification: "Direct mapping from bbs_articles.deleted_at. Nullable.", description: "Soft-deletion timestamp, null if active." }\n ]\n }\n})\n```\n\n**Result**: 9 DB properties → 6 mapped in `revises` + 3 in `excludes` = complete coverage.\n\n## 8. Checklist\n\nBefore calling `complete`:\n\n**Object-Level** (reviewed drafts from `x-autobe-*`):\n- [ ] `databaseSchema` correct (table name or null)\n- [ ] `specification` refined (MANDATORY)\n- [ ] `description` refined (MANDATORY)\n\n**Property-Level**:\n- [ ] Every DTO property in `revises` (`depict`, `create`, `update`, or `erase`)\n- [ ] Every DB property either mapped via `databaseSchemaProperty` in `revises`, or declared in `excludes`\n- [ ] No DB property appears in both `excludes` and `revises`\n- [ ] No duplicates (one action per key)\n- [ ] WHICH → HOW → WHAT order followed\n- [ ] `databaseSchemaProperty: null` only for computed values (not in DB)\n- [ ] Before `erase`: verify against loaded DB schemas and requirements — cross-table mapping, transformation, or query parameter role means valid (not phantom)\n\n**Pre-Review Hardening**:\n- [ ] Content: All fields present (DB + computed); ISummary describes a single entity item, not a paginated response\n- [ ] Did NOT "fix" DB non-null → DTO nullable (it\'s intentional, e.g., `@default`)\n- [ ] Phantom: No fields without valid source; DB-mapped non-relation and recognized-role fields never erased\n- [ ] Relation: FK → `$ref` in Read DTOs; `databaseSchemaProperty` uses relation name (Read) or column name (Request)\n- [ ] Security (Actor DTOs): No exposed passwords/secrets; guest IJoin has no `password`; `ip` optional in IJoin/ILogin\n\n**Function Calling**:\n- [ ] All needed materials loaded\n- [ ] No imagination - verified against actual data\n- [ ] Did NOT call `getInterfaceSchemas` for types that do not yet exist'
31302
31747
  }, ...props.preliminary.getHistories(), {
31303
31748
  type: "assistantMessage",
31304
31749
  id: v7(),
@@ -31736,7 +32181,7 @@ var AutoBeInterfaceSchemaRefineProgrammer;
31736
32181
  })(AutoBeInterfaceSchemaRefineProgrammer || (AutoBeInterfaceSchemaRefineProgrammer = {}));
31737
32182
 
31738
32183
  async function orchestrateInterfaceSchemaRefine(ctx, props) {
31739
- const typeNames = Object.entries(props.schemas).filter(([k, v]) => AutoBeJsonSchemaValidator.isPreset(k) === false && AutoBeOpenApiTypeChecker.isObject(v) && Object.keys(v.properties).length !== 0).map(([k]) => k);
32184
+ const typeNames = Object.entries(props.schemas).filter(([k, v]) => AutoBeJsonSchemaValidator.isPreset(k) === false && AutoBeOpenApiTypeChecker.isObject(v)).map(([k]) => k);
31740
32185
  props.progress.total += typeNames.length;
31741
32186
  const x = {};
31742
32187
  await executeCachedBatch(ctx, typeNames.map(it => async promptCacheKey => {
@@ -35500,7 +35945,7 @@ var AutoBeInterfaceSchemaReviewProgrammer;
35500
35945
  })(AutoBeInterfaceSchemaReviewProgrammer || (AutoBeInterfaceSchemaReviewProgrammer = {}));
35501
35946
 
35502
35947
  async function orchestrateInterfaceSchemaReview(ctx, props) {
35503
- const typeNames = Object.entries(props.schemas).filter(([k, v]) => AutoBeJsonSchemaValidator.isPreset(k) === false && AutoBeOpenApiTypeChecker.isObject(v) && Object.keys(v.properties).length !== 0).map(([k]) => k);
35948
+ const typeNames = Object.entries(props.schemas).filter(([k, v]) => AutoBeJsonSchemaValidator.isPreset(k) === false && AutoBeOpenApiTypeChecker.isObject(v)).map(([k]) => k);
35504
35949
  const x = {};
35505
35950
  await executeCachedBatch(ctx, typeNames.map(it => async promptCacheKey => {
35506
35951
  const predicate = key => key === it || AutoBeJsonSchemaValidator.isPage(key) && AutoBeJsonSchemaFactory.getPageName(key) === it;
@@ -44016,7 +44461,7 @@ const transformPrismaComponentsHistory = (state, props) => {
44016
44461
  id: v7(),
44017
44462
  created_at: (new Date).toISOString(),
44018
44463
  type: "systemMessage",
44019
- text: '\x3c!--\nfilename: DATABASE_COMPONENT.md\n--\x3e\n# Database Component Table Extraction Agent\n\nYou are extracting **tables** for a **single database component skeleton**. Your ONLY job is to fill in the `tables` array for the component you received.\n\n**Function calling is MANDATORY** - execute immediately without asking for permission.\n\n---\n\n## 1. Quick Reference\n\n### 1.1. Your Assignment\n\n| Received | Your Job |\n|----------|----------|\n| `filename`, `namespace`, `thinking`, `review`, `rationale` | Fill in `tables` array |\n\n**YOU ARE NOT**: Creating multiple components, reorganizing, or changing namespace/filename.\n\n### 1.2. Table Structure\n```typescript\n{\n name: "shopping_sale_reviews", // snake_case, plural\n description: "Customer reviews and ratings for sales"\n}\n```\n\n### 1.3. Naming Conventions\n\n| Rule | Example |\n|------|---------|\n| Plural | `users`, `products`, `order_items` |\n| snake_case | `user_profiles`, `shopping_carts` |\n| Domain prefix | `shopping_customers`, `bbs_articles` |\n| Snapshots | `{entity}_snapshots` |\n| Junction tables | `user_roles`, `product_categories` |\n| NO prefix duplication | ❌ `bbs_bbs_articles` → ✅ `bbs_articles` |\n\n---\n\n## 2. ⛔ ABSOLUTE PROHIBITION: Actor Tables\n\n**NEVER create actor or authentication tables. These are handled by the Authorization Agent.**\n\n| ❌ FORBIDDEN | ✅ CORRECT |\n|--------------|-----------|\n| `users`, `customers`, `administrators` | Reference via FK: `user_id` |\n| `user_sessions`, `customer_sessions` | Assume these exist |\n| `password_resets`, `oauth_connections` | (handled elsewhere) |\n```typescript\n// ❌ WRONG\ntables: [\n { name: "shopping_customers", ... }, // FORBIDDEN!\n { name: "orders", ... }\n]\n\n// ✅ CORRECT\ntables: [\n { name: "orders", description: "Orders with customer_id FK to shopping_customers" }\n]\n```\n\n---\n\n## 3. Normalization Patterns (CRITICAL)\n\n### 3.1. Separate Entities Pattern\n\n**When distinct entities have different lifecycles → Separate tables**\n```typescript\n// ❌ WRONG - Nullable field proliferation\nshopping_sale_questions: {\n answer_title: string? // Nullable!\n answer_body: string? // Nullable!\n seller_id: string? // Nullable!\n}\n\n// ✅ CORRECT - Separate tables\ntables: [\n { name: "shopping_sale_questions", description: "Customer questions about sales" },\n { name: "shopping_sale_question_answers", description: "Seller answers (1:1 with questions)" }\n]\n```\n\n### 3.2. Polymorphic Ownership Pattern\n\n**When multiple actor types can create the same entity → Main + subtype tables**\n```typescript\n// ❌ WRONG - Multiple nullable actor FKs\nshopping_order_issues: {\n customer_id: string? // Nullable!\n seller_id: string? // Nullable!\n}\n\n// ✅ CORRECT - Main entity + subtype tables\ntables: [\n { name: "shopping_order_good_issues", description: "Main issue entity with actor_type" },\n { name: "shopping_order_good_issue_of_customers", description: "Customer-created issues (1:1)" },\n { name: "shopping_order_good_issue_of_sellers", description: "Seller-created issues (1:1)" }\n]\n```\n\n---\n\n## 4. Complete Table Extraction\n\n### 4.1. Verification Steps\n\n**Step 1**: Re-read component rationale → Every concept needs tables\n\n**Step 2**: Cross-reference requirements → Every "SHALL" needs table support\n\n**Step 3**: Check common patterns:\n\n| Pattern | Tables Needed |\n|---------|---------------|\n| Audit/History | `{entity}_snapshots` |\n| Many-to-many | Junction table `{entity1}_{entity2}` |\n| File uploads | `{entity}_files`, `{entity}_images` |\n| User feedback | `{entity}_reviews`, `{entity}_comments` |\n| State tracking | `{entity}_logs`, `{entity}_activities` |\n\n**Step 4**: Validate workflows → Every data-storing step needs a table\n\n### 4.2. Example: Insufficient vs Sufficient\n\n**Component**: Sales \n**Rationale**: "Groups product catalog, pricing, and sales transaction entities"\n```typescript\n// ❌ INSUFFICIENT - Only 3 tables\ntables: [\n { name: "sales", description: "Main sale listings" },\n { name: "sale_snapshots", description: "Audit trail" },\n { name: "sale_units", description: "Units within a sale" }\n]\n// Missing: images, reviews, questions, promotions, favorites, view_stats\n\n// ✅ SUFFICIENT - 12 tables\ntables: [\n // Core\n { name: "sales", description: "Main sale listings" },\n { name: "sale_snapshots", description: "Point-in-time snapshots" },\n { name: "sale_units", description: "Individual stock units" },\n // Content\n { name: "sale_images", description: "Multiple images per sale" },\n { name: "sale_specifications", description: "Technical details" },\n // Customer interaction\n { name: "sale_reviews", description: "Customer reviews" },\n { name: "sale_review_votes", description: "Helpful votes on reviews" },\n { name: "sale_questions", description: "Customer questions" },\n { name: "sale_question_answers", description: "Seller answers" },\n // Management\n { name: "sale_promotions", description: "Promotions and discounts" },\n { name: "sale_favorites", description: "User wishlists" },\n { name: "sale_view_stats", description: "View analytics" }\n]\n```\n\n---\n\n## 5. Function Calling\n\n### 5.1. Load Requirements (when needed)\n```typescript\nprocess({\n thinking: "Missing business domain context for table extraction.",\n request: {\n type: "getAnalysisSections",\n sectionIds: [1, 2, 5]\n }\n})\n```\n\n### 5.2. Complete\n```typescript\nprocess({\n thinking: "Designed 12 tables for Sales component covering all requirements.",\n request: {\n type: "complete",\n analysis: "Identified core entities, customer interactions, and management tables...",\n rationale: "Applied 3NF normalization, separated Q&A into distinct tables...",\n tables: [\n { name: "sales", description: "Main sale listings with product, pricing, seller" },\n { name: "sale_snapshots", description: "Point-in-time snapshots for audit" },\n // ... more tables\n ]\n }\n})\n```\n\n---\n\n## 6. Input Materials Management\n\n| Instruction | Action |\n|-------------|--------|\n| Materials already loaded | DO NOT re-request |\n| Materials available | May request if needed |\n| Preliminary returns `[]` | Move to complete |\n\n---\n\n## 7. Final Checklist\n\n**Component Rationale Coverage:**\n- [ ] Every concept in rationale has tables\n- [ ] Every business capability has supporting tables\n\n**Requirements Coverage:**\n- [ ] Every "SHALL" statement has table support\n- [ ] Every user workflow can be executed\n\n**Normalization:**\n- [ ] Separate entities pattern applied (no nullable field proliferation)\n- [ ] Polymorphic pattern applied where needed (main + subtypes)\n- [ ] Junction tables for many-to-many relationships\n- [ ] Snapshot tables for audit trails\n\n**Table Quality:**\n- [ ] Table count: 3-15 (typical)\n- [ ] All names: snake_case, plural\n- [ ] No prefix duplication\n- [ ] Each table has clear description\n- [ ] All descriptions in English\n\n**Prohibitions:**\n- [ ] NO actor tables (`users`, `customers`, etc.)\n- [ ] NO session tables\n- [ ] NO authentication tables\n- [ ] NOT mixing domains from other components\n\n**Output:**\n- [ ] `thinking` summarizes tables designed\n- [ ] `analysis` documents component scope\n- [ ] `rationale` explains design decisions\n- [ ] Ready to call `process()` with `type: "complete"`\n\n**When in Doubt:**\n- [ ] Create MORE tables rather than FEWER\n- [ ] Better 12 complete tables than 6 incomplete'
44464
+ text: '\x3c!--\nfilename: DATABASE_COMPONENT.md\n--\x3e\n# Database Component Table Extraction Agent\n\nYou are extracting **tables** for a **single database component skeleton**. Your ONLY job is to fill in the `tables` array for the component you received.\n\n**Function calling is MANDATORY** - execute immediately without asking for permission.\n\n---\n\n## 1. Quick Reference\n\n### 1.1. Your Assignment\n\n| Received | Your Job |\n|----------|----------|\n| `filename`, `namespace`, `thinking`, `review`, `rationale` | Fill in `tables` array |\n\n**YOU ARE NOT**: Creating multiple components, reorganizing, or changing namespace/filename.\n\n### 1.2. Table Structure\n```typescript\n{\n name: "shopping_sale_reviews", // snake_case, plural\n description: "Customer reviews and ratings for sales"\n}\n```\n\n### 1.3. Naming Conventions\n\n| Rule | Example |\n|------|---------|\n| Plural | `users`, `products`, `order_items` |\n| snake_case | `user_profiles`, `shopping_carts` |\n| Domain prefix | `shopping_customers`, `bbs_articles` |\n| Snapshots | `{entity}_snapshots` |\n| Junction tables | `user_roles`, `product_categories` |\n| NO prefix duplication | ❌ `bbs_bbs_articles` → ✅ `bbs_articles` |\n\n---\n\n## 2. ⛔ ABSOLUTE PROHIBITION: Actor Tables\n\n**NEVER create actor or authentication tables. These are handled by the Authorization Agent.**\n\n| ❌ FORBIDDEN | ✅ CORRECT |\n|--------------|-----------|\n| `users`, `customers`, `administrators` | Reference via FK: `user_id` |\n| `user_sessions`, `customer_sessions` | Assume these exist |\n| `password_resets`, `oauth_connections` | (handled elsewhere) |\n```typescript\n// ❌ WRONG\ntables: [\n { name: "shopping_customers", ... }, // FORBIDDEN!\n { name: "orders", ... }\n]\n\n// ✅ CORRECT\ntables: [\n { name: "orders", description: "Orders with customer_id FK to shopping_customers" }\n]\n```\n\n---\n\n## 3. Normalization Patterns (CRITICAL)\n\n### 3.1. Separate Entities Pattern\n\n**When distinct entities have different lifecycles → Separate tables**\n```typescript\n// ❌ WRONG - Nullable field proliferation\nshopping_sale_questions: {\n answer_title: string? // Nullable!\n answer_body: string? // Nullable!\n seller_id: string? // Nullable!\n}\n\n// ✅ CORRECT - Separate tables\ntables: [\n { name: "shopping_sale_questions", description: "Customer questions about sales" },\n { name: "shopping_sale_question_answers", description: "Seller answers (1:1 with questions)" }\n]\n```\n\n### 3.2. Polymorphic Ownership Pattern\n\n**When multiple actor types can create the same entity → Main + subtype tables**\n```typescript\n// ❌ WRONG - Multiple nullable actor FKs\nshopping_order_issues: {\n customer_id: string? // Nullable!\n seller_id: string? // Nullable!\n}\n\n// ✅ CORRECT - Main entity + subtype tables\ntables: [\n { name: "shopping_order_good_issues", description: "Main issue entity with actor_type" },\n { name: "shopping_order_good_issue_of_customers", description: "Customer-created issues (1:1)" },\n { name: "shopping_order_good_issue_of_sellers", description: "Seller-created issues (1:1)" }\n]\n```\n\n---\n\n## 4. Complete Table Extraction\n\n### 4.1. Verification Steps\n\n**Step 1**: Re-read component rationale → Every concept needs tables\n\n**Step 2**: Cross-reference requirements → Every "SHALL" needs table support\n\n**Step 3**: Check common patterns:\n\n| Pattern | Tables Needed |\n|---------|---------------|\n| Audit/History | `{entity}_snapshots` |\n| Many-to-many | Junction table `{entity1}_{entity2}` |\n| File uploads | `{entity}_files`, `{entity}_images` |\n| User feedback | `{entity}_reviews`, `{entity}_comments` |\n| State tracking | `{entity}_logs`, `{entity}_activities` |\n\n**Step 4**: Validate workflows → Every data-storing step needs a table\n\n### 4.2. Example: Insufficient vs Sufficient\n\n**Component**: Sales \n**Rationale**: "Groups product catalog, pricing, and sales transaction entities"\n```typescript\n// ❌ INSUFFICIENT - Only 3 tables\ntables: [\n { name: "sales", description: "Main sale listings" },\n { name: "sale_snapshots", description: "Audit trail" },\n { name: "sale_units", description: "Units within a sale" }\n]\n// Missing: images, reviews, questions, promotions, favorites, view_stats\n\n// ✅ SUFFICIENT - 12 tables\ntables: [\n // Core\n { name: "sales", description: "Main sale listings" },\n { name: "sale_snapshots", description: "Point-in-time snapshots" },\n { name: "sale_units", description: "Individual stock units" },\n // Content\n { name: "sale_images", description: "Multiple images per sale" },\n { name: "sale_specifications", description: "Technical details" },\n // Customer interaction\n { name: "sale_reviews", description: "Customer reviews" },\n { name: "sale_review_votes", description: "Helpful votes on reviews" },\n { name: "sale_questions", description: "Customer questions" },\n { name: "sale_question_answers", description: "Seller answers" },\n // Management\n { name: "sale_promotions", description: "Promotions and discounts" },\n { name: "sale_favorites", description: "User wishlists" },\n { name: "sale_view_stats", description: "View analytics" }\n]\n```\n\n---\n\n## 5. Function Calling\n\n### 5.1. Load Requirements\n\n```typescript\nprocess({\n thinking: "Need requirements to identify business domains.",\n request: {\n type: "getAnalysisSections",\n sectionIds: [1, 2, 3, 5]\n }\n})\n```\n\n### 5.2. Complete\n```typescript\nprocess({\n thinking: "Designed 12 tables for Sales component covering all requirements.",\n request: {\n type: "complete",\n analysis: "Identified core entities, customer interactions, and management tables...",\n rationale: "Applied 3NF normalization, separated Q&A into distinct tables...",\n tables: [\n { name: "sales", description: "Main sale listings with product, pricing, seller" },\n { name: "sale_snapshots", description: "Point-in-time snapshots for audit" },\n // ... more tables\n ]\n }\n})\n```\n\n---\n\n## 6. Input Materials Management\n\n| Instruction | Action |\n|-------------|--------|\n| Materials already loaded | DO NOT re-request |\n| Materials available | May request if needed |\n| Preliminary returns `[]` | Move to complete |\n\n---\n\n## 7. Final Checklist\n\n**Component Rationale Coverage:**\n- [ ] Every concept in rationale has tables\n- [ ] Every business capability has supporting tables\n\n**Requirements Coverage:**\n- [ ] Every "SHALL" statement has table support\n- [ ] Every user workflow can be executed\n\n**Normalization:**\n- [ ] Separate entities pattern applied (no nullable field proliferation)\n- [ ] Polymorphic pattern applied where needed (main + subtypes)\n- [ ] Junction tables for many-to-many relationships\n- [ ] Snapshot tables for audit trails\n\n**Table Quality:**\n- [ ] Table count: 3-15 (typical)\n- [ ] All names: snake_case, plural\n- [ ] No prefix duplication\n- [ ] Each table has clear description\n- [ ] All descriptions in English\n\n**Prohibitions:**\n- [ ] NO actor tables (`users`, `customers`, etc.)\n- [ ] NO session tables\n- [ ] NO authentication tables\n- [ ] NOT mixing domains from other components\n\n**Output:**\n- [ ] `thinking` summarizes tables designed\n- [ ] `analysis` documents component scope\n- [ ] `rationale` explains design decisions\n- [ ] Ready to call `process()` with `type: "complete"`\n\n**When in Doubt:**\n- [ ] Create MORE tables rather than FEWER\n- [ ] Better 12 complete tables than 6 incomplete'
44020
44465
  }, ...props.preliminary.getHistories(), {
44021
44466
  id: v7(),
44022
44467
  created_at: (new Date).toISOString(),
@@ -44889,12 +45334,12 @@ const transformPrismaComponentReviewHistory = props => ({
44889
45334
  id: v7(),
44890
45335
  created_at: (new Date).toISOString(),
44891
45336
  type: "systemMessage",
44892
- text: '\x3c!--\nfilename: DATABASE_COMPONENT.md\n--\x3e\n# Database Component Table Extraction Agent\n\nYou are extracting **tables** for a **single database component skeleton**. Your ONLY job is to fill in the `tables` array for the component you received.\n\n**Function calling is MANDATORY** - execute immediately without asking for permission.\n\n---\n\n## 1. Quick Reference\n\n### 1.1. Your Assignment\n\n| Received | Your Job |\n|----------|----------|\n| `filename`, `namespace`, `thinking`, `review`, `rationale` | Fill in `tables` array |\n\n**YOU ARE NOT**: Creating multiple components, reorganizing, or changing namespace/filename.\n\n### 1.2. Table Structure\n```typescript\n{\n name: "shopping_sale_reviews", // snake_case, plural\n description: "Customer reviews and ratings for sales"\n}\n```\n\n### 1.3. Naming Conventions\n\n| Rule | Example |\n|------|---------|\n| Plural | `users`, `products`, `order_items` |\n| snake_case | `user_profiles`, `shopping_carts` |\n| Domain prefix | `shopping_customers`, `bbs_articles` |\n| Snapshots | `{entity}_snapshots` |\n| Junction tables | `user_roles`, `product_categories` |\n| NO prefix duplication | ❌ `bbs_bbs_articles` → ✅ `bbs_articles` |\n\n---\n\n## 2. ⛔ ABSOLUTE PROHIBITION: Actor Tables\n\n**NEVER create actor or authentication tables. These are handled by the Authorization Agent.**\n\n| ❌ FORBIDDEN | ✅ CORRECT |\n|--------------|-----------|\n| `users`, `customers`, `administrators` | Reference via FK: `user_id` |\n| `user_sessions`, `customer_sessions` | Assume these exist |\n| `password_resets`, `oauth_connections` | (handled elsewhere) |\n```typescript\n// ❌ WRONG\ntables: [\n { name: "shopping_customers", ... }, // FORBIDDEN!\n { name: "orders", ... }\n]\n\n// ✅ CORRECT\ntables: [\n { name: "orders", description: "Orders with customer_id FK to shopping_customers" }\n]\n```\n\n---\n\n## 3. Normalization Patterns (CRITICAL)\n\n### 3.1. Separate Entities Pattern\n\n**When distinct entities have different lifecycles → Separate tables**\n```typescript\n// ❌ WRONG - Nullable field proliferation\nshopping_sale_questions: {\n answer_title: string? // Nullable!\n answer_body: string? // Nullable!\n seller_id: string? // Nullable!\n}\n\n// ✅ CORRECT - Separate tables\ntables: [\n { name: "shopping_sale_questions", description: "Customer questions about sales" },\n { name: "shopping_sale_question_answers", description: "Seller answers (1:1 with questions)" }\n]\n```\n\n### 3.2. Polymorphic Ownership Pattern\n\n**When multiple actor types can create the same entity → Main + subtype tables**\n```typescript\n// ❌ WRONG - Multiple nullable actor FKs\nshopping_order_issues: {\n customer_id: string? // Nullable!\n seller_id: string? // Nullable!\n}\n\n// ✅ CORRECT - Main entity + subtype tables\ntables: [\n { name: "shopping_order_good_issues", description: "Main issue entity with actor_type" },\n { name: "shopping_order_good_issue_of_customers", description: "Customer-created issues (1:1)" },\n { name: "shopping_order_good_issue_of_sellers", description: "Seller-created issues (1:1)" }\n]\n```\n\n---\n\n## 4. Complete Table Extraction\n\n### 4.1. Verification Steps\n\n**Step 1**: Re-read component rationale → Every concept needs tables\n\n**Step 2**: Cross-reference requirements → Every "SHALL" needs table support\n\n**Step 3**: Check common patterns:\n\n| Pattern | Tables Needed |\n|---------|---------------|\n| Audit/History | `{entity}_snapshots` |\n| Many-to-many | Junction table `{entity1}_{entity2}` |\n| File uploads | `{entity}_files`, `{entity}_images` |\n| User feedback | `{entity}_reviews`, `{entity}_comments` |\n| State tracking | `{entity}_logs`, `{entity}_activities` |\n\n**Step 4**: Validate workflows → Every data-storing step needs a table\n\n### 4.2. Example: Insufficient vs Sufficient\n\n**Component**: Sales \n**Rationale**: "Groups product catalog, pricing, and sales transaction entities"\n```typescript\n// ❌ INSUFFICIENT - Only 3 tables\ntables: [\n { name: "sales", description: "Main sale listings" },\n { name: "sale_snapshots", description: "Audit trail" },\n { name: "sale_units", description: "Units within a sale" }\n]\n// Missing: images, reviews, questions, promotions, favorites, view_stats\n\n// ✅ SUFFICIENT - 12 tables\ntables: [\n // Core\n { name: "sales", description: "Main sale listings" },\n { name: "sale_snapshots", description: "Point-in-time snapshots" },\n { name: "sale_units", description: "Individual stock units" },\n // Content\n { name: "sale_images", description: "Multiple images per sale" },\n { name: "sale_specifications", description: "Technical details" },\n // Customer interaction\n { name: "sale_reviews", description: "Customer reviews" },\n { name: "sale_review_votes", description: "Helpful votes on reviews" },\n { name: "sale_questions", description: "Customer questions" },\n { name: "sale_question_answers", description: "Seller answers" },\n // Management\n { name: "sale_promotions", description: "Promotions and discounts" },\n { name: "sale_favorites", description: "User wishlists" },\n { name: "sale_view_stats", description: "View analytics" }\n]\n```\n\n---\n\n## 5. Function Calling\n\n### 5.1. Load Requirements (when needed)\n```typescript\nprocess({\n thinking: "Missing business domain context for table extraction.",\n request: {\n type: "getAnalysisSections",\n sectionIds: [1, 2, 5]\n }\n})\n```\n\n### 5.2. Complete\n```typescript\nprocess({\n thinking: "Designed 12 tables for Sales component covering all requirements.",\n request: {\n type: "complete",\n analysis: "Identified core entities, customer interactions, and management tables...",\n rationale: "Applied 3NF normalization, separated Q&A into distinct tables...",\n tables: [\n { name: "sales", description: "Main sale listings with product, pricing, seller" },\n { name: "sale_snapshots", description: "Point-in-time snapshots for audit" },\n // ... more tables\n ]\n }\n})\n```\n\n---\n\n## 6. Input Materials Management\n\n| Instruction | Action |\n|-------------|--------|\n| Materials already loaded | DO NOT re-request |\n| Materials available | May request if needed |\n| Preliminary returns `[]` | Move to complete |\n\n---\n\n## 7. Final Checklist\n\n**Component Rationale Coverage:**\n- [ ] Every concept in rationale has tables\n- [ ] Every business capability has supporting tables\n\n**Requirements Coverage:**\n- [ ] Every "SHALL" statement has table support\n- [ ] Every user workflow can be executed\n\n**Normalization:**\n- [ ] Separate entities pattern applied (no nullable field proliferation)\n- [ ] Polymorphic pattern applied where needed (main + subtypes)\n- [ ] Junction tables for many-to-many relationships\n- [ ] Snapshot tables for audit trails\n\n**Table Quality:**\n- [ ] Table count: 3-15 (typical)\n- [ ] All names: snake_case, plural\n- [ ] No prefix duplication\n- [ ] Each table has clear description\n- [ ] All descriptions in English\n\n**Prohibitions:**\n- [ ] NO actor tables (`users`, `customers`, etc.)\n- [ ] NO session tables\n- [ ] NO authentication tables\n- [ ] NOT mixing domains from other components\n\n**Output:**\n- [ ] `thinking` summarizes tables designed\n- [ ] `analysis` documents component scope\n- [ ] `rationale` explains design decisions\n- [ ] Ready to call `process()` with `type: "complete"`\n\n**When in Doubt:**\n- [ ] Create MORE tables rather than FEWER\n- [ ] Better 12 complete tables than 6 incomplete'
45337
+ text: '\x3c!--\nfilename: DATABASE_COMPONENT.md\n--\x3e\n# Database Component Table Extraction Agent\n\nYou are extracting **tables** for a **single database component skeleton**. Your ONLY job is to fill in the `tables` array for the component you received.\n\n**Function calling is MANDATORY** - execute immediately without asking for permission.\n\n---\n\n## 1. Quick Reference\n\n### 1.1. Your Assignment\n\n| Received | Your Job |\n|----------|----------|\n| `filename`, `namespace`, `thinking`, `review`, `rationale` | Fill in `tables` array |\n\n**YOU ARE NOT**: Creating multiple components, reorganizing, or changing namespace/filename.\n\n### 1.2. Table Structure\n```typescript\n{\n name: "shopping_sale_reviews", // snake_case, plural\n description: "Customer reviews and ratings for sales"\n}\n```\n\n### 1.3. Naming Conventions\n\n| Rule | Example |\n|------|---------|\n| Plural | `users`, `products`, `order_items` |\n| snake_case | `user_profiles`, `shopping_carts` |\n| Domain prefix | `shopping_customers`, `bbs_articles` |\n| Snapshots | `{entity}_snapshots` |\n| Junction tables | `user_roles`, `product_categories` |\n| NO prefix duplication | ❌ `bbs_bbs_articles` → ✅ `bbs_articles` |\n\n---\n\n## 2. ⛔ ABSOLUTE PROHIBITION: Actor Tables\n\n**NEVER create actor or authentication tables. These are handled by the Authorization Agent.**\n\n| ❌ FORBIDDEN | ✅ CORRECT |\n|--------------|-----------|\n| `users`, `customers`, `administrators` | Reference via FK: `user_id` |\n| `user_sessions`, `customer_sessions` | Assume these exist |\n| `password_resets`, `oauth_connections` | (handled elsewhere) |\n```typescript\n// ❌ WRONG\ntables: [\n { name: "shopping_customers", ... }, // FORBIDDEN!\n { name: "orders", ... }\n]\n\n// ✅ CORRECT\ntables: [\n { name: "orders", description: "Orders with customer_id FK to shopping_customers" }\n]\n```\n\n---\n\n## 3. Normalization Patterns (CRITICAL)\n\n### 3.1. Separate Entities Pattern\n\n**When distinct entities have different lifecycles → Separate tables**\n```typescript\n// ❌ WRONG - Nullable field proliferation\nshopping_sale_questions: {\n answer_title: string? // Nullable!\n answer_body: string? // Nullable!\n seller_id: string? // Nullable!\n}\n\n// ✅ CORRECT - Separate tables\ntables: [\n { name: "shopping_sale_questions", description: "Customer questions about sales" },\n { name: "shopping_sale_question_answers", description: "Seller answers (1:1 with questions)" }\n]\n```\n\n### 3.2. Polymorphic Ownership Pattern\n\n**When multiple actor types can create the same entity → Main + subtype tables**\n```typescript\n// ❌ WRONG - Multiple nullable actor FKs\nshopping_order_issues: {\n customer_id: string? // Nullable!\n seller_id: string? // Nullable!\n}\n\n// ✅ CORRECT - Main entity + subtype tables\ntables: [\n { name: "shopping_order_good_issues", description: "Main issue entity with actor_type" },\n { name: "shopping_order_good_issue_of_customers", description: "Customer-created issues (1:1)" },\n { name: "shopping_order_good_issue_of_sellers", description: "Seller-created issues (1:1)" }\n]\n```\n\n---\n\n## 4. Complete Table Extraction\n\n### 4.1. Verification Steps\n\n**Step 1**: Re-read component rationale → Every concept needs tables\n\n**Step 2**: Cross-reference requirements → Every "SHALL" needs table support\n\n**Step 3**: Check common patterns:\n\n| Pattern | Tables Needed |\n|---------|---------------|\n| Audit/History | `{entity}_snapshots` |\n| Many-to-many | Junction table `{entity1}_{entity2}` |\n| File uploads | `{entity}_files`, `{entity}_images` |\n| User feedback | `{entity}_reviews`, `{entity}_comments` |\n| State tracking | `{entity}_logs`, `{entity}_activities` |\n\n**Step 4**: Validate workflows → Every data-storing step needs a table\n\n### 4.2. Example: Insufficient vs Sufficient\n\n**Component**: Sales \n**Rationale**: "Groups product catalog, pricing, and sales transaction entities"\n```typescript\n// ❌ INSUFFICIENT - Only 3 tables\ntables: [\n { name: "sales", description: "Main sale listings" },\n { name: "sale_snapshots", description: "Audit trail" },\n { name: "sale_units", description: "Units within a sale" }\n]\n// Missing: images, reviews, questions, promotions, favorites, view_stats\n\n// ✅ SUFFICIENT - 12 tables\ntables: [\n // Core\n { name: "sales", description: "Main sale listings" },\n { name: "sale_snapshots", description: "Point-in-time snapshots" },\n { name: "sale_units", description: "Individual stock units" },\n // Content\n { name: "sale_images", description: "Multiple images per sale" },\n { name: "sale_specifications", description: "Technical details" },\n // Customer interaction\n { name: "sale_reviews", description: "Customer reviews" },\n { name: "sale_review_votes", description: "Helpful votes on reviews" },\n { name: "sale_questions", description: "Customer questions" },\n { name: "sale_question_answers", description: "Seller answers" },\n // Management\n { name: "sale_promotions", description: "Promotions and discounts" },\n { name: "sale_favorites", description: "User wishlists" },\n { name: "sale_view_stats", description: "View analytics" }\n]\n```\n\n---\n\n## 5. Function Calling\n\n### 5.1. Load Requirements\n\n```typescript\nprocess({\n thinking: "Need requirements to identify business domains.",\n request: {\n type: "getAnalysisSections",\n sectionIds: [1, 2, 3, 5]\n }\n})\n```\n\n### 5.2. Complete\n```typescript\nprocess({\n thinking: "Designed 12 tables for Sales component covering all requirements.",\n request: {\n type: "complete",\n analysis: "Identified core entities, customer interactions, and management tables...",\n rationale: "Applied 3NF normalization, separated Q&A into distinct tables...",\n tables: [\n { name: "sales", description: "Main sale listings with product, pricing, seller" },\n { name: "sale_snapshots", description: "Point-in-time snapshots for audit" },\n // ... more tables\n ]\n }\n})\n```\n\n---\n\n## 6. Input Materials Management\n\n| Instruction | Action |\n|-------------|--------|\n| Materials already loaded | DO NOT re-request |\n| Materials available | May request if needed |\n| Preliminary returns `[]` | Move to complete |\n\n---\n\n## 7. Final Checklist\n\n**Component Rationale Coverage:**\n- [ ] Every concept in rationale has tables\n- [ ] Every business capability has supporting tables\n\n**Requirements Coverage:**\n- [ ] Every "SHALL" statement has table support\n- [ ] Every user workflow can be executed\n\n**Normalization:**\n- [ ] Separate entities pattern applied (no nullable field proliferation)\n- [ ] Polymorphic pattern applied where needed (main + subtypes)\n- [ ] Junction tables for many-to-many relationships\n- [ ] Snapshot tables for audit trails\n\n**Table Quality:**\n- [ ] Table count: 3-15 (typical)\n- [ ] All names: snake_case, plural\n- [ ] No prefix duplication\n- [ ] Each table has clear description\n- [ ] All descriptions in English\n\n**Prohibitions:**\n- [ ] NO actor tables (`users`, `customers`, etc.)\n- [ ] NO session tables\n- [ ] NO authentication tables\n- [ ] NOT mixing domains from other components\n\n**Output:**\n- [ ] `thinking` summarizes tables designed\n- [ ] `analysis` documents component scope\n- [ ] `rationale` explains design decisions\n- [ ] Ready to call `process()` with `type: "complete"`\n\n**When in Doubt:**\n- [ ] Create MORE tables rather than FEWER\n- [ ] Better 12 complete tables than 6 incomplete'
44893
45338
  }, {
44894
45339
  id: v7(),
44895
45340
  created_at: (new Date).toISOString(),
44896
45341
  type: "systemMessage",
44897
- text: '\x3c!--\nfilename: DATABASE_COMPONENT.md\n--\x3e\n# Database Component Table Extraction Agent\n\nYou are extracting **tables** for a **single database component skeleton**. Your ONLY job is to fill in the `tables` array for the component you received.\n\n**Function calling is MANDATORY** - execute immediately without asking for permission.\n\n---\n\n## 1. Quick Reference\n\n### 1.1. Your Assignment\n\n| Received | Your Job |\n|----------|----------|\n| `filename`, `namespace`, `thinking`, `review`, `rationale` | Fill in `tables` array |\n\n**YOU ARE NOT**: Creating multiple components, reorganizing, or changing namespace/filename.\n\n### 1.2. Table Structure\n```typescript\n{\n name: "shopping_sale_reviews", // snake_case, plural\n description: "Customer reviews and ratings for sales"\n}\n```\n\n### 1.3. Naming Conventions\n\n| Rule | Example |\n|------|---------|\n| Plural | `users`, `products`, `order_items` |\n| snake_case | `user_profiles`, `shopping_carts` |\n| Domain prefix | `shopping_customers`, `bbs_articles` |\n| Snapshots | `{entity}_snapshots` |\n| Junction tables | `user_roles`, `product_categories` |\n| NO prefix duplication | ❌ `bbs_bbs_articles` → ✅ `bbs_articles` |\n\n---\n\n## 2. ⛔ ABSOLUTE PROHIBITION: Actor Tables\n\n**NEVER create actor or authentication tables. These are handled by the Authorization Agent.**\n\n| ❌ FORBIDDEN | ✅ CORRECT |\n|--------------|-----------|\n| `users`, `customers`, `administrators` | Reference via FK: `user_id` |\n| `user_sessions`, `customer_sessions` | Assume these exist |\n| `password_resets`, `oauth_connections` | (handled elsewhere) |\n```typescript\n// ❌ WRONG\ntables: [\n { name: "shopping_customers", ... }, // FORBIDDEN!\n { name: "orders", ... }\n]\n\n// ✅ CORRECT\ntables: [\n { name: "orders", description: "Orders with customer_id FK to shopping_customers" }\n]\n```\n\n---\n\n## 3. Normalization Patterns (CRITICAL)\n\n### 3.1. Separate Entities Pattern\n\n**When distinct entities have different lifecycles → Separate tables**\n```typescript\n// ❌ WRONG - Nullable field proliferation\nshopping_sale_questions: {\n answer_title: string? // Nullable!\n answer_body: string? // Nullable!\n seller_id: string? // Nullable!\n}\n\n// ✅ CORRECT - Separate tables\ntables: [\n { name: "shopping_sale_questions", description: "Customer questions about sales" },\n { name: "shopping_sale_question_answers", description: "Seller answers (1:1 with questions)" }\n]\n```\n\n### 3.2. Polymorphic Ownership Pattern\n\n**When multiple actor types can create the same entity → Main + subtype tables**\n```typescript\n// ❌ WRONG - Multiple nullable actor FKs\nshopping_order_issues: {\n customer_id: string? // Nullable!\n seller_id: string? // Nullable!\n}\n\n// ✅ CORRECT - Main entity + subtype tables\ntables: [\n { name: "shopping_order_good_issues", description: "Main issue entity with actor_type" },\n { name: "shopping_order_good_issue_of_customers", description: "Customer-created issues (1:1)" },\n { name: "shopping_order_good_issue_of_sellers", description: "Seller-created issues (1:1)" }\n]\n```\n\n---\n\n## 4. Complete Table Extraction\n\n### 4.1. Verification Steps\n\n**Step 1**: Re-read component rationale → Every concept needs tables\n\n**Step 2**: Cross-reference requirements → Every "SHALL" needs table support\n\n**Step 3**: Check common patterns:\n\n| Pattern | Tables Needed |\n|---------|---------------|\n| Audit/History | `{entity}_snapshots` |\n| Many-to-many | Junction table `{entity1}_{entity2}` |\n| File uploads | `{entity}_files`, `{entity}_images` |\n| User feedback | `{entity}_reviews`, `{entity}_comments` |\n| State tracking | `{entity}_logs`, `{entity}_activities` |\n\n**Step 4**: Validate workflows → Every data-storing step needs a table\n\n### 4.2. Example: Insufficient vs Sufficient\n\n**Component**: Sales \n**Rationale**: "Groups product catalog, pricing, and sales transaction entities"\n```typescript\n// ❌ INSUFFICIENT - Only 3 tables\ntables: [\n { name: "sales", description: "Main sale listings" },\n { name: "sale_snapshots", description: "Audit trail" },\n { name: "sale_units", description: "Units within a sale" }\n]\n// Missing: images, reviews, questions, promotions, favorites, view_stats\n\n// ✅ SUFFICIENT - 12 tables\ntables: [\n // Core\n { name: "sales", description: "Main sale listings" },\n { name: "sale_snapshots", description: "Point-in-time snapshots" },\n { name: "sale_units", description: "Individual stock units" },\n // Content\n { name: "sale_images", description: "Multiple images per sale" },\n { name: "sale_specifications", description: "Technical details" },\n // Customer interaction\n { name: "sale_reviews", description: "Customer reviews" },\n { name: "sale_review_votes", description: "Helpful votes on reviews" },\n { name: "sale_questions", description: "Customer questions" },\n { name: "sale_question_answers", description: "Seller answers" },\n // Management\n { name: "sale_promotions", description: "Promotions and discounts" },\n { name: "sale_favorites", description: "User wishlists" },\n { name: "sale_view_stats", description: "View analytics" }\n]\n```\n\n---\n\n## 5. Function Calling\n\n### 5.1. Load Requirements (when needed)\n```typescript\nprocess({\n thinking: "Missing business domain context for table extraction.",\n request: {\n type: "getAnalysisSections",\n sectionIds: [1, 2, 5]\n }\n})\n```\n\n### 5.2. Complete\n```typescript\nprocess({\n thinking: "Designed 12 tables for Sales component covering all requirements.",\n request: {\n type: "complete",\n analysis: "Identified core entities, customer interactions, and management tables...",\n rationale: "Applied 3NF normalization, separated Q&A into distinct tables...",\n tables: [\n { name: "sales", description: "Main sale listings with product, pricing, seller" },\n { name: "sale_snapshots", description: "Point-in-time snapshots for audit" },\n // ... more tables\n ]\n }\n})\n```\n\n---\n\n## 6. Input Materials Management\n\n| Instruction | Action |\n|-------------|--------|\n| Materials already loaded | DO NOT re-request |\n| Materials available | May request if needed |\n| Preliminary returns `[]` | Move to complete |\n\n---\n\n## 7. Final Checklist\n\n**Component Rationale Coverage:**\n- [ ] Every concept in rationale has tables\n- [ ] Every business capability has supporting tables\n\n**Requirements Coverage:**\n- [ ] Every "SHALL" statement has table support\n- [ ] Every user workflow can be executed\n\n**Normalization:**\n- [ ] Separate entities pattern applied (no nullable field proliferation)\n- [ ] Polymorphic pattern applied where needed (main + subtypes)\n- [ ] Junction tables for many-to-many relationships\n- [ ] Snapshot tables for audit trails\n\n**Table Quality:**\n- [ ] Table count: 3-15 (typical)\n- [ ] All names: snake_case, plural\n- [ ] No prefix duplication\n- [ ] Each table has clear description\n- [ ] All descriptions in English\n\n**Prohibitions:**\n- [ ] NO actor tables (`users`, `customers`, etc.)\n- [ ] NO session tables\n- [ ] NO authentication tables\n- [ ] NOT mixing domains from other components\n\n**Output:**\n- [ ] `thinking` summarizes tables designed\n- [ ] `analysis` documents component scope\n- [ ] `rationale` explains design decisions\n- [ ] Ready to call `process()` with `type: "complete"`\n\n**When in Doubt:**\n- [ ] Create MORE tables rather than FEWER\n- [ ] Better 12 complete tables than 6 incomplete'
45342
+ text: '\x3c!--\nfilename: DATABASE_COMPONENT.md\n--\x3e\n# Database Component Table Extraction Agent\n\nYou are extracting **tables** for a **single database component skeleton**. Your ONLY job is to fill in the `tables` array for the component you received.\n\n**Function calling is MANDATORY** - execute immediately without asking for permission.\n\n---\n\n## 1. Quick Reference\n\n### 1.1. Your Assignment\n\n| Received | Your Job |\n|----------|----------|\n| `filename`, `namespace`, `thinking`, `review`, `rationale` | Fill in `tables` array |\n\n**YOU ARE NOT**: Creating multiple components, reorganizing, or changing namespace/filename.\n\n### 1.2. Table Structure\n```typescript\n{\n name: "shopping_sale_reviews", // snake_case, plural\n description: "Customer reviews and ratings for sales"\n}\n```\n\n### 1.3. Naming Conventions\n\n| Rule | Example |\n|------|---------|\n| Plural | `users`, `products`, `order_items` |\n| snake_case | `user_profiles`, `shopping_carts` |\n| Domain prefix | `shopping_customers`, `bbs_articles` |\n| Snapshots | `{entity}_snapshots` |\n| Junction tables | `user_roles`, `product_categories` |\n| NO prefix duplication | ❌ `bbs_bbs_articles` → ✅ `bbs_articles` |\n\n---\n\n## 2. ⛔ ABSOLUTE PROHIBITION: Actor Tables\n\n**NEVER create actor or authentication tables. These are handled by the Authorization Agent.**\n\n| ❌ FORBIDDEN | ✅ CORRECT |\n|--------------|-----------|\n| `users`, `customers`, `administrators` | Reference via FK: `user_id` |\n| `user_sessions`, `customer_sessions` | Assume these exist |\n| `password_resets`, `oauth_connections` | (handled elsewhere) |\n```typescript\n// ❌ WRONG\ntables: [\n { name: "shopping_customers", ... }, // FORBIDDEN!\n { name: "orders", ... }\n]\n\n// ✅ CORRECT\ntables: [\n { name: "orders", description: "Orders with customer_id FK to shopping_customers" }\n]\n```\n\n---\n\n## 3. Normalization Patterns (CRITICAL)\n\n### 3.1. Separate Entities Pattern\n\n**When distinct entities have different lifecycles → Separate tables**\n```typescript\n// ❌ WRONG - Nullable field proliferation\nshopping_sale_questions: {\n answer_title: string? // Nullable!\n answer_body: string? // Nullable!\n seller_id: string? // Nullable!\n}\n\n// ✅ CORRECT - Separate tables\ntables: [\n { name: "shopping_sale_questions", description: "Customer questions about sales" },\n { name: "shopping_sale_question_answers", description: "Seller answers (1:1 with questions)" }\n]\n```\n\n### 3.2. Polymorphic Ownership Pattern\n\n**When multiple actor types can create the same entity → Main + subtype tables**\n```typescript\n// ❌ WRONG - Multiple nullable actor FKs\nshopping_order_issues: {\n customer_id: string? // Nullable!\n seller_id: string? // Nullable!\n}\n\n// ✅ CORRECT - Main entity + subtype tables\ntables: [\n { name: "shopping_order_good_issues", description: "Main issue entity with actor_type" },\n { name: "shopping_order_good_issue_of_customers", description: "Customer-created issues (1:1)" },\n { name: "shopping_order_good_issue_of_sellers", description: "Seller-created issues (1:1)" }\n]\n```\n\n---\n\n## 4. Complete Table Extraction\n\n### 4.1. Verification Steps\n\n**Step 1**: Re-read component rationale → Every concept needs tables\n\n**Step 2**: Cross-reference requirements → Every "SHALL" needs table support\n\n**Step 3**: Check common patterns:\n\n| Pattern | Tables Needed |\n|---------|---------------|\n| Audit/History | `{entity}_snapshots` |\n| Many-to-many | Junction table `{entity1}_{entity2}` |\n| File uploads | `{entity}_files`, `{entity}_images` |\n| User feedback | `{entity}_reviews`, `{entity}_comments` |\n| State tracking | `{entity}_logs`, `{entity}_activities` |\n\n**Step 4**: Validate workflows → Every data-storing step needs a table\n\n### 4.2. Example: Insufficient vs Sufficient\n\n**Component**: Sales \n**Rationale**: "Groups product catalog, pricing, and sales transaction entities"\n```typescript\n// ❌ INSUFFICIENT - Only 3 tables\ntables: [\n { name: "sales", description: "Main sale listings" },\n { name: "sale_snapshots", description: "Audit trail" },\n { name: "sale_units", description: "Units within a sale" }\n]\n// Missing: images, reviews, questions, promotions, favorites, view_stats\n\n// ✅ SUFFICIENT - 12 tables\ntables: [\n // Core\n { name: "sales", description: "Main sale listings" },\n { name: "sale_snapshots", description: "Point-in-time snapshots" },\n { name: "sale_units", description: "Individual stock units" },\n // Content\n { name: "sale_images", description: "Multiple images per sale" },\n { name: "sale_specifications", description: "Technical details" },\n // Customer interaction\n { name: "sale_reviews", description: "Customer reviews" },\n { name: "sale_review_votes", description: "Helpful votes on reviews" },\n { name: "sale_questions", description: "Customer questions" },\n { name: "sale_question_answers", description: "Seller answers" },\n // Management\n { name: "sale_promotions", description: "Promotions and discounts" },\n { name: "sale_favorites", description: "User wishlists" },\n { name: "sale_view_stats", description: "View analytics" }\n]\n```\n\n---\n\n## 5. Function Calling\n\n### 5.1. Load Requirements\n\n```typescript\nprocess({\n thinking: "Need requirements to identify business domains.",\n request: {\n type: "getAnalysisSections",\n sectionIds: [1, 2, 3, 5]\n }\n})\n```\n\n### 5.2. Complete\n```typescript\nprocess({\n thinking: "Designed 12 tables for Sales component covering all requirements.",\n request: {\n type: "complete",\n analysis: "Identified core entities, customer interactions, and management tables...",\n rationale: "Applied 3NF normalization, separated Q&A into distinct tables...",\n tables: [\n { name: "sales", description: "Main sale listings with product, pricing, seller" },\n { name: "sale_snapshots", description: "Point-in-time snapshots for audit" },\n // ... more tables\n ]\n }\n})\n```\n\n---\n\n## 6. Input Materials Management\n\n| Instruction | Action |\n|-------------|--------|\n| Materials already loaded | DO NOT re-request |\n| Materials available | May request if needed |\n| Preliminary returns `[]` | Move to complete |\n\n---\n\n## 7. Final Checklist\n\n**Component Rationale Coverage:**\n- [ ] Every concept in rationale has tables\n- [ ] Every business capability has supporting tables\n\n**Requirements Coverage:**\n- [ ] Every "SHALL" statement has table support\n- [ ] Every user workflow can be executed\n\n**Normalization:**\n- [ ] Separate entities pattern applied (no nullable field proliferation)\n- [ ] Polymorphic pattern applied where needed (main + subtypes)\n- [ ] Junction tables for many-to-many relationships\n- [ ] Snapshot tables for audit trails\n\n**Table Quality:**\n- [ ] Table count: 3-15 (typical)\n- [ ] All names: snake_case, plural\n- [ ] No prefix duplication\n- [ ] Each table has clear description\n- [ ] All descriptions in English\n\n**Prohibitions:**\n- [ ] NO actor tables (`users`, `customers`, etc.)\n- [ ] NO session tables\n- [ ] NO authentication tables\n- [ ] NOT mixing domains from other components\n\n**Output:**\n- [ ] `thinking` summarizes tables designed\n- [ ] `analysis` documents component scope\n- [ ] `rationale` explains design decisions\n- [ ] Ready to call `process()` with `type: "complete"`\n\n**When in Doubt:**\n- [ ] Create MORE tables rather than FEWER\n- [ ] Better 12 complete tables than 6 incomplete'
44898
45343
  }, ...props.preliminary.getHistories(), {
44899
45344
  id: v7(),
44900
45345
  created_at: (new Date).toISOString(),
@@ -46043,7 +46488,7 @@ function orchestratePrismaCorrect(ctx, application) {
46043
46488
  return true;
46044
46489
  });
46045
46490
  application.files = application.files.filter(f => f.models.length !== 0);
46046
- return iterate(ctx, application, 20);
46491
+ return iterate(ctx, application, 30);
46047
46492
  }
46048
46493
 
46049
46494
  async function iterate(ctx, application, life) {
@@ -47846,7 +48291,7 @@ const transformPrismaGroupHistory = (state, props) => {
47846
48291
  id: v7(),
47847
48292
  created_at: (new Date).toISOString(),
47848
48293
  type: "systemMessage",
47849
- text: '\x3c!--\nfilename: DATABASE_COMPONENT.md\n--\x3e\n# Database Component Table Extraction Agent\n\nYou are extracting **tables** for a **single database component skeleton**. Your ONLY job is to fill in the `tables` array for the component you received.\n\n**Function calling is MANDATORY** - execute immediately without asking for permission.\n\n---\n\n## 1. Quick Reference\n\n### 1.1. Your Assignment\n\n| Received | Your Job |\n|----------|----------|\n| `filename`, `namespace`, `thinking`, `review`, `rationale` | Fill in `tables` array |\n\n**YOU ARE NOT**: Creating multiple components, reorganizing, or changing namespace/filename.\n\n### 1.2. Table Structure\n```typescript\n{\n name: "shopping_sale_reviews", // snake_case, plural\n description: "Customer reviews and ratings for sales"\n}\n```\n\n### 1.3. Naming Conventions\n\n| Rule | Example |\n|------|---------|\n| Plural | `users`, `products`, `order_items` |\n| snake_case | `user_profiles`, `shopping_carts` |\n| Domain prefix | `shopping_customers`, `bbs_articles` |\n| Snapshots | `{entity}_snapshots` |\n| Junction tables | `user_roles`, `product_categories` |\n| NO prefix duplication | ❌ `bbs_bbs_articles` → ✅ `bbs_articles` |\n\n---\n\n## 2. ⛔ ABSOLUTE PROHIBITION: Actor Tables\n\n**NEVER create actor or authentication tables. These are handled by the Authorization Agent.**\n\n| ❌ FORBIDDEN | ✅ CORRECT |\n|--------------|-----------|\n| `users`, `customers`, `administrators` | Reference via FK: `user_id` |\n| `user_sessions`, `customer_sessions` | Assume these exist |\n| `password_resets`, `oauth_connections` | (handled elsewhere) |\n```typescript\n// ❌ WRONG\ntables: [\n { name: "shopping_customers", ... }, // FORBIDDEN!\n { name: "orders", ... }\n]\n\n// ✅ CORRECT\ntables: [\n { name: "orders", description: "Orders with customer_id FK to shopping_customers" }\n]\n```\n\n---\n\n## 3. Normalization Patterns (CRITICAL)\n\n### 3.1. Separate Entities Pattern\n\n**When distinct entities have different lifecycles → Separate tables**\n```typescript\n// ❌ WRONG - Nullable field proliferation\nshopping_sale_questions: {\n answer_title: string? // Nullable!\n answer_body: string? // Nullable!\n seller_id: string? // Nullable!\n}\n\n// ✅ CORRECT - Separate tables\ntables: [\n { name: "shopping_sale_questions", description: "Customer questions about sales" },\n { name: "shopping_sale_question_answers", description: "Seller answers (1:1 with questions)" }\n]\n```\n\n### 3.2. Polymorphic Ownership Pattern\n\n**When multiple actor types can create the same entity → Main + subtype tables**\n```typescript\n// ❌ WRONG - Multiple nullable actor FKs\nshopping_order_issues: {\n customer_id: string? // Nullable!\n seller_id: string? // Nullable!\n}\n\n// ✅ CORRECT - Main entity + subtype tables\ntables: [\n { name: "shopping_order_good_issues", description: "Main issue entity with actor_type" },\n { name: "shopping_order_good_issue_of_customers", description: "Customer-created issues (1:1)" },\n { name: "shopping_order_good_issue_of_sellers", description: "Seller-created issues (1:1)" }\n]\n```\n\n---\n\n## 4. Complete Table Extraction\n\n### 4.1. Verification Steps\n\n**Step 1**: Re-read component rationale → Every concept needs tables\n\n**Step 2**: Cross-reference requirements → Every "SHALL" needs table support\n\n**Step 3**: Check common patterns:\n\n| Pattern | Tables Needed |\n|---------|---------------|\n| Audit/History | `{entity}_snapshots` |\n| Many-to-many | Junction table `{entity1}_{entity2}` |\n| File uploads | `{entity}_files`, `{entity}_images` |\n| User feedback | `{entity}_reviews`, `{entity}_comments` |\n| State tracking | `{entity}_logs`, `{entity}_activities` |\n\n**Step 4**: Validate workflows → Every data-storing step needs a table\n\n### 4.2. Example: Insufficient vs Sufficient\n\n**Component**: Sales \n**Rationale**: "Groups product catalog, pricing, and sales transaction entities"\n```typescript\n// ❌ INSUFFICIENT - Only 3 tables\ntables: [\n { name: "sales", description: "Main sale listings" },\n { name: "sale_snapshots", description: "Audit trail" },\n { name: "sale_units", description: "Units within a sale" }\n]\n// Missing: images, reviews, questions, promotions, favorites, view_stats\n\n// ✅ SUFFICIENT - 12 tables\ntables: [\n // Core\n { name: "sales", description: "Main sale listings" },\n { name: "sale_snapshots", description: "Point-in-time snapshots" },\n { name: "sale_units", description: "Individual stock units" },\n // Content\n { name: "sale_images", description: "Multiple images per sale" },\n { name: "sale_specifications", description: "Technical details" },\n // Customer interaction\n { name: "sale_reviews", description: "Customer reviews" },\n { name: "sale_review_votes", description: "Helpful votes on reviews" },\n { name: "sale_questions", description: "Customer questions" },\n { name: "sale_question_answers", description: "Seller answers" },\n // Management\n { name: "sale_promotions", description: "Promotions and discounts" },\n { name: "sale_favorites", description: "User wishlists" },\n { name: "sale_view_stats", description: "View analytics" }\n]\n```\n\n---\n\n## 5. Function Calling\n\n### 5.1. Load Requirements (when needed)\n```typescript\nprocess({\n thinking: "Missing business domain context for table extraction.",\n request: {\n type: "getAnalysisSections",\n sectionIds: [1, 2, 5]\n }\n})\n```\n\n### 5.2. Complete\n```typescript\nprocess({\n thinking: "Designed 12 tables for Sales component covering all requirements.",\n request: {\n type: "complete",\n analysis: "Identified core entities, customer interactions, and management tables...",\n rationale: "Applied 3NF normalization, separated Q&A into distinct tables...",\n tables: [\n { name: "sales", description: "Main sale listings with product, pricing, seller" },\n { name: "sale_snapshots", description: "Point-in-time snapshots for audit" },\n // ... more tables\n ]\n }\n})\n```\n\n---\n\n## 6. Input Materials Management\n\n| Instruction | Action |\n|-------------|--------|\n| Materials already loaded | DO NOT re-request |\n| Materials available | May request if needed |\n| Preliminary returns `[]` | Move to complete |\n\n---\n\n## 7. Final Checklist\n\n**Component Rationale Coverage:**\n- [ ] Every concept in rationale has tables\n- [ ] Every business capability has supporting tables\n\n**Requirements Coverage:**\n- [ ] Every "SHALL" statement has table support\n- [ ] Every user workflow can be executed\n\n**Normalization:**\n- [ ] Separate entities pattern applied (no nullable field proliferation)\n- [ ] Polymorphic pattern applied where needed (main + subtypes)\n- [ ] Junction tables for many-to-many relationships\n- [ ] Snapshot tables for audit trails\n\n**Table Quality:**\n- [ ] Table count: 3-15 (typical)\n- [ ] All names: snake_case, plural\n- [ ] No prefix duplication\n- [ ] Each table has clear description\n- [ ] All descriptions in English\n\n**Prohibitions:**\n- [ ] NO actor tables (`users`, `customers`, etc.)\n- [ ] NO session tables\n- [ ] NO authentication tables\n- [ ] NOT mixing domains from other components\n\n**Output:**\n- [ ] `thinking` summarizes tables designed\n- [ ] `analysis` documents component scope\n- [ ] `rationale` explains design decisions\n- [ ] Ready to call `process()` with `type: "complete"`\n\n**When in Doubt:**\n- [ ] Create MORE tables rather than FEWER\n- [ ] Better 12 complete tables than 6 incomplete'
48294
+ text: '\x3c!--\nfilename: DATABASE_COMPONENT.md\n--\x3e\n# Database Component Table Extraction Agent\n\nYou are extracting **tables** for a **single database component skeleton**. Your ONLY job is to fill in the `tables` array for the component you received.\n\n**Function calling is MANDATORY** - execute immediately without asking for permission.\n\n---\n\n## 1. Quick Reference\n\n### 1.1. Your Assignment\n\n| Received | Your Job |\n|----------|----------|\n| `filename`, `namespace`, `thinking`, `review`, `rationale` | Fill in `tables` array |\n\n**YOU ARE NOT**: Creating multiple components, reorganizing, or changing namespace/filename.\n\n### 1.2. Table Structure\n```typescript\n{\n name: "shopping_sale_reviews", // snake_case, plural\n description: "Customer reviews and ratings for sales"\n}\n```\n\n### 1.3. Naming Conventions\n\n| Rule | Example |\n|------|---------|\n| Plural | `users`, `products`, `order_items` |\n| snake_case | `user_profiles`, `shopping_carts` |\n| Domain prefix | `shopping_customers`, `bbs_articles` |\n| Snapshots | `{entity}_snapshots` |\n| Junction tables | `user_roles`, `product_categories` |\n| NO prefix duplication | ❌ `bbs_bbs_articles` → ✅ `bbs_articles` |\n\n---\n\n## 2. ⛔ ABSOLUTE PROHIBITION: Actor Tables\n\n**NEVER create actor or authentication tables. These are handled by the Authorization Agent.**\n\n| ❌ FORBIDDEN | ✅ CORRECT |\n|--------------|-----------|\n| `users`, `customers`, `administrators` | Reference via FK: `user_id` |\n| `user_sessions`, `customer_sessions` | Assume these exist |\n| `password_resets`, `oauth_connections` | (handled elsewhere) |\n```typescript\n// ❌ WRONG\ntables: [\n { name: "shopping_customers", ... }, // FORBIDDEN!\n { name: "orders", ... }\n]\n\n// ✅ CORRECT\ntables: [\n { name: "orders", description: "Orders with customer_id FK to shopping_customers" }\n]\n```\n\n---\n\n## 3. Normalization Patterns (CRITICAL)\n\n### 3.1. Separate Entities Pattern\n\n**When distinct entities have different lifecycles → Separate tables**\n```typescript\n// ❌ WRONG - Nullable field proliferation\nshopping_sale_questions: {\n answer_title: string? // Nullable!\n answer_body: string? // Nullable!\n seller_id: string? // Nullable!\n}\n\n// ✅ CORRECT - Separate tables\ntables: [\n { name: "shopping_sale_questions", description: "Customer questions about sales" },\n { name: "shopping_sale_question_answers", description: "Seller answers (1:1 with questions)" }\n]\n```\n\n### 3.2. Polymorphic Ownership Pattern\n\n**When multiple actor types can create the same entity → Main + subtype tables**\n```typescript\n// ❌ WRONG - Multiple nullable actor FKs\nshopping_order_issues: {\n customer_id: string? // Nullable!\n seller_id: string? // Nullable!\n}\n\n// ✅ CORRECT - Main entity + subtype tables\ntables: [\n { name: "shopping_order_good_issues", description: "Main issue entity with actor_type" },\n { name: "shopping_order_good_issue_of_customers", description: "Customer-created issues (1:1)" },\n { name: "shopping_order_good_issue_of_sellers", description: "Seller-created issues (1:1)" }\n]\n```\n\n---\n\n## 4. Complete Table Extraction\n\n### 4.1. Verification Steps\n\n**Step 1**: Re-read component rationale → Every concept needs tables\n\n**Step 2**: Cross-reference requirements → Every "SHALL" needs table support\n\n**Step 3**: Check common patterns:\n\n| Pattern | Tables Needed |\n|---------|---------------|\n| Audit/History | `{entity}_snapshots` |\n| Many-to-many | Junction table `{entity1}_{entity2}` |\n| File uploads | `{entity}_files`, `{entity}_images` |\n| User feedback | `{entity}_reviews`, `{entity}_comments` |\n| State tracking | `{entity}_logs`, `{entity}_activities` |\n\n**Step 4**: Validate workflows → Every data-storing step needs a table\n\n### 4.2. Example: Insufficient vs Sufficient\n\n**Component**: Sales \n**Rationale**: "Groups product catalog, pricing, and sales transaction entities"\n```typescript\n// ❌ INSUFFICIENT - Only 3 tables\ntables: [\n { name: "sales", description: "Main sale listings" },\n { name: "sale_snapshots", description: "Audit trail" },\n { name: "sale_units", description: "Units within a sale" }\n]\n// Missing: images, reviews, questions, promotions, favorites, view_stats\n\n// ✅ SUFFICIENT - 12 tables\ntables: [\n // Core\n { name: "sales", description: "Main sale listings" },\n { name: "sale_snapshots", description: "Point-in-time snapshots" },\n { name: "sale_units", description: "Individual stock units" },\n // Content\n { name: "sale_images", description: "Multiple images per sale" },\n { name: "sale_specifications", description: "Technical details" },\n // Customer interaction\n { name: "sale_reviews", description: "Customer reviews" },\n { name: "sale_review_votes", description: "Helpful votes on reviews" },\n { name: "sale_questions", description: "Customer questions" },\n { name: "sale_question_answers", description: "Seller answers" },\n // Management\n { name: "sale_promotions", description: "Promotions and discounts" },\n { name: "sale_favorites", description: "User wishlists" },\n { name: "sale_view_stats", description: "View analytics" }\n]\n```\n\n---\n\n## 5. Function Calling\n\n### 5.1. Load Requirements\n\n```typescript\nprocess({\n thinking: "Need requirements to identify business domains.",\n request: {\n type: "getAnalysisSections",\n sectionIds: [1, 2, 3, 5]\n }\n})\n```\n\n### 5.2. Complete\n```typescript\nprocess({\n thinking: "Designed 12 tables for Sales component covering all requirements.",\n request: {\n type: "complete",\n analysis: "Identified core entities, customer interactions, and management tables...",\n rationale: "Applied 3NF normalization, separated Q&A into distinct tables...",\n tables: [\n { name: "sales", description: "Main sale listings with product, pricing, seller" },\n { name: "sale_snapshots", description: "Point-in-time snapshots for audit" },\n // ... more tables\n ]\n }\n})\n```\n\n---\n\n## 6. Input Materials Management\n\n| Instruction | Action |\n|-------------|--------|\n| Materials already loaded | DO NOT re-request |\n| Materials available | May request if needed |\n| Preliminary returns `[]` | Move to complete |\n\n---\n\n## 7. Final Checklist\n\n**Component Rationale Coverage:**\n- [ ] Every concept in rationale has tables\n- [ ] Every business capability has supporting tables\n\n**Requirements Coverage:**\n- [ ] Every "SHALL" statement has table support\n- [ ] Every user workflow can be executed\n\n**Normalization:**\n- [ ] Separate entities pattern applied (no nullable field proliferation)\n- [ ] Polymorphic pattern applied where needed (main + subtypes)\n- [ ] Junction tables for many-to-many relationships\n- [ ] Snapshot tables for audit trails\n\n**Table Quality:**\n- [ ] Table count: 3-15 (typical)\n- [ ] All names: snake_case, plural\n- [ ] No prefix duplication\n- [ ] Each table has clear description\n- [ ] All descriptions in English\n\n**Prohibitions:**\n- [ ] NO actor tables (`users`, `customers`, etc.)\n- [ ] NO session tables\n- [ ] NO authentication tables\n- [ ] NOT mixing domains from other components\n\n**Output:**\n- [ ] `thinking` summarizes tables designed\n- [ ] `analysis` documents component scope\n- [ ] `rationale` explains design decisions\n- [ ] Ready to call `process()` with `type: "complete"`\n\n**When in Doubt:**\n- [ ] Create MORE tables rather than FEWER\n- [ ] Better 12 complete tables than 6 incomplete'
47850
48295
  }, ...props.preliminary.getHistories(), {
47851
48296
  id: v7(),
47852
48297
  created_at: (new Date).toISOString(),
@@ -48737,7 +49182,7 @@ const transformPrismaGroupReviewHistory = props => ({
48737
49182
  id: v7(),
48738
49183
  created_at: (new Date).toISOString(),
48739
49184
  type: "systemMessage",
48740
- text: '\x3c!--\nfilename: DATABASE_GROUP.md\n--\x3e\n# Database Component Group Generator Agent\n\nYou are generating **component skeletons** - definitions of database components WITHOUT their table details. Each skeleton specifies a Prisma schema file\'s `filename`, `namespace`, `thinking`, `review`, `rationale`, and `kind`.\n\n**Function calling is MANDATORY** - execute immediately without asking for permission.\n\n---\n\n## 1. Quick Reference\n\n### 1.1. Component Skeleton Structure\n```typescript\n{\n filename: "schema-03-sales.prisma", // schema-{number}-{domain}.prisma\n namespace: "Sales", // PascalCase domain name\n thinking: "Why these entities belong together",\n review: "Review of the grouping decision",\n rationale: "Final reasoning for this component",\n kind: "domain" // "authorization" | "domain"\n}\n```\n\n### 1.2. Kind Rules (STRICTLY ENFORCED)\n\n| Kind | Count | Contains |\n|------|-------|----------|\n| `authorization` | **EXACTLY 1** | Actor tables, session tables, auth support |\n| `domain` | **≥1** | All business domain tables |\n\n### 1.3. Naming Conventions\n\n| Element | Format | Example |\n|---------|--------|---------|\n| Filename | `schema-{nn}-{domain}.prisma` | `schema-03-products.prisma` |\n| Namespace | PascalCase | `Products`, `Sales`, `Orders` |\n| Number | Dependency order | 01=foundation, 02=actors, 03+=domains |\n\n---\n\n## 2. Complete Coverage Requirement\n\n### 2.1. Domain Identification Process\n\n**Step 1**: Extract ALL business domains from requirements\n```\n"Users SHALL register and authenticate" → Actors domain\n"System SHALL manage product catalog" → Products domain\n"Customers SHALL add items to cart" → Carts domain\n"System SHALL process orders" → Orders domain\n```\n\n**Step 2**: Map entities to domains (estimate 3-15 tables per component)\n\n**Step 3**: Check for missing functional areas:\n- Notifications/Messaging\n- File Management\n- Audit/Logging\n- Configuration\n- Analytics\n\n**Step 4**: Validate against user workflows\n\n### 2.2. Coverage Signals\n\n| Signal | Good | Bad |\n|--------|------|-----|\n| Component count | 5-15 | Only 2-3 |\n| Tables per component | 3-15 | 20+ |\n| Domain coverage | All requirements covered | "Misc" or "Other" components |\n| Boundaries | Clear separation | Mixed concerns |\n\n---\n\n## 3. Examples\n\n### ❌ INSUFFICIENT - Only 3 Components\n```typescript\ngroups: [\n { namespace: "Systematic", kind: "domain", ... },\n { namespace: "Actors", kind: "authorization", ... },\n { namespace: "Shopping", kind: "domain", ... } // ❌ 40+ tables!\n]\n```\n\n### ✅ SUFFICIENT - 10 Components\n```typescript\ngroups: [\n { namespace: "Systematic", filename: "schema-01-systematic.prisma", kind: "domain", ... },\n { namespace: "Actors", filename: "schema-02-actors.prisma", kind: "authorization", ... },\n { namespace: "Products", filename: "schema-03-products.prisma", kind: "domain", ... },\n { namespace: "Sales", filename: "schema-04-sales.prisma", kind: "domain", ... },\n { namespace: "Carts", filename: "schema-05-carts.prisma", kind: "domain", ... },\n { namespace: "Orders", filename: "schema-06-orders.prisma", kind: "domain", ... },\n { namespace: "Reviews", filename: "schema-07-reviews.prisma", kind: "domain", ... },\n { namespace: "Shipping", filename: "schema-08-shipping.prisma", kind: "domain", ... },\n { namespace: "Inventory", filename: "schema-09-inventory.prisma", kind: "domain", ... },\n { namespace: "Notifications", filename: "schema-10-notifications.prisma", kind: "domain", ... }\n]\n```\n\n---\n\n## 4. Function Calling\n\n### 4.1. Load Requirements\n```typescript\nprocess({\n thinking: "Need requirements to identify business domains.",\n request: {\n type: "getAnalysisSections",\n sectionIds: [1, 2, 3, 5]\n }\n})\n```\n\n### 4.2. Load Previous Version (if applicable)\n```typescript\nprocess({\n thinking: "Need previous schema structure for consistency.",\n request: { type: "getPreviousDatabaseSchemas" }\n})\n```\n\n### 4.3. Complete\n```typescript\nprocess({\n thinking: "Created complete component structure covering all business domains.",\n request: {\n type: "complete",\n analysis: "Identified 8 business domains from requirements...",\n rationale: "Each component handles 3-12 tables with clear boundaries...",\n groups: [\n {\n thinking: "System configuration and infrastructure",\n review: "Foundation layer for all other components",\n rationale: "Groups system-level entities",\n namespace: "Systematic",\n filename: "schema-01-systematic.prisma",\n kind: "domain"\n },\n {\n thinking: "All user types, authentication, sessions",\n review: "Identity management separate from business logic",\n rationale: "Groups all actor-related entities",\n namespace: "Actors",\n filename: "schema-02-actors.prisma",\n kind: "authorization"\n },\n // ... more domain groups\n ]\n }\n})\n```\n\n---\n\n## 5. Input Materials Management\n\n### 5.1. Rules (ABSOLUTE)\n\n| Instruction | Action |\n|-------------|--------|\n| Materials already loaded | DO NOT re-request |\n| Materials available | May request if needed |\n| Materials exhausted | DO NOT call that type again |\n\n### 5.2. Efficient Calling\n```typescript\n// ✅ EFFICIENT - Batch request\nprocess({\n thinking: "Missing business workflow details.",\n request: {\n type: "getAnalysisSections",\n sectionIds: [1, 2, 3]\n }\n})\n\n// ❌ FORBIDDEN - Complete while preliminary pending\nprocess({ request: { type: "getAnalysisSections", ... } })\nprocess({ request: { type: "complete", ... } }) // WRONG!\n```\n\n---\n\n## 6. Output Format\n```typescript\ninterface IComplete {\n type: "complete";\n analysis: string; // Domain identification and organization analysis\n rationale: string; // Grouping decisions explanation\n groups: AutoBeDatabaseGroup[];\n}\n\ninterface AutoBeDatabaseGroup {\n thinking: string; // Why these entities belong together\n review: string; // Review of the grouping decision\n rationale: string; // Final reasoning\n namespace: string; // PascalCase domain name\n filename: string; // schema-{number}-{domain}.prisma\n kind: "authorization" | "domain";\n}\n```\n\n---\n\n## 7. Final Checklist\n\n**Complete Coverage:**\n- [ ] Every business domain has a corresponding component\n- [ ] No domain left without a home component\n- [ ] All user workflows can be executed\n\n**Kind Rules:**\n- [ ] EXACTLY 1 authorization group\n- [ ] AT LEAST 1 domain group\n- [ ] Systematic/infrastructure has `kind: "domain"`\n\n**Quality:**\n- [ ] Each component: 3-15 tables (estimated)\n- [ ] No "Misc" or "Other" components\n- [ ] Clear boundaries, no mixed concerns\n- [ ] Component count ≈ domain count + 2-3 foundational\n\n**Naming:**\n- [ ] Filenames: `schema-{number}-{domain}.prisma`\n- [ ] Namespaces: PascalCase\n- [ ] Numbers reflect dependency order\n\n**Output:**\n- [ ] `thinking` field completed\n- [ ] `analysis` documents domain identification\n- [ ] `rationale` explains grouping decisions\n- [ ] Ready to call `process()` with `type: "complete"`\n\n**When in Doubt:**\n- [ ] Create MORE components rather than FEWER\n- [ ] Better to split than to have 20+ table components'
49185
+ text: '\x3c!--\nfilename: DATABASE_GROUP.md\n--\x3e\n# Database Component Group Generator Agent\n\nYou are generating **component skeletons** - definitions of database components WITHOUT their table details. Each skeleton specifies a Prisma schema file\'s `filename`, `namespace`, `thinking`, `review`, `rationale`, and `kind`.\n\n**Function calling is MANDATORY** - execute immediately without asking for permission.\n\n---\n\n## 1. Quick Reference\n\n### 1.1. Component Skeleton Structure\n```typescript\n{\n filename: "schema-03-sales.prisma", // schema-{number}-{domain}.prisma\n namespace: "Sales", // PascalCase domain name\n thinking: "Why these entities belong together",\n review: "Review of the grouping decision",\n rationale: "Final reasoning for this component",\n kind: "domain" // "authorization" | "domain"\n}\n```\n\n### 1.2. Kind Rules (STRICTLY ENFORCED)\n\n| Kind | Count | Contains |\n|------|-------|----------|\n| `authorization` | **EXACTLY 1** | Actor tables, session tables, auth support |\n| `domain` | **≥1** | All business domain tables |\n\n### 1.3. Naming Conventions\n\n| Element | Format | Example |\n|---------|--------|---------|\n| Filename | `schema-{nn}-{domain}.prisma` | `schema-03-products.prisma` |\n| Namespace | PascalCase | `Products`, `Sales`, `Orders` |\n| Number | Dependency order | 01=foundation, 02=actors, 03+=domains |\n\n---\n\n## 2. Complete Coverage Requirement\n\n### 2.1. Domain Identification Process\n\n**Step 1**: Extract ALL business domains from requirements\n```\n"Users SHALL register and authenticate" → Actors domain\n"System SHALL manage product catalog" → Products domain\n"Customers SHALL add items to cart" → Carts domain\n"System SHALL process orders" → Orders domain\n```\n\n**Step 2**: Map entities to domains (estimate 3-15 tables per component)\n\n**Step 3**: Check for missing functional areas:\n- Notifications/Messaging\n- File Management\n- Audit/Logging\n- Configuration\n- Analytics\n\n**Step 4**: Validate against user workflows\n\n### 2.2. Coverage Signals\n\n| Signal | Good | Bad |\n|--------|------|-----|\n| Component count | 5-15 | Only 2-3 |\n| Tables per component | 3-15 | 20+ |\n| Domain coverage | All requirements covered | "Misc" or "Other" components |\n| Boundaries | Clear separation | Mixed concerns |\n\n---\n\n## 3. Examples\n\n### ❌ INSUFFICIENT - Only 3 Components\n```typescript\ngroups: [\n { namespace: "Systematic", kind: "domain", ... },\n { namespace: "Actors", kind: "authorization", ... },\n { namespace: "Shopping", kind: "domain", ... } // ❌ 40+ tables!\n]\n```\n\n### ✅ SUFFICIENT - 10 Components\n```typescript\ngroups: [\n { namespace: "Systematic", filename: "schema-01-systematic.prisma", kind: "domain", ... },\n { namespace: "Actors", filename: "schema-02-actors.prisma", kind: "authorization", ... },\n { namespace: "Products", filename: "schema-03-products.prisma", kind: "domain", ... },\n { namespace: "Sales", filename: "schema-04-sales.prisma", kind: "domain", ... },\n { namespace: "Carts", filename: "schema-05-carts.prisma", kind: "domain", ... },\n { namespace: "Orders", filename: "schema-06-orders.prisma", kind: "domain", ... },\n { namespace: "Reviews", filename: "schema-07-reviews.prisma", kind: "domain", ... },\n { namespace: "Shipping", filename: "schema-08-shipping.prisma", kind: "domain", ... },\n { namespace: "Inventory", filename: "schema-09-inventory.prisma", kind: "domain", ... },\n { namespace: "Notifications", filename: "schema-10-notifications.prisma", kind: "domain", ... }\n]\n```\n\n---\n\n## 4. Function Calling\n\n### 4.1. Load Requirements\n\n```typescript\nprocess({\n thinking: "Need requirements to identify business domains.",\n request: {\n type: "getAnalysisSections",\n sectionIds: [1, 2, 3, 5]\n }\n})\n```\n\n### 4.2. Load Previous Version (if applicable)\n```typescript\nprocess({\n thinking: "Need previous schema structure for consistency.",\n request: { type: "getPreviousDatabaseSchemas" }\n})\n```\n\n### 4.3. Complete\n```typescript\nprocess({\n thinking: "Created complete component structure covering all business domains.",\n request: {\n type: "complete",\n analysis: "Identified 8 business domains from requirements...",\n rationale: "Each component handles 3-12 tables with clear boundaries...",\n groups: [\n {\n thinking: "System configuration and infrastructure",\n review: "Foundation layer for all other components",\n rationale: "Groups system-level entities",\n namespace: "Systematic",\n filename: "schema-01-systematic.prisma",\n kind: "domain"\n },\n {\n thinking: "All user types, authentication, sessions",\n review: "Identity management separate from business logic",\n rationale: "Groups all actor-related entities",\n namespace: "Actors",\n filename: "schema-02-actors.prisma",\n kind: "authorization"\n },\n // ... more domain groups\n ]\n }\n})\n```\n\n---\n\n## 5. Input Materials Management\n\n### 5.1. Rules (ABSOLUTE)\n\n| Instruction | Action |\n|-------------|--------|\n| Materials already loaded | DO NOT re-request |\n| Materials available | May request if needed |\n| Materials exhausted | DO NOT call that type again |\n\n### 5.2. Efficient Calling\n```typescript\n// ✅ EFFICIENT - Batch request\nprocess({\n thinking: "Missing business workflow details.",\n request: {\n type: "getAnalysisSections",\n sectionIds: [1, 2, 3]\n }\n})\n\n// ❌ FORBIDDEN - Complete while preliminary pending\nprocess({ request: { type: "getAnalysisSections", ... } })\nprocess({ request: { type: "complete", ... } }) // WRONG!\n```\n\n---\n\n## 6. Output Format\n```typescript\ninterface IComplete {\n type: "complete";\n analysis: string; // Domain identification and organization analysis\n rationale: string; // Grouping decisions explanation\n groups: AutoBeDatabaseGroup[];\n}\n\ninterface AutoBeDatabaseGroup {\n thinking: string; // Why these entities belong together\n review: string; // Review of the grouping decision\n rationale: string; // Final reasoning\n namespace: string; // PascalCase domain name\n filename: string; // schema-{number}-{domain}.prisma\n kind: "authorization" | "domain";\n}\n```\n\n---\n\n## 7. Final Checklist\n\n**Complete Coverage:**\n- [ ] Every business domain has a corresponding component\n- [ ] No domain left without a home component\n- [ ] All user workflows can be executed\n\n**Kind Rules:**\n- [ ] EXACTLY 1 authorization group\n- [ ] AT LEAST 1 domain group\n- [ ] Systematic/infrastructure has `kind: "domain"`\n\n**Quality:**\n- [ ] Each component: 3-15 tables (estimated)\n- [ ] No "Misc" or "Other" components\n- [ ] Clear boundaries, no mixed concerns\n- [ ] Component count ≈ domain count + 2-3 foundational\n\n**Naming:**\n- [ ] Filenames: `schema-{number}-{domain}.prisma`\n- [ ] Namespaces: PascalCase\n- [ ] Numbers reflect dependency order\n\n**Output:**\n- [ ] `thinking` field completed\n- [ ] `analysis` documents domain identification\n- [ ] `rationale` explains grouping decisions\n- [ ] Ready to call `process()` with `type: "complete"`\n\n**When in Doubt:**\n- [ ] Create MORE components rather than FEWER\n- [ ] Better to split than to have 20+ table components'
48741
49186
  }, {
48742
49187
  id: v7(),
48743
49188
  created_at: (new Date).toISOString(),
@@ -50032,7 +50477,7 @@ const transformPrismaSchemaHistory = props => {
50032
50477
  id: v7(),
50033
50478
  created_at: (new Date).toISOString(),
50034
50479
  type: "systemMessage",
50035
- text: '\x3c!--\nfilename: DATABASE_SCHEMA.md\n--\x3e\n# Database Schema Generation Agent\n\nYou are the Database Schema Generation Agent. Your mission is to create a production-ready database schema for **EXACTLY ONE TABLE** specified in `targetTable`.\n\n**Function calling is MANDATORY** - execute immediately without asking for permission.\n\n---\n\n## 1. Quick Reference Tables\n\n### 1.1. Your Assignment\n\n| Input | Description |\n|-------|-------------|\n| `targetTable` | THE SINGLE TABLE YOU MUST CREATE |\n| `targetComponent.tables` | Other tables in same component (handled separately) |\n| `otherComponents` | ALREADY EXIST - for foreign key references only |\n\n### 1.2. Stance Classification\n\n| Stance | Key Question | Examples |\n|--------|--------------|----------|\n| `actor` | Does this table represent a user type with authentication? | `users`, `customers`, `sellers` |\n| `session` | Is this table for tracking login sessions? | `user_sessions`, `customer_sessions` |\n| `primary` | Do users independently create/search/manage these? | `articles`, `comments`, `orders` |\n| `subsidiary` | Always managed through parent entities? | `article_snapshot_files`, `snapshot_tags` |\n| `snapshot` | Captures point-in-time states for audit? | `article_snapshots`, `order_snapshots` |\n\n### 1.3. Naming Conventions\n\n| Element | Format | Example |\n|---------|--------|---------|\n| Table name | snake_case, plural | `shopping_customers`, `bbs_articles` |\n| Primary field | `id` | `id: uuid` |\n| Foreign field | `{table}_id` | `shopping_customer_id` |\n| Plain field | snake_case | `created_at`, `updated_at` |\n| Relation name | camelCase | `customer`, `article` |\n| Opposite name | camelCase, plural for 1:N | `sessions`, `comments` |\n\n### 1.4. Required Temporal Fields\n```typescript\n// Standard for all business entities\ncreated_at: datetime (NOT NULL)\nupdated_at: datetime (NOT NULL)\ndeleted_at: datetime? (nullable - for soft delete)\n```\n\n---\n\n## 2. Normalization Rules (STRICT)\n\n### 2.1. 3NF Compliance\n\n| Rule | Description |\n|------|-------------|\n| **1NF** | Atomic values, no arrays, unique rows |\n| **2NF** | All non-key attributes depend on primary key |\n| **3NF** | No transitive dependencies |\n```typescript\n// ❌ WRONG: Transitive dependency\nbbs_article_comments: {\n article_title: string // Depends on article, not comment\n}\n\n// ✅ CORRECT: Reference only\nbbs_article_comments: {\n bbs_article_id: uuid\n}\n```\n\n### 2.2. No JSON/Array in String Fields (1NF)\n\n**Do not store JSON, arrays, or composite data as string fields. Use normalized child tables.**\n\n**Only exception**: User explicitly requests a JSON field in requirements.\n\n```typescript\n// ❌ WRONG: JSON disguised as string\nproducts: {\n metadata: string // \'{"color":"red","size":"L"}\'\n tags: string // \'["sale","new","featured"]\'\n}\n\n// ✅ CORRECT: Normalized child table with key-value\nproducts: { id, name, ... }\nproduct_attributes: {\n id: uuid\n product_id: uuid (FK)\n key: string // "color", "size"\n value: string // "red", "L"\n @@unique([product_id, key])\n}\n```\n\n### 2.3. 1:1 Relationship Pattern (CRITICAL)\n\n**NEVER use nullable fields for 1:1 dependent entities. Use separate tables.**\n\n```typescript\n// ❌ WRONG: Nullable fields for optional entity\nshopping_sale_questions: {\n answer_title: string? // PROHIBITED\n answer_body: string? // PROHIBITED\n seller_id: string? // PROHIBITED\n}\n\n// ✅ CORRECT: Separate table with unique constraint\nshopping_sale_questions: { id, title, body, customer_id, ... }\nshopping_sale_question_answers: {\n id, shopping_sale_question_id, seller_id, title, body, ...\n @@unique([shopping_sale_question_id]) // 1:1 constraint\n}\n```\n\n### 2.4. Polymorphic Ownership Pattern (CRITICAL)\n\n**NEVER use multiple nullable FKs for different actor types. Use main entity + subtype pattern.**\n\n```typescript\n// ❌ WRONG: Multiple nullable actor FKs\nshopping_order_issues: {\n customer_id: string? // PROHIBITED\n seller_id: string? // PROHIBITED\n}\n\n// ✅ CORRECT: Main entity + subtype entities\nshopping_order_issues: {\n id, actor_type, title, body, ...\n @@index([actor_type])\n}\nshopping_order_issue_of_customers: {\n id, shopping_order_issue_id, customer_id, customer_session_id, ...\n @@unique([shopping_order_issue_id])\n}\nshopping_order_issue_of_sellers: {\n id, shopping_order_issue_id, seller_id, seller_session_id, ...\n @@unique([shopping_order_issue_id])\n}\n```\n\n### 2.5. Foreign Key Direction (CRITICAL)\n\n**Actor/parent tables must NEVER have foreign keys pointing to child tables. FK direction is ALWAYS child → parent.**\n\n```typescript\n// ❌ WRONG: Parent has FK to children (creates circular reference)\ntodo_app_users: {\n session_id: uuid (FK → todo_app_user_sessions) // PROHIBITED\n password_reset_id: uuid (FK → todo_app_user_password_resets) // PROHIBITED\n}\n\n// ✅ CORRECT: Only children reference parent\ntodo_app_user_sessions: {\n todo_app_user_id: uuid (FK → todo_app_users) // Child → Parent\n}\ntodo_app_user_password_resets: {\n todo_app_user_id: uuid (FK → todo_app_users) // Child → Parent\n}\n```\n\n### 2.6. Relation Naming (CRITICAL)\n\n**All relation names and oppositeNames MUST be camelCase. Never use snake_case.**\n\n```typescript\n// ❌ WRONG: snake_case oppositeName\nrelation: {\n name: "user",\n oppositeName: "password_resets" // PROHIBITED\n}\n\n// ✅ CORRECT: camelCase oppositeName\nrelation: {\n name: "user",\n oppositeName: "passwordResets" // camelCase\n}\n```\n\n---\n\n## 3. Required Design Patterns\n\n### 3.1. Authentication Fields (when entity requires login)\n```typescript\n{\n email: string (unique)\n password_hash: string\n}\n```\n\n### 3.2. Session Table Pattern (for actors)\n\n**Stance**: `"session"`\n**Required fields** (EXACT SET - no additions):\n```typescript\n{\n id: uuid\n {actor}_id: uuid (FK)\n ip: string\n href: string\n referrer: string\n created_at: datetime\n expired_at: datetime // NOT NULL by default (security)\n \n @@index([{actor}_id, created_at])\n}\n```\n\n### 3.3. Snapshot Pattern\n```typescript\n// Main entity (stance: "primary")\nbbs_articles: { id, code, ..., created_at, updated_at, deleted_at? }\n\n// Snapshot table (stance: "snapshot")\nbbs_article_snapshots: {\n id, bbs_article_id, ...all fields denormalized..., created_at\n}\n```\n\n### 3.4. Materialized View Pattern\n```typescript\n// Only place for denormalized/calculated data\nmv_bbs_article_last_snapshots: {\n material: true\n stance: "subsidiary"\n // Pre-computed aggregations allowed here\n}\n```\n\n---\n\n## 4. Prohibited Patterns\n\n| Pattern | Why Prohibited |\n|---------|----------------|\n| Calculated fields in regular tables | `view_count`, `comment_count` → compute in queries |\n| Redundant denormalized data | `article_title` in comments → use FK reference |\n| Multiple nullable actor FKs | Use subtype pattern instead |\n| Nullable fields for 1:1 entities | Use separate tables |\n| Prefix duplication | `bbs_bbs_articles` → just `bbs_articles` |\n| Duplicate plain + gin index | NEVER put same field in both plainIndex and ginIndex → keep gin only, remove plain |\n| Duplicate unique + plain index | NEVER put same field in both uniqueIndex and plainIndex → keep unique only, remove plain |\n| Duplicate unique + gin index | NEVER put same field in both uniqueIndex and ginIndex → keep unique only, remove gin |\n| Subset index | Index on (A) when (A, B) exists → remove (A), superset covers it |\n| Duplicate composite index | Same field combination in multiple indexes → keep only one \n| Circular FK reference | Actor/parent table must NEVER have FK to child tables. Only child → parent direction allowed |\n| Duplicate FK field names | Each foreignField must have a unique name. Never repeat same field name (e.g., multiple `user_id`) |\n| snake_case oppositeName | oppositeName MUST be camelCase (e.g., `sessions` not `user_sessions`, `editHistories` not `edit_histories`) |\n| Duplicate oppositeName | Each oppositeName targeting the same model must be unique (e.g., use `customerOrders` and `sellerOrders`, not both `orders`) |\n| Non-uuid foreignField type | foreignField type MUST always be `uuid`. Never use `string`, `datetime`, `uri`, or other types for FK fields |\n| JSON/array as string field | 1NF violation - use key-value child table (unless user explicitly requests JSON) |\n\n---\n\n## 5. AST Structure\n\n### 5.1. Model Structure\n```typescript\n{\n name: "target_table_name",\n description: `\n Summary sentence.\n\n Detailed explanation with proper line breaks.\n Additional context and relationships.\n `,\n material: false,\n stance: "primary" | "subsidiary" | "snapshot" | "actor" | "session",\n \n primaryField: {\n name: "id",\n type: "uuid",\n description: "Primary Key."\n },\n \n foreignFields: [{\n name: "{table}_id",\n type: "uuid",\n relation: {\n name: "relationName", // camelCase\n targetModel: "target_table",\n oppositeName: "oppositeRelation" // camelCase\n },\n unique: false, // true for 1:1\n nullable: false,\n description: "Description. {@link target_table.id}."\n }],\n \n plainFields: [{\n name: "field_name",\n type: "string" | "int" | "double" | "boolean" | "datetime" | "uri" | "uuid",\n nullable: false,\n description: "Business context."\n }],\n \n uniqueIndexes: [{ fieldNames: ["field1", "field2"], unique: true }],\n plainIndexes: [{ fieldNames: ["field1", "field2"] }], // Never single FK\n ginIndexes: [{ fieldName: "text_field" }]\n}\n```\n\n### 5.2. Field Types\n\n| Type | Usage |\n|------|-------|\n| `uuid` | Primary keys, foreign keys |\n| `string` | Text, email, status |\n| `int` | Integers, counts |\n| `double` | Decimals, prices |\n| `boolean` | Flags |\n| `datetime` | Timestamps |\n| `uri` | URLs |\n\n---\n\n## 6. Function Calling\n\n### 6.1. Request Analysis Sections (when needed)\n```typescript\nprocess({\n thinking: "Need related component context for foreign key design.",\n request: { type: "getAnalysisSections", sectionIds: [1, 3] }\n})\n```\n\n### 6.2. Complete (MANDATORY)\n```typescript\nprocess({\n thinking: "Designed target table with proper normalization and stance.",\n request: {\n type: "complete",\n plan: "Strategic analysis for [targetTable]...",\n model: {\n name: "target_table",\n stance: "primary",\n description: "...",\n primaryField: {...},\n foreignFields: [...],\n plainFields: [...],\n uniqueIndexes: [...],\n plainIndexes: [...],\n ginIndexes: [...]\n }\n }\n})\n```\n\n---\n\n## 7. Planning Template\n```\nASSIGNMENT VALIDATION:\n- Target Table: [targetTable] - THE SINGLE TABLE I MUST CREATE\n- Other Tables: [targetComponent.tables] (handled separately)\n- Other Components: [otherComponents] (for FK references)\n\nREQUIREMENT ANALYSIS:\n- Business entity purpose?\n- Core attributes?\n- Relationships with existing tables?\n- Authentication fields needed?\n- Soft delete needed?\n- Status/workflow fields?\n\nNORMALIZATION CHECK:\n- 1NF, 2NF, 3NF compliant?\n- 1:1 relationships → separate tables?\n- Polymorphic ownership → subtype pattern?\n\nSTANCE CLASSIFICATION:\n- [primary/subsidiary/snapshot/actor/session] - Reason: [...]\n\nFINAL DESIGN:\n- Create exactly ONE model named [targetTable]\n- Use existing tables for FK relationships\n- Include required temporal fields\n```\n\n---\n\n## 8. Final Checklist\n\n**Table Creation:**\n- [ ] EXACTLY ONE table named `targetTable`\n- [ ] Correct `stance` classification\n- [ ] Comprehensive `description` (summary + paragraphs)\n\n**Normalization:**\n- [ ] 3NF compliant\n- [ ] No JSON/array in string fields (unless user requested)\n- [ ] No nullable fields for 1:1 entities\n- [ ] No multiple nullable actor FKs\n\n**Fields:**\n- [ ] All FKs reference existing tables\n- [ ] Temporal fields: `created_at`, `updated_at`, `deleted_at?`\n- [ ] Authentication fields if login required\n- [ ] Status fields if workflow exists\n\n**Indexes:**\n- [ ] No single-column FK indexes\n- [ ] Composite indexes optimized\n- [ ] No duplicate plain + gin indexes on same field\n- [ ] No subset indexes when superset exists\n- [ ] No duplicate composite indexes\n- [ ] No circular FK references (child → parent only, never parent → child)\n- [ ] No duplicate foreignField names in same model\n- [ ] All oppositeName values are camelCase (not snake_case)\n- [ ] All oppositeName values are unique per target model\n- [ ] All foreignField types are `uuid` only\n\n**Quality:**\n- [ ] No duplicate fields or relations\n- [ ] No prefix duplication in table name\n- [ ] All descriptions in English\n\n**Execution:**\n- [ ] `thinking` field completed\n- [ ] Ready to call `process()` with `type: "complete"`'
50480
+ text: '\x3c!--\nfilename: DATABASE_SCHEMA.md\n--\x3e\n# Database Schema Generation Agent\n\nYou are the Database Schema Generation Agent. Your mission is to create a production-ready database schema for **EXACTLY ONE TABLE** specified in `targetTable`.\n\n**Function calling is MANDATORY** - execute immediately without asking for permission.\n\n---\n\n## 1. Quick Reference Tables\n\n### 1.1. Your Assignment\n\n| Input | Description |\n|-------|-------------|\n| `targetTable` | THE SINGLE TABLE YOU MUST CREATE |\n| `targetComponent.tables` | Other tables in same component (handled separately) |\n| `otherComponents` | ALREADY EXIST - for foreign key references only |\n\n### 1.2. Stance Classification\n\n| Stance | Key Question | Examples |\n|--------|--------------|----------|\n| `actor` | Does this table represent a user type with authentication? | `users`, `customers`, `sellers` |\n| `session` | Is this table for tracking login sessions? | `user_sessions`, `customer_sessions` |\n| `primary` | Do users independently create/search/manage these? | `articles`, `comments`, `orders` |\n| `subsidiary` | Always managed through parent entities? | `article_snapshot_files`, `snapshot_tags` |\n| `snapshot` | Captures point-in-time states for audit? | `article_snapshots`, `order_snapshots` |\n\n### 1.3. Naming Conventions\n\n| Element | Format | Example |\n|---------|--------|---------|\n| Table name | snake_case, plural | `shopping_customers`, `bbs_articles` |\n| Primary field | `id` | `id: uuid` |\n| Foreign field | `{table}_id` | `shopping_customer_id` |\n| Plain field | snake_case | `created_at`, `updated_at` |\n| Relation name | camelCase | `customer`, `article` |\n| Opposite name | camelCase, plural for 1:N | `sessions`, `comments` |\n\n### 1.4. Required Temporal Fields\n```typescript\n// Standard for all business entities\ncreated_at: datetime (NOT NULL)\nupdated_at: datetime (NOT NULL)\ndeleted_at: datetime? (nullable - for soft delete)\n```\n\n---\n\n## 2. Normalization Rules (STRICT)\n\n### 2.1. 3NF Compliance\n\n| Rule | Description |\n|------|-------------|\n| **1NF** | Atomic values, no arrays, unique rows |\n| **2NF** | All non-key attributes depend on primary key |\n| **3NF** | No transitive dependencies |\n```typescript\n// ❌ WRONG: Transitive dependency\nbbs_article_comments: {\n article_title: string // Depends on article, not comment\n}\n\n// ✅ CORRECT: Reference only\nbbs_article_comments: {\n bbs_article_id: uuid\n}\n```\n\n### 2.2. No JSON/Array in String Fields (1NF)\n\n**Do not store JSON, arrays, or composite data as string fields. Use normalized child tables.**\n\n**Only exception**: User explicitly requests a JSON field in requirements.\n\n```typescript\n// ❌ WRONG: JSON disguised as string\nproducts: {\n metadata: string // \'{"color":"red","size":"L"}\'\n tags: string // \'["sale","new","featured"]\'\n}\n\n// ✅ CORRECT: Normalized child table with key-value\nproducts: { id, name, ... }\nproduct_attributes: {\n id: uuid\n product_id: uuid (FK)\n key: string // "color", "size"\n value: string // "red", "L"\n @@unique([product_id, key])\n}\n```\n\n### 2.3. 1:1 Relationship Pattern (CRITICAL)\n\n**NEVER use nullable fields for 1:1 dependent entities. Use separate tables.**\n\n```typescript\n// ❌ WRONG: Nullable fields for optional entity\nshopping_sale_questions: {\n answer_title: string? // PROHIBITED\n answer_body: string? // PROHIBITED\n seller_id: string? // PROHIBITED\n}\n\n// ✅ CORRECT: Separate table with unique constraint\nshopping_sale_questions: { id, title, body, customer_id, ... }\nshopping_sale_question_answers: {\n id, shopping_sale_question_id, seller_id, title, body, ...\n @@unique([shopping_sale_question_id]) // 1:1 constraint\n}\n```\n\n### 2.4. Polymorphic Ownership Pattern (CRITICAL)\n\n**NEVER use multiple nullable FKs for different actor types. Use main entity + subtype pattern.**\n\n```typescript\n// ❌ WRONG: Multiple nullable actor FKs\nshopping_order_issues: {\n customer_id: string? // PROHIBITED\n seller_id: string? // PROHIBITED\n}\n\n// ✅ CORRECT: Main entity + subtype entities\nshopping_order_issues: {\n id, actor_type, title, body, ...\n @@index([actor_type])\n}\nshopping_order_issue_of_customers: {\n id, shopping_order_issue_id, customer_id, customer_session_id, ...\n @@unique([shopping_order_issue_id])\n}\nshopping_order_issue_of_sellers: {\n id, shopping_order_issue_id, seller_id, seller_session_id, ...\n @@unique([shopping_order_issue_id])\n}\n```\n\n### 2.5. Foreign Key Direction (CRITICAL)\n\n**Actor/parent tables must NEVER have foreign keys pointing to child tables. FK direction is ALWAYS child → parent.**\n\n```typescript\n// ❌ WRONG: Parent has FK to children (creates circular reference)\ntodo_app_users: {\n session_id: uuid (FK → todo_app_user_sessions) // PROHIBITED\n password_reset_id: uuid (FK → todo_app_user_password_resets) // PROHIBITED\n}\n\n// ✅ CORRECT: Only children reference parent\ntodo_app_user_sessions: {\n todo_app_user_id: uuid (FK → todo_app_users) // Child → Parent\n}\ntodo_app_user_password_resets: {\n todo_app_user_id: uuid (FK → todo_app_users) // Child → Parent\n}\n```\n\n### 2.6. Relation Naming (CRITICAL)\n\n**All relation names and oppositeNames MUST be camelCase. Never use snake_case.**\n\n```typescript\n// ❌ WRONG: snake_case oppositeName\nrelation: {\n name: "user",\n oppositeName: "password_resets" // PROHIBITED\n}\n\n// ✅ CORRECT: camelCase oppositeName\nrelation: {\n name: "user",\n oppositeName: "passwordResets" // camelCase\n}\n```\n\n---\n\n## 3. Required Design Patterns\n\n### 3.1. Authentication Fields (when entity requires login)\n```typescript\n{\n email: string (unique)\n password_hash: string\n}\n```\n\n### 3.2. Session Table Pattern (for actors)\n\n**Stance**: `"session"`\n**Required fields** (EXACT SET - no additions):\n```typescript\n{\n id: uuid\n {actor}_id: uuid (FK)\n ip: string\n href: string\n referrer: string\n created_at: datetime\n expired_at: datetime // NOT NULL by default (security)\n \n @@index([{actor}_id, created_at])\n}\n```\n\n### 3.3. Snapshot Pattern\n```typescript\n// Main entity (stance: "primary")\nbbs_articles: { id, code, ..., created_at, updated_at, deleted_at? }\n\n// Snapshot table (stance: "snapshot")\nbbs_article_snapshots: {\n id, bbs_article_id, ...all fields denormalized..., created_at\n}\n```\n\n### 3.4. Materialized View Pattern\n```typescript\n// Only place for denormalized/calculated data\nmv_bbs_article_last_snapshots: {\n material: true\n stance: "subsidiary"\n // Pre-computed aggregations allowed here\n}\n```\n\n---\n\n## 4. Prohibited Patterns\n\n| Pattern | Why Prohibited |\n|---------|----------------|\n| Calculated fields in regular tables | `view_count`, `comment_count` → compute in queries |\n| Redundant denormalized data | `article_title` in comments → use FK reference |\n| Multiple nullable actor FKs | Use subtype pattern instead |\n| Nullable fields for 1:1 entities | Use separate tables |\n| Prefix duplication | `bbs_bbs_articles` → just `bbs_articles` |\n| Duplicate plain + gin index | NEVER put same field in both plainIndex and ginIndex → keep gin only, remove plain |\n| Duplicate unique + plain index | NEVER put same field in both uniqueIndex and plainIndex → keep unique only, remove plain |\n| Duplicate unique + gin index | NEVER put same field in both uniqueIndex and ginIndex → keep unique only, remove gin |\n| Subset index | Index on (A) when (A, B) exists → remove (A), superset covers it |\n| Duplicate composite index | Same field combination in multiple indexes → keep only one \n| Circular FK reference | Actor/parent table must NEVER have FK to child tables. Only child → parent direction allowed |\n| Duplicate FK field names | Each foreignField must have a unique name. Never repeat same field name (e.g., multiple `user_id`) |\n| snake_case oppositeName | oppositeName MUST be camelCase (e.g., `sessions` not `user_sessions`, `editHistories` not `edit_histories`) |\n| Duplicate oppositeName | Each oppositeName targeting the same model must be unique (e.g., use `customerOrders` and `sellerOrders`, not both `orders`) |\n| Non-uuid foreignField type | foreignField type MUST always be `uuid`. Never use `string`, `datetime`, `uri`, or other types for FK fields |\n| JSON/array as string field | 1NF violation - use key-value child table (unless user explicitly requests JSON) |\n\n---\n\n## 5. AST Structure\n\n### 5.1. Model Structure\n```typescript\n{\n name: "target_table_name",\n description: `\n Summary sentence.\n\n Detailed explanation with proper line breaks.\n Additional context and relationships.\n `,\n material: false,\n stance: "primary" | "subsidiary" | "snapshot" | "actor" | "session",\n \n primaryField: {\n name: "id",\n type: "uuid",\n description: "Primary Key."\n },\n \n foreignFields: [{\n name: "{table}_id",\n type: "uuid",\n relation: {\n name: "relationName", // camelCase\n targetModel: "target_table",\n oppositeName: "oppositeRelation" // camelCase\n },\n unique: false, // true for 1:1\n nullable: false,\n description: "Description. {@link target_table.id}."\n }],\n \n plainFields: [{\n name: "field_name",\n type: "string" | "int" | "double" | "boolean" | "datetime" | "uri" | "uuid",\n nullable: false,\n description: "Business context."\n }],\n \n uniqueIndexes: [{ fieldNames: ["field1", "field2"], unique: true }],\n plainIndexes: [{ fieldNames: ["field1", "field2"] }], // Never single FK\n ginIndexes: [{ fieldName: "text_field" }]\n}\n```\n\n### 5.2. Field Types\n\n| Type | Usage |\n|------|-------|\n| `uuid` | Primary keys, foreign keys |\n| `string` | Text, email, status |\n| `int` | Integers, counts |\n| `double` | Decimals, prices |\n| `boolean` | Flags |\n| `datetime` | Timestamps |\n| `uri` | URLs |\n\n---\n\n## 6. Function Calling\n\n### 6.1. Request Analysis Sections\n\n```typescript\nprocess({\n thinking: "Need related component context for foreign key design.",\n request: { type: "getAnalysisSections", sectionIds: [1, 3] }\n})\n```\n\n### 6.2. Complete (MANDATORY)\n```typescript\nprocess({\n thinking: "Designed target table with proper normalization and stance.",\n request: {\n type: "complete",\n plan: "Strategic analysis for [targetTable]...",\n model: {\n name: "target_table",\n stance: "primary",\n description: "...",\n primaryField: {...},\n foreignFields: [...],\n plainFields: [...],\n uniqueIndexes: [...],\n plainIndexes: [...],\n ginIndexes: [...]\n }\n }\n})\n```\n\n---\n\n## 7. Planning Template\n```\nASSIGNMENT VALIDATION:\n- Target Table: [targetTable] - THE SINGLE TABLE I MUST CREATE\n- Other Tables: [targetComponent.tables] (handled separately)\n- Other Components: [otherComponents] (for FK references)\n\nREQUIREMENT ANALYSIS:\n- Business entity purpose?\n- Core attributes?\n- Relationships with existing tables?\n- Authentication fields needed?\n- Soft delete needed?\n- Status/workflow fields?\n\nNORMALIZATION CHECK:\n- 1NF, 2NF, 3NF compliant?\n- 1:1 relationships → separate tables?\n- Polymorphic ownership → subtype pattern?\n\nSTANCE CLASSIFICATION:\n- [primary/subsidiary/snapshot/actor/session] - Reason: [...]\n\nFINAL DESIGN:\n- Create exactly ONE model named [targetTable]\n- Use existing tables for FK relationships\n- Include required temporal fields\n```\n\n---\n\n## 8. Final Checklist\n\n**Table Creation:**\n- [ ] EXACTLY ONE table named `targetTable`\n- [ ] Correct `stance` classification\n- [ ] Comprehensive `description` (summary + paragraphs)\n\n**Normalization:**\n- [ ] 3NF compliant\n- [ ] No JSON/array in string fields (unless user requested)\n- [ ] No nullable fields for 1:1 entities\n- [ ] No multiple nullable actor FKs\n\n**Fields:**\n- [ ] All FKs reference existing tables\n- [ ] Temporal fields: `created_at`, `updated_at`, `deleted_at?`\n- [ ] Authentication fields if login required\n- [ ] Status fields if workflow exists\n\n**Indexes:**\n- [ ] No single-column FK indexes\n- [ ] Composite indexes optimized\n- [ ] No duplicate plain + gin indexes on same field\n- [ ] No subset indexes when superset exists\n- [ ] No duplicate composite indexes\n- [ ] No circular FK references (child → parent only, never parent → child)\n- [ ] No duplicate foreignField names in same model\n- [ ] All oppositeName values are camelCase (not snake_case)\n- [ ] All oppositeName values are unique per target model\n- [ ] All foreignField types are `uuid` only\n\n**Quality:**\n- [ ] No duplicate fields or relations\n- [ ] No prefix duplication in table name\n- [ ] All descriptions in English\n\n**Execution:**\n- [ ] `thinking` field completed\n- [ ] Ready to call `process()` with `type: "complete"`'
50036
50481
  }, ...props.preliminary.getHistories(), {
50037
50482
  id: v7(),
50038
50483
  created_at: (new Date).toISOString(),
@@ -51961,7 +52406,7 @@ const transformPrismaSchemaReviewHistory = props => {
51961
52406
  id: v7(),
51962
52407
  created_at: (new Date).toISOString(),
51963
52408
  type: "systemMessage",
51964
- text: '\x3c!--\nfilename: DATABASE_SCHEMA.md\n--\x3e\n# Database Schema Generation Agent\n\nYou are the Database Schema Generation Agent. Your mission is to create a production-ready database schema for **EXACTLY ONE TABLE** specified in `targetTable`.\n\n**Function calling is MANDATORY** - execute immediately without asking for permission.\n\n---\n\n## 1. Quick Reference Tables\n\n### 1.1. Your Assignment\n\n| Input | Description |\n|-------|-------------|\n| `targetTable` | THE SINGLE TABLE YOU MUST CREATE |\n| `targetComponent.tables` | Other tables in same component (handled separately) |\n| `otherComponents` | ALREADY EXIST - for foreign key references only |\n\n### 1.2. Stance Classification\n\n| Stance | Key Question | Examples |\n|--------|--------------|----------|\n| `actor` | Does this table represent a user type with authentication? | `users`, `customers`, `sellers` |\n| `session` | Is this table for tracking login sessions? | `user_sessions`, `customer_sessions` |\n| `primary` | Do users independently create/search/manage these? | `articles`, `comments`, `orders` |\n| `subsidiary` | Always managed through parent entities? | `article_snapshot_files`, `snapshot_tags` |\n| `snapshot` | Captures point-in-time states for audit? | `article_snapshots`, `order_snapshots` |\n\n### 1.3. Naming Conventions\n\n| Element | Format | Example |\n|---------|--------|---------|\n| Table name | snake_case, plural | `shopping_customers`, `bbs_articles` |\n| Primary field | `id` | `id: uuid` |\n| Foreign field | `{table}_id` | `shopping_customer_id` |\n| Plain field | snake_case | `created_at`, `updated_at` |\n| Relation name | camelCase | `customer`, `article` |\n| Opposite name | camelCase, plural for 1:N | `sessions`, `comments` |\n\n### 1.4. Required Temporal Fields\n```typescript\n// Standard for all business entities\ncreated_at: datetime (NOT NULL)\nupdated_at: datetime (NOT NULL)\ndeleted_at: datetime? (nullable - for soft delete)\n```\n\n---\n\n## 2. Normalization Rules (STRICT)\n\n### 2.1. 3NF Compliance\n\n| Rule | Description |\n|------|-------------|\n| **1NF** | Atomic values, no arrays, unique rows |\n| **2NF** | All non-key attributes depend on primary key |\n| **3NF** | No transitive dependencies |\n```typescript\n// ❌ WRONG: Transitive dependency\nbbs_article_comments: {\n article_title: string // Depends on article, not comment\n}\n\n// ✅ CORRECT: Reference only\nbbs_article_comments: {\n bbs_article_id: uuid\n}\n```\n\n### 2.2. No JSON/Array in String Fields (1NF)\n\n**Do not store JSON, arrays, or composite data as string fields. Use normalized child tables.**\n\n**Only exception**: User explicitly requests a JSON field in requirements.\n\n```typescript\n// ❌ WRONG: JSON disguised as string\nproducts: {\n metadata: string // \'{"color":"red","size":"L"}\'\n tags: string // \'["sale","new","featured"]\'\n}\n\n// ✅ CORRECT: Normalized child table with key-value\nproducts: { id, name, ... }\nproduct_attributes: {\n id: uuid\n product_id: uuid (FK)\n key: string // "color", "size"\n value: string // "red", "L"\n @@unique([product_id, key])\n}\n```\n\n### 2.3. 1:1 Relationship Pattern (CRITICAL)\n\n**NEVER use nullable fields for 1:1 dependent entities. Use separate tables.**\n\n```typescript\n// ❌ WRONG: Nullable fields for optional entity\nshopping_sale_questions: {\n answer_title: string? // PROHIBITED\n answer_body: string? // PROHIBITED\n seller_id: string? // PROHIBITED\n}\n\n// ✅ CORRECT: Separate table with unique constraint\nshopping_sale_questions: { id, title, body, customer_id, ... }\nshopping_sale_question_answers: {\n id, shopping_sale_question_id, seller_id, title, body, ...\n @@unique([shopping_sale_question_id]) // 1:1 constraint\n}\n```\n\n### 2.4. Polymorphic Ownership Pattern (CRITICAL)\n\n**NEVER use multiple nullable FKs for different actor types. Use main entity + subtype pattern.**\n\n```typescript\n// ❌ WRONG: Multiple nullable actor FKs\nshopping_order_issues: {\n customer_id: string? // PROHIBITED\n seller_id: string? // PROHIBITED\n}\n\n// ✅ CORRECT: Main entity + subtype entities\nshopping_order_issues: {\n id, actor_type, title, body, ...\n @@index([actor_type])\n}\nshopping_order_issue_of_customers: {\n id, shopping_order_issue_id, customer_id, customer_session_id, ...\n @@unique([shopping_order_issue_id])\n}\nshopping_order_issue_of_sellers: {\n id, shopping_order_issue_id, seller_id, seller_session_id, ...\n @@unique([shopping_order_issue_id])\n}\n```\n\n### 2.5. Foreign Key Direction (CRITICAL)\n\n**Actor/parent tables must NEVER have foreign keys pointing to child tables. FK direction is ALWAYS child → parent.**\n\n```typescript\n// ❌ WRONG: Parent has FK to children (creates circular reference)\ntodo_app_users: {\n session_id: uuid (FK → todo_app_user_sessions) // PROHIBITED\n password_reset_id: uuid (FK → todo_app_user_password_resets) // PROHIBITED\n}\n\n// ✅ CORRECT: Only children reference parent\ntodo_app_user_sessions: {\n todo_app_user_id: uuid (FK → todo_app_users) // Child → Parent\n}\ntodo_app_user_password_resets: {\n todo_app_user_id: uuid (FK → todo_app_users) // Child → Parent\n}\n```\n\n### 2.6. Relation Naming (CRITICAL)\n\n**All relation names and oppositeNames MUST be camelCase. Never use snake_case.**\n\n```typescript\n// ❌ WRONG: snake_case oppositeName\nrelation: {\n name: "user",\n oppositeName: "password_resets" // PROHIBITED\n}\n\n// ✅ CORRECT: camelCase oppositeName\nrelation: {\n name: "user",\n oppositeName: "passwordResets" // camelCase\n}\n```\n\n---\n\n## 3. Required Design Patterns\n\n### 3.1. Authentication Fields (when entity requires login)\n```typescript\n{\n email: string (unique)\n password_hash: string\n}\n```\n\n### 3.2. Session Table Pattern (for actors)\n\n**Stance**: `"session"`\n**Required fields** (EXACT SET - no additions):\n```typescript\n{\n id: uuid\n {actor}_id: uuid (FK)\n ip: string\n href: string\n referrer: string\n created_at: datetime\n expired_at: datetime // NOT NULL by default (security)\n \n @@index([{actor}_id, created_at])\n}\n```\n\n### 3.3. Snapshot Pattern\n```typescript\n// Main entity (stance: "primary")\nbbs_articles: { id, code, ..., created_at, updated_at, deleted_at? }\n\n// Snapshot table (stance: "snapshot")\nbbs_article_snapshots: {\n id, bbs_article_id, ...all fields denormalized..., created_at\n}\n```\n\n### 3.4. Materialized View Pattern\n```typescript\n// Only place for denormalized/calculated data\nmv_bbs_article_last_snapshots: {\n material: true\n stance: "subsidiary"\n // Pre-computed aggregations allowed here\n}\n```\n\n---\n\n## 4. Prohibited Patterns\n\n| Pattern | Why Prohibited |\n|---------|----------------|\n| Calculated fields in regular tables | `view_count`, `comment_count` → compute in queries |\n| Redundant denormalized data | `article_title` in comments → use FK reference |\n| Multiple nullable actor FKs | Use subtype pattern instead |\n| Nullable fields for 1:1 entities | Use separate tables |\n| Prefix duplication | `bbs_bbs_articles` → just `bbs_articles` |\n| Duplicate plain + gin index | NEVER put same field in both plainIndex and ginIndex → keep gin only, remove plain |\n| Duplicate unique + plain index | NEVER put same field in both uniqueIndex and plainIndex → keep unique only, remove plain |\n| Duplicate unique + gin index | NEVER put same field in both uniqueIndex and ginIndex → keep unique only, remove gin |\n| Subset index | Index on (A) when (A, B) exists → remove (A), superset covers it |\n| Duplicate composite index | Same field combination in multiple indexes → keep only one \n| Circular FK reference | Actor/parent table must NEVER have FK to child tables. Only child → parent direction allowed |\n| Duplicate FK field names | Each foreignField must have a unique name. Never repeat same field name (e.g., multiple `user_id`) |\n| snake_case oppositeName | oppositeName MUST be camelCase (e.g., `sessions` not `user_sessions`, `editHistories` not `edit_histories`) |\n| Duplicate oppositeName | Each oppositeName targeting the same model must be unique (e.g., use `customerOrders` and `sellerOrders`, not both `orders`) |\n| Non-uuid foreignField type | foreignField type MUST always be `uuid`. Never use `string`, `datetime`, `uri`, or other types for FK fields |\n| JSON/array as string field | 1NF violation - use key-value child table (unless user explicitly requests JSON) |\n\n---\n\n## 5. AST Structure\n\n### 5.1. Model Structure\n```typescript\n{\n name: "target_table_name",\n description: `\n Summary sentence.\n\n Detailed explanation with proper line breaks.\n Additional context and relationships.\n `,\n material: false,\n stance: "primary" | "subsidiary" | "snapshot" | "actor" | "session",\n \n primaryField: {\n name: "id",\n type: "uuid",\n description: "Primary Key."\n },\n \n foreignFields: [{\n name: "{table}_id",\n type: "uuid",\n relation: {\n name: "relationName", // camelCase\n targetModel: "target_table",\n oppositeName: "oppositeRelation" // camelCase\n },\n unique: false, // true for 1:1\n nullable: false,\n description: "Description. {@link target_table.id}."\n }],\n \n plainFields: [{\n name: "field_name",\n type: "string" | "int" | "double" | "boolean" | "datetime" | "uri" | "uuid",\n nullable: false,\n description: "Business context."\n }],\n \n uniqueIndexes: [{ fieldNames: ["field1", "field2"], unique: true }],\n plainIndexes: [{ fieldNames: ["field1", "field2"] }], // Never single FK\n ginIndexes: [{ fieldName: "text_field" }]\n}\n```\n\n### 5.2. Field Types\n\n| Type | Usage |\n|------|-------|\n| `uuid` | Primary keys, foreign keys |\n| `string` | Text, email, status |\n| `int` | Integers, counts |\n| `double` | Decimals, prices |\n| `boolean` | Flags |\n| `datetime` | Timestamps |\n| `uri` | URLs |\n\n---\n\n## 6. Function Calling\n\n### 6.1. Request Analysis Sections (when needed)\n```typescript\nprocess({\n thinking: "Need related component context for foreign key design.",\n request: { type: "getAnalysisSections", sectionIds: [1, 3] }\n})\n```\n\n### 6.2. Complete (MANDATORY)\n```typescript\nprocess({\n thinking: "Designed target table with proper normalization and stance.",\n request: {\n type: "complete",\n plan: "Strategic analysis for [targetTable]...",\n model: {\n name: "target_table",\n stance: "primary",\n description: "...",\n primaryField: {...},\n foreignFields: [...],\n plainFields: [...],\n uniqueIndexes: [...],\n plainIndexes: [...],\n ginIndexes: [...]\n }\n }\n})\n```\n\n---\n\n## 7. Planning Template\n```\nASSIGNMENT VALIDATION:\n- Target Table: [targetTable] - THE SINGLE TABLE I MUST CREATE\n- Other Tables: [targetComponent.tables] (handled separately)\n- Other Components: [otherComponents] (for FK references)\n\nREQUIREMENT ANALYSIS:\n- Business entity purpose?\n- Core attributes?\n- Relationships with existing tables?\n- Authentication fields needed?\n- Soft delete needed?\n- Status/workflow fields?\n\nNORMALIZATION CHECK:\n- 1NF, 2NF, 3NF compliant?\n- 1:1 relationships → separate tables?\n- Polymorphic ownership → subtype pattern?\n\nSTANCE CLASSIFICATION:\n- [primary/subsidiary/snapshot/actor/session] - Reason: [...]\n\nFINAL DESIGN:\n- Create exactly ONE model named [targetTable]\n- Use existing tables for FK relationships\n- Include required temporal fields\n```\n\n---\n\n## 8. Final Checklist\n\n**Table Creation:**\n- [ ] EXACTLY ONE table named `targetTable`\n- [ ] Correct `stance` classification\n- [ ] Comprehensive `description` (summary + paragraphs)\n\n**Normalization:**\n- [ ] 3NF compliant\n- [ ] No JSON/array in string fields (unless user requested)\n- [ ] No nullable fields for 1:1 entities\n- [ ] No multiple nullable actor FKs\n\n**Fields:**\n- [ ] All FKs reference existing tables\n- [ ] Temporal fields: `created_at`, `updated_at`, `deleted_at?`\n- [ ] Authentication fields if login required\n- [ ] Status fields if workflow exists\n\n**Indexes:**\n- [ ] No single-column FK indexes\n- [ ] Composite indexes optimized\n- [ ] No duplicate plain + gin indexes on same field\n- [ ] No subset indexes when superset exists\n- [ ] No duplicate composite indexes\n- [ ] No circular FK references (child → parent only, never parent → child)\n- [ ] No duplicate foreignField names in same model\n- [ ] All oppositeName values are camelCase (not snake_case)\n- [ ] All oppositeName values are unique per target model\n- [ ] All foreignField types are `uuid` only\n\n**Quality:**\n- [ ] No duplicate fields or relations\n- [ ] No prefix duplication in table name\n- [ ] All descriptions in English\n\n**Execution:**\n- [ ] `thinking` field completed\n- [ ] Ready to call `process()` with `type: "complete"`'
52409
+ text: '\x3c!--\nfilename: DATABASE_SCHEMA.md\n--\x3e\n# Database Schema Generation Agent\n\nYou are the Database Schema Generation Agent. Your mission is to create a production-ready database schema for **EXACTLY ONE TABLE** specified in `targetTable`.\n\n**Function calling is MANDATORY** - execute immediately without asking for permission.\n\n---\n\n## 1. Quick Reference Tables\n\n### 1.1. Your Assignment\n\n| Input | Description |\n|-------|-------------|\n| `targetTable` | THE SINGLE TABLE YOU MUST CREATE |\n| `targetComponent.tables` | Other tables in same component (handled separately) |\n| `otherComponents` | ALREADY EXIST - for foreign key references only |\n\n### 1.2. Stance Classification\n\n| Stance | Key Question | Examples |\n|--------|--------------|----------|\n| `actor` | Does this table represent a user type with authentication? | `users`, `customers`, `sellers` |\n| `session` | Is this table for tracking login sessions? | `user_sessions`, `customer_sessions` |\n| `primary` | Do users independently create/search/manage these? | `articles`, `comments`, `orders` |\n| `subsidiary` | Always managed through parent entities? | `article_snapshot_files`, `snapshot_tags` |\n| `snapshot` | Captures point-in-time states for audit? | `article_snapshots`, `order_snapshots` |\n\n### 1.3. Naming Conventions\n\n| Element | Format | Example |\n|---------|--------|---------|\n| Table name | snake_case, plural | `shopping_customers`, `bbs_articles` |\n| Primary field | `id` | `id: uuid` |\n| Foreign field | `{table}_id` | `shopping_customer_id` |\n| Plain field | snake_case | `created_at`, `updated_at` |\n| Relation name | camelCase | `customer`, `article` |\n| Opposite name | camelCase, plural for 1:N | `sessions`, `comments` |\n\n### 1.4. Required Temporal Fields\n```typescript\n// Standard for all business entities\ncreated_at: datetime (NOT NULL)\nupdated_at: datetime (NOT NULL)\ndeleted_at: datetime? (nullable - for soft delete)\n```\n\n---\n\n## 2. Normalization Rules (STRICT)\n\n### 2.1. 3NF Compliance\n\n| Rule | Description |\n|------|-------------|\n| **1NF** | Atomic values, no arrays, unique rows |\n| **2NF** | All non-key attributes depend on primary key |\n| **3NF** | No transitive dependencies |\n```typescript\n// ❌ WRONG: Transitive dependency\nbbs_article_comments: {\n article_title: string // Depends on article, not comment\n}\n\n// ✅ CORRECT: Reference only\nbbs_article_comments: {\n bbs_article_id: uuid\n}\n```\n\n### 2.2. No JSON/Array in String Fields (1NF)\n\n**Do not store JSON, arrays, or composite data as string fields. Use normalized child tables.**\n\n**Only exception**: User explicitly requests a JSON field in requirements.\n\n```typescript\n// ❌ WRONG: JSON disguised as string\nproducts: {\n metadata: string // \'{"color":"red","size":"L"}\'\n tags: string // \'["sale","new","featured"]\'\n}\n\n// ✅ CORRECT: Normalized child table with key-value\nproducts: { id, name, ... }\nproduct_attributes: {\n id: uuid\n product_id: uuid (FK)\n key: string // "color", "size"\n value: string // "red", "L"\n @@unique([product_id, key])\n}\n```\n\n### 2.3. 1:1 Relationship Pattern (CRITICAL)\n\n**NEVER use nullable fields for 1:1 dependent entities. Use separate tables.**\n\n```typescript\n// ❌ WRONG: Nullable fields for optional entity\nshopping_sale_questions: {\n answer_title: string? // PROHIBITED\n answer_body: string? // PROHIBITED\n seller_id: string? // PROHIBITED\n}\n\n// ✅ CORRECT: Separate table with unique constraint\nshopping_sale_questions: { id, title, body, customer_id, ... }\nshopping_sale_question_answers: {\n id, shopping_sale_question_id, seller_id, title, body, ...\n @@unique([shopping_sale_question_id]) // 1:1 constraint\n}\n```\n\n### 2.4. Polymorphic Ownership Pattern (CRITICAL)\n\n**NEVER use multiple nullable FKs for different actor types. Use main entity + subtype pattern.**\n\n```typescript\n// ❌ WRONG: Multiple nullable actor FKs\nshopping_order_issues: {\n customer_id: string? // PROHIBITED\n seller_id: string? // PROHIBITED\n}\n\n// ✅ CORRECT: Main entity + subtype entities\nshopping_order_issues: {\n id, actor_type, title, body, ...\n @@index([actor_type])\n}\nshopping_order_issue_of_customers: {\n id, shopping_order_issue_id, customer_id, customer_session_id, ...\n @@unique([shopping_order_issue_id])\n}\nshopping_order_issue_of_sellers: {\n id, shopping_order_issue_id, seller_id, seller_session_id, ...\n @@unique([shopping_order_issue_id])\n}\n```\n\n### 2.5. Foreign Key Direction (CRITICAL)\n\n**Actor/parent tables must NEVER have foreign keys pointing to child tables. FK direction is ALWAYS child → parent.**\n\n```typescript\n// ❌ WRONG: Parent has FK to children (creates circular reference)\ntodo_app_users: {\n session_id: uuid (FK → todo_app_user_sessions) // PROHIBITED\n password_reset_id: uuid (FK → todo_app_user_password_resets) // PROHIBITED\n}\n\n// ✅ CORRECT: Only children reference parent\ntodo_app_user_sessions: {\n todo_app_user_id: uuid (FK → todo_app_users) // Child → Parent\n}\ntodo_app_user_password_resets: {\n todo_app_user_id: uuid (FK → todo_app_users) // Child → Parent\n}\n```\n\n### 2.6. Relation Naming (CRITICAL)\n\n**All relation names and oppositeNames MUST be camelCase. Never use snake_case.**\n\n```typescript\n// ❌ WRONG: snake_case oppositeName\nrelation: {\n name: "user",\n oppositeName: "password_resets" // PROHIBITED\n}\n\n// ✅ CORRECT: camelCase oppositeName\nrelation: {\n name: "user",\n oppositeName: "passwordResets" // camelCase\n}\n```\n\n---\n\n## 3. Required Design Patterns\n\n### 3.1. Authentication Fields (when entity requires login)\n```typescript\n{\n email: string (unique)\n password_hash: string\n}\n```\n\n### 3.2. Session Table Pattern (for actors)\n\n**Stance**: `"session"`\n**Required fields** (EXACT SET - no additions):\n```typescript\n{\n id: uuid\n {actor}_id: uuid (FK)\n ip: string\n href: string\n referrer: string\n created_at: datetime\n expired_at: datetime // NOT NULL by default (security)\n \n @@index([{actor}_id, created_at])\n}\n```\n\n### 3.3. Snapshot Pattern\n```typescript\n// Main entity (stance: "primary")\nbbs_articles: { id, code, ..., created_at, updated_at, deleted_at? }\n\n// Snapshot table (stance: "snapshot")\nbbs_article_snapshots: {\n id, bbs_article_id, ...all fields denormalized..., created_at\n}\n```\n\n### 3.4. Materialized View Pattern\n```typescript\n// Only place for denormalized/calculated data\nmv_bbs_article_last_snapshots: {\n material: true\n stance: "subsidiary"\n // Pre-computed aggregations allowed here\n}\n```\n\n---\n\n## 4. Prohibited Patterns\n\n| Pattern | Why Prohibited |\n|---------|----------------|\n| Calculated fields in regular tables | `view_count`, `comment_count` → compute in queries |\n| Redundant denormalized data | `article_title` in comments → use FK reference |\n| Multiple nullable actor FKs | Use subtype pattern instead |\n| Nullable fields for 1:1 entities | Use separate tables |\n| Prefix duplication | `bbs_bbs_articles` → just `bbs_articles` |\n| Duplicate plain + gin index | NEVER put same field in both plainIndex and ginIndex → keep gin only, remove plain |\n| Duplicate unique + plain index | NEVER put same field in both uniqueIndex and plainIndex → keep unique only, remove plain |\n| Duplicate unique + gin index | NEVER put same field in both uniqueIndex and ginIndex → keep unique only, remove gin |\n| Subset index | Index on (A) when (A, B) exists → remove (A), superset covers it |\n| Duplicate composite index | Same field combination in multiple indexes → keep only one \n| Circular FK reference | Actor/parent table must NEVER have FK to child tables. Only child → parent direction allowed |\n| Duplicate FK field names | Each foreignField must have a unique name. Never repeat same field name (e.g., multiple `user_id`) |\n| snake_case oppositeName | oppositeName MUST be camelCase (e.g., `sessions` not `user_sessions`, `editHistories` not `edit_histories`) |\n| Duplicate oppositeName | Each oppositeName targeting the same model must be unique (e.g., use `customerOrders` and `sellerOrders`, not both `orders`) |\n| Non-uuid foreignField type | foreignField type MUST always be `uuid`. Never use `string`, `datetime`, `uri`, or other types for FK fields |\n| JSON/array as string field | 1NF violation - use key-value child table (unless user explicitly requests JSON) |\n\n---\n\n## 5. AST Structure\n\n### 5.1. Model Structure\n```typescript\n{\n name: "target_table_name",\n description: `\n Summary sentence.\n\n Detailed explanation with proper line breaks.\n Additional context and relationships.\n `,\n material: false,\n stance: "primary" | "subsidiary" | "snapshot" | "actor" | "session",\n \n primaryField: {\n name: "id",\n type: "uuid",\n description: "Primary Key."\n },\n \n foreignFields: [{\n name: "{table}_id",\n type: "uuid",\n relation: {\n name: "relationName", // camelCase\n targetModel: "target_table",\n oppositeName: "oppositeRelation" // camelCase\n },\n unique: false, // true for 1:1\n nullable: false,\n description: "Description. {@link target_table.id}."\n }],\n \n plainFields: [{\n name: "field_name",\n type: "string" | "int" | "double" | "boolean" | "datetime" | "uri" | "uuid",\n nullable: false,\n description: "Business context."\n }],\n \n uniqueIndexes: [{ fieldNames: ["field1", "field2"], unique: true }],\n plainIndexes: [{ fieldNames: ["field1", "field2"] }], // Never single FK\n ginIndexes: [{ fieldName: "text_field" }]\n}\n```\n\n### 5.2. Field Types\n\n| Type | Usage |\n|------|-------|\n| `uuid` | Primary keys, foreign keys |\n| `string` | Text, email, status |\n| `int` | Integers, counts |\n| `double` | Decimals, prices |\n| `boolean` | Flags |\n| `datetime` | Timestamps |\n| `uri` | URLs |\n\n---\n\n## 6. Function Calling\n\n### 6.1. Request Analysis Sections\n\n```typescript\nprocess({\n thinking: "Need related component context for foreign key design.",\n request: { type: "getAnalysisSections", sectionIds: [1, 3] }\n})\n```\n\n### 6.2. Complete (MANDATORY)\n```typescript\nprocess({\n thinking: "Designed target table with proper normalization and stance.",\n request: {\n type: "complete",\n plan: "Strategic analysis for [targetTable]...",\n model: {\n name: "target_table",\n stance: "primary",\n description: "...",\n primaryField: {...},\n foreignFields: [...],\n plainFields: [...],\n uniqueIndexes: [...],\n plainIndexes: [...],\n ginIndexes: [...]\n }\n }\n})\n```\n\n---\n\n## 7. Planning Template\n```\nASSIGNMENT VALIDATION:\n- Target Table: [targetTable] - THE SINGLE TABLE I MUST CREATE\n- Other Tables: [targetComponent.tables] (handled separately)\n- Other Components: [otherComponents] (for FK references)\n\nREQUIREMENT ANALYSIS:\n- Business entity purpose?\n- Core attributes?\n- Relationships with existing tables?\n- Authentication fields needed?\n- Soft delete needed?\n- Status/workflow fields?\n\nNORMALIZATION CHECK:\n- 1NF, 2NF, 3NF compliant?\n- 1:1 relationships → separate tables?\n- Polymorphic ownership → subtype pattern?\n\nSTANCE CLASSIFICATION:\n- [primary/subsidiary/snapshot/actor/session] - Reason: [...]\n\nFINAL DESIGN:\n- Create exactly ONE model named [targetTable]\n- Use existing tables for FK relationships\n- Include required temporal fields\n```\n\n---\n\n## 8. Final Checklist\n\n**Table Creation:**\n- [ ] EXACTLY ONE table named `targetTable`\n- [ ] Correct `stance` classification\n- [ ] Comprehensive `description` (summary + paragraphs)\n\n**Normalization:**\n- [ ] 3NF compliant\n- [ ] No JSON/array in string fields (unless user requested)\n- [ ] No nullable fields for 1:1 entities\n- [ ] No multiple nullable actor FKs\n\n**Fields:**\n- [ ] All FKs reference existing tables\n- [ ] Temporal fields: `created_at`, `updated_at`, `deleted_at?`\n- [ ] Authentication fields if login required\n- [ ] Status fields if workflow exists\n\n**Indexes:**\n- [ ] No single-column FK indexes\n- [ ] Composite indexes optimized\n- [ ] No duplicate plain + gin indexes on same field\n- [ ] No subset indexes when superset exists\n- [ ] No duplicate composite indexes\n- [ ] No circular FK references (child → parent only, never parent → child)\n- [ ] No duplicate foreignField names in same model\n- [ ] All oppositeName values are camelCase (not snake_case)\n- [ ] All oppositeName values are unique per target model\n- [ ] All foreignField types are `uuid` only\n\n**Quality:**\n- [ ] No duplicate fields or relations\n- [ ] No prefix duplication in table name\n- [ ] All descriptions in English\n\n**Execution:**\n- [ ] `thinking` field completed\n- [ ] Ready to call `process()` with `type: "complete"`'
51965
52410
  }, {
51966
52411
  id: v7(),
51967
52412
  created_at: (new Date).toISOString(),
@@ -70951,8 +71396,6 @@ const sleepMap = {
70951
71396
  analyzeWriteModule: 500,
70952
71397
  analyzeWriteUnit: 500,
70953
71398
  analyzeWriteSection: 500,
70954
- analyzeModuleReview: 300,
70955
- analyzeUnitReview: 300,
70956
71399
  analyzeSectionReview: 300,
70957
71400
  analyzeScenarioReview: 300,
70958
71401
  analyzeComplete: 1e3,