adelie-ai 0.3.2 → 0.3.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.
@@ -12,4 +12,4 @@ def _get_version() -> str:
12
12
  except Exception:
13
13
  pass
14
14
  return "0.0.0"
15
- __version__ = "0.3.2"
15
+ __version__ = "0.3.3"
@@ -44,6 +44,41 @@ Output a single valid JSON array of files to create/update."""
44
44
  SYSTEM_PROMPT = load_prompt("coder", _FALLBACK_PROMPT)
45
45
 
46
46
 
47
+ def _get_framework_guidelines(framework: str) -> str:
48
+ """Return framework-specific coding rules to inject into coder prompt."""
49
+ guidelines = {
50
+ "nextjs": (
51
+ "\n## ⚠️ Next.js App Router — MANDATORY Rules\n"
52
+ "- Any component using useState, useEffect, onClick, or other client hooks "
53
+ "MUST start with `'use client';` as the FIRST line.\n"
54
+ "- `layout.tsx` is a SERVER component — NEVER use client-side hooks, "
55
+ "context providers, or event handlers in it without `'use client'`.\n"
56
+ "- Dynamic routes use `[param]`, `[...catch]`, `[[...optional]]` syntax — "
57
+ "these are valid directory names.\n"
58
+ "- API routes go in `src/app/api/` as `route.ts` files.\n"
59
+ "- Use `next/navigation` (not `next/router`) for App Router.\n"
60
+ "- The package name for lucide icons is `lucide-react` (NOT `@lucide/react`).\n\n"
61
+ ),
62
+ "nuxt": (
63
+ "\n## ⚠️ Nuxt 3 — MANDATORY Rules\n"
64
+ "- Use `<script setup lang='ts'>` for composition API.\n"
65
+ "- Auto-imports: `ref`, `computed`, `useRoute` etc. are auto-imported.\n"
66
+ "- Pages go in `pages/`, layouts in `layouts/`.\n\n"
67
+ ),
68
+ "sveltekit": (
69
+ "\n## ⚠️ SvelteKit — MANDATORY Rules\n"
70
+ "- Pages go in `src/routes/` as `+page.svelte`.\n"
71
+ "- Server-only code uses `+page.server.ts` or `+server.ts`.\n"
72
+ "- Layouts use `+layout.svelte`.\n\n"
73
+ ),
74
+ "vite": (
75
+ "\n## ⚠️ Vite + React — MANDATORY Rules\n"
76
+ "- Entry point is `index.html` referencing `src/main.tsx`.\n"
77
+ "- Use `vite.config.ts` with `@vitejs/plugin-react`.\n\n"
78
+ ),
79
+ }
80
+ return guidelines.get(framework, "")
81
+
47
82
  def _get_coder_log_dir(layer: int, coder_name: str) -> Path:
48
83
  """Get or create the log directory for a coder."""
49
84
  log_dir = CODER_ROOT / "layer" / str(layer) / coder_name
@@ -174,6 +209,16 @@ def run_coder(
174
209
  f"## Lower Layer Coder Logs\n{lower_logs}\n\n"
175
210
  )
176
211
 
212
+ # Bug #7: Inject framework-specific coding rules to prevent common mistakes
213
+ try:
214
+ from adelie.agents.expert_ai import _detect_framework
215
+ fw = _detect_framework(workspace_root)
216
+ fw_guidelines = _get_framework_guidelines(fw)
217
+ if fw_guidelines:
218
+ user_prompt += fw_guidelines
219
+ except Exception:
220
+ pass
221
+
177
222
  if feedback:
178
223
  user_prompt += (
179
224
  f"## ⚠️ REVIEWER FEEDBACK (FIX THESE ISSUES)\n{feedback}\n\n"
@@ -444,8 +444,9 @@ def _get_scaffolding_need() -> str:
444
444
  return ""
445
445
 
446
446
  lines = [
447
- "⚠️ CRITICAL: The following entry files are MISSING. Without them, the build WILL FAIL.",
448
- "Create a 'project_scaffolding' coder task (layer 0) to generate these BEFORE any feature tasks:",
447
+ "ℹ️ SCAFFOLDING NOTE: The following entry files are missing.",
448
+ "If no scaffolding coder has been created yet, create ONE scaffolding task (layer 0).",
449
+ "If scaffolding was ALREADY attempted in a previous cycle, SKIP this and focus on feature tasks:",
449
450
  ]
450
451
  for c in checks:
451
452
  lines.append(f" - {c['file']}: {c['desc']}")
@@ -112,6 +112,9 @@ class Orchestrator:
112
112
  self._last_assembled_contexts: list | None = None
113
113
  self._last_build_errors: list[dict] = []
114
114
 
115
+ # Track coder/reviewer results for next cycle's Expert AI context (Bug #4)
116
+ self._last_coder_result: dict | None = None
117
+
115
118
  # Auto-scan: if KB is empty and project has existing code, scan first
116
119
  self._auto_scan_done = False
117
120
 
@@ -181,6 +184,10 @@ class Orchestrator:
181
184
  # Include recent build errors for Expert AI context
182
185
  if self._last_build_errors:
183
186
  state["build_errors"] = self._last_build_errors[:3] # 최대 3개
187
+ # Include last cycle's coder/reviewer result so Expert AI can avoid
188
+ # re-issuing tasks that previously failed (Bug #4)
189
+ if self._last_coder_result:
190
+ state["last_coder_result"] = self._last_coder_result
184
191
  return state
185
192
 
186
193
  def get_agent_context(self, agent_type: AgentType | str) -> dict:
@@ -976,7 +983,10 @@ class Orchestrator:
976
983
  )] or all_written_files
977
984
 
978
985
  for retry in range(MAX_REVIEW_RETRIES + 1):
979
- review = run_review(coder_name=name, written_files=task_files)
986
+ # Bug #6: pass STAGING_ROOT so reviewer reads files from
987
+ # staging (where Coder wrote them), not PROJECT_ROOT.
988
+ from adelie.agents.coder_ai import STAGING_ROOT as _REVIEW_STAGING
989
+ review = run_review(coder_name=name, written_files=task_files, workspace_root=_REVIEW_STAGING)
980
990
  score = review.get("overall_score", 5)
981
991
  self._review_score_history.append(score)
982
992
 
@@ -1005,6 +1015,44 @@ class Orchestrator:
1005
1015
  self._emit_agent_end("Reviewer", f"error: {e}")
1006
1016
  else:
1007
1017
  self._emit_agent_end("Reviewer", "approved" if reviewer_approved else "rejected")
1018
+
1019
+ # Bug #3: Log review failures to KB so Expert AI avoids re-issuing
1020
+ # the exact same task that was rejected.
1021
+ if not reviewer_approved and all_written_files:
1022
+ failed_files = [f.get("filepath", "") for f in all_written_files]
1023
+ review_summary = review.get("summary", "N/A") if review else "N/A"
1024
+ review_issues = ""
1025
+ if review:
1026
+ for issue in review.get("issues", [])[:5]:
1027
+ review_issues += f"- [{issue.get('severity')}] {issue.get('title')}: {issue.get('suggestion', '')}\n"
1028
+ failure_note = (
1029
+ f"# Review Failure Log (Cycle #{self.loop_iteration})\n\n"
1030
+ f"The following files were rejected by Reviewer AI after "
1031
+ f"{MAX_REVIEW_RETRIES + 1} attempts:\n"
1032
+ + "\n".join(f"- `{f}`" for f in failed_files) + "\n\n"
1033
+ f"**Review Summary**: {review_summary}\n\n"
1034
+ f"**Issues**:\n{review_issues}\n"
1035
+ f"Expert AI should NOT re-assign the same task until "
1036
+ f"the underlying issue is resolved.\n"
1037
+ )
1038
+ failure_path = WORKSPACE_PATH / "errors" / f"review_failure_{self.loop_iteration}.md"
1039
+ failure_path.parent.mkdir(parents=True, exist_ok=True)
1040
+ failure_path.write_text(failure_note, encoding="utf-8")
1041
+ retriever.update_index(
1042
+ f"errors/{failure_path.name}",
1043
+ tags=["error", "review-failure"],
1044
+ summary=f"Review rejected cycle #{self.loop_iteration}: {', '.join(failed_files[:3])}",
1045
+ )
1046
+ console.print(f"[yellow]📝 Review failure logged to KB for Expert AI awareness[/yellow]")
1047
+
1048
+ # Bug #4: Record coder/reviewer results for next cycle context
1049
+ self._last_coder_result = {
1050
+ "cycle": self.loop_iteration,
1051
+ "files_written": len(all_written_files),
1052
+ "reviewer_approved": reviewer_approved,
1053
+ "review_score": review.get("overall_score", 0) if review else 0,
1054
+ "review_summary": review.get("summary", "")[:300] if review else "",
1055
+ }
1008
1056
  elif all_written_files and self.phase != "initial":
1009
1057
  # Reviewer not scheduled this cycle — auto-approve staged files
1010
1058
  reviewer_approved = True
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adelie-ai",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "Adelie — Self-Communicating Autonomous AI Loop CLI",
5
5
  "bin": {
6
6
  "adelie": "bin/adelie.js"